1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Traits for netlist data types.
//!
//! Instead of putting a netlist data structure into the center of the world,
//! this data base concentrates on the way *how* a netlist can be accessed and modified.
//! The basic necessary operations are defined in the [`NetlistBase'] trait and in the
//! [`NetlistEdit`] trait.
//!
//! More complex operations on netlist are provided by the [`NetlistUtil`] and [`NetlistEditUtil`] traits.
//!
//! [`NetlistBase`]: trait@NetlistBase
//! [`NetlistEdit`]: trait@NetlistEdit
//! [`NetlistUtil`]: trait@crate::netlist::util::NetlistUtil
//! [`NetlistEditUtil`]: trait@crate::netlist::util::NetlistEditUtil
#![allow(missing_docs)] // Necessary because portrait does not generate docs.
use super::prelude::*;
pub use super::util::{NetlistEditUtil, NetlistUtil};
pub use crate::traits::{HierarchyBase, HierarchyEdit};
use crate::traits::{HierarchyBaseMT, HierarchyIds, IdType, IdTypeMT};
/// Identifier types used for components of netlists.
#[portrait::make]
pub trait NetlistIds: HierarchyIds {
/// Pin identifier type. Uniquely identifies a pin in the whole netlist.
type PinId: IdType;
/// Pin instance identifier type. Uniquely identifies a pin instance in the whole netlist.
/// A pin instance is a pin of a circuit instance.
type PinInstId: IdType;
/// Net identifier type. Uniquely identifies a net in the whole netlist.
type NetId: IdType;
}
/// Helper trait which constrains [`trait@NetlistBase`] for such that ID types
/// are [`Send`] and [`Sync`] as commonly used for parallel algorithms.
#[portrait::make]
pub trait NetlistBaseMT:
NetlistBase<PinId = Self::PinIdMT, PinInstId = Self::PinInstIdMT, NetId = Self::NetIdMT>
+ HierarchyBaseMT
{
/// ID of a pin.
type PinIdMT: IdTypeMT;
/// ID of a pin instance.
type PinInstIdMT: IdTypeMT;
/// ID of a net.
type NetIdMT: IdTypeMT;
}
impl<N> NetlistBaseMT for N
where
N: NetlistBase + HierarchyBaseMT,
N::PinId: Send + Sync,
N::PinInstId: Send + Sync,
N::NetId: Send + Sync,
{
type PinIdMT = N::PinId;
type PinInstIdMT = N::PinInstId;
type NetIdMT = N::NetId;
}
/// Most basic trait for traversing a netlist.
/// A netlist extends the `HierarchyBase` and hence is hierarchical.
/// `NetlistBase` extends the components of the hierarchy with pins and nets.
/// Each cell can have pins. Each cell instance has pin instances that correspond one-to-one
/// to the pins of the template cell. Cells can contain nets. Each pin and each pin instance can be
/// connected to one or zero nets. A net can be connected to an arbitrary number of pins and pin instances.
///
/// Pins must have a name and also a signal direction.
///
/// Nets *can* have a name.
///
#[portrait::make(import(crate::prelude::Direction))]
pub trait NetlistBase: HierarchyBase + NetlistIds {
/// Get the ID of the template pin of this pin instance.
fn template_pin(&self, pin_instance: &Self::PinInstId) -> Self::PinId;
/// Get the signal direction of the pin.
fn pin_direction(&self, pin: &Self::PinId) -> Direction;
/// Get the name of the pin.
fn pin_name(&self, pin: &Self::PinId) -> Self::NameType;
/// Find a pin by its name.
/// Returns `None` if no such pin can be found.
fn pin_by_name(&self, parent_circuit: &Self::CellId, name: &str) -> Option<Self::PinId>;
/// Get the ID of the parent circuit of this pin.
fn parent_cell_of_pin(&self, pin: &Self::PinId) -> Self::CellId;
/// Get the ID of the circuit instance that holds this pin instance.
fn parent_of_pin_instance(&self, pin_inst: &Self::PinInstId) -> Self::CellInstId;
/// Get the ID of a pin instance given the cell instance and the pin ID.
fn pin_instance(&self, cell_inst: &Self::CellInstId, pin: &Self::PinId) -> Self::PinInstId {
// Inefficient default implementation.
self.each_pin_instance(cell_inst)
.find(|inst| &self.template_pin(inst) == pin)
.expect("No such pin found in this cell.")
}
/// Get the ID of the parent circuit of this net.
fn parent_cell_of_net(&self, net: &Self::NetId) -> Self::CellId;
/// Get the internal net attached to this pin.
fn net_of_pin(&self, pin: &Self::PinId) -> Option<Self::NetId>;
/// Get the external net attached to this pin instance.
fn net_of_pin_instance(&self, pin_instance: &Self::PinInstId) -> Option<Self::NetId>;
/// Get the net of the logical constant zero.
fn net_zero(&self, parent_circuit: &Self::CellId) -> Self::NetId;
/// Get the net of the logical constant one.
fn net_one(&self, parent_circuit: &Self::CellId) -> Self::NetId;
/// Find a net by its name inside the parent circuit.
/// Returns `None` if no such net can be found.
fn net_by_name(&self, parent_circuit: &Self::CellId, name: &str) -> Option<Self::NetId>;
/// Get the name of the net.
fn net_name(&self, net: &Self::NetId) -> Option<Self::NameType>;
/// Call a function for each pin of the circuit.
fn for_each_pin<F>(&self, circuit: &Self::CellId, f: F)
where
F: FnMut(Self::PinId);
/// Get a `Vec` with the IDs of all pins of this circuit.
fn each_pin_vec(&self, circuit: &Self::CellId) -> Vec<Self::PinId> {
let mut v = Vec::new();
self.for_each_pin(circuit, |c| v.push(c));
v
}
/// Iterate over all pins of a circuit.
fn each_pin<'a>(
&'a self,
circuit: &Self::CellId,
) -> Box<dyn Iterator<Item = Self::PinId> + 'a> {
Box::new(self.each_pin_vec(circuit).into_iter())
}
// /// Find the position of the pin.
// fn pin_position(&self, pin: &Self::PinId) -> usize {
// self.for_each_pin(&self.parent_cell_of_pin(pin))
// .enumerate()
// .find(|(_, p)| p == pin)
// .map(|(idx, _)| idx)
// .expect("pin ID does not exist")
// }
/// Call a function for each pin instance of the circuit instance.
fn for_each_pin_instance<F>(&self, circuit_inst: &Self::CellInstId, f: F)
where
F: FnMut(Self::PinInstId);
/// Get a `Vec` with the IDs of all pin instance of this circuit instance.
fn each_pin_instance_vec(&self, circuit_instance: &Self::CellInstId) -> Vec<Self::PinInstId> {
let mut v = Vec::new();
self.for_each_pin_instance(circuit_instance, |c| v.push(c));
v
}
/// Iterate over all pin instances of a circuit.
fn each_pin_instance<'a>(
&'a self,
circuit_instance: &Self::CellInstId,
) -> Box<dyn Iterator<Item = Self::PinInstId> + 'a> {
Box::new(self.each_pin_instance_vec(circuit_instance).into_iter())
}
/// Iterate over all external nets connected to the circuit instance.
/// A net might appear more than once.
fn each_external_net<'a>(
&'a self,
circuit_instance: &Self::CellInstId,
) -> Box<dyn Iterator<Item = Self::NetId> + 'a> {
Box::new(
self.each_pin_instance(circuit_instance)
.flat_map(move |pin_id| self.net_of_pin_instance(&pin_id)),
)
}
/// Iterate over all external nets connected to the circuit instance.
/// A net might appear more than once.
fn for_each_external_net<F>(&self, circuit_instance: &Self::CellInstId, mut f: F)
where
F: FnMut(Self::NetId),
{
self.for_each_pin_instance(circuit_instance, |i| {
self.net_of_pin_instance(&i)
.iter()
.cloned()
.for_each(|n| f(n))
});
}
/// Get a vector of all external nets connected to the circuit instance.
/// A net might appear more than once.
fn each_external_net_vec(&self, circuit_instance: &Self::CellInstId) -> Vec<Self::NetId> {
let mut v = Vec::new();
self.for_each_external_net(circuit_instance, |n| v.push(n));
v
}
/// Call a function for net of the circuit.
fn for_each_internal_net<F>(&self, circuit: &Self::CellId, f: F)
where
F: FnMut(Self::NetId);
/// Get a `Vec` with all nets in this circuit.
fn each_internal_net_vec(&self, circuit: &Self::CellId) -> Vec<Self::NetId> {
let mut v = Vec::new();
self.for_each_internal_net(circuit, |c| v.push(c));
v
}
/// Iterate over all defined nets inside a circuit.
fn each_internal_net<'a>(
&'a self,
circuit: &Self::CellId,
) -> Box<dyn Iterator<Item = Self::NetId> + 'a> {
Box::new(self.each_internal_net_vec(circuit).into_iter())
}
/// Return the number of nets defined inside a cell.
fn num_internal_nets(&self, circuit: &Self::CellId) -> usize {
// Inefficient default implementation.
let mut counter = 0;
self.for_each_internal_net(circuit, |_| counter += 1);
counter
}
/// Get the number of pins that are connected to this net.
fn num_net_pins(&self, net: &Self::NetId) -> usize {
let mut n = 0;
self.for_each_pin_of_net(net, |_| n += 1);
n
}
/// Get the number of pin instances that are connected to this net.
fn num_net_pin_instances(&self, net: &Self::NetId) -> usize {
let mut n = 0;
self.for_each_pin_instance_of_net(net, |_| n += 1);
n
}
/// Get the number of terminals that are connected to this net.
fn num_net_terminals(&self, net: &Self::NetId) -> usize {
self.num_net_pins(net) + self.num_net_pin_instances(net)
}
/// Get the number of pins of a circuit.
fn num_pins(&self, circuit: &Self::CellId) -> usize;
/// Call a function for each pin connected to this net.
fn for_each_pin_of_net<F>(&self, net: &Self::NetId, f: F)
where
F: FnMut(Self::PinId);
/// Get a `Vec` with all pin IDs connected to this net.
fn each_pin_of_net_vec(&self, net: &Self::NetId) -> Vec<Self::PinId> {
let mut v = Vec::new();
self.for_each_pin_of_net(net, |c| v.push(c));
v
}
/// Iterate over all pins of a net.
fn each_pin_of_net<'a>(
&'a self,
net: &Self::NetId,
) -> Box<dyn Iterator<Item = Self::PinId> + 'a> {
Box::new(self.each_pin_of_net_vec(net).into_iter())
}
/// Call a function for each pin instance connected to this net.
fn for_each_pin_instance_of_net<F>(&self, net: &Self::NetId, f: F)
where
F: FnMut(Self::PinInstId);
/// Get a `Vec` with all pin instance IDs connected to this net.
fn each_pin_instance_of_net_vec(&self, net: &Self::NetId) -> Vec<Self::PinInstId> {
let mut v = Vec::new();
self.for_each_pin_instance_of_net(net, |c| v.push(c));
v
}
/// Iterate over all pins of a net.
fn each_pin_instance_of_net<'a>(
&'a self,
net: &Self::NetId,
) -> Box<dyn Iterator<Item = Self::PinInstId> + 'a> {
Box::new(self.each_pin_instance_of_net_vec(net).into_iter())
}
}
/// Trait for netlists that support editing.
///
/// This includes:
///
/// * creation and removal of pins and nets
/// * connecting pins and pin instances to nets
/// * renaming nets
/// * renaming pins
///
/// More complex operations which can be build on top of the basic operations
/// are provided by the [`NetlistEditUtil`] trait.
///
/// [`NetlistEditUtil`]: crate::netlist::util::NetlistEditUtil
#[portrait::make(import(crate::prelude::Direction))]
pub trait NetlistEdit: NetlistBase + HierarchyEdit {
// /// Create a multi-bit port.
// /// Internally creates a pin for every bit of the port.
// fn create_bus(&mut self, circuit: &Self::CellId, name: Self::NameType, direction: Direction, width: usize) -> Vec<Self::PinId>;
/// Create a new pin in this cell.
/// Also adds the pin to all instances of the cell.
fn create_pin(
&mut self,
cell: &Self::CellId,
name: Self::NameType,
direction: Direction,
) -> Self::PinId;
/// Remove the pin from this circuit and from all instances of this circuit.
fn remove_pin(&mut self, id: &Self::PinId);
/// Change the name of the pin, returns the old name.
/// # Panics
/// Panics when the name is already occupied.
fn rename_pin(&mut self, pin: &Self::PinId, new_name: Self::NameType) -> Self::NameType;
/// Create a net net that lives in the `parent` circuit.
fn create_net(&mut self, parent: &Self::CellId, name: Option<Self::NameType>) -> Self::NetId;
/// Set a new name for the net. This might panic if the name already exists.
/// Returns the old name.
fn rename_net(
&mut self,
net_id: &Self::NetId,
new_name: Option<Self::NameType>,
) -> Option<Self::NameType>;
/// Delete the net if it exists and disconnect all connected terminals.
fn remove_net(&mut self, net: &Self::NetId);
/// Connect a pin to a net.
/// Returns the old connected net, if any.
fn connect_pin(&mut self, pin: &Self::PinId, net: Option<Self::NetId>) -> Option<Self::NetId>;
/// Disconnect the pin from any connected net.
/// Returns the old connected net, if any.
fn disconnect_pin(&mut self, pin: &Self::PinId) -> Option<Self::NetId> {
self.connect_pin(pin, None)
}
/// Connect a pin instance to a net.
/// Returns the old connected net, if any.
fn connect_pin_instance(
&mut self,
pin: &Self::PinInstId,
net: Option<Self::NetId>,
) -> Option<Self::NetId>;
/// Disconnect the pin instance from any connected net.
/// Returns the old connected net, if any.
fn disconnect_pin_instance(&mut self, pin_instance: &Self::PinInstId) -> Option<Self::NetId> {
self.connect_pin_instance(pin_instance, None)
}
}