diff --git a/src/lib.rs b/src/lib.rs
index f2f7888e17e2b09611670228ab3c4b7dc437dd24..6a790878f555e85d100d0d95daeaef095b7d6725 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,11 +1,11 @@
 mod signal;
 pub use signal::*;
 
-pub struct Component {
-    pub inputs: Vec<Signal>,
-    pub outputs: Vec<(Signal, Box<Component>)>,
-}
+// pub struct Component {
+//     pub inputs: Vec<Signal>,
+//     pub outputs: Vec<(Signal, Box<Component>)>,
+// }
 
 pub trait Eval {
-    fn eval(&mut self) -> ();
+    fn eval(&self) -> ();
 }
diff --git a/src/main.rs b/src/main.rs
index 070b5e2070edc8cb03759b1cccad405b66d3a0a9..2e52888420ee3de96d1530ebc564b74d0bd8b65a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,5 @@
+use core::fmt;
+
 use rsim::*;
 
 // fn main() {
@@ -63,35 +65,58 @@ use rsim::*;
 //     file.write_all(out.as_bytes()).unwrap();
 // }
 
-use std::cell::Cell;
-
 #[derive(Debug)]
-struct CSignal(Cell<Signal>);
+struct Mux<'a, const I: usize, const S: usize, const N: usize> {
+    inputs: [&'a Signal<N>; I],
+    sel: &'a Signal<S>,
+    output: Signal<N>,
+}
 
-#[derive(Debug)]
-struct MuxIn<'a> {
-    a: &'a CSignal,
-    b: &'a CSignal,
-    sel: &'a CSignal,
+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())
+    }
 }
 
-fn main() {}
+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)
+    }
+}
 
-// #[derive(Debug)]
-// struct Mux<'a> {
-//     inputs: MuxIn<'a>,
-//     output: CSignal,
-// }
+fn main() {
+    let s1: Signal<8> = 0b10101u8.into();
+    println!("s1 {:?}", s1);
+    println!("s1 {:b}", s1);
 
-// impl<'a> Eval for Mux<'a> {
-//     fn eval(&mut self) {
-//         self.output = match self.inputs.sel[0] {
-//             false => self.inputs.a.get(),
-//             true => self.inputs.b,
-//         }
-//         .clone()
-//     }
-// }
+    let s2: Signal<8> = 0b00110u8.into();
+    println!("s2 {:b}", s2);
+
+    let s3 = &s1 & &s2;
+
+    println!("s3 {:b}", s3);
+
+    let sel: Signal<1> = [true].into();
+
+    let m: Mux<2, 1, 8> = Mux {
+        inputs: [&s1, &s2],
+        sel: &sel,
+        output: 0u8.into(),
+    };
+
+    println!("m {:?}", m);
+
+    println!("m {:b}", m);
+
+    m.eval();
+    println!("m {:?}", m);
+    println!("m {:b}", m);
+}
 
 // #[derive(Debug)]
 // struct AndIn<'a> {
diff --git a/src/signal.rs b/src/signal.rs
index 1011433e4c5be08021087496e0fea01e131cbf0d..834b09cbd5c068d59d442022b83f013d30f92ead 100644
--- a/src/signal.rs
+++ b/src/signal.rs
@@ -1,125 +1,154 @@
+use std::cell::Cell;
 use std::convert::{From, Into};
 use std::fmt;
-use std::ops::{BitAnd, Index};
+use std::ops::{BitAnd, BitOr, Deref, Index};
 use std::string::String;
 
-#[derive(Debug, PartialEq, Copy, Clone)]
-pub struct Signal(Vec<bool>);
+#[derive(Debug, PartialEq, Clone)]
+pub struct Signal<const N: usize> {
+    // we should probably have set/get instead of exposing store
+    pub store: Cell<[bool; N]>,
+}
 
