use bitvec::vec::BitVec;
use safety_net::{Identifier, Instantiable, Logic, Net, Netlist, Parameter, format_id};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
struct Lut {
lookup_table: BitVec,
id: Identifier,
inputs: Vec<Net>,
output: Net,
}
impl Lut {
fn new(k: usize, lookup_table: usize) -> Self {
let mut bv: BitVec<usize, _> = BitVec::from_element(lookup_table);
bv.truncate(1 << k);
Lut {
lookup_table: bv,
id: format_id!("LUT{k}"),
inputs: (0..k).map(|i| Net::new_logic(format_id!("I{i}"))).collect(),
output: Net::new_logic("O".into()),
}
}
fn invert(&mut self) {
self.lookup_table = !self.lookup_table.clone();
}
}
impl Instantiable for Lut {
fn get_name(&self) -> &Identifier {
&self.id
}
fn get_input_ports(&self) -> &[Net] {
&self.inputs
}
fn get_output_ports(&self) -> &[Net] {
std::slice::from_ref(&self.output)
}
fn has_parameter(&self, id: &Identifier) -> bool {
*id == Identifier::new("INIT".to_string())
}
fn get_parameter(&self, id: &Identifier) -> Option<Parameter> {
if self.has_parameter(id) {
Some(Parameter::BitVec(self.lookup_table.clone()))
} else {
None
}
}
fn set_parameter(&mut self, id: &Identifier, val: Parameter) -> Option<Parameter> {
if !self.has_parameter(id) {
panic!("Parameter {} not applicable", id);
}
let old = Some(Parameter::BitVec(self.lookup_table.clone()));
if let Parameter::BitVec(bv) = val {
self.lookup_table = bv;
} else {
panic!("Invalid parameter type for INIT");
}
old
}
fn clear_parameter(&mut self, id: &Identifier) -> Option<Parameter> {
if self.has_parameter(id) {
panic!("LUT truth table cannot be cleared");
}
None
}
fn parameters(&self) -> Vec<(Identifier, Parameter)> {
vec![(
Identifier::new("INIT".to_string()),
Parameter::BitVec(self.lookup_table.clone()),
)]
}
fn from_constant(val: Logic) -> Option<Self> {
match val {
Logic::True => Some(Self {
lookup_table: BitVec::from_element(1),
id: "VDD".into(),
inputs: vec![],
output: "Y".into(),
}),
Logic::False => Some(Self {
lookup_table: BitVec::from_element(0),
id: "GND".into(),
inputs: vec![],
output: "Y".into(),
}),
_ => None,
}
}
fn get_constant(&self) -> Option<Logic> {
match self.id.to_string().as_str() {
"VDD" => Some(Logic::True),
"GND" => Some(Logic::False),
_ => None,
}
}
fn is_seq(&self) -> bool {
false
}
}
fn main() {
let netlist = Netlist::new("example".into());
let a = netlist.insert_input("a".into());
let b = netlist.insert_input("b".into());
let instance = netlist
.insert_gate(Lut::new(2, 7), "inst_0".into(), &[a, b])
.unwrap();
instance.get_instance_type_mut().unwrap().invert();
instance.expose_with_name("y".into());
println!("{netlist}");
#[cfg(feature = "serde")]
{
let res = netlist.try_unlink().unwrap().serialize(std::io::stdout());
if res.is_err() {
eprintln!("Failed to serialize netlist: {:?}", res.err());
}
}
}