#![allow(unused_variables)]
use super::prelude::*;
use crate::index::{Index, IndexGenerator};
use std::rc::Rc;
use std::collections::HashMap;
use std::hash::Hash;
use std::borrow::Borrow;
use std::fmt;
use itertools::Itertools;
use std::ops::Deref;
use log::debug;
use crate::netlist::traits::{NetlistBase, NetlistEdit};
pub type CircuitInstIndex = Index<CircuitInstance>;
pub(crate) type CircuitInstIndexGenerator = IndexGenerator<CircuitInstance>;
pub type NetIndex = Index<Net>;
pub(crate) type NetIndexGenerator = IndexGenerator<Net>;
pub type CircuitIndex = Index<Circuit>;
pub(crate) type CircuitIndexGenerator = IndexGenerator<Circuit>;
pub struct RcNetlist {
circuits: HashMap<CircuitIndex, Rc<Circuit>>,
circuits_by_name: HashMap<String, CircuitIndex>,
circuit_index_generator: CircuitIndexGenerator,
}
impl fmt::Debug for RcNetlist {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut circuits = self.each_circuit().collect_vec();
circuits.sort_by_key(|c| c.id());
f.debug_struct("Netlist")
.field("circuits", &circuits)
.finish()
}
}
impl fmt::Display for RcNetlist {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut circuits = self.each_circuit().collect_vec();
circuits.sort_by_key(|c| c.id());
for c in circuits {
fmt::Display::fmt(Rc::deref(c), f)?;
}
fmt::Result::Ok(())
}
}
impl RcNetlist {
pub fn new() -> Self {
RcNetlist {
circuits: Default::default(),
circuits_by_name: Default::default(),
circuit_index_generator: CircuitIndexGenerator::new(1), }
}
pub fn create_circuit<S: Into<String>>(&mut self, name: S, pins: Vec<Pin>) -> Rc<Circuit> {
let name = name.into();
if self.circuits_by_name.contains_key(&name) {
panic!(format!("Circuit '{}' already exists!", &name));
}
let circuit_id = self.circuit_index_generator.next();
let circuit = Circuit::new(circuit_id, name, pins);
self.circuits_by_name.insert(circuit.name.to_owned(), circuit_id);
let circuit_rc = Rc::new(circuit);
circuit_rc.self_reference.replace(Rc::downgrade(&circuit_rc));
circuit_rc.each_pin()
.for_each(|p| { p.parent_circuit.replace(Rc::downgrade(&circuit_rc)); });
self.circuits.insert(circuit_id, circuit_rc.clone());
circuit_rc
}
pub fn circuit_by_id(&self, id: &CircuitIndex) -> Option<Rc<Circuit>> {
self.circuits.get(id).cloned()
}
pub fn circuit_by_name<S: ?Sized>(&self, name: &S) -> Option<Rc<Circuit>>
where String: Borrow<S>,
S: Hash + Eq {
self.circuits_by_name.get(name)
.and_then(|i| self.circuit_by_id(i))
}
pub fn each_circuit(&self) -> impl Iterator<Item=&Rc<Circuit>> + ExactSizeIterator {
self.circuits.values()
}
pub fn each_circuit_bottom_up(&self) -> () {
unimplemented!()
}
pub fn each_circuit_top_down(&self) -> () {
unimplemented!()
}
pub fn flatten_circuit(&mut self, circuit: &Rc<Circuit>) {
debug!("Flatten circuit {}.", circuit.name());
let references: Vec<_> = circuit.references().iter().cloned().collect();
for r in references {
let parent = r.parent_circuit().upgrade().unwrap();
parent.flatten_circuit_instance(&r)
}
debug_assert!(!circuit.has_references(), "Circuit should not have any references anymore.");
self.remove_circuit(circuit);
}
pub fn purge_nets(&mut self) -> usize {
self.each_circuit()
.map(|c| c.purge_nets())
.sum()
}
pub fn remove_circuit(&mut self, circuit: &Rc<Circuit>) -> () {
let references = circuit.each_reference().collect_vec();
for inst in references {
circuit.remove_circuit_instance(&inst)
}
debug_assert_eq!(circuit.num_references(), 0);
self.circuits_by_name.remove(&circuit.name).unwrap();
self.circuits.remove(&circuit.id());
}
pub fn top_circuit_count(&self) -> usize {
self.each_circuit()
.filter(|c| c.num_references() == 0)
.count()
}
}
impl Clone for RcNetlist {
fn clone(&self) -> Self {
let mut netlist = Self::new();
let circuit_map = {
let mut circuit_map = HashMap::new();
for old_circuit in self.each_circuit() {
let pins = old_circuit.each_pin()
.map(|p| Pin::new(p.name(), p.direction()))
.collect();
let new_circuit = netlist.create_circuit(old_circuit.name(), pins);
circuit_map.insert(old_circuit.clone(), new_circuit);
}
circuit_map
};
for old_circuit in self.each_circuit() {
let new_circuit = circuit_map[old_circuit].clone();
let net_map = {
let mut net_map = HashMap::new();
for old_net in old_circuit.each_net() {
let new_net = new_circuit.create_net(old_net.name());
net_map.insert(old_net, new_net);
}
net_map
};
for old_pin in old_circuit.each_pin() {
let new_net = old_pin.internal_net()
.map(|n| net_map[&n].clone());
new_circuit.connect_pin_by_id(old_pin.id, new_net);
}
for old_inst in old_circuit.each_instance() {
let new_inst = new_circuit.create_circuit_instance(
&circuit_map[&old_inst.circuit_ref().upgrade().unwrap()],
old_inst.name(),
);
for (old_pin_inst, new_pin_inst) in old_inst.each_pin_instance()
.zip(new_inst.each_pin_instance()) {
let new_net = old_pin_inst.net()
.map(|n| net_map[&n].clone());
new_pin_inst.connect_net(new_net);
}
}
}
netlist
}
}
#[test]
fn test_create_pin() {
let _ = Pin::new("A", Direction::None);
let _ = Pin::new("A".to_string(), Direction::None);
let _ = Pin::new(&"A".to_string(), Direction::None);
}
#[test]
fn test_netlist_create_circuit() {
let mut netlist = RcNetlist::new();
let pins = vec![Pin::new("A", Direction::Input)];
let top = netlist.create_circuit("TOP", pins);
assert_eq!(top.each_pin().len(), 1);
assert_eq!(netlist.top_circuit_count(), 1);
}
#[test]
fn test_netlist_remove_circuit() {
let mut netlist = RcNetlist::new();
let pins = vec![Pin::new("A", Direction::Input)];
{
let top = netlist.create_circuit("TOP", pins);
netlist.remove_circuit(&top);
assert_eq!(netlist.top_circuit_count(), 0);
}
}
#[test]
fn test_netlist_create_net() {
let mut netlist = RcNetlist::new();
let pins = vec![Pin::new("A", Direction::Input)];
let top = netlist.create_circuit("TOP", pins);
let net_x = top.create_net(Some("x"));
assert_eq!(top.net_count(), 1, "net_count() is wrong.");
assert!(Rc::ptr_eq(&net_x, &top.net_by_name("x").unwrap()),
"Failed to find net by name.");
}
#[test]
fn test_netlist_connect_pin() {
let mut netlist = RcNetlist::new();
let pins = vec![Pin::new("TOP_A", Direction::Input)];
let top = netlist.create_circuit("TOP", pins);
let pins = vec![Pin::new("SUB_A", Direction::Input)];
let sub = netlist.create_circuit("SUB", pins);
let net1 = top.create_net(Some("net1"));
let inst_sub = top.create_circuit_instance(&sub, Some("INST_SUB1"));
inst_sub.connect_pin_by_id(0, Some(net1.clone()));
assert_eq!(net1.num_terminals(), 1);
assert_eq!(inst_sub.net_for_pin(0), Some(net1.clone()));
top.connect_pin_by_id(0, Some(net1.clone()));
assert_eq!(net1.num_terminals(), 2);
}
#[test]
fn test_netlist_circuit_remove_net() {
let mut netlist = RcNetlist::new();
let pins = vec![Pin::new("TOP_A", Direction::Input)];
let top = netlist.create_circuit("TOP", pins);
let pins = vec![Pin::new("SUB_A", Direction::Input)];
let sub = netlist.create_circuit("SUB", pins);
let net1 = top.create_net(Some("net1"));
let inst_sub = top.create_circuit_instance(&sub, Some("INST_SUB1"));
assert_eq!(sub.num_references(), 1);
inst_sub.connect_pin_by_id(0, Some(net1.clone()));
assert_eq!(net1.num_terminals(), 1);
assert_eq!(inst_sub.net_for_pin(0), Some(net1.clone()));
top.connect_pin_by_id(0, Some(net1.clone()));
assert_eq!(net1.num_terminals(), 2);
top.remove_net(&net1);
assert_eq!(net1.num_terminals(), 0);
assert_eq!(top.net_for_pin(0), None);
assert_eq!(inst_sub.net_for_pin(0), None);
}
#[test]
fn test_netlist_clone() {
let netlist = {
let mut netlist = RcNetlist::new();
let pins = vec![Pin::new("TOP_A", Direction::Input)];
let top = netlist.create_circuit("TOP", pins);
let pins = vec![Pin::new("SUB_A", Direction::Input)];
let sub = netlist.create_circuit("SUB", pins);
let net1 = top.create_net(Some("net1"));
let inst_sub = top.create_circuit_instance(&sub, Some("INST_SUB1"));
inst_sub.connect_pin_by_id(0, Some(net1.clone()));
top.connect_pin_by_id(0, Some(net1.clone()));
netlist
};
let netlist_clone = netlist.clone();
assert_eq!(netlist_clone.top_circuit_count(), 1);
let top = netlist_clone.circuit_by_name("TOP").unwrap();
let _sub = netlist_clone.circuit_by_name("SUB").unwrap();
assert_eq!(top.net_count(), 1);
assert_eq!(top.num_instances(), 1);
let net1 = top.net_by_name("net1").unwrap();
assert_eq!(net1.num_terminals(), 2);
let inst_sub = top.circuit_instance_by_name("INST_SUB1").unwrap();
assert_eq!(inst_sub.net_for_pin(0), Some(net1.clone()));
}
impl NetlistBase for RcNetlist {
type NameType = String;
type PinId = Rc<Pin>;
type PinInstId = Rc<PinInstance>;
type TerminalId = ();
type CircuitId = Rc<Circuit>;
type CircuitInstId = Rc<CircuitInstance>;
type NetId = Rc<Net>;
fn new() -> Self {
RcNetlist::new()
}
fn circuit_by_name<N: ?Sized>(&self, name: &N) -> Option<Rc<Circuit>>
where Self::NameType: Borrow<N>,
N: Hash + Eq {
RcNetlist::circuit_by_name(self, name)
}
fn circuit_instance_by_name<N: ?Sized + Eq + Hash>(&self, parent_circuit: &Self::CircuitId, name: &N)
-> Option<Self::CircuitInstId> where Self::NameType: Borrow<N> {
parent_circuit.circuit_instance_by_name(name)
}
fn template_circuit(&self, circuit_instance: &Self::CircuitInstId) -> Self::CircuitId {
circuit_instance.circuit_ref().upgrade().unwrap()
}
fn template_pin(&self, pin_instance: &Self::PinInstId) -> Self::PinId {
pin_instance.pin().clone()
}
fn pin_direction(&self, pin: &Self::PinId) -> Direction {
pin.direction()
}
fn pin_name(&self, pin: &Self::PinId) -> Self::NameType {
pin.name().to_string()
}
fn pin_by_name<N: ?Sized + Eq + Hash>(&self, parent_circuit: &Self::CircuitId, name: &N) -> Option<Self::PinId>
where Self::NameType: Borrow<N> {
parent_circuit.pin_by_name(name)
}
fn parent_circuit(&self, circuit_instance: &Self::CircuitInstId) -> Self::CircuitId {
circuit_instance.parent_circuit().upgrade().unwrap()
}
fn parent_circuit_of_pin(&self, pin: &Self::PinId) -> Self::CircuitId {
pin.parent_circuit().upgrade().unwrap()
}
fn parent_of_pin_instance(&self, pin_inst: &Self::PinInstId) -> Self::CircuitInstId {
pin_inst.circuit_instance().upgrade().unwrap()
}
fn net_of_pin(&self, pin: &Self::PinId) -> Option<Self::NetId> {
pin.internal_net()
}
fn net_of_pin_instance(&self, pin: &Self::PinInstId) -> Option<Self::NetId> {
pin.net()
}
fn net_zero(&self, parent_circuit: &Self::CircuitId) -> Self::NetId {
parent_circuit.net_zero()
}
fn net_one(&self, parent_circuit: &Self::CircuitId) -> Self::NetId {
parent_circuit.net_one()
}
fn net_by_name<N: ?Sized + Eq + Hash>(&self, parent: &Self::CircuitId, name: &N) -> Option<Self::NetId>
where Self::NameType: Borrow<N> {
parent.net_by_name(name)
}
fn net_name(&self, net: &Self::NetId) -> Option<Self::NameType> {
net.name()
}
fn circuit_name(&self, circuit: &Self::CircuitId) -> Self::NameType {
circuit.name().clone()
}
fn circuit_instance_name(&self, circuit_inst: &Self::CircuitInstId) -> Option<Self::NameType> {
circuit_inst.name().cloned()
}
fn for_each_circuit<F>(&self, f: F) where F: FnMut(Self::CircuitId) -> () {
RcNetlist::each_circuit(self).cloned().for_each(f)
}
fn each_circuit(&self) -> Box<dyn Iterator<Item=Self::CircuitId> + '_> {
Box::new(RcNetlist::each_circuit(self).cloned())
}
fn for_each_instance<F>(&self, circuit: &Self::CircuitId, f: F) where F: FnMut(Self::CircuitInstId) -> () {
circuit.each_instance().for_each(f)
}
fn for_each_circuit_dependency<F>(&self, circuit: &Self::CircuitId, f: F) where F: FnMut(Self::CircuitId) -> () {
circuit.each_circuit_dependency().for_each(f)
}
fn for_each_dependent_circuit<F>(&self, circuit: &Self::CircuitId, f: F) where F: FnMut(Self::CircuitId) -> () {
circuit.each_dependent_circuit().for_each(f)
}
fn for_each_reference<F>(&self, circuit: &Self::CircuitId, f: F) where F: FnMut(Self::CircuitInstId) -> () {
circuit.each_reference().for_each(f);
}
fn for_each_pin<F>(&self, circuit: &Self::CircuitId, f: F) where F: FnMut(Self::PinId) -> () {
circuit.each_pin().cloned().for_each(f)
}
fn each_pin_vec(&self, circuit: &Self::CircuitId) -> Vec<Self::PinId> {
circuit.each_pin_vec()
}
fn for_each_pin_instance<F>(&self, circuit_inst: &Self::CircuitInstId, f: F) where F: FnMut(Self::PinInstId) -> () {
circuit_inst.each_pin_instance().cloned().for_each(f)
}
fn each_pin_instance_vec(&self, circuit_instance: &Self::CircuitInstId) -> Vec<Self::PinInstId> {
circuit_instance.each_pin_instance_vec()
}
fn for_each_internal_net<F>(&self, circuit: &Self::CircuitId, f: F) where F: FnMut(Self::NetId) -> () {
circuit.each_net().for_each(f)
}
fn num_child_instances(&self, circuit: &Self::CircuitId) -> usize {
circuit.num_instances()
}
fn num_circuits(&self) -> usize {
self.circuits.len()
}
fn num_pins(&self, circuit: &Self::CircuitId) -> usize {
circuit.pin_count()
}
fn for_each_pin_of_net<F>(&self, net: &Self::NetId, f: F) where F: FnMut(Self::PinId) -> () {
net.each_pin().for_each(f)
}
fn for_each_pin_instance_of_net<F>(&self, net: &Self::NetId, f: F) where F: FnMut(Self::PinInstId) -> () {
net.each_pin_instance().for_each(f)
}
}
impl NetlistEdit for RcNetlist {
fn create_circuit(&mut self, name: Self::NameType, pins: Vec<(Self::NameType, Direction)>) -> Self::CircuitId {
let pins = pins.into_iter()
.map(|(name, direction)| Pin::new(name, direction))
.collect();
RcNetlist::create_circuit(self, name, pins)
}
fn remove_circuit(&mut self, circuit_id: &Self::CircuitId) {
RcNetlist::remove_circuit(self, circuit_id)
}
fn create_circuit_instance(&mut self, parent_circuit: &Self::CircuitId,
template_circuit: &Self::CircuitId,
name: Option<Self::NameType>) -> Self::CircuitInstId {
parent_circuit.create_circuit_instance(template_circuit, name)
}
fn remove_circuit_instance(&mut self, circuit_inst: &Self::CircuitInstId) {
circuit_inst.parent_circuit().upgrade()
.unwrap()
.remove_circuit_instance(circuit_inst)
}
fn create_net(&mut self, parent: &Self::CircuitId, name: Option<Self::NameType>) -> Self::NetId {
parent.create_net(name)
}
fn rename_net(&mut self, parent_circuit: &Self::CircuitId, net_id: &Self::NetId, new_name: Option<Self::NameType>) {
parent_circuit.rename_net(net_id.id, new_name);
}
fn remove_net(&mut self, net: &Self::NetId) {
net.parent_circuit().upgrade()
.unwrap().remove_net(net)
}
fn connect_pin(&mut self, pin: &Self::PinId, net: Option<Self::NetId>) -> Option<Self::NetId> {
pin.connect_net(net)
}
fn connect_pin_instance(&mut self, pin_inst: &Self::PinInstId, net: Option<Self::NetId>) -> Option<Self::NetId> {
pin_inst.connect_net(net)
}
}