Skip to content
Snippets Groups Projects
Commit 1382c580 authored by Per Lindgren's avatar Per Lindgren
Browse files

refactor

parent d9f97a50
No related branches found
No related tags found
No related merge requests found
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());
}
}
mod bitarr;
mod signal; mod signal;
pub use bitarr::*;
pub use signal::*; pub use signal::*;
// pub struct Component { // pub struct Component {
......
...@@ -70,8 +70,8 @@ use rsim::*; ...@@ -70,8 +70,8 @@ use rsim::*;
// two input mux // two input mux
struct Mux<'a, const N: usize> { struct Mux<'a, const N: usize> {
ins: (Signal<'a, N>, Signal<'a, N>), ins: (Signal<'a, N>, Signal<'a, N>),
sel: &'a Signal<'a, 1>, sel: Signal<'a, 1>,
out: &'a Signal<'a, N>, out: Signal<'a, N>,
} }
impl<'a, const N: usize> Eval for Mux<'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> { ...@@ -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() { fn main() {
let mut in1: BitArr<2> = 0b10u8.into(); // [false, true]; let mut in1: BitArr<2> = 0b10u8.into(); // [false, true];
println!("{:?}", in1); println!("{:?}", in1);
...@@ -97,56 +155,34 @@ fn main() { ...@@ -97,56 +155,34 @@ fn main() {
let mut sel = [false]; let mut sel = [false];
let sel = Signal::new(&mut sel); let sel = Signal::new(&mut sel);
let mut out = [false, false]; 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 out0: Signal<1> = out.view(0, 1); // let out1: Signal<1> = out.view(1, 2);
let out1: Signal<1> = out.view(1, 2);
let m = Mux { let m = Mux {
ins: (Signal::new(&mut in1), Signal::new(&mut in2)), ins: (Signal::new(&mut in1), Signal::new(&mut in2)),
sel: &sel, sel: sel,
out, out,
}; };
println!("m.out {:b}", m.out); println!("m.out {:b}", m.out);
m.eval(); m.eval();
sel.w(BitArr([false])); m.sel.w(BitArr([false]));
m.eval(); m.eval();
println!("m.out {:b}", m.out); println!("m.out {:b}", m.out);
sel[0].set(false); m.sel[0].set(false);
sel.w(BitArr([false])); m.sel.w(BitArr([false]));
// sel.store_slice(&[false]);
m.eval(); m.eval();
println!("m.out {:?}", m.out); println!("m.out {:?}", m.out);
println!("out0 {:b}", &out0); // println!("out0 {:b}", out0);
println!("out1 {:b}", &out1); // println!("out1 {:b}", out1);
let p = &m.out[0..1]; let p = &m.out[0..1];
let m: Signal<2> = 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> {
// 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() { // fn main() {
// let s1: Signal<8> = 0b10101u8.into(); // let s1: Signal<8> = 0b10101u8.into();
...@@ -178,24 +214,6 @@ fn main() { ...@@ -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() { // fn main() {
// let a: Signal = 1u8.into(); // let a: Signal = 1u8.into();
// let b: Signal = 2u8.into(); // let b: Signal = 2u8.into();
......
...@@ -5,92 +5,7 @@ use std::fmt; ...@@ -5,92 +5,7 @@ use std::fmt;
use std::ops::{BitAnd, BitOr, Deref, DerefMut, Index, Range}; use std::ops::{BitAnd, BitOr, Deref, DerefMut, Index, Range};
use std::string::String; use std::string::String;
#[derive(Debug, PartialEq, Clone)] use crate::bitarr::*;
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 // representation of stateful signal
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
...@@ -124,11 +39,11 @@ impl<'a, const N: usize> Signal<'a, N> { ...@@ -124,11 +39,11 @@ impl<'a, const N: usize> Signal<'a, N> {
} }
// not sure if we should support this // not sure if we should support this
// pub fn store_slice(&self, a: &[bool]) { pub fn store_slice(&self, a: &[bool]) {
// for (i, v) in self.store.iter().enumerate() { for (i, v) in self.store.iter().enumerate() {
// v.set(a[i]) v.set(a[i])
// } }
// } }
// create a view of the signal // create a view of the signal
// for now this view provides both reading and writing // for now this view provides both reading and writing
...@@ -166,7 +81,7 @@ impl<'a, const N: usize> Deref for Signal<'a, N> { ...@@ -166,7 +81,7 @@ impl<'a, const N: usize> Deref for Signal<'a, N> {
// prints the value of a signal // prints the value of a signal
// perhaps we should enforce reading the signal into a bit array first // 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 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut s = String::new(); let mut s = String::new();
for i in self.store.iter().rev() { for i in self.store.iter().rev() {
...@@ -187,72 +102,6 @@ impl<'a, const N: usize> fmt::Binary for &Signal<'a, N> { ...@@ -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] // #[test]
// fn test_partial_eq() { // fn test_partial_eq() {
// let b: Signal = 12345u32.into(); // let b: Signal = 12345u32.into();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment