diff --git a/src/cpu/mod.rs b/src/cpu/mod.rs index 5e689cf..c2b4fdb 100644 --- a/src/cpu/mod.rs +++ b/src/cpu/mod.rs @@ -1,8 +1,8 @@ +use crate::ext::decode; use crate::system::bus::*; -use std::{cell::RefCell, rc::Rc}; use crate::system::ram; use crate::system::rv32; -use crate::ext::decode; +use std::{cell::RefCell, rc::Rc}; // Register ABI Description Saver // x0 zero Zero Immutable @@ -19,26 +19,28 @@ use crate::ext::decode; // x18-x27 s2-s11 Saved registers Callee // x28-x31 t3-t6 Temporaries Caller pub struct CPUState { - x: [rv32::Word; 32], - pc: rv32::Word, + pub x: [rv32::Word; 32], + pub pc: rv32::Word, } pub struct CPU { state: CPUState, bus: Rc>, instruction_decoder: Rc>, - // extensions: + extensions: Vec, } impl CPU { - pub fn new(bus: Rc>, instruction_decoder: Rc>) -> CPU { + pub fn new( + bus: Rc>, + instruction_decoder: Rc>, + extensions: Vec, + ) -> CPU { CPU { - state: CPUState { - x: [0; 32], - pc: 0, - }, + state: CPUState { x: [0; 32], pc: 0 }, bus, instruction_decoder, + extensions, } } @@ -50,6 +52,7 @@ impl CPU { self.state.pc = DRAM_BASE as rv32::Word; self.state.x[0] = 0x00000000; // x0 is tied to ground self.state.x[2] = ram::DRAM_SIZE as u32; // x2 the addressable + println!("VM > CPU Initialisd with extensions {:?}", self.extensions); } pub fn get_pc(&self) -> rv32::Word { @@ -64,45 +67,14 @@ impl CPU { while self.state.pc - DRAM_BASE < ram::DRAM_SIZE as u32 { // fetch let inst = self.fetch(); - println!("VM > Fetched 0x{:08x}: 0x{:08x}", self.state.pc, inst ); + println!("VM > Fetched 0x{:08x}: 0x{:08x}", self.state.pc, inst); self.state.pc = self.state.pc + rv32::WORD as u32; self.state.x[0] = 0x00000000; - self.instruction_decoder.borrow_mut().decode_exec_inst(inst, &mut self.state)?; + self.instruction_decoder + .borrow_mut() + .decode_exec_inst(inst, &mut self.state)?; - // // decode and execute - // // we can use nulltype to extract the opcode - // let opcode = unsafe { inst.null.opcode() }; - // // then we can match the opcode to extract the op type - // match opcode { - // inst::I_TYPE => { - // let inst = unsafe { inst.I }; - // println!("VM > Decoded I Type instruction {:?}", inst); - // match inst.funct3() { - // 0x0 => { - // self.x[inst.rd() as usize] = - // self.x[inst.rs1() as usize].wrapping_add(inst.imm() as u32); - // } - // _ => println!("VM > INST {:03b} not implemented", inst.funct3()), - // }; - // } - // inst::R_TYPE => { - // let inst = unsafe { inst.R }; - // println!("VM > Decoded R Type instruction {:?}", inst); - // match inst.funct3() { - // 0x0 => { - // self.x[inst.rd() as usize] = self.x[inst.rs1() as usize] - // .wrapping_add(self.x[inst.rs2() as usize]); - // } - // _ => println!("VM > INST {:03b} not implemented", inst.funct3()), - // } - // } - // inst::S_TYPE => { - // println!("VM > OPCODE S TYPE not implemented"); - // } - // _ => println!("VM > OPCODE {:08b} not implemented", opcode), - // }; - // self.dump_reg(); } Ok(()) diff --git a/src/ext/decode.rs b/src/ext/decode.rs index 2ee20d6..57530f3 100644 --- a/src/ext/decode.rs +++ b/src/ext/decode.rs @@ -1,7 +1,7 @@ use bits::match_mask; use enum_dispatch::*; -use strum::{IntoEnumIterator, EnumIter}; use modular_bitfield::prelude::*; +use strum::{EnumIter, IntoEnumIterator}; use crate::cpu; use crate::system::rv32; @@ -78,7 +78,7 @@ pub union GenInstruction { trait Instruction { fn name(&self) -> &'static str; fn match_inst(&self, inst: rv32::Word) -> bool; - fn step(&self, inst: rv32::Word, state: &mut cpu::CPUState); + fn step(&self, inst: GenInstruction, state: &mut cpu::CPUState); } #[derive(Default, Copy, Clone)] @@ -96,10 +96,10 @@ impl Instruction for ADDI { match_mask!(inst, "xxxxxxxxxxxxxxxxx000xxxxx0010011") } - fn step(&self, inst: rv32::Word, state: &mut cpu::CPUState) { - println!("VM > Decoded I Type instruction 0x{:08x}", inst); + fn step(&self, inst: GenInstruction, state: &mut cpu::CPUState) { println!("VM > Executing ADDI"); - // self.x[inst.rd() as usize] = self.x[inst.rs1() as usize].wrapping_add(inst.imm() as u32); + let inst = unsafe { inst.I }; + state.x[inst.rd() as usize] = state.x[inst.rs1() as usize].wrapping_add(inst.imm() as u32); } } @@ -118,9 +118,31 @@ impl Instruction for ADD { match_mask!(inst, "0000000xxxxxxxxxx000xxxxx0110011") } - fn step(&self, inst: rv32::Word, state: &mut cpu::CPUState) { - println!("VM > Decoded R Type instruction 0x{:08x}", inst); + fn step(&self, inst: GenInstruction, state: &mut cpu::CPUState) { println!("VM > Executing ADD"); + let inst = unsafe { inst.R }; + state.x[inst.rd() as usize] = + state.x[inst.rs1() as usize].wrapping_add(state.x[inst.rs2() as usize]); + } +} + +#[derive(Default, Copy, Clone)] +struct GENERICM; + +impl Instruction for GENERICM { + fn name(&self) -> &'static str { + "GENERICM" + } + + fn match_inst(&self,inst:rv32::Word) -> bool { + println!("VM > Checking GENERICM"); + println!("VM > GENERICM: 0b{:032b}", inst); + println!("VM > GENERICM: 0b0000000xxxxxxxxxx000xxxxx0110011"); + match_mask!(inst, "0000000xxxxxxxxxx000xxxxx0110011") + } + + fn step(&self,inst:GenInstruction,state: &mut cpu::CPUState) { + println!("epc") } } @@ -131,8 +153,10 @@ enum ExtensionI { ADD(ADD), } -enum Extensions { - ExtensionI(Option), +#[enum_dispatch(Instruction)] +#[derive(EnumIter)] +enum ExtensionM { + GENERICM(GENERICM) } pub struct DecodeCycle { @@ -144,29 +168,33 @@ impl DecodeCycle { DecodeCycle { extensions: ext } } - pub fn decode_exec_inst(&self, inst: rv32::Word, state: &mut cpu::CPUState) -> Result<(), String> { + pub fn decode_exec_inst( + &self, + inst: rv32::Word, + state: &mut cpu::CPUState, + ) -> Result<(), &str> { // we want to go through each extension and then go through each instruction in that extension // if we find a match, we want to execute it // if we don't find a match, we want to return an error - for extension in self.extensions.iter() { - match extension { - 'i' => { - println!("VM > Attempting to decode instruction as I extension: 0x{:08x}", inst); - for instruction in ExtensionI::iter() { - println!("VM > Checking instruction: {:?}", instruction.name()); - if instruction.match_inst(inst) { - println!("VM > Decoded instruction as I extension: 0x{:08x}", inst); - instruction.step(inst, state); - return Ok(()); - } - } - } - _ => { - println!("VM > Unknown Extension"); + fn enumerate_extension(inst: rv32::Word, state: &mut cpu::CPUState) -> Option<()> { + for instruction in T::iter() { + if instruction.match_inst(inst) { + let geninst = GenInstruction { inst }; + instruction.step(geninst, state); + return Some(()); } } + None } - Ok(()) - } + + for extension in self.extensions.iter() { + match extension { + 'm' => if let Some(()) = enumerate_extension::(inst, state) { return Ok(()); }, + 'i' => if let Some(()) = enumerate_extension::(inst, state) { return Ok(()); }, + _ => println!("VM > Unknown Extension"), + } + } + Err("No instruction found") + } } diff --git a/src/main.rs b/src/main.rs index f02231f..b3740e2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,14 +7,14 @@ use std::io::Read; use std::{cell::RefCell, rc::Rc}; mod cpu; -mod ext; mod err; -mod system; +mod ext; mod inst; +mod system; -use crate::system::bus; -use crate::ext::decode; use crate::cpu::*; +use crate::ext::decode; +use crate::system::bus; struct VMRV32I { bus: Rc>, @@ -24,14 +24,18 @@ struct VMRV32I { impl VMRV32I { fn new() -> VMRV32I { - let extensions = vec!['i']; + let extensions = vec!['i', 'm']; let bus = Rc::new(RefCell::new(bus::Bus::new())); - let instruction_decoder = Rc::new(RefCell::new(decode::DecodeCycle::new(extensions))); - let mut cpu = CPU::new(Rc::clone(&bus), Rc::clone(&instruction_decoder)); + let instruction_decoder = Rc::new(RefCell::new(decode::DecodeCycle::new(extensions.clone()))); + let mut cpu = CPU::new(Rc::clone(&bus), Rc::clone(&instruction_decoder), extensions.clone()); cpu.init(); - VMRV32I { cpu, bus, instruction_decoder } + VMRV32I { + cpu, + bus, + instruction_decoder, + } } fn load_prog(&mut self, file: &str) {