-impl Signal {
+impl<const N: usize> Signal<N> {
     pub fn new() -> Self {
-        Self { 0: Vec::new() }
-    }
-
-    pub fn new_zeroed(n: usize) -> Self {
-        let mut bs = Signal::new();
-        for i in 0..n {
-            bs.push(false)
+        Self {
+            store: Cell::new([false; N]),
         }
-        bs
-    }
-
-    pub fn push(&mut self, b: bool) {
-        self.0.push(b)
-    }
-
-    pub fn pop(&mut self) -> Option<bool> {
-        self.0.pop()
     }
 
-    pub fn set(&mut self, i: usize, b: bool) {
-        self.0[i] = b;
-    }
+    // pub fn set(&mut self, i: usize, b: bool) {
+    //     self.0[i] = b;
+    // }
 }
 
-impl fmt::Binary for Signal {
+impl<const N: usize> fmt::Binary for Signal<N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut s = String::new();
-        for i in self.0.iter().rev() {
+        for i in self.store.get().iter().rev() {
             s.push(if *i { '1' } else { '0' });
         }
         write!(f, "{}", s)
     }
 }
 
-impl Index<usize> for Signal {
-    type Output = bool;
+// impl<const N: usize> Deref for Signal<N> {
+//     type Target = [bool; N];
 
-    #[inline]
-    fn index(&self, index: usize) -> &Self::Output {
-        &self.0[index]
-    }
-}
+//     fn deref(&self) -> Self::Target {
+//         self.store.get()
+//     }
+// }
+
+// impl Index<usize> for Signal {
+//     type Output = bool;
+
+//     #[inline]
+//     fn index(&self, index: usize) -> &Self::Output {
+//         &self.0[index]
+//     }
+// }
 
 // operations on signal
-impl BitAnd for &Signal {
-    type Output = Signal;
+impl<const N: usize> BitAnd for &Signal<N> {
+    type Output = Signal<N>;
 
     // rhs is the "right-hand side" of the expression `a & b`
     fn bitand(self, rhs: Self) -> Self::Output {
-        let mut bs = Signal::new();
-        for (a, b) in self.0.iter().zip(&rhs.0) {
-            bs.push(a & b);
+        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),
         }
-        bs
     }
 }
 
-impl From<u8> for Signal {
+// 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<u8> for Signal<N> {
     fn from(u: u8) -> Self {
-        let mut bs = Signal::new();
+        let mut bs = [false; N];
         for i in 0..8 {
-            bs.push(u & (1 << i) != 0)
+            bs[i] = u & (1 << i) != 0
         }
-        bs
-    }
-}
-
-impl From<Signal> for u8 {
-    fn from(b: Signal) -> u8 {
-        let mut u = 0;
-        for (n, b) in b.0.iter().enumerate() {
-            u |= if *b { 1 << n } else { 0 }
+        Signal {
+            store: Cell::new(bs),
         }
-        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)
+impl<const N: usize> From<[bool; N]> for Signal<N> {
+    fn from(a: [bool; N]) -> Self {
+        Signal {
+            store: Cell::new(a),
         }
-        bs
     }
 }
 
-impl From<Signal> for u32 {
-    fn from(b: Signal) -> u32 {
+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;
-        for (n, b) in b.0.iter().enumerate() {
-            u |= if *b { 1 << n } else { 0 }
+        let a = s.store.get();
+
+        for i in 0..N {
+            u |= if a[i] { 1 << i } else { 0 }
         }
         u
     }
 }
 
-#[test]
-fn test_partial_eq() {
-    let b: Signal = 12345u32.into();
-    let c: Signal = 1245u32.into();
-    assert!(b != c);
-    assert!(b == b);
-}
-
-#[test]
-fn test_and() {
-    let a = 0x15u8;
-    let b = 0x51u8;
-
-    let a_bs: Signal = a.into();
-    let b_bs: Signal = b.into();
-    let c_bs = &a_bs & &b_bs;
-    assert!(a & b == c_bs.into());
-}
+// 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();
+//     let c: Signal = 1245u32.into();
+//     assert!(b != c);
+//     assert!(b == b);
+// }
+
+// #[test]
+// fn test_and() {
+//     let a = 0x15u8;
+//     let b = 0x51u8;
+
+//     let a_bs: Signal = a.into();
+//     let b_bs: Signal = b.into();
+//     let c_bs = &a_bs & &b_bs;
+//     assert!(a & b == c_bs.into());
+// }