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::{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, 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> std::hash::Hash for NetRef<I>
479where
480    I: Instantiable,
481{
482    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
483        Rc::as_ptr(&self.netref).hash(state);
484    }
485}
486
487impl<I> NetRef<I>
488where
489    I: Instantiable,
490{
491    /// Creates a new [NetRef] from a [NetRefT]
492    fn wrap(netref: NetRefT<I>) -> Self {
493        Self { netref }
494    }
495
496    /// Returns the underlying [NetRefT]
497    fn unwrap(self) -> NetRefT<I> {
498        self.netref
499    }
500
501    /// Returns a borrow to the [Net] at this circuit node.
502    ///
503    /// # Panics
504    ///
505    /// Panics if the circuit node has multiple outputs.
506    pub fn as_net(&self) -> Ref<'_, Net> {
507        Ref::map(self.netref.borrow(), |f| f.as_net())
508    }
509
510    /// Returns a mutable borrow to the [Net] at this circuit node.
511    ///
512    /// # Panics
513    ///
514    /// Panics if the circuit node has multiple outputs.
515    pub fn as_net_mut(&self) -> RefMut<'_, Net> {
516        RefMut::map(self.netref.borrow_mut(), |f| f.as_net_mut())
517    }
518
519    /// Returns a borrow to the output [Net] as position `idx`
520    pub fn get_net(&self, idx: usize) -> Ref<'_, Net> {
521        Ref::map(self.netref.borrow(), |f| f.get_net(idx))
522    }
523
524    /// Returns a mutable borrow to the output [Net] as position `idx`
525    pub fn get_net_mut(&self, idx: usize) -> RefMut<'_, Net> {
526        RefMut::map(self.netref.borrow_mut(), |f| f.get_net_mut(idx))
527    }
528
529    /// Returns a borrow to the output [Net] as position `idx`
530    pub fn get_output(&self, idx: usize) -> DrivenNet<I> {
531        DrivenNet::new(idx, self.clone())
532    }
533
534    /// Returns a borrow to the output connected to port `id`
535    pub fn find_output(&self, id: &Identifier) -> Option<DrivenNet<I>> {
536        let ind = self.get_instance_type()?.find_output(id)?;
537        Some(self.get_output(ind))
538    }
539
540    /// Returns an abstraction around the input connection
541    pub fn get_input(&self, idx: usize) -> InputPort<I> {
542        if self.is_an_input() {
543            panic!("Principal inputs do not have inputs");
544        }
545        InputPort::new(idx, self.clone())
546    }
547
548    /// Returns a borrow to the input port with name `id`
549    pub fn find_input(&self, id: &Identifier) -> Option<InputPort<I>> {
550        let ind = self.get_instance_type()?.find_input(id)?;
551        Some(self.get_input(ind))
552    }
553
554    /// Returns the name of the net at this circuit node.
555    ///
556    /// # Panics
557    ///
558    /// Panics if the circuit node has multiple outputs.
559    pub fn get_identifier(&self) -> Identifier {
560        self.as_net().get_identifier().clone()
561    }
562
563    /// Changes the identifier of the net at this circuit node.
564    ///
565    /// # Panics
566    ///
567    /// Panics if the circuit node has multiple outputs.
568    pub fn set_identifier(&self, identifier: Identifier) {
569        self.as_net_mut().set_identifier(identifier)
570    }
571
572    /// Returns `true` if this circuit node is a principal input
573    pub fn is_an_input(&self) -> bool {
574        matches!(self.netref.borrow().get(), Object::Input(_))
575    }
576
577    /// Returns a reference to the object at this node.
578    pub fn get_obj(&self) -> Ref<'_, Object<I>> {
579        Ref::map(self.netref.borrow(), |f| f.get())
580    }
581
582    /// Returns the [Instantiable] type of the instance, if this circuit node is an instance
583    pub fn get_instance_type(&self) -> Option<Ref<'_, I>> {
584        Ref::filter_map(self.netref.borrow(), |f| f.get().get_instance_type()).ok()
585    }
586
587    /// Returns the [Instantiable] type of the instance, if this circuit node is an instance
588    pub fn get_instance_type_mut(&self) -> Option<RefMut<'_, I>> {
589        RefMut::filter_map(self.netref.borrow_mut(), |f| {
590            f.get_mut().get_instance_type_mut()
591        })
592        .ok()
593    }
594
595    /// Returns a copy of the name of the instance, if the circuit node is a instance.
596    pub fn get_instance_name(&self) -> Option<Identifier> {
597        match self.netref.borrow().get() {
598            Object::Instance(_, inst_name, _) => Some(inst_name.clone()),
599            _ => None,
600        }
601    }
602
603    /// Updates the name of the instance, if the circuit node is an instance.
604    ///
605    /// # Panics
606    ///
607    /// Panics if the circuit node is a principal input.
608    pub fn set_instance_name(&self, name: Identifier) {
609        match self.netref.borrow_mut().get_mut() {
610            Object::Instance(_, inst_name, _) => *inst_name = name,
611            _ => panic!("Attempted to set instance name on a non-instance object"),
612        }
613    }
614
615    /// Exposes this circuit node as a top-level output in the netlist.
616    /// Returns an error if the circuit node is a principal input.
617    ///
618    /// # Panics
619    ///
620    /// Panics if cell is a multi-output circuit node.
621    /// Panics if the reference to the netlist is lost.
622    pub fn expose_as_output(self) -> Result<Self, Error> {
623        let netlist = self
624            .netref
625            .borrow()
626            .owner
627            .upgrade()
628            .expect("NetRef is unlinked from netlist");
629        netlist.expose_net(self.clone().into())?;
630        Ok(self)
631    }
632
633    /// Exposes this circuit node as a top-level output in the netlist with a specific port name.
634    ///
635    /// # Panics
636    ///
637    /// Panics if the cell is a multi-output circuit node.
638    /// Panics if the reference to the netlist is lost.
639    pub fn expose_with_name(self, name: Identifier) -> Self {
640        let netlist = self
641            .netref
642            .borrow()
643            .owner
644            .upgrade()
645            .expect("NetRef is unlinked from netlist");
646        netlist.expose_net_with_name(self.clone().into(), name);
647        self
648    }
649
650    /// Exposes the `net` driven by this circuit node as a top-level output.
651    /// Errors if `net` is not driven by this circuit node.
652    ///
653    /// # Panics
654    /// Panics if the reference to the netlist is lost.
655    pub fn expose_net(&self, net: &Net) -> Result<(), Error> {
656        let netlist = self
657            .netref
658            .borrow()
659            .owner
660            .upgrade()
661            .expect("NetRef is unlinked from netlist");
662        let net_index = self
663            .netref
664            .borrow()
665            .find_net(net)
666            .ok_or(Error::NetNotFound(net.clone()))?;
667        let dr = DrivenNet::new(net_index, self.clone());
668        netlist.expose_net(dr)?;
669        Ok(())
670    }
671
672    /// Returns the circuit node that drives the `index`th input
673    pub fn get_driver(&self, index: usize) -> Option<Self> {
674        self.netref.borrow().get_driver(index).map(NetRef::wrap)
675    }
676
677    /// Returns the net that drives the `index`th input
678    ///
679    /// # Panics
680    ///
681    /// Panics if the reference to the netlist is lost.
682    pub fn get_driver_net(&self, index: usize) -> Option<Net> {
683        self.netref.borrow().get_driver_net(index)
684    }
685
686    /// Returns a request to mutably borrow the operand net
687    /// This requires another borrow in the form of [MutBorrowReq]
688    ///
689    /// # Panics
690    ///
691    /// Panics if the reference to the netlist is lost.
692    pub fn req_driver_net(&self, index: usize) -> Option<MutBorrowReq<I>> {
693        let net = self.get_driver_net(index)?;
694        let operand = self.get_driver(index).unwrap();
695        Some(MutBorrowReq::new(operand, net))
696    }
697
698    /// Returns the number of input ports for this circuit node.
699    pub fn get_num_input_ports(&self) -> usize {
700        if let Some(inst_type) = self.get_instance_type() {
701            inst_type.get_input_ports().into_iter().count()
702        } else {
703            0
704        }
705    }
706
707    /// Returns `true` if this circuit node has all its input ports connected.
708    pub fn is_fully_connected(&self) -> bool {
709        assert_eq!(
710            self.netref.borrow().operands.len(),
711            self.get_num_input_ports()
712        );
713        self.netref.borrow().operands.iter().all(|o| o.is_some())
714    }
715
716    /// Returns an iterator to the driving circuit nodes.
717    pub fn drivers(&self) -> impl Iterator<Item = Option<Self>> {
718        let drivers: Vec<Option<Self>> = self
719            .netref
720            .borrow()
721            .drivers()
722            .map(|o| o.map(NetRef::wrap))
723            .collect();
724        drivers.into_iter()
725    }
726
727    /// Returns an interator to the driving nets.
728    pub fn driver_nets(&self) -> impl Iterator<Item = Option<Net>> {
729        let vec: Vec<Option<Net>> = self.netref.borrow().driver_nets().collect();
730        vec.into_iter()
731    }
732
733    /// Returns an iterator to the output nets of this circuit node.
734    #[allow(clippy::unnecessary_to_owned)]
735    pub fn nets(&self) -> impl Iterator<Item = Net> {
736        self.netref.borrow().get().get_nets().to_vec().into_iter()
737    }
738
739    /// Returns an iterator to the output nets of this circuit node, along with port information.
740    pub fn inputs(&self) -> impl Iterator<Item = InputPort<I>> {
741        let len = self.netref.borrow().operands.len();
742        (0..len).map(move |i| InputPort::new(i, self.clone()))
743    }
744
745    /// Returns an iterator to the output nets of this circuit node, along with port information.
746    pub fn outputs(&self) -> impl Iterator<Item = DrivenNet<I>> {
747        let len = self.netref.borrow().get().get_nets().len();
748        (0..len).map(move |i| DrivenNet::new(i, self.clone()))
749    }
750
751    /// Returns an iterator to mutate the output nets of this circuit node.
752    pub fn nets_mut(&self) -> impl Iterator<Item = RefMut<'_, Net>> {
753        let nnets = self.netref.borrow().get().get_nets().len();
754        (0..nnets).map(|i| self.get_net_mut(i))
755    }
756
757    /// Returns `true` if this circuit node drives the given net.
758    pub fn drives_net(&self, net: &Net) -> bool {
759        self.netref.borrow().find_net(net).is_some()
760    }
761
762    /// Returns `true` if this circuit node drives a top-level output.
763    ///
764    /// # Panics
765    /// Panics if the weak reference to the netlist is lost.
766    pub fn drives_a_top_output(&self) -> bool {
767        let netlist = self
768            .netref
769            .borrow()
770            .owner
771            .upgrade()
772            .expect("NetRef is unlinked from netlist");
773        netlist.drives_an_output(self.clone())
774    }
775
776    /// Attempts to find a mutable reference to `net` within this circuit node.
777    pub fn find_net_mut(&self, net: &Net) -> Option<RefMut<'_, Net>> {
778        RefMut::filter_map(self.netref.borrow_mut(), |f| f.find_net_mut(net)).ok()
779    }
780
781    /// Returns `true` if this circuit node has multiple outputs/nets.
782    pub fn is_multi_output(&self) -> bool {
783        self.netref.borrow().get().get_nets().len() > 1
784    }
785
786    /// Deletes the uses of this circuit node from the netlist.
787    ///
788    /// # Panics
789    ///
790    /// Panics if the reference to the netlist is lost.
791    pub fn delete_uses(self) -> Result<Object<I>, Error> {
792        let netlist = self
793            .netref
794            .borrow()
795            .owner
796            .upgrade()
797            .expect("NetRef is unlinked from netlist");
798        netlist.delete_net_uses(self)
799    }
800
801    /// Replaces the uses of this circuit node in the netlist with another circuit node.
802    ///
803    /// # Panics
804    ///
805    /// Panics if either `self` is a multi-output circuit node.
806    /// Panics if the weak reference to the netlist is lost.
807    pub fn replace_uses_with(self, other: &DrivenNet<I>) -> Result<Object<I>, Error> {
808        let netlist = self
809            .netref
810            .borrow()
811            .owner
812            .upgrade()
813            .expect("NetRef is unlinked from netlist");
814        netlist.replace_net_uses(self.into(), other)
815    }
816
817    /// Clears the attribute with the given key on this circuit node.
818    pub fn clear_attribute(&self, k: &AttributeKey) -> Option<AttributeValue> {
819        self.netref.borrow_mut().clear_attribute(k)
820    }
821
822    /// Set an attribute without a value
823    pub fn set_attribute(&self, k: AttributeKey) {
824        self.netref.borrow_mut().set_attribute(k);
825    }
826
827    /// Insert an attribute on this node with a value
828    pub fn insert_attribute(&self, k: AttributeKey, v: String) -> Option<AttributeValue> {
829        self.netref.borrow_mut().insert_attribute(k, v)
830    }
831
832    /// Returns an iterator to the attributes at this circuit node
833    pub fn attributes(&self) -> impl Iterator<Item = Attribute> {
834        let v: Vec<_> = self.netref.borrow().attributes().collect();
835        v.into_iter()
836    }
837}
838
839impl<I> std::fmt::Display for NetRef<I>
840where
841    I: Instantiable,
842{
843    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
844        self.netref.borrow().object.fmt(f)
845    }
846}
847
848impl<I> From<NetRef<I>> for DrivenNet<I>
849where
850    I: Instantiable,
851{
852    fn from(val: NetRef<I>) -> Self {
853        if val.is_multi_output() {
854            panic!("Cannot convert a multi-output netref to an output port");
855        }
856        DrivenNet::new(0, val)
857    }
858}
859
860impl<I> From<&NetRef<I>> for DrivenNet<I>
861where
862    I: Instantiable,
863{
864    fn from(val: &NetRef<I>) -> Self {
865        if val.is_multi_output() {
866            panic!("Cannot convert a multi-output netref to an output port");
867        }
868        DrivenNet::new(0, val.clone())
869    }
870}
871
872/// Facilitates mutable borrows to driver nets
873pub struct MutBorrowReq<I: Instantiable> {
874    from: NetRef<I>,
875    ind: Net,
876}
877
878impl<I> MutBorrowReq<I>
879where
880    I: Instantiable,
881{
882    /// Creates a new mutable borrow request
883    fn new(from: NetRef<I>, ind: Net) -> Self {
884        Self { from, ind }
885    }
886
887    /// Mutably borrows the requested net from the circuit node
888    pub fn borrow_mut(&self) -> RefMut<'_, Net> {
889        self.from.find_net_mut(&self.ind).unwrap()
890    }
891
892    /// Returns `true` if the circuit node is an input
893    pub fn is_an_input(&self) -> bool {
894        self.from.is_an_input()
895    }
896
897    /// Attempts to borrow the net mutably if the condition `f` is satisfied.
898    pub fn borrow_mut_if(&self, f: impl Fn(&NetRef<I>) -> bool) -> Option<RefMut<'_, Net>> {
899        if f(&self.from) {
900            Some(self.borrow_mut())
901        } else {
902            None
903        }
904    }
905}
906
907/// A netlist data structure
908#[derive(Debug)]
909pub struct Netlist<I>
910where
911    I: Instantiable,
912{
913    /// The name of the netlist
914    name: RefCell<String>,
915    /// The list of objects in the netlist, such as inputs, modules, and primitives
916    objects: RefCell<Vec<NetRefT<I>>>,
917    /// The list of operands that point to objects which are outputs
918    outputs: RefCell<HashMap<Operand, Net>>,
919}
920
921/// Represent the input port of a primitive
922#[derive(Debug, Clone)]
923pub struct InputPort<I: Instantiable> {
924    pos: usize,
925    netref: NetRef<I>,
926}
927
928impl<I> InputPort<I>
929where
930    I: Instantiable,
931{
932    fn new(pos: usize, netref: NetRef<I>) -> Self {
933        if pos >= netref.clone().unwrap().borrow().operands.len() {
934            panic!(
935                "Position {} out of bounds for netref with {} input nets",
936                pos,
937                netref.unwrap().borrow().get().get_nets().len()
938            );
939        }
940        Self { pos, netref }
941    }
942
943    /// Returns the net that is driving this input port
944    pub fn get_driver(&self) -> Option<DrivenNet<I>> {
945        if self.netref.is_an_input() {
946            panic!("Input port is not driven by a primitive");
947        }
948        if let Some(prev_operand) = self.netref.clone().unwrap().borrow().operands[self.pos].clone()
949        {
950            let netlist = self
951                .netref
952                .clone()
953                .unwrap()
954                .borrow()
955                .owner
956                .upgrade()
957                .expect("Input port is unlinked from netlist");
958            let driver_nr = netlist.index_weak(&prev_operand.root());
959            let nr = NetRef::wrap(driver_nr);
960            let pos = prev_operand.secondary();
961            Some(DrivenNet::new(pos, nr))
962        } else {
963            None
964        }
965    }
966
967    /// Disconnects an input port and returns the previous [DrivenNet] if it was connected.
968    pub fn disconnect(&self) -> Option<DrivenNet<I>> {
969        let val = self.get_driver();
970        self.netref.clone().unwrap().borrow_mut().operands[self.pos] = None;
971        val
972    }
973
974    /// Get the input port associated with this connection
975    pub fn get_port(&self) -> Net {
976        if self.netref.is_an_input() {
977            panic!("Net is not driven by a primitive");
978        }
979        self.netref
980            .get_instance_type()
981            .unwrap()
982            .get_input_port(self.pos)
983            .clone()
984    }
985
986    /// Connects this input port to a driven net.
987    pub fn connect(self, output: DrivenNet<I>) {
988        output.connect(self);
989    }
990
991    /// Return the underlying circuit node
992    pub fn unwrap(self) -> NetRef<I> {
993        self.netref
994    }
995}
996
997impl<I> std::fmt::Display for InputPort<I>
998where
999    I: Instantiable,
1000{
1001    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1002        self.get_port().fmt(f)
1003    }
1004}
1005
1006/// Represent a net that is being driven by a [Instantiable]
1007#[derive(Debug, Clone)]
1008pub struct DrivenNet<I: Instantiable> {
1009    pos: usize,
1010    netref: NetRef<I>,
1011}
1012
1013impl<I> DrivenNet<I>
1014where
1015    I: Instantiable,
1016{
1017    fn new(pos: usize, netref: NetRef<I>) -> Self {
1018        if pos >= netref.clone().unwrap().borrow().get().get_nets().len() {
1019            panic!(
1020                "Position {} out of bounds for netref with {} outputted nets",
1021                pos,
1022                netref.unwrap().borrow().get().get_nets().len()
1023            );
1024        }
1025        Self { pos, netref }
1026    }
1027
1028    /// Returns the index that can address this net in the netlist.
1029    fn get_operand(&self) -> Operand {
1030        if self.netref.is_multi_output() {
1031            Operand::CellIndex(self.netref.clone().unwrap().borrow().get_index(), self.pos)
1032        } else {
1033            Operand::DirectIndex(self.netref.clone().unwrap().borrow().get_index())
1034        }
1035    }
1036
1037    /// Borrow the net being driven
1038    pub fn as_net(&self) -> Ref<'_, Net> {
1039        self.netref.get_net(self.pos)
1040    }
1041
1042    /// Get a mutable reference to the net being driven
1043    pub fn as_net_mut(&self) -> RefMut<'_, Net> {
1044        self.netref.get_net_mut(self.pos)
1045    }
1046
1047    /// Returns `true` if this net is a principal input
1048    pub fn is_an_input(&self) -> bool {
1049        self.netref.is_an_input()
1050    }
1051
1052    /// Get the output port associated with this connection
1053    pub fn get_port(&self) -> Net {
1054        if self.netref.is_an_input() {
1055            panic!("Net is not driven by a primitive");
1056        }
1057        self.netref
1058            .get_instance_type()
1059            .unwrap()
1060            .get_output_port(self.pos)
1061            .clone()
1062    }
1063
1064    /// Connects the net driven by this output port to the given input port.
1065    pub fn connect(&self, input: InputPort<I>) {
1066        let operand = self.get_operand();
1067        let index = input.netref.unwrap().borrow().get_index();
1068        let netlist = self
1069            .netref
1070            .clone()
1071            .unwrap()
1072            .borrow()
1073            .owner
1074            .upgrade()
1075            .expect("Output port is unlinked from netlist");
1076        let obj = netlist.index_weak(&index);
1077        obj.borrow_mut().operands[input.pos] = Some(operand.clone());
1078    }
1079
1080    /// Returns `true` if this net is a top-level output in the netlist.
1081    pub fn is_top_level_output(&self) -> bool {
1082        let netlist = self
1083            .netref
1084            .clone()
1085            .unwrap()
1086            .borrow()
1087            .owner
1088            .upgrade()
1089            .expect("DrivenNet is unlinked from netlist");
1090        let outputs = netlist.outputs.borrow();
1091        outputs.contains_key(&self.get_operand())
1092    }
1093
1094    /// Return the underlying circuit node
1095    pub fn unwrap(self) -> NetRef<I> {
1096        self.netref
1097    }
1098
1099    /// Returns a copy of the identifier of the net being driven.
1100    pub fn get_identifier(&self) -> Identifier {
1101        self.as_net().get_identifier().clone()
1102    }
1103
1104    /// Expose this driven net as a module output
1105    ///
1106    /// # Panics
1107    ///
1108    /// Panics if the weak reference to the netlist is dead.
1109    pub fn expose_with_name(self, name: Identifier) -> Self {
1110        let netlist = self
1111            .netref
1112            .clone()
1113            .unwrap()
1114            .borrow()
1115            .owner
1116            .upgrade()
1117            .expect("DrivenNet is unlinked from netlist");
1118        netlist.expose_net_with_name(self.clone(), name);
1119        self
1120    }
1121
1122    /// Returns the output position, if the net is the output of a gate.
1123    pub fn get_output_index(&self) -> Option<usize> {
1124        if self.netref.is_an_input() {
1125            None
1126        } else {
1127            Some(self.pos)
1128        }
1129    }
1130
1131    /// Returns the [Instantiable] type driving this net, if it has a driver.
1132    pub fn get_instance_type(&self) -> Option<Ref<'_, I>> {
1133        self.netref.get_instance_type()
1134    }
1135}
1136
1137impl<I> std::fmt::Display for DrivenNet<I>
1138where
1139    I: Instantiable,
1140{
1141    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1142        self.as_net().fmt(f)
1143    }
1144}
1145
1146impl<I> PartialEq for DrivenNet<I>
1147where
1148    I: Instantiable,
1149{
1150    fn eq(&self, other: &Self) -> bool {
1151        self.netref == other.netref && self.pos == other.pos
1152    }
1153}
1154
1155impl<I> Eq for DrivenNet<I> where I: Instantiable {}
1156
1157impl<I> std::hash::Hash for DrivenNet<I>
1158where
1159    I: Instantiable,
1160{
1161    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1162        self.netref.hash(state);
1163        self.pos.hash(state);
1164    }
1165}
1166
1167impl<I> WeakIndex<usize> for Netlist<I>
1168where
1169    I: Instantiable,
1170{
1171    type Output = OwnedObject<I, Self>;
1172
1173    fn index_weak(&self, index: &usize) -> Rc<RefCell<Self::Output>> {
1174        self.objects.borrow()[*index].clone()
1175    }
1176}
1177
1178impl<I> Netlist<I>
1179where
1180    I: Instantiable,
1181{
1182    /// Creates a new netlist with the given name
1183    pub fn new(name: String) -> Rc<Self> {
1184        Rc::new(Self {
1185            name: RefCell::new(name),
1186            objects: RefCell::new(Vec::new()),
1187            outputs: RefCell::new(HashMap::new()),
1188        })
1189    }
1190
1191    /// Attempts to reclaim the netlist, returning [Some] if successful.
1192    pub fn reclaim(self: Rc<Self>) -> Option<Self> {
1193        Rc::try_unwrap(self).ok()
1194    }
1195
1196    /// Use interior mutability to add an object to the netlist. Returns a mutable reference to the created object.
1197    fn insert_object(
1198        self: &Rc<Self>,
1199        object: Object<I>,
1200        operands: &[DrivenNet<I>],
1201    ) -> Result<NetRef<I>, Error> {
1202        let index = self.objects.borrow().len();
1203        let weak = Rc::downgrade(self);
1204        let operands = operands
1205            .iter()
1206            .map(|net| Some(net.get_operand()))
1207            .collect::<Vec<_>>();
1208        let owned_object = Rc::new(RefCell::new(OwnedObject {
1209            object,
1210            owner: weak,
1211            operands,
1212            attributes: HashMap::new(),
1213            index,
1214        }));
1215        self.objects.borrow_mut().push(owned_object.clone());
1216        Ok(NetRef::wrap(owned_object))
1217    }
1218
1219    /// Inserts an input net to the netlist
1220    pub fn insert_input(self: &Rc<Self>, net: Net) -> DrivenNet<I> {
1221        let obj = Object::Input(net);
1222        self.insert_object(obj, &[]).unwrap().into()
1223    }
1224
1225    /// Inserts a four-state logic input port to the netlist
1226    pub fn insert_input_escaped_logic_bus(
1227        self: &Rc<Self>,
1228        net: String,
1229        bw: usize,
1230    ) -> Vec<DrivenNet<I>> {
1231        Net::new_escaped_logic_bus(net, bw)
1232            .into_iter()
1233            .map(|n| self.insert_input(n))
1234            .collect()
1235    }
1236
1237    /// Inserts a gate to the netlist
1238    pub fn insert_gate(
1239        self: &Rc<Self>,
1240        inst_type: I,
1241        inst_name: Identifier,
1242        operands: &[DrivenNet<I>],
1243    ) -> Result<NetRef<I>, Error> {
1244        let nets = inst_type
1245            .get_output_ports()
1246            .into_iter()
1247            .map(|pnet| pnet.with_name(&inst_name + pnet.get_identifier()))
1248            .collect::<Vec<_>>();
1249        let input_count = inst_type.get_input_ports().into_iter().count();
1250        if operands.len() != input_count {
1251            return Err(Error::ArgumentMismatch(input_count, operands.len()));
1252        }
1253        let obj = Object::Instance(nets, inst_name, inst_type);
1254        self.insert_object(obj, operands)
1255    }
1256
1257    /// Use interior mutability to add an object to the netlist. Returns a mutable reference to the created object.
1258    pub fn insert_gate_disconnected(
1259        self: &Rc<Self>,
1260        inst_type: I,
1261        inst_name: Identifier,
1262    ) -> NetRef<I> {
1263        let nets = inst_type
1264            .get_output_ports()
1265            .into_iter()
1266            .map(|pnet| pnet.with_name(&inst_name + pnet.get_identifier()))
1267            .collect::<Vec<_>>();
1268        let object = Object::Instance(nets, inst_name, inst_type);
1269        let index = self.objects.borrow().len();
1270        let weak = Rc::downgrade(self);
1271        let input_count = object
1272            .get_instance_type()
1273            .unwrap()
1274            .get_input_ports()
1275            .into_iter()
1276            .count();
1277        let operands = vec![None; input_count];
1278        let owned_object = Rc::new(RefCell::new(OwnedObject {
1279            object,
1280            owner: weak,
1281            operands,
1282            attributes: HashMap::new(),
1283            index,
1284        }));
1285        self.objects.borrow_mut().push(owned_object.clone());
1286        NetRef::wrap(owned_object)
1287    }
1288
1289    /// Inserts a constant [Logic] value to the netlist
1290    pub fn insert_constant(
1291        self: &Rc<Self>,
1292        value: Logic,
1293        inst_name: Identifier,
1294    ) -> Result<DrivenNet<I>, Error> {
1295        let obj = I::from_constant(value).ok_or(Error::InstantiableError(format!(
1296            "Instantiable type does not support constant value {}",
1297            value
1298        )))?;
1299        Ok(self.insert_gate_disconnected(obj, inst_name).into())
1300    }
1301
1302    /// Returns the driving node at input position `index` for `netref`
1303    ///
1304    /// # Panics
1305    ///
1306    /// Panics if `index` is out of bounds
1307    pub fn get_driver(&self, netref: NetRef<I>, index: usize) -> Option<NetRef<I>> {
1308        let op = netref.unwrap().borrow().operands[index].clone()?;
1309        Some(NetRef::wrap(self.index_weak(&op.root()).clone()))
1310    }
1311
1312    /// Set an added object as a top-level output.
1313    pub fn expose_net_with_name(&self, net: DrivenNet<I>, name: Identifier) -> DrivenNet<I> {
1314        let mut outputs = self.outputs.borrow_mut();
1315        outputs.insert(net.get_operand(), net.as_net().with_name(name));
1316        net
1317    }
1318
1319    /// Set an added object as a top-level output.
1320    pub fn expose_net(&self, net: DrivenNet<I>) -> Result<DrivenNet<I>, Error> {
1321        if net.is_an_input() {
1322            return Err(Error::InputNeedsAlias(net.as_net().clone()));
1323        }
1324        let mut outputs = self.outputs.borrow_mut();
1325        outputs.insert(net.get_operand(), net.as_net().clone());
1326        Ok(net)
1327    }
1328
1329    /// Unlink a circuit node from the rest of the netlist. Return the object that was being stored.
1330    pub fn delete_net_uses(&self, netref: NetRef<I>) -> Result<Object<I>, Error> {
1331        let unwrapped = netref.clone().unwrap();
1332        if Rc::strong_count(&unwrapped) > 3 {
1333            return Err(Error::DanglingReference(netref.nets().collect()));
1334        }
1335        let old_index = unwrapped.borrow().get_index();
1336        let objects = self.objects.borrow();
1337        for oref in objects.iter() {
1338            let operands = &mut oref.borrow_mut().operands;
1339            for operand in operands.iter_mut() {
1340                if let Some(op) = operand {
1341                    match op {
1342                        Operand::DirectIndex(idx) | Operand::CellIndex(idx, _)
1343                            if *idx == old_index =>
1344                        {
1345                            *operand = None;
1346                        }
1347                        _ => (),
1348                    }
1349                }
1350            }
1351        }
1352
1353        let outputs: Vec<Operand> = self
1354            .outputs
1355            .borrow()
1356            .keys()
1357            .filter(|operand| match operand {
1358                Operand::DirectIndex(idx) | Operand::CellIndex(idx, _) => *idx == old_index,
1359            })
1360            .cloned()
1361            .collect();
1362
1363        for operand in outputs {
1364            self.outputs.borrow_mut().remove(&operand);
1365        }
1366
1367        Ok(netref.unwrap().borrow().get().clone())
1368    }
1369
1370    /// Replaces the uses of a circuit node with another circuit node. The [Object] stored at `of` is returned.
1371    pub fn replace_net_uses(
1372        &self,
1373        of: DrivenNet<I>,
1374        with: &DrivenNet<I>,
1375    ) -> Result<Object<I>, Error> {
1376        let unwrapped = of.clone().unwrap().unwrap();
1377        let i = of.get_output_index();
1378        let k = with.get_output_index();
1379
1380        if of.clone().unwrap() == with.clone().unwrap() {
1381            if i == k || Rc::strong_count(&unwrapped) > 4 {
1382                return Err(Error::DanglingReference(of.unwrap().nets().collect()));
1383            }
1384        } else if Rc::strong_count(&unwrapped) > 3 {
1385            return Err(Error::DanglingReference(of.unwrap().nets().collect()));
1386        }
1387
1388        let old_index = of.get_operand();
1389
1390        if let Some(v) = self.outputs.borrow().get(&old_index)
1391            && *v == *of.as_net()
1392        {
1393            return Err(Error::NonuniqueNets(vec![v.clone()]));
1394        }
1395
1396        let new_index = with.get_operand();
1397        let objects = self.objects.borrow();
1398        for oref in objects.iter() {
1399            let operands = &mut oref.borrow_mut().operands;
1400            for operand in operands.iter_mut() {
1401                if let Some(op) = operand
1402                    && *op == old_index
1403                {
1404                    *operand = Some(new_index.clone());
1405                }
1406            }
1407        }
1408
1409        let already_mapped = self.outputs.borrow().contains_key(&new_index);
1410        let old_mapping = self.outputs.borrow_mut().remove(&old_index);
1411
1412        if already_mapped {
1413            self.outputs.borrow_mut().remove(&old_index);
1414        } else if let Some(v) = old_mapping {
1415            self.outputs.borrow_mut().insert(new_index, v.clone());
1416        }
1417
1418        Ok(of.unwrap().unwrap().borrow().get().clone())
1419    }
1420}
1421
1422impl<I> Netlist<I>
1423where
1424    I: Instantiable,
1425{
1426    /// Returns the name of the netlist module
1427    pub fn get_name(&self) -> Ref<'_, String> {
1428        self.name.borrow()
1429    }
1430
1431    /// Sets the name of the netlist module
1432    /// # Panics
1433    ///
1434    /// Panics if the module name cannot be borrowed mutably.
1435    pub fn set_name(&self, name: String) {
1436        *self.name.borrow_mut() = name;
1437    }
1438
1439    /// Iterates over the input ports of the netlist.
1440    pub fn get_input_ports(&self) -> impl Iterator<Item = Net> {
1441        self.objects().filter_map(|oref| {
1442            if oref.is_an_input() {
1443                Some(oref.as_net().clone())
1444            } else {
1445                None
1446            }
1447        })
1448    }
1449
1450    /// Returns a list of output nets
1451    pub fn get_output_ports(&self) -> Vec<Net> {
1452        self.outputs.borrow().values().cloned().collect::<Vec<_>>()
1453    }
1454
1455    /// Constructs an analysis of the netlist.
1456    pub fn get_analysis<'a, A: Analysis<'a, I>>(&'a self) -> Result<A, Error> {
1457        A::build(self)
1458    }
1459
1460    /// Finds the first circuit node that drives the `net`. This operation is O(n).
1461    /// This should be unique provided the netlist is well-formed.
1462    pub fn find_net(&self, net: &Net) -> Option<DrivenNet<I>> {
1463        for obj in self.objects() {
1464            for o in obj.outputs() {
1465                if *o.as_net() == *net {
1466                    return Some(o);
1467                }
1468            }
1469        }
1470        None
1471    }
1472
1473    /// Returns a `NetRef` to the first circuit node
1474    pub fn first(&self) -> Option<NetRef<I>> {
1475        self.objects
1476            .borrow()
1477            .first()
1478            .map(|nr| NetRef::wrap(nr.clone()))
1479    }
1480
1481    /// Returns a `NetRef` to the last circuit node
1482    pub fn last(&self) -> Option<NetRef<I>> {
1483        self.objects
1484            .borrow()
1485            .last()
1486            .map(|nr| NetRef::wrap(nr.clone()))
1487    }
1488
1489    /// Returns `true` if an output of `netref` which is driving a module output.
1490    pub fn drives_an_output(&self, netref: NetRef<I>) -> bool {
1491        let my_index = netref.unwrap().borrow().get_index();
1492        for key in self.outputs.borrow().keys() {
1493            if key.root() == my_index {
1494                return true;
1495            }
1496        }
1497        false
1498    }
1499
1500    /// Cleans unused nodes from the netlist, returning `Ok(true)` if the netlist changed.
1501    pub fn clean_once(&self) -> Result<bool, Error> {
1502        let mut dead_objs = HashSet::new();
1503        {
1504            let fan_out = self.get_analysis::<FanOutTable<I>>()?;
1505            for obj in self.objects() {
1506                let mut is_dead = true;
1507                for net in obj.nets() {
1508                    // This should account for outputs
1509                    if fan_out.net_has_uses(&net) {
1510                        is_dead = false;
1511                        break;
1512                    }
1513                }
1514                if is_dead && !obj.is_an_input() {
1515                    dead_objs.insert(obj.unwrap().borrow().index);
1516                }
1517            }
1518        }
1519
1520        if dead_objs.is_empty() {
1521            return Ok(false);
1522        }
1523
1524        let old_objects = self.objects.take();
1525        let mut remap: HashMap<usize, usize> = HashMap::new();
1526        for (old_index, obj) in old_objects.into_iter().enumerate() {
1527            if dead_objs.contains(&old_index) {
1528                // 1. this ref, 2. as an output
1529                if Rc::strong_count(&obj) > 2 {
1530                    return Err(Error::DanglingReference(
1531                        obj.borrow().get().get_nets().to_vec(),
1532                    ));
1533                }
1534                continue;
1535            }
1536            let new_index = self.objects.borrow().len();
1537            remap.insert(old_index, new_index);
1538            obj.borrow_mut().index = new_index;
1539            self.objects.borrow_mut().push(obj);
1540        }
1541
1542        for obj in self.objects.borrow().iter() {
1543            for operand in obj.borrow_mut().inds_mut() {
1544                let root = operand.root();
1545                let root = *remap.get(&root).unwrap_or(&root);
1546                *operand = operand.clone().remap(root);
1547            }
1548        }
1549
1550        let pairs: Vec<_> = self.outputs.take().into_iter().collect();
1551        for (operand, net) in pairs {
1552            let root = operand.root();
1553            let root = *remap.get(&root).unwrap_or(&root);
1554            let new_operand = operand.clone().remap(root);
1555            self.outputs.borrow_mut().insert(new_operand, net);
1556        }
1557
1558        Ok(true)
1559    }
1560
1561    /// Greedly removes unused nodes from the netlist, until it stops changing.
1562    /// Returns true if the netlist was changed.
1563    pub fn clean(&self) -> Result<bool, Error> {
1564        if !self.clean_once()? {
1565            Ok(false)
1566        } else {
1567            let mut changed = true;
1568            while changed {
1569                changed = self.clean_once()?;
1570            }
1571            Ok(true)
1572        }
1573    }
1574
1575    /// Returns `true` if all the nets are uniquely named
1576    fn nets_unique(&self) -> Result<(), Error> {
1577        let mut nets = HashSet::new();
1578        for net in self.into_iter() {
1579            if !nets.insert(net.clone().take_identifier()) {
1580                return Err(Error::NonuniqueNets(vec![net]));
1581            }
1582        }
1583        Ok(())
1584    }
1585
1586    /// Returns `true` if all the nets are uniquely named
1587    fn insts_unique(&self) -> Result<(), Error> {
1588        let mut insts = HashSet::new();
1589        for inst in self.objects() {
1590            if let Some(name) = inst.get_instance_name()
1591                && !insts.insert(name.clone())
1592            {
1593                return Err(Error::NonuniqueInsts(vec![name]));
1594            }
1595        }
1596        Ok(())
1597    }
1598
1599    /// Verifies that a netlist is well-formed.
1600    pub fn verify(&self) -> Result<(), Error> {
1601        if self.outputs.borrow().is_empty() {
1602            return Err(Error::NoOutputs);
1603        }
1604
1605        self.nets_unique()?;
1606
1607        self.insts_unique()?;
1608
1609        Ok(())
1610    }
1611}
1612
1613/// Represent a driven net alongside its connection to an input port
1614#[derive(Debug, Clone)]
1615pub struct Connection<I: Instantiable> {
1616    driver: DrivenNet<I>,
1617    input: InputPort<I>,
1618}
1619
1620impl<I> Connection<I>
1621where
1622    I: Instantiable,
1623{
1624    fn new(driver: DrivenNet<I>, input: InputPort<I>) -> Self {
1625        Self { driver, input }
1626    }
1627
1628    /// Return the driver of the connection
1629    pub fn src(&self) -> DrivenNet<I> {
1630        self.driver.clone()
1631    }
1632
1633    /// Return the net along the connection
1634    pub fn net(&self) -> Net {
1635        self.driver.as_net().clone()
1636    }
1637
1638    /// Returns the input port of the connection
1639    pub fn target(&self) -> InputPort<I> {
1640        self.input.clone()
1641    }
1642}
1643
1644impl<I> std::fmt::Display for Connection<I>
1645where
1646    I: Instantiable,
1647{
1648    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1649        self.net().fmt(f)
1650    }
1651}
1652
1653/// A collection of iterators for the netlist
1654pub mod iter {
1655
1656    use super::{
1657        Connection, DrivenNet, InputPort, Instantiable, Net, NetRef, Netlist, Operand, WeakIndex,
1658    };
1659    use std::collections::{HashMap, HashSet};
1660    /// An iterator over the nets in a netlist
1661    pub struct NetIterator<'a, I: Instantiable> {
1662        netlist: &'a Netlist<I>,
1663        index: usize,
1664        subindex: usize,
1665    }
1666
1667    impl<'a, I> NetIterator<'a, I>
1668    where
1669        I: Instantiable,
1670    {
1671        /// Creates a new iterator for the netlist
1672        pub fn new(netlist: &'a Netlist<I>) -> Self {
1673            Self {
1674                netlist,
1675                index: 0,
1676                subindex: 0,
1677            }
1678        }
1679    }
1680
1681    impl<I> Iterator for NetIterator<'_, I>
1682    where
1683        I: Instantiable,
1684    {
1685        type Item = Net;
1686
1687        fn next(&mut self) -> Option<Self::Item> {
1688            while self.index < self.netlist.objects.borrow().len() {
1689                let objects = self.netlist.objects.borrow();
1690                let object = objects[self.index].borrow();
1691                if self.subindex < object.get().get_nets().len() {
1692                    let net = object.get().get_nets()[self.subindex].clone();
1693                    self.subindex += 1;
1694                    return Some(net);
1695                }
1696                self.subindex = 0;
1697                self.index += 1;
1698            }
1699            None
1700        }
1701    }
1702
1703    /// An iterator over the objects in a netlist
1704    pub struct ObjectIterator<'a, I: Instantiable> {
1705        netlist: &'a Netlist<I>,
1706        index: usize,
1707    }
1708
1709    impl<'a, I> ObjectIterator<'a, I>
1710    where
1711        I: Instantiable,
1712    {
1713        /// Creates a new  object iterator for the netlist
1714        pub fn new(netlist: &'a Netlist<I>) -> Self {
1715            Self { netlist, index: 0 }
1716        }
1717    }
1718
1719    impl<I> Iterator for ObjectIterator<'_, I>
1720    where
1721        I: Instantiable,
1722    {
1723        type Item = NetRef<I>;
1724
1725        fn next(&mut self) -> Option<Self::Item> {
1726            if self.index < self.netlist.objects.borrow().len() {
1727                let objects = self.netlist.objects.borrow();
1728                let object = &objects[self.index];
1729                self.index += 1;
1730                return Some(NetRef::wrap(object.clone()));
1731            }
1732            None
1733        }
1734    }
1735
1736    /// An iterator over the connections in a netlist
1737    pub struct ConnectionIterator<'a, I: Instantiable> {
1738        netlist: &'a Netlist<I>,
1739        index: usize,
1740        subindex: usize,
1741    }
1742
1743    impl<'a, I> ConnectionIterator<'a, I>
1744    where
1745        I: Instantiable,
1746    {
1747        /// Create a new connection iterator for the netlist
1748        pub fn new(netlist: &'a Netlist<I>) -> Self {
1749            Self {
1750                netlist,
1751                index: 0,
1752                subindex: 0,
1753            }
1754        }
1755    }
1756
1757    impl<I> Iterator for ConnectionIterator<'_, I>
1758    where
1759        I: Instantiable,
1760    {
1761        type Item = super::Connection<I>;
1762
1763        fn next(&mut self) -> Option<Self::Item> {
1764            while self.index < self.netlist.objects.borrow().len() {
1765                let objects = self.netlist.objects.borrow();
1766                let object = objects[self.index].borrow();
1767                let noperands = object.operands.len();
1768                while self.subindex < noperands {
1769                    if let Some(operand) = &object.operands[self.subindex] {
1770                        let driver = match operand {
1771                            Operand::DirectIndex(idx) => {
1772                                DrivenNet::new(0, NetRef::wrap(objects[*idx].clone()))
1773                            }
1774                            Operand::CellIndex(idx, j) => {
1775                                DrivenNet::new(*j, NetRef::wrap(objects[*idx].clone()))
1776                            }
1777                        };
1778                        let input = InputPort::new(
1779                            self.subindex,
1780                            NetRef::wrap(objects[self.index].clone()),
1781                        );
1782                        self.subindex += 1;
1783                        return Some(Connection::new(driver, input));
1784                    }
1785                    self.subindex += 1;
1786                }
1787                self.subindex = 0;
1788                self.index += 1;
1789            }
1790            None
1791        }
1792    }
1793
1794    /// A stack that can check contains in roughly O(1) time.
1795    #[derive(Clone)]
1796    struct Walk<T: std::hash::Hash + PartialEq + Eq + Clone> {
1797        stack: Vec<T>,
1798        counter: HashMap<T, usize>,
1799    }
1800
1801    impl<T> Walk<T>
1802    where
1803        T: std::hash::Hash + PartialEq + Eq + Clone,
1804    {
1805        /// Create a new, empty Stack.
1806        fn new() -> Self {
1807            Self {
1808                stack: Vec::new(),
1809                counter: HashMap::new(),
1810            }
1811        }
1812
1813        /// Inserts an element into the stack
1814        fn push(&mut self, item: T) {
1815            self.stack.push(item.clone());
1816            *self.counter.entry(item).or_insert(0) += 1;
1817        }
1818
1819        /// Returns true if the stack shows a cycle
1820        fn contains_cycle(&self) -> bool {
1821            self.counter.values().any(|&count| count > 1)
1822        }
1823
1824        /// Returns a reference to the last element in the stack
1825        fn last(&self) -> Option<&T> {
1826            self.stack.last()
1827        }
1828    }
1829
1830    /// A depth-first iterator over the circuit nodes in a netlist
1831    /// # Examples
1832    ///
1833    /// ```
1834    /// use safety_net::iter::DFSIterator;
1835    /// use safety_net::GateNetlist;
1836    ///
1837    /// let netlist = GateNetlist::new("example".to_string());
1838    /// netlist.insert_input("input1".into());
1839    /// let mut nodes = Vec::new();
1840    /// let mut dfs = DFSIterator::new(&netlist, netlist.last().unwrap());
1841    /// while let Some(n) = dfs.next() {
1842    ///     if dfs.check_cycles() {
1843    ///         panic!("Cycle detected in the netlist");
1844    ///     }
1845    ///     nodes.push(n);
1846    /// }
1847    /// ```
1848    pub struct DFSIterator<'a, I: Instantiable> {
1849        netlist: &'a Netlist<I>,
1850        stacks: Vec<Walk<NetRef<I>>>,
1851        visited: HashSet<usize>,
1852        cycles: bool,
1853    }
1854
1855    impl<'a, I> DFSIterator<'a, I>
1856    where
1857        I: Instantiable,
1858    {
1859        /// Create a new DFS iterator for the netlist starting at `from`.
1860        pub fn new(netlist: &'a Netlist<I>, from: NetRef<I>) -> Self {
1861            let mut s = Walk::new();
1862            s.push(from);
1863            Self {
1864                netlist,
1865                stacks: vec![s],
1866                visited: HashSet::new(),
1867                cycles: false,
1868            }
1869        }
1870    }
1871
1872    impl<I> DFSIterator<'_, I>
1873    where
1874        I: Instantiable,
1875    {
1876        /// Check if the DFS traversal has encountered a cycle yet.
1877        pub fn check_cycles(&self) -> bool {
1878            self.cycles
1879        }
1880
1881        /// Consumes the iterator to detect cycles in the netlist.
1882        pub fn detect_cycles(mut self) -> bool {
1883            if self.cycles {
1884                return true;
1885            }
1886
1887            while let Some(_) = self.next() {
1888                if self.cycles {
1889                    return true;
1890                }
1891            }
1892
1893            self.cycles
1894        }
1895    }
1896
1897    impl<I> Iterator for DFSIterator<'_, I>
1898    where
1899        I: Instantiable,
1900    {
1901        type Item = NetRef<I>;
1902
1903        fn next(&mut self) -> Option<Self::Item> {
1904            if let Some(walk) = self.stacks.pop() {
1905                let item = walk.last().cloned();
1906                let uw = item.clone().unwrap().unwrap();
1907                let index = uw.borrow().get_index();
1908                if self.visited.insert(index) {
1909                    let operands = &uw.borrow().operands;
1910                    for operand in operands.iter().flatten() {
1911                        let mut new_walk = walk.clone();
1912                        new_walk.push(NetRef::wrap(self.netlist.index_weak(&operand.root())));
1913                        if !new_walk.contains_cycle() {
1914                            self.stacks.push(new_walk);
1915                        } else {
1916                            self.cycles = true;
1917                        }
1918                    }
1919                    return item;
1920                }
1921
1922                return self.next();
1923            }
1924
1925            None
1926        }
1927    }
1928}
1929
1930impl<'a, I> IntoIterator for &'a Netlist<I>
1931where
1932    I: Instantiable,
1933{
1934    type Item = Net;
1935    type IntoIter = iter::NetIterator<'a, I>;
1936
1937    fn into_iter(self) -> Self::IntoIter {
1938        iter::NetIterator::new(self)
1939    }
1940}
1941
1942/// Filter invariants of [Instantiable] in a netlist. Use it like you would `matches!`.
1943/// Example: ```filter_nodes!(netlist, Gate::AND(_));```
1944#[macro_export]
1945macro_rules! filter_nodes {
1946    ($netlist:ident, $pattern:pat $(if $guard:expr)? $(,)?) => {
1947        $netlist.matches(|f| match f {
1948            $pattern $(if $guard)? => true,
1949            _ => false
1950        })
1951    };
1952}
1953
1954impl<I> Netlist<I>
1955where
1956    I: Instantiable,
1957{
1958    /// Returns an iterator over the circuit nodes in the netlist.
1959    pub fn objects(&self) -> impl Iterator<Item = NetRef<I>> {
1960        iter::ObjectIterator::new(self)
1961    }
1962
1963    /// Returns an iterator over the circuit nodes that match the instance type.
1964    pub fn matches<F>(&self, filter: F) -> impl Iterator<Item = NetRef<I>>
1965    where
1966        F: Fn(&I) -> bool,
1967    {
1968        self.objects().filter(move |f| {
1969            if let Some(inst_type) = f.get_instance_type() {
1970                filter(&inst_type)
1971            } else {
1972                false
1973            }
1974        })
1975    }
1976
1977    /// Returns an iterator to principal inputs in the netlist as references.
1978    pub fn inputs(&self) -> impl Iterator<Item = DrivenNet<I>> {
1979        self.objects()
1980            .filter(|n| n.is_an_input())
1981            .map(|n| DrivenNet::new(0, n))
1982    }
1983
1984    /// Returns an iterator to circuit nodes that drive an output in the netlist.
1985    pub fn outputs(&self) -> Vec<(DrivenNet<I>, Net)> {
1986        self.outputs
1987            .borrow()
1988            .iter()
1989            .map(|(k, n)| {
1990                (
1991                    DrivenNet::new(k.secondary(), NetRef::wrap(self.index_weak(&k.root()))),
1992                    n.clone(),
1993                )
1994            })
1995            .collect()
1996    }
1997
1998    /// Returns an iterator over the wire connections in the netlist.
1999    pub fn connections(&self) -> impl Iterator<Item = Connection<I>> {
2000        iter::ConnectionIterator::new(self)
2001    }
2002
2003    /// Returns a depth-first search iterator over the nodes in the netlist.
2004    pub fn dfs(&self, from: NetRef<I>) -> impl Iterator<Item = NetRef<I>> {
2005        iter::DFSIterator::new(self, from)
2006    }
2007
2008    #[cfg(feature = "serde")]
2009    /// Serializes the netlist to a writer.
2010    pub fn serialize(self, writer: impl std::io::Write) -> Result<(), serde_json::Error>
2011    where
2012        I: ::serde::Serialize,
2013    {
2014        serde::netlist_serialize(self, writer)
2015    }
2016}
2017
2018impl<I> std::fmt::Display for Netlist<I>
2019where
2020    I: Instantiable,
2021{
2022    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2023        // Borrow everything first
2024        let objects = self.objects.borrow();
2025        let outputs = self.outputs.borrow();
2026
2027        writeln!(f, "module {} (", self.get_name())?;
2028
2029        // Print inputs and outputs
2030        let level = 2;
2031        let indent = " ".repeat(level);
2032        for oref in objects.iter() {
2033            let owned = oref.borrow();
2034            let obj = owned.get();
2035            if let Object::Input(net) = obj {
2036                writeln!(f, "{}{},", indent, net.get_identifier().emit_name())?;
2037            }
2038        }
2039        for (i, (_, net)) in outputs.iter().enumerate() {
2040            if i == outputs.len() - 1 {
2041                writeln!(f, "{}{}", indent, net.get_identifier().emit_name())?;
2042            } else {
2043                writeln!(f, "{}{},", indent, net.get_identifier().emit_name())?;
2044            }
2045        }
2046        writeln!(f, ");")?;
2047
2048        // Make wire decls
2049        let mut already_decl = HashSet::new();
2050        for oref in objects.iter() {
2051            let owned = oref.borrow();
2052            let obj = owned.get();
2053            if let Object::Input(net) = obj {
2054                writeln!(f, "{}input {};", indent, net.get_identifier().emit_name())?;
2055                writeln!(f, "{}wire {};", indent, net.get_identifier().emit_name())?;
2056                already_decl.insert(net.clone());
2057            }
2058        }
2059        for (_, net) in outputs.iter() {
2060            if !already_decl.contains(net) {
2061                writeln!(f, "{}output {};", indent, net.get_identifier().emit_name())?;
2062                writeln!(f, "{}wire {};", indent, net.get_identifier().emit_name())?;
2063                already_decl.insert(net.clone());
2064            }
2065        }
2066        for oref in objects.iter() {
2067            let owned = oref.borrow();
2068            let obj = owned.get();
2069            if let Object::Instance(nets, _, inst_type) = obj
2070                && inst_type.get_constant().is_none()
2071            {
2072                for net in nets.iter() {
2073                    if !already_decl.contains(net) {
2074                        writeln!(f, "{}wire {};", indent, net.get_identifier().emit_name())?;
2075                        already_decl.insert(net.clone());
2076                    }
2077                }
2078            }
2079        }
2080
2081        for oref in objects.iter() {
2082            let owned = oref.borrow();
2083            let obj = owned.get();
2084
2085            // Skip emitting constants as their uses will be hard-wired
2086            if let Some(inst_type) = obj.get_instance_type()
2087                && inst_type.get_constant().is_some()
2088            {
2089                continue;
2090            }
2091
2092            if let Object::Instance(nets, inst_name, inst_type) = obj {
2093                for (k, v) in owned.attributes.iter() {
2094                    if let Some(value) = v {
2095                        writeln!(f, "{indent}(* {k} = \"{value}\" *)")?;
2096                    } else {
2097                        writeln!(f, "{indent}(* {k} *)")?;
2098                    }
2099                }
2100
2101                write!(f, "{}{} ", indent, inst_type.get_name())?;
2102                if inst_type.is_parameterized() {
2103                    writeln!(f, "#(")?;
2104                    let level = 4;
2105                    let indent = " ".repeat(level);
2106                    let params: Vec<_> = inst_type.parameters().collect();
2107                    for (i, (k, v)) in params.iter().enumerate() {
2108                        if i == params.len() - 1 {
2109                            writeln!(f, "{indent}.{k}({v})")?;
2110                        } else {
2111                            writeln!(f, "{indent}.{k}({v}),")?;
2112                        }
2113                    }
2114                    let level = 2;
2115                    let indent = " ".repeat(level);
2116                    write!(f, "{indent}) ")?;
2117                }
2118                writeln!(f, "{} (", inst_name.emit_name())?;
2119                let level = 4;
2120                let indent = " ".repeat(level);
2121                for (idx, port) in inst_type.get_input_ports().into_iter().enumerate() {
2122                    let port_name = port.get_identifier().emit_name();
2123                    if let Some(operand) = owned.operands[idx].as_ref() {
2124                        let operand_net = match operand {
2125                            Operand::DirectIndex(idx) => objects[*idx].borrow().as_net().clone(),
2126                            Operand::CellIndex(idx, j) => {
2127                                objects[*idx].borrow().get_net(*j).clone()
2128                            }
2129                        };
2130
2131                        let operand_str = if let Some(inst_type) =
2132                            objects[operand.root()].borrow().get().get_instance_type()
2133                            && let Some(logic) = inst_type.get_constant()
2134                        {
2135                            logic.to_string()
2136                        } else {
2137                            operand_net.get_identifier().emit_name()
2138                        };
2139
2140                        writeln!(f, "{}.{}({}),", indent, port_name, operand_str)?;
2141                    }
2142                }
2143
2144                for (idx, net) in nets.iter().enumerate() {
2145                    let port_name = inst_type.get_output_port(idx).get_identifier().emit_name();
2146                    if idx == nets.len() - 1 {
2147                        writeln!(
2148                            f,
2149                            "{}.{}({})",
2150                            indent,
2151                            port_name,
2152                            net.get_identifier().emit_name()
2153                        )?;
2154                    } else {
2155                        writeln!(
2156                            f,
2157                            "{}.{}({}),",
2158                            indent,
2159                            port_name,
2160                            net.get_identifier().emit_name()
2161                        )?;
2162                    }
2163                }
2164
2165                let level = 2;
2166                let indent = " ".repeat(level);
2167                writeln!(f, "{indent});")?;
2168            }
2169        }
2170
2171        for (driver, net) in outputs.iter() {
2172            let driver_net = match driver {
2173                Operand::DirectIndex(idx) => self.index_weak(idx).borrow().as_net().clone(),
2174                Operand::CellIndex(idx, j) => self.index_weak(idx).borrow().get_net(*j).clone(),
2175            };
2176
2177            let driver_str = if let Some(inst_type) = self
2178                .index_weak(&driver.root())
2179                .borrow()
2180                .get()
2181                .get_instance_type()
2182                && let Some(logic) = inst_type.get_constant()
2183            {
2184                logic.to_string()
2185            } else {
2186                driver_net.get_identifier().emit_name()
2187            };
2188
2189            if net.get_identifier() != driver_net.get_identifier() {
2190                writeln!(
2191                    f,
2192                    "{}assign {} = {};",
2193                    indent,
2194                    net.get_identifier().emit_name(),
2195                    driver_str
2196                )?;
2197            }
2198        }
2199
2200        writeln!(f, "endmodule")
2201    }
2202}
2203
2204/// A type alias for a netlist of gates
2205pub type GateNetlist = Netlist<Gate>;
2206/// A type alias to Gate circuit nodes
2207pub type GateRef = NetRef<Gate>;
2208
2209#[cfg(test)]
2210mod tests {
2211    use super::*;
2212    #[test]
2213    fn test_delete_netlist() {
2214        let netlist = Netlist::new("simple_example".to_string());
2215
2216        // Add the the two inputs
2217        let input1 = netlist.insert_input("input1".into());
2218        let input2 = netlist.insert_input("input2".into());
2219
2220        // Instantiate an AND gate
2221        let instance = netlist
2222            .insert_gate(
2223                Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into()),
2224                "my_and".into(),
2225                &[input1.clone(), input2.clone()],
2226            )
2227            .unwrap();
2228
2229        // Make this AND gate an output
2230        let instance = instance.expose_as_output().unwrap();
2231        instance.delete_uses().unwrap();
2232        // Cannot clean a netlist that is in a invalid state
2233        assert!(netlist.clean().is_err());
2234        input1.expose_with_name("an_output".into());
2235        assert!(netlist.clean().is_ok());
2236    }
2237
2238    #[test]
2239    #[should_panic(expected = "Attempted to create a gate with a sliced identifier")]
2240    fn gate_w_slice_panics() {
2241        Gate::new_logical("AND[1]".into(), vec!["A".into(), "B".into()], "Y".into());
2242    }
2243
2244    #[test]
2245    fn gates_dont_have_params() {
2246        // The baseline implementation of gates do not have parameters.
2247        let gate = Gate::new_logical("AND".into(), vec!["A".into(), "B".into()], "Y".into());
2248        assert!(!gate.has_parameter(&"id".into()));
2249        assert!(gate.get_parameter(&"id".into()).is_none());
2250        assert_eq!(*gate.get_gate_name(), "AND".into());
2251    }
2252
2253    #[test]
2254    fn operand_conversions() {
2255        let operand = Operand::CellIndex(3, 2);
2256        assert_eq!(operand.to_string(), "3.2");
2257        let parsed = "3.2".parse::<Operand>();
2258        assert!(parsed.is_ok());
2259        let parsed = parsed.unwrap();
2260        assert_eq!(operand, parsed);
2261    }
2262
2263    #[test]
2264    #[should_panic(expected = "out of bounds for netref")]
2265    fn test_bad_output() {
2266        let netlist = GateNetlist::new("min_module".to_string());
2267        let a = netlist.insert_input("a".into());
2268        DrivenNet::new(1, a.unwrap());
2269    }
2270}
2271
2272#[cfg(feature = "serde")]
2273/// Serde support for netlists
2274pub mod serde {
2275    use super::{Netlist, Operand, OwnedObject, WeakIndex};
2276    use crate::{
2277        attribute::{AttributeKey, AttributeValue},
2278        circuit::{Instantiable, Net, Object},
2279    };
2280    use serde::{Deserialize, Serialize, de::DeserializeOwned};
2281    use std::cell::RefCell;
2282    use std::{collections::HashMap, rc::Rc};
2283
2284    #[derive(Debug, Serialize, Deserialize)]
2285    struct SerdeObject<I>
2286    where
2287        I: Instantiable + Serialize,
2288    {
2289        /// The object that is owned by the netlist
2290        object: Object<I>,
2291        /// The list of operands for the object
2292        operands: Vec<Option<Operand>>,
2293        /// A collection of attributes for the object
2294        attributes: HashMap<AttributeKey, AttributeValue>,
2295    }
2296
2297    impl<I, O> From<OwnedObject<I, O>> for SerdeObject<I>
2298    where
2299        I: Instantiable + Serialize,
2300        O: WeakIndex<usize, Output = OwnedObject<I, O>>,
2301    {
2302        fn from(value: OwnedObject<I, O>) -> Self {
2303            SerdeObject {
2304                object: value.object,
2305                operands: value.operands,
2306                attributes: value.attributes,
2307            }
2308        }
2309    }
2310
2311    impl<I> SerdeObject<I>
2312    where
2313        I: Instantiable + Serialize,
2314    {
2315        fn into_owned_object<O>(self, owner: &Rc<O>, index: usize) -> OwnedObject<I, O>
2316        where
2317            O: WeakIndex<usize, Output = OwnedObject<I, O>>,
2318        {
2319            OwnedObject {
2320                object: self.object,
2321                owner: Rc::downgrade(owner),
2322                operands: self.operands,
2323                attributes: self.attributes,
2324                index,
2325            }
2326        }
2327    }
2328
2329    #[derive(Debug, Serialize, Deserialize)]
2330    struct SerdeNetlist<I>
2331    where
2332        I: Instantiable + Serialize,
2333    {
2334        /// The name of the netlist
2335        name: String,
2336        /// The list of objects in the netlist, such as inputs, modules, and primitives
2337        objects: Vec<SerdeObject<I>>,
2338        /// The list of operands that point to objects which are outputs.
2339        /// Indices must be a string if we want to support JSON.
2340        outputs: HashMap<String, Net>,
2341    }
2342
2343    impl<I> From<Netlist<I>> for SerdeNetlist<I>
2344    where
2345        I: Instantiable + Serialize,
2346    {
2347        fn from(value: Netlist<I>) -> Self {
2348            SerdeNetlist {
2349                name: value.name.into_inner(),
2350                objects: value
2351                    .objects
2352                    .into_inner()
2353                    .into_iter()
2354                    .map(|o| {
2355                        Rc::try_unwrap(o)
2356                            .ok()
2357                            .expect("Cannot serialize with live references")
2358                            .into_inner()
2359                            .into()
2360                    })
2361                    .collect(),
2362                outputs: value
2363                    .outputs
2364                    .into_inner()
2365                    .into_iter()
2366                    // Indices must be a string if we want to support JSON.
2367                    .map(|(o, n)| (o.to_string(), n))
2368                    .collect(),
2369            }
2370        }
2371    }
2372
2373    impl<I> SerdeNetlist<I>
2374    where
2375        I: Instantiable + Serialize,
2376    {
2377        /// Convert the serialized netlist back into a reference-counted netlist.
2378        fn into_netlist(self) -> Rc<Netlist<I>> {
2379            let netlist = Netlist::new(self.name);
2380            let outputs: HashMap<Operand, Net> = self
2381                .outputs
2382                .into_iter()
2383                .map(|(k, v)| {
2384                    let operand = k.parse::<Operand>().expect("Invalid index");
2385                    (operand, v)
2386                })
2387                .collect();
2388            let objects = self
2389                .objects
2390                .into_iter()
2391                .enumerate()
2392                .map(|(i, o)| {
2393                    let owned_object = o.into_owned_object(&netlist, i);
2394                    Rc::new(RefCell::new(owned_object))
2395                })
2396                .collect::<Vec<_>>();
2397            {
2398                let mut objs_mut = netlist.objects.borrow_mut();
2399                *objs_mut = objects;
2400                let mut outputs_mut = netlist.outputs.borrow_mut();
2401                *outputs_mut = outputs;
2402            }
2403            netlist
2404        }
2405    }
2406
2407    /// Serialize the netlist into the writer.
2408    pub fn netlist_serialize<I: Instantiable + Serialize>(
2409        netlist: Netlist<I>,
2410        writer: impl std::io::Write,
2411    ) -> Result<(), serde_json::Error> {
2412        let sobj: SerdeNetlist<I> = netlist.into();
2413        serde_json::to_writer_pretty(writer, &sobj)
2414    }
2415
2416    /// Deserialize a netlist from the reader.
2417    pub fn netlist_deserialize<I: Instantiable + Serialize + DeserializeOwned>(
2418        reader: impl std::io::Read,
2419    ) -> Result<Rc<Netlist<I>>, serde_json::Error> {
2420        let sobj: SerdeNetlist<I> = serde_json::from_reader(reader)?;
2421        Ok(sobj.into_netlist())
2422    }
2423}