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    /// # See also:
857    /// - [`NetMapper`](rewriter::NetMapper)
858    ///
859    /// # Panics
860    ///
861    /// Panics if either `self` is a multi-output circuit node.
862    /// Panics if the weak reference to the netlist is lost.
863    pub fn replace_uses_with(self, other: &DrivenNet<I>) -> Result<NetRef<I>, Error> {
864        let netlist = self
865            .netref
866            .borrow()
867            .owner
868            .upgrade()
869            .expect("NetRef is unlinked from netlist");
870        netlist
871            .replace_net_uses(self.into(), other)
872            .map(|d| d.unwrap())
873    }
874
875    /// Clears the attribute with the given key on this circuit node.
876    pub fn clear_attribute(&self, k: &AttributeKey) -> Option<AttributeValue> {
877        self.netref.borrow_mut().clear_attribute(k)
878    }
879
880    /// Set an attribute without a value
881    pub fn set_attribute(&self, k: AttributeKey) {
882        self.netref.borrow_mut().set_attribute(k);
883    }
884
885    /// Insert an attribute on this node with a value
886    pub fn insert_attribute(&self, k: AttributeKey, v: String) -> Option<AttributeValue> {
887        self.netref.borrow_mut().insert_attribute(k, v)
888    }
889
890    /// Returns an iterator to the attributes at this circuit node
891    pub fn attributes(&self) -> impl Iterator<Item = Attribute> {
892        let v: Vec<_> = self.netref.borrow().attributes().collect();
893        v.into_iter()
894    }
895}
896
897impl<I> std::fmt::Display for NetRef<I>
898where
899    I: Instantiable,
900{
901    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
902        self.netref.borrow().object.fmt(f)
903    }
904}
905
906impl<I> From<NetRef<I>> for DrivenNet<I>
907where
908    I: Instantiable,
909{
910    fn from(val: NetRef<I>) -> Self {
911        if val.is_multi_output() {
912            panic!("Cannot convert a multi-output netref to an output port");
913        }
914        DrivenNet::new(0, val)
915    }
916}
917
918impl<I> From<&NetRef<I>> for DrivenNet<I>
919where
920    I: Instantiable,
921{
922    fn from(val: &NetRef<I>) -> Self {
923        if val.is_multi_output() {
924            panic!("Cannot convert a multi-output netref to an output port");
925        }
926        DrivenNet::new(0, val.clone())
927    }
928}
929
930/// Facilitates mutable borrows to driver nets
931pub struct MutBorrowReq<I: Instantiable> {
932    from: NetRef<I>,
933    ind: Net,
934}
935
936impl<I> MutBorrowReq<I>
937where
938    I: Instantiable,
939{
940    /// Creates a new mutable borrow request
941    fn new(from: NetRef<I>, ind: Net) -> Self {
942        Self { from, ind }
943    }
944
945    /// Mutably borrows the requested net from the circuit node
946    pub fn borrow_mut(&self) -> RefMut<'_, Net> {
947        self.from.find_net_mut(&self.ind).unwrap()
948    }
949
950    /// Returns `true` if the circuit node is an input
951    pub fn is_an_input(&self) -> bool {
952        self.from.is_an_input()
953    }
954
955    /// Attempts to borrow the net mutably if the condition `f` is satisfied.
956    pub fn borrow_mut_if(&self, f: impl Fn(&NetRef<I>) -> bool) -> Option<RefMut<'_, Net>> {
957        if f(&self.from) {
958            Some(self.borrow_mut())
959        } else {
960            None
961        }
962    }
963}
964
965/// A netlist data structure
966#[derive(Debug)]
967pub struct Netlist<I>
968where
969    I: Instantiable,
970{
971    /// The name of the netlist
972    name: RefCell<String>,
973    /// The list of objects in the netlist, such as inputs, modules, and primitives
974    objects: RefCell<Vec<NetRefT<I>>>,
975    /// Each operand can map to multiple nets, supporting output aliases.
976    outputs: RefCell<HashMap<Operand, BTreeSet<Net>>>,
977}
978
979/// Represent the input port of a primitive
980#[derive(Debug, Clone)]
981pub struct InputPort<I: Instantiable> {
982    pos: usize,
983    netref: NetRef<I>,
984}
985
986impl<I> InputPort<I>
987where
988    I: Instantiable,
989{
990    fn new(pos: usize, netref: NetRef<I>) -> Self {
991        if pos >= netref.clone().unwrap().borrow().operands.len() {
992            panic!(
993                "Position {} out of bounds for netref with {} input nets",
994                pos,
995                netref.unwrap().borrow().get().get_nets().len()
996            );
997        }
998        Self { pos, netref }
999    }
1000
1001    /// Returns the net that is driving this input port
1002    pub fn get_driver(&self) -> Option<DrivenNet<I>> {
1003        if self.netref.is_an_input() {
1004            panic!("Input port is not driven by a primitive");
1005        }
1006        if let Some(prev_operand) = self.netref.clone().unwrap().borrow().operands[self.pos] {
1007            let netlist = self
1008                .netref
1009                .clone()
1010                .unwrap()
1011                .borrow()
1012                .owner
1013                .upgrade()
1014                .expect("Input port is unlinked from netlist");
1015            let driver_nr = netlist.index_weak(&prev_operand.root());
1016            let nr = NetRef::wrap(driver_nr);
1017            let pos = prev_operand.secondary();
1018            Some(DrivenNet::new(pos, nr))
1019        } else {
1020            None
1021        }
1022    }
1023
1024    /// Disconnects an input port and returns the previous [DrivenNet] if it was connected.
1025    pub fn disconnect(&self) -> Option<DrivenNet<I>> {
1026        let val = self.get_driver();
1027        self.netref.clone().unwrap().borrow_mut().operands[self.pos] = None;
1028        val
1029    }
1030
1031    /// Get the input port associated with this connection
1032    pub fn get_port(&self) -> Net {
1033        if self.netref.is_an_input() {
1034            panic!("Net is not driven by a primitive");
1035        }
1036        self.netref
1037            .get_instance_type()
1038            .unwrap()
1039            .get_input_port(self.pos)
1040            .clone()
1041    }
1042
1043    /// Connects this input port to a driven net.
1044    pub fn connect(self, output: DrivenNet<I>) {
1045        output.connect(self);
1046    }
1047
1048    /// Return the underlying circuit node
1049    pub fn unwrap(self) -> NetRef<I> {
1050        self.netref
1051    }
1052
1053    /// Returns the index associated with this input port
1054    pub fn get_input_num(&self) -> usize {
1055        self.pos
1056    }
1057}
1058
1059impl<I> std::fmt::Display for InputPort<I>
1060where
1061    I: Instantiable,
1062{
1063    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1064        self.get_port().fmt(f)
1065    }
1066}
1067
1068/// Represent a net that is being driven by a [Instantiable]
1069#[derive(Debug, Clone)]
1070pub struct DrivenNet<I: Instantiable> {
1071    pos: usize,
1072    netref: NetRef<I>,
1073}
1074
1075impl<I> DrivenNet<I>
1076where
1077    I: Instantiable,
1078{
1079    fn new(pos: usize, netref: NetRef<I>) -> Self {
1080        if pos >= netref.clone().unwrap().borrow().get().get_nets().len() {
1081            panic!(
1082                "Position {} out of bounds for netref with {} outputted nets",
1083                pos,
1084                netref.unwrap().borrow().get().get_nets().len()
1085            );
1086        }
1087        Self { pos, netref }
1088    }
1089
1090    /// Returns the index that can address this net in the netlist.
1091    fn get_operand(&self) -> Operand {
1092        if self.netref.is_multi_output() {
1093            Operand::CellIndex(self.netref.clone().unwrap().borrow().get_index(), self.pos)
1094        } else {
1095            Operand::DirectIndex(self.netref.clone().unwrap().borrow().get_index())
1096        }
1097    }
1098
1099    /// Borrow the net being driven
1100    pub fn as_net(&self) -> Ref<'_, Net> {
1101        self.netref.get_net(self.pos)
1102    }
1103
1104    /// Get a mutable reference to the net being driven
1105    pub fn as_net_mut(&self) -> RefMut<'_, Net> {
1106        self.netref.get_net_mut(self.pos)
1107    }
1108
1109    /// Returns `true` if this net is a principal input
1110    pub fn is_an_input(&self) -> bool {
1111        self.netref.is_an_input()
1112    }
1113
1114    /// Get the output port associated with this connection
1115    pub fn get_port(&self) -> Net {
1116        if self.netref.is_an_input() {
1117            panic!("Net is not driven by a primitive");
1118        }
1119        self.netref
1120            .get_instance_type()
1121            .unwrap()
1122            .get_output_port(self.pos)
1123            .clone()
1124    }
1125
1126    /// Connects the net driven by this output port to the given input port.
1127    pub fn connect(&self, input: InputPort<I>) {
1128        let operand = self.get_operand();
1129        let index = input.netref.unwrap().borrow().get_index();
1130        let netlist = self
1131            .netref
1132            .clone()
1133            .unwrap()
1134            .borrow()
1135            .owner
1136            .upgrade()
1137            .expect("Output port is unlinked from netlist");
1138        let obj = netlist.index_weak(&index);
1139        obj.borrow_mut().operands[input.pos] = Some(operand);
1140    }
1141
1142    /// Returns `true` if this net is a top-level output in the netlist.
1143    pub fn is_top_level_output(&self) -> bool {
1144        let netlist = self
1145            .netref
1146            .clone()
1147            .unwrap()
1148            .borrow()
1149            .owner
1150            .upgrade()
1151            .expect("DrivenNet is unlinked from netlist");
1152        let outputs = netlist.outputs.borrow();
1153        outputs.contains_key(&self.get_operand())
1154    }
1155
1156    /// Return the underlying circuit node
1157    pub fn unwrap(self) -> NetRef<I> {
1158        self.netref
1159    }
1160
1161    /// Returns a copy of the identifier of the net being driven.
1162    pub fn get_identifier(&self) -> Identifier {
1163        self.as_net().get_identifier().clone()
1164    }
1165
1166    /// Exposes this driven net as a top-level output with a specific port name.
1167    /// Multiple calls to this method can be used to create multiple output aliases for the same net.
1168    ///
1169    /// # Panics
1170    ///
1171    /// Panics if the weak reference to the netlist is dead.
1172    pub fn expose_with_name(self, name: Identifier) -> Self {
1173        let netlist = self
1174            .netref
1175            .clone()
1176            .unwrap()
1177            .borrow()
1178            .owner
1179            .upgrade()
1180            .expect("DrivenNet is unlinked from netlist");
1181        netlist.expose_net_with_name(self.clone(), name);
1182        self
1183    }
1184
1185    /// Removes a specific output alias by its name from this driven net.
1186    /// Returns true if the output was removed, false if it didn't exist.
1187    ///
1188    /// # Panics
1189    ///
1190    /// Panics if the reference to the netlist is lost.
1191    pub fn remove_output(&self, net_name: &Identifier) -> bool {
1192        let netlist = self
1193            .netref
1194            .clone()
1195            .unwrap()
1196            .borrow()
1197            .owner
1198            .upgrade()
1199            .expect("DrivenNet is unlinked from netlist");
1200        netlist.remove_output(self, net_name)
1201    }
1202
1203    /// Removes all output aliases for this driven net.
1204    /// Returns the number of outputs that were removed.
1205    ///
1206    /// # Panics
1207    ///
1208    /// Panics if the reference to the netlist is lost.
1209    pub fn remove_all_outputs(&self) -> usize {
1210        let netlist = self
1211            .netref
1212            .clone()
1213            .unwrap()
1214            .borrow()
1215            .owner
1216            .upgrade()
1217            .expect("DrivenNet is unlinked from netlist");
1218        netlist.remove_outputs(self)
1219    }
1220
1221    /// Returns the output position, if the net is the output of a gate.
1222    pub fn get_output_index(&self) -> Option<usize> {
1223        if self.netref.is_an_input() {
1224            None
1225        } else {
1226            Some(self.pos)
1227        }
1228    }
1229
1230    /// Returns the [Instantiable] type driving this net, if it has a driver.
1231    pub fn get_instance_type(&self) -> Option<Ref<'_, I>> {
1232        self.netref.get_instance_type()
1233    }
1234}
1235
1236impl<I> std::fmt::Display for DrivenNet<I>
1237where
1238    I: Instantiable,
1239{
1240    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1241        self.as_net().fmt(f)
1242    }
1243}
1244
1245impl<I> PartialEq for DrivenNet<I>
1246where
1247    I: Instantiable,
1248{
1249    fn eq(&self, other: &Self) -> bool {
1250        self.netref == other.netref && self.pos == other.pos
1251    }
1252}
1253
1254impl<I> Eq for DrivenNet<I> where I: Instantiable {}
1255
1256impl<I> std::hash::Hash for DrivenNet<I>
1257where
1258    I: Instantiable,
1259{
1260    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1261        self.netref.hash(state);
1262        self.pos.hash(state);
1263    }
1264}
1265
1266impl<I> Ord for DrivenNet<I>
1267where
1268    I: Instantiable,
1269{
1270    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1271        match self.netref.cmp(&other.netref) {
1272            std::cmp::Ordering::Equal => self.pos.cmp(&other.pos),
1273            ord => ord,
1274        }
1275    }
1276}
1277
1278impl<I> PartialOrd for DrivenNet<I>
1279where
1280    I: Instantiable,
1281{
1282    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1283        Some(self.cmp(other))
1284    }
1285}
1286
1287impl<I> WeakIndex<usize> for Netlist<I>
1288where
1289    I: Instantiable,
1290{
1291    type Output = OwnedObject<I, Self>;
1292
1293    fn index_weak(&self, index: &usize) -> Rc<RefCell<Self::Output>> {
1294        self.objects.borrow()[*index].clone()
1295    }
1296}
1297
1298impl<I> Netlist<I>
1299where
1300    I: Instantiable,
1301{
1302    /// Creates a new netlist with the given name
1303    pub fn new(name: String) -> Rc<Self> {
1304        Rc::new(Self {
1305            name: RefCell::new(name),
1306            objects: RefCell::new(Vec::new()),
1307            outputs: RefCell::new(HashMap::new()),
1308        })
1309    }
1310
1311    /// Attempts to reclaim the netlist, returning [Some] if successful.
1312    pub fn reclaim(self: Rc<Self>) -> Option<Self> {
1313        Rc::try_unwrap(self).ok()
1314    }
1315
1316    /// Creates a deep clone of the netlist.
1317    pub fn deep_clone(self: &Rc<Self>) -> Rc<Self> {
1318        let dc = Rc::new(Self {
1319            name: self.name.clone(),
1320            objects: RefCell::new(Vec::new()),
1321            outputs: self.outputs.clone(),
1322        });
1323
1324        let objects_linked: Vec<NetRefT<I>> = self
1325            .objects
1326            .borrow()
1327            .iter()
1328            .map(|obj| {
1329                Rc::new(RefCell::new(OwnedObject {
1330                    object: obj.borrow().object.clone(),
1331                    owner: Rc::downgrade(&dc),
1332                    operands: obj.borrow().operands.clone(),
1333                    attributes: obj.borrow().attributes.clone(),
1334                    index: obj.borrow().index,
1335                }))
1336            })
1337            .collect();
1338
1339        *dc.objects.borrow_mut() = objects_linked;
1340
1341        dc
1342    }
1343
1344    /// Use interior mutability to add an object to the netlist. Returns a mutable reference to the created object.
1345    ///
1346    /// # Panics
1347    /// If any of the `operands` do not belong to this netlist.
1348    fn insert_object(
1349        self: &Rc<Self>,
1350        object: Object<I>,
1351        operands: &[DrivenNet<I>],
1352    ) -> Result<NetRef<I>, Error> {
1353        for operand in operands {
1354            self.belongs(&operand.clone().unwrap());
1355        }
1356        let index = self.objects.borrow().len();
1357        let weak = Rc::downgrade(self);
1358        let operands = operands
1359            .iter()
1360            .map(|net| Some(net.get_operand()))
1361            .collect::<Vec<_>>();
1362        let owned_object = Rc::new(RefCell::new(OwnedObject {
1363            object,
1364            owner: weak,
1365            operands,
1366            attributes: HashMap::new(),
1367            index,
1368        }));
1369        self.objects.borrow_mut().push(owned_object.clone());
1370        Ok(NetRef::wrap(owned_object))
1371    }
1372
1373    /// Inserts an input net to the netlist
1374    pub fn insert_input(self: &Rc<Self>, net: Net) -> DrivenNet<I> {
1375        let obj = Object::Input(net);
1376        self.insert_object(obj, &[]).unwrap().into()
1377    }
1378
1379    /// Inserts a four-state logic input port to the netlist
1380    pub fn insert_input_escaped_logic_bus(
1381        self: &Rc<Self>,
1382        net: String,
1383        bw: usize,
1384    ) -> Vec<DrivenNet<I>> {
1385        Net::new_escaped_logic_bus(net, bw)
1386            .into_iter()
1387            .map(|n| self.insert_input(n))
1388            .collect()
1389    }
1390
1391    /// Inserts a gate to the netlist
1392    pub fn insert_gate(
1393        self: &Rc<Self>,
1394        inst_type: I,
1395        inst_name: Identifier,
1396        operands: &[DrivenNet<I>],
1397    ) -> Result<NetRef<I>, Error> {
1398        let nets = inst_type
1399            .get_output_ports()
1400            .into_iter()
1401            .map(|pnet| pnet.with_name(&inst_name + pnet.get_identifier()))
1402            .collect::<Vec<_>>();
1403        let input_count = inst_type.get_input_ports().into_iter().count();
1404        if operands.len() != input_count {
1405            return Err(Error::ArgumentMismatch(input_count, operands.len()));
1406        }
1407        let obj = Object::Instance(nets, inst_name, inst_type);
1408        self.insert_object(obj, operands)
1409    }
1410
1411    /// Use interior mutability to add an object to the netlist. Returns a mutable reference to the created object.
1412    pub fn insert_gate_disconnected(
1413        self: &Rc<Self>,
1414        inst_type: I,
1415        inst_name: Identifier,
1416    ) -> NetRef<I> {
1417        let nets = inst_type
1418            .get_output_ports()
1419            .into_iter()
1420            .map(|pnet| pnet.with_name(&inst_name + pnet.get_identifier()))
1421            .collect::<Vec<_>>();
1422        let object = Object::Instance(nets, inst_name, inst_type);
1423        let index = self.objects.borrow().len();
1424        let weak = Rc::downgrade(self);
1425        let input_count = object
1426            .get_instance_type()
1427            .unwrap()
1428            .get_input_ports()
1429            .into_iter()
1430            .count();
1431        let operands = vec![None; input_count];
1432        let owned_object = Rc::new(RefCell::new(OwnedObject {
1433            object,
1434            owner: weak,
1435            operands,
1436            attributes: HashMap::new(),
1437            index,
1438        }));
1439        self.objects.borrow_mut().push(owned_object.clone());
1440        NetRef::wrap(owned_object)
1441    }
1442
1443    /// Inserts a constant [Logic] value to the netlist
1444    pub fn insert_constant(
1445        self: &Rc<Self>,
1446        value: Logic,
1447        inst_name: Identifier,
1448    ) -> Result<DrivenNet<I>, Error> {
1449        let obj = I::from_constant(value).ok_or(Error::InstantiableError(format!(
1450            "Instantiable type does not support constant value {}",
1451            value
1452        )))?;
1453        Ok(self.insert_gate_disconnected(obj, inst_name).into())
1454    }
1455
1456    /// # Panics
1457    ///
1458    /// Panics if `netref` definitely does not belong to this netlist.
1459    fn belongs(&self, netref: &NetRef<I>) {
1460        if let Some(nl) = netref.netref.borrow().owner.upgrade() {
1461            if self.objects.borrow().len() != nl.objects.borrow().len() {
1462                panic!("NetRef does not belong to this netlist");
1463            }
1464
1465            if let Some(p) = self.objects.borrow().first()
1466                && let Some(np) = nl.objects.borrow().first()
1467                && !Rc::ptr_eq(p, np)
1468            {
1469                panic!("NetRef does not belong to this netlist");
1470            }
1471        }
1472
1473        if netref.netref.borrow().index >= self.objects.borrow().len() {
1474            panic!("NetRef does not belong to this netlist");
1475        }
1476    }
1477
1478    /// Returns the driving node at input position `index` for `netref`
1479    ///
1480    /// # Panics
1481    ///
1482    /// Panics if `index` is out of bounds
1483    /// The `netref` does not belong to this netlist
1484    pub fn get_driver(&self, netref: NetRef<I>, index: usize) -> Option<DrivenNet<I>> {
1485        self.belongs(&netref);
1486        let op = netref.unwrap().borrow().operands[index]?;
1487        Some(DrivenNet::new(
1488            op.secondary(),
1489            NetRef::wrap(self.index_weak(&op.root()).clone()),
1490        ))
1491    }
1492
1493    /// Set an added object as a top-level output with a specific name.
1494    /// Multiple calls with different names for the same net will create multiple aliases.
1495    ///
1496    /// # Panics
1497    /// The `net` does not belong to this netlist
1498    pub fn expose_net_with_name(&self, net: DrivenNet<I>, name: Identifier) -> DrivenNet<I> {
1499        self.belongs(&net.clone().unwrap());
1500        let mut outputs = self.outputs.borrow_mut();
1501        let named_net = net.as_net().with_name(name);
1502        outputs
1503            .entry(net.get_operand())
1504            .or_default()
1505            .insert(named_net);
1506        net
1507    }
1508
1509    /// Sets the current net as a top-level output using the current name of the net
1510    ///
1511    /// # Panics
1512    /// The `net` does not belong to this netlist
1513    pub fn expose_net(&self, net: DrivenNet<I>) -> Result<DrivenNet<I>, Error> {
1514        self.belongs(&net.clone().unwrap());
1515        if net.is_an_input() {
1516            return Err(Error::InputNeedsAlias(net.as_net().clone()));
1517        }
1518        let mut outputs = self.outputs.borrow_mut();
1519        outputs
1520            .entry(net.get_operand())
1521            .or_default()
1522            .insert(net.as_net().clone());
1523        Ok(net)
1524    }
1525
1526    /// Removes a specific output alias by its operand and net name.
1527    /// Returns true if the output was removed, false if it didn't exist.
1528    ///
1529    /// # Panics
1530    /// The `operand` does not belong to this netlist
1531    pub fn remove_output(&self, operand: &DrivenNet<I>, net_name: &Identifier) -> bool {
1532        self.belongs(&operand.clone().unwrap());
1533        let mut outputs = self.outputs.borrow_mut();
1534        if let Some(nets) = outputs.get_mut(&operand.get_operand()) {
1535            // Create a net with just the identifier to match for removal
1536            let net_to_remove = Net::new(net_name.clone(), crate::circuit::DataType::logic());
1537            if nets.remove(&net_to_remove) {
1538                // If the set is now empty, remove the operand entirely
1539                if nets.is_empty() {
1540                    outputs.remove(&operand.get_operand());
1541                }
1542                return true;
1543            }
1544        }
1545        false
1546    }
1547
1548    /// Removes all output aliases for a specific operand.
1549    /// Returns the number of outputs that were removed.
1550    pub fn remove_outputs(&self, operand: &DrivenNet<I>) -> usize {
1551        //let mut outputs = self.outputs.borrow_mut();
1552        self.outputs
1553            .borrow_mut()
1554            .remove(&operand.get_operand())
1555            .map(|nets| nets.len())
1556            .unwrap_or(0)
1557    }
1558
1559    /// Removes all outputs from the netlist.
1560    pub fn clear_outputs(&self) {
1561        self.outputs.borrow_mut().clear();
1562    }
1563
1564    /// Unlink a circuit node from the rest of the netlist. Return the object that was being stored.
1565    ///
1566    /// # Panics
1567    /// The `netref` does not belong to this netlist
1568    pub fn delete_net_uses(&self, netref: NetRef<I>) -> Result<Object<I>, Error> {
1569        self.belongs(&netref);
1570        let unwrapped = netref.clone().unwrap();
1571        if Rc::strong_count(&unwrapped) > 3 {
1572            return Err(Error::DanglingReference(netref.nets().collect()));
1573        }
1574        let old_index = unwrapped.borrow().get_index();
1575        let objects = self.objects.borrow();
1576        for oref in objects.iter() {
1577            let operands = &mut oref.borrow_mut().operands;
1578            for operand in operands.iter_mut() {
1579                if let Some(op) = operand {
1580                    match op {
1581                        Operand::DirectIndex(idx) | Operand::CellIndex(idx, _)
1582                            if *idx == old_index =>
1583                        {
1584                            *operand = None;
1585                        }
1586                        _ => (),
1587                    }
1588                }
1589            }
1590        }
1591
1592        let outputs: Vec<Operand> = self
1593            .outputs
1594            .borrow()
1595            .keys()
1596            .filter(|operand| match operand {
1597                Operand::DirectIndex(idx) | Operand::CellIndex(idx, _) => *idx == old_index,
1598            })
1599            .cloned()
1600            .collect();
1601
1602        for operand in outputs {
1603            self.outputs.borrow_mut().remove(&operand);
1604        }
1605
1606        Ok(netref.unwrap().borrow().get().clone())
1607    }
1608
1609    /// Replaces the uses of a circuit node with another circuit node. `of` is returned and unused.
1610    ///
1611    /// # See also:
1612    /// - [`NetMapper`](rewriter::NetMapper)
1613    ///
1614    /// # Panics
1615    /// `of` or `with` do not belong to this netlist
1616    pub fn replace_net_uses(
1617        &self,
1618        of: DrivenNet<I>,
1619        with: &DrivenNet<I>,
1620    ) -> Result<DrivenNet<I>, Error> {
1621        {
1622            self.belongs(&of.clone().unwrap());
1623            self.belongs(&with.clone().unwrap());
1624        }
1625        let unwrapped = of.clone().unwrap().unwrap();
1626        let i = of.get_output_index();
1627        let k = with.get_output_index();
1628
1629        if of.clone().unwrap() == with.clone().unwrap() {
1630            if i == k {
1631                return Ok(of);
1632            }
1633
1634            if Rc::strong_count(&unwrapped) > 4 {
1635                return Err(Error::DanglingReference(of.unwrap().nets().collect()));
1636            }
1637        } else if Rc::strong_count(&unwrapped) > 3 {
1638            return Err(Error::DanglingReference(of.unwrap().nets().collect()));
1639        }
1640
1641        let old_index = of.get_operand();
1642
1643        if let Some(nets) = self.outputs.borrow().get(&old_index)
1644            && nets.contains(&of.as_net())
1645        {
1646            if of.is_an_input() {
1647                return Err(Error::NonuniqueNets(nets.iter().cloned().collect()));
1648            } else {
1649                let id = of.as_net().get_identifier().clone() + "_replaced".into();
1650                of.as_net_mut().set_identifier(id);
1651            }
1652        }
1653
1654        let new_index = with.get_operand();
1655        let objects = self.objects.borrow();
1656        for oref in objects.iter() {
1657            let operands = &mut oref.borrow_mut().operands;
1658            for operand in operands.iter_mut() {
1659                if let Some(op) = operand
1660                    && *op == old_index
1661                {
1662                    *operand = Some(new_index);
1663                }
1664            }
1665        }
1666
1667        // Move all the old outputs to the new key
1668        let outs = self.outputs.borrow_mut().remove(&old_index);
1669        if let Some(outs) = outs {
1670            self.outputs
1671                .borrow_mut()
1672                .entry(new_index)
1673                .or_default()
1674                .extend(outs);
1675        }
1676
1677        Ok(of)
1678    }
1679}
1680
1681impl<I> Netlist<I>
1682where
1683    I: Instantiable,
1684{
1685    /// Returns the name of the netlist module
1686    pub fn get_name(&self) -> Ref<'_, String> {
1687        self.name.borrow()
1688    }
1689
1690    /// Sets the name of the netlist module
1691    /// # Panics
1692    ///
1693    /// Panics if the module name cannot be borrowed mutably.
1694    pub fn set_name(&self, name: String) {
1695        *self.name.borrow_mut() = name;
1696    }
1697
1698    /// Iterates over the input ports of the netlist.
1699    pub fn get_input_ports(&self) -> impl Iterator<Item = Net> {
1700        self.objects().filter_map(|oref| {
1701            if oref.is_an_input() {
1702                Some(oref.as_net().clone())
1703            } else {
1704                None
1705            }
1706        })
1707    }
1708
1709    /// Returns a list of output nets
1710    pub fn get_output_ports(&self) -> Vec<Net> {
1711        self.outputs
1712            .borrow()
1713            .values()
1714            .flat_map(|nets| nets.iter().cloned())
1715            .collect()
1716    }
1717
1718    /// Constructs an analysis of the netlist.
1719    pub fn get_analysis<'a, A: Analysis<'a, I>>(&'a self) -> Result<A, Error> {
1720        A::build(self)
1721    }
1722
1723    /// Finds the first circuit node that drives the `net`. This operation is O(n).
1724    /// This should be unique provided the netlist is well-formed.
1725    pub fn find_net(&self, net: &Net) -> Option<DrivenNet<I>> {
1726        for obj in self.objects() {
1727            for o in obj.outputs() {
1728                if *o.as_net() == *net {
1729                    return Some(o);
1730                }
1731            }
1732        }
1733        None
1734    }
1735
1736    /// Returns a `NetRef` to the first circuit node
1737    pub fn first(&self) -> Option<NetRef<I>> {
1738        self.objects
1739            .borrow()
1740            .first()
1741            .map(|nr| NetRef::wrap(nr.clone()))
1742    }
1743
1744    /// Returns a `NetRef` to the last circuit node
1745    pub fn last(&self) -> Option<NetRef<I>> {
1746        self.objects
1747            .borrow()
1748            .last()
1749            .map(|nr| NetRef::wrap(nr.clone()))
1750    }
1751
1752    /// Returns the number of objects in the netlist (instances + inputs)
1753    pub fn len(&self) -> usize {
1754        self.objects.borrow().len()
1755    }
1756
1757    /// Returns `true` if the netlist contains no objects.
1758    pub fn is_empty(&self) -> bool {
1759        self.objects.borrow().is_empty()
1760    }
1761
1762    /// Returns `true` if an output of `netref` which is driving a module output.
1763    ///
1764    /// # Panics
1765    /// The `netref` does not belong to this netlist
1766    pub fn drives_an_output(&self, netref: NetRef<I>) -> bool {
1767        self.belongs(&netref);
1768        let my_index = netref.unwrap().borrow().get_index();
1769        for key in self.outputs.borrow().keys() {
1770            if key.root() == my_index {
1771                return true;
1772            }
1773        }
1774        false
1775    }
1776
1777    /// Rename nets and instances in the netlist using the provided *injective* function.
1778    /// Returns an error if the function is not injective.
1779    /// # Examples
1780    ///
1781    /// ```
1782    /// use safety_net::format_id;
1783    /// use safety_net::{Gate, GateNetlist};
1784    ///
1785    /// let netlist = GateNetlist::new("example".to_string());
1786    /// let inv = Gate::new_logical("INV".into(), vec!["A".into()], "Y".into());
1787    /// let foo = netlist.insert_input("foo".into());
1788    /// let nr = netlist.insert_gate(inv, "bar".into(), &[foo]).unwrap();
1789    /// nr.expose_with_name("baz".into());
1790    /// netlist.rename_nets(|id, i| format_id!("{}_{}", id, i) ).unwrap();
1791    /// // "bar_Y" -> "bar_Y_0"
1792    /// // "bar" -> "bar_1"
1793    /// ```
1794    pub fn rename_nets<F: Fn(&Identifier, usize) -> Identifier>(&self, f: F) -> Result<(), Error> {
1795        let mut i: usize = 0;
1796        for nr in self.objects() {
1797            if nr.is_an_input() {
1798                continue;
1799            }
1800            for mut net in nr.nets_mut() {
1801                let rename = f(net.get_identifier(), i);
1802                net.set_identifier(rename);
1803                i += 1;
1804            }
1805        }
1806
1807        for nr in self.objects() {
1808            if nr.is_an_input() {
1809                continue;
1810            }
1811
1812            let rename = f(&nr.get_instance_name().unwrap(), i);
1813            nr.set_instance_name(rename);
1814            i += 1;
1815        }
1816
1817        self.verify()
1818    }
1819
1820    /// Retains the [DrivenNet]s in `set`, given they are used. Otherwise, they are cleaned and returned in a `Ok(vec)`.
1821    pub fn retain_once(&self, set: &mut HashSet<DrivenNet<I>>) -> Result<Vec<Object<I>>, Error> {
1822        let mut dead_objs = HashSet::new();
1823        {
1824            let fan_out = self.get_analysis::<FanOutTable<I>>()?;
1825            for obj in self.objects() {
1826                let mut is_dead = true;
1827                for net in obj.outputs() {
1828                    // This should account for outputs
1829                    if fan_out.net_has_uses(&net.as_net()) {
1830                        is_dead = false;
1831                    } else {
1832                        set.remove(&net);
1833                    }
1834                }
1835                if is_dead && !obj.is_an_input() {
1836                    dead_objs.insert(obj.unwrap().borrow().index);
1837                }
1838            }
1839        }
1840
1841        if dead_objs.is_empty() {
1842            return Ok(vec![]);
1843        }
1844
1845        let old_objects = self.objects.take();
1846
1847        // Check no dangling references will be created before mutating
1848        for i in dead_objs.iter() {
1849            let rc = &old_objects[*i];
1850            if Rc::strong_count(rc) > 1 {
1851                self.objects.replace(old_objects.clone());
1852                return Err(Error::DanglingReference(
1853                    rc.borrow().get().get_nets().to_vec(),
1854                ));
1855            }
1856        }
1857
1858        let mut removed = Vec::new();
1859        let mut remap: HashMap<usize, usize> = HashMap::new();
1860        for (old_index, obj) in old_objects.into_iter().enumerate() {
1861            if dead_objs.contains(&old_index) {
1862                removed.push(obj.borrow().get().clone());
1863                continue;
1864            }
1865
1866            let new_index = self.objects.borrow().len();
1867            remap.insert(old_index, new_index);
1868            obj.borrow_mut().index = new_index;
1869            self.objects.borrow_mut().push(obj);
1870        }
1871
1872        for obj in self.objects.borrow().iter() {
1873            for operand in obj.borrow_mut().inds_mut() {
1874                let root = operand.root();
1875                let root = *remap.get(&root).unwrap_or(&root);
1876                *operand = operand.remap(root);
1877            }
1878        }
1879
1880        let pairs: Vec<_> = self.outputs.take().into_iter().collect();
1881        for (operand, net) in pairs {
1882            let root = operand.root();
1883            let root = *remap.get(&root).unwrap_or(&root);
1884            let new_operand = operand.remap(root);
1885            self.outputs.borrow_mut().insert(new_operand, net);
1886        }
1887
1888        Ok(removed)
1889    }
1890
1891    /// Removes unused nodes from the netlist, until it stops changing.
1892    /// Returns `Ok(vec)` of the removed objects.
1893    pub fn clean(&self) -> Result<Vec<Object<I>>, Error> {
1894        let mut removed = Vec::new();
1895        let mut r = self.retain_once(&mut HashSet::new())?;
1896        while !r.is_empty() {
1897            removed.extend(r);
1898            r = self.retain_once(&mut HashSet::new())?;
1899        }
1900        Ok(removed)
1901    }
1902
1903    /// Retains the [DrivenNet]s in `set`, given they are used. Otherwise, they are cleaned and returned in a `Ok(vec)`.
1904    pub fn retain(&self, set: &mut HashSet<DrivenNet<I>>) -> Result<Vec<Object<I>>, Error> {
1905        let mut removed = Vec::new();
1906        let mut r = self.retain_once(set)?;
1907        while !r.is_empty() {
1908            removed.extend(r);
1909            r = self.retain_once(set)?;
1910        }
1911        Ok(removed)
1912    }
1913
1914    /// Returns `true` if all the nets/insts are uniquely named
1915    fn nets_insts_unique(&self) -> Result<(), Error> {
1916        let mut nets = HashSet::new();
1917        for net in self {
1918            if !nets.insert(net.clone().take_identifier()) {
1919                return Err(Error::NonuniqueNets(vec![net]));
1920            }
1921        }
1922        for inst in self.objects() {
1923            if let Some(name) = inst.get_instance_name()
1924                && !nets.insert(name.clone())
1925            {
1926                return Err(Error::NonuniqueInsts(vec![name]));
1927            }
1928        }
1929        Ok(())
1930    }
1931
1932    fn connections_type_check(&self) -> Result<(), Error> {
1933        for conn in self.connections() {
1934            let target = *conn.target().get_port().get_type();
1935            let source = *conn.src().as_net().get_type();
1936            if target != source {
1937                return Err(Error::TypeError(conn.src().as_net().clone()));
1938            }
1939        }
1940        Ok(())
1941    }
1942
1943    /// Verifies that a netlist is well-formed.
1944    pub fn verify(&self) -> Result<(), Error> {
1945        if self.outputs.borrow().is_empty() {
1946            return Err(Error::NoOutputs);
1947        }
1948
1949        self.nets_insts_unique()?;
1950        self.connections_type_check()?;
1951
1952        Ok(())
1953    }
1954}
1955
1956/// Represent a driven net alongside its connection to an input port
1957#[derive(Debug, Clone)]
1958pub struct Connection<I: Instantiable> {
1959    driver: DrivenNet<I>,
1960    input: InputPort<I>,
1961}
1962
1963impl<I> Connection<I>
1964where
1965    I: Instantiable,
1966{
1967    fn new(driver: DrivenNet<I>, input: InputPort<I>) -> Self {
1968        Self { driver, input }
1969    }
1970
1971    /// Return the driver of the connection
1972    pub fn src(&self) -> DrivenNet<I> {
1973        self.driver.clone()
1974    }
1975
1976    /// Return the net along the connection
1977    pub fn net(&self) -> Net {
1978        self.driver.as_net().clone()
1979    }
1980
1981    /// Returns the input port of the connection
1982    pub fn target(&self) -> InputPort<I> {
1983        self.input.clone()
1984    }
1985}
1986
1987impl<I> std::fmt::Display for Connection<I>
1988where
1989    I: Instantiable,
1990{
1991    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1992        self.net().fmt(f)
1993    }
1994}
1995
1996/// Strategies for fast batching netlist rewrites
1997pub mod rewriter {
1998    use super::{DrivenNet, Error, Instantiable, NetRef, Netlist, Operand};
1999    use crate::graph::FanOutTable;
2000    use std::collections::HashMap;
2001    use std::rc::Rc;
2002
2003    /// Uses a union-find to batch replacements in a netlist closer to O(n) time.
2004    /// The replacement only considers the uses of a net that existed at the time of creation of [NetMapper].
2005    /// Connections created after the creation of the [NetMapper] will not be replaced.
2006    pub struct NetMapper<'a, I: Instantiable> {
2007        parent: HashMap<DrivenNet<I>, DrivenNet<I>>,
2008        netlist: &'a Netlist<I>,
2009        fanout: FanOutTable<'a, I>,
2010    }
2011
2012    impl<'a, I: Instantiable> NetMapper<'a, I> {
2013        /// Create a new empty mapper.
2014        pub fn new(netlist: &'a Netlist<I>) -> Result<Self, Error> {
2015            Ok(Self {
2016                parent: HashMap::new(),
2017                netlist,
2018                fanout: netlist.get_analysis::<FanOutTable<I>>()?,
2019            })
2020        }
2021
2022        /// Get the final replacement for the net
2023        pub fn find(&self, x: DrivenNet<I>) -> DrivenNet<I> {
2024            let mut root = x;
2025            while let Some(p) = self.parent.get(&root) {
2026                root = p.clone();
2027            }
2028            root
2029        }
2030
2031        /// Add a replacement to the mapper. Returns an error if the replacement creates a cycle.
2032        ///
2033        /// # Panics
2034        /// If `of` was already mapped to `with`
2035        pub fn replace(&mut self, of: DrivenNet<I>, with: DrivenNet<I>) -> DrivenNet<I> {
2036            let of_root = self.find(of.clone());
2037            let with_root = self.find(with);
2038            if of_root == with_root {
2039                panic!("Already mapped by NetMapper: {of}");
2040            }
2041            self.parent.insert(of_root, with_root);
2042            of
2043        }
2044
2045        /// Apply the replacements to the netlist.
2046        /// Returns the nets that were replaced.
2047        pub fn apply(self) -> Result<Vec<DrivenNet<I>>, Error> {
2048            // Build the one-pass map
2049            let mut map: HashMap<Operand, Operand> = HashMap::new();
2050            for k in self.parent.keys().cloned() {
2051                let v = self.find(k.clone());
2052                if k != v {
2053                    map.insert(k.get_operand(), v.get_operand());
2054                }
2055            }
2056
2057            drop(self.parent);
2058
2059            // Check that replacements are all valid
2060            for (of, with) in map.iter() {
2061                let unwrapped = self.netlist.objects.borrow()[of.root()].clone();
2062                let i = of.secondary();
2063                let k = of.secondary();
2064                let nr = NetRef::wrap(unwrapped.clone());
2065
2066                if of.root() == with.root() {
2067                    if i == k {
2068                        continue;
2069                    }
2070
2071                    if Rc::strong_count(&unwrapped) - self.fanout.get_ref_count(&nr) > 4 {
2072                        return Err(Error::DanglingReference(nr.nets().collect()));
2073                    }
2074                } else if Rc::strong_count(&unwrapped) - self.fanout.get_ref_count(&nr) > 3 {
2075                    return Err(Error::DanglingReference(nr.nets().collect()));
2076                }
2077
2078                let old_index = of;
2079                let of = DrivenNet::new(i, nr);
2080
2081                if let Some(nets) = self.netlist.outputs.borrow().get(old_index)
2082                    && nets.contains(&of.as_net())
2083                {
2084                    if of.is_an_input() {
2085                        return Err(Error::NonuniqueNets(nets.iter().cloned().collect()));
2086                    } else {
2087                        let id = of.as_net().get_identifier().clone() + "_replaced".into();
2088                        of.as_net_mut().set_identifier(id);
2089                    }
2090                }
2091            }
2092
2093            let objects = self.netlist.objects.borrow();
2094            for (of, &with) in map.iter() {
2095                let of = DrivenNet::new(of.secondary(), NetRef::wrap(objects[of.root()].clone()));
2096                for u in self.fanout.get_users(&of) {
2097                    let place = u.pos;
2098                    let u = u.unwrap().unwrap();
2099                    let operands = &mut u.borrow_mut().operands;
2100                    operands[place] = Some(with);
2101                }
2102            }
2103
2104            for (of, &with) in map.iter() {
2105                // Move all the old outputs to the new key
2106                let outs = self.netlist.outputs.borrow_mut().remove(of);
2107                if let Some(outs) = outs {
2108                    self.netlist
2109                        .outputs
2110                        .borrow_mut()
2111                        .entry(with)
2112                        .or_default()
2113                        .extend(outs);
2114                }
2115            }
2116
2117            let res: Vec<_> = map
2118                .into_keys()
2119                .map(|operand| {
2120                    DrivenNet::new(
2121                        operand.secondary(),
2122                        NetRef::wrap(self.netlist.objects.borrow()[operand.root()].clone()),
2123                    )
2124                })
2125                .collect();
2126
2127            Ok(res)
2128        }
2129    }
2130}
2131
2132/// A collection of iterators for the netlist
2133pub mod iter {
2134
2135    use super::{
2136        Connection, DrivenNet, InputPort, Instantiable, Net, NetRef, Netlist, Operand, WeakIndex,
2137    };
2138    use std::collections::{HashMap, HashSet};
2139    /// An iterator over the nets in a netlist
2140    pub struct NetIterator<'a, I: Instantiable> {
2141        netlist: &'a Netlist<I>,
2142        index: usize,
2143        subindex: usize,
2144    }
2145
2146    impl<'a, I> NetIterator<'a, I>
2147    where
2148        I: Instantiable,
2149    {
2150        /// Creates a new iterator for the netlist
2151        pub fn new(netlist: &'a Netlist<I>) -> Self {
2152            Self {
2153                netlist,
2154                index: 0,
2155                subindex: 0,
2156            }
2157        }
2158    }
2159
2160    impl<I> Iterator for NetIterator<'_, I>
2161    where
2162        I: Instantiable,
2163    {
2164        type Item = Net;
2165
2166        fn next(&mut self) -> Option<Self::Item> {
2167            while self.index < self.netlist.objects.borrow().len() {
2168                let objects = self.netlist.objects.borrow();
2169                let object = objects[self.index].borrow();
2170                if self.subindex < object.get().get_nets().len() {
2171                    let net = object.get().get_nets()[self.subindex].clone();
2172                    self.subindex += 1;
2173                    return Some(net);
2174                }
2175                self.subindex = 0;
2176                self.index += 1;
2177            }
2178            None
2179        }
2180    }
2181
2182    /// An iterator over the objects in a netlist
2183    pub struct ObjectIterator<'a, I: Instantiable> {
2184        netlist: &'a Netlist<I>,
2185        index: usize,
2186    }
2187
2188    impl<'a, I> ObjectIterator<'a, I>
2189    where
2190        I: Instantiable,
2191    {
2192        /// Creates a new  object iterator for the netlist
2193        pub fn new(netlist: &'a Netlist<I>) -> Self {
2194            Self { netlist, index: 0 }
2195        }
2196    }
2197
2198    impl<I> Iterator for ObjectIterator<'_, I>
2199    where
2200        I: Instantiable,
2201    {
2202        type Item = NetRef<I>;
2203
2204        fn next(&mut self) -> Option<Self::Item> {
2205            if self.index < self.netlist.objects.borrow().len() {
2206                let objects = self.netlist.objects.borrow();
2207                let object = &objects[self.index];
2208                self.index += 1;
2209                return Some(NetRef::wrap(object.clone()));
2210            }
2211            None
2212        }
2213    }
2214
2215    /// An iterator over the connections in a netlist
2216    pub struct ConnectionIterator<'a, I: Instantiable> {
2217        netlist: &'a Netlist<I>,
2218        index: usize,
2219        subindex: usize,
2220    }
2221
2222    impl<'a, I> ConnectionIterator<'a, I>
2223    where
2224        I: Instantiable,
2225    {
2226        /// Create a new connection iterator for the netlist
2227        pub fn new(netlist: &'a Netlist<I>) -> Self {
2228            Self {
2229                netlist,
2230                index: 0,
2231                subindex: 0,
2232            }
2233        }
2234    }
2235
2236    impl<I> Iterator for ConnectionIterator<'_, I>
2237    where
2238        I: Instantiable,
2239    {
2240        type Item = super::Connection<I>;
2241
2242        fn next(&mut self) -> Option<Self::Item> {
2243            while self.index < self.netlist.objects.borrow().len() {
2244                let objects = self.netlist.objects.borrow();
2245                let object = objects[self.index].borrow();
2246                let noperands = object.operands.len();
2247                while self.subindex < noperands {
2248                    if let Some(operand) = &object.operands[self.subindex] {
2249                        let driver = match operand {
2250                            Operand::DirectIndex(idx) => {
2251                                DrivenNet::new(0, NetRef::wrap(objects[*idx].clone()))
2252                            }
2253                            Operand::CellIndex(idx, j) => {
2254                                DrivenNet::new(*j, NetRef::wrap(objects[*idx].clone()))
2255                            }
2256                        };
2257                        let input = InputPort::new(
2258                            self.subindex,
2259                            NetRef::wrap(objects[self.index].clone()),
2260                        );
2261                        self.subindex += 1;
2262                        return Some(Connection::new(driver, input));
2263                    }
2264                    self.subindex += 1;
2265                }
2266                self.subindex = 0;
2267                self.index += 1;
2268            }
2269            None
2270        }
2271    }
2272
2273    /// A stack that can check contains in roughly O(1) time.
2274    #[derive(Clone)]
2275    struct Walk<T: std::hash::Hash + PartialEq + Eq + Clone> {
2276        stack: Vec<T>,
2277        counter: HashMap<T, usize>,
2278    }
2279
2280    impl<T> Walk<T>
2281    where
2282        T: std::hash::Hash + PartialEq + Eq + Clone,
2283    {
2284        /// Create a new, empty Stack.
2285        fn new() -> Self {
2286            Self {
2287                stack: Vec::new(),
2288                counter: HashMap::new(),
2289            }
2290        }
2291
2292        /// Inserts an element into the stack
2293        fn push(&mut self, item: T) {
2294            self.stack.push(item.clone());
2295            *self.counter.entry(item).or_insert(0) += 1;
2296        }
2297
2298        /// Returns true if the stack shows a cycle
2299        fn contains_cycle(&self) -> bool {
2300            self.counter.values().any(|&count| count > 1)
2301        }
2302
2303        /// Returns true if the stack contains a cycle to the root node
2304        fn root_cycle(&self) -> bool {
2305            if self.stack.is_empty() {
2306                return false;
2307            }
2308            self.counter[&self.stack[0]] > 1
2309        }
2310
2311        /// Returns a reference to the last element in the stack
2312        fn last(&self) -> Option<&T> {
2313            self.stack.last()
2314        }
2315    }
2316
2317    /// A depth-first iterator over the circuit nodes in a netlist
2318    /// # Examples
2319    ///
2320    /// ```
2321    /// use safety_net::iter::DFSIterator;
2322    /// use safety_net::GateNetlist;
2323    ///
2324    /// let netlist = GateNetlist::new("example".to_string());
2325    /// netlist.insert_input("input1".into());
2326    /// let mut nodes = Vec::new();
2327    /// let mut dfs = DFSIterator::new(&netlist, netlist.last().unwrap());
2328    /// while let Some(n) = dfs.next() {
2329    ///     if dfs.check_cycles() {
2330    ///         panic!("Cycle detected in the netlist");
2331    ///     }
2332    ///     nodes.push(n);
2333    /// }
2334    /// ```
2335    pub struct DFSIterator<'a, I: Instantiable> {
2336        dfs: NetDFSIterator<'a, I>,
2337        seen: HashSet<NetRef<I>>,
2338    }
2339
2340    impl<'a, I> DFSIterator<'a, I>
2341    where
2342        I: Instantiable,
2343    {
2344        /// Create a new DFS iterator for the netlist starting at `from`.
2345        pub fn new(netlist: &'a Netlist<I>, from: NetRef<I>) -> Self {
2346            Self {
2347                dfs: NetDFSIterator::new(netlist, DrivenNet::new(0, from)),
2348                seen: HashSet::new(),
2349            }
2350        }
2351    }
2352
2353    impl<I> DFSIterator<'_, I>
2354    where
2355        I: Instantiable,
2356    {
2357        /// Check if the DFS traversal has encountered a cycle yet.
2358        pub fn check_cycles(&self) -> bool {
2359            self.dfs.check_cycles()
2360        }
2361
2362        /// Consumes the iterator to detect cycles in the netlist.
2363        pub fn detect_cycles(self) -> bool {
2364            self.dfs.detect_cycles()
2365        }
2366
2367        /// Check if the DFS traversal has encountered the root `from`` again.
2368        pub fn check_self_loop(&self) -> bool {
2369            self.dfs.check_self_loop()
2370        }
2371
2372        /// Consumes the iterator to detect if the DFS traversal will encounter the root `from` again.
2373        pub fn detect_self_loop(self) -> bool {
2374            self.dfs.detect_self_loop()
2375        }
2376    }
2377
2378    impl<I> Iterator for DFSIterator<'_, I>
2379    where
2380        I: Instantiable,
2381    {
2382        type Item = NetRef<I>;
2383
2384        fn next(&mut self) -> Option<Self::Item> {
2385            let d = self.dfs.next()?;
2386            if self.seen.insert(d.clone().unwrap()) {
2387                Some(d.unwrap())
2388            } else {
2389                self.next()
2390            }
2391        }
2392    }
2393
2394    type TermFn<I> = Box<dyn Fn(&DrivenNet<I>) -> bool + 'static>;
2395
2396    /// Depth-first iterator that works like DFSIterator but iterates over DrivenNet
2397    pub struct NetDFSIterator<'a, I: Instantiable> {
2398        netlist: &'a Netlist<I>,
2399        stacks: Vec<Walk<DrivenNet<I>>>,
2400        visited: HashSet<usize>,
2401        visited_net: HashSet<(usize, usize)>,
2402        any_cycle: bool,
2403        root_cycle: bool,
2404        terminate: TermFn<I>,
2405    }
2406
2407    impl<'a, I> NetDFSIterator<'a, I>
2408    where
2409        I: Instantiable,
2410    {
2411        /// Create a new DFS DrivenNet iterator for the netlist starting at `from`, ignoring all dependencies beyond the `terminate` condition.
2412        /// Terminators themselves *are* included in the iteration.
2413        pub fn new_filtered<F: Fn(&DrivenNet<I>) -> bool + 'static>(
2414            netlist: &'a Netlist<I>,
2415            from: DrivenNet<I>,
2416            terminate: F,
2417        ) -> Self {
2418            let mut s = Walk::new();
2419            s.push(from);
2420            Self {
2421                netlist,
2422                stacks: vec![s],
2423                visited: HashSet::new(),
2424                visited_net: HashSet::new(),
2425                any_cycle: false,
2426                root_cycle: false,
2427                terminate: Box::new(terminate),
2428            }
2429        }
2430
2431        /// Create a new DFS DrivenNet iterator for the netlist starting at `from`.
2432        pub fn new(netlist: &'a Netlist<I>, from: DrivenNet<I>) -> Self {
2433            Self::new_filtered(netlist, from, |_| false)
2434        }
2435    }
2436
2437    impl<I> NetDFSIterator<'_, I>
2438    where
2439        I: Instantiable,
2440    {
2441        /// Check if the DFS traversal has encountered a cycle yet.
2442        pub fn check_cycles(&self) -> bool {
2443            self.any_cycle
2444        }
2445
2446        /// Consumes the iterator to detect cycles in the netlist.
2447        pub fn detect_cycles(mut self) -> bool {
2448            if self.any_cycle {
2449                return true;
2450            }
2451
2452            while let Some(_) = self.next() {
2453                if self.any_cycle {
2454                    return true;
2455                }
2456            }
2457
2458            self.any_cycle
2459        }
2460
2461        /// Check if the DFS traversal has encountered the root `from` again.
2462        pub fn check_self_loop(&self) -> bool {
2463            self.root_cycle
2464        }
2465
2466        /// Consumes the iterator to detect if the DFS traversal will encounter the root `from` again.
2467        pub fn detect_self_loop(mut self) -> bool {
2468            if self.root_cycle {
2469                return true;
2470            }
2471
2472            while let Some(_) = self.next() {
2473                if self.root_cycle {
2474                    return true;
2475                }
2476            }
2477
2478            self.root_cycle
2479        }
2480    }
2481
2482    impl<I> Iterator for NetDFSIterator<'_, I>
2483    where
2484        I: Instantiable,
2485    {
2486        type Item = DrivenNet<I>;
2487
2488        fn next(&mut self) -> Option<Self::Item> {
2489            if let Some(walk) = self.stacks.pop() {
2490                self.any_cycle |= walk.contains_cycle();
2491                self.root_cycle |= walk.root_cycle();
2492                let item = walk.last().cloned();
2493                let uw = item.clone().unwrap().unwrap().unwrap();
2494                let index = uw.borrow().get_index();
2495                let secondary = item.as_ref().unwrap().pos;
2496                if self.visited.insert(index) {
2497                    if !(self.terminate)(item.as_ref().unwrap()) {
2498                        let operands = &uw.borrow().operands;
2499                        for operand in operands.iter().flatten() {
2500                            let mut new_walk = walk.clone();
2501                            new_walk.push(DrivenNet::new(
2502                                operand.secondary(),
2503                                NetRef::wrap(self.netlist.index_weak(&operand.root())),
2504                            ));
2505                            self.stacks.push(new_walk);
2506                        }
2507                    }
2508                    self.visited_net.insert((index, secondary));
2509                    return item;
2510                }
2511
2512                if self.visited_net.insert((index, secondary)) {
2513                    return item;
2514                }
2515
2516                return self.next();
2517            }
2518
2519            None
2520        }
2521    }
2522}
2523
2524impl<'a, I> IntoIterator for &'a Netlist<I>
2525where
2526    I: Instantiable,
2527{
2528    type Item = Net;
2529    type IntoIter = iter::NetIterator<'a, I>;
2530
2531    fn into_iter(self) -> Self::IntoIter {
2532        iter::NetIterator::new(self)
2533    }
2534}
2535
2536/// Filter invariants of [Instantiable] in a netlist. Use it like you would `matches!`.
2537/// Example: ```filter_nodes!(netlist, Gate::AND(_));```
2538#[macro_export]
2539macro_rules! filter_nodes {
2540    ($netlist:ident, $pattern:pat $(if $guard:expr)? $(,)?) => {
2541        $netlist.matches(|f| match f {
2542            $pattern $(if $guard)? => true,
2543            _ => false
2544        })
2545    };
2546}
2547
2548impl<I> Netlist<I>
2549where
2550    I: Instantiable,
2551{
2552    /// Returns an iterator over the circuit nodes in the netlist.
2553    pub fn objects(&self) -> impl Iterator<Item = NetRef<I>> {
2554        iter::ObjectIterator::new(self)
2555    }
2556
2557    /// Returns an iterator over the circuit nodes that match the instance type.
2558    pub fn matches<F>(&self, filter: F) -> impl Iterator<Item = NetRef<I>>
2559    where
2560        F: Fn(&I) -> bool,
2561    {
2562        self.objects().filter(move |f| {
2563            if let Some(inst_type) = f.get_instance_type() {
2564                filter(&inst_type)
2565            } else {
2566                false
2567            }
2568        })
2569    }
2570
2571    /// Returns an iterator to principal inputs in the netlist as references.
2572    pub fn inputs(&self) -> impl Iterator<Item = DrivenNet<I>> {
2573        self.objects()
2574            .filter(|n| n.is_an_input())
2575            .map(|n| DrivenNet::new(0, n))
2576    }
2577
2578    /// Returns an iterator to circuit nodes that drive an output in the netlist.
2579    pub fn outputs(&self) -> Vec<(DrivenNet<I>, Net)> {
2580        self.outputs
2581            .borrow()
2582            .iter()
2583            .flat_map(|(k, nets)| {
2584                nets.iter().map(|n| {
2585                    (
2586                        DrivenNet::new(k.secondary(), NetRef::wrap(self.index_weak(&k.root()))),
2587                        n.clone(),
2588                    )
2589                })
2590            })
2591            .collect()
2592    }
2593
2594    /// Returns an iterator over the wire connections in the netlist.
2595    pub fn connections(&self) -> impl Iterator<Item = Connection<I>> {
2596        iter::ConnectionIterator::new(self)
2597    }
2598
2599    /// Returns a depth-first search iterator over the nodes in the netlist.
2600    ///
2601    /// # Panics
2602    /// `from` does not belong to this netlist
2603    pub fn node_dfs(&self, from: NetRef<I>) -> impl Iterator<Item = NetRef<I>> {
2604        self.belongs(&from);
2605        iter::DFSIterator::new(self, from)
2606    }
2607
2608    /// Returns a depth-first search iterator over the nodes in the netlist, with the nodes in DrivenNet form.
2609    ///
2610    /// # Panics
2611    /// `from` does not belong to this netlist
2612    pub fn net_dfs(&self, from: DrivenNet<I>) -> impl Iterator<Item = DrivenNet<I>> {
2613        self.belongs(&from.clone().unwrap());
2614        iter::NetDFSIterator::new(self, from)
2615    }
2616
2617    #[cfg(feature = "serde")]
2618    /// Serializes the netlist to a writer.
2619    pub fn serialize(self, writer: impl std::io::Write) -> Result<(), serde_json::Error>
2620    where
2621        I: ::serde::Serialize,
2622    {
2623        serde::netlist_serialize(self, writer)
2624    }
2625
2626    #[cfg(feature = "graph")]
2627    /// Converts the current configuration of the netlist to a graphviz string
2628    pub fn dot_string(&self) -> Result<String, Error> {
2629        use super::graph::{Edge, MultiDiGraph, Node};
2630        use petgraph::dot::{Config, Dot};
2631        use petgraph::graph::{DiGraph, EdgeReference, NodeIndex};
2632        let analysis = self.get_analysis::<MultiDiGraph<_>>()?;
2633        let graph = analysis.get_graph();
2634
2635        fn node_impl<I: Instantiable>(
2636            _graph: &DiGraph<Node<I, String>, Edge<I, Net>>,
2637            node: (NodeIndex, &Node<I, String>),
2638        ) -> String {
2639            let n = node.1;
2640            let mut attr = String::new();
2641
2642            match n {
2643                Node::NetRef(nr) if nr.get_instance_type().is_some() => attr += "shape=record, ",
2644                _ => attr += "shape=ellipse, ",
2645            }
2646
2647            match n {
2648                Node::NetRef(nr)
2649                    if let Some(inst_type) = nr.get_instance_type()
2650                        && !inst_type.is_driverless() =>
2651                {
2652                    let mut record = "{ { ".to_string();
2653
2654                    let l = nr.get_num_input_ports();
2655                    for (i, port) in nr.inputs().enumerate() {
2656                        let id = port.get_port().get_identifier().clone();
2657                        record += &format!("{{ <{}> {} }}", id, id);
2658
2659                        if i != l - 1 {
2660                            record += " | ";
2661                        }
2662                    }
2663
2664                    record += &format!(
2665                        " }} | {}({}) }}",
2666                        inst_type.get_name(),
2667                        nr.get_instance_name().unwrap()
2668                    );
2669                    attr += &format!("label=\"{record}\"");
2670                }
2671                _ => attr += &format!("label=\"{n}\""),
2672            }
2673
2674            attr
2675        }
2676
2677        fn edge_impl<I: Instantiable>(
2678            _graph: &DiGraph<Node<I, String>, Edge<I, Net>>,
2679            edge: EdgeReference<Edge<I, Net>>,
2680        ) -> String {
2681            match edge.weight() {
2682                Edge::Connection(c) => {
2683                    format!(", port=\"{}\"", c.target().get_port().get_identifier())
2684                }
2685                _ => String::new(),
2686            }
2687        }
2688
2689        let dot = Dot::with_attr_getters(
2690            graph,
2691            &[Config::NodeNoLabel],
2692            &edge_impl::<I>,
2693            &node_impl::<I>,
2694        );
2695
2696        // Post-process to add port specifiers to the edges.
2697        let mut result = String::new();
2698        for line in dot.to_string().lines() {
2699            if line.contains("->") && line.contains("port=") {
2700                let port = line
2701                    .split("port=\"")
2702                    .nth(1)
2703                    .unwrap()
2704                    .split('"')
2705                    .next()
2706                    .unwrap();
2707                let (l, r) = line.split_once("->").unwrap();
2708                let (l, r) = (l, r.trim());
2709                let (d, r) = r.split_once(" ").unwrap();
2710                result += &format!("{l}-> {d}:{port} {r}\n");
2711            } else {
2712                result += line;
2713                result += "\n";
2714            }
2715        }
2716
2717        Ok(result)
2718    }
2719
2720    #[cfg(feature = "graph")]
2721    /// Dumps the current netlist to <module_name>.dot in the current working directory.
2722    pub fn dump_dot(&self) -> std::io::Result<()> {
2723        use std::io::Write;
2724        let mut dir = std::env::current_dir()?;
2725        let mod_name = format!("{}.dot", self.get_name());
2726        dir.push(mod_name);
2727        let mut file = std::fs::File::create(dir)?;
2728        if let Err(e) = self.verify() {
2729            write!(file, "Netlist verification failed: {e}")
2730        } else {
2731            let dot = self.dot_string().unwrap();
2732            write!(file, "{dot}")
2733        }
2734    }
2735}
2736
2737impl<I> std::fmt::Display for Netlist<I>
2738where
2739    I: Instantiable,
2740{
2741    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2742        // Borrow everything first
2743        let objects = self.objects.borrow();
2744        let outputs = self.outputs.borrow();
2745
2746        writeln!(f, "module {} (", self.get_name())?;
2747
2748        // Print inputs and outputs
2749        let level = 2;
2750        let indent = " ".repeat(level);
2751        for oref in objects.iter() {
2752            let owned = oref.borrow();
2753            let obj = owned.get();
2754            if let Object::Input(net) = obj {
2755                writeln!(f, "{}{},", indent, net.get_identifier().emit_name())?;
2756            }
2757        }
2758
2759        // Flatten the outputs to collect all (operand, net) pairs
2760        let all_outputs: Vec<_> = outputs.values().flat_map(|nets| nets.iter()).collect();
2761        for (i, net) in all_outputs.iter().enumerate() {
2762            if i == all_outputs.len() - 1 {
2763                writeln!(f, "{}{}", indent, net.get_identifier().emit_name())?;
2764            } else {
2765                writeln!(f, "{}{},", indent, net.get_identifier().emit_name())?;
2766            }
2767        }
2768        writeln!(f, ");")?;
2769
2770        // Make wire decls
2771        let mut already_decl = HashSet::new();
2772        for oref in objects.iter() {
2773            let owned = oref.borrow();
2774            let obj = owned.get();
2775            if let Object::Input(net) = obj {
2776                writeln!(f, "{}input {};", indent, net.get_identifier().emit_name())?;
2777                writeln!(f, "{}wire {};", indent, net.get_identifier().emit_name())?;
2778                already_decl.insert(net.clone());
2779            }
2780        }
2781        for nets in outputs.values() {
2782            for net in nets {
2783                if !already_decl.contains(net) {
2784                    writeln!(f, "{}output {};", indent, net.get_identifier().emit_name())?;
2785                    writeln!(f, "{}wire {};", indent, net.get_identifier().emit_name())?;
2786                    already_decl.insert(net.clone());
2787                }
2788            }
2789        }
2790        for oref in objects.iter() {
2791            let owned = oref.borrow();
2792            let obj = owned.get();
2793            if let Object::Instance(nets, _, inst_type) = obj
2794                && inst_type.get_constant().is_none()
2795            {
2796                for net in nets.iter() {
2797                    if !already_decl.contains(net) {
2798                        writeln!(f, "{}wire {};", indent, net.get_identifier().emit_name())?;
2799                        already_decl.insert(net.clone());
2800                    }
2801                }
2802            }
2803        }
2804
2805        for oref in objects.iter() {
2806            let owned = oref.borrow();
2807            let obj = owned.get();
2808
2809            // Skip emitting constants as their uses will be hard-wired
2810            if let Some(inst_type) = obj.get_instance_type()
2811                && inst_type.get_constant().is_some()
2812            {
2813                continue;
2814            }
2815
2816            if let Object::Instance(nets, inst_name, inst_type) = obj {
2817                for (k, v) in owned.attributes.iter() {
2818                    if let Some(value) = v {
2819                        writeln!(f, "{indent}(* {k} = \"{value}\" *)")?;
2820                    } else {
2821                        writeln!(f, "{indent}(* {k} *)")?;
2822                    }
2823                }
2824
2825                write!(f, "{}{} ", indent, inst_type.get_name())?;
2826                if inst_type.is_parameterized() {
2827                    writeln!(f, "#(")?;
2828                    let level = 4;
2829                    let indent = " ".repeat(level);
2830                    let params: Vec<_> = inst_type.parameters().collect();
2831                    for (i, (k, v)) in params.iter().enumerate() {
2832                        if i == params.len() - 1 {
2833                            writeln!(f, "{indent}.{k}({v})")?;
2834                        } else {
2835                            writeln!(f, "{indent}.{k}({v}),")?;
2836                        }
2837                    }
2838                    let level = 2;
2839                    let indent = " ".repeat(level);
2840                    write!(f, "{indent}) ")?;
2841                }
2842                writeln!(f, "{} (", inst_name.emit_name())?;
2843                let level = 4;
2844                let indent = " ".repeat(level);
2845                for (idx, port) in inst_type.get_input_ports().into_iter().enumerate() {
2846                    let port_name = port.get_identifier().emit_name();
2847                    if let Some(operand) = owned.operands[idx].as_ref() {
2848                        let operand_net = match operand {
2849                            Operand::DirectIndex(idx) => objects[*idx].borrow().as_net().clone(),
2850                            Operand::CellIndex(idx, j) => {
2851                                objects[*idx].borrow().get_net(*j).clone()
2852                            }
2853                        };
2854
2855                        let operand_str = if let Some(inst_type) =
2856                            objects[operand.root()].borrow().get().get_instance_type()
2857                            && let Some(logic) = inst_type.get_constant()
2858                        {
2859                            logic.to_string()
2860                        } else {
2861                            operand_net.get_identifier().emit_name()
2862                        };
2863
2864                        writeln!(f, "{}.{}({}),", indent, port_name, operand_str)?;
2865                    }
2866                }
2867
2868                for (idx, net) in nets.iter().enumerate() {
2869                    let port_name = inst_type.get_output_port(idx).get_identifier().emit_name();
2870                    if idx == nets.len() - 1 {
2871                        writeln!(
2872                            f,
2873                            "{}.{}({})",
2874                            indent,
2875                            port_name,
2876                            net.get_identifier().emit_name()
2877                        )?;
2878                    } else {
2879                        writeln!(
2880                            f,
2881                            "{}.{}({}),",
2882                            indent,
2883                            port_name,
2884                            net.get_identifier().emit_name()
2885                        )?;
2886                    }
2887                }
2888
2889                let level = 2;
2890                let indent = " ".repeat(level);
2891                writeln!(f, "{indent});")?;
2892            }
2893        }
2894
2895        for (driver, nets) in outputs.iter() {
2896            for net in nets {
2897                let driver_net = match driver {
2898                    Operand::DirectIndex(idx) => self.index_weak(idx).borrow().as_net().clone(),
2899                    Operand::CellIndex(idx, j) => self.index_weak(idx).borrow().get_net(*j).clone(),
2900                };
2901
2902                let driver_str = if let Some(inst_type) = self
2903                    .index_weak(&driver.root())
2904                    .borrow()
2905                    .get()
2906                    .get_instance_type()
2907                    && let Some(logic) = inst_type.get_constant()
2908                {
2909                    logic.to_string()
2910                } else {
2911                    driver_net.get_identifier().emit_name()
2912                };
2913
2914                if net.get_identifier() != driver_net.get_identifier() {
2915                    writeln!(
2916                        f,
2917                        "{}assign {} = {};",
2918                        indent,
2919                        net.get_identifier().emit_name(),
2920                        driver_str
2921                    )?;
2922                }
2923            }
2924        }
2925
2926        writeln!(f, "endmodule")
2927    }
2928}
2929
2930/// A type alias for a netlist of gates
2931pub type GateNetlist = Netlist<Gate>;
2932/// A type alias to Gate circuit nodes
2933pub type GateRef = NetRef<Gate>;
2934
2935#[cfg(test)]
2936mod tests {
2937    use super::iter::{DFSIterator, NetDFSIterator};
2938    use super::*;
2939    #[test]
2940    fn test_delete_netlist() {
2941        let netlist = Netlist::new("simple_example".to_string());
2942
2943        // Add the the two inputs
2944        let input1 = netlist.insert_input("input1".into());
2945        let input2 = netlist.insert_input("input2".into());
2946
2947        // Instantiate an AND gate
2948        let instance = netlist
2949            .insert_gate(
2950                Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into()),
2951                "my_and".into(),
2952                &[input1.clone(), input2.clone()],
2953            )
2954            .unwrap();
2955
2956        // Make this AND gate an output
2957        let instance = instance.expose_as_output().unwrap();
2958        instance.delete_uses().unwrap();
2959        // We can still clean this mostly empty netlist
2960        assert!(netlist.clean().is_ok());
2961        input1.expose_with_name("an_output".into());
2962        assert!(netlist.clean().is_ok());
2963    }
2964
2965    #[test]
2966    #[should_panic(expected = "Attempted to create a gate with a sliced identifier")]
2967    fn gate_w_slice_panics() {
2968        Gate::new_logical("AND[1]".into(), vec!["A".into(), "B".into()], "Y".into());
2969    }
2970
2971    #[test]
2972    fn gates_dont_have_params() {
2973        // The baseline implementation of gates do not have parameters.
2974        let gate = Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into());
2975        assert!(!gate.has_parameter(&"id".into()));
2976        assert!(gate.get_parameter(&"id".into()).is_none());
2977        assert_eq!(*gate.get_gate_name(), "AND".into());
2978    }
2979
2980    #[test]
2981    fn operand_conversions() {
2982        let operand = Operand::CellIndex(3, 2);
2983        assert_eq!(operand.to_string(), "3.2");
2984        let parsed = "3.2".parse::<Operand>();
2985        assert!(parsed.is_ok());
2986        let parsed = parsed.unwrap();
2987        assert_eq!(operand, parsed);
2988    }
2989
2990    #[test]
2991    #[should_panic(expected = "out of bounds for netref")]
2992    fn test_bad_output() {
2993        let netlist = GateNetlist::new("min_module".to_string());
2994        let a = netlist.insert_input("a".into());
2995        DrivenNet::new(1, a.unwrap());
2996    }
2997
2998    #[test]
2999    fn test_netdfsiterator() {
3000        let netlist = Netlist::new("dfs_netlist".to_string());
3001
3002        // inputs
3003        let a = netlist.insert_input("a".into());
3004        let b = netlist.insert_input("b".into());
3005        let c = netlist.insert_input("c".into());
3006        let d = netlist.insert_input("d".into());
3007        let e = netlist.insert_input("e".into());
3008
3009        // gates
3010        let n1 = netlist
3011            .insert_gate(
3012                Gate::new_logical("OR".into(), vec!["A".into(), "B".into()], "Y".into()),
3013                "n1".into(),
3014                &[a.clone(), b.clone()],
3015            )
3016            .unwrap()
3017            .get_output(0);
3018        let n2 = netlist
3019            .insert_gate(
3020                Gate::new_logical("NOR".into(), vec!["A".into(), "B".into()], "Y".into()),
3021                "n2".into(),
3022                &[d.clone(), e.clone()],
3023            )
3024            .unwrap()
3025            .get_output(0);
3026        let n3 = netlist
3027            .insert_gate(
3028                Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into()),
3029                "n3".into(),
3030                &[n1.clone(), c.clone()],
3031            )
3032            .unwrap()
3033            .get_output(0);
3034        let n4 = netlist
3035            .insert_gate(
3036                Gate::new_logical("NAND".into(), vec!["A".into(), "B".into()], "Y".into()),
3037                "n4".into(),
3038                &[n3.clone(), n2.clone()],
3039            )
3040            .unwrap()
3041            .get_output(0);
3042        n4.clone().expose_with_name("y".into());
3043
3044        // test DFSIterator
3045        let mut dfs = NetDFSIterator::new(&netlist, n4.clone());
3046        assert_eq!(dfs.next(), Some(n4));
3047        assert_eq!(dfs.next(), Some(n2));
3048        assert_eq!(dfs.next(), Some(e));
3049        assert_eq!(dfs.next(), Some(d));
3050        assert_eq!(dfs.next(), Some(n3));
3051        assert_eq!(dfs.next(), Some(c));
3052        assert_eq!(dfs.next(), Some(n1));
3053        assert_eq!(dfs.next(), Some(b));
3054        assert_eq!(dfs.next(), Some(a));
3055        assert_eq!(dfs.next(), None);
3056    }
3057
3058    #[test]
3059    fn test_dfs_cycles() {
3060        let netlist = Netlist::new("dfs_cycles".to_string());
3061
3062        // inputs
3063        let a = netlist.insert_input("a".into());
3064
3065        // gates
3066        let and = netlist.insert_gate_disconnected(
3067            Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into()),
3068            "and".into(),
3069        );
3070
3071        // connect and form cycle
3072        a.connect(and.get_input(0));
3073        and.get_output(0).connect(and.get_input(1));
3074
3075        // test dfs iterators
3076        let dfs = DFSIterator::new(&netlist, and.clone());
3077        let driven_dfs = NetDFSIterator::new(&netlist, and.get_output(0));
3078
3079        assert!(dfs.detect_cycles());
3080        assert!(driven_dfs.detect_cycles());
3081    }
3082
3083    #[test]
3084    fn test_netdfsiterator_with_boundary() {
3085        let netlist = Netlist::new("dfs_netlist".to_string());
3086
3087        // inputs
3088        let a = netlist.insert_input("a".into());
3089        let b = netlist.insert_input("b".into());
3090        let c = netlist.insert_input("c".into());
3091        let d = netlist.insert_input("d".into());
3092        let e = netlist.insert_input("e".into());
3093
3094        // gates
3095        let n1 = netlist
3096            .insert_gate(
3097                Gate::new_logical("OR".into(), vec!["A".into(), "B".into()], "Y".into()),
3098                "n1".into(),
3099                &[a.clone(), b.clone()],
3100            )
3101            .unwrap()
3102            .get_output(0);
3103        let n2 = netlist
3104            .insert_gate(
3105                Gate::new_logical("NOR".into(), vec!["A".into(), "B".into()], "Y".into()),
3106                "n2".into(),
3107                &[d.clone(), e.clone()],
3108            )
3109            .unwrap()
3110            .get_output(0);
3111        let n3 = netlist
3112            .insert_gate(
3113                Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into()),
3114                "n3".into(),
3115                &[n1.clone(), c.clone()],
3116            )
3117            .unwrap()
3118            .get_output(0);
3119        let n4 = netlist
3120            .insert_gate(
3121                Gate::new_logical("NAND".into(), vec!["A".into(), "B".into()], "Y".into()),
3122                "n4".into(),
3123                &[n3.clone(), n2.clone()],
3124            )
3125            .unwrap()
3126            .get_output(0);
3127
3128        // Stop DFS expansion at n3 to emulate a traversal boundary.
3129        let n3_boundary = n3.clone();
3130        let mut dfs =
3131            NetDFSIterator::new_filtered(&netlist, n4.clone(), move |n| *n == n3_boundary);
3132        assert_eq!(dfs.next(), Some(n4));
3133        assert_eq!(dfs.next(), Some(n2));
3134        assert_eq!(dfs.next(), Some(e));
3135        assert_eq!(dfs.next(), Some(d));
3136        assert_eq!(dfs.next(), Some(n3));
3137        assert_eq!(dfs.next(), None);
3138    }
3139
3140    #[test]
3141    fn test_dfs_convergence() {
3142        let netlist = GateNetlist::new("example".to_string());
3143        let gate = Gate::new_logical_multi(
3144            "FA".into(),
3145            vec!["A".into(), "B".into()],
3146            vec!["S".into(), "COUT".into()],
3147        );
3148        let a = netlist.insert_input("a".into());
3149        let b = netlist.insert_input("b".into());
3150        let gate = netlist.insert_gate(gate, "g".into(), &[a, b]).unwrap();
3151        let s = gate.get_output(0);
3152        let c = gate.get_output(1);
3153        let gate = Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into());
3154        let d = netlist.insert_gate(gate, "h".into(), &[s, c]).unwrap();
3155
3156        let dfs = NetDFSIterator::new(&netlist, d.get_output(0));
3157        let c = dfs.count();
3158        assert_eq!(c, 5);
3159
3160        let dfs = DFSIterator::new(&netlist, d.clone());
3161        let c = dfs.count();
3162        assert_eq!(c, 4);
3163    }
3164}
3165#[cfg(feature = "serde")]
3166/// Serde support for netlists
3167pub mod serde {
3168    use super::{Netlist, Operand, OwnedObject, WeakIndex};
3169    use crate::{
3170        attribute::{AttributeKey, AttributeValue},
3171        circuit::{Instantiable, Net, Object},
3172    };
3173    use serde::{Deserialize, Serialize, de::DeserializeOwned};
3174    use std::cell::RefCell;
3175    use std::{
3176        collections::{BTreeSet, HashMap},
3177        rc::Rc,
3178    };
3179
3180    #[derive(Debug, Serialize, Deserialize)]
3181    struct SerdeObject<I>
3182    where
3183        I: Instantiable + Serialize,
3184    {
3185        /// The object that is owned by the netlist
3186        object: Object<I>,
3187        /// The list of operands for the object
3188        operands: Vec<Option<Operand>>,
3189        /// A collection of attributes for the object
3190        attributes: HashMap<AttributeKey, AttributeValue>,
3191    }
3192
3193    impl<I, O> From<OwnedObject<I, O>> for SerdeObject<I>
3194    where
3195        I: Instantiable + Serialize,
3196        O: WeakIndex<usize, Output = OwnedObject<I, O>>,
3197    {
3198        fn from(value: OwnedObject<I, O>) -> Self {
3199            SerdeObject {
3200                object: value.object,
3201                operands: value.operands,
3202                attributes: value.attributes,
3203            }
3204        }
3205    }
3206
3207    impl<I> SerdeObject<I>
3208    where
3209        I: Instantiable + Serialize,
3210    {
3211        fn into_owned_object<O>(self, owner: &Rc<O>, index: usize) -> OwnedObject<I, O>
3212        where
3213            O: WeakIndex<usize, Output = OwnedObject<I, O>>,
3214        {
3215            OwnedObject {
3216                object: self.object,
3217                owner: Rc::downgrade(owner),
3218                operands: self.operands,
3219                attributes: self.attributes,
3220                index,
3221            }
3222        }
3223    }
3224
3225    #[derive(Debug, Serialize, Deserialize)]
3226    struct SerdeNetlist<I>
3227    where
3228        I: Instantiable + Serialize,
3229    {
3230        /// The name of the netlist
3231        name: String,
3232        /// The list of objects in the netlist, such as inputs, modules, and primitives
3233        objects: Vec<SerdeObject<I>>,
3234        /// The list of operands that point to objects which are outputs.
3235        /// Indices must be a string if we want to support JSON.
3236        /// Each operand can map to multiple nets, supporting output aliases.
3237        outputs: HashMap<String, BTreeSet<Net>>,
3238    }
3239
3240    impl<I> From<Netlist<I>> for SerdeNetlist<I>
3241    where
3242        I: Instantiable + Serialize,
3243    {
3244        fn from(value: Netlist<I>) -> Self {
3245            SerdeNetlist {
3246                name: value.name.into_inner(),
3247                objects: value
3248                    .objects
3249                    .into_inner()
3250                    .into_iter()
3251                    .map(|o| {
3252                        Rc::try_unwrap(o)
3253                            .ok()
3254                            .expect("Cannot serialize with live references")
3255                            .into_inner()
3256                            .into()
3257                    })
3258                    .collect(),
3259                outputs: value
3260                    .outputs
3261                    .into_inner()
3262                    .into_iter()
3263                    // Indices must be a string if we want to support JSON.
3264                    .map(|(o, nets)| (o.to_string(), nets.into_iter().collect()))
3265                    .collect(),
3266            }
3267        }
3268    }
3269
3270    impl<I> SerdeNetlist<I>
3271    where
3272        I: Instantiable + Serialize,
3273    {
3274        /// Convert the serialized netlist back into a reference-counted netlist.
3275        fn into_netlist(self) -> Rc<Netlist<I>> {
3276            let netlist = Netlist::new(self.name);
3277            let outputs: HashMap<Operand, BTreeSet<Net>> = self
3278                .outputs
3279                .into_iter()
3280                .map(|(k, v)| {
3281                    let operand = k.parse::<Operand>().expect("Invalid index");
3282                    (operand, v.into_iter().collect())
3283                })
3284                .collect();
3285            let objects = self
3286                .objects
3287                .into_iter()
3288                .enumerate()
3289                .map(|(i, o)| {
3290                    let owned_object = o.into_owned_object(&netlist, i);
3291                    Rc::new(RefCell::new(owned_object))
3292                })
3293                .collect::<Vec<_>>();
3294            {
3295                let mut objs_mut = netlist.objects.borrow_mut();
3296                *objs_mut = objects;
3297                let mut outputs_mut = netlist.outputs.borrow_mut();
3298                *outputs_mut = outputs;
3299            }
3300            netlist
3301        }
3302    }
3303
3304    /// Serialize the netlist into the writer.
3305    pub fn netlist_serialize<I: Instantiable + Serialize>(
3306        netlist: Netlist<I>,
3307        writer: impl std::io::Write,
3308    ) -> Result<(), serde_json::Error> {
3309        let sobj: SerdeNetlist<I> = netlist.into();
3310        serde_json::to_writer_pretty(writer, &sobj)
3311    }
3312
3313    /// Deserialize a netlist from the reader.
3314    pub fn netlist_deserialize<I: Instantiable + Serialize + DeserializeOwned>(
3315        reader: impl std::io::Read,
3316    ) -> Result<Rc<Netlist<I>>, serde_json::Error> {
3317        let sobj: SerdeNetlist<I> = serde_json::from_reader(reader)?;
3318        Ok(sobj.into_netlist())
3319    }
3320}