machine_check/types/
array.rs

1use std::{
2    fmt::Debug,
3    ops::{Index, IndexMut},
4};
5
6use mck::{
7    concr::{IntoMck, UnsignedBitvector},
8    misc::{CBound, LightArray},
9};
10
11use crate::Bitvector;
12
13///
14/// Power-of-two array of bitvectors without signedness information.
15///
16/// The exponent of array size (index width) is specified in the first generic parameter I.
17/// Element width is specified in the second generic parameter L.
18///
19/// The array is indexed by bitvectors of width I, so no out-of-bound access can occur.
20///
21#[derive(Clone, Hash, PartialEq, Eq)]
22pub struct BitvectorArray<const I: u32, const W: u32> {
23    pub(super) inner: LightArray<UnsignedBitvector<CBound<I>>, Bitvector<W>>,
24}
25
26impl<const I: u32, const W: u32> BitvectorArray<I, W> {
27    /// Creates a new array filled with the given element.
28    pub fn new_filled(element: Bitvector<W>) -> Self {
29        Self {
30            inner: LightArray::new_filled(CBound::<I>, element),
31        }
32    }
33
34    /// Creates the bitvector array from a correctly sized slice of bitvectors.
35    ///
36    /// Panics if the bitvector slice width is not equal to 2<sup>L</sup>.
37    ///
38    /// Cannot be used within the machine_description macro.
39    pub fn from_slice(slice: &[Bitvector<W>]) -> Self {
40        assert!(I < usize::BITS);
41        assert_eq!(1 << I, slice.len());
42        // make zeroed first
43        let mut inner = LightArray::new_filled(CBound::<I>, Bitvector::new(0));
44        // assign each element
45        let mut index = UnsignedBitvector::zero(CBound::<I>);
46        for element in slice.iter().cloned() {
47            inner.write(index, element);
48            index = index + UnsignedBitvector::one(CBound::<I>);
49        }
50
51        Self { inner }
52    }
53}
54
55impl<const I: u32, const W: u32> Index<Bitvector<I>> for BitvectorArray<I, W> {
56    type Output = Bitvector<W>;
57
58    fn index(&self, index: Bitvector<I>) -> &Self::Output {
59        &self.inner[index.into_mck().as_unsigned()]
60    }
61}
62
63impl<const I: u32, const W: u32> IndexMut<Bitvector<I>> for BitvectorArray<I, W> {
64    fn index_mut(&mut self, index: Bitvector<I>) -> &mut Self::Output {
65        self.inner.mutable_index(index.into_mck().as_unsigned())
66    }
67}
68
69impl<const I: u32, const W: u32> IntoMck for BitvectorArray<I, W> {
70    type Type = mck::concr::Array<I, W>;
71
72    fn into_mck(self) -> Self::Type {
73        Self::Type::from_inner(self.inner.map(|v| v.into_mck()))
74    }
75}
76
77impl<const I: u32, const W: u32> Debug for BitvectorArray<I, W> {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        write!(f, "BitvectorArray<{},{}> ", I, W)?;
80        Debug::fmt(&self.inner, f)
81    }
82}