Skip to main content

safety_net/
netlist.rs

1/*!
2
3  API for a netlist data structure.
4
5*/
6
7use crate::{
8    attribute::{Attribute, AttributeKey, AttributeValue, Parameter},
9    circuit::{Identifier, Instantiable, Net, Object},
10    error::Error,
11    graph::{Analysis, FanOutTable},
12    logic::Logic,
13};
14use std::{
15    cell::{Ref, RefCell, RefMut},
16    collections::{BTreeMap, BTreeSet, HashMap, HashSet},
17    num::ParseIntError,
18    rc::{Rc, Weak},
19};
20
21/// A trait for indexing into a collection of objects weakly.
22trait WeakIndex<Idx: ?Sized> {
23    /// The output data type which will be referred to weakly
24    type Output: ?Sized;
25    /// Indexes the collection weakly by the given index.
26    fn index_weak(&self, index: &Idx) -> Rc<RefCell<Self::Output>>;
27}
28
29/// A primitive gate in a digital circuit, such as AND, OR, NOT, etc.
30/// VDD and GND are reserved to represent logic one and zero, respectively.
31#[derive(Debug, Clone)]
32#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
33pub struct Gate {
34    /// The name of the primitive
35    name: Identifier,
36    /// Input ports, order matters
37    inputs: Vec<Net>,
38    /// Output ports, order matters
39    outputs: Vec<Net>,
40}
41
42impl Instantiable for Gate {
43    fn get_name(&self) -> &Identifier {
44        &self.name
45    }
46
47    fn get_input_ports(&self) -> impl IntoIterator<Item = &Net> {
48        &self.inputs
49    }
50
51    fn get_output_ports(&self) -> impl IntoIterator<Item = &Net> {
52        &self.outputs
53    }
54
55    fn has_parameter(&self, _id: &Identifier) -> bool {
56        false
57    }
58
59    fn get_parameter(&self, _id: &Identifier) -> Option<Parameter> {
60        None
61    }
62
63    fn set_parameter(&mut self, _id: &Identifier, _val: Parameter) -> Option<Parameter> {
64        None
65    }
66
67    fn parameters(&self) -> impl Iterator<Item = (Identifier, Parameter)> {
68        std::iter::empty()
69    }
70
71    fn from_constant(val: Logic) -> Option<Self> {
72        match val {
73            Logic::True => Some(Gate::new_logical("VDD".into(), vec![], "Y".into())),
74            Logic::False => Some(Gate::new_logical("GND".into(), vec![], "Y".into())),
75            _ => None,
76        }
77    }
78
79    fn get_constant(&self) -> Option<Logic> {
80        match self.name.to_string().as_str() {
81            "VDD" => Some(Logic::True),
82            "GND" => Some(Logic::False),
83            _ => None,
84        }
85    }
86
87    fn is_seq(&self) -> bool {
88        false
89    }
90}
91
92impl Gate {
93    /// Creates a new gate primitive with four-state logic types
94    pub fn new_logical(name: Identifier, inputs: Vec<Identifier>, output: Identifier) -> Self {
95        if name.is_sliced() {
96            panic!("Attempted to create a gate with a sliced identifier: {name}");
97        }
98
99        let outputs = vec![Net::new_logic(output)];
100        let inputs = inputs.into_iter().map(Net::new_logic).collect::<Vec<_>>();
101        Self {
102            name,
103            inputs,
104            outputs,
105        }
106    }
107
108    /// Creates a new gate primitive with four-state logic types with multiple outputs
109    pub fn new_logical_multi(
110        name: Identifier,
111        inputs: Vec<Identifier>,
112        outputs: Vec<Identifier>,
113    ) -> Self {
114        if name.is_sliced() {
115            panic!("Attempted to create a gate with a sliced identifier: {name}");
116        }
117
118        let outputs = outputs.into_iter().map(Net::new_logic).collect::<Vec<_>>();
119        let inputs = inputs.into_iter().map(Net::new_logic).collect::<Vec<_>>();
120        Self {
121            name,
122            inputs,
123            outputs,
124        }
125    }
126
127    /// Returns the single output port of the gate
128    pub fn get_single_output_port(&self) -> &Net {
129        if self.outputs.len() > 1 {
130            panic!("Attempted to grab output port of a multi-output gate");
131        }
132        self.outputs
133            .first()
134            .expect("Gate is missing an output port")
135    }
136
137    /// Set the type of cell by name
138    pub fn set_gate_name(&mut self, new_name: Identifier) {
139        self.name = new_name;
140    }
141
142    /// Returns the name of the gate primitive
143    pub fn get_gate_name(&self) -> &Identifier {
144        &self.name
145    }
146}
147
148/// An operand to an [Instantiable]
149#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
150#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
151enum Operand {
152    /// An index into the list of objects
153    DirectIndex(usize),
154    /// An index into the list of objects, with an extra index on the cell/primitive
155    CellIndex(usize, usize),
156}
157
158impl Ord for Operand {
159    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
160        match (self, other) {
161            (Operand::DirectIndex(a), Operand::DirectIndex(b)) => a.cmp(b),
162            (Operand::CellIndex(a, b), Operand::CellIndex(c, d)) => (a, b).cmp(&(c, d)),
163            (Operand::DirectIndex(a), Operand::CellIndex(c, d)) => {
164                if a == c && *d == 0 {
165                    std::cmp::Ordering::Less
166                } else {
167                    (a, &0).cmp(&(c, d))
168                }
169            }
170            (Operand::CellIndex(a, b), Operand::DirectIndex(c)) => {
171                if a == c && *b == 0 {
172                    std::cmp::Ordering::Greater
173                } else {
174                    (a, b).cmp(&(c, &0))
175                }
176            }
177        }
178    }
179}
180
181impl PartialOrd for Operand {
182    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
183        Some(self.cmp(other))
184    }
185}
186
187impl Operand {
188    /// Remap the node index of the operand to `x`.
189    fn remap(self, x: usize) -> Self {
190        match self {
191            Operand::DirectIndex(_idx) => Operand::DirectIndex(x),
192            Operand::CellIndex(_idx, j) => Operand::CellIndex(x, j),
193        }
194    }
195
196    /// Returns the circuit node index
197    fn root(&self) -> usize {
198        match self {
199            Operand::DirectIndex(idx) => *idx,
200            Operand::CellIndex(idx, _) => *idx,
201        }
202    }
203
204    /// Returns the secondary index (the cell index)
205    fn secondary(&self) -> usize {
206        match self {
207            Operand::DirectIndex(_) => 0,
208            Operand::CellIndex(_, j) => *j,
209        }
210    }
211}
212
213impl std::fmt::Display for Operand {
214    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
215        match self {
216            Operand::DirectIndex(idx) => write!(f, "{idx}"),
217            Operand::CellIndex(idx, j) => write!(f, "{idx}.{j}"),
218        }
219    }
220}
221
222impl std::str::FromStr for Operand {
223    type Err = ParseIntError;
224
225    fn from_str(s: &str) -> Result<Self, Self::Err> {
226        match s.split_once('.') {
227            Some((idx, j)) => {
228                let idx = idx.parse::<usize>()?;
229                let j = j.parse::<usize>()?;
230                Ok(Operand::CellIndex(idx, j))
231            }
232            None => {
233                let idx = s.parse::<usize>()?;
234                Ok(Operand::DirectIndex(idx))
235            }
236        }
237    }
238}
239
240/// An object that has a reference to its owning netlist/module
241#[derive(Debug)]
242struct OwnedObject<I, O>
243where
244    I: Instantiable,
245    O: WeakIndex<usize, Output = Self>,
246{
247    /// The object that is owned by the netlist
248    object: Object<I>,
249    /// The weak reference to the owner netlist/module
250    owner: Weak<O>,
251    /// The list of operands for the object
252    operands: Vec<Option<Operand>>,
253    /// A collection of attributes for the object
254    attributes: BTreeMap<AttributeKey, AttributeValue>,
255    /// The index of the object within the netlist/module
256    index: usize,
257}
258
259impl<I, O> OwnedObject<I, O>
260where
261    I: Instantiable,
262    O: WeakIndex<usize, Output = Self>,
263{
264    /// Get an iterator to mutate the operand indices
265    fn inds_mut(&mut self) -> impl Iterator<Item = &mut Operand> {
266        self.operands
267            .iter_mut()
268            .filter_map(|operand| operand.as_mut())
269    }
270
271    /// Get the driver to input `index`
272    fn get_driver(&self, index: usize) -> Option<Rc<RefCell<Self>>> {
273        self.operands[index].as_ref().map(|operand| {
274            self.owner
275                .upgrade()
276                .expect("Object is unlinked from netlist")
277                .index_weak(&operand.root())
278        })
279    }
280
281    /// Iterator to driving objects
282    fn drivers(&self) -> impl Iterator<Item = Option<Rc<RefCell<Self>>>> {
283        self.operands.iter().map(|operand| {
284            operand.as_ref().map(|operand| {
285                self.owner
286                    .upgrade()
287                    .expect("Object is unlinked from netlist")
288                    .index_weak(&operand.root())
289            })
290        })
291    }
292
293    /// Iterator to driving nets
294    fn driver_nets(&self) -> impl Iterator<Item = Option<Net>> {
295        self.operands.iter().map(|operand| {
296            operand.as_ref().map(|operand| match operand {
297                Operand::DirectIndex(idx) => self
298                    .owner
299                    .upgrade()
300                    .expect("Object is unlinked from netlist")
301                    .index_weak(idx)
302                    .borrow()
303                    .as_net()
304                    .clone(),
305                Operand::CellIndex(idx, j) => self
306                    .owner
307                    .upgrade()
308                    .expect("Object is unlinked from netlist")
309                    .index_weak(idx)
310                    .borrow()
311                    .get_net(*j)
312                    .clone(),
313            })
314        })
315    }
316
317    /// Get the underlying object
318    fn get(&self) -> &Object<I> {
319        &self.object
320    }
321
322    /// Get the underlying object mutably
323    fn get_mut(&mut self) -> &mut Object<I> {
324        &mut self.object
325    }
326
327    /// Get the index of `self` relative to the owning module
328    fn get_index(&self) -> usize {
329        self.index
330    }
331
332    /// Get the net that is driven by this object
333    fn as_net(&self) -> &Net {
334        match &self.object {
335            Object::Input(net) => net,
336            Object::Instance(nets, _, _) => {
337                if nets.len() > 1 {
338                    panic!("Attempt to grab the net of a multi-output instance");
339                } else {
340                    nets.first().expect("Instance is missing a net to drive")
341                }
342            }
343        }
344    }
345
346    /// Get the net that is driven by this object
347    fn as_net_mut(&mut self) -> &mut Net {
348        match &mut self.object {
349            Object::Input(net) => net,
350            Object::Instance(nets, _, _) => {
351                if nets.len() > 1 {
352                    panic!("Attempt to grab the net of a multi-output instance");
353                } else {
354                    nets.first_mut()
355                        .expect("Instance is missing a net to drive")
356                }
357            }
358        }
359    }
360
361    /// Get the net that is driven by this object at position `idx`
362    fn get_net(&self, idx: usize) -> &Net {
363        match &self.object {
364            Object::Input(net) => {
365                if idx != 0 {
366                    panic!("Nonzero index on an input object");
367                }
368                net
369            }
370            Object::Instance(nets, _, _) => &nets[idx],
371        }
372    }
373
374    /// Get a mutable reference to the net that is driven by this object at position `idx`
375    fn get_net_mut(&mut self, idx: usize) -> &mut Net {
376        match &mut self.object {
377            Object::Input(net) => {
378                if idx != 0 {
379                    panic!("Nonzero index on an input object");
380                }
381                net
382            }
383            Object::Instance(nets, _, _) => &mut nets[idx],
384        }
385    }
386
387    /// Check if this object drives a specific net
388    fn find_net(&self, net: &Net) -> Option<usize> {
389        match &self.object {
390            Object::Input(input_net) => {
391                if input_net == net {
392                    Some(0)
393                } else {
394                    None
395                }
396            }
397            Object::Instance(nets, _, _) => nets.iter().position(|n| n == net),
398        }
399    }
400
401    /// Attempt to find a mutable reference to a net within this object
402    fn find_net_mut(&mut self, net: &Net) -> Option<&mut Net> {
403        match &mut self.object {
404            Object::Input(input_net) => {
405                if input_net == net {
406                    Some(input_net)
407                } else {
408                    None
409                }
410            }
411            Object::Instance(nets, _, _) => nets.iter_mut().find(|n| *n == net),
412        }
413    }
414
415    /// Get driving net using the weak reference
416    ///
417    /// # Panics
418    ///
419    /// Panics if the reference to the netlist is lost.
420    fn get_driver_net(&self, index: usize) -> Option<Net> {
421        let operand = &self.operands[index];
422        match operand {
423            Some(op) => match op {
424                Operand::DirectIndex(idx) => self
425                    .owner
426                    .upgrade()
427                    .expect("Object is unlinked from netlist")
428                    .index_weak(idx)
429                    .borrow()
430                    .as_net()
431                    .clone()
432                    .into(),
433                Operand::CellIndex(idx, j) => self
434                    .owner
435                    .upgrade()
436                    .expect("Object is unlinked from netlist")
437                    .index_weak(idx)
438                    .borrow()
439                    .get_net(*j)
440                    .clone()
441                    .into(),
442            },
443            None => None,
444        }
445    }
446
447    fn clear_attribute(&mut self, k: &AttributeKey) -> Option<AttributeValue> {
448        self.attributes.remove(k)
449    }
450
451    fn set_attribute(&mut self, k: AttributeKey) {
452        self.attributes.insert(k, None);
453    }
454
455    fn insert_attribute(&mut self, k: AttributeKey, v: String) -> Option<AttributeValue> {
456        self.attributes.insert(k, Some(v))
457    }
458
459    fn attributes(&self) -> impl Iterator<Item = Attribute> {
460        Attribute::from_pairs(self.attributes.clone().into_iter())
461    }
462}
463
464/// This type exposes the interior mutability of elements in a netlist.
465type NetRefT<I> = Rc<RefCell<OwnedObject<I, Netlist<I>>>>;
466
467/// Provides an idiomatic interface
468/// to the interior mutability of the netlist
469#[derive(Clone)]
470pub struct NetRef<I>
471where
472    I: Instantiable,
473{
474    netref: NetRefT<I>,
475}
476
477impl<I> std::fmt::Debug for NetRef<I>
478where
479    I: Instantiable,
480{
481    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
482        let b = self.netref.borrow();
483        let o = b.get();
484        let i = b.index;
485        let owner = &b.owner;
486        match owner.upgrade() {
487            Some(owner) => {
488                let n = owner.get_name();
489                write!(f, "{{ owner: \"{n}\", index: {i}, val: \"{o}\" }}")
490            }
491            None => write!(f, "{{ owner: None, index: {i}, val: \"{o}\" }}"),
492        }
493    }
494}
495
496impl<I> PartialEq for NetRef<I>
497where
498    I: Instantiable,
499{
500    fn eq(&self, other: &Self) -> bool {
501        Rc::ptr_eq(&self.netref, &other.netref)
502    }
503}
504
505impl<I> Eq for NetRef<I> where I: Instantiable {}
506
507impl<I> Ord for NetRef<I>
508where
509    I: Instantiable,
510{
511    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
512        Rc::as_ptr(&self.netref).cmp(&Rc::as_ptr(&other.netref))
513    }
514}
515
516impl<I> PartialOrd for NetRef<I>
517where
518    I: Instantiable,
519{
520    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
521        Some(self.cmp(other))
522    }
523}
524
525impl<I> std::hash::Hash for NetRef<I>
526where
527    I: Instantiable,
528{
529    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
530        Rc::as_ptr(&self.netref).hash(state);
531    }
532}
533
534impl<I> NetRef<I>
535where
536    I: Instantiable,
537{
538    /// Creates a new [NetRef] from a [NetRefT]
539    fn wrap(netref: NetRefT<I>) -> Self {
540        Self { netref }
541    }
542
543    /// Returns the underlying [NetRefT]
544    fn unwrap(self) -> NetRefT<I> {
545        self.netref
546    }
547
548    /// Returns a borrow to the [Net] at this circuit node.
549    ///
550    /// # Panics
551    ///
552    /// Panics if the circuit node has multiple outputs.
553    pub fn as_net(&self) -> Ref<'_, Net> {
554        Ref::map(self.netref.borrow(), |f| f.as_net())
555    }
556
557    /// Returns a mutable borrow to the [Net] at this circuit node.
558    ///
559    /// # Panics
560    ///
561    /// Panics if the circuit node has multiple outputs.
562    pub fn as_net_mut(&self) -> RefMut<'_, Net> {
563        RefMut::map(self.netref.borrow_mut(), |f| f.as_net_mut())
564    }
565
566    /// Returns a borrow to the output [Net] as position `idx`
567    pub fn get_net(&self, idx: usize) -> Ref<'_, Net> {
568        Ref::map(self.netref.borrow(), |f| f.get_net(idx))
569    }
570
571    /// Returns a mutable borrow to the output [Net] as position `idx`
572    pub fn get_net_mut(&self, idx: usize) -> RefMut<'_, Net> {
573        RefMut::map(self.netref.borrow_mut(), |f| f.get_net_mut(idx))
574    }
575
576    /// Returns a borrow to the output [Net] as position `idx`
577    pub fn get_output(&self, idx: usize) -> DrivenNet<I> {
578        DrivenNet::new(idx, self.clone())
579    }
580
581    /// Returns a borrow to the output connected to port `id`
582    pub fn find_output(&self, id: &Identifier) -> Option<DrivenNet<I>> {
583        let ind = self.get_instance_type()?.find_output(id)?;
584        Some(self.get_output(ind))
585    }
586
587    /// Returns an abstraction around the input connection
588    pub fn get_input(&self, idx: usize) -> InputPort<I> {
589        if self.is_an_input() {
590            panic!("Principal inputs do not have inputs");
591        }
592        InputPort::new(idx, self.clone())
593    }
594
595    /// Returns a borrow to the input port with name `id`
596    pub fn find_input(&self, id: &Identifier) -> Option<InputPort<I>> {
597        let ind = self.get_instance_type()?.find_input(id)?;
598        Some(self.get_input(ind))
599    }
600
601    /// Returns the name of the net at this circuit node.
602    ///
603    /// # Panics
604    ///
605    /// Panics if the circuit node has multiple outputs.
606    pub fn get_identifier(&self) -> Identifier {
607        self.as_net().get_identifier().clone()
608    }
609
610    /// Changes the identifier of the net at this circuit node.
611    ///
612    /// # Panics
613    ///
614    /// Panics if the circuit node has multiple outputs.
615    pub fn set_identifier(&self, identifier: Identifier) {
616        self.as_net_mut().set_identifier(identifier)
617    }
618
619    /// Returns `true` if this circuit node is a principal input
620    pub fn is_an_input(&self) -> bool {
621        matches!(self.netref.borrow().get(), Object::Input(_))
622    }
623
624    /// Returns a reference to the object at this node.
625    pub fn get_obj(&self) -> Ref<'_, Object<I>> {
626        Ref::map(self.netref.borrow(), |f| f.get())
627    }
628
629    /// Returns the [Instantiable] type of the instance, if this circuit node is an instance
630    pub fn get_instance_type(&self) -> Option<Ref<'_, I>> {
631        Ref::filter_map(self.netref.borrow(), |f| f.get().get_instance_type()).ok()
632    }
633
634    /// Returns the [Instantiable] type of the instance, if this circuit node is an instance
635    pub fn get_instance_type_mut(&self) -> Option<RefMut<'_, I>> {
636        RefMut::filter_map(self.netref.borrow_mut(), |f| {
637            f.get_mut().get_instance_type_mut()
638        })
639        .ok()
640    }
641
642    /// Returns a copy of the name of the instance, if the circuit node is a instance.
643    pub fn get_instance_name(&self) -> Option<Identifier> {
644        match self.netref.borrow().get() {
645            Object::Instance(_, inst_name, _) => Some(inst_name.clone()),
646            _ => None,
647        }
648    }
649
650    /// Updates the name of the instance, if the circuit node is an instance.
651    ///
652    /// # Panics
653    ///
654    /// Panics if the circuit node is a principal input.
655    pub fn set_instance_name(&self, name: Identifier) {
656        match self.netref.borrow_mut().get_mut() {
657            Object::Instance(_, inst_name, _) => *inst_name = name,
658            _ => panic!("Attempted to set instance name on a non-instance object"),
659        }
660    }
661
662    /// Exposes this circuit node as a top-level output in the netlist.
663    /// Returns an error if the circuit node is a principal input.
664    ///
665    /// # Panics
666    ///
667    /// Panics if cell is a multi-output circuit node.
668    /// Panics if the reference to the netlist is lost.
669    pub fn expose_as_output(self) -> Result<Self, Error> {
670        let netlist = self
671            .netref
672            .borrow()
673            .owner
674            .upgrade()
675            .expect("NetRef is unlinked from netlist");
676        netlist.expose_net(self.clone().into())?;
677        Ok(self)
678    }
679
680    /// Exposes this circuit node as a top-level output in the netlist with a specific port name.
681    /// Multiple calls to this method can be used to create multiple output aliases for the same net.
682    ///
683    /// # Panics
684    ///
685    /// Panics if the cell is a multi-output circuit node.
686    /// Panics if the reference to the netlist is lost.
687    pub fn expose_with_name(self, name: Identifier) -> Self {
688        let netlist = self
689            .netref
690            .borrow()
691            .owner
692            .upgrade()
693            .expect("NetRef is unlinked from netlist");
694        netlist.expose_net_with_name(self.clone().into(), name);
695        self
696    }
697
698    /// Exposes the `net` driven by this circuit node as a top-level output.
699    /// Errors if `net` is not driven by this circuit node.
700    ///
701    /// # Panics
702    /// Panics if the reference to the netlist is lost.
703    pub fn expose_net(&self, net: &Net) -> Result<(), Error> {
704        let netlist = self
705            .netref
706            .borrow()
707            .owner
708            .upgrade()
709            .expect("NetRef is unlinked from netlist");
710        let net_index = self
711            .netref
712            .borrow()
713            .find_net(net)
714            .ok_or(Error::NetNotFound(net.clone()))?;
715        let dr = DrivenNet::new(net_index, self.clone());
716        netlist.expose_net(dr)?;
717        Ok(())
718    }
719
720    /// Removes a specific output alias by its name from this circuit node.
721    /// Returns true if the output was removed, false if it didn't exist.
722    ///
723    /// # Panics
724    ///
725    /// Panics if cell is a multi-output circuit node.
726    /// Panics if the reference to the netlist is lost.
727    pub fn remove_output(&self, net_name: &Identifier) -> bool {
728        let netlist = self
729            .netref
730            .borrow()
731            .owner
732            .upgrade()
733            .expect("NetRef is unlinked from netlist");
734        netlist.remove_output(&self.into(), net_name)
735    }
736
737    /// Removes all output aliases for this circuit node.
738    /// Returns the number of outputs that were removed.
739    ///
740    /// # Panics
741    ///
742    /// Panics if cell is a multi-output circuit node.
743    /// Panics if the reference to the netlist is lost.
744    pub fn remove_all_outputs(&self) -> usize {
745        let netlist = self
746            .netref
747            .borrow()
748            .owner
749            .upgrade()
750            .expect("NetRef is unlinked from netlist");
751        netlist.remove_outputs(&self.into())
752    }
753
754    /// Returns the circuit node that drives the `index`th input
755    pub fn get_driver(&self, index: usize) -> Option<Self> {
756        self.netref.borrow().get_driver(index).map(NetRef::wrap)
757    }
758
759    /// Returns the net that drives the `index`th input
760    ///
761    /// # Panics
762    ///
763    /// Panics if the reference to the netlist is lost.
764    pub fn get_driver_net(&self, index: usize) -> Option<Net> {
765        self.netref.borrow().get_driver_net(index)
766    }
767
768    /// Returns a request to mutably borrow the operand net
769    /// This requires another borrow in the form of [MutBorrowReq]
770    ///
771    /// # Panics
772    ///
773    /// Panics if the reference to the netlist is lost.
774    pub fn req_driver_net(&self, index: usize) -> Option<MutBorrowReq<I>> {
775        let net = self.get_driver_net(index)?;
776        let operand = self.get_driver(index).unwrap();
777        Some(MutBorrowReq::new(operand, net))
778    }
779
780    /// Returns the number of input ports for this circuit node.
781    pub fn get_num_input_ports(&self) -> usize {
782        if let Some(inst_type) = self.get_instance_type() {
783            inst_type.get_input_ports().into_iter().count()
784        } else {
785            0
786        }
787    }
788
789    /// Returns `true` if this circuit node has all its input ports connected.
790    pub fn is_fully_connected(&self) -> bool {
791        assert_eq!(
792            self.netref.borrow().operands.len(),
793            self.get_num_input_ports()
794        );
795        self.netref.borrow().operands.iter().all(|o| o.is_some())
796    }
797
798    /// Returns an iterator to the driving circuit nodes.
799    pub fn drivers(&self) -> impl Iterator<Item = Option<Self>> {
800        let drivers: Vec<Option<Self>> = self
801            .netref
802            .borrow()
803            .drivers()
804            .map(|o| o.map(NetRef::wrap))
805            .collect();
806        drivers.into_iter()
807    }
808
809    /// Returns an interator to the driving nets.
810    pub fn driver_nets(&self) -> impl Iterator<Item = Option<Net>> {
811        let vec: Vec<Option<Net>> = self.netref.borrow().driver_nets().collect();
812        vec.into_iter()
813    }
814
815    /// Returns an iterator to the output nets of this circuit node.
816    #[allow(clippy::unnecessary_to_owned)]
817    pub fn nets(&self) -> impl Iterator<Item = Net> {
818        self.netref.borrow().get().get_nets().to_vec().into_iter()
819    }
820
821    /// Returns an iterator to the output nets of this circuit node, along with port information.
822    pub fn inputs(&self) -> impl Iterator<Item = InputPort<I>> {
823        let len = self.netref.borrow().operands.len();
824        (0..len).map(move |i| InputPort::new(i, self.clone()))
825    }
826
827    /// Returns an iterator to the output nets of this circuit node, along with port information.
828    pub fn outputs(&self) -> impl Iterator<Item = DrivenNet<I>> {
829        let len = self.netref.borrow().get().get_nets().len();
830        (0..len).map(move |i| DrivenNet::new(i, self.clone()))
831    }
832
833    /// Returns an iterator to mutate the output nets of this circuit node.
834    pub fn nets_mut(&self) -> impl Iterator<Item = RefMut<'_, Net>> {
835        let nnets = self.netref.borrow().get().get_nets().len();
836        (0..nnets).map(|i| self.get_net_mut(i))
837    }
838
839    /// Returns `true` if this circuit node drives the given net.
840    pub fn drives_net(&self, net: &Net) -> bool {
841        self.netref.borrow().find_net(net).is_some()
842    }
843
844    /// Returns `true` if this circuit node drives a top-level output.
845    ///
846    /// # Panics
847    /// Panics if the weak reference to the netlist is lost.
848    pub fn drives_a_top_output(&self) -> bool {
849        let netlist = self
850            .netref
851            .borrow()
852            .owner
853            .upgrade()
854            .expect("NetRef is unlinked from netlist");
855        netlist.drives_an_output(self.clone())
856    }
857
858    /// Attempts to find a mutable reference to `net` within this circuit node.
859    pub fn find_net_mut(&self, net: &Net) -> Option<RefMut<'_, Net>> {
860        RefMut::filter_map(self.netref.borrow_mut(), |f| f.find_net_mut(net)).ok()
861    }
862
863    /// Returns `true` if this circuit node has multiple outputs/nets.
864    pub fn is_multi_output(&self) -> bool {
865        self.netref.borrow().get().get_nets().len() > 1
866    }
867
868    /// Deletes the uses of this circuit node from the netlist.
869    ///
870    /// # Panics
871    ///
872    /// Panics if the reference to the netlist is lost.
873    pub fn delete_uses(self) -> Result<Object<I>, Error> {
874        let netlist = self
875            .netref
876            .borrow()
877            .owner
878            .upgrade()
879            .expect("NetRef is unlinked from netlist");
880        netlist.delete_net_uses(self)
881    }
882
883    /// Replaces the uses of this circuit node in the netlist with another circuit node.
884    ///
885    /// # See also:
886    /// - [`NetMapper`](rewriter::NetMapper)
887    ///
888    /// # Panics
889    ///
890    /// Panics if either `self` is a multi-output circuit node.
891    /// Panics if the weak reference to the netlist is lost.
892    pub fn replace_uses_with(self, other: &DrivenNet<I>) -> Result<NetRef<I>, Error> {
893        let netlist = self
894            .netref
895            .borrow()
896            .owner
897            .upgrade()
898            .expect("NetRef is unlinked from netlist");
899        netlist
900            .replace_net_uses(self.into(), other)
901            .map(|d| d.unwrap())
902    }
903
904    /// Clears the attribute with the given key on this circuit node.
905    pub fn clear_attribute(&self, k: &AttributeKey) -> Option<AttributeValue> {
906        self.netref.borrow_mut().clear_attribute(k)
907    }
908
909    /// Set an attribute without a value
910    pub fn set_attribute(&self, k: AttributeKey) {
911        self.netref.borrow_mut().set_attribute(k);
912    }
913
914    /// Insert an attribute on this node with a value
915    pub fn insert_attribute(&self, k: AttributeKey, v: String) -> Option<AttributeValue> {
916        self.netref.borrow_mut().insert_attribute(k, v)
917    }
918
919    /// Returns an iterator to the attributes at this circuit node
920    pub fn attributes(&self) -> impl Iterator<Item = Attribute> {
921        let v: Vec<_> = self.netref.borrow().attributes().collect();
922        v.into_iter()
923    }
924}
925
926impl<I> std::fmt::Display for NetRef<I>
927where
928    I: Instantiable,
929{
930    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
931        self.netref.borrow().object.fmt(f)
932    }
933}
934
935impl<I> From<NetRef<I>> for DrivenNet<I>
936where
937    I: Instantiable,
938{
939    fn from(val: NetRef<I>) -> Self {
940        if val.is_multi_output() {
941            panic!("Cannot convert a multi-output netref to an output port");
942        }
943        DrivenNet::new(0, val)
944    }
945}
946
947impl<I> From<&NetRef<I>> for DrivenNet<I>
948where
949    I: Instantiable,
950{
951    fn from(val: &NetRef<I>) -> Self {
952        if val.is_multi_output() {
953            panic!("Cannot convert a multi-output netref to an output port");
954        }
955        DrivenNet::new(0, val.clone())
956    }
957}
958
959/// Facilitates mutable borrows to driver nets
960pub struct MutBorrowReq<I: Instantiable> {
961    from: NetRef<I>,
962    ind: Net,
963}
964
965impl<I> MutBorrowReq<I>
966where
967    I: Instantiable,
968{
969    /// Creates a new mutable borrow request
970    fn new(from: NetRef<I>, ind: Net) -> Self {
971        Self { from, ind }
972    }
973
974    /// Mutably borrows the requested net from the circuit node
975    pub fn borrow_mut(&self) -> RefMut<'_, Net> {
976        self.from.find_net_mut(&self.ind).unwrap()
977    }
978
979    /// Returns `true` if the circuit node is an input
980    pub fn is_an_input(&self) -> bool {
981        self.from.is_an_input()
982    }
983
984    /// Attempts to borrow the net mutably if the condition `f` is satisfied.
985    pub fn borrow_mut_if(&self, f: impl Fn(&NetRef<I>) -> bool) -> Option<RefMut<'_, Net>> {
986        if f(&self.from) {
987            Some(self.borrow_mut())
988        } else {
989            None
990        }
991    }
992}
993
994/// A netlist data structure
995#[derive(Debug)]
996pub struct Netlist<I>
997where
998    I: Instantiable,
999{
1000    /// The name of the netlist
1001    name: RefCell<String>,
1002    /// The list of objects in the netlist, such as inputs, modules, and primitives
1003    objects: RefCell<Vec<NetRefT<I>>>,
1004    /// Each operand can map to multiple nets, supporting output aliases.
1005    outputs: RefCell<BTreeMap<Operand, BTreeSet<Net>>>,
1006}
1007
1008/// Represent the input port of a primitive
1009#[derive(Debug, Clone)]
1010pub struct InputPort<I: Instantiable> {
1011    pos: usize,
1012    netref: NetRef<I>,
1013}
1014
1015impl<I> InputPort<I>
1016where
1017    I: Instantiable,
1018{
1019    fn new(pos: usize, netref: NetRef<I>) -> Self {
1020        if pos >= netref.clone().unwrap().borrow().operands.len() {
1021            panic!(
1022                "Position {} out of bounds for netref with {} input nets",
1023                pos,
1024                netref.unwrap().borrow().get().get_nets().len()
1025            );
1026        }
1027        Self { pos, netref }
1028    }
1029
1030    /// Returns the net that is driving this input port
1031    pub fn get_driver(&self) -> Option<DrivenNet<I>> {
1032        if self.netref.is_an_input() {
1033            panic!("Input port is not driven by a primitive");
1034        }
1035        if let Some(prev_operand) = self.netref.clone().unwrap().borrow().operands[self.pos] {
1036            let netlist = self
1037                .netref
1038                .clone()
1039                .unwrap()
1040                .borrow()
1041                .owner
1042                .upgrade()
1043                .expect("Input port is unlinked from netlist");
1044            let driver_nr = netlist.index_weak(&prev_operand.root());
1045            let nr = NetRef::wrap(driver_nr);
1046            let pos = prev_operand.secondary();
1047            Some(DrivenNet::new(pos, nr))
1048        } else {
1049            None
1050        }
1051    }
1052
1053    /// Disconnects an input port and returns the previous [DrivenNet] if it was connected.
1054    pub fn disconnect(&self) -> Option<DrivenNet<I>> {
1055        let val = self.get_driver();
1056        self.netref.clone().unwrap().borrow_mut().operands[self.pos] = None;
1057        val
1058    }
1059
1060    /// Get the input port associated with this connection
1061    pub fn get_port(&self) -> Net {
1062        if self.netref.is_an_input() {
1063            panic!("Net is not driven by a primitive");
1064        }
1065        self.netref
1066            .get_instance_type()
1067            .unwrap()
1068            .get_input_port(self.pos)
1069            .clone()
1070    }
1071
1072    /// Connects this input port to a driven net.
1073    pub fn connect(self, output: DrivenNet<I>) {
1074        output.connect(self);
1075    }
1076
1077    /// Return the underlying circuit node
1078    pub fn unwrap(self) -> NetRef<I> {
1079        self.netref
1080    }
1081
1082    /// Returns the index associated with this input port
1083    pub fn get_input_num(&self) -> usize {
1084        self.pos
1085    }
1086}
1087
1088impl<I> std::fmt::Display for InputPort<I>
1089where
1090    I: Instantiable,
1091{
1092    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1093        self.get_port().fmt(f)
1094    }
1095}
1096
1097/// Represent a net that is being driven by a [Instantiable]
1098#[derive(Debug, Clone)]
1099pub struct DrivenNet<I: Instantiable> {
1100    pos: usize,
1101    netref: NetRef<I>,
1102}
1103
1104impl<I> DrivenNet<I>
1105where
1106    I: Instantiable,
1107{
1108    fn new(pos: usize, netref: NetRef<I>) -> Self {
1109        if pos >= netref.clone().unwrap().borrow().get().get_nets().len() {
1110            panic!(
1111                "Position {} out of bounds for netref with {} outputted nets",
1112                pos,
1113                netref.unwrap().borrow().get().get_nets().len()
1114            );
1115        }
1116        Self { pos, netref }
1117    }
1118
1119    /// Returns the index that can address this net in the netlist.
1120    fn get_operand(&self) -> Operand {
1121        if self.netref.is_multi_output() {
1122            Operand::CellIndex(self.netref.clone().unwrap().borrow().get_index(), self.pos)
1123        } else {
1124            Operand::DirectIndex(self.netref.clone().unwrap().borrow().get_index())
1125        }
1126    }
1127
1128    /// Borrow the net being driven
1129    pub fn as_net(&self) -> Ref<'_, Net> {
1130        self.netref.get_net(self.pos)
1131    }
1132
1133    /// Get a mutable reference to the net being driven
1134    pub fn as_net_mut(&self) -> RefMut<'_, Net> {
1135        self.netref.get_net_mut(self.pos)
1136    }
1137
1138    /// Returns `true` if this net is a principal input
1139    pub fn is_an_input(&self) -> bool {
1140        self.netref.is_an_input()
1141    }
1142
1143    /// Get the output port associated with this connection
1144    pub fn get_port(&self) -> Net {
1145        if self.netref.is_an_input() {
1146            panic!("Net is not driven by a primitive");
1147        }
1148        self.netref
1149            .get_instance_type()
1150            .unwrap()
1151            .get_output_port(self.pos)
1152            .clone()
1153    }
1154
1155    /// Connects the net driven by this output port to the given input port.
1156    pub fn connect(&self, input: InputPort<I>) {
1157        let operand = self.get_operand();
1158        let index = input.netref.unwrap().borrow().get_index();
1159        let netlist = self
1160            .netref
1161            .clone()
1162            .unwrap()
1163            .borrow()
1164            .owner
1165            .upgrade()
1166            .expect("Output port is unlinked from netlist");
1167        let obj = netlist.index_weak(&index);
1168        obj.borrow_mut().operands[input.pos] = Some(operand);
1169    }
1170
1171    /// Returns `true` if this net is a top-level output in the netlist.
1172    pub fn is_top_level_output(&self) -> bool {
1173        let netlist = self
1174            .netref
1175            .clone()
1176            .unwrap()
1177            .borrow()
1178            .owner
1179            .upgrade()
1180            .expect("DrivenNet is unlinked from netlist");
1181        let outputs = netlist.outputs.borrow();
1182        outputs.contains_key(&self.get_operand())
1183    }
1184
1185    /// Return the underlying circuit node
1186    pub fn unwrap(self) -> NetRef<I> {
1187        self.netref
1188    }
1189
1190    /// Returns a copy of the identifier of the net being driven.
1191    pub fn get_identifier(&self) -> Identifier {
1192        self.as_net().get_identifier().clone()
1193    }
1194
1195    /// Exposes this driven net as a top-level output with a specific port name.
1196    /// Multiple calls to this method can be used to create multiple output aliases for the same net.
1197    ///
1198    /// # Panics
1199    ///
1200    /// Panics if the weak reference to the netlist is dead.
1201    pub fn expose_with_name(self, name: Identifier) -> Self {
1202        let netlist = self
1203            .netref
1204            .clone()
1205            .unwrap()
1206            .borrow()
1207            .owner
1208            .upgrade()
1209            .expect("DrivenNet is unlinked from netlist");
1210        netlist.expose_net_with_name(self.clone(), name);
1211        self
1212    }
1213
1214    /// Removes a specific output alias by its name from this driven net.
1215    /// Returns true if the output was removed, false if it didn't exist.
1216    ///
1217    /// # Panics
1218    ///
1219    /// Panics if the reference to the netlist is lost.
1220    pub fn remove_output(&self, net_name: &Identifier) -> bool {
1221        let netlist = self
1222            .netref
1223            .clone()
1224            .unwrap()
1225            .borrow()
1226            .owner
1227            .upgrade()
1228            .expect("DrivenNet is unlinked from netlist");
1229        netlist.remove_output(self, net_name)
1230    }
1231
1232    /// Removes all output aliases for this driven net.
1233    /// Returns the number of outputs that were removed.
1234    ///
1235    /// # Panics
1236    ///
1237    /// Panics if the reference to the netlist is lost.
1238    pub fn remove_all_outputs(&self) -> usize {
1239        let netlist = self
1240            .netref
1241            .clone()
1242            .unwrap()
1243            .borrow()
1244            .owner
1245            .upgrade()
1246            .expect("DrivenNet is unlinked from netlist");
1247        netlist.remove_outputs(self)
1248    }
1249
1250    /// Returns the output position, if the net is the output of a gate.
1251    pub fn get_output_index(&self) -> Option<usize> {
1252        if self.netref.is_an_input() {
1253            None
1254        } else {
1255            Some(self.pos)
1256        }
1257    }
1258
1259    /// Returns the [Instantiable] type driving this net, if it has a driver.
1260    pub fn get_instance_type(&self) -> Option<Ref<'_, I>> {
1261        self.netref.get_instance_type()
1262    }
1263}
1264
1265impl<I> std::fmt::Display for DrivenNet<I>
1266where
1267    I: Instantiable,
1268{
1269    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1270        self.as_net().fmt(f)
1271    }
1272}
1273
1274impl<I> PartialEq for DrivenNet<I>
1275where
1276    I: Instantiable,
1277{
1278    fn eq(&self, other: &Self) -> bool {
1279        self.netref == other.netref && self.pos == other.pos
1280    }
1281}
1282
1283impl<I> Eq for DrivenNet<I> where I: Instantiable {}
1284
1285impl<I> std::hash::Hash for DrivenNet<I>
1286where
1287    I: Instantiable,
1288{
1289    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1290        self.netref.hash(state);
1291        self.pos.hash(state);
1292    }
1293}
1294
1295impl<I> Ord for DrivenNet<I>
1296where
1297    I: Instantiable,
1298{
1299    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1300        match self.netref.cmp(&other.netref) {
1301            std::cmp::Ordering::Equal => self.pos.cmp(&other.pos),
1302            ord => ord,
1303        }
1304    }
1305}
1306
1307impl<I> PartialOrd for DrivenNet<I>
1308where
1309    I: Instantiable,
1310{
1311    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1312        Some(self.cmp(other))
1313    }
1314}
1315
1316impl<I> WeakIndex<usize> for Netlist<I>
1317where
1318    I: Instantiable,
1319{
1320    type Output = OwnedObject<I, Self>;
1321
1322    fn index_weak(&self, index: &usize) -> Rc<RefCell<Self::Output>> {
1323        self.objects.borrow()[*index].clone()
1324    }
1325}
1326
1327impl<I> Netlist<I>
1328where
1329    I: Instantiable,
1330{
1331    /// Creates a new netlist with the given name
1332    pub fn new(name: String) -> Rc<Self> {
1333        Rc::new(Self {
1334            name: RefCell::new(name),
1335            objects: RefCell::new(Vec::new()),
1336            outputs: RefCell::new(BTreeMap::new()),
1337        })
1338    }
1339
1340    /// Attempts to reclaim the netlist, returning [Some] if successful.
1341    pub fn reclaim(self: Rc<Self>) -> Option<Self> {
1342        Rc::try_unwrap(self).ok()
1343    }
1344
1345    /// Creates a deep clone of the netlist.
1346    pub fn deep_clone(self: &Rc<Self>) -> Rc<Self> {
1347        let dc = Rc::new(Self {
1348            name: self.name.clone(),
1349            objects: RefCell::new(Vec::new()),
1350            outputs: self.outputs.clone(),
1351        });
1352
1353        let objects_linked: Vec<NetRefT<I>> = self
1354            .objects
1355            .borrow()
1356            .iter()
1357            .map(|obj| {
1358                Rc::new(RefCell::new(OwnedObject {
1359                    object: obj.borrow().object.clone(),
1360                    owner: Rc::downgrade(&dc),
1361                    operands: obj.borrow().operands.clone(),
1362                    attributes: obj.borrow().attributes.clone(),
1363                    index: obj.borrow().index,
1364                }))
1365            })
1366            .collect();
1367
1368        *dc.objects.borrow_mut() = objects_linked;
1369
1370        dc
1371    }
1372
1373    /// Use interior mutability to add an object to the netlist. Returns a mutable reference to the created object.
1374    ///
1375    /// # Panics
1376    /// If any of the `operands` do not belong to this netlist.
1377    fn insert_object(
1378        self: &Rc<Self>,
1379        object: Object<I>,
1380        operands: &[DrivenNet<I>],
1381    ) -> Result<NetRef<I>, Error> {
1382        for operand in operands {
1383            self.belongs(&operand.clone().unwrap());
1384        }
1385        let index = self.objects.borrow().len();
1386        let weak = Rc::downgrade(self);
1387        let operands = operands
1388            .iter()
1389            .map(|net| Some(net.get_operand()))
1390            .collect::<Vec<_>>();
1391        let owned_object = Rc::new(RefCell::new(OwnedObject {
1392            object,
1393            owner: weak,
1394            operands,
1395            attributes: BTreeMap::new(),
1396            index,
1397        }));
1398        self.objects.borrow_mut().push(owned_object.clone());
1399        Ok(NetRef::wrap(owned_object))
1400    }
1401
1402    /// Inserts an input net to the netlist
1403    pub fn insert_input(self: &Rc<Self>, net: Net) -> DrivenNet<I> {
1404        let obj = Object::Input(net);
1405        self.insert_object(obj, &[]).unwrap().into()
1406    }
1407
1408    /// Inserts a four-state logic input port to the netlist
1409    pub fn insert_input_logic_bus(self: &Rc<Self>, net: String, bw: usize) -> Vec<DrivenNet<I>> {
1410        Net::new_logic_bus(net, bw)
1411            .into_iter()
1412            .map(|n| self.insert_input(n))
1413            .collect()
1414    }
1415
1416    /// Inserts a gate to the netlist
1417    pub fn insert_gate(
1418        self: &Rc<Self>,
1419        inst_type: I,
1420        inst_name: Identifier,
1421        operands: &[DrivenNet<I>],
1422    ) -> Result<NetRef<I>, Error> {
1423        let nets = inst_type
1424            .get_output_ports()
1425            .into_iter()
1426            .map(|pnet| pnet.with_name(&inst_name + pnet.get_identifier()))
1427            .collect::<Vec<_>>();
1428        let input_count = inst_type.get_input_ports().into_iter().count();
1429        if operands.len() != input_count {
1430            return Err(Error::ArgumentMismatch(input_count, operands.len()));
1431        }
1432        let obj = Object::Instance(nets, inst_name, inst_type);
1433        self.insert_object(obj, operands)
1434    }
1435
1436    /// Use interior mutability to add an object to the netlist. Returns a mutable reference to the created object.
1437    pub fn insert_gate_disconnected(
1438        self: &Rc<Self>,
1439        inst_type: I,
1440        inst_name: Identifier,
1441    ) -> NetRef<I> {
1442        let nets = inst_type
1443            .get_output_ports()
1444            .into_iter()
1445            .map(|pnet| pnet.with_name(&inst_name + pnet.get_identifier()))
1446            .collect::<Vec<_>>();
1447        let object = Object::Instance(nets, inst_name, inst_type);
1448        let index = self.objects.borrow().len();
1449        let weak = Rc::downgrade(self);
1450        let input_count = object
1451            .get_instance_type()
1452            .unwrap()
1453            .get_input_ports()
1454            .into_iter()
1455            .count();
1456        let operands = vec![None; input_count];
1457        let owned_object = Rc::new(RefCell::new(OwnedObject {
1458            object,
1459            owner: weak,
1460            operands,
1461            attributes: BTreeMap::new(),
1462            index,
1463        }));
1464        self.objects.borrow_mut().push(owned_object.clone());
1465        NetRef::wrap(owned_object)
1466    }
1467
1468    /// Inserts a constant [Logic] value to the netlist
1469    pub fn insert_constant(
1470        self: &Rc<Self>,
1471        value: Logic,
1472        inst_name: Identifier,
1473    ) -> Result<DrivenNet<I>, Error> {
1474        let obj = I::from_constant(value).ok_or(Error::InstantiableError(format!(
1475            "Instantiable type does not support constant value {}",
1476            value
1477        )))?;
1478        Ok(self.insert_gate_disconnected(obj, inst_name).into())
1479    }
1480
1481    /// # Panics
1482    ///
1483    /// Panics if `netref` definitely does not belong to this netlist.
1484    fn belongs(&self, netref: &NetRef<I>) {
1485        if let Some(nl) = netref.netref.borrow().owner.upgrade() {
1486            if self.objects.borrow().len() != nl.objects.borrow().len() {
1487                panic!("NetRef does not belong to this netlist");
1488            }
1489
1490            if let Some(p) = self.objects.borrow().first()
1491                && let Some(np) = nl.objects.borrow().first()
1492                && !Rc::ptr_eq(p, np)
1493            {
1494                panic!("NetRef does not belong to this netlist");
1495            }
1496        }
1497
1498        if netref.netref.borrow().index >= self.objects.borrow().len() {
1499            panic!("NetRef does not belong to this netlist");
1500        }
1501    }
1502
1503    /// Returns the driving node at input position `index` for `netref`
1504    ///
1505    /// # Panics
1506    ///
1507    /// Panics if `index` is out of bounds
1508    /// The `netref` does not belong to this netlist
1509    pub fn get_driver(&self, netref: NetRef<I>, index: usize) -> Option<DrivenNet<I>> {
1510        self.belongs(&netref);
1511        let op = netref.unwrap().borrow().operands[index]?;
1512        Some(DrivenNet::new(
1513            op.secondary(),
1514            NetRef::wrap(self.index_weak(&op.root()).clone()),
1515        ))
1516    }
1517
1518    /// Set an added object as a top-level output with a specific name.
1519    /// Multiple calls with different names for the same net will create multiple aliases.
1520    ///
1521    /// # Panics
1522    /// The `net` does not belong to this netlist
1523    pub fn expose_net_with_name(&self, net: DrivenNet<I>, name: Identifier) -> DrivenNet<I> {
1524        self.belongs(&net.clone().unwrap());
1525        let mut outputs = self.outputs.borrow_mut();
1526        let named_net = net.as_net().with_name(name);
1527        outputs
1528            .entry(net.get_operand())
1529            .or_default()
1530            .insert(named_net);
1531        net
1532    }
1533
1534    /// Sets the current net as a top-level output using the current name of the net
1535    ///
1536    /// # Panics
1537    /// The `net` does not belong to this netlist
1538    pub fn expose_net(&self, net: DrivenNet<I>) -> Result<DrivenNet<I>, Error> {
1539        self.belongs(&net.clone().unwrap());
1540        if net.is_an_input() {
1541            return Err(Error::InputNeedsAlias(net.as_net().clone()));
1542        }
1543        let mut outputs = self.outputs.borrow_mut();
1544        outputs
1545            .entry(net.get_operand())
1546            .or_default()
1547            .insert(net.as_net().clone());
1548        Ok(net)
1549    }
1550
1551    /// Removes a specific output alias by its operand and net name.
1552    /// Returns true if the output was removed, false if it didn't exist.
1553    ///
1554    /// # Panics
1555    /// The `operand` does not belong to this netlist
1556    pub fn remove_output(&self, operand: &DrivenNet<I>, net_name: &Identifier) -> bool {
1557        self.belongs(&operand.clone().unwrap());
1558        let mut outputs = self.outputs.borrow_mut();
1559        if let Some(nets) = outputs.get_mut(&operand.get_operand()) {
1560            // Create a net with just the identifier to match for removal
1561            let net_to_remove = Net::new(net_name.clone(), crate::circuit::DataType::logic());
1562            if nets.remove(&net_to_remove) {
1563                // If the set is now empty, remove the operand entirely
1564                if nets.is_empty() {
1565                    outputs.remove(&operand.get_operand());
1566                }
1567                return true;
1568            }
1569        }
1570        false
1571    }
1572
1573    /// Removes all output aliases for a specific operand.
1574    /// Returns the number of outputs that were removed.
1575    pub fn remove_outputs(&self, operand: &DrivenNet<I>) -> usize {
1576        //let mut outputs = self.outputs.borrow_mut();
1577        self.outputs
1578            .borrow_mut()
1579            .remove(&operand.get_operand())
1580            .map(|nets| nets.len())
1581            .unwrap_or(0)
1582    }
1583
1584    /// Removes all outputs from the netlist.
1585    pub fn clear_outputs(&self) {
1586        self.outputs.borrow_mut().clear();
1587    }
1588
1589    /// Unlink a circuit node from the rest of the netlist. Return the object that was being stored.
1590    ///
1591    /// # Panics
1592    /// The `netref` does not belong to this netlist
1593    pub fn delete_net_uses(&self, netref: NetRef<I>) -> Result<Object<I>, Error> {
1594        self.belongs(&netref);
1595        let unwrapped = netref.clone().unwrap();
1596        if Rc::strong_count(&unwrapped) > 3 {
1597            return Err(Error::DanglingReference(netref.nets().collect()));
1598        }
1599        let old_index = unwrapped.borrow().get_index();
1600        let objects = self.objects.borrow();
1601        for oref in objects.iter() {
1602            let operands = &mut oref.borrow_mut().operands;
1603            for operand in operands.iter_mut() {
1604                if let Some(op) = operand {
1605                    match op {
1606                        Operand::DirectIndex(idx) | Operand::CellIndex(idx, _)
1607                            if *idx == old_index =>
1608                        {
1609                            *operand = None;
1610                        }
1611                        _ => (),
1612                    }
1613                }
1614            }
1615        }
1616
1617        let outputs: Vec<Operand> = self
1618            .outputs
1619            .borrow()
1620            .keys()
1621            .filter(|operand| match operand {
1622                Operand::DirectIndex(idx) | Operand::CellIndex(idx, _) => *idx == old_index,
1623            })
1624            .cloned()
1625            .collect();
1626
1627        for operand in outputs {
1628            self.outputs.borrow_mut().remove(&operand);
1629        }
1630
1631        Ok(netref.unwrap().borrow().get().clone())
1632    }
1633
1634    /// Replaces the uses of a circuit node with another circuit node. `of` is returned and unused.
1635    ///
1636    /// # See also:
1637    /// - [`NetMapper`](rewriter::NetMapper)
1638    ///
1639    /// # Panics
1640    /// `of` or `with` do not belong to this netlist
1641    pub fn replace_net_uses(
1642        &self,
1643        of: DrivenNet<I>,
1644        with: &DrivenNet<I>,
1645    ) -> Result<DrivenNet<I>, Error> {
1646        {
1647            self.belongs(&of.clone().unwrap());
1648            self.belongs(&with.clone().unwrap());
1649        }
1650        let unwrapped = of.clone().unwrap().unwrap();
1651        let i = of.get_output_index();
1652        let k = with.get_output_index();
1653
1654        if of.clone().unwrap() == with.clone().unwrap() {
1655            if i == k {
1656                return Ok(of);
1657            }
1658
1659            if Rc::strong_count(&unwrapped) > 4 {
1660                return Err(Error::DanglingReference(of.unwrap().nets().collect()));
1661            }
1662        } else if Rc::strong_count(&unwrapped) > 3 {
1663            return Err(Error::DanglingReference(of.unwrap().nets().collect()));
1664        }
1665
1666        let old_index = of.get_operand();
1667
1668        if let Some(nets) = self.outputs.borrow().get(&old_index)
1669            && nets.contains(&of.as_net())
1670        {
1671            if of.is_an_input() {
1672                return Err(Error::NonuniqueNets(nets.iter().cloned().collect()));
1673            } else {
1674                let id = of.as_net().get_identifier().clone() + "_replaced".into();
1675                of.as_net_mut().set_identifier(id);
1676            }
1677        }
1678
1679        let new_index = with.get_operand();
1680        let objects = self.objects.borrow();
1681        for oref in objects.iter() {
1682            let operands = &mut oref.borrow_mut().operands;
1683            for operand in operands.iter_mut() {
1684                if let Some(op) = operand
1685                    && *op == old_index
1686                {
1687                    *operand = Some(new_index);
1688                }
1689            }
1690        }
1691
1692        // Move all the old outputs to the new key
1693        let outs = self.outputs.borrow_mut().remove(&old_index);
1694        if let Some(outs) = outs {
1695            self.outputs
1696                .borrow_mut()
1697                .entry(new_index)
1698                .or_default()
1699                .extend(outs);
1700        }
1701
1702        Ok(of)
1703    }
1704}
1705
1706impl<I> Netlist<I>
1707where
1708    I: Instantiable,
1709{
1710    /// Returns the name of the netlist module
1711    pub fn get_name(&self) -> Ref<'_, String> {
1712        self.name.borrow()
1713    }
1714
1715    /// Sets the name of the netlist module
1716    /// # Panics
1717    ///
1718    /// Panics if the module name cannot be borrowed mutably.
1719    pub fn set_name(&self, name: String) {
1720        *self.name.borrow_mut() = name;
1721    }
1722
1723    /// Iterates over the input ports of the netlist.
1724    pub fn get_input_ports(&self) -> impl Iterator<Item = Net> {
1725        self.objects().filter_map(|oref| {
1726            if oref.is_an_input() {
1727                Some(oref.as_net().clone())
1728            } else {
1729                None
1730            }
1731        })
1732    }
1733
1734    /// Returns a list of output nets
1735    pub fn get_output_ports(&self) -> Vec<Net> {
1736        self.outputs
1737            .borrow()
1738            .values()
1739            .flat_map(|nets| nets.iter().cloned())
1740            .collect()
1741    }
1742
1743    /// Constructs an analysis of the netlist.
1744    pub fn get_analysis<'a, A: Analysis<'a, I>>(&'a self) -> Result<A, Error> {
1745        A::build(self)
1746    }
1747
1748    /// Finds the first circuit node that drives the `net`. This operation is O(n).
1749    /// This should be unique provided the netlist is well-formed.
1750    pub fn find_net(&self, net: &Net) -> Option<DrivenNet<I>> {
1751        for obj in self.objects() {
1752            for o in obj.outputs() {
1753                if *o.as_net() == *net {
1754                    return Some(o);
1755                }
1756            }
1757        }
1758        None
1759    }
1760
1761    /// Returns a `NetRef` to the first circuit node
1762    pub fn first(&self) -> Option<NetRef<I>> {
1763        self.objects
1764            .borrow()
1765            .first()
1766            .map(|nr| NetRef::wrap(nr.clone()))
1767    }
1768
1769    /// Returns a `NetRef` to the last circuit node
1770    pub fn last(&self) -> Option<NetRef<I>> {
1771        self.objects
1772            .borrow()
1773            .last()
1774            .map(|nr| NetRef::wrap(nr.clone()))
1775    }
1776
1777    /// Returns the number of objects in the netlist (instances + inputs)
1778    pub fn len(&self) -> usize {
1779        self.objects.borrow().len()
1780    }
1781
1782    /// Returns `true` if the netlist contains no objects.
1783    pub fn is_empty(&self) -> bool {
1784        self.objects.borrow().is_empty()
1785    }
1786
1787    /// Returns `true` if an output of `netref` which is driving a module output.
1788    ///
1789    /// # Panics
1790    /// The `netref` does not belong to this netlist
1791    pub fn drives_an_output(&self, netref: NetRef<I>) -> bool {
1792        self.belongs(&netref);
1793        let my_index = netref.unwrap().borrow().get_index();
1794        for key in self.outputs.borrow().keys() {
1795            if key.root() == my_index {
1796                return true;
1797            }
1798        }
1799        false
1800    }
1801
1802    /// Rename nets and instances in the netlist using the provided *injective* function.
1803    /// Returns an error if the function is not injective.
1804    /// # Examples
1805    ///
1806    /// ```
1807    /// use safety_net::format_id;
1808    /// use safety_net::{Gate, GateNetlist};
1809    ///
1810    /// let netlist = GateNetlist::new("example".to_string());
1811    /// let inv = Gate::new_logical("INV".into(), vec!["A".into()], "Y".into());
1812    /// let foo = netlist.insert_input("foo".into());
1813    /// let nr = netlist.insert_gate(inv, "bar".into(), &[foo]).unwrap();
1814    /// nr.expose_with_name("baz".into());
1815    /// netlist.rename_nets(|id, i| format_id!("{}_{}", id, i) ).unwrap();
1816    /// // "bar_Y" -> "bar_Y_0"
1817    /// // "bar" -> "bar_1"
1818    /// ```
1819    pub fn rename_nets<F: Fn(&Identifier, usize) -> Identifier>(&self, f: F) -> Result<(), Error> {
1820        let mut i: usize = 0;
1821        for nr in self.objects() {
1822            if nr.is_an_input() {
1823                continue;
1824            }
1825            for mut net in nr.nets_mut() {
1826                let rename = f(net.get_identifier(), i);
1827                net.set_identifier(rename);
1828                i += 1;
1829            }
1830        }
1831
1832        for nr in self.objects() {
1833            if nr.is_an_input() {
1834                continue;
1835            }
1836
1837            let rename = f(&nr.get_instance_name().unwrap(), i);
1838            nr.set_instance_name(rename);
1839            i += 1;
1840        }
1841
1842        self.verify()
1843    }
1844
1845    /// Retains the [DrivenNet]s in `set`, given they are used. Otherwise, they are cleaned and returned in a `Ok(vec)`.
1846    pub fn retain_once(&self, set: &mut HashSet<DrivenNet<I>>) -> Result<Vec<Object<I>>, Error> {
1847        let mut dead_objs = HashSet::new();
1848        {
1849            let fan_out = self.get_analysis::<FanOutTable<I>>()?;
1850            for obj in self.objects() {
1851                let mut is_dead = true;
1852                for net in obj.outputs() {
1853                    // This should account for outputs
1854                    if fan_out.net_has_uses(&net.as_net()) {
1855                        is_dead = false;
1856                    } else {
1857                        set.remove(&net);
1858                    }
1859                }
1860                if is_dead && !obj.is_an_input() {
1861                    dead_objs.insert(obj.unwrap().borrow().index);
1862                }
1863            }
1864        }
1865
1866        if dead_objs.is_empty() {
1867            return Ok(vec![]);
1868        }
1869
1870        let old_objects = self.objects.take();
1871
1872        // Check no dangling references will be created before mutating
1873        for i in dead_objs.iter() {
1874            let rc = &old_objects[*i];
1875            if Rc::strong_count(rc) > 1 {
1876                self.objects.replace(old_objects.clone());
1877                return Err(Error::DanglingReference(
1878                    rc.borrow().get().get_nets().to_vec(),
1879                ));
1880            }
1881        }
1882
1883        let mut removed = Vec::new();
1884        let mut remap: HashMap<usize, usize> = HashMap::new();
1885        for (old_index, obj) in old_objects.into_iter().enumerate() {
1886            if dead_objs.contains(&old_index) {
1887                removed.push(obj.borrow().get().clone());
1888                continue;
1889            }
1890
1891            let new_index = self.objects.borrow().len();
1892            remap.insert(old_index, new_index);
1893            obj.borrow_mut().index = new_index;
1894            self.objects.borrow_mut().push(obj);
1895        }
1896
1897        for obj in self.objects.borrow().iter() {
1898            for operand in obj.borrow_mut().inds_mut() {
1899                let root = operand.root();
1900                let root = *remap.get(&root).unwrap_or(&root);
1901                *operand = operand.remap(root);
1902            }
1903        }
1904
1905        let pairs: Vec<_> = self.outputs.take().into_iter().collect();
1906        for (operand, net) in pairs {
1907            let root = operand.root();
1908            let root = *remap.get(&root).unwrap_or(&root);
1909            let new_operand = operand.remap(root);
1910            self.outputs.borrow_mut().insert(new_operand, net);
1911        }
1912
1913        Ok(removed)
1914    }
1915
1916    /// Removes unused nodes from the netlist, until it stops changing.
1917    /// Returns `Ok(vec)` of the removed objects.
1918    pub fn clean(&self) -> Result<Vec<Object<I>>, Error> {
1919        let mut removed = Vec::new();
1920        let mut r = self.retain_once(&mut HashSet::new())?;
1921        while !r.is_empty() {
1922            removed.extend(r);
1923            r = self.retain_once(&mut HashSet::new())?;
1924        }
1925        Ok(removed)
1926    }
1927
1928    /// Retains the [DrivenNet]s in `set`, given they are used. Otherwise, they are cleaned and returned in a `Ok(vec)`.
1929    pub fn retain(&self, set: &mut HashSet<DrivenNet<I>>) -> Result<Vec<Object<I>>, Error> {
1930        let mut removed = Vec::new();
1931        let mut r = self.retain_once(set)?;
1932        while !r.is_empty() {
1933            removed.extend(r);
1934            r = self.retain_once(set)?;
1935        }
1936        Ok(removed)
1937    }
1938
1939    /// Returns `true` if all the nets/insts are uniquely named
1940    fn nets_insts_unique(&self) -> Result<(), Error> {
1941        let mut nets = HashSet::new();
1942        let mut stems = HashSet::new();
1943        for net in self {
1944            if !nets.insert(net.clone().take_identifier()) {
1945                return Err(Error::NonuniqueNets(vec![net]));
1946            }
1947            if !stems.insert(net.get_identifier().get_stem().to_string())
1948                && net.get_identifier().get_bit_index().is_none()
1949            {
1950                return Err(Error::NonuniqueNets(vec![net]));
1951            }
1952        }
1953        for inst in self.objects() {
1954            if let Some(name) = inst.get_instance_name()
1955                && !stems.insert(name.get_stem().to_string())
1956            {
1957                return Err(Error::NonuniqueInsts(vec![name]));
1958            }
1959            if let Some(name) = inst.get_instance_name()
1960                && name.get_bit_index().is_some()
1961            {
1962                return Err(Error::InstantiableError(format!(
1963                    "Instance identifier {name} cannot be indexed"
1964                )));
1965            }
1966        }
1967        Ok(())
1968    }
1969
1970    fn connections_type_check(&self) -> Result<(), Error> {
1971        for conn in self.connections() {
1972            let target = *conn.target().get_port().get_type();
1973            let source = *conn.src().as_net().get_type();
1974            if target != source {
1975                return Err(Error::TypeError(conn.src().as_net().clone()));
1976            }
1977        }
1978        Ok(())
1979    }
1980
1981    /// Verifies that a netlist is well-formed.
1982    pub fn verify(&self) -> Result<(), Error> {
1983        if self.outputs.borrow().is_empty() {
1984            return Err(Error::NoOutputs);
1985        }
1986
1987        self.nets_insts_unique()?;
1988        self.connections_type_check()?;
1989
1990        Ok(())
1991    }
1992}
1993
1994/// Represent a driven net alongside its connection to an input port
1995#[derive(Debug, Clone)]
1996pub struct Connection<I: Instantiable> {
1997    driver: DrivenNet<I>,
1998    input: InputPort<I>,
1999}
2000
2001impl<I> Connection<I>
2002where
2003    I: Instantiable,
2004{
2005    fn new(driver: DrivenNet<I>, input: InputPort<I>) -> Self {
2006        Self { driver, input }
2007    }
2008
2009    /// Return the driver of the connection
2010    pub fn src(&self) -> DrivenNet<I> {
2011        self.driver.clone()
2012    }
2013
2014    /// Return the net along the connection
2015    pub fn net(&self) -> Net {
2016        self.driver.as_net().clone()
2017    }
2018
2019    /// Returns the input port of the connection
2020    pub fn target(&self) -> InputPort<I> {
2021        self.input.clone()
2022    }
2023}
2024
2025impl<I> std::fmt::Display for Connection<I>
2026where
2027    I: Instantiable,
2028{
2029    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2030        self.net().fmt(f)
2031    }
2032}
2033
2034/// Strategies for fast batching netlist rewrites
2035pub mod rewriter {
2036    use super::{DrivenNet, Error, Instantiable, NetRef, Netlist, Operand};
2037    use crate::graph::FanOutTable;
2038    use std::collections::HashMap;
2039    use std::rc::Rc;
2040
2041    /// Uses a union-find to batch replacements in a netlist closer to O(n) time.
2042    /// The replacement only considers the uses of a net that existed at the time of creation of [NetMapper].
2043    /// Connections created after the creation of the [NetMapper] will not be replaced.
2044    pub struct NetMapper<'a, I: Instantiable> {
2045        parent: HashMap<DrivenNet<I>, DrivenNet<I>>,
2046        netlist: &'a Netlist<I>,
2047        fanout: FanOutTable<'a, I>,
2048    }
2049
2050    impl<'a, I: Instantiable> NetMapper<'a, I> {
2051        /// Create a new empty mapper.
2052        pub fn new(netlist: &'a Netlist<I>) -> Result<Self, Error> {
2053            Ok(Self {
2054                parent: HashMap::new(),
2055                netlist,
2056                fanout: netlist.get_analysis::<FanOutTable<I>>()?,
2057            })
2058        }
2059
2060        /// Get the final replacement for the net
2061        pub fn find(&self, x: DrivenNet<I>) -> DrivenNet<I> {
2062            let mut root = x;
2063            while let Some(p) = self.parent.get(&root) {
2064                root = p.clone();
2065            }
2066            root
2067        }
2068
2069        /// Add a replacement to the mapper. Returns an error if the replacement creates a cycle.
2070        ///
2071        /// # Panics
2072        /// If `of` was already mapped to `with`
2073        pub fn replace(&mut self, of: DrivenNet<I>, with: DrivenNet<I>) -> DrivenNet<I> {
2074            let of_root = self.find(of.clone());
2075            let with_root = self.find(with);
2076            if of_root == with_root {
2077                panic!("Already mapped by NetMapper: {of}");
2078            }
2079            self.parent.insert(of_root, with_root);
2080            of
2081        }
2082
2083        /// Apply the replacements to the netlist.
2084        /// Returns the nets that were replaced.
2085        pub fn apply(self) -> Result<Vec<DrivenNet<I>>, Error> {
2086            // Build the one-pass map
2087            let mut map: HashMap<Operand, Operand> = HashMap::new();
2088            for k in self.parent.keys().cloned() {
2089                let v = self.find(k.clone());
2090                if k != v {
2091                    map.insert(k.get_operand(), v.get_operand());
2092                }
2093            }
2094
2095            drop(self.parent);
2096
2097            // Check that replacements are all valid
2098            for (of, with) in map.iter() {
2099                let unwrapped = self.netlist.objects.borrow()[of.root()].clone();
2100                let i = of.secondary();
2101                let k = of.secondary();
2102                let nr = NetRef::wrap(unwrapped.clone());
2103
2104                if of.root() == with.root() {
2105                    if i == k {
2106                        continue;
2107                    }
2108
2109                    if Rc::strong_count(&unwrapped) - self.fanout.get_ref_count(&nr) > 4 {
2110                        return Err(Error::DanglingReference(nr.nets().collect()));
2111                    }
2112                } else if Rc::strong_count(&unwrapped) - self.fanout.get_ref_count(&nr) > 3 {
2113                    return Err(Error::DanglingReference(nr.nets().collect()));
2114                }
2115
2116                let old_index = of;
2117                let of = DrivenNet::new(i, nr);
2118
2119                if let Some(nets) = self.netlist.outputs.borrow().get(old_index)
2120                    && nets.contains(&of.as_net())
2121                {
2122                    if of.is_an_input() {
2123                        return Err(Error::NonuniqueNets(nets.iter().cloned().collect()));
2124                    } else {
2125                        let id = of.as_net().get_identifier().clone() + "_replaced".into();
2126                        of.as_net_mut().set_identifier(id);
2127                    }
2128                }
2129            }
2130
2131            let objects = self.netlist.objects.borrow();
2132            for (of, &with) in map.iter() {
2133                let of = DrivenNet::new(of.secondary(), NetRef::wrap(objects[of.root()].clone()));
2134                for u in self.fanout.get_users(&of) {
2135                    let place = u.pos;
2136                    let u = u.unwrap().unwrap();
2137                    let operands = &mut u.borrow_mut().operands;
2138                    operands[place] = Some(with);
2139                }
2140            }
2141
2142            for (of, &with) in map.iter() {
2143                // Move all the old outputs to the new key
2144                let outs = self.netlist.outputs.borrow_mut().remove(of);
2145                if let Some(outs) = outs {
2146                    self.netlist
2147                        .outputs
2148                        .borrow_mut()
2149                        .entry(with)
2150                        .or_default()
2151                        .extend(outs);
2152                }
2153            }
2154
2155            let res: Vec<_> = map
2156                .into_keys()
2157                .map(|operand| {
2158                    DrivenNet::new(
2159                        operand.secondary(),
2160                        NetRef::wrap(self.netlist.objects.borrow()[operand.root()].clone()),
2161                    )
2162                })
2163                .collect();
2164
2165            Ok(res)
2166        }
2167    }
2168}
2169
2170/// A collection of iterators for the netlist
2171pub mod iter {
2172
2173    use super::{
2174        Connection, DrivenNet, InputPort, Instantiable, Net, NetRef, Netlist, Operand, WeakIndex,
2175    };
2176    use std::collections::{HashMap, HashSet};
2177    /// An iterator over the nets in a netlist
2178    pub struct NetIterator<'a, I: Instantiable> {
2179        netlist: &'a Netlist<I>,
2180        index: usize,
2181        subindex: usize,
2182    }
2183
2184    impl<'a, I> NetIterator<'a, I>
2185    where
2186        I: Instantiable,
2187    {
2188        /// Creates a new iterator for the netlist
2189        pub fn new(netlist: &'a Netlist<I>) -> Self {
2190            Self {
2191                netlist,
2192                index: 0,
2193                subindex: 0,
2194            }
2195        }
2196    }
2197
2198    impl<I> Iterator for NetIterator<'_, I>
2199    where
2200        I: Instantiable,
2201    {
2202        type Item = Net;
2203
2204        fn next(&mut self) -> Option<Self::Item> {
2205            while self.index < self.netlist.objects.borrow().len() {
2206                let objects = self.netlist.objects.borrow();
2207                let object = objects[self.index].borrow();
2208                if self.subindex < object.get().get_nets().len() {
2209                    let net = object.get().get_nets()[self.subindex].clone();
2210                    self.subindex += 1;
2211                    return Some(net);
2212                }
2213                self.subindex = 0;
2214                self.index += 1;
2215            }
2216            None
2217        }
2218    }
2219
2220    /// An iterator over the objects in a netlist
2221    pub struct ObjectIterator<'a, I: Instantiable> {
2222        netlist: &'a Netlist<I>,
2223        index: usize,
2224    }
2225
2226    impl<'a, I> ObjectIterator<'a, I>
2227    where
2228        I: Instantiable,
2229    {
2230        /// Creates a new  object iterator for the netlist
2231        pub fn new(netlist: &'a Netlist<I>) -> Self {
2232            Self { netlist, index: 0 }
2233        }
2234    }
2235
2236    impl<I> Iterator for ObjectIterator<'_, I>
2237    where
2238        I: Instantiable,
2239    {
2240        type Item = NetRef<I>;
2241
2242        fn next(&mut self) -> Option<Self::Item> {
2243            if self.index < self.netlist.objects.borrow().len() {
2244                let objects = self.netlist.objects.borrow();
2245                let object = &objects[self.index];
2246                self.index += 1;
2247                return Some(NetRef::wrap(object.clone()));
2248            }
2249            None
2250        }
2251    }
2252
2253    /// An iterator over the connections in a netlist
2254    pub struct ConnectionIterator<'a, I: Instantiable> {
2255        netlist: &'a Netlist<I>,
2256        index: usize,
2257        subindex: usize,
2258    }
2259
2260    impl<'a, I> ConnectionIterator<'a, I>
2261    where
2262        I: Instantiable,
2263    {
2264        /// Create a new connection iterator for the netlist
2265        pub fn new(netlist: &'a Netlist<I>) -> Self {
2266            Self {
2267                netlist,
2268                index: 0,
2269                subindex: 0,
2270            }
2271        }
2272    }
2273
2274    impl<I> Iterator for ConnectionIterator<'_, I>
2275    where
2276        I: Instantiable,
2277    {
2278        type Item = super::Connection<I>;
2279
2280        fn next(&mut self) -> Option<Self::Item> {
2281            while self.index < self.netlist.objects.borrow().len() {
2282                let objects = self.netlist.objects.borrow();
2283                let object = objects[self.index].borrow();
2284                let noperands = object.operands.len();
2285                while self.subindex < noperands {
2286                    if let Some(operand) = &object.operands[self.subindex] {
2287                        let driver = match operand {
2288                            Operand::DirectIndex(idx) => {
2289                                DrivenNet::new(0, NetRef::wrap(objects[*idx].clone()))
2290                            }
2291                            Operand::CellIndex(idx, j) => {
2292                                DrivenNet::new(*j, NetRef::wrap(objects[*idx].clone()))
2293                            }
2294                        };
2295                        let input = InputPort::new(
2296                            self.subindex,
2297                            NetRef::wrap(objects[self.index].clone()),
2298                        );
2299                        self.subindex += 1;
2300                        return Some(Connection::new(driver, input));
2301                    }
2302                    self.subindex += 1;
2303                }
2304                self.subindex = 0;
2305                self.index += 1;
2306            }
2307            None
2308        }
2309    }
2310
2311    /// A stack that can check contains in roughly O(1) time.
2312    #[derive(Clone)]
2313    struct Walk<T: std::hash::Hash + PartialEq + Eq + Clone> {
2314        stack: Vec<T>,
2315        counter: HashMap<T, usize>,
2316    }
2317
2318    impl<T> Walk<T>
2319    where
2320        T: std::hash::Hash + PartialEq + Eq + Clone,
2321    {
2322        /// Create a new, empty Stack.
2323        fn new() -> Self {
2324            Self {
2325                stack: Vec::new(),
2326                counter: HashMap::new(),
2327            }
2328        }
2329
2330        /// Inserts an element into the stack
2331        fn push(&mut self, item: T) {
2332            self.stack.push(item.clone());
2333            *self.counter.entry(item).or_insert(0) += 1;
2334        }
2335
2336        /// Returns true if the stack shows a cycle
2337        fn contains_cycle(&self) -> bool {
2338            self.counter.values().any(|&count| count > 1)
2339        }
2340
2341        /// Returns true if the stack contains a cycle to the root node
2342        fn root_cycle(&self) -> bool {
2343            if self.stack.is_empty() {
2344                return false;
2345            }
2346            self.counter[&self.stack[0]] > 1
2347        }
2348
2349        /// Returns a reference to the last element in the stack
2350        fn last(&self) -> Option<&T> {
2351            self.stack.last()
2352        }
2353    }
2354
2355    /// A depth-first iterator over the circuit nodes in a netlist
2356    /// # Examples
2357    ///
2358    /// ```
2359    /// use safety_net::iter::DFSIterator;
2360    /// use safety_net::GateNetlist;
2361    ///
2362    /// let netlist = GateNetlist::new("example".to_string());
2363    /// netlist.insert_input("input1".into());
2364    /// let mut nodes = Vec::new();
2365    /// let mut dfs = DFSIterator::new(&netlist, netlist.last().unwrap());
2366    /// while let Some(n) = dfs.next() {
2367    ///     if dfs.check_cycles() {
2368    ///         panic!("Cycle detected in the netlist");
2369    ///     }
2370    ///     nodes.push(n);
2371    /// }
2372    /// ```
2373    pub struct DFSIterator<'a, I: Instantiable> {
2374        dfs: NetDFSIterator<'a, I>,
2375        seen: HashSet<NetRef<I>>,
2376    }
2377
2378    impl<'a, I> DFSIterator<'a, I>
2379    where
2380        I: Instantiable,
2381    {
2382        /// Create a new DFS iterator for the netlist starting at `from`.
2383        pub fn new(netlist: &'a Netlist<I>, from: NetRef<I>) -> Self {
2384            Self {
2385                dfs: NetDFSIterator::new(netlist, DrivenNet::new(0, from)),
2386                seen: HashSet::new(),
2387            }
2388        }
2389    }
2390
2391    impl<I> DFSIterator<'_, I>
2392    where
2393        I: Instantiable,
2394    {
2395        /// Check if the DFS traversal has encountered a cycle yet.
2396        pub fn check_cycles(&self) -> bool {
2397            self.dfs.check_cycles()
2398        }
2399
2400        /// Consumes the iterator to detect cycles in the netlist.
2401        pub fn detect_cycles(self) -> bool {
2402            self.dfs.detect_cycles()
2403        }
2404
2405        /// Check if the DFS traversal has encountered the root `from`` again.
2406        pub fn check_self_loop(&self) -> bool {
2407            self.dfs.check_self_loop()
2408        }
2409
2410        /// Consumes the iterator to detect if the DFS traversal will encounter the root `from` again.
2411        pub fn detect_self_loop(self) -> bool {
2412            self.dfs.detect_self_loop()
2413        }
2414    }
2415
2416    impl<I> Iterator for DFSIterator<'_, I>
2417    where
2418        I: Instantiable,
2419    {
2420        type Item = NetRef<I>;
2421
2422        fn next(&mut self) -> Option<Self::Item> {
2423            let d = self.dfs.next()?;
2424            if self.seen.insert(d.clone().unwrap()) {
2425                Some(d.unwrap())
2426            } else {
2427                self.next()
2428            }
2429        }
2430    }
2431
2432    type TermFn<I> = Box<dyn Fn(&DrivenNet<I>) -> bool + 'static>;
2433
2434    /// Depth-first iterator that works like DFSIterator but iterates over DrivenNet
2435    pub struct NetDFSIterator<'a, I: Instantiable> {
2436        netlist: &'a Netlist<I>,
2437        stacks: Vec<Walk<DrivenNet<I>>>,
2438        visited: HashSet<usize>,
2439        visited_net: HashSet<(usize, usize)>,
2440        any_cycle: bool,
2441        root_cycle: bool,
2442        terminate: TermFn<I>,
2443    }
2444
2445    impl<'a, I> NetDFSIterator<'a, I>
2446    where
2447        I: Instantiable,
2448    {
2449        /// Create a new DFS DrivenNet iterator for the netlist starting at `from`, ignoring all dependencies beyond the `terminate` condition.
2450        /// Terminators themselves *are* included in the iteration.
2451        pub fn new_filtered<F: Fn(&DrivenNet<I>) -> bool + 'static>(
2452            netlist: &'a Netlist<I>,
2453            from: DrivenNet<I>,
2454            terminate: F,
2455        ) -> Self {
2456            let mut s = Walk::new();
2457            s.push(from);
2458            Self {
2459                netlist,
2460                stacks: vec![s],
2461                visited: HashSet::new(),
2462                visited_net: HashSet::new(),
2463                any_cycle: false,
2464                root_cycle: false,
2465                terminate: Box::new(terminate),
2466            }
2467        }
2468
2469        /// Create a new DFS DrivenNet iterator for the netlist starting at `from`.
2470        pub fn new(netlist: &'a Netlist<I>, from: DrivenNet<I>) -> Self {
2471            Self::new_filtered(netlist, from, |_| false)
2472        }
2473    }
2474
2475    impl<I> NetDFSIterator<'_, I>
2476    where
2477        I: Instantiable,
2478    {
2479        /// Check if the DFS traversal has encountered a cycle yet.
2480        pub fn check_cycles(&self) -> bool {
2481            self.any_cycle
2482        }
2483
2484        /// Consumes the iterator to detect cycles in the netlist.
2485        pub fn detect_cycles(mut self) -> bool {
2486            if self.any_cycle {
2487                return true;
2488            }
2489
2490            while let Some(_) = self.next() {
2491                if self.any_cycle {
2492                    return true;
2493                }
2494            }
2495
2496            self.any_cycle
2497        }
2498
2499        /// Check if the DFS traversal has encountered the root `from` again.
2500        pub fn check_self_loop(&self) -> bool {
2501            self.root_cycle
2502        }
2503
2504        /// Consumes the iterator to detect if the DFS traversal will encounter the root `from` again.
2505        pub fn detect_self_loop(mut self) -> bool {
2506            if self.root_cycle {
2507                return true;
2508            }
2509
2510            while let Some(_) = self.next() {
2511                if self.root_cycle {
2512                    return true;
2513                }
2514            }
2515
2516            self.root_cycle
2517        }
2518    }
2519
2520    impl<I> Iterator for NetDFSIterator<'_, I>
2521    where
2522        I: Instantiable,
2523    {
2524        type Item = DrivenNet<I>;
2525
2526        fn next(&mut self) -> Option<Self::Item> {
2527            if let Some(walk) = self.stacks.pop() {
2528                self.any_cycle |= walk.contains_cycle();
2529                self.root_cycle |= walk.root_cycle();
2530                let item = walk.last().cloned();
2531                let uw = item.clone().unwrap().unwrap().unwrap();
2532                let index = uw.borrow().get_index();
2533                let secondary = item.as_ref().unwrap().pos;
2534                if self.visited.insert(index) {
2535                    if !(self.terminate)(item.as_ref().unwrap()) {
2536                        let operands = &uw.borrow().operands;
2537                        for operand in operands.iter().flatten() {
2538                            let mut new_walk = walk.clone();
2539                            new_walk.push(DrivenNet::new(
2540                                operand.secondary(),
2541                                NetRef::wrap(self.netlist.index_weak(&operand.root())),
2542                            ));
2543                            self.stacks.push(new_walk);
2544                        }
2545                    }
2546                    self.visited_net.insert((index, secondary));
2547                    return item;
2548                }
2549
2550                if self.visited_net.insert((index, secondary)) {
2551                    return item;
2552                }
2553
2554                return self.next();
2555            }
2556
2557            None
2558        }
2559    }
2560}
2561
2562impl<'a, I> IntoIterator for &'a Netlist<I>
2563where
2564    I: Instantiable,
2565{
2566    type Item = Net;
2567    type IntoIter = iter::NetIterator<'a, I>;
2568
2569    fn into_iter(self) -> Self::IntoIter {
2570        iter::NetIterator::new(self)
2571    }
2572}
2573
2574/// Filter invariants of [Instantiable] in a netlist. Use it like you would `matches!`.
2575/// Example: ```filter_nodes!(netlist, Gate::AND(_));```
2576#[macro_export]
2577macro_rules! filter_nodes {
2578    ($netlist:ident, $pattern:pat $(if $guard:expr)? $(,)?) => {
2579        $netlist.matches(|f| match f {
2580            $pattern $(if $guard)? => true,
2581            _ => false
2582        })
2583    };
2584}
2585
2586impl<I> Netlist<I>
2587where
2588    I: Instantiable,
2589{
2590    /// Returns an iterator over the circuit nodes in the netlist.
2591    pub fn objects(&self) -> impl Iterator<Item = NetRef<I>> {
2592        iter::ObjectIterator::new(self)
2593    }
2594
2595    /// Returns an iterator over the circuit nodes that match the instance type.
2596    pub fn matches<F>(&self, filter: F) -> impl Iterator<Item = NetRef<I>>
2597    where
2598        F: Fn(&I) -> bool,
2599    {
2600        self.objects().filter(move |f| {
2601            if let Some(inst_type) = f.get_instance_type() {
2602                filter(&inst_type)
2603            } else {
2604                false
2605            }
2606        })
2607    }
2608
2609    /// Returns an iterator to principal inputs in the netlist as references.
2610    pub fn inputs(&self) -> impl Iterator<Item = DrivenNet<I>> {
2611        self.objects()
2612            .filter(|n| n.is_an_input())
2613            .map(|n| DrivenNet::new(0, n))
2614    }
2615
2616    /// Returns an iterator to circuit nodes that drive an output in the netlist.
2617    pub fn outputs(&self) -> Vec<(DrivenNet<I>, Net)> {
2618        self.outputs
2619            .borrow()
2620            .iter()
2621            .flat_map(|(k, nets)| {
2622                nets.iter().map(|n| {
2623                    (
2624                        DrivenNet::new(k.secondary(), NetRef::wrap(self.index_weak(&k.root()))),
2625                        n.clone(),
2626                    )
2627                })
2628            })
2629            .collect()
2630    }
2631
2632    /// Returns an iterator over the wire connections in the netlist.
2633    pub fn connections(&self) -> impl Iterator<Item = Connection<I>> {
2634        iter::ConnectionIterator::new(self)
2635    }
2636
2637    /// Returns a depth-first search iterator over the nodes in the netlist.
2638    ///
2639    /// # Panics
2640    /// `from` does not belong to this netlist
2641    pub fn node_dfs(&self, from: NetRef<I>) -> impl Iterator<Item = NetRef<I>> {
2642        self.belongs(&from);
2643        iter::DFSIterator::new(self, from)
2644    }
2645
2646    /// Returns a depth-first search iterator over the nodes in the netlist, with the nodes in DrivenNet form.
2647    ///
2648    /// # Panics
2649    /// `from` does not belong to this netlist
2650    pub fn net_dfs(&self, from: DrivenNet<I>) -> impl Iterator<Item = DrivenNet<I>> {
2651        self.belongs(&from.clone().unwrap());
2652        iter::NetDFSIterator::new(self, from)
2653    }
2654
2655    #[cfg(feature = "serde")]
2656    /// Serializes the netlist to a writer.
2657    pub fn serialize(self, writer: impl std::io::Write) -> Result<(), serde_json::Error>
2658    where
2659        I: ::serde::Serialize,
2660    {
2661        serde::netlist_serialize(self, writer)
2662    }
2663
2664    #[cfg(feature = "graph")]
2665    /// Converts the current configuration of the netlist to a graphviz string
2666    pub fn dot_string(&self) -> Result<String, Error> {
2667        use super::graph::{Edge, MultiDiGraph, Node};
2668        use petgraph::dot::{Config, Dot};
2669        use petgraph::graph::{DiGraph, EdgeReference, NodeIndex};
2670        let analysis = self.get_analysis::<MultiDiGraph<_>>()?;
2671        let graph = analysis.get_graph();
2672
2673        fn node_impl<I: Instantiable>(
2674            _graph: &DiGraph<Node<I, String>, Edge<I, Net>>,
2675            node: (NodeIndex, &Node<I, String>),
2676        ) -> String {
2677            let n = node.1;
2678            let mut attr = String::new();
2679
2680            match n {
2681                Node::NetRef(nr) if nr.get_instance_type().is_some() => attr += "shape=record, ",
2682                _ => attr += "shape=ellipse, ",
2683            }
2684
2685            match n {
2686                Node::NetRef(nr)
2687                    if let Some(inst_type) = nr.get_instance_type()
2688                        && !inst_type.is_driverless() =>
2689                {
2690                    let mut record = "{ { ".to_string();
2691
2692                    let l = nr.get_num_input_ports();
2693                    for (i, port) in nr.inputs().enumerate() {
2694                        let id = port.get_port().get_identifier().clone();
2695                        record += &format!("{{ <{}> {} }}", id, id);
2696
2697                        if i != l - 1 {
2698                            record += " | ";
2699                        }
2700                    }
2701
2702                    record += &format!(
2703                        " }} | {}({}) }}",
2704                        inst_type.get_name(),
2705                        nr.get_instance_name().unwrap()
2706                    );
2707                    attr += &format!("label=\"{record}\"");
2708                }
2709                _ => attr += &format!("label=\"{n}\""),
2710            }
2711
2712            attr
2713        }
2714
2715        fn edge_impl<I: Instantiable>(
2716            _graph: &DiGraph<Node<I, String>, Edge<I, Net>>,
2717            edge: EdgeReference<Edge<I, Net>>,
2718        ) -> String {
2719            match edge.weight() {
2720                Edge::Connection(c) => {
2721                    format!(", port=\"{}\"", c.target().get_port().get_identifier())
2722                }
2723                _ => String::new(),
2724            }
2725        }
2726
2727        let dot = Dot::with_attr_getters(
2728            graph,
2729            &[Config::NodeNoLabel],
2730            &edge_impl::<I>,
2731            &node_impl::<I>,
2732        );
2733
2734        // Post-process to add port specifiers to the edges.
2735        let mut result = String::new();
2736        for line in dot.to_string().lines() {
2737            if line.contains("->") && line.contains("port=") {
2738                let port = line
2739                    .split("port=\"")
2740                    .nth(1)
2741                    .unwrap()
2742                    .split('"')
2743                    .next()
2744                    .unwrap();
2745                let (l, r) = line.split_once("->").unwrap();
2746                let (l, r) = (l, r.trim());
2747                let (d, r) = r.split_once(" ").unwrap();
2748                result += &format!("{l}-> {d}:{port} {r}\n");
2749            } else {
2750                result += line;
2751                result += "\n";
2752            }
2753        }
2754
2755        Ok(result)
2756    }
2757
2758    #[cfg(feature = "graph")]
2759    /// Dumps the current netlist to <module_name>.dot in the current working directory.
2760    pub fn dump_dot(&self) -> std::io::Result<()> {
2761        use std::io::Write;
2762        let mut dir = std::env::current_dir()?;
2763        let mod_name = format!("{}.dot", self.get_name());
2764        dir.push(mod_name);
2765        let mut file = std::fs::File::create(dir)?;
2766        if let Err(e) = self.verify() {
2767            write!(file, "Netlist verification failed: {e}")
2768        } else {
2769            let dot = self.dot_string().unwrap();
2770            write!(file, "{dot}")
2771        }
2772    }
2773}
2774
2775impl<I> std::fmt::Display for Netlist<I>
2776where
2777    I: Instantiable,
2778{
2779    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2780        // Borrow everything first
2781        let objects = self.objects.borrow();
2782        let outputs = self.outputs.borrow();
2783
2784        writeln!(f, "module {} (", self.get_name())?;
2785
2786        // Print inputs and outputs
2787        let mut input_list: BTreeMap<(String, bool), (usize, usize)> = BTreeMap::new();
2788        let mut output_list: BTreeMap<(String, bool), (usize, usize)> = BTreeMap::new();
2789        let mut net_list: BTreeMap<(String, bool), (usize, usize)> = BTreeMap::new();
2790
2791        for oref in objects.iter() {
2792            let owned = oref.borrow();
2793            let obj = owned.get();
2794            if let Object::Input(net) = obj {
2795                let stem = net.get_identifier().get_stem();
2796                let entry = input_list
2797                    .entry((stem.to_string(), net.get_identifier().is_escaped()))
2798                    .or_default();
2799                if let Some(idx) = net.get_identifier().get_bit_index() {
2800                    entry.0 = entry.0.min(idx);
2801                    entry.1 = entry.1.max(idx);
2802                }
2803            }
2804        }
2805
2806        // Flatten the outputs to collect all (operand, net) pairs
2807        let all_outputs: Vec<_> = outputs.values().flat_map(|nets| nets.iter()).collect();
2808        for &net in &all_outputs {
2809            let stem = net.get_identifier().get_stem();
2810            if input_list.contains_key(&(stem.to_string(), net.get_identifier().is_escaped())) {
2811                continue;
2812            }
2813            let entry = output_list
2814                .entry((stem.to_string(), net.get_identifier().is_escaped()))
2815                .or_default();
2816            if let Some(idx) = net.get_identifier().get_bit_index() {
2817                entry.0 = entry.0.min(idx);
2818                entry.1 = entry.1.max(idx);
2819            }
2820        }
2821
2822        let level = 2;
2823        let indent = " ".repeat(level);
2824        for (id, escaped) in input_list.keys() {
2825            write!(f, "{}", indent)?;
2826            if *escaped {
2827                write!(f, "\\")?;
2828            }
2829            write!(f, "{}", id)?;
2830            if *escaped {
2831                write!(f, " ")?;
2832            }
2833            writeln!(f, ",")?;
2834        }
2835
2836        for (i, (id, escaped)) in output_list.keys().enumerate() {
2837            write!(f, "{}", indent)?;
2838            if *escaped {
2839                write!(f, "\\")?;
2840            }
2841            write!(f, "{}", id)?;
2842            if *escaped {
2843                write!(f, " ")?;
2844            }
2845            if i == output_list.len() - 1 {
2846                writeln!(f)?;
2847            } else {
2848                writeln!(f, ",")?;
2849            }
2850        }
2851
2852        writeln!(f, ");")?;
2853
2854        // Make wire decls
2855        let mut already_decl = HashSet::new();
2856        for ((id, escaped), (lsb, msb)) in input_list {
2857            write!(f, "{}input wire ", indent)?;
2858            if lsb != msb {
2859                write!(f, "[{}:{}] ", msb, lsb)?;
2860            }
2861            if escaped {
2862                write!(f, "\\")?;
2863            }
2864            write!(f, "{}", id)?;
2865            if escaped {
2866                write!(f, " ")?;
2867            }
2868            writeln!(f, ";")?;
2869            already_decl.insert(id);
2870        }
2871
2872        for ((id, escaped), (lsb, msb)) in output_list {
2873            write!(f, "{}output wire ", indent)?;
2874            if lsb != msb {
2875                write!(f, "[{}:{}] ", msb, lsb)?;
2876            }
2877            if escaped {
2878                write!(f, "\\")?;
2879            }
2880            write!(f, "{}", id)?;
2881            if escaped {
2882                write!(f, " ")?;
2883            }
2884            writeln!(f, ";")?;
2885            already_decl.insert(id);
2886        }
2887
2888        for oref in objects.iter() {
2889            let owned = oref.borrow();
2890            let obj = owned.get();
2891            if let Object::Instance(nets, _, inst_type) = obj
2892                && inst_type.get_constant().is_none()
2893            {
2894                for net in nets.iter() {
2895                    if already_decl.contains(net.get_identifier().get_stem()) {
2896                        continue;
2897                    }
2898                    let stem = net.get_identifier().get_stem();
2899                    let entry = net_list
2900                        .entry((stem.to_string(), net.get_identifier().is_escaped()))
2901                        .or_default();
2902                    if let Some(idx) = net.get_identifier().get_bit_index() {
2903                        entry.0 = entry.0.min(idx);
2904                        entry.1 = entry.1.max(idx);
2905                    }
2906                }
2907            }
2908        }
2909
2910        for ((id, escaped), (lsb, msb)) in net_list {
2911            write!(f, "{}wire ", indent)?;
2912            if lsb != msb {
2913                write!(f, "[{}:{}] ", msb, lsb)?;
2914            }
2915            if escaped {
2916                write!(f, "\\")?;
2917            }
2918            write!(f, "{}", id)?;
2919            if escaped {
2920                write!(f, " ")?;
2921            }
2922            writeln!(f, ";")?;
2923        }
2924
2925        for oref in objects.iter() {
2926            let owned = oref.borrow();
2927            let obj = owned.get();
2928
2929            // Skip emitting constants as their uses will be hard-wired
2930            if let Some(inst_type) = obj.get_instance_type()
2931                && inst_type.get_constant().is_some()
2932            {
2933                continue;
2934            }
2935
2936            if let Object::Instance(nets, inst_name, inst_type) = obj {
2937                for (k, v) in owned.attributes.iter() {
2938                    if let Some(value) = v {
2939                        writeln!(f, "{indent}(* {k} = \"{value}\" *)")?;
2940                    } else {
2941                        writeln!(f, "{indent}(* {k} *)")?;
2942                    }
2943                }
2944
2945                write!(f, "{}{} ", indent, inst_type.get_name())?;
2946                if inst_type.is_parameterized() {
2947                    writeln!(f, "#(")?;
2948                    let level = 4;
2949                    let indent = " ".repeat(level);
2950                    let params: Vec<_> = inst_type.parameters().collect();
2951                    for (i, (k, v)) in params.iter().enumerate() {
2952                        if i == params.len() - 1 {
2953                            writeln!(f, "{indent}.{k}({v})")?;
2954                        } else {
2955                            writeln!(f, "{indent}.{k}({v}),")?;
2956                        }
2957                    }
2958                    let level = 2;
2959                    let indent = " ".repeat(level);
2960                    write!(f, "{indent}) ")?;
2961                }
2962                writeln!(f, "{} (", inst_name.emit_name())?;
2963                let level = 4;
2964                let indent = " ".repeat(level);
2965                for (idx, port) in inst_type.get_input_ports().into_iter().enumerate() {
2966                    let port_name = port.get_identifier().emit_name();
2967                    if let Some(operand) = owned.operands[idx].as_ref() {
2968                        let operand_net = match operand {
2969                            Operand::DirectIndex(idx) => objects[*idx].borrow().as_net().clone(),
2970                            Operand::CellIndex(idx, j) => {
2971                                objects[*idx].borrow().get_net(*j).clone()
2972                            }
2973                        };
2974
2975                        let operand_str = if let Some(inst_type) =
2976                            objects[operand.root()].borrow().get().get_instance_type()
2977                            && let Some(logic) = inst_type.get_constant()
2978                        {
2979                            logic.to_string()
2980                        } else {
2981                            operand_net.get_identifier().emit_name()
2982                        };
2983
2984                        writeln!(f, "{}.{}({}),", indent, port_name, operand_str)?;
2985                    }
2986                }
2987
2988                for (idx, net) in nets.iter().enumerate() {
2989                    let port_name = inst_type.get_output_port(idx).get_identifier().emit_name();
2990                    if idx == nets.len() - 1 {
2991                        writeln!(
2992                            f,
2993                            "{}.{}({})",
2994                            indent,
2995                            port_name,
2996                            net.get_identifier().emit_name()
2997                        )?;
2998                    } else {
2999                        writeln!(
3000                            f,
3001                            "{}.{}({}),",
3002                            indent,
3003                            port_name,
3004                            net.get_identifier().emit_name()
3005                        )?;
3006                    }
3007                }
3008
3009                let level = 2;
3010                let indent = " ".repeat(level);
3011                writeln!(f, "{indent});")?;
3012            }
3013        }
3014
3015        for (driver, nets) in outputs.iter() {
3016            for net in nets {
3017                let driver_net = match driver {
3018                    Operand::DirectIndex(idx) => self.index_weak(idx).borrow().as_net().clone(),
3019                    Operand::CellIndex(idx, j) => self.index_weak(idx).borrow().get_net(*j).clone(),
3020                };
3021
3022                let driver_str = if let Some(inst_type) = self
3023                    .index_weak(&driver.root())
3024                    .borrow()
3025                    .get()
3026                    .get_instance_type()
3027                    && let Some(logic) = inst_type.get_constant()
3028                {
3029                    logic.to_string()
3030                } else {
3031                    driver_net.get_identifier().emit_name()
3032                };
3033
3034                if net.get_identifier() != driver_net.get_identifier() {
3035                    writeln!(
3036                        f,
3037                        "{}assign {} = {};",
3038                        indent,
3039                        net.get_identifier().emit_name(),
3040                        driver_str
3041                    )?;
3042                }
3043            }
3044        }
3045
3046        writeln!(f, "endmodule")
3047    }
3048}
3049
3050/// A type alias for a netlist of gates
3051pub type GateNetlist = Netlist<Gate>;
3052/// A type alias to Gate circuit nodes
3053pub type GateRef = NetRef<Gate>;
3054
3055#[cfg(test)]
3056mod tests {
3057    use super::iter::{DFSIterator, NetDFSIterator};
3058    use super::*;
3059    #[test]
3060    fn test_delete_netlist() {
3061        let netlist = Netlist::new("simple_example".to_string());
3062
3063        // Add the the two inputs
3064        let input1 = netlist.insert_input("input1".into());
3065        let input2 = netlist.insert_input("input2".into());
3066
3067        // Instantiate an AND gate
3068        let instance = netlist
3069            .insert_gate(
3070                Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into()),
3071                "my_and".into(),
3072                &[input1.clone(), input2.clone()],
3073            )
3074            .unwrap();
3075
3076        // Make this AND gate an output
3077        let instance = instance.expose_as_output().unwrap();
3078        instance.delete_uses().unwrap();
3079        // We can still clean this mostly empty netlist
3080        assert!(netlist.clean().is_ok());
3081        input1.expose_with_name("an_output".into());
3082        assert!(netlist.clean().is_ok());
3083    }
3084
3085    #[test]
3086    #[should_panic(expected = "Attempted to create a gate with a sliced identifier")]
3087    fn gate_w_slice_panics() {
3088        Gate::new_logical("AND[1]".into(), vec!["A".into(), "B".into()], "Y".into());
3089    }
3090
3091    #[test]
3092    fn gates_dont_have_params() {
3093        // The baseline implementation of gates do not have parameters.
3094        let gate = Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into());
3095        assert!(!gate.has_parameter(&"id".into()));
3096        assert!(gate.get_parameter(&"id".into()).is_none());
3097        assert_eq!(*gate.get_gate_name(), "AND".into());
3098    }
3099
3100    #[test]
3101    fn operand_conversions() {
3102        let operand = Operand::CellIndex(3, 2);
3103        assert_eq!(operand.to_string(), "3.2");
3104        let parsed = "3.2".parse::<Operand>();
3105        assert!(parsed.is_ok());
3106        let parsed = parsed.unwrap();
3107        assert_eq!(operand, parsed);
3108    }
3109
3110    #[test]
3111    #[should_panic(expected = "out of bounds for netref")]
3112    fn test_bad_output() {
3113        let netlist = GateNetlist::new("min_module".to_string());
3114        let a = netlist.insert_input("a".into());
3115        DrivenNet::new(1, a.unwrap());
3116    }
3117
3118    #[test]
3119    fn test_netdfsiterator() {
3120        let netlist = Netlist::new("dfs_netlist".to_string());
3121
3122        // inputs
3123        let a = netlist.insert_input("a".into());
3124        let b = netlist.insert_input("b".into());
3125        let c = netlist.insert_input("c".into());
3126        let d = netlist.insert_input("d".into());
3127        let e = netlist.insert_input("e".into());
3128
3129        // gates
3130        let n1 = netlist
3131            .insert_gate(
3132                Gate::new_logical("OR".into(), vec!["A".into(), "B".into()], "Y".into()),
3133                "n1".into(),
3134                &[a.clone(), b.clone()],
3135            )
3136            .unwrap()
3137            .get_output(0);
3138        let n2 = netlist
3139            .insert_gate(
3140                Gate::new_logical("NOR".into(), vec!["A".into(), "B".into()], "Y".into()),
3141                "n2".into(),
3142                &[d.clone(), e.clone()],
3143            )
3144            .unwrap()
3145            .get_output(0);
3146        let n3 = netlist
3147            .insert_gate(
3148                Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into()),
3149                "n3".into(),
3150                &[n1.clone(), c.clone()],
3151            )
3152            .unwrap()
3153            .get_output(0);
3154        let n4 = netlist
3155            .insert_gate(
3156                Gate::new_logical("NAND".into(), vec!["A".into(), "B".into()], "Y".into()),
3157                "n4".into(),
3158                &[n3.clone(), n2.clone()],
3159            )
3160            .unwrap()
3161            .get_output(0);
3162        n4.clone().expose_with_name("y".into());
3163
3164        // test DFSIterator
3165        let mut dfs = NetDFSIterator::new(&netlist, n4.clone());
3166        assert_eq!(dfs.next(), Some(n4));
3167        assert_eq!(dfs.next(), Some(n2));
3168        assert_eq!(dfs.next(), Some(e));
3169        assert_eq!(dfs.next(), Some(d));
3170        assert_eq!(dfs.next(), Some(n3));
3171        assert_eq!(dfs.next(), Some(c));
3172        assert_eq!(dfs.next(), Some(n1));
3173        assert_eq!(dfs.next(), Some(b));
3174        assert_eq!(dfs.next(), Some(a));
3175        assert_eq!(dfs.next(), None);
3176    }
3177
3178    #[test]
3179    fn test_dfs_cycles() {
3180        let netlist = Netlist::new("dfs_cycles".to_string());
3181
3182        // inputs
3183        let a = netlist.insert_input("a".into());
3184
3185        // gates
3186        let and = netlist.insert_gate_disconnected(
3187            Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into()),
3188            "and".into(),
3189        );
3190
3191        // connect and form cycle
3192        a.connect(and.get_input(0));
3193        and.get_output(0).connect(and.get_input(1));
3194
3195        // test dfs iterators
3196        let dfs = DFSIterator::new(&netlist, and.clone());
3197        let driven_dfs = NetDFSIterator::new(&netlist, and.get_output(0));
3198
3199        assert!(dfs.detect_cycles());
3200        assert!(driven_dfs.detect_cycles());
3201    }
3202
3203    #[test]
3204    fn test_netdfsiterator_with_boundary() {
3205        let netlist = Netlist::new("dfs_netlist".to_string());
3206
3207        // inputs
3208        let a = netlist.insert_input("a".into());
3209        let b = netlist.insert_input("b".into());
3210        let c = netlist.insert_input("c".into());
3211        let d = netlist.insert_input("d".into());
3212        let e = netlist.insert_input("e".into());
3213
3214        // gates
3215        let n1 = netlist
3216            .insert_gate(
3217                Gate::new_logical("OR".into(), vec!["A".into(), "B".into()], "Y".into()),
3218                "n1".into(),
3219                &[a.clone(), b.clone()],
3220            )
3221            .unwrap()
3222            .get_output(0);
3223        let n2 = netlist
3224            .insert_gate(
3225                Gate::new_logical("NOR".into(), vec!["A".into(), "B".into()], "Y".into()),
3226                "n2".into(),
3227                &[d.clone(), e.clone()],
3228            )
3229            .unwrap()
3230            .get_output(0);
3231        let n3 = netlist
3232            .insert_gate(
3233                Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into()),
3234                "n3".into(),
3235                &[n1.clone(), c.clone()],
3236            )
3237            .unwrap()
3238            .get_output(0);
3239        let n4 = netlist
3240            .insert_gate(
3241                Gate::new_logical("NAND".into(), vec!["A".into(), "B".into()], "Y".into()),
3242                "n4".into(),
3243                &[n3.clone(), n2.clone()],
3244            )
3245            .unwrap()
3246            .get_output(0);
3247
3248        // Stop DFS expansion at n3 to emulate a traversal boundary.
3249        let n3_boundary = n3.clone();
3250        let mut dfs =
3251            NetDFSIterator::new_filtered(&netlist, n4.clone(), move |n| *n == n3_boundary);
3252        assert_eq!(dfs.next(), Some(n4));
3253        assert_eq!(dfs.next(), Some(n2));
3254        assert_eq!(dfs.next(), Some(e));
3255        assert_eq!(dfs.next(), Some(d));
3256        assert_eq!(dfs.next(), Some(n3));
3257        assert_eq!(dfs.next(), None);
3258    }
3259
3260    #[test]
3261    fn test_dfs_convergence() {
3262        let netlist = GateNetlist::new("example".to_string());
3263        let gate = Gate::new_logical_multi(
3264            "FA".into(),
3265            vec!["A".into(), "B".into()],
3266            vec!["S".into(), "COUT".into()],
3267        );
3268        let a = netlist.insert_input("a".into());
3269        let b = netlist.insert_input("b".into());
3270        let gate = netlist.insert_gate(gate, "g".into(), &[a, b]).unwrap();
3271        let s = gate.get_output(0);
3272        let c = gate.get_output(1);
3273        let gate = Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into());
3274        let d = netlist.insert_gate(gate, "h".into(), &[s, c]).unwrap();
3275
3276        let dfs = NetDFSIterator::new(&netlist, d.get_output(0));
3277        let c = dfs.count();
3278        assert_eq!(c, 5);
3279
3280        let dfs = DFSIterator::new(&netlist, d.clone());
3281        let c = dfs.count();
3282        assert_eq!(c, 4);
3283    }
3284
3285    #[test]
3286    fn test_operand_comparison() {
3287        let a = Operand::CellIndex(3, 0);
3288        let b = Operand::DirectIndex(3);
3289        assert_eq!(a.cmp(&b), std::cmp::Ordering::Greater);
3290        assert_eq!(b.cmp(&a), std::cmp::Ordering::Less);
3291    }
3292}
3293#[cfg(feature = "serde")]
3294/// Serde support for netlists
3295pub mod serde {
3296    use super::{Netlist, Operand, OwnedObject, WeakIndex};
3297    use crate::{
3298        attribute::{AttributeKey, AttributeValue},
3299        circuit::{Instantiable, Net, Object},
3300    };
3301    use serde::{Deserialize, Serialize, de::DeserializeOwned};
3302    use std::cell::RefCell;
3303    use std::{
3304        collections::{BTreeMap, BTreeSet},
3305        rc::Rc,
3306    };
3307
3308    #[derive(Debug, Serialize, Deserialize)]
3309    struct SerdeObject<I>
3310    where
3311        I: Instantiable + Serialize,
3312    {
3313        /// The object that is owned by the netlist
3314        object: Object<I>,
3315        /// The list of operands for the object
3316        operands: Vec<Option<Operand>>,
3317        /// A collection of attributes for the object
3318        attributes: BTreeMap<AttributeKey, AttributeValue>,
3319    }
3320
3321    impl<I, O> From<OwnedObject<I, O>> for SerdeObject<I>
3322    where
3323        I: Instantiable + Serialize,
3324        O: WeakIndex<usize, Output = OwnedObject<I, O>>,
3325    {
3326        fn from(value: OwnedObject<I, O>) -> Self {
3327            SerdeObject {
3328                object: value.object,
3329                operands: value.operands,
3330                attributes: value.attributes,
3331            }
3332        }
3333    }
3334
3335    impl<I> SerdeObject<I>
3336    where
3337        I: Instantiable + Serialize,
3338    {
3339        fn into_owned_object<O>(self, owner: &Rc<O>, index: usize) -> OwnedObject<I, O>
3340        where
3341            O: WeakIndex<usize, Output = OwnedObject<I, O>>,
3342        {
3343            OwnedObject {
3344                object: self.object,
3345                owner: Rc::downgrade(owner),
3346                operands: self.operands,
3347                attributes: self.attributes,
3348                index,
3349            }
3350        }
3351    }
3352
3353    #[derive(Debug, Serialize, Deserialize)]
3354    struct SerdeNetlist<I>
3355    where
3356        I: Instantiable + Serialize,
3357    {
3358        /// The name of the netlist
3359        name: String,
3360        /// The list of objects in the netlist, such as inputs, modules, and primitives
3361        objects: Vec<SerdeObject<I>>,
3362        /// The list of operands that point to objects which are outputs.
3363        /// Indices must be a string if we want to support JSON.
3364        /// Each operand can map to multiple nets, supporting output aliases.
3365        outputs: BTreeMap<String, BTreeSet<Net>>,
3366    }
3367
3368    impl<I> From<Netlist<I>> for SerdeNetlist<I>
3369    where
3370        I: Instantiable + Serialize,
3371    {
3372        fn from(value: Netlist<I>) -> Self {
3373            SerdeNetlist {
3374                name: value.name.into_inner(),
3375                objects: value
3376                    .objects
3377                    .into_inner()
3378                    .into_iter()
3379                    .map(|o| {
3380                        Rc::try_unwrap(o)
3381                            .ok()
3382                            .expect("Cannot serialize with live references")
3383                            .into_inner()
3384                            .into()
3385                    })
3386                    .collect(),
3387                outputs: value
3388                    .outputs
3389                    .into_inner()
3390                    .into_iter()
3391                    // Indices must be a string if we want to support JSON.
3392                    .map(|(o, nets)| (o.to_string(), nets.into_iter().collect()))
3393                    .collect(),
3394            }
3395        }
3396    }
3397
3398    impl<I> SerdeNetlist<I>
3399    where
3400        I: Instantiable + Serialize,
3401    {
3402        /// Convert the serialized netlist back into a reference-counted netlist.
3403        fn into_netlist(self) -> Rc<Netlist<I>> {
3404            let netlist = Netlist::new(self.name);
3405            let outputs: BTreeMap<Operand, BTreeSet<Net>> = self
3406                .outputs
3407                .into_iter()
3408                .map(|(k, v)| {
3409                    let operand = k.parse::<Operand>().expect("Invalid index");
3410                    (operand, v.into_iter().collect())
3411                })
3412                .collect();
3413            let objects = self
3414                .objects
3415                .into_iter()
3416                .enumerate()
3417                .map(|(i, o)| {
3418                    let owned_object = o.into_owned_object(&netlist, i);
3419                    Rc::new(RefCell::new(owned_object))
3420                })
3421                .collect::<Vec<_>>();
3422            {
3423                let mut objs_mut = netlist.objects.borrow_mut();
3424                *objs_mut = objects;
3425                let mut outputs_mut = netlist.outputs.borrow_mut();
3426                *outputs_mut = outputs;
3427            }
3428            netlist
3429        }
3430    }
3431
3432    /// Serialize the netlist into the writer.
3433    pub fn netlist_serialize<I: Instantiable + Serialize>(
3434        netlist: Netlist<I>,
3435        writer: impl std::io::Write,
3436    ) -> Result<(), serde_json::Error> {
3437        let sobj: SerdeNetlist<I> = netlist.into();
3438        serde_json::to_writer_pretty(writer, &sobj)
3439    }
3440
3441    /// Deserialize a netlist from the reader.
3442    pub fn netlist_deserialize<I: Instantiable + Serialize + DeserializeOwned>(
3443        reader: impl std::io::Read,
3444    ) -> Result<Rc<Netlist<I>>, serde_json::Error> {
3445        let sobj: SerdeNetlist<I> = serde_json::from_reader(reader)?;
3446        Ok(sobj.into_netlist())
3447    }
3448}