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}