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) -> impl IntoIterator<Item = &Net> {
36 &self.inputs
37 }
38
39 fn get_output_ports(&self) -> impl IntoIterator<Item = &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 return None;
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 parameters(&self) -> impl Iterator<Item = (Identifier, Parameter)> {
72 std::iter::once((
73 Identifier::new("INIT".to_string()),
74 Parameter::BitVec(self.lookup_table.clone()),
75 ))
76 }
77
78 fn from_constant(val: Logic) -> Option<Self> {
79 match val {
80 Logic::True => Some(Self {
81 lookup_table: BitVec::from_element(1),
82 id: "VDD".into(),
83 inputs: vec![],
84 output: "Y".into(),
85 }),
86 Logic::False => Some(Self {
87 lookup_table: BitVec::from_element(0),
88 id: "GND".into(),
89 inputs: vec![],
90 output: "Y".into(),
91 }),
92 _ => None,
93 }
94 }
95
96 fn get_constant(&self) -> Option<Logic> {
97 match self.id.to_string().as_str() {
98 "VDD" => Some(Logic::True),
99 "GND" => Some(Logic::False),
100 _ => None,
101 }
102 }
103
104 fn is_seq(&self) -> bool {
105 false
106 }
107}
108
109fn main() {
110 let netlist = Netlist::new("example".to_string());
111
112 let a = netlist.insert_input("a".into());
114 let b = netlist.insert_input("b".into());
115
116 let instance = netlist
118 .insert_gate(Lut::new(2, 7), "inst_0".into(), &[a, b])
119 .unwrap();
120
121 instance.get_instance_type_mut().unwrap().invert();
123
124 instance.expose_with_name("y".into());
126
127 println!("{netlist}");
129
130 #[cfg(feature = "serde")]
131 {
132 let res = netlist.reclaim().unwrap().serialize(std::io::stdout());
133 if res.is_err() {
134 eprintln!("Failed to serialize netlist: {:?}", res.err());
135 }
136 }
137}