libreda_db/reference_access/
netlist_reference_access.rs

1// Copyright (c) 2020-2021 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6use crate::netlist::prelude::*;
7use crate::traits::NetlistBase;
8
9use super::hierarchy_reference_access::*;
10
11/// Trait that provides object-like read access to a hierarchical netlist structure and its elements.
12pub trait NetlistReferenceAccess: NetlistBase {
13    /// Get a reference to a pin from a pin ID.
14    fn pin_ref(&self, pin: &Self::PinId) -> PinRef<'_, Self> {
15        PinRef {
16            base: self,
17            id: pin.clone(),
18        }
19    }
20
21    /// Get a reference to a pin instance.
22    fn pin_instance_ref(&self, id: &Self::PinInstId) -> PinInstRef<'_, Self> {
23        PinInstRef {
24            base: self,
25            id: id.clone(),
26        }
27    }
28
29    /// Get a reference to a net.
30    fn net_ref(&self, net: &Self::NetId) -> NetRef<'_, Self> {
31        NetRef {
32            base: self,
33            id: net.clone(),
34        }
35    }
36
37    /// Get a reference to a terminal.
38    fn terminal_ref(&self, t: &TerminalId<Self>) -> TerminalRef<Self> {
39        match t {
40            TerminalId::PinId(p) => TerminalRef::Pin(self.pin_ref(p)),
41            TerminalId::PinInstId(p) => TerminalRef::PinInst(self.pin_instance_ref(p)),
42        }
43    }
44}
45
46impl<T: NetlistBase> NetlistReferenceAccess for T {}
47
48impl<'a, N: NetlistBase> CellRef<'a, N> {
49    /// Iterate over the IDs of all pins of this cell.
50    pub fn each_pin_id(&self) -> impl Iterator<Item = N::PinId> + '_ {
51        self.base.each_pin(&self.id)
52    }
53
54    /// Iterate over all pins of this cell.
55    pub fn each_pin(&self) -> impl Iterator<Item = PinRef<'a, N>> + '_ {
56        self.base.each_pin(&self.id).map(move |id| PinRef {
57            base: self.base,
58            id,
59        })
60    }
61
62    /// Iterate over all input pins of this cell.
63    pub fn each_input_pin(&self) -> impl Iterator<Item = PinRef<'a, N>> + '_ {
64        self.each_pin().filter(|p| p.direction().is_input())
65    }
66
67    /// Iterate over all output pins of this cell.
68    pub fn each_output_pin(&self) -> impl Iterator<Item = PinRef<'a, N>> + '_ {
69        self.each_pin().filter(|p| p.direction().is_output())
70    }
71
72    /// Find a pin by it's name.
73    pub fn pin_by_name(&self, name: &str) -> Option<PinRef<'a, N>> {
74        self.base.pin_by_name(&self.id, name).map(|id| PinRef {
75            base: self.base,
76            id,
77        })
78    }
79
80    /// Iterate over all nets that live directly in this cell.
81    pub fn each_net(&self) -> impl Iterator<Item = NetRef<'a, N>> + '_ {
82        self.base.each_internal_net(&self.id).map(move |id| NetRef {
83            base: self.base,
84            id,
85        })
86    }
87
88    /// Get the number of nets inside this cell.
89    pub fn num_internal_nets(&self) -> usize {
90        self.base.num_internal_nets(&self.id)
91    }
92
93    /// Find a net by its name.
94    pub fn net_by_name(&self, name: &str) -> Option<NetRef<'a, N>> {
95        self.base.net_by_name(&self.id, name).map(|id| NetRef {
96            base: self.base,
97            id,
98        })
99    }
100}
101
102impl<'a, N: NetlistBase> CellInstRef<'a, N> {
103    /// Iterate over the IDs of all pins of this cell.
104    pub fn each_pin_instance_id(&self) -> impl Iterator<Item = N::PinInstId> + '_ {
105        self.base.each_pin_instance(&self.id)
106    }
107
108    /// Iterate over all pins of this cell.
109    pub fn each_pin_instance(&self) -> impl Iterator<Item = PinInstRef<'a, N>> + '_ {
110        self.base
111            .each_pin_instance(&self.id)
112            .map(move |id| PinInstRef {
113                base: self.base,
114                id,
115            })
116    }
117
118    /// Iterate over all nets are connected to this instance. A net might appear more than once.
119    pub fn each_net(&self) -> impl Iterator<Item = NetRef<'a, N>> + '_ {
120        self.base.each_external_net(&self.id).map(move |id| NetRef {
121            base: self.base,
122            id,
123        })
124    }
125
126    /// Get the pin instance which matches the given pin template.
127    pub fn pin_instance(&self, pin: &N::PinId) -> PinInstRef<'a, N> {
128        self.base.pin_ref(pin).instance(&self.id())
129    }
130
131    /// Find a pin instance by its name.
132    pub fn pin_instance_by_name(&self, name: &str) -> Option<PinInstRef<'a, N>> {
133        let pin_id = self.base.pin_by_name(&self.template().id(), name);
134        pin_id.map(|p| self.pin_instance(&p))
135    }
136}
137
138/// A reference to a net.
139/// This is just a wrapper around a netlist and a net ID.
140pub struct NetRef<'a, N: NetlistBase + ?Sized> {
141    /// Reference to the parent data structure.
142    pub(super) base: &'a N,
143    /// ID of the net.
144    pub(super) id: N::NetId,
145}
146
147impl<'a, N: NetlistBase> Eq for NetRef<'a, N> {}
148impl<'a, N: NetlistBase> PartialEq for NetRef<'a, N> {
149    fn eq(&self, other: &Self) -> bool {
150        self.id == other.id && std::ptr::eq(self.base, other.base)
151    }
152}
153
154impl<'a, N: NetlistBase> NetRef<'a, N> {
155    /// Get the net ID.
156    pub fn id(&self) -> N::NetId {
157        self.id.clone()
158    }
159
160    /// Get the name of the net.
161    pub fn name(&self) -> Option<N::NameType> {
162        self.base.net_name(&self.id)
163    }
164
165    /// Get the cell where this net lives in.
166    pub fn parent(&self) -> CellRef<'a, N> {
167        CellRef {
168            base: self.base,
169            id: self.base.parent_cell_of_net(&self.id),
170        }
171    }
172
173    /// Iterate over each pin attached to this net.
174    pub fn each_pin(&self) -> impl Iterator<Item = PinRef<'a, N>> + '_ {
175        self.base.each_pin_of_net(&self.id).map(move |id| PinRef {
176            base: self.base,
177            id,
178        })
179    }
180
181    /// Iterate over each pin instance attached to this net.
182    pub fn each_pin_instance(&self) -> impl Iterator<Item = PinInstRef<'a, N>> + '_ {
183        self.base
184            .each_pin_instance_of_net(&self.id)
185            .map(move |id| PinInstRef {
186                base: self.base,
187                id,
188            })
189    }
190
191    /// Iterate over terminal attached to this net.
192    pub fn each_terminal(&self) -> impl Iterator<Item = TerminalRef<'a, N>> + '_ {
193        let pins = self.each_pin().map(|p| p.into());
194        let pin_insts = self.each_pin_instance().map(|p| p.into());
195        pins.chain(pin_insts)
196    }
197
198    /// Iterate over all terminals that drive the net. This should usually be one.
199    /// Returns the pins that are marked as `inputs` and pin instances marked as `outputs`.
200    /// Skips `InOut` terminals.
201    pub fn each_driver(&self) -> impl Iterator<Item = TerminalRef<'a, N>> + '_ {
202        self.each_terminal().filter(|t| match t {
203            TerminalRef::Pin(p) => p.direction().is_input(),
204            TerminalRef::PinInst(p) => p.pin().direction().is_output(),
205        })
206    }
207
208    /// Iterate over all terminals that drive the net. This should usually be one.
209    /// Returns the pins that are marked as `inputs` and pin instances marked as `outputs`.
210    /// Skips `InOut` terminals.
211    pub fn each_sink(&self) -> impl Iterator<Item = TerminalRef<'a, N>> + '_ {
212        self.each_terminal().filter(|t| match t {
213            TerminalRef::Pin(p) => p.direction().is_output(),
214            TerminalRef::PinInst(p) => p.pin().direction().is_input(),
215        })
216    }
217
218    /// Get a qualified name for this net.
219    pub fn qname(&self, separator: &str) -> String {
220        format!(
221            "{}{}{}",
222            self.parent().name(),
223            separator,
224            self.name()
225                .unwrap_or_else(|| "<unnamed>".to_string().into())
226        )
227    }
228
229    /// Get the number of external pins attached to this net (pins towards the outside of the circuit).
230    pub fn num_pins(&self) -> usize {
231        self.base.num_net_pins(&self.id)
232    }
233
234    /// Get the number of pin instances attached to this net. Excludes the pins towards the outside of the circuit.
235    pub fn num_pin_instances(&self) -> usize {
236        self.base.num_net_pin_instances(&self.id)
237    }
238
239    /// Get the total number of pins and pin instances connected to this net.
240    pub fn num_terminals(&self) -> usize {
241        self.base.num_net_terminals(&self.id)
242    }
243}
244
245/// A reference to a pin.
246/// This is just a wrapper around a netlist and a pin ID.
247pub struct PinRef<'a, N: NetlistBase + ?Sized> {
248    /// Reference to the parent data structure.
249    pub(super) base: &'a N,
250    /// ID of the pin.
251    pub(super) id: N::PinId,
252}
253
254impl<'a, N: NetlistBase> Eq for PinRef<'a, N> {}
255impl<'a, N: NetlistBase> PartialEq for PinRef<'a, N> {
256    fn eq(&self, other: &Self) -> bool {
257        self.id == other.id && std::ptr::eq(self.base, other.base)
258    }
259}
260
261impl<'a, N: NetlistBase + ?Sized> Clone for PinRef<'a, N> {
262    fn clone(&self) -> Self {
263        Self {
264            base: self.base,
265            id: self.id.clone(),
266        }
267    }
268}
269
270impl<'a, N: NetlistBase> PinRef<'a, N> {
271    /// Access the base structure.
272    pub fn base(&self) -> &'_ N {
273        self.base
274    }
275
276    /// Get the pin ID.
277    pub fn id(&self) -> N::PinId {
278        self.id.clone()
279    }
280
281    /// Get the terminal ID of this pin.
282    pub fn terminal_id(&self) -> TerminalId<N> {
283        TerminalId::PinId(self.id())
284    }
285
286    /// Get the name of the pin.
287    pub fn name(&self) -> N::NameType {
288        self.base.pin_name(&self.id)
289    }
290
291    /// Get the signal direction of the pin.
292    pub fn direction(&self) -> Direction {
293        self.base.pin_direction(&self.id)
294    }
295
296    /// Get the net which is attached to the pin from inside the cell.
297    pub fn net(&self) -> Option<NetRef<'a, N>> {
298        self.base.net_of_pin(&self.id).map(|id| NetRef {
299            base: self.base,
300            id,
301        })
302    }
303
304    /// Get the cell which contains this pin.
305    pub fn cell(&self) -> CellRef<'a, N> {
306        CellRef {
307            base: self.base,
308            id: self.base.parent_cell_of_pin(&self.id),
309        }
310    }
311
312    /// Find the instance of this pin in the given cell instance.
313    pub fn instance(&self, cell_inst: &N::CellInstId) -> PinInstRef<'a, N> {
314        PinInstRef {
315            base: self.base,
316            id: self.base.pin_instance(cell_inst, &self.id),
317        }
318    }
319
320    /// Convert the pin reference into a terminal reference.
321    pub fn into_terminal(self) -> TerminalRef<'a, N> {
322        self.into()
323    }
324
325    /// Create a qualified name.
326    /// For pins: 'cell_name:pin_name'
327    pub fn qname(&self, separator: &str) -> String {
328        format!("{}{}{}", self.cell().name(), separator, self.name())
329    }
330}
331
332/// A reference to a pin instance.
333/// This is just a wrapper around a netlist and a pin instance ID.
334pub struct PinInstRef<'a, N: NetlistBase + ?Sized> {
335    /// Reference to the parent data structure.
336    pub(super) base: &'a N,
337    /// ID of the pin instance.
338    pub(super) id: N::PinInstId,
339}
340
341impl<'a, N: NetlistBase> Eq for PinInstRef<'a, N> {}
342impl<'a, N: NetlistBase> PartialEq for PinInstRef<'a, N> {
343    fn eq(&self, other: &Self) -> bool {
344        self.id == other.id && std::ptr::eq(self.base, other.base)
345    }
346}
347
348impl<'a, N: NetlistBase + ?Sized> Clone for PinInstRef<'a, N> {
349    fn clone(&self) -> Self {
350        Self {
351            base: self.base,
352            id: self.id.clone(),
353        }
354    }
355}
356
357impl<'a, N: NetlistBase> PinInstRef<'a, N> {
358    /// Get the pin instance ID.
359    pub fn id(&self) -> N::PinInstId {
360        self.id.clone()
361    }
362
363    /// Access the base structure.
364    pub fn base(&self) -> &'_ N {
365        self.base
366    }
367
368    /// Get the terminal ID of this pin instance.
369    pub fn terminal_id(&self) -> TerminalId<N> {
370        TerminalId::PinInstId(self.id())
371    }
372
373    /// Get the template of this pin instance.
374    pub fn pin(&self) -> PinRef<'a, N> {
375        PinRef {
376            base: self.base,
377            id: self.base.template_pin(&self.id),
378        }
379    }
380
381    /// Get the parent cell instance.
382    pub fn cell_instance(&self) -> CellInstRef<'a, N> {
383        CellInstRef {
384            base: self.base,
385            id: self.base.parent_of_pin_instance(&self.id),
386        }
387    }
388
389    /// Get the net which is attached to this pin instance.
390    pub fn net(&self) -> Option<NetRef<'a, N>> {
391        self.base.net_of_pin_instance(&self.id).map(|id| NetRef {
392            base: self.base,
393            id,
394        })
395    }
396
397    /// Convert the pin instance reference into a terminal reference.
398    pub fn into_terminal(self) -> TerminalRef<'a, N> {
399        self.into()
400    }
401
402    /// Create a qualified name.
403    /// For pin instances: 'cell_name:cell_instance:pin_name'
404    /// Where `:` is defined by `separator`.
405    pub fn qname(&self, separator: &str) -> String {
406        format!(
407            "{}{}{}{}{}",
408            self.pin().cell().name(),
409            separator,
410            self.cell_instance()
411                .name()
412                .unwrap_or_else(|| "<unnamed>".to_string().into()),
413            separator,
414            self.pin().name()
415        )
416    }
417}
418
419/// Either a pin or a pin instance.
420pub enum TerminalRef<'a, N: NetlistBase + ?Sized> {
421    /// A template pin.
422    Pin(PinRef<'a, N>),
423    /// An instance of a pin.
424    PinInst(PinInstRef<'a, N>),
425}
426
427impl<'a, N: NetlistBase + ?Sized> Clone for TerminalRef<'a, N> {
428    fn clone(&self) -> Self {
429        match self {
430            TerminalRef::Pin(p) => TerminalRef::Pin(p.clone()),
431            TerminalRef::PinInst(p) => TerminalRef::PinInst(p.clone()),
432        }
433    }
434}
435
436impl<'a, N: NetlistBase> PartialEq for TerminalRef<'a, N> {
437    fn eq(&self, other: &Self) -> bool {
438        self.id() == other.id()
439    }
440}
441
442impl<'a, N: NetlistBase> From<PinRef<'a, N>> for TerminalRef<'a, N> {
443    fn from(p: PinRef<'a, N>) -> Self {
444        Self::Pin(p)
445    }
446}
447
448impl<'a, N: NetlistBase> From<PinInstRef<'a, N>> for TerminalRef<'a, N> {
449    fn from(p: PinInstRef<'a, N>) -> Self {
450        Self::PinInst(p)
451    }
452}
453
454impl<'a, N: NetlistBase> From<TerminalRef<'a, N>> for TerminalId<N> {
455    fn from(t: TerminalRef<'a, N>) -> Self {
456        match t {
457            TerminalRef::Pin(p) => TerminalId::PinId(p.id),
458            TerminalRef::PinInst(p) => TerminalId::PinInstId(p.id),
459        }
460    }
461}
462
463impl<'a, N: NetlistBase> TerminalRef<'a, N> {
464    /// Get the ID of the terminal.
465    pub fn id(&self) -> TerminalId<N> {
466        (*self).clone().into()
467    }
468
469    /// Get a reference to the netlist structure.
470    pub fn base(&self) -> &'_ N {
471        match self {
472            TerminalRef::Pin(p) => p.base(),
473            TerminalRef::PinInst(p) => p.base(),
474        }
475    }
476
477    /// Get the attached net.
478    pub fn net(&self) -> Option<NetRef<'a, N>> {
479        match self {
480            TerminalRef::Pin(p) => p.net(),
481            TerminalRef::PinInst(p) => p.net(),
482        }
483    }
484
485    /// Get the name of the pin.
486    pub fn pin_name(&self) -> N::NameType {
487        match self {
488            TerminalRef::Pin(p) => p.name(),
489            TerminalRef::PinInst(p) => p.pin().name(),
490        }
491    }
492
493    /// Get the parent cell of this terminal.
494    /// For a pin, this equals the cell where the pin is defined.
495    /// For a pin instance, this equals the parent of the cell instance which contains the pin instance.
496    pub fn parent(&self) -> CellRef<N> {
497        match self {
498            TerminalRef::Pin(p) => p.cell(),
499            TerminalRef::PinInst(p) => p.cell_instance().parent(),
500        }
501    }
502
503    /// Create a qualified name.
504    /// For pins: 'cell_name:pin_name'
505    /// For pin instances: 'cell_name:cell_instance:pin_name'
506    /// Where `:` is defined by `separator`.
507    pub fn qname(&self, separator: &str) -> String {
508        match self {
509            TerminalRef::Pin(p) => p.qname(separator),
510            TerminalRef::PinInst(p) => p.qname(separator),
511        }
512    }
513}