From d9f97a5027f1a14d97e6311d9141bd676abd1b5c Mon Sep 17 00:00:00 2001
From: Per Lindgren <per.lindgren@ltu.se>
Date: Tue, 8 Jun 2021 18:40:44 +0200
Subject: [PATCH] bit array introduced

---
 src/main.rs   |  40 +++++-----
 src/signal.rs | 197 +++++++++++++++++++++++++++++++++++---------------
 2 files changed, 159 insertions(+), 78 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index 26f4e3b..5068a7f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -65,7 +65,7 @@ use rsim::*;
 //     file.write_all(out.as_bytes()).unwrap();
 // }
 
-use std::cell::Cell;
+//use std::cell::Cell;
 
 // two input mux
 struct Mux<'a, const N: usize> {
@@ -76,28 +76,32 @@ struct Mux<'a, const N: usize> {
 
 impl<'a, const N: usize> Eval for Mux<'a, N> {
     fn eval(&self) -> () {
-        let sel = self.sel[0].get();
-        for (i, o) in self.out.iter().enumerate() {
-            o.set(match sel {
-                false => self.ins.0[i].get(),
-                true => self.ins.1[i].get(),
-            })
-        }
+        self.out.w(match self.sel.r()[0] {
+            false => self.ins.0.r(),
+            true => self.ins.1.r(),
+        })
     }
 }
 
 fn main() {
-    let mut in1 = [false, true];
-    let mut in2 = [true, false];
+    let mut in1: BitArr<2> = 0b10u8.into(); // [false, true];
+    println!("{:?}", in1);
+    println!("{:b}", in1);
+
+    let mut in2: BitArr<2> = BitArr([true, false]);
+    let c = &in1 & &in2;
+    println!("c {:b}", c);
+
+    let c = &in1 | &in2;
+    println!("c {:b}", c);
+
     let mut sel = [false];
     let sel = Signal::new(&mut sel);
     let mut out = [false, false];
 
     let out = &Signal::new(&mut out);
-    // let s = &(&*out)[0..3]; // .to_slice(0, 1);
     let out0: Signal<1> = out.view(0, 1);
     let out1: Signal<1> = out.view(1, 2);
-    // println!("s {:b}", &s);
 
     let m = Mux {
         ins: (Signal::new(&mut in1), Signal::new(&mut in2)),
@@ -107,18 +111,18 @@ fn main() {
 
     println!("m.out {:b}", m.out);
     m.eval();
-    sel[0].set(true);
+    sel.w(BitArr([false]));
     m.eval();
     println!("m.out {:b}", m.out);
-    // sel[0].set(false);
-    sel.store([false]);
-    sel.store_slice(&[false]);
+    sel[0].set(false);
+    sel.w(BitArr([false]));
+    // sel.store_slice(&[false]);
     m.eval();
-    println!("m.out {:b}", m.out);
+    println!("m.out {:?}", m.out);
     println!("out0 {:b}", &out0);
     println!("out1 {:b}", &out1);
     let p = &m.out[0..1];
-    let m: Signal<1> = m.out[0..2].into();
+    let m: Signal<2> = m.out[0..2].into();
 }
 // #[derive(Debug)]
 // struct Mux<'a, const I: usize, const S: usize, const N: usize> {
diff --git a/src/signal.rs b/src/signal.rs
index b277860..d739ef9 100644
--- a/src/signal.rs
+++ b/src/signal.rs
@@ -1,68 +1,161 @@
 use std::cell::Cell;
+use std::convert::TryFrom;
 use std::convert::{From, Into};
 use std::fmt;
-use std::ops::{BitAnd, BitOr, Deref, Index, Range};
+use std::ops::{BitAnd, BitOr, Deref, DerefMut, Index, Range};
 use std::string::String;
 
+#[derive(Debug, PartialEq, Clone)]
+pub struct BitArr<const N: usize>(pub [bool; N]);
+
+impl<const N: usize> DerefMut for BitArr<N> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+impl<const N: usize> Deref for BitArr<N> {
+    type Target = [bool; N];
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<const N: usize> fmt::Binary for BitArr<N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut s = String::new();
+        for i in self.0.iter().rev() {
+            s.push(if *i { '1' } else { '0' });
+        }
+        write!(f, "{}", s)
+    }
+}
+
+// Convert a u8 to BitArr<N>
+// panic: N is too small to fit all true bits of u8
+// if N is larger than 8, other bits set zero
+impl<const N: usize> From<u8> for BitArr<N> {
+    fn from(u: u8) -> Self {
+        let mut bs = [false; N];
+        for i in 0..8 {
+            let b = u & (1 << i);
+            if b != 0 {
+                bs[i] = true
+            }
+        }
+        BitArr(bs)
+    }
+}
+
+// Convert a BitArr<N> to u8
+// panic: if N > 8
+// if N <= 8 upper bits are set 0
+impl<const N: usize> From<BitArr<N>> for u8 {
+    fn from(bs: BitArr<N>) -> Self {
+        assert!(N <= 8);
+        let mut b = 0u8;
+        for i in 0..N {
+            if bs[i] {
+                b |= 1 << i
+            }
+        }
+        b
+    }
+}
+
+// operations on bit array
+impl<const N: usize> BitAnd for &BitArr<N> {
+    type Output = BitArr<N>;
+
+    // rhs is the "right-hand side" of the expression `a & b`
+    fn bitand(self, rhs: Self) -> Self::Output {
+        let mut bs = [false; N];
+        for i in 0..self.0.len() {
+            bs[i] = self.0[i] & rhs.0[i]
+        }
+        BitArr(bs)
+    }
+}
+
+impl<const N: usize> BitOr for &BitArr<N> {
+    type Output = BitArr<N>;
+
+    // rhs is the "right-hand side" of the expression `a & b`
+    fn bitor(self, rhs: Self) -> Self::Output {
+        let mut bs = [false; N];
+        for i in 0..self.0.len() {
+            bs[i] = self.0[i] | rhs.0[i]
+        }
+        BitArr(bs)
+    }
+}
+
+// representation of stateful signal
 #[derive(Debug, PartialEq, Clone)]
 
 pub struct Signal<'a, const N: usize> {
-    pub store: &'a [Cell<bool>],
+    store: &'a [Cell<bool>; N],
 }
 
 impl<'a, const N: usize> Signal<'a, N> {
+    // construct a signal from a mutable array
     pub fn new(arr: &'a mut [bool; N]) -> Self {
         let cell_slice: &'a Cell<[bool]> = Cell::from_mut(arr);
-        Self {
-            store: cell_slice.as_slice_of_cells(),
-        }
+        let slice_cell = cell_slice.as_slice_of_cells();
+        let a = <&[Cell<bool>; N]>::try_from(slice_cell).unwrap();
+        Self { store: a }
     }
 
-    pub fn load(&self) -> [bool; N] {
+    // read a signal value to a bit array
+    pub fn r(&self) -> BitArr<N> {
         let mut a = [false; N];
         for (i, v) in self.store.iter().enumerate() {
             a[i] = v.get()
         }
-        a
+        BitArr(a)
     }
 
-    pub fn store(&self, a: [bool; N]) {
+    // write a signal to a bit array
+    pub fn w(&self, a: BitArr<N>) {
         for (i, v) in self.store.iter().enumerate() {
             v.set(a[i])
         }
     }
 
-    pub fn store_slice(&self, a: &[bool]) {
-        for (i, v) in self.store.iter().enumerate() {
-            v.set(a[i])
-        }
-    }
+    // not sure if we should support this
+    // pub fn store_slice(&self, a: &[bool]) {
+    //     for (i, v) in self.store.iter().enumerate() {
+    //         v.set(a[i])
+    //     }
+    // }
 
+    // create a view of the signal
+    // for now this view provides both reading and writing
+    // not sure if this is what we want in the end
     pub fn view<const M: usize>(&self, f: usize, t: usize) -> Signal<M> {
-        assert!(M == t - f);
-        Signal {
-            store: &self.store[f..t],
-        }
+        let slice_cell = &self.store[f..t];
+        let a = <&[Cell<bool>; M]>::try_from(slice_cell).unwrap();
+        Signal { store: a }
     }
 }
 
-// impl<'a, const N: usize> From<u8> for Signal<'a, N> {
-//     fn from(u: u8) -> Self {
-//         let mut bs = [false; N];
-//         for i in 0..8 {
-//             bs[i] = 1 << i != 0
-//         }
-//         Signal::new(&mut bs)
-//     }
-// }
+// create a signal from a bit array
+impl<'a, const N: usize> From<&'a mut BitArr<N>> for Signal<'a, N> {
+    fn from(a: &'a mut BitArr<N>) -> Self {
+        Signal::new(&mut a.0)
+    }
+}
 
+// create a signal from a slice of the bit array storage
 impl<'a, const N: usize> From<&'a [Cell<bool>]> for Signal<'a, N> {
-    fn from(slice: &'a [Cell<bool>]) -> Self {
-        assert!(N == slice.len());
-        Signal { store: slice }
+    fn from(slice_cell: &'a [Cell<bool>]) -> Self {
+        let a = <&[Cell<bool>; N]>::try_from(slice_cell).unwrap();
+        Signal { store: a }
     }
 }
 
+// automatic dereferencing
 impl<'a, const N: usize> Deref for Signal<'a, N> {
     type Target = [Cell<bool>];
 
@@ -71,6 +164,8 @@ impl<'a, const N: usize> Deref for Signal<'a, N> {
     }
 }
 
+// prints the value of a signal
+// perhaps we should enforce reading the signal into a bit array first
 impl<'a, const N: usize> fmt::Binary for &Signal<'a, N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut s = String::new();
@@ -92,32 +187,22 @@ impl<'a, const N: usize> fmt::Binary for &Signal<'a, N> {
 //     }
 // }
 
-// impl<'a, const N: usize> Index<usize> for Signal<'a, N> {
-//     type Output = Signal<'a, 1>;
-
-//     #[inline]
-//     fn index(&self, index: usize) -> Self::Output {
-//         Signal {
-//             store: &[self.store[index].clone()],
-//         }
-//     }
-// }
-
-// operations on signal
-// impl<const N: usize> BitAnd for &Signal<N> {
-//     type Output = Signal<N>;
+// // operations on signal
+// impl<'a, const N: usize> BitAnd for Signal<'a, N> {
+//     type Output = Signal<'a, N>;
 
 //     // rhs is the "right-hand side" of the expression `a & b`
 //     fn bitand(self, rhs: Self) -> Self::Output {
-//         let mut bs = [false; N];
-//         let a = self.store.get();
-//         let b = rhs.store.get();
-//         for i in 0..self.store.get().len() {
-//             bs[i] = a[i] & b[i]
-//         }
-//         Signal {
-//             store: Cell::new(bs),
-//         }
+
+//         // let mut bs = [false; N];
+//         // let a = self.store.get();
+//         // let b = rhs.store.get();
+//         // for i in 0..self.store.get().len() {
+//         //     bs[i] = a[i] & b[i]
+//         // }
+//         // Signal {
+//         //     store: Cell::new(bs),
+//         // }
 //     }
 // }
 
@@ -134,14 +219,6 @@ impl<'a, const N: usize> fmt::Binary for &Signal<'a, N> {
 //     }
 // }
 
-// impl<const N: usize> From<[bool; N]> for Signal<N> {
-//     fn from(a: [bool; N]) -> Self {
-//         Signal {
-//             store: Cell::new(a),
-//         }
-//     }
-// }
-
 // impl<const N: usize> From<Signal<N>> for u8 {
 //     fn from(s: Signal<N>) -> u8 {
 //         // check that it fits u8
-- 
GitLab