1use super::{
6 elem_type::{BitMask, Endianness, IntegerRepresentation, Sign},
7 interface::{IInteger, INode, IRegister, ISelector, IncrementMode},
8 node_base::{NodeAttributeBase, NodeBase},
9 register_base::RegisterBase,
10 store::{CacheStore, NodeId, NodeStore, ValueStore},
11 utils, Device, GenApiError, GenApiResult, ValueCtxt,
12};
13
14#[derive(Debug, Clone)]
15pub struct MaskedIntRegNode {
16 pub(crate) attr_base: NodeAttributeBase,
17 pub(crate) register_base: RegisterBase,
18
19 pub(crate) bit_mask: BitMask,
20 pub(crate) sign: Sign,
21 pub(crate) endianness: Endianness,
22 pub(crate) unit: Option<String>,
23 pub(crate) representation: IntegerRepresentation,
24 pub(crate) p_selected: Vec<NodeId>,
25}
26
27impl MaskedIntRegNode {
28 #[must_use]
29 pub fn register_base(&self) -> &RegisterBase {
30 &self.register_base
31 }
32
33 #[must_use]
34 pub fn bit_mask(&self) -> BitMask {
35 self.bit_mask
36 }
37
38 #[must_use]
39 pub fn sign(&self) -> Sign {
40 self.sign
41 }
42
43 #[must_use]
44 pub fn endianness(&self) -> Endianness {
45 self.endianness
46 }
47
48 #[must_use]
49 pub fn unit_elem(&self) -> Option<&str> {
50 self.unit.as_deref()
51 }
52
53 #[must_use]
54 pub fn representation_elem(&self) -> IntegerRepresentation {
55 self.representation
56 }
57
58 #[must_use]
59 pub fn p_selected(&self) -> &[NodeId] {
60 &self.p_selected
61 }
62}
63
64impl INode for MaskedIntRegNode {
65 fn node_base(&self) -> NodeBase {
66 let elem_base = &self.register_base.elem_base;
67 NodeBase::new(&self.attr_base, elem_base)
68 }
69
70 fn streamable(&self) -> bool {
71 self.register_base().streamable()
72 }
73}
74
75impl IInteger for MaskedIntRegNode {
76 #[tracing::instrument(skip(self, device, store, cx),
77 level = "trace",
78 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
79 fn value<T: ValueStore, U: CacheStore>(
80 &self,
81 device: &mut impl Device,
82 store: &impl NodeStore,
83 cx: &mut ValueCtxt<T, U>,
84 ) -> GenApiResult<i64> {
85 let nid = self.node_base().id();
86 let reg = self.register_base();
87
88 let reg_value = reg.with_cache_or_read(nid, device, store, cx, |data| {
90 utils::int_from_slice(data, self.endianness, self.sign)
91 })?;
92
93 let len = reg.length(device, store, cx)? as usize;
95 let res = self
96 .bit_mask
97 .apply_mask(reg_value, len, self.endianness, self.sign);
98
99 Ok(res)
100 }
101
102 #[tracing::instrument(skip(self, device, store, cx),
103 level = "trace",
104 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
105 fn set_value<T: ValueStore, U: CacheStore>(
106 &self,
107 value: i64,
108 device: &mut impl Device,
109 store: &impl NodeStore,
110 cx: &mut ValueCtxt<T, U>,
111 ) -> GenApiResult<()> {
112 let nid = self.node_base().id();
113 cx.invalidate_cache_by(nid);
114
115 let reg = self.register_base();
116 let old_reg_value = reg.with_cache_or_read(nid, device, store, cx, |data| {
117 utils::int_from_slice(data, self.endianness, self.sign)
118 })?;
119
120 let length = reg.length(device, store, cx)? as usize;
121 let new_reg_value =
122 self.bit_mask
123 .masked_value(old_reg_value, value, length, self.endianness, self.sign)?;
124 let mut buf = vec![0; length];
125 utils::bytes_from_int(new_reg_value, &mut buf, self.endianness, self.sign)?;
126 reg.write_and_cache(nid, &buf, device, store, cx)?;
127
128 Ok(())
129 }
130
131 #[tracing::instrument(skip(self, device, store, cx),
132 level = "trace",
133 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
134 fn min<T: ValueStore, U: CacheStore>(
135 &self,
136 device: &mut impl Device,
137 store: &impl NodeStore,
138 cx: &mut ValueCtxt<T, U>,
139 ) -> GenApiResult<i64> {
140 let len = self.register_base().length(device, store, cx)? as usize;
141 Ok(self.bit_mask.min(len, self.endianness, self.sign))
142 }
143
144 #[tracing::instrument(skip(self, device, store, cx),
145 level = "trace",
146 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
147 fn max<T: ValueStore, U: CacheStore>(
148 &self,
149 device: &mut impl Device,
150 store: &impl NodeStore,
151 cx: &mut ValueCtxt<T, U>,
152 ) -> GenApiResult<i64> {
153 let len = self.register_base().length(device, store, cx)? as usize;
154 Ok(self.bit_mask.max(len, self.endianness, self.sign))
155 }
156
157 fn inc_mode(&self, _: &impl NodeStore) -> Option<IncrementMode> {
158 None
159 }
160
161 fn inc<T: ValueStore, U: CacheStore>(
162 &self,
163 _: &mut impl Device,
164 _: &impl NodeStore,
165 _: &mut ValueCtxt<T, U>,
166 ) -> GenApiResult<Option<i64>> {
167 Ok(None)
168 }
169
170 fn valid_value_set(&self, _: &impl NodeStore) -> &[i64] {
171 &[]
172 }
173
174 fn representation(&self, _: &impl NodeStore) -> IntegerRepresentation {
175 self.representation_elem()
176 }
177
178 fn unit(&self, _: &impl NodeStore) -> Option<&str> {
179 self.unit_elem()
180 }
181
182 #[tracing::instrument(skip(self, store),
183 level = "trace",
184 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
185 fn set_min<T: ValueStore, U: CacheStore>(
186 &self,
187 _: i64,
188 _: &mut impl Device,
189 store: &impl NodeStore,
190 _: &mut ValueCtxt<T, U>,
191 ) -> GenApiResult<()> {
192 Err(GenApiError::not_writable())
193 }
194
195 #[tracing::instrument(skip(self, store),
196 level = "trace",
197 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
198 fn set_max<T: ValueStore, U: CacheStore>(
199 &self,
200 _: i64,
201 _: &mut impl Device,
202 store: &impl NodeStore,
203 _: &mut ValueCtxt<T, U>,
204 ) -> GenApiResult<()> {
205 Err(GenApiError::not_writable())
206 }
207
208 #[tracing::instrument(skip(self, device, store, cx),
209 level = "trace",
210 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
211 fn is_readable<T: ValueStore, U: CacheStore>(
212 &self,
213 device: &mut impl Device,
214 store: &impl NodeStore,
215 cx: &mut ValueCtxt<T, U>,
216 ) -> GenApiResult<bool> {
217 self.register_base().is_readable(device, store, cx)
218 }
219
220 #[tracing::instrument(skip(self, device, store, cx),
221 level = "trace",
222 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
223 fn is_writable<T: ValueStore, U: CacheStore>(
224 &self,
225 device: &mut impl Device,
226 store: &impl NodeStore,
227 cx: &mut ValueCtxt<T, U>,
228 ) -> GenApiResult<bool> {
229 self.register_base().is_writable(device, store, cx)
230 }
231}
232
233impl IRegister for MaskedIntRegNode {
234 #[tracing::instrument(skip(self, device, store, cx),
235 level = "trace",
236 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
237 fn read<T: ValueStore, U: CacheStore>(
238 &self,
239 buf: &mut [u8],
240 device: &mut impl Device,
241 store: &impl NodeStore,
242 cx: &mut ValueCtxt<T, U>,
243 ) -> GenApiResult<()> {
244 let address = self.address(device, store, cx)?;
245 let length = self.length(device, store, cx)?;
246 self.register_base().read_and_cache(
247 self.node_base().id(),
248 address,
249 length,
250 buf,
251 device,
252 store,
253 cx,
254 )
255 }
256
257 #[tracing::instrument(skip(self, device, store, cx),
258 level = "trace",
259 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
260 fn write<T: ValueStore, U: CacheStore>(
261 &self,
262 buf: &[u8],
263 device: &mut impl Device,
264 store: &impl NodeStore,
265 cx: &mut ValueCtxt<T, U>,
266 ) -> GenApiResult<()> {
267 self.register_base()
268 .write_and_cache(self.node_base().id(), buf, device, store, cx)
269 }
270
271 #[tracing::instrument(skip(self, device, store, cx),
272 level = "trace",
273 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
274 fn address<T: ValueStore, U: CacheStore>(
275 &self,
276 device: &mut impl Device,
277 store: &impl NodeStore,
278 cx: &mut ValueCtxt<T, U>,
279 ) -> GenApiResult<i64> {
280 self.register_base().address(device, store, cx)
281 }
282
283 #[tracing::instrument(skip(self, device, store, cx),
284 level = "trace",
285 fields(node = store.name_by_id(self.node_base().id()).unwrap()))]
286 fn length<T: ValueStore, U: CacheStore>(
287 &self,
288 device: &mut impl Device,
289 store: &impl NodeStore,
290 cx: &mut ValueCtxt<T, U>,
291 ) -> GenApiResult<i64> {
292 self.register_base().length(device, store, cx)
293 }
294}
295
296impl ISelector for MaskedIntRegNode {
297 fn selecting_nodes(&self, _: &impl NodeStore) -> GenApiResult<&[NodeId]> {
298 Ok(self.p_selected())
299 }
300}
301
302impl BitMask {
303 fn apply_mask(
304 &self,
305 reg_value: i64,
306 reg_byte_len: usize,
307 endianness: Endianness,
308 sign: Sign,
309 ) -> i64 {
310 let mask = self.mask(reg_byte_len, endianness);
311 let (lsb, msb) = (
312 self.lsb(reg_byte_len, endianness),
313 self.msb(reg_byte_len, endianness),
314 );
315 let res = (reg_value & mask) >> lsb;
316
317 match sign {
318 Sign::Signed if res >> (msb - lsb) == 1 => {
319 res | ((-1) ^ (mask >> lsb))
321 }
322 _ => res,
323 }
324 }
325
326 fn masked_value(
327 &self,
328 old_reg_value: i64,
329 value: i64,
330 reg_byte_len: usize,
331 endianness: Endianness,
332 sign: Sign,
333 ) -> GenApiResult<i64> {
334 if value > self.max(reg_byte_len, endianness, sign)
335 || value < self.min(reg_byte_len, endianness, sign)
336 {
337 return Err(GenApiError::invalid_data(
338 "given value doesn't fit into the bit range".into(),
339 ));
340 }
341
342 let mask = self.mask(reg_byte_len, endianness);
343 let lsb = self.lsb(reg_byte_len, endianness);
344 Ok((old_reg_value & !mask) | ((value << lsb) & mask))
345 }
346
347 fn lsb(self, reg_byte_len: usize, endianness: Endianness) -> usize {
348 let lsb = match self {
349 Self::SingleBit(lsb) | Self::Range { lsb, .. } => lsb as usize,
350 };
351
352 let bits_len = reg_byte_len * 8;
354 match endianness {
355 Endianness::LE => lsb,
356 Endianness::BE => bits_len - lsb - 1,
357 }
358 }
359
360 fn msb(self, reg_byte_len: usize, endianness: Endianness) -> usize {
361 let msb = match self {
362 Self::SingleBit(msb) | Self::Range { msb, .. } => msb as usize,
363 };
364
365 let bits_len = reg_byte_len * 8;
367 match endianness {
368 Endianness::LE => msb,
369 Endianness::BE => bits_len - msb - 1,
370 }
371 }
372
373 fn min(&self, reg_byte_len: usize, endianness: Endianness, sign: Sign) -> i64 {
374 let (lsb, msb) = (
375 self.lsb(reg_byte_len, endianness),
376 self.msb(reg_byte_len, endianness),
377 );
378 match sign {
379 Sign::Signed => {
380 if msb - lsb == 63 {
381 i64::MIN
382 } else {
383 let value = 1 << (msb - lsb) as i64;
384 -value
385 }
386 }
387 Sign::Unsigned => 0,
388 }
389 }
390
391 fn max(&self, reg_byte_len: usize, endianness: Endianness, sign: Sign) -> i64 {
392 let (lsb, msb) = (
393 self.lsb(reg_byte_len, endianness),
394 self.msb(reg_byte_len, endianness),
395 );
396 if msb - lsb == 63 {
397 return i64::MAX;
398 }
399 match sign {
400 Sign::Signed => (1 << (msb - lsb)) - 1,
401 Sign::Unsigned => {
402 if msb - lsb == 63 {
403 i64::MAX
404 } else {
405 (1 << (msb - lsb + 1)) - 1
406 }
407 }
408 }
409 }
410
411 fn mask(&self, reg_byte_len: usize, endianness: Endianness) -> i64 {
412 let (lsb, msb) = (
413 self.lsb(reg_byte_len, endianness),
414 self.msb(reg_byte_len, endianness),
415 );
416 if msb - lsb == 63 {
417 -1
418 } else {
419 ((1 << (msb - lsb + 1)) - 1) << lsb
420 }
421 }
422}
423
424#[cfg(test)]
425mod tests {
426 use super::*;
427
428 #[test]
429 fn test_bit_mask_8bit_single_bit() {
430 let reg_len = 1;
431 let reg_value = 0b1100_1011;
432 let endianness = Endianness::LE;
433 let mask = BitMask::SingleBit(3);
434
435 let sign = Sign::Unsigned;
436 assert_eq!(mask.min(reg_len, endianness, sign), 0);
437 assert_eq!(mask.max(reg_len, endianness, sign), 1);
438 let value = mask.apply_mask(reg_value, reg_len, endianness, sign);
439 assert_eq!(value, 1);
440 let new_value = mask
441 .masked_value(reg_value, 0, reg_len, endianness, sign)
442 .unwrap();
443 assert_eq!(new_value, 0b1100_0011);
444
445 let sign = Sign::Signed;
446 assert_eq!(mask.min(reg_len, endianness, sign), -1);
447 assert_eq!(mask.max(reg_len, endianness, sign), 0);
448 let value = mask.apply_mask(reg_value, reg_len, endianness, sign);
449 assert_eq!(value, -1);
450 let new_value = mask
451 .masked_value(reg_value, 0, reg_len, endianness, sign)
452 .unwrap();
453 assert_eq!(new_value, 0b1100_0011);
454 }
455
456 #[test]
457 fn test_bit_mask_8bit_le() {
458 let reg_len = 1;
459 let reg_value = 0b1100_1011;
460 let endianness = Endianness::LE;
461 let mask = BitMask::Range { lsb: 1, msb: 4 };
462
463 let sign = Sign::Unsigned;
464 assert_eq!(mask.min(reg_len, endianness, sign), 0);
465 assert_eq!(mask.max(reg_len, endianness, sign), 15);
466 let value = mask.apply_mask(reg_value, reg_len, endianness, sign);
467 assert_eq!(value, 0b0101);
468 let new_value = mask
469 .masked_value(reg_value, 0b0110, reg_len, endianness, sign)
470 .unwrap();
471 assert_eq!(new_value, 0b1100_1101);
472
473 let sign = Sign::Signed;
474 let value = mask.apply_mask(reg_value, reg_len, endianness, sign);
475 assert_eq!(mask.min(reg_len, endianness, sign), -8);
476 assert_eq!(mask.max(reg_len, endianness, sign), 7);
477 assert_eq!(value, 5);
478 let new_value = mask
479 .masked_value(reg_value, -1, reg_len, endianness, sign)
480 .unwrap();
481 assert_eq!(new_value, 0b1101_1111);
482 }
483
484 #[test]
485 fn test_bit_mask_8bit_be() {
486 let reg_len = 1;
487 let reg_value = 0b1100_1011;
488 let endianness = Endianness::BE;
489 let mask = BitMask::Range { lsb: 6, msb: 3 };
490
491 let sign = Sign::Unsigned;
492 let value = mask.apply_mask(reg_value, reg_len, endianness, sign);
493 assert_eq!(value, 0b0101);
494 let new_value = mask
495 .masked_value(reg_value, 0b0110, reg_len, endianness, sign)
496 .unwrap();
497 assert_eq!(new_value, 0b1100_1101);
498
499 let sign = Sign::Signed;
500 let value = mask.apply_mask(reg_value, reg_len, endianness, sign);
501 assert_eq!(value, 5);
502 let new_value = mask
503 .masked_value(reg_value, -1, reg_len, endianness, sign)
504 .unwrap();
505 assert_eq!(new_value, 0b1101_1111);
506
507 let new_value = mask.masked_value(reg_value, 256, reg_len, endianness, sign);
508 assert!(new_value.is_err());
509 }
510
511 #[test]
512 fn test_bit_mask_64bit() {
513 let reg_len = 1;
514 let reg_value = i64::MAX;
515 let endianness = Endianness::LE;
516 let mask = BitMask::Range { lsb: 0, msb: 63 };
517
518 let sign = Sign::Unsigned;
519 assert_eq!(mask.min(reg_len, endianness, sign), 0);
520 assert_eq!(mask.max(reg_len, endianness, sign), i64::MAX);
521 let value = mask.apply_mask(reg_value, reg_len, endianness, sign);
522 assert_eq!(value, i64::MAX);
523 let new_value = mask
524 .masked_value(reg_value, 0, reg_len, endianness, sign)
525 .unwrap();
526 assert_eq!(new_value, 0);
527
528 let sign = Sign::Signed;
529 assert_eq!(mask.min(reg_len, endianness, sign), i64::MIN);
530 assert_eq!(mask.max(reg_len, endianness, sign), i64::MAX);
531 let value = mask.apply_mask(reg_value, reg_len, endianness, sign);
532 assert_eq!(value, i64::MAX);
533 let new_value = mask
534 .masked_value(reg_value, i64::MIN, reg_len, endianness, sign)
535 .unwrap();
536 assert_eq!(new_value, i64::MIN);
537 }
538}