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