diff --git a/src/ext/decode.rs b/src/ext/decode.rs index 57530f3..5588b6e 100644 --- a/src/ext/decode.rs +++ b/src/ext/decode.rs @@ -1,163 +1,10 @@ -use bits::match_mask; -use enum_dispatch::*; -use modular_bitfield::prelude::*; -use strum::{EnumIter, IntoEnumIterator}; +use strum::IntoEnumIterator; +use super::encoding::{GenInstruction, Instruction}; use crate::cpu; use crate::system::rv32; -// trait Instruction { -// fn impl_register(&self, exts: &mut Vec, name: &'static str) { -// for ext in exts { -// if ext.name == name { -// exts.add(self) -// } -// } -// } -// } -// -// fn main() { -// let mut extensions = vec![ext1, ext2, ...]; -// ADDI.register(&extensions); -// SUBI.register(&extensions); -// } -// -// // ... -// -// impl Instruction for ADDI { -// fn register(&self, exts: &mut Vec) { -// self.impl_register(exts, "instr_set") -// } -// } - -// Null undecided type -#[bitfield] -#[derive(Debug)] -pub struct NullType { - pub opcode: B7, - pub _unused: B25, -} - -// Arithmetic logic -#[bitfield] -#[derive(Debug)] -pub struct RType { - pub opcode: B7, - pub rd: B5, - pub funct3: B3, - pub rs1: B5, - pub rs2: B5, - pub funct7: B7, -} - -// Loads & immeiate arithmetic -#[bitfield] -#[derive(Debug)] -pub struct IType { - pub opcode: B7, - pub rd: B5, - pub funct3: B3, - pub rs1: B5, - pub imm: B12, -} - -enum EncodingType { - R(RType), - I(IType), -} - -#[repr(align(8))] -pub union GenInstruction { - pub inst: rv32::Word, - pub null: std::mem::ManuallyDrop, - pub R: std::mem::ManuallyDrop, - pub I: std::mem::ManuallyDrop, -} - -#[enum_dispatch] -trait Instruction { - fn name(&self) -> &'static str; - fn match_inst(&self, inst: rv32::Word) -> bool; - fn step(&self, inst: GenInstruction, state: &mut cpu::CPUState); -} - -#[derive(Default, Copy, Clone)] -struct ADDI; - -impl Instruction for ADDI { - fn name(&self) -> &'static str { - "ADDI" - } - - fn match_inst(&self, inst: rv32::Word) -> bool { - println!("VM > Checking ADDI"); - println!("VM > ADDI: 0b{:032b}", inst); - println!("VM > ADDI: 0bxxxxxxxxxxxxxxxxx000xxxxx0010011"); - match_mask!(inst, "xxxxxxxxxxxxxxxxx000xxxxx0010011") - } - - fn step(&self, inst: GenInstruction, state: &mut cpu::CPUState) { - println!("VM > Executing ADDI"); - let inst = unsafe { inst.I }; - state.x[inst.rd() as usize] = state.x[inst.rs1() as usize].wrapping_add(inst.imm() as u32); - } -} - -#[derive(Default, Copy, Clone)] -struct ADD; - -impl Instruction for ADD { - fn name(&self) -> &'static str { - "ADD" - } - - fn match_inst(&self, inst: rv32::Word) -> bool { - println!("VM > Checking ADD"); - println!("VM > ADD: 0b{:032b}", inst); - println!("VM > ADD: 0b0000000xxxxxxxxxx000xxxxx0110011"); - match_mask!(inst, "0000000xxxxxxxxxx000xxxxx0110011") - } - - 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") - } -} - -#[enum_dispatch(Instruction)] -#[derive(EnumIter)] -enum ExtensionI { - ADDI(ADDI), - ADD(ADD), -} - -#[enum_dispatch(Instruction)] -#[derive(EnumIter)] -enum ExtensionM { - GENERICM(GENERICM) -} +use crate::ext::i; pub struct DecodeCycle { extensions: Vec, @@ -177,7 +24,10 @@ impl DecodeCycle { // if we find a match, we want to execute it // if we don't find a match, we want to return an error - fn enumerate_extension(inst: rv32::Word, state: &mut cpu::CPUState) -> Option<()> { + 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 }; @@ -190,8 +40,11 @@ impl DecodeCycle { 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(()); }, + 'i' => { + if let Some(()) = enumerate_extension::(inst, state) { + return Ok(()); + } + } _ => println!("VM > Unknown Extension"), } } diff --git a/src/ext/encoding.rs b/src/ext/encoding.rs new file mode 100644 index 0000000..31bfc9f --- /dev/null +++ b/src/ext/encoding.rs @@ -0,0 +1,57 @@ +use modular_bitfield::prelude::*; +use enum_dispatch::*; + +use crate::system::rv32; +use crate::cpu; + +#[enum_dispatch] +pub trait Instruction { + fn name(&self) -> &'static str; + fn match_inst(&self, inst: rv32::Word) -> bool; + fn step(&self, inst: GenInstruction, state: &mut cpu::CPUState); +} + + +// Null undecided type +#[bitfield] +#[derive(Debug)] +pub struct NullType { + pub opcode: B7, + pub _unused: B25, +} + +// Arithmetic logic +#[bitfield] +#[derive(Debug)] +pub struct RType { + pub opcode: B7, + pub rd: B5, + pub funct3: B3, + pub rs1: B5, + pub rs2: B5, + pub funct7: B7, +} + +// Loads & immeiate arithmetic +#[bitfield] +#[derive(Debug)] +pub struct IType { + pub opcode: B7, + pub rd: B5, + pub funct3: B3, + pub rs1: B5, + pub imm: B12, +} + +enum EncodingType { + R(RType), + I(IType), +} + +#[repr(align(8))] +pub union GenInstruction { + pub inst: rv32::Word, + pub null: std::mem::ManuallyDrop, + pub R: std::mem::ManuallyDrop, + pub I: std::mem::ManuallyDrop, +} diff --git a/src/ext/i/mod.rs b/src/ext/i/mod.rs index 8b13789..477eade 100644 --- a/src/ext/i/mod.rs +++ b/src/ext/i/mod.rs @@ -1 +1,61 @@ +use bits::match_mask; +use enum_dispatch::*; +use strum::EnumIter; + +use super::encoding::{GenInstruction, Instruction}; +use crate::helpers::sext; +use crate::cpu; +use crate::system::rv32; + +#[derive(Default, Copy, Clone)] +pub struct ADDI; + +impl Instruction for ADDI { + fn name(&self) -> &'static str { + "ADDI" + } + + fn match_inst(&self, inst: rv32::Word) -> bool { + println!("VM > Checking ADDI"); + println!("VM > ADDI: 0b{:032b}", inst); + println!("VM > ADDI: 0bxxxxxxxxxxxxxxxxx000xxxxx0010011"); + match_mask!(inst, "xxxxxxxxxxxxxxxxx000xxxxx0010011") + } + + fn step(&self, inst: GenInstruction, state: &mut cpu::CPUState) { + println!("VM > Executing ADDI"); + let inst = unsafe { inst.I }; + state.x[inst.rd() as usize] = state.x[inst.rs1() as usize].wrapping_add(sext(inst.imm() as u32,)); + } +} + +#[derive(Default, Copy, Clone)] +pub struct ADD; + +impl Instruction for ADD { + fn name(&self) -> &'static str { + "ADD" + } + + fn match_inst(&self, inst: rv32::Word) -> bool { + println!("VM > Checking ADD"); + println!("VM > ADD: 0b{:032b}", inst); + println!("VM > ADD: 0b0000000xxxxxxxxxx000xxxxx0110011"); + match_mask!(inst, "0000000xxxxxxxxxx000xxxxx0110011") + } + + 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]); + } +} + +#[enum_dispatch(Instruction)] +#[derive(EnumIter)] +pub enum ExtensionI { + ADDI(ADDI), + ADD(ADD), +} diff --git a/src/ext/mod.rs b/src/ext/mod.rs index 7cf3e95..1fe3e72 100644 --- a/src/ext/mod.rs +++ b/src/ext/mod.rs @@ -1,6 +1,8 @@ use crate::system::rv32; +pub mod encoding; pub mod decode; +pub mod i; // Instruction bitmasks // This will be awkward as the instruction types diff --git a/src/helpers.rs b/src/helpers.rs new file mode 100644 index 0000000..ed6913d --- /dev/null +++ b/src/helpers.rs @@ -0,0 +1,15 @@ +pub fn sext(value: u32, len: usize) -> u32 { + let bit_len = std::mem::size_of::() << 3; + assert!(len > 0 && len <= bit_len); + if len == bit_len { + return value; + } + let sign = value >> (len - 1) as u32 & 0x1; + let mask = ((1 as u32) << (len as u32)) - 1 as u32; + if sign == 0 { + value & mask + } else { + let high = (((1 as u32) << (bit_len as u32 - len as u32)) - 1 as u32) << (len as u32); + value & mask | high + } +} diff --git a/src/inst.rs b/src/inst.rs deleted file mode 100644 index 92de238..0000000 --- a/src/inst.rs +++ /dev/null @@ -1,111 +0,0 @@ -use modular_bitfield::prelude::*; - -use crate::system::rv32; - -pub const R_TYPE: u8 = 0b00110011; -pub const I_TYPE: u8 = 0b00010011; -pub const S_TYPE: u8 = 0b00100011; -pub const B_TYPE: u8 = 0b01100011; -pub const U_TYPE: u8 = 0b00110111; -pub const J_TYPE: u8 = 0b01110011; - -// Null undecided type -#[bitfield] -#[derive(Debug)] -pub struct NullType { - pub opcode: B7, - pub _undefined: B25, -} - -// Arithmetic logic -#[bitfield] -#[derive(Debug)] -pub struct RType { - pub opcode: B7, - pub rd: B5, - pub funct3: B3, - pub rs1: B5, - pub rs2: B5, - pub funct7: B7, -} - -// Loads & immeiate arithmetic -#[bitfield] -#[derive(Debug)] -pub struct IType { - pub opcode: B7, - pub rd: B5, - pub funct3: B3, - pub rs1: B5, - pub imm: B12, -} - -// Stores -#[bitfield] -#[derive(Debug)] -pub struct SType { - pub opcode: B7, - pub imm_l: B5, - pub funct3: B3, - pub rs1: B5, - pub rs2: B5, - pub imm_h: B7, -} - -// Conditional jump -#[bitfield] -#[derive(Debug)] -pub struct BType { - pub opcode: B7, - pub imm_11: B1, - pub imm_4_1: B4, - pub funct3: B3, - pub rs1: B5, - pub rs2: B5, - pub imm_10_5: B6, - pub imm_12: B1, -} - -// Upper immediate -#[bitfield] -#[derive(Debug)] -pub struct UType { - pub opcode: B7, - pub rd: B5, - pub imm: B20, -} - -// Unconditional jump -#[bitfield] -#[derive(Debug)] -pub struct JType { - pub opcode: B7, - pub rd: B5, - pub imm_19_12: B8, - pub imm_11: B1, - pub imm_10_1: B10, - pub imm_20: B1, -} - -/* #[derive(Debug)] -pub enum Decode { - null(std::mem::ManuallyDrop), - R(std::mem::ManuallyDrop), - I(std::mem::ManuallyDrop), - S(std::mem::ManuallyDrop), - B(std::mem::ManuallyDrop), - U(std::mem::ManuallyDrop), - J(std::mem::ManuallyDrop), -} */ - -#[repr(align(8))] -pub union Instruction { - pub inst: rv32::Word, - pub null: std::mem::ManuallyDrop, - pub R: std::mem::ManuallyDrop, - pub I: std::mem::ManuallyDrop, - pub S: std::mem::ManuallyDrop, - pub B: std::mem::ManuallyDrop, - pub U: std::mem::ManuallyDrop, - pub J: std::mem::ManuallyDrop, -} diff --git a/src/main.rs b/src/main.rs index b3740e2..cdf12eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,8 +9,8 @@ use std::{cell::RefCell, rc::Rc}; mod cpu; mod err; mod ext; -mod inst; mod system; +mod helpers; use crate::cpu::*; use crate::ext::decode; @@ -24,7 +24,7 @@ struct VMRV32I { impl VMRV32I { fn new() -> VMRV32I { - let extensions = vec!['i', 'm']; + let extensions = vec!['i']; let bus = Rc::new(RefCell::new(bus::Bus::new())); let instruction_decoder = Rc::new(RefCell::new(decode::DecodeCycle::new(extensions.clone()))); @@ -83,7 +83,7 @@ fn main() { println!("VM Starting Up"); let mut vm = VMRV32I::new(); - vm.load_prog("./test/add.bin"); + vm.load_prog("./test/test.bin"); vm.dump_prog(); vm.dispatch(); }