1pub mod arbitrary_float;
2pub mod instruction;
3pub mod memory;
4pub mod registers;
5pub mod snapshot;
6pub mod vector_engine;
7
8use derive_builder::Builder;
9
10use instruction::{executor::Executor, Instruction};
11use memory::Memory;
12use registers::Registers;
13
14use self::vector_engine::VectorEngine;
15
16#[derive(Builder, Clone, PartialEq, Debug)]
17#[builder(build_fn(skip))]
18pub struct RvCore {
19 pub memory: Memory,
20 pub instructions: Vec<Instruction>,
21 #[builder(setter(skip))]
22 pub registers: Registers,
23 pub vec_engine: VectorEngine,
24}
25
26impl RvCore {
27 pub fn step(&mut self) -> Option<Result<(), String>> {
28 self.run().next()
29 }
30
31 pub fn run(&mut self) -> RunningRvCore<'_> {
32 RunningRvCore { core: self }
33 }
34}
35
36impl Default for RvCore {
37 fn default() -> Self {
38 let vec_engine = VectorEngine::default();
39 let memory = Memory::default();
40
41 Self {
42 instructions: Vec::new(),
43 registers: Registers::new(&vec_engine, &memory),
44 memory,
45 vec_engine,
46 }
47 }
48}
49
50impl RvCoreBuilder {
51 pub fn build(&self) -> RvCore {
52 let memory = self.memory.clone().unwrap_or_default();
53 let instructions = self.instructions.clone().unwrap_or_default();
54 let vec_engine = self.vec_engine.unwrap_or_default();
55 let registers = Registers::new(&vec_engine, &memory);
56
57 RvCore {
58 memory,
59 instructions,
60 vec_engine,
61 registers,
62 }
63 }
64}
65
66pub struct RunningRvCore<'core> {
67 core: &'core mut RvCore,
68}
69
70impl Iterator for RunningRvCore<'_> {
71 type Item = Result<(), String>;
72
73 fn next(&mut self) -> Option<Self::Item> {
74 let instruction_pointer = self.core.registers.pc / 4;
75 let instruction = self
76 .core
77 .instructions
78 .get(instruction_pointer as usize)?
79 .clone();
80
81 Some(
82 Executor::new(
83 &mut self.core.registers,
84 &mut self.core.memory,
85 &mut self.core.vec_engine,
86 )
87 .execute(instruction),
88 )
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use crate::rv_core::{
95 registers::aliases::{csr::VLENB, integer::SP},
96 snapshot::Snapshotable,
97 vector_engine::{VectorEngineBuilder, Vlen},
98 };
99
100 use super::*;
101
102 #[test]
103 fn default_has_vector_registers() {
104 let core = RvCore::default();
105 assert_eq!(
106 core.registers.snapshot().v.len(),
107 32 * Vlen::V128.byte_length()
108 );
109 }
110
111 #[test]
112 fn custom_vlen_works() {
113 use Instruction::*;
114
115 let core = RvCoreBuilder::default()
116 .instructions(vec![Vsetvli(instruction::format::Vsetvli {
117 rd: 5,
118 rs1: 12,
119 vtypei: 195,
120 })])
121 .vec_engine(VectorEngineBuilder::default().vlen(Vlen::V256).build())
122 .build();
123 assert_eq!(
124 core.registers.snapshot().v.len(),
125 32 * Vlen::V256.byte_length()
126 );
127 }
128
129 #[test]
130 fn vlenb_csr_works() {
131 let core = RvCoreBuilder::default()
132 .vec_engine(VectorEngineBuilder::default().vlen(Vlen::V256).build())
133 .build();
134 assert_eq!(
135 core.registers.snapshot().c[VLENB].read(),
136 Vlen::V256.byte_length() as u64
137 );
138 }
139
140 #[test]
141 fn sp_points_to_stack() {
142 let memory = Memory::new([5, 2, 1, 3, 4].into_iter());
143
144 let core = RvCoreBuilder::default().memory(memory).build();
145
146 assert_eq!(core.registers.snapshot().x[SP], 4);
147 }
148}