///|
pub(all) enum NodeKind {
Port
InstancePin
Internal
External
} derive(Eq, Debug)
///|
pub(all) enum Direction {
Input
Output
Inout
Unknown
} derive(Eq, Debug)
///|
pub(all) struct Point {
x : Double
y : Double
} derive(Debug)
///|
pub(all) struct Node {
id : Int
name : String
kind : NodeKind
span : @diagnostic.SourceSpan?
} derive(Debug)
///|
pub(all) struct Connection {
node_id : Int
direction : Direction
coordinate : Point?
load_capacitance : Double?
driving_cell : String?
span : @diagnostic.SourceSpan?
} derive(Debug)
///|
/// Semantic pin view resolved from a connection and its backing node.
pub(all) struct Pin {
node_id : Int
name : String
kind : NodeKind
direction : Direction
coordinate : Point?
load_capacitance : Double?
driving_cell : String?
} derive(Debug)
///|
pub(all) struct Resistor {
id : Int
from_node : Int
to_node : Int
resistance : Double
span : @diagnostic.SourceSpan?
} derive(Debug)
///|
/// `to_node = None` represents a capacitance to ground.
pub(all) struct Capacitor {
id : Int
from_node : Int
to_node : Int?
capacitance : Double
span : @diagnostic.SourceSpan?
} derive(Debug)
///|
pub(all) struct Net {
id : Int
name : String
declared_capacitance : Double
nodes : Array[Node]
connections : Array[Connection]
resistors : Array[Resistor]
capacitors : Array[Capacitor]
span : @diagnostic.SourceSpan?
} derive(Debug)
///|
pub(all) struct NameMapEntry {
index : Int
name : String
span : @diagnostic.SourceSpan?
} derive(Debug)
///|
pub(all) struct PortDecl {
name : String
direction : Direction
coordinate : Point?
span : @diagnostic.SourceSpan?
} derive(Debug)
///|
pub(all) struct DesignHeader {
spef_version : String?
design_name : String?
date : String?
vendor : String?
program : String?
program_version : String?
design_flow : Array[String]
divider : String
delimiter : String
bus_delimiter_open : String
bus_delimiter_close : String
time_unit : UnitScale
capacitance_unit : UnitScale
resistance_unit : UnitScale
inductance_unit : UnitScale
} derive(Debug)
///|
pub(all) struct RCNetwork {
header : DesignHeader
name_map : Array[NameMapEntry]
ports : Array[PortDecl]
nets : Array[Net]
diagnostics : Array[@diagnostic.Diagnostic]
} derive(Debug)
///|
/// Design-level view exposed to library consumers.
pub(all) struct Design {
header : DesignHeader
name_map : Array[NameMapEntry]
ports : Array[PortDecl]
nets : Array[Net]
} derive(Debug)
///|
pub fn DesignHeader::default() -> DesignHeader {
{
spef_version: None,
design_name: None,
date: None,
vendor: None,
program: None,
program_version: None,
design_flow: [],
divider: "/",
delimiter: ":",
bus_delimiter_open: "[",
bus_delimiter_close: "]",
time_unit: default_time_unit(),
capacitance_unit: default_capacitance_unit(),
resistance_unit: default_resistance_unit(),
inductance_unit: default_inductance_unit(),
}
}
///|
pub fn RCNetwork::empty() -> RCNetwork {
{
header: DesignHeader::default(),
name_map: [],
ports: [],
nets: [],
diagnostics: [],
}
}
///|
pub fn RCNetwork::design(self : RCNetwork) -> Design {
{
header: self.header,
name_map: self.name_map,
ports: self.ports,
nets: self.nets,
}
}
///|
pub fn Net::pins(self : Net) -> Array[Pin] {
let pins : Array[Pin] = []
for connection in self.connections {
match self.find_node(connection.node_id) {
Some(node) =>
pins.push({
node_id: node.id,
name: node.name,
kind: node.kind,
direction: connection.direction,
coordinate: connection.coordinate,
load_capacitance: connection.load_capacitance,
driving_cell: connection.driving_cell,
})
None => ()
}
}
pins
}
///|
pub fn Net::total_resistance(self : Net) -> Double {
let mut total = 0.0
for resistor in self.resistors {
total += resistor.resistance
}
total
}
///|
/// Effective grounded capacitance using a 0.5 split for coupling capacitors.
pub fn Net::effective_capacitance(self : Net) -> Double {
let mut total = 0.0
for capacitor in self.capacitors {
total += capacitor.capacitance
}
total
}
///|
pub fn Net::ground_capacitance(self : Net) -> Double {
let mut total = 0.0
for capacitor in self.capacitors {
if capacitor.to_node is None {
total += capacitor.capacitance
}
}
total
}
///|
pub fn Net::coupling_capacitance(self : Net) -> Double {
let mut total = 0.0
for capacitor in self.capacitors {
if capacitor.to_node is Some(_) {
total += capacitor.capacitance
}
}
total
}
///|
pub fn Net::find_node(self : Net, node_id : Int) -> Node? {
self.nodes.iter().find_first(fn(node) { node.id == node_id })
}
///|
pub fn Net::driver_nodes(self : Net) -> Array[Int] {
let result : Array[Int] = []
for connection in self.connections {
if connection.direction == Output {
result.push(connection.node_id)
}
}
result
}
///|
pub fn Direction::from_spef(value : String) -> Direction {
match value {
"I" => Input
"O" => Output
"B" => Inout
_ => Unknown
}
}
///|
pub fn Direction::spef_code(self : Direction) -> String {
match self {
Input => "I"
Output => "O"
Inout => "B"
Unknown => "?"
}
}