From 9dc01a04044b5f882bb15567818fa2a51af68691 Mon Sep 17 00:00:00 2001 From: Aleksa Vuckovic Date: Sun, 13 Apr 2025 15:22:11 +0200 Subject: Initial commit --- src/rv32_cpu/mod.rs | 1 + src/rv32_cpu/rv32_cpu.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 src/rv32_cpu/mod.rs create mode 100644 src/rv32_cpu/rv32_cpu.rs (limited to 'src/rv32_cpu') diff --git a/src/rv32_cpu/mod.rs b/src/rv32_cpu/mod.rs new file mode 100644 index 0000000..ec271da --- /dev/null +++ b/src/rv32_cpu/mod.rs @@ -0,0 +1 @@ +pub mod rv32_cpu; \ No newline at end of file diff --git a/src/rv32_cpu/rv32_cpu.rs b/src/rv32_cpu/rv32_cpu.rs new file mode 100644 index 0000000..aefd1c0 --- /dev/null +++ b/src/rv32_cpu/rv32_cpu.rs @@ -0,0 +1,89 @@ +use std::collections::HashMap; +use std::error::Error; +use crate::instruction::instruction::{Instruction, Opcode}; +use crate::extension::extension::Extension; + +#[derive(Default)] +pub struct GPRegisters { + pub registers: [u32; 32] +} + +#[derive(Default)] +pub struct SMRegisters { + sie: u32, + stvec: u32, +} + +#[derive(Default)] +pub struct MMRegisters { + pub mie: u32, + pub mtvec: u32, + pub mepc: u32, + pub mcause: u32, + pub mhart: u32, +} + +#[derive(Default)] +pub struct State { + pub pc: u32, + pub gp_regs: GPRegisters, + pub sm_regs: SMRegisters, + pub mm_regs: MMRegisters, +} + +pub struct Rv32Cpu { + decoders: HashMap>, + state: State, +} + +impl Rv32Cpu { + pub fn new(id: u32) -> Self { + let mut state = State::default(); + state.mm_regs.mhart = id; + Rv32Cpu { + decoders: HashMap::new(), + state + } + } + + pub fn add_extension(mut self) -> Self { + T::add_instructions(&mut self); + self + } + + pub fn add_decode(&mut self, key: Opcode, instruction: Box) { + self.decoders.insert(key, instruction); + } + + fn decode(decoders: &HashMap>, instruction: u32) -> Result<&Box, Box> { + if instruction & 0x3 != 0x3 { + return Err("Invalid opcode".into()); + } + + let op: [u32; 3] = [(instruction >> 2) & 0x1F, (instruction >> 12) & 0x7, (instruction >> 27) & 0x7F]; + + let key3 = Opcode{opcode6_2: op[0], opcode14_12: Some(op[1]), opcode31_27: Some(op[2])}; + if let Some(x) = decoders.get(&key3) { + return Ok(x); + } + + let key2 = Opcode{opcode6_2: op[0], opcode14_12: Some(op[1]), opcode31_27: None}; + if let Some(x) = decoders.get(&key2) { + return Ok(x); + } + + let key1 = Opcode{opcode6_2: op[0], opcode14_12: None, opcode31_27: None}; + if let Some(x) = decoders.get(&key1) { + return Ok(x); + } + + Err("Invalid opcode".into()) + } + + pub fn execute(&mut self, instruction: u32) -> Result<(), Box> { + let instr: &Box = Self::decode(&self.decoders, instruction)?; + instr.execute(instruction, &mut self.state)?; + Ok(()) + } + +} -- cgit v1.2.3