use std::hash::Hash;
use crate::netlist::direction::Direction;
use std::borrow::Borrow;
use std::collections::{HashMap, HashSet};
use std::fmt;
use itertools::Itertools;
pub trait CircuitRef {
type N: NetlistBase;
fn id(&self) -> <<Self as CircuitRef>::N as NetlistBase>::CircuitId;
fn name(&self) -> <<Self as CircuitRef>::N as NetlistBase>::NameType;
fn net_zero(&self) -> <<Self as CircuitRef>::N as NetlistBase>::NetId;
fn net_one(&self) -> <<Self as CircuitRef>::N as NetlistBase>::NetId;
}
pub trait CircuitInstRef {
type N: NetlistBase;
fn id(&self) -> <<Self as CircuitInstRef>::N as NetlistBase>::CircuitInstId;
fn name(&self) -> Option<<<Self as CircuitInstRef>::N as NetlistBase>::NameType>;
}
pub struct DefaultCircuitRef<'a, N: NetlistBase + ?Sized> {
netlist: &'a N,
id: N::CircuitId,
}
impl<'a, N: NetlistBase> CircuitRef for DefaultCircuitRef<'a, N> {
type N = N;
fn id(&self) -> N::CircuitId {
self.id.clone()
}
fn name(&self) -> N::NameType {
self.netlist.circuit_name(&self.id)
}
fn net_zero(&self) -> N::NetId {
self.netlist.net_zero(&self.id)
}
fn net_one(&self) -> N::NetId {
self.netlist.net_one(&self.id)
}
}
pub struct DefaultCircuitInstRef<'a, N: NetlistBase + ?Sized> {
netlist: &'a N,
id: N::CircuitInstId,
}
impl<'a, N: NetlistBase> CircuitInstRef for DefaultCircuitInstRef<'a, N> {
type N = N;
fn id(&self) -> N::CircuitInstId {
self.id.clone()
}
fn name(&self) -> Option<N::NameType> {
self.netlist.circuit_instance_name(&self.id)
}
}
pub trait NetlistBase {
type NameType: Eq + Hash + From<String> + Into<String> + Clone
+ Borrow<String> + Borrow<str>
+ PartialOrd + Ord
+ std::fmt::Display + std::fmt::Debug;
type PinId: Eq + Hash + Clone + std::fmt::Debug;
type PinInstId: Eq + Hash + Clone + std::fmt::Debug;
type TerminalId: Eq + Hash + Clone + std::fmt::Debug;
type CircuitId: Eq + Hash + Clone + std::fmt::Debug;
type CircuitInstId: Eq + Hash + Clone + std::fmt::Debug;
type NetId: Eq + Hash + Clone + std::fmt::Debug;
fn new() -> Self;
fn circuit_by_name<N: ?Sized + Eq + Hash>(&self, name: &N) -> Option<Self::CircuitId>
where Self::NameType: Borrow<N>;
fn circuit_instance_by_name<N: ?Sized + Eq + Hash>(&self, parent_circuit: &Self::CircuitId, name: &N) -> Option<Self::CircuitInstId>
where Self::NameType: Borrow<N>;
fn template_circuit(&self, circuit_instance: &Self::CircuitInstId) -> Self::CircuitId;
fn template_pin(&self, pin_instance: &Self::PinInstId) -> Self::PinId;
fn pin_direction(&self, pin: &Self::PinId) -> Direction;
fn pin_name(&self, pin: &Self::PinId) -> Self::NameType;
fn pin_by_name<N: ?Sized + Eq + Hash>(&self, parent_circuit: &Self::CircuitId, name: &N) -> Option<Self::PinId>
where Self::NameType: Borrow<N>;
fn parent_circuit(&self, circuit_instance: &Self::CircuitInstId) -> Self::CircuitId;
fn parent_circuit_of_pin(&self, pin: &Self::PinId) -> Self::CircuitId;
fn parent_of_pin_instance(&self, pin_inst: &Self::PinInstId) -> Self::CircuitInstId;
fn net_of_pin(&self, pin: &Self::PinId) -> Option<Self::NetId>;
fn net_of_pin_instance(&self, pin_instance: &Self::PinInstId) -> Option<Self::NetId>;
fn net_zero(&self, parent_circuit: &Self::CircuitId) -> Self::NetId;
fn net_one(&self, parent_circuit: &Self::CircuitId) -> Self::NetId;
fn net_by_name<N: ?Sized + Eq + Hash>(&self, parent_circuit: &Self::CircuitId, name: &N) -> Option<Self::NetId>
where Self::NameType: Borrow<N>;
fn net_name(&self, net: &Self::NetId) -> Option<Self::NameType>;
fn circuit_name(&self, circuit: &Self::CircuitId) -> Self::NameType;
fn circuit_instance_name(&self, circuit_inst: &Self::CircuitInstId) -> Option<Self::NameType>;
fn for_each_circuit<F>(&self, f: F) where F: FnMut(Self::CircuitId) -> ();
fn each_circuit_vec(&self) -> Vec<Self::CircuitId> {
let mut v = Vec::new();
self.for_each_circuit(|c| v.push(c.clone()));
v
}
fn each_circuit<'a>(&'a self) -> Box<dyn Iterator<Item=Self::CircuitId> + 'a> {
Box::new(self.each_circuit_vec().into_iter())
}
fn for_each_instance<F>(&self, circuit: &Self::CircuitId, f: F) where F: FnMut(Self::CircuitInstId) -> ();
fn each_instance_vec(&self, circuit: &Self::CircuitId) -> Vec<Self::CircuitInstId> {
let mut v = Vec::new();
self.for_each_instance(circuit, |c| v.push(c.clone()));
v
}
fn each_instance<'a>(&'a self, circuit: &Self::CircuitId) -> Box<dyn Iterator<Item=Self::CircuitInstId> + 'a> {
Box::new(self.each_instance_vec(circuit).into_iter())
}
fn for_each_circuit_dependency<F>(&self, circuit: &Self::CircuitId, f: F) where F: FnMut(Self::CircuitId) -> ();
fn each_circuit_dependency_vec(&self, circuit: &Self::CircuitId) -> Vec<Self::CircuitId> {
let mut v = Vec::new();
self.for_each_circuit_dependency(circuit, |c| v.push(c.clone()));
v
}
fn each_circuit_dependency<'a>(&'a self, circuit: &Self::CircuitId) -> Box<dyn Iterator<Item=Self::CircuitId> + 'a> {
Box::new(self.each_circuit_dependency_vec(circuit).into_iter())
}
fn for_each_dependent_circuit<F>(&self, circuit: &Self::CircuitId, f: F) where F: FnMut(Self::CircuitId) -> ();
fn each_dependent_circuit_vec(&self, circuit: &Self::CircuitId) -> Vec<Self::CircuitId> {
let mut v = Vec::new();
self.for_each_dependent_circuit(circuit, |c| v.push(c.clone()));
v
}
fn each_dependent_circuit<'a>(&'a self, circuit: &Self::CircuitId) -> Box<dyn Iterator<Item=Self::CircuitId> + 'a> {
Box::new(self.each_dependent_circuit_vec(circuit).into_iter())
}
fn for_each_reference<F>(&self, circuit: &Self::CircuitId, f: F) where F: FnMut(Self::CircuitInstId) -> ();
fn each_reference_vec(&self, circuit: &Self::CircuitId) -> Vec<Self::CircuitInstId> {
let mut v = Vec::new();
self.for_each_reference(circuit, |c| v.push(c.clone()));
v
}
fn each_reference<'a>(&'a self, circuit: &Self::CircuitId) -> Box<dyn Iterator<Item=Self::CircuitInstId> + 'a> {
Box::new(self.each_reference_vec(circuit).into_iter())
}
fn for_each_pin<F>(&self, circuit: &Self::CircuitId, f: F) where F: FnMut(Self::PinId) -> ();
fn each_pin_vec(&self, circuit: &Self::CircuitId) -> Vec<Self::PinId> {
let mut v = Vec::new();
self.for_each_pin(circuit, |c| v.push(c.clone()));
v
}
fn each_pin<'a>(&'a self, circuit: &Self::CircuitId) -> Box<dyn Iterator<Item=Self::PinId> + 'a> {
Box::new(self.each_pin_vec(circuit).into_iter())
}
fn for_each_pin_instance<F>(&self, circuit_inst: &Self::CircuitInstId, f: F) where F: FnMut(Self::PinInstId) -> ();
fn each_pin_instance_vec(&self, circuit_instance: &Self::CircuitInstId) -> Vec<Self::PinInstId> {
let mut v = Vec::new();
self.for_each_pin_instance(circuit_instance, |c| v.push(c.clone()));
v
}
fn each_pin_instance<'a>(&'a self, circuit_instance: &Self::CircuitInstId) -> Box<dyn Iterator<Item=Self::PinInstId> + 'a> {
Box::new(self.each_pin_instance_vec(circuit_instance).into_iter())
}
fn each_external_net<'a>(&'a self, circuit_instance: &Self::CircuitInstId) -> Box<dyn Iterator<Item=Self::NetId> + 'a> {
Box::new(self.each_pin_instance(circuit_instance)
.flat_map(move |pin_id| self.net_of_pin_instance(&pin_id)))
}
fn for_each_internal_net<F>(&self, circuit: &Self::CircuitId, f: F) where F: FnMut(Self::NetId) -> ();
fn each_internal_net_vec(&self, circuit: &Self::CircuitId) -> Vec<Self::NetId> {
let mut v = Vec::new();
self.for_each_internal_net(circuit, |c| v.push(c.clone()));
v
}
fn each_internal_net<'a>(&'a self, circuit: &Self::CircuitId) -> Box<dyn Iterator<Item=Self::NetId> + 'a> {
Box::new(self.each_internal_net_vec(circuit).into_iter())
}
fn num_net_pins(&self, net: &Self::NetId) -> usize {
let mut n = 0;
self.for_each_pin_of_net(net, |_| n += 1);
n
}
fn num_net_pin_instances(&self, net: &Self::NetId) -> usize {
let mut n = 0;
self.for_each_pin_instance_of_net(net, |_| n += 1);
n
}
fn num_net_terminals(&self, net: &Self::NetId) -> usize {
self.num_net_pins(net) + self.num_net_pin_instances(net)
}
fn num_child_instances(&self, circuit: &Self::CircuitId) -> usize;
fn num_circuits(&self) -> usize;
fn num_pins(&self, circuit: &Self::CircuitId) -> usize;
fn num_references(&self, circuit: &Self::CircuitId) -> usize {
self.each_reference(circuit).count()
}
fn for_each_pin_of_net<F>(&self, net: &Self::NetId, f: F) where F: FnMut(Self::PinId) -> ();
fn each_pin_of_net_vec(&self, net: &Self::NetId) -> Vec<Self::PinId> {
let mut v = Vec::new();
self.for_each_pin_of_net(net, |c| v.push(c.clone()));
v
}
fn each_pin_of_net<'a>(&'a self, net: &Self::NetId) -> Box<dyn Iterator<Item=Self::PinId> + 'a> {
Box::new(self.each_pin_of_net_vec(net).into_iter())
}
fn for_each_pin_instance_of_net<F>(&self, net: &Self::NetId, f: F) where F: FnMut(Self::PinInstId) -> ();
fn each_pin_instance_of_net_vec(&self, net: &Self::NetId) -> Vec<Self::PinInstId> {
let mut v = Vec::new();
self.for_each_pin_instance_of_net(net, |c| v.push(c.clone()));
v
}
fn each_pin_instance_of_net<'a>(&'a self, net: &Self::NetId) -> Box<dyn Iterator<Item=Self::PinInstId> + 'a> {
Box::new(self.each_pin_instance_of_net_vec(net).into_iter())
}
fn for_each_circuit_instance_of_net<F>(&self, net: &Self::NetId, mut f: F) where F: FnMut(Self::CircuitInstId) -> () {
let mut visited = HashSet::new();
self.for_each_pin_instance_of_net(net, |pin_inst| {
let inst = self.parent_of_pin_instance(&pin_inst);
if !visited.contains(&inst) {
f(inst);
} else {
visited.insert(inst);
}
})
}
fn each_circuit_instance_of_net_vec(&self, net: &Self::NetId) -> Vec<Self::CircuitInstId> {
let mut v = Vec::new();
self.for_each_circuit_instance_of_net(net, |c| v.push(c.clone()));
v
}
fn circuit(&self, id: Self::CircuitId) -> Box<dyn CircuitRef<N=Self> + '_>
where Self: Sized {
Box::new(DefaultCircuitRef {
netlist: self,
id,
})
}
fn circuit_inst(&self, id: Self::CircuitInstId) -> Box<dyn CircuitInstRef<N=Self> + '_>
where Self: Sized {
Box::new(DefaultCircuitInstRef {
netlist: self,
id,
})
}
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let circuits = self.each_circuit_vec();
for c in &circuits {
let circuit_name = self.circuit_name(c);
let circuit_instances = self.each_instance_vec(c);
let pin_names = self.each_pin(c)
.map(|pin| {
let pin_name = self.pin_name(&pin);
let net = self.net_of_pin(&pin);
let net_name: Option<String> = net.
map(|n| self.net_name(&n)
.map(|n| n.into())
.unwrap_or("<unnamed>".into()));
format!("{}={:?}", pin_name, net_name)
}).join(" ");
writeln!(f, ".subckt {} {}", circuit_name, pin_names)?;
for inst in &circuit_instances {
let sub_name: String = self.circuit_instance_name(inst)
.map(|n| n.into())
.unwrap_or("<unnamed>".into());
let sub_template = self.template_circuit(inst);
let template_name = self.circuit_name(&sub_template);
let nets = self.each_pin_instance(inst)
.map(|p| {
let pin = self.template_pin(&p);
let pin_name = self.pin_name(&pin);
let net = self.net_of_pin_instance(&p);
let net_name: Option<String> = net.
map(|n| self.net_name(&n)
.map(|n| n.into())
.unwrap_or("<unnamed>".into()));
format!("{}={:?}", pin_name, net_name)
}).join(" ");
writeln!(f, " X{} {} {}", sub_name, template_name, nets)?;
}
writeln!(f, ".ends {}\n", circuit_name)?;
}
fmt::Result::Ok(())
}
}
pub trait NetlistEdit: NetlistBase {
fn create_circuit(&mut self, name: Self::NameType, pins: Vec<(Self::NameType, Direction)>) -> Self::CircuitId;
fn remove_circuit(&mut self, circuit_id: &Self::CircuitId);
fn create_circuit_instance(&mut self,
parent_circuit: &Self::CircuitId,
template_circuit: &Self::CircuitId,
name: Option<Self::NameType>) -> Self::CircuitInstId;
fn remove_circuit_instance(&mut self, id: &Self::CircuitInstId);
fn create_net(&mut self, parent: &Self::CircuitId,
name: Option<Self::NameType>) -> Self::NetId;
fn rename_net(&mut self, parent_circuit: &Self::CircuitId,
net_id: &Self::NetId,
new_name: Option<Self::NameType>);
fn remove_net(&mut self, net: &Self::NetId);
fn connect_pin(&mut self, pin: &Self::PinId, net: Option<Self::NetId>) -> Option<Self::NetId>;
fn disconnect_pin(&mut self, pin: &Self::PinId) -> Option<Self::NetId> {
self.connect_pin(pin, None)
}
fn connect_pin_instance(&mut self, pin: &Self::PinInstId, net: Option<Self::NetId>) -> Option<Self::NetId>;
fn disconnect_pin_instance(&mut self, pin_instance: &Self::PinInstId) -> Option<Self::NetId> {
self.connect_pin_instance(pin_instance, None)
}
fn replace_net(&mut self, old_net: &Self::NetId, new_net: &Self::NetId) {
let terminals: Vec<_> = self.each_pin_of_net(&old_net).collect();
for pin in terminals {
self.connect_pin(&pin, Some(new_net.clone()));
}
let terminals: Vec<_> = self.each_pin_instance_of_net(&old_net).collect();
for pin in terminals {
self.connect_pin_instance(&pin, Some(new_net.clone()));
}
self.remove_net(&old_net);
}
fn flatten_circuit_instance(&mut self, circuit_instance: &Self::CircuitInstId) {
let template = self.template_circuit(circuit_instance);
let parent_circuit = self.parent_circuit(circuit_instance);
assert!(template != parent_circuit);
let mut net_mapping: HashMap<Self::NetId, Self::NetId> = HashMap::new();
let mut get_new_net = |netlist: &mut Self, old_net: &Self::NetId| -> Self::NetId {
if let Some(net_net) = net_mapping.get(old_net) {
net_net.clone()
} else {
let net_name = netlist.net_name(old_net);
let net_name = if let Some(net_name) = net_name {
if let Some(_) = netlist.net_by_name(&parent_circuit, &net_name) {
None
} else {
Some(net_name)
}
} else {
None
};
let new_net = netlist.create_net(&parent_circuit, net_name);
net_mapping.insert(old_net.clone(), new_net.clone());
new_net
}
};
let all_instances = self.each_instance_vec(&template);
for sub in all_instances {
let sub_template = self.template_circuit(&sub);
let new_name = if let (Some(sub_instance_name), Some(inst_name)) =
(self.circuit_instance_name(&sub), self.circuit_instance_name(circuit_instance)) {
{
let mut new_name = format!("{}:{}", inst_name, sub_instance_name);
let mut i = 0;
while self.circuit_instance_by_name(&parent_circuit, &new_name).is_some() {
new_name = format!("{}:{}_{}", inst_name, sub_instance_name, i);
i += 1;
}
Some(new_name)
}
} else {
None
};
let new_inst = self.create_circuit_instance(&parent_circuit, &sub_template,
new_name.map(|n| n.into()));
let pin_mapping: Vec<_> = self.each_pin_instance(&sub)
.zip(self.each_pin_instance(&new_inst))
.collect();
for (old_pin, new_pin) in pin_mapping {
if let Some(old_net) = self.net_of_pin_instance(&old_pin) {
let new_net = get_new_net(self, &old_net);
self.connect_pin_instance(&new_pin, Some(new_net));
}
}
}
{
let net_replacement_mapping: HashMap<_, _> = self.each_pin_instance_vec(circuit_instance)
.into_iter()
.filter_map(|old_pin| {
let outer_old_net = self.net_of_pin_instance(&old_pin);
let inner_old_net = self.net_of_pin(&self.template_pin(&old_pin));
if let (Some(outer_net), Some(inner_old_net)) = (outer_old_net, inner_old_net) {
let inner_new_net = get_new_net(self, &inner_old_net);
Some((inner_new_net, outer_net))
} else {
None
}
})
.collect();
net_replacement_mapping.iter()
.for_each(|(inner_new_net, outer_net)|
self.replace_net(inner_new_net, outer_net)
);
}
self.remove_circuit_instance(circuit_instance);
}
fn flatten_circuit(&mut self, circuit: &Self::CircuitId) {
for r in self.each_reference_vec(circuit) {
self.flatten_circuit_instance(&r);
}
debug_assert_eq!(self.each_reference(circuit).count(), 0,
"Circuit should not have any references anymore.");
self.remove_circuit(circuit);
}
fn purge_nets_in_circuit(&mut self, circuit_id: &Self::CircuitId) -> usize {
let mut unused = Vec::new();
self.for_each_internal_net(circuit_id, |n| {
if self.num_net_terminals(&n) == 0 {
unused.push(n)
}
});
unused.iter()
.for_each(|n| self.remove_net(n));
return unused.len();
}
fn purge_nets(&mut self) -> usize {
let all_circuits = self.each_circuit_vec();
all_circuits.iter()
.map(|c| self.purge_nets_in_circuit(c))
.sum()
}
}