ab_riscv_interpreter/v/
vector_registers.rs1use crate::Csrs;
4use ab_riscv_primitives::prelude::*;
5
6pub(crate) const VLENB_USIZE<const VLEN: Vlen>: usize = VLEN.bytes() as usize;
7
8#[derive(Debug, Clone, Copy)]
10#[repr(align(128))]
13pub struct VectorRegisterFile<const VLEN: Vlen>([[u8; VLENB_USIZE::<VLEN>]; 32]);
14
15const impl<const VLEN: Vlen> Default for VectorRegisterFile<VLEN> {
16 #[inline(always)]
17 fn default() -> Self {
18 Self([[0; _]; _])
19 }
20}
21
22impl<const VLEN: Vlen> VectorRegisterFile<VLEN> {
23 #[inline(always)]
25 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
26 pub const fn get(&self, index: VReg) -> &[u8; VLENB_USIZE::<VLEN>] {
27 unsafe { self.0.get_unchecked(usize::from(index.to_bits())) }
29 }
30
31 #[inline(always)]
33 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
34 pub const fn get_mut(&mut self, index: VReg) -> &mut [u8; VLENB_USIZE::<VLEN>] {
35 unsafe { self.0.get_unchecked_mut(usize::from(index.to_bits())) }
37 }
38}
39
40pub const trait VectorRegisters {
53 const ELEN: Elen;
55 const VLEN: Vlen;
57
58 fn read_vregs(&self) -> &VectorRegisterFile<{ Self::VLEN }>;
60
61 fn write_vregs(&mut self) -> &mut VectorRegisterFile<{ Self::VLEN }>;
63
64 fn vector_instructions_allowed(&self) -> bool;
69
70 fn mark_vs_dirty(&mut self);
75
76 #[inline(always)]
82 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
83 fn compute_vl(&self, avl: Vl, vlmax: Vl) -> Vl {
84 avl.min(vlmax)
85 }
86
87 #[inline(always)]
89 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
90 fn vlmax_for_vtype(&self, vtype: Vtype<{ Self::ELEN }, { Self::VLEN }>) -> Vl
91 where
92 [(); SUPPORTED_ELEN_VLEN::<{ Self::ELEN }, { Self::VLEN }>]:,
93 {
94 vtype.vlmul().vlmax::<{ Self::VLEN }>(vtype.vsew())
95 }
96}
97
98pub const trait VectorRegistersExt<Reg>
108where
109 Self: [const] Csrs<Reg> + [const] VectorRegisters,
110 [(); SUPPORTED_ELEN_VLEN::<{ Self::ELEN }, { Self::VLEN }>]:,
111 Reg: [const] Register,
112{
113 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
119 fn initialize_vector_state(&mut self) {
120 self.set_vtype(None);
121 self.set_vl(Vl::ZERO);
122 self.set_vstart(Vstart::ZERO);
123 self.set_vxrm(Vxrm::default());
124 self.set_vxsat(false);
125 }
126
127 #[inline(always)]
129 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
130 fn vstart(&self) -> Vstart {
131 let raw = self
132 .read_csr(VectorCsr::Vstart.to_csr_index())
133 .unwrap_or_default()
134 .as_u64();
135 Vstart::from(raw as u16)
136 }
137
138 #[inline(always)]
143 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
144 fn set_vstart(&mut self, vstart: Vstart) {
145 let result = self.write_csr(
146 VectorCsr::Vstart.to_csr_index(),
147 Reg::Type::from(u16::from(vstart)),
148 );
149 debug_assert!(
150 result.is_ok(),
151 "Implementation must initialize `vstart` CSR"
152 );
153 }
154
155 #[inline(always)]
159 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
160 fn reset_vstart(&mut self) {
161 self.set_vstart(Vstart::ZERO);
162 }
163
164 #[inline(always)]
166 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
167 fn vxsat(&self) -> bool {
168 let raw = self
169 .read_csr(VectorCsr::Vxsat.to_csr_index())
170 .unwrap_or_default()
171 .as_u64();
172 (raw & 1) == 1
173 }
174
175 #[inline(always)]
180 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
181 fn set_vxsat(&mut self, vxsat: bool) {
182 let masked = Reg::Type::from(u8::from(vxsat));
183 let result = self.write_csr(VectorCsr::Vxsat.to_csr_index(), masked);
184 debug_assert!(result.is_ok(), "Implementation must initialize `vxsat` CSR");
185 let old_vcsr = self
187 .read_csr(VectorCsr::Vcsr.to_csr_index())
188 .unwrap_or_default();
189 let new_vcsr = (old_vcsr & !Reg::Type::from(1u8)) | masked;
190 let result = self.write_csr(VectorCsr::Vcsr.to_csr_index(), new_vcsr);
191 debug_assert!(result.is_ok(), "Implementation must initialize `vcsr` CSR");
192 }
193
194 #[inline(always)]
196 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
197 fn vxrm(&self) -> Vxrm {
198 let raw = self
199 .read_csr(VectorCsr::Vxrm.to_csr_index())
200 .unwrap_or_default()
201 .as_u64();
202 Vxrm::from_bits(raw as u8)
203 }
204
205 #[inline(always)]
210 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
211 fn set_vxrm(&mut self, vxrm: Vxrm) {
212 let masked = Reg::Type::from(vxrm.to_bits());
213 let result = self.write_csr(VectorCsr::Vxrm.to_csr_index(), masked);
214 debug_assert!(result.is_ok(), "Implementation must initialize `vxrm` CSR");
215 let old_vcsr = self
217 .read_csr(VectorCsr::Vcsr.to_csr_index())
218 .unwrap_or_default();
219 let new_vcsr = (old_vcsr & !Reg::Type::from(0b110u8)) | (masked << 1u8);
220 let result = self.write_csr(VectorCsr::Vcsr.to_csr_index(), new_vcsr);
221 debug_assert!(result.is_ok(), "Implementation must initialize `vcsr` CSR");
222 }
223
224 #[inline(always)]
226 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
227 fn vl(&self) -> Vl {
228 let vl = self
229 .read_csr(VectorCsr::Vl.to_csr_index())
230 .unwrap_or_default()
231 .as_u64() as u32;
232 Vl::new(vl).unwrap_or_default()
234 }
235
236 #[inline(always)]
244 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
245 fn set_vl(&mut self, vl: Vl) {
246 let result = self.write_csr(VectorCsr::Vl.to_csr_index(), Reg::Type::from(u32::from(vl)));
247 debug_assert!(result.is_ok(), "Implementation must initialize `vl` CSR");
248 }
249
250 #[inline(always)]
252 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
253 fn vtype(&self) -> Option<Vtype<{ Self::ELEN }, { Self::VLEN }>> {
254 self.read_csr(VectorCsr::Vtype.to_csr_index())
255 .ok()
256 .and_then(Vtype::from_raw::<Reg>)
257 }
258
259 #[inline(always)]
267 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
268 fn set_vtype(&mut self, vtype: Option<Vtype<{ Self::ELEN }, { Self::VLEN }>>) {
269 let vtype_raw = if let Some(vt) = vtype {
270 vt.to_raw::<Reg>()
271 } else {
272 Vtype::<{ Self::ELEN }, { Self::VLEN }>::illegal_raw::<Reg>()
273 };
274
275 let result = self.write_csr(VectorCsr::Vtype.to_csr_index(), vtype_raw);
276 debug_assert!(result.is_ok(), "Implementation must initialize `vtype` CSR");
277 }
278}
279
280#[macro_export]
285macro_rules! impl_vector_registers_for_mut_ref {
286 ($env:ty, $reg:ty) => {
287 impl VectorRegisters for &mut $env {
288 const ELEN: Elen = <$env as VectorRegisters>::ELEN;
289 const VLEN: Vlen = <$env as VectorRegisters>::VLEN;
290
291 #[inline(always)]
292 fn read_vregs(&self) -> &VectorRegisterFile<{ Self::VLEN }> {
293 <$env as VectorRegisters>::read_vregs(self)
294 }
295
296 #[inline(always)]
297 fn write_vregs(&mut self) -> &mut VectorRegisterFile<{ Self::VLEN }> {
298 <$env as VectorRegisters>::write_vregs(self)
299 }
300
301 #[inline(always)]
302 fn vector_instructions_allowed(&self) -> bool {
303 <$env as VectorRegisters>::vector_instructions_allowed(self)
304 }
305
306 #[inline(always)]
307 fn mark_vs_dirty(&mut self) {
308 <$env as VectorRegisters>::mark_vs_dirty(self);
309 }
310 }
311
312 impl VectorRegistersExt<$reg> for &mut $env {}
313 };
314}