diff --git a/src/main.rs b/src/main.rs index 26f4e3b5dcadef34ef53f3b051ffd61ed76f1df9..5068a7f5b5f73c507326a2c1d57abcf8c8290ee5 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 b277860a7d219d725d7b3a40e928bd9be6758d0e..d739ef99776684da6295bda40f9eeee497a8681a 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