Skip to main content

lut/
lut.rs

1use bitvec::vec::BitVec;
2use safety_net::{Identifier, Instantiable, Logic, Net, Netlist, Parameter, format_id};
3
4#[derive(Debug, Clone)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6struct Lut {
7    lookup_table: BitVec,
8    id: Identifier,
9    inputs: Vec<Net>,
10    output: Net,
11}
12
13impl Lut {
14    fn new(k: usize, lookup_table: usize) -> Self {
15        let mut bv: BitVec<usize, _> = BitVec::from_element(lookup_table);
16        bv.truncate(1 << k);
17        Lut {
18            lookup_table: bv,
19            id: format_id!("LUT{k}"),
20            inputs: (0..k).map(|i| Net::new_logic(format_id!("I{i}"))).collect(),
21            output: Net::new_logic("O".into()),
22        }
23    }
24
25    fn invert(&mut self) {
26        self.lookup_table = !self.lookup_table.clone();
27    }
28}
29
30impl Instantiable for Lut {
31    fn get_name(&self) -> &Identifier {
32        &self.id
33    }
34
35    fn get_input_ports(&self) -> &[Net] {
36        &self.inputs
37    }
38
39    fn get_output_ports(&self) -> &[Net] {
40        std::slice::from_ref(&self.output)
41    }
42
43    fn has_parameter(&self, id: &Identifier) -> bool {
44        *id == Identifier::new("INIT".to_string())
45    }
46
47    fn get_parameter(&self, id: &Identifier) -> Option<Parameter> {
48        if self.has_parameter(id) {
49            Some(Parameter::BitVec(self.lookup_table.clone()))
50        } else {
51            None
52        }
53    }
54
55    fn set_parameter(&mut self, id: &Identifier, val: Parameter) -> Option<Parameter> {
56        if !self.has_parameter(id) {
57            panic!("Parameter {} not applicable", id);
58        }
59
60        let old = Some(Parameter::BitVec(self.lookup_table.clone()));
61
62        if let Parameter::BitVec(bv) = val {
63            self.lookup_table = bv;
64        } else {
65            panic!("Invalid parameter type for INIT");
66        }
67
68        old
69    }
70
71    fn clear_parameter(&mut self, id: &Identifier) -> Option<Parameter> {
72        if self.has_parameter(id) {
73            panic!("LUT truth table cannot be cleared");
74        }
75
76        None
77    }
78
79    fn parameters(&self) -> Vec<(Identifier, Parameter)> {
80        vec![(
81            Identifier::new("INIT".to_string()),
82            Parameter::BitVec(self.lookup_table.clone()),
83        )]
84    }
85
86    fn from_constant(val: Logic) -> Option<Self> {
87        match val {
88            Logic::True => Some(Self {
89                lookup_table: BitVec::from_element(1),
90                id: "VDD".into(),
91                inputs: vec![],
92                output: "Y".into(),
93            }),
94            Logic::False => Some(Self {
95                lookup_table: BitVec::from_element(0),
96                id: "GND".into(),
97                inputs: vec![],
98                output: "Y".into(),
99            }),
100            _ => None,
101        }
102    }
103
104    fn get_constant(&self) -> Option<Logic> {
105        match self.id.to_string().as_str() {
106            "VDD" => Some(Logic::True),
107            "GND" => Some(Logic::False),
108            _ => None,
109        }
110    }
111
112    fn is_seq(&self) -> bool {
113        false
114    }
115}
116
117fn main() {
118    let netlist = Netlist::new("example".into());
119
120    // Add the the two inputs
121    let a = netlist.insert_input("a".into());
122    let b = netlist.insert_input("b".into());
123
124    // Instantiate an NAND gate
125    let instance = netlist
126        .insert_gate(Lut::new(2, 7), "inst_0".into(), &[a, b])
127        .unwrap();
128
129    // Let's make it an AND gate by inverting the lookup table
130    instance.get_instance_type_mut().unwrap().invert();
131
132    // Make this LUT an output
133    instance.expose_with_name("y".into());
134
135    // Print the netlist
136    println!("{netlist}");
137
138    #[cfg(feature = "serde")]
139    {
140        let res = netlist.try_unlink().unwrap().serialize(std::io::stdout());
141        if res.is_err() {
142            eprintln!("Failed to serialize netlist: {:?}", res.err());
143        }
144    }
145}