From 1382c580b65c251b06e71b71c6967b67727d18ea Mon Sep 17 00:00:00 2001 From: Per Lindgren <per.lindgren@ltu.se> Date: Thu, 10 Jun 2021 11:25:03 +0200 Subject: [PATCH] refactor --- src/bitarr.rs | 124 +++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 + src/main.rs | 124 +++++++++++++++++++++---------------- src/signal.rs | 165 +++----------------------------------------------- 4 files changed, 205 insertions(+), 211 deletions(-) create mode 100644 src/bitarr.rs diff --git a/src/bitarr.rs b/src/bitarr.rs new file mode 100644 index 0000000..4a1b962 --- /dev/null +++ b/src/bitarr.rs @@ -0,0 +1,124 @@ +use std::cell::Cell; +use std::convert::TryFrom; +use std::convert::{From, Into}; +use std::fmt; +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]); + +// operations on BitArr +impl<const N: usize> BitArr<N> { + pub fn sign_zero_ext<const M: usize>(&self, b: bool) -> BitArr<M> { + let msb = if b { self.0[N - 1] } else { false }; + let mut res = [msb; M]; + res[0..N].copy_from_slice(&self.0); + + BitArr(res) + } + + pub fn sign_ext<const M: usize>(&self) -> BitArr<M> { + self.sign_zero_ext(true) + } + + pub fn zero_ext<const M: usize>(&self) -> BitArr<M> { + self.sign_zero_ext(false) + } +} + +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) + } +} + +#[test] +mod test { + #[test] + fn extensions() { + let a: BitArr<2> = 0b10u8.into(); + let ze: BitArr<4> = a.zero_ext(); + let se: BitArr<4> = a.sign_ext(); + assert!(ze == 0b0010u8.into()); + assert!(se == 0b1110u8.into()); + } +} diff --git a/src/lib.rs b/src/lib.rs index 6a79087..6278f9e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,7 @@ +mod bitarr; mod signal; + +pub use bitarr::*; pub use signal::*; // pub struct Component { diff --git a/src/main.rs b/src/main.rs index 5068a7f..7f4e78c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -70,8 +70,8 @@ use rsim::*; // two input mux struct Mux<'a, const N: usize> { ins: (Signal<'a, N>, Signal<'a, N>), - sel: &'a Signal<'a, 1>, - out: &'a Signal<'a, N>, + sel: Signal<'a, 1>, + out: Signal<'a, N>, } impl<'a, const N: usize> Eval for Mux<'a, N> { @@ -83,6 +83,64 @@ impl<'a, const N: usize> Eval for Mux<'a, N> { } } +// zero extend +struct ZeroExt<'a, const N: usize, const M: usize> { + ins: Signal<'a, N>, + out: Signal<'a, M>, +} + +impl<'a, const N: usize, const M: usize> Eval for ZeroExt<'a, N, M> { + fn eval(&self) -> () { + let mut res = BitArr([false; M]); + res[0..N].clone_from_slice(&*self.ins.r()); + + self.out.w(res); + } +} + + + +#[test] +fn test_zero_ext() { + let mut ins: BitArr<2> = 0b10u8.into(); + println!("ins {:b}", ins); + let mut out: BitArr<4> = 0.into(); + let ze = ZeroExt { + ins: Signal::new(&mut ins), + out: Signal::new(&mut out), + }; + ze.eval(); + println!("ze.out {:b}", ze.out); +} + +// sign extend +struct SignExt<'a, const N: usize, const M: usize> { + ins: Signal<'a, N>, + out: Signal<'a, M>, +} + +impl<'a, const N: usize, const M: usize> Eval for SignExt<'a, N, M> { + fn eval(&self) -> () { + let mut res = BitArr([self.ins.r()[N - 1]; M]); + res[0..N].clone_from_slice(&*self.ins.r()); + + self.out.w(res); + } +} + +#[test] +fn test_sign_ext() { + let mut ins: BitArr<2> = 0b10u8.into(); + println!("ins {:b}", ins); + let mut out: BitArr<4> = 0.into(); + let se = SignExt { + ins: Signal::new(&mut ins), + out: Signal::new(&mut out), + }; + se.eval(); + println!("ze.out {:b}", se.out); +} + fn main() { let mut in1: BitArr<2> = 0b10u8.into(); // [false, true]; println!("{:?}", in1); @@ -97,56 +155,34 @@ fn main() { let mut sel = [false]; let sel = Signal::new(&mut sel); + let mut out = [false, false]; + let out = Signal::new(&mut out); - let out = &Signal::new(&mut out); - let out0: Signal<1> = out.view(0, 1); - let out1: Signal<1> = out.view(1, 2); + // let out0: Signal<1> = out.view(0, 1); + // let out1: Signal<1> = out.view(1, 2); let m = Mux { ins: (Signal::new(&mut in1), Signal::new(&mut in2)), - sel: &sel, + sel: sel, out, }; println!("m.out {:b}", m.out); m.eval(); - sel.w(BitArr([false])); + m.sel.w(BitArr([false])); m.eval(); println!("m.out {:b}", m.out); - sel[0].set(false); - sel.w(BitArr([false])); - // sel.store_slice(&[false]); + m.sel[0].set(false); + m.sel.w(BitArr([false])); + m.eval(); println!("m.out {:?}", m.out); - println!("out0 {:b}", &out0); - println!("out1 {:b}", &out1); + // println!("out0 {:b}", out0); + // println!("out1 {:b}", out1); let p = &m.out[0..1]; let m: Signal<2> = m.out[0..2].into(); } -// #[derive(Debug)] -// struct Mux<'a, const I: usize, const S: usize, const N: usize> { -// inputs: [&'a Signal<N>; I], -// sel: &'a Signal<S>, -// output: Signal<N>, -// } - -// impl<'a, const I: usize, const S: usize, const N: usize> Eval for Mux<'a, I, S, N> { -// fn eval(&self) { -// let s: u8 = self.sel.clone().into(); -// println!("s {}", s); - -// let o = self.inputs[s as usize]; - -// self.output.store.set(o.store.get()) -// } -// } - -// impl<'a, const I: usize, const S: usize, const N: usize> fmt::Binary for Mux<'a, I, S, N> { -// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -// fmt::Binary::fmt(&self.output, f) -// } -// } // fn main() { // let s1: Signal<8> = 0b10101u8.into(); @@ -178,24 +214,6 @@ fn main() { // } -// #[derive(Debug)] -// struct AndIn<'a> { -// a: &'a Signal, -// b: &'a Signal, -// } - -// #[derive(Debug)] -// struct And<'a> { -// inputs: AndIn<'a>, -// output: Signal, -// } - -// impl<'a> Eval for And<'a> { -// fn eval(&mut self) { -// self.output = (self.inputs.a & self.inputs.b).clone() -// } -// } - // fn main() { // let a: Signal = 1u8.into(); // let b: Signal = 2u8.into(); diff --git a/src/signal.rs b/src/signal.rs index d739ef9..cbac7f5 100644 --- a/src/signal.rs +++ b/src/signal.rs @@ -5,92 +5,7 @@ use std::fmt; 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) - } -} - +use crate::bitarr::*; // representation of stateful signal #[derive(Debug, PartialEq, Clone)] @@ -124,11 +39,11 @@ impl<'a, const N: usize> Signal<'a, N> { } // 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]) - // } - // } + 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 @@ -166,7 +81,7 @@ 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> { +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(); for i in self.store.iter().rev() { @@ -187,72 +102,6 @@ impl<'a, const N: usize> fmt::Binary for &Signal<'a, 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), -// // } -// } -// } - -// impl<const N: usize> BitOr for &Signal<N> { -// type Output = Signal<N>; - -// // rhs is the "right-hand side" of the expression `a & b` -// fn bitor(self, rhs: Self) -> Self::Output { -// let mut bs: Signal<N> = Signal::new(); -// for i in 0..self.store.len() { -// bs.store[i] = self.store[i] | rhs.store[i] -// } -// bs -// } -// } - -// impl<const N: usize> From<Signal<N>> for u8 { -// fn from(s: Signal<N>) -> u8 { -// // check that it fits u8 -// assert!(N < 8); -// let mut u = 0; -// let a = s.store.get(); - -// for i in 0..N { -// u |= if a[i] { 1 << i } else { 0 } -// } -// u -// } -// } - -// impl From<u32> for Signal { -// fn from(u: u32) -> Self { -// let mut bs = Signal::new(); -// for i in 0..32 { -// bs.push(u & (1 << i) != 0) -// } -// bs -// } -// } - -// impl From<Signal> for u32 { -// fn from(b: Signal) -> u32 { -// let mut u = 0; -// for (n, b) in b.0.iter().enumerate() { -// u |= if *b { 1 << n } else { 0 } -// } -// u -// } -// } - // #[test] // fn test_partial_eq() { // let b: Signal = 12345u32.into(); -- GitLab