use super::prelude::*;
use std::rc::{Weak, Rc};
use std::cell::RefCell;
use std::collections::HashSet;
use genawaiter::rc::Gen;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
#[derive(Debug)]
pub struct Net {
pub(super) id: NetIndex,
pub(super) name: RefCell<Option<String>>,
pub(super) parent_circuit: Weak<Circuit>,
pub(super) pins: RefCell<HashSet<Rc<Pin>>>,
pub(super) pin_instances: RefCell<HashSet<Rc<PinInstance>>>,
}
impl Net {
pub fn name(&self) -> Option<String> {
self.name.borrow().as_ref().cloned()
}
pub fn create_name(&self) -> String {
self.name()
.unwrap_or_else(|| {
format!("__{}", self.id)
})
}
pub fn create_qname(&self) -> String {
format!("{}:{}", self.parent_circuit().upgrade().unwrap().name(), self.create_name())
}
pub fn rename<S: Into<String>>(&self, name: Option<S>) {
self.parent_circuit().upgrade()
.unwrap()
.rename_net(self.id(), name)
}
pub fn id(&self) -> NetIndex {
self.id
}
pub fn pins(&self) -> impl Deref<Target=HashSet<Rc<Pin>>> + '_ {
self.pins.borrow()
}
pub fn pins_instances(&self) -> impl Deref<Target=HashSet<Rc<PinInstance>>> + '_ {
self.pin_instances.borrow()
}
pub fn each_terminal(&self) -> impl Iterator<Item=TerminalRef> + '_ {
let generator = Gen::new(|co| async move {
for t in self.pins.borrow().iter().cloned() {
co.yield_(TerminalRef::Pin(t)).await;
}
for t in self.pin_instances.borrow().iter().cloned() {
co.yield_(TerminalRef::PinInstance(t)).await;
}
});
generator.into_iter()
}
pub fn each_pin_instance(&self) -> impl Iterator<Item=Rc<PinInstance>> + '_ {
let generator = Gen::new(|co| async move {
for t in self.pin_instances.borrow().iter().cloned()
{
co.yield_(t).await;
}
});
generator.into_iter()
}
pub fn each_pin(&self) -> impl Iterator<Item=Rc<Pin>> + '_ {
let generator = Gen::new(|co| async move {
for p in self.pins.borrow().iter().cloned()
{
co.yield_(p).await;
}
});
generator.into_iter()
}
pub fn each_instance(&self) -> impl Iterator<Item=Rc<CircuitInstance>> + '_ {
let generator = Gen::new(|co| async move {
for p in self.pin_instances.borrow().iter() {
if let Some(inst) = p.circuit_instance().upgrade() {
co.yield_(inst).await;
} else {
debug_assert!(false, "Weak reference to circuit instance should never by `None`.");
}
}
});
generator.into_iter()
}
pub fn parent_circuit(&self) -> Weak<Circuit> {
self.parent_circuit.clone()
}
pub fn num_pins(&self) -> usize { self.pins.borrow().len() }
pub fn num_pin_instances(&self) -> usize { self.pin_instances.borrow().len() }
pub fn num_terminals(&self) -> usize {
self.num_pins() + self.num_pin_instances()
}
}
impl Eq for Net {}
impl PartialEq for Net {
fn eq(&self, other: &Self) -> bool {
debug_assert_ne!(self.parent_circuit.upgrade(), None,
"Cannot compare nets that don't live in a circuit.");
self.id == other.id
&& self.parent_circuit.ptr_eq(&other.parent_circuit)
}
}
impl Hash for Net {
fn hash<H: Hasher>(&self, state: &mut H) {
debug_assert_ne!(self.parent_circuit.upgrade(), None,
"Cannot hash nets that don't live in a circuit.");
self.id.hash(state);
self.parent_circuit.upgrade().hash(state);
}
}