ab_riscv_interpreter/v/
vector_config.rs1#[cfg(test)]
4mod tests;
5
6use ab_riscv_primitives::prelude::*;
7use core::fmt;
8use core::hint::{assert_unchecked, cold_path};
9use core::marker::PhantomData;
10
11#[derive(Debug, Clone, Copy)]
17pub struct BoundedVl<Hart>(Vl, PhantomData<Hart>)
18where
19 Hart: VectorHartConfig;
20
21const impl<Hart> PartialEq for BoundedVl<Hart>
22where
23 Hart: VectorHartConfig,
24{
25 #[inline(always)]
26 fn eq(&self, other: &Self) -> bool {
27 self.0 == other.0
28 }
29}
30
31const impl<Hart> Eq for BoundedVl<Hart> where Hart: VectorHartConfig {}
32
33impl<Hart> fmt::Display for BoundedVl<Hart>
34where
35 Hart: VectorHartConfig,
36{
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 self.0.fmt(f)
39 }
40}
41
42const impl<Hart> From<BoundedVl<Hart>> for Vl
43where
44 Hart: VectorHartConfig,
45{
46 #[inline(always)]
47 fn from(value: BoundedVl<Hart>) -> Self {
48 value.get()
49 }
50}
51
52impl<Hart> BoundedVl<Hart>
53where
54 Hart: VectorHartConfig,
55{
56 #[inline(always)]
58 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
59 pub const fn new(vl: Vl) -> Option<Self> {
60 if u32::from(vl) > u32::from(Hart::VECTOR_LENGTHS.vlen) {
61 cold_path();
62 return None;
63 }
64 Some(Self(vl, PhantomData))
65 }
66
67 #[inline(always)]
69 pub const fn get(self) -> Vl {
70 unsafe {
72 assert_unchecked(u32::from(self.0) <= u32::from(Hart::VECTOR_LENGTHS.vlen));
73 }
74 self.0
75 }
76
77 #[inline(always)]
82 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
83 pub fn indices(self) -> impl Iterator<Item = u16> {
84 (0..u32::from(self.get())).map(u32::truncate)
86 }
87
88 #[inline(always)]
90 pub const fn bytes(self) -> u16 {
91 let bytes = self.get().bytes();
92 unsafe {
94 assert_unchecked(u32::from(bytes) <= Hart::VECTOR_LENGTHS.vlen.bytes());
95 }
96 bytes
97 }
98}
99
100#[derive(Debug, Clone, Copy)]
110pub struct VectorConfig<Hart>
111where
112 Hart: VectorHartConfig,
113{
114 vtype: Vtype<Hart>,
115 vl: Vl,
116}
117
118const impl<Hart> PartialEq for VectorConfig<Hart>
119where
120 Hart: VectorHartConfig,
121{
122 #[inline(always)]
123 fn eq(&self, other: &Self) -> bool {
124 self.vtype == other.vtype && self.vl == other.vl
125 }
126}
127
128const impl<Hart> Eq for VectorConfig<Hart> where Hart: VectorHartConfig {}
129
130impl<Hart> VectorConfig<Hart>
131where
132 Hart: VectorHartConfig,
133{
134 #[inline(always)]
138 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
139 pub const fn new(vtype: Vtype<Hart>, vl: Vl) -> Option<Self> {
140 if u32::from(vl) > u32::from(vtype.vlmax()) {
141 cold_path();
142 return None;
143 }
144
145 Some(Self { vtype, vl })
146 }
147
148 #[inline(always)]
154 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
155 pub const fn from_avl(vtype: Vtype<Hart>, avl: Vl) -> Self {
156 let vlmax = vtype.vlmax();
157 let vl = if u32::from(avl) > u32::from(vlmax) {
158 vlmax
159 } else {
160 avl
161 };
162
163 Self { vtype, vl }
164 }
165
166 #[inline(always)]
172 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
173 pub const fn from_raw<Reg>(vtype: Reg::Type, vl: Reg::Type) -> Option<Self>
174 where
175 Reg: [const] Register,
176 {
177 let vtype = Vtype::from_raw::<Reg>(vtype)?;
178 let Ok(vl) = u32::try_from(vl.as_u64()) else {
179 cold_path();
180 return None;
181 };
182 let vl = Vl::new(vl)?;
183
184 Self::new(vtype, vl)
185 }
186
187 #[inline(always)]
189 pub const fn vtype(self) -> Vtype<Hart> {
190 self.vtype
191 }
192
193 #[inline(always)]
195 pub const fn vl(self) -> BoundedVl<Hart> {
196 BoundedVl(self.vl, PhantomData)
197 }
198
199 #[inline(always)]
201 pub const fn vlmax(self) -> Vl {
202 self.vtype.vlmax()
203 }
204
205 #[inline(always)]
208 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
209 pub const fn with_vl_at_most(self, vl: Vl) -> Self {
210 let vl = if u32::from(vl) < u32::from(self.vl) {
211 vl
212 } else {
213 self.vl
214 };
215
216 Self {
217 vtype: self.vtype,
218 vl,
219 }
220 }
221}