use std::sync::Once;
use super::{Backend, BackendCircuit};
use crate::gate::Gate;
pub struct RsfqlibSpice;
static WARN_ONCE: Once = Once::new();
fn warn_timing_ignored() {
WARN_ONCE.call_once(|| {
eprintln!("Warning: timing information is currently not supported and will be ignored.");
});
}
macro_rules! gate_string {
($c:ident, $name:ident, [$($arg:expr),*],$gate:expr) => {
format!("X{} {} THmitll_{}", $name, vec![$($c.get_wire_name($arg), )*].join(" "), $gate)
};
}
impl Backend for RsfqlibSpice {
fn generate(&self, circuit: &BackendCircuit<'_>) -> String {
let c = circuit.view();
warn_timing_ignored();
let mut res = Vec::new();
res.push(format!(".subckt {} {}", c.name(), c.all_ports().join(" "),));
for gate in c.gates().iter() {
let s = match &gate.value {
Gate::Jtl { name, a, q } => gate_string!(c, name, [*a, *q], "JTL"),
Gate::Split { name, a, q1, q2 } => gate_string!(c, name, [*a, *q1, *q2], "SPLIT"),
Gate::Merge { name, a, b, q } => gate_string!(c, name, [*a, *b, *q], "MERGE"),
Gate::And {
name, a, b, clk, q, ..
} => gate_string!(c, name, [a.id, b.id, clk.id, *q], "AND2"),
Gate::Or {
name, a, b, clk, q, ..
} => gate_string!(c, name, [a.id, b.id, clk.id, *q], "OR2"),
Gate::Xor {
name, a, b, clk, q, ..
} => gate_string!(c, name, [a.id, b.id, clk.id, *q], "XOR"),
Gate::Xnor {
name, a, b, clk, q, ..
} => gate_string!(c, name, [a.id, b.id, clk.id, *q], "XNOR"),
Gate::Not {
name, a, clk, q, ..
} => gate_string!(c, name, [a.id, clk.id, *q], "NOT"),
Gate::Dff {
name, a, clk, q, ..
} => gate_string!(c, name, [a.id, clk.id, *q], "DFF"),
Gate::Ndro {
name, a, b, clk, q, ..
} => gate_string!(c, name, [a.id, b.id, clk.id, *q], "NDRO"),
Gate::Buff { name, a, q } => gate_string!(c, name, [*a, *q], "BUFF"),
Gate::ZeroAsync { name, q } => gate_string!(c, name, [*q], "ALWAYS0_ASYNC_NOA"),
Gate::Terminate { name, a } => {
format!("R{} {} 0 2", name, c.get_wire_name(*a))
}
Gate::Subcircuit {
name,
inputs,
outputs,
circuit,
..
} => {
let ports: Vec<&str> = inputs
.iter()
.chain(outputs.iter())
.map(|wid| c.get_wire_name(*wid))
.collect();
format!("X{} {} {}", name, ports.join(" "), circuit)
}
_ => panic!("Unsupported Gate"),
};
res.push(s);
}
res.push(".ends".to_string());
return res.join("\n");
}
}