use crate::netlist::prelude::*;
use crate::traits::NetlistBase;
use super::hierarchy_reference_access::*;
pub trait NetlistReferenceAccess: NetlistBase {
fn pin_ref(&self, pin: &Self::PinId) -> PinRef<'_, Self> {
PinRef {
base: self,
id: pin.clone(),
}
}
fn pin_instance_ref(&self, id: &Self::PinInstId) -> PinInstRef<'_, Self> {
PinInstRef {
base: self,
id: id.clone(),
}
}
fn net_ref(&self, net: &Self::NetId) -> NetRef<'_, Self> {
NetRef {
base: self,
id: net.clone(),
}
}
fn terminal_ref(&self, t: &TerminalId<Self>) -> TerminalRef<Self> {
match t {
TerminalId::PinId(p) => TerminalRef::Pin(self.pin_ref(p)),
TerminalId::PinInstId(p) => TerminalRef::PinInst(self.pin_instance_ref(p)),
}
}
}
impl<T: NetlistBase> NetlistReferenceAccess for T {}
impl<'a, N: NetlistBase> CellRef<'a, N> {
pub fn each_pin_id(&self) -> impl Iterator<Item = N::PinId> + '_ {
self.base.each_pin(&self.id)
}
pub fn each_pin(&self) -> impl Iterator<Item = PinRef<'a, N>> + '_ {
self.base.each_pin(&self.id).map(move |id| PinRef {
base: self.base,
id,
})
}
pub fn each_input_pin(&self) -> impl Iterator<Item = PinRef<'a, N>> + '_ {
self.each_pin().filter(|p| p.direction().is_input())
}
pub fn each_output_pin(&self) -> impl Iterator<Item = PinRef<'a, N>> + '_ {
self.each_pin().filter(|p| p.direction().is_output())
}
pub fn pin_by_name(&self, name: &str) -> Option<PinRef<'a, N>> {
self.base.pin_by_name(&self.id, name).map(|id| PinRef {
base: self.base,
id,
})
}
pub fn each_net(&self) -> impl Iterator<Item = NetRef<'a, N>> + '_ {
self.base.each_internal_net(&self.id).map(move |id| NetRef {
base: self.base,
id,
})
}
pub fn num_internal_nets(&self) -> usize {
self.base.num_internal_nets(&self.id)
}
pub fn net_by_name(&self, name: &str) -> Option<NetRef<'a, N>> {
self.base.net_by_name(&self.id, name).map(|id| NetRef {
base: self.base,
id,
})
}
}
impl<'a, N: NetlistBase> CellInstRef<'a, N> {
pub fn each_pin_instance_id(&self) -> impl Iterator<Item = N::PinInstId> + '_ {
self.base.each_pin_instance(&self.id)
}
pub fn each_pin_instance(&self) -> impl Iterator<Item = PinInstRef<'a, N>> + '_ {
self.base
.each_pin_instance(&self.id)
.map(move |id| PinInstRef {
base: self.base,
id,
})
}
pub fn each_net(&self) -> impl Iterator<Item = NetRef<'a, N>> + '_ {
self.base.each_external_net(&self.id).map(move |id| NetRef {
base: self.base,
id,
})
}
pub fn pin_instance(&self, pin: &N::PinId) -> PinInstRef<'a, N> {
self.base.pin_ref(pin).instance(&self.id())
}
pub fn pin_instance_by_name(&self, name: &str) -> Option<PinInstRef<'a, N>> {
let pin_id = self.base.pin_by_name(&self.template().id(), name);
pin_id.map(|p| self.pin_instance(&p))
}
}
pub struct NetRef<'a, N: NetlistBase + ?Sized> {
pub(super) base: &'a N,
pub(super) id: N::NetId,
}
impl<'a, N: NetlistBase> Eq for NetRef<'a, N> {}
impl<'a, N: NetlistBase> PartialEq for NetRef<'a, N> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id && std::ptr::eq(self.base, other.base)
}
}
impl<'a, N: NetlistBase> NetRef<'a, N> {
pub fn id(&self) -> N::NetId {
self.id.clone()
}
pub fn name(&self) -> Option<N::NameType> {
self.base.net_name(&self.id)
}
pub fn parent(&self) -> CellRef<'a, N> {
CellRef {
base: self.base,
id: self.base.parent_cell_of_net(&self.id),
}
}
pub fn each_pin(&self) -> impl Iterator<Item = PinRef<'a, N>> + '_ {
self.base.each_pin_of_net(&self.id).map(move |id| PinRef {
base: self.base,
id,
})
}
pub fn each_pin_instance(&self) -> impl Iterator<Item = PinInstRef<'a, N>> + '_ {
self.base
.each_pin_instance_of_net(&self.id)
.map(move |id| PinInstRef {
base: self.base,
id,
})
}
pub fn each_terminal(&self) -> impl Iterator<Item = TerminalRef<'a, N>> + '_ {
let pins = self.each_pin().map(|p| p.into());
let pin_insts = self.each_pin_instance().map(|p| p.into());
pins.chain(pin_insts)
}
pub fn each_driver(&self) -> impl Iterator<Item = TerminalRef<'a, N>> + '_ {
self.each_terminal().filter(|t| match t {
TerminalRef::Pin(p) => p.direction().is_input(),
TerminalRef::PinInst(p) => p.pin().direction().is_output(),
})
}
pub fn each_sink(&self) -> impl Iterator<Item = TerminalRef<'a, N>> + '_ {
self.each_terminal().filter(|t| match t {
TerminalRef::Pin(p) => p.direction().is_output(),
TerminalRef::PinInst(p) => p.pin().direction().is_input(),
})
}
pub fn qname(&self, separator: &str) -> String {
format!(
"{}{}{}",
self.parent().name(),
separator,
self.name()
.unwrap_or_else(|| "<unnamed>".to_string().into())
)
}
pub fn num_pins(&self) -> usize {
self.base.num_net_pins(&self.id)
}
pub fn num_pin_instances(&self) -> usize {
self.base.num_net_pin_instances(&self.id)
}
pub fn num_terminals(&self) -> usize {
self.base.num_net_terminals(&self.id)
}
}
pub struct PinRef<'a, N: NetlistBase + ?Sized> {
pub(super) base: &'a N,
pub(super) id: N::PinId,
}
impl<'a, N: NetlistBase> Eq for PinRef<'a, N> {}
impl<'a, N: NetlistBase> PartialEq for PinRef<'a, N> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id && std::ptr::eq(self.base, other.base)
}
}
impl<'a, N: NetlistBase + ?Sized> Clone for PinRef<'a, N> {
fn clone(&self) -> Self {
Self {
base: self.base,
id: self.id.clone(),
}
}
}
impl<'a, N: NetlistBase> PinRef<'a, N> {
pub fn base(&self) -> &'_ N {
self.base
}
pub fn id(&self) -> N::PinId {
self.id.clone()
}
pub fn terminal_id(&self) -> TerminalId<N> {
TerminalId::PinId(self.id())
}
pub fn name(&self) -> N::NameType {
self.base.pin_name(&self.id)
}
pub fn direction(&self) -> Direction {
self.base.pin_direction(&self.id)
}
pub fn net(&self) -> Option<NetRef<'a, N>> {
self.base.net_of_pin(&self.id).map(|id| NetRef {
base: self.base,
id,
})
}
pub fn cell(&self) -> CellRef<'a, N> {
CellRef {
base: self.base,
id: self.base.parent_cell_of_pin(&self.id),
}
}
pub fn instance(&self, cell_inst: &N::CellInstId) -> PinInstRef<'a, N> {
PinInstRef {
base: self.base,
id: self.base.pin_instance(cell_inst, &self.id),
}
}
pub fn into_terminal(self) -> TerminalRef<'a, N> {
self.into()
}
pub fn qname(&self, separator: &str) -> String {
format!("{}{}{}", self.cell().name(), separator, self.name())
}
}
pub struct PinInstRef<'a, N: NetlistBase + ?Sized> {
pub(super) base: &'a N,
pub(super) id: N::PinInstId,
}
impl<'a, N: NetlistBase> Eq for PinInstRef<'a, N> {}
impl<'a, N: NetlistBase> PartialEq for PinInstRef<'a, N> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id && std::ptr::eq(self.base, other.base)
}
}
impl<'a, N: NetlistBase + ?Sized> Clone for PinInstRef<'a, N> {
fn clone(&self) -> Self {
Self {
base: self.base,
id: self.id.clone(),
}
}
}
impl<'a, N: NetlistBase> PinInstRef<'a, N> {
pub fn id(&self) -> N::PinInstId {
self.id.clone()
}
pub fn base(&self) -> &'_ N {
self.base
}
pub fn terminal_id(&self) -> TerminalId<N> {
TerminalId::PinInstId(self.id())
}
pub fn pin(&self) -> PinRef<'a, N> {
PinRef {
base: self.base,
id: self.base.template_pin(&self.id),
}
}
pub fn cell_instance(&self) -> CellInstRef<'a, N> {
CellInstRef {
base: self.base,
id: self.base.parent_of_pin_instance(&self.id),
}
}
pub fn net(&self) -> Option<NetRef<'a, N>> {
self.base.net_of_pin_instance(&self.id).map(|id| NetRef {
base: self.base,
id,
})
}
pub fn into_terminal(self) -> TerminalRef<'a, N> {
self.into()
}
pub fn qname(&self, separator: &str) -> String {
format!(
"{}{}{}{}{}",
self.pin().cell().name(),
separator,
self.cell_instance()
.name()
.unwrap_or_else(|| "<unnamed>".to_string().into()),
separator,
self.pin().name()
)
}
}
pub enum TerminalRef<'a, N: NetlistBase + ?Sized> {
Pin(PinRef<'a, N>),
PinInst(PinInstRef<'a, N>),
}
impl<'a, N: NetlistBase + ?Sized> Clone for TerminalRef<'a, N> {
fn clone(&self) -> Self {
match self {
TerminalRef::Pin(p) => TerminalRef::Pin(p.clone()),
TerminalRef::PinInst(p) => TerminalRef::PinInst(p.clone()),
}
}
}
impl<'a, N: NetlistBase> PartialEq for TerminalRef<'a, N> {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id()
}
}
impl<'a, N: NetlistBase> From<PinRef<'a, N>> for TerminalRef<'a, N> {
fn from(p: PinRef<'a, N>) -> Self {
Self::Pin(p)
}
}
impl<'a, N: NetlistBase> From<PinInstRef<'a, N>> for TerminalRef<'a, N> {
fn from(p: PinInstRef<'a, N>) -> Self {
Self::PinInst(p)
}
}
impl<'a, N: NetlistBase> From<TerminalRef<'a, N>> for TerminalId<N> {
fn from(t: TerminalRef<'a, N>) -> Self {
match t {
TerminalRef::Pin(p) => TerminalId::PinId(p.id),
TerminalRef::PinInst(p) => TerminalId::PinInstId(p.id),
}
}
}
impl<'a, N: NetlistBase> TerminalRef<'a, N> {
pub fn id(&self) -> TerminalId<N> {
(*self).clone().into()
}
pub fn base(&self) -> &'_ N {
match self {
TerminalRef::Pin(p) => p.base(),
TerminalRef::PinInst(p) => p.base(),
}
}
pub fn net(&self) -> Option<NetRef<'a, N>> {
match self {
TerminalRef::Pin(p) => p.net(),
TerminalRef::PinInst(p) => p.net(),
}
}
pub fn pin_name(&self) -> N::NameType {
match self {
TerminalRef::Pin(p) => p.name(),
TerminalRef::PinInst(p) => p.pin().name(),
}
}
pub fn parent(&self) -> CellRef<N> {
match self {
TerminalRef::Pin(p) => p.cell(),
TerminalRef::PinInst(p) => p.cell_instance().parent(),
}
}
pub fn qname(&self, separator: &str) -> String {
match self {
TerminalRef::Pin(p) => p.qname(separator),
TerminalRef::PinInst(p) => p.qname(separator),
}
}
}