ab_riscv_interpreter/v/vector_registers/
segment.rs1use crate::v::vector_registers::{VRegGroup, VectorRegisterFile};
4use ab_riscv_primitives::prelude::*;
5use core::hint::cold_path;
6
7#[derive(Debug, Clone, Copy)]
10pub struct VRegSegmentGroup<Hart>
11where
12 Hart: VectorHartConfig,
13{
14 first: VRegGroup<Hart>,
16 nf: Nf,
17}
18
19impl<Hart> VRegSegmentGroup<Hart>
20where
21 Hart: VectorHartConfig,
22{
23 #[inline(always)]
28 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
29 pub const fn new(first: VRegGroup<Hart>, nf: Nf) -> Option<Self> {
30 let regs = u32::from(nf.fields_per_segment()) * u32::from(first.group_regs().get());
31 if regs > 8 || u32::from(first.base.to_bits()) + regs > 32 {
34 cold_path();
35 return None;
36 }
37 Some(Self { first, nf })
38 }
39
40 #[inline(always)]
42 pub const fn single(group: VRegGroup<Hart>) -> Self {
43 Self {
44 first: group,
45 nf: Nf::N1,
46 }
47 }
48
49 #[inline(always)]
51 pub const fn first(self) -> VRegGroup<Hart> {
52 self.first
53 }
54
55 #[inline(always)]
57 pub const fn nf(self) -> Nf {
58 self.nf
59 }
60
61 #[inline(always)]
63 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
64 pub const fn field(self, field: u8) -> Option<VRegGroup<Hart>> {
65 if field >= self.nf.fields_per_segment() {
66 cold_path();
67 return None;
68 }
69 let base = unsafe { self.field_base(field) };
71 Some(VRegGroup { base, ..self.first })
72 }
73
74 #[inline(always)]
79 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
80 const unsafe fn field_base(self, field: u8) -> VReg {
81 unsafe {
84 VReg::from_bits(self.first.base.to_bits() + field * self.first.group_regs().get())
85 .unwrap_unchecked()
86 }
87 }
88
89 #[inline(always)]
91 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
92 pub fn fields(self) -> impl Iterator<Item = VRegGroup<Hart>> {
93 (0..self.nf.fields_per_segment()).filter_map(move |field| self.field(field))
94 }
95
96 #[inline(always)]
101 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
102 pub fn elements(self, start: u16) -> impl Iterator<Item = SegmentElement<Hart>> {
103 (u32::from(start)..u32::from(self.first.vl.get())).map(move |index| SegmentElement {
105 group: self,
106 index: u32::truncate(index),
107 })
108 }
109
110 #[inline(always)]
115 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
116 pub fn with_index(self, index: VRegGroup<Hart>) -> Option<IndexedSegmentGroup<Hart>> {
117 if index.vl != self.first.vl {
118 cold_path();
119 return None;
120 }
121 Some(IndexedSegmentGroup { data: self, index })
122 }
123}
124
125#[derive(Debug, Clone, Copy)]
127pub struct SegmentElement<Hart>
128where
129 Hart: VectorHartConfig,
130{
131 group: VRegSegmentGroup<Hart>,
132 index: u16,
134}
135
136impl<Hart> SegmentElement<Hart>
137where
138 Hart: VectorHartConfig,
139{
140 #[inline(always)]
142 pub const fn index(self) -> u16 {
143 self.index
144 }
145
146 #[inline(always)]
148 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
149 pub fn fields(self) -> impl Iterator<Item = SegmentField<Hart>> {
150 (0..self.group.nf.fields_per_segment()).map(move |field| SegmentField {
151 element: self,
152 field,
153 })
154 }
155
156 #[inline(always)]
159 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
160 pub fn read_fields(
161 self,
162 vregs: &VectorRegisterFile<Hart>,
163 ) -> [u64; const { usize::from(Nf::MAX.fields_per_segment()) }] {
164 let mut fields = [0; _];
165 for (field, value) in (0..self.group.nf.fields_per_segment()).zip(&mut fields) {
166 unsafe {
170 let base = self.group.field_base(field);
171 *value = vregs.read_element(base, self.index, self.group.first.eew);
172 }
173 }
174 fields
175 }
176
177 #[inline(always)]
180 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
181 pub fn write_fields(self, vregs: &mut VectorRegisterFile<Hart>, fields: &[u64]) {
182 for (field, &value) in (0..self.group.nf.fields_per_segment()).zip(fields) {
183 unsafe {
185 let base = self.group.field_base(field);
186 vregs.write_element(base, self.index, self.group.first.eew, value);
187 }
188 }
189 }
190}
191
192#[derive(Debug, Clone, Copy)]
194pub struct SegmentField<Hart>
195where
196 Hart: VectorHartConfig,
197{
198 element: SegmentElement<Hart>,
199 field: u8,
201}
202
203impl<Hart> SegmentField<Hart>
204where
205 Hart: VectorHartConfig,
206{
207 #[inline(always)]
209 pub const fn index(self) -> u8 {
210 self.field
211 }
212
213 #[inline(always)]
215 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
216 pub fn write(self, vregs: &mut VectorRegisterFile<Hart>, value: u64) {
217 let element = self.element;
218 unsafe {
222 let base = element.group.field_base(self.field);
223 vregs.write_element(base, element.index, element.group.first.eew, value);
224 }
225 }
226}
227
228#[derive(Debug, Clone, Copy)]
231pub struct IndexedSegmentGroup<Hart>
232where
233 Hart: VectorHartConfig,
234{
235 data: VRegSegmentGroup<Hart>,
236 index: VRegGroup<Hart>,
238}
239
240impl<Hart> IndexedSegmentGroup<Hart>
241where
242 Hart: VectorHartConfig,
243{
244 #[inline(always)]
246 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
247 pub fn elements(self, start: u16) -> impl Iterator<Item = IndexedSegmentElement<Hart>> {
248 self.data
249 .elements(start)
250 .map(move |element| IndexedSegmentElement {
251 element,
252 index: self.index,
253 })
254 }
255}
256
257#[derive(Debug, Clone, Copy)]
259pub struct IndexedSegmentElement<Hart>
260where
261 Hart: VectorHartConfig,
262{
263 element: SegmentElement<Hart>,
264 index: VRegGroup<Hart>,
266}
267
268impl<Hart> IndexedSegmentElement<Hart>
269where
270 Hart: VectorHartConfig,
271{
272 #[inline(always)]
274 pub const fn element(self) -> SegmentElement<Hart> {
275 self.element
276 }
277
278 #[inline(always)]
280 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
281 pub fn read_index(self, vregs: &VectorRegisterFile<Hart>) -> u64 {
282 unsafe { vregs.read_element(self.index.base, self.element.index, self.index.eew) }
286 }
287}