use std::collections::{HashMap, HashSet};
mod builder;
mod endpoint;
mod node;
mod query;
#[cfg(test)]
mod tests;
pub use endpoint::{Endpoint, EndpointKind};
pub use node::NetNode;
pub use query::NetQuery;
use crate::parser::Circuit;
#[derive(Debug, Clone, Default)]
pub struct Netlist {
pub(crate) nets: Vec<NetNode>,
pub(crate) by_id: HashMap<String, usize>,
pub(crate) by_name: HashMap<String, usize>,
pub(crate) port_to_net: HashMap<String, usize>,
pub(crate) pad_to_net: HashMap<String, usize>,
pub(crate) endpoint_ids_per_net: Vec<HashSet<String>>,
}
impl Netlist {
pub fn from_circuit(circuit: &Circuit) -> Self {
builder::build_netlist(circuit)
}
pub fn net(&self, query: impl NetQuery) -> Option<&NetNode> {
query.resolve_index(self).map(|idx| &self.nets[idx])
}
pub fn endpoints(&self, query: impl NetQuery) -> &[Endpoint] {
match query.resolve_index(self) {
Some(idx) => &self.nets[idx].endpoints,
None => &[],
}
}
pub fn is_floating(&self, query: impl NetQuery) -> bool {
match query.resolve_index(self) {
Some(idx) => self.nets[idx].is_floating(),
None => true,
}
}
pub fn nets(&self) -> impl Iterator<Item = &NetNode> {
self.nets.iter()
}
pub fn floating_nets(&self) -> impl Iterator<Item = &NetNode> {
self.nets.iter().filter(|n| n.is_floating())
}
pub fn ghost_nets(&self) -> impl Iterator<Item = &NetNode> {
self.nets.iter().filter(|n| n.is_ghost())
}
pub fn are_connected(&self, endpoint_a: &str, endpoint_b: &str) -> bool {
let net_a = self
.port_to_net
.get(endpoint_a)
.or_else(|| self.pad_to_net.get(endpoint_a));
let net_b = self
.port_to_net
.get(endpoint_b)
.or_else(|| self.pad_to_net.get(endpoint_b));
match (net_a, net_b) {
(Some(a), Some(b)) => a == b,
_ => false,
}
}
}