1pub mod instruction_executor;
11pub mod instruction_formats;
12pub mod instruction_string_outputter;
13pub mod memories;
14pub mod process_instruction;
15
16use downcast_rs::{impl_downcast, Downcast};
17
18pub use process_instruction::process_instruction;
19
20pub trait InstructionProcessor {
27    type InstructionResult;
28
29    fn process_add(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
30    fn process_sub(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
31    fn process_sll(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
32    fn process_slt(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
33    fn process_sltu(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
34    fn process_xor(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
35    fn process_srl(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
36    fn process_sra(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
37    fn process_or(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
38    fn process_and(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
39
40    fn process_addi(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
41    fn process_slli(
42        &mut self,
43        dec_insn: instruction_formats::ITypeShamt,
44    ) -> Self::InstructionResult;
45    fn process_slti(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
46    fn process_sltui(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
47    fn process_xori(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
48    fn process_srli(
49        &mut self,
50        dec_insn: instruction_formats::ITypeShamt,
51    ) -> Self::InstructionResult;
52    fn process_srai(
53        &mut self,
54        dec_insn: instruction_formats::ITypeShamt,
55    ) -> Self::InstructionResult;
56    fn process_ori(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
57    fn process_andi(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
58
59    fn process_lui(&mut self, dec_insn: instruction_formats::UType) -> Self::InstructionResult;
60    fn process_auipc(&mut self, dec_insn: instruction_formats::UType) -> Self::InstructionResult;
61
62    fn process_beq(&mut self, dec_insn: instruction_formats::BType) -> Self::InstructionResult;
63    fn process_bne(&mut self, dec_insn: instruction_formats::BType) -> Self::InstructionResult;
64    fn process_blt(&mut self, dec_insn: instruction_formats::BType) -> Self::InstructionResult;
65    fn process_bltu(&mut self, dec_insn: instruction_formats::BType) -> Self::InstructionResult;
66    fn process_bge(&mut self, dec_insn: instruction_formats::BType) -> Self::InstructionResult;
67    fn process_bgeu(&mut self, dec_insn: instruction_formats::BType) -> Self::InstructionResult;
68
69    fn process_lb(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
70    fn process_lbu(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
71    fn process_lh(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
72    fn process_lhu(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
73    fn process_lw(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
74
75    fn process_sb(&mut self, dec_insn: instruction_formats::SType) -> Self::InstructionResult;
76    fn process_sh(&mut self, dec_insn: instruction_formats::SType) -> Self::InstructionResult;
77    fn process_sw(&mut self, dec_insn: instruction_formats::SType) -> Self::InstructionResult;
78
79    fn process_jal(&mut self, dec_insn: instruction_formats::JType) -> Self::InstructionResult;
80    fn process_jalr(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
81
82    fn process_mul(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
83    fn process_mulh(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
84    fn process_mulhu(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
85    fn process_mulhsu(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
86
87    fn process_div(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
88    fn process_divu(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
89    fn process_rem(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
90    fn process_remu(&mut self, dec_insn: instruction_formats::RType) -> Self::InstructionResult;
91
92    fn process_fence(&mut self, dec_insn: instruction_formats::IType) -> Self::InstructionResult;
93}
94
95pub struct HartState {
97    pub registers: [u32; 32],
99    pub pc: u32,
101    pub last_register_write: Option<usize>,
104}
105
106impl HartState {
107    pub fn new() -> Self {
108        HartState {
109            registers: [0; 32],
110            pc: 0,
111            last_register_write: None,
112        }
113    }
114
115    fn write_register(&mut self, reg_index: usize, data: u32) {
118        if reg_index == 0 {
119            return;
120        }
121
122        self.registers[reg_index] = data;
123        self.last_register_write = Some(reg_index)
124    }
125
126    fn read_register(&self, reg_index: usize) -> u32 {
129        if reg_index == 0 {
130            0
131        } else {
132            self.registers[reg_index]
133        }
134    }
135}
136
137impl Default for HartState {
138    fn default() -> Self {
139        Self::new()
140    }
141}
142
143#[derive(Clone, Copy)]
145pub enum MemAccessSize {
146    Byte,
148    HalfWord,
150    Word,
152}
153
154pub trait Memory: Downcast {
156    fn read_mem(&mut self, addr: u32, size: MemAccessSize) -> Option<u32>;
161
162    fn write_mem(&mut self, addr: u32, size: MemAccessSize, store_data: u32) -> bool;
167}
168
169impl_downcast!(Memory);
170
171#[cfg(test)]
172mod tests {
173    use super::instruction_executor::{InstructionException, InstructionExecutor};
174    use super::instruction_string_outputter::InstructionStringOutputter;
175    use super::*;
176
177    #[test]
178    fn test_insn_execute() {
179        let mut hart = HartState::new();
180        let mut mem = memories::VecMemory::new(vec![
181            0x1234b137, 0xbcd10113, 0xf387e1b7, 0x3aa18193, 0xbed892b7, 0x7ac28293, 0x003100b3,
182            0xf4e0e213, 0x02120a63, 0x00121463, 0x1542c093, 0x00c0036f, 0x0020f0b3, 0x402080b3,
183            0x00000397, 0x02838393, 0x0003a403, 0x00638483, 0x0023d503, 0x00139223, 0x0043a583,
184            0x00000000, 0x00000000, 0x00000000, 0xdeadbeef, 0xbaadf00d,
185        ]);
186
187        hart.pc = 0;
188
189        let mut executor = InstructionExecutor {
195            hart_state: &mut hart,
196            mem: &mut mem,
197        };
198
199        while executor.hart_state.pc != 0x54 {
200            let mut outputter = InstructionStringOutputter {
201                insn_pc: executor.hart_state.pc,
202            };
203            let insn_bits = executor
204                .mem
205                .read_mem(executor.hart_state.pc, MemAccessSize::Word)
206                .unwrap();
207
208            assert_eq!(executor.step(), Ok(()));
209
210            println!(
211                "{:x} {}",
212                executor.hart_state.pc,
213                process_instruction(&mut outputter, insn_bits).unwrap()
214            );
215            if let Some(reg_index) = executor.hart_state.last_register_write {
216                println!(
217                    "x{} = {:08x}",
218                    reg_index, executor.hart_state.registers[reg_index]
219                );
220            }
221        }
222
223        assert_eq!(executor.hart_state.registers[1], 0x05bc8f77);
224        assert_eq!(executor.hart_state.registers[2], 0x1234abcd);
225        assert_eq!(executor.hart_state.registers[3], 0xf387e3aa);
226        assert_eq!(executor.hart_state.registers[4], 0xffffff7f);
227        assert_eq!(executor.hart_state.registers[5], 0xbed897ac);
228        assert_eq!(executor.hart_state.registers[6], 0x00000030);
229        assert_eq!(executor.hart_state.registers[7], 0x00000060);
230        assert_eq!(executor.hart_state.registers[8], 0xdeadbeef);
231        assert_eq!(executor.hart_state.registers[9], 0xffffffad);
232        assert_eq!(executor.hart_state.registers[10], 0x0000dead);
233        assert_eq!(executor.hart_state.registers[11], 0xbaad8f77);
234
235        assert_eq!(
236            executor.step(),
237            Err(InstructionException::IllegalInstruction(0x54, 0))
238        );
239    }
240}