@@ -315,6 +315,10 @@ where
315315 }
316316
317317 /// Get driving net using the weak reference
318+ ///
319+ /// # Panics
320+ ///
321+ /// Panics if the reference to the netlist is lost.
318322 fn get_driver_net ( & self , index : usize ) -> Option < Net > {
319323 let operand = & self . operands [ index] ;
320324 match operand {
@@ -387,12 +391,18 @@ where
387391 }
388392
389393 /// Returns a borrow to the [Net] at this circuit node.
394+ ///
395+ /// # Panics
396+ ///
390397 /// Panics if the circuit node has multiple outputs.
391398 pub fn as_net ( & self ) -> Ref < Net > {
392399 Ref :: map ( self . netref . borrow ( ) , |f| f. as_net ( ) )
393400 }
394401
395402 /// Returns a mutable borrow to the [Net] at this circuit node.
403+ ///
404+ /// # Panics
405+ ///
396406 /// Panics if the circuit node has multiple outputs.
397407 pub fn as_net_mut ( & self ) -> RefMut < Net > {
398408 RefMut :: map ( self . netref . borrow_mut ( ) , |f| f. as_net_mut ( ) )
@@ -422,12 +432,18 @@ where
422432 }
423433
424434 /// Returns the name of the net at this circuit node.
435+ ///
436+ /// # Panics
437+ ///
425438 /// Panics if the circuit node has multiple outputs.
426439 pub fn get_identifier ( & self ) -> Identifier {
427440 self . as_net ( ) . get_identifier ( ) . clone ( )
428441 }
429442
430443 /// Changes the identifier of the net at this circuit node.
444+ ///
445+ /// # Panics
446+ ///
431447 /// Panics if the circuit node has multiple outputs.
432448 pub fn set_identifier ( & self , identifier : Identifier ) {
433449 self . as_net_mut ( ) . set_identifier ( identifier)
@@ -465,7 +481,10 @@ where
465481 }
466482
467483 /// Updates the name of the instance, if the circuit node is an instance.
468- /// Panics if the circuit node is not an instance.
484+ ///
485+ /// # Panics
486+ ///
487+ /// Panics if the circuit node is a principal input.
469488 pub fn set_instance_name ( & self , name : Identifier ) {
470489 match self . netref . borrow_mut ( ) . get_mut ( ) {
471490 Object :: Instance ( _, inst_name, _) => * inst_name = name,
@@ -474,7 +493,12 @@ where
474493 }
475494
476495 /// Exposes this circuit node as a top-level output in the netlist.
477- /// Panics if cell is a multi-output circuit node. Errors if circuit node is a principal input.
496+ /// Returns an error if the circuit node is a principal input.
497+ ///
498+ /// # Panics
499+ ///
500+ /// Panics if cell is a multi-output circuit node.
501+ /// Panics if the reference to the netlist is lost.
478502 pub fn expose_as_output ( self ) -> Result < Self , String > {
479503 let netlist = self
480504 . netref
@@ -487,6 +511,11 @@ where
487511 }
488512
489513 /// Exposes this circuit node as a top-level output in the netlist with a specific port name.
514+ ///
515+ /// # Panics
516+ ///
517+ /// Panics if the cell is a multi-output circuit node.
518+ /// Panics if the reference to the netlist is lost.
490519 pub fn expose_with_name ( self , name : String ) -> Self {
491520 let netlist = self
492521 . netref
@@ -500,6 +529,9 @@ where
500529
501530 /// Exposes the `net` driven by this circuit node as a top-level output.
502531 /// Errors if `net` is not driven by this circuit node.
532+ ///
533+ /// # Panics
534+ /// Panics if the reference to the netlist is lost.
503535 pub fn expose_net ( & self , net : & Net ) -> Result < ( ) , String > {
504536 let netlist = self
505537 . netref
@@ -522,12 +554,20 @@ where
522554 }
523555
524556 /// Returns the net that drives the `index`th input
557+ ///
558+ /// # Panics
559+ ///
560+ /// Panics if the reference to the netlist is lost.
525561 pub fn get_driver_net ( & self , index : usize ) -> Option < Net > {
526562 self . netref . borrow ( ) . get_driver_net ( index)
527563 }
528564
529565 /// Returns a request to mutably borrow the operand net
530566 /// This requires another borrow in the form of [MutBorrowReq]
567+ ///
568+ /// # Panics
569+ ///
570+ /// Panics if the reference to the netlist is lost.
531571 pub fn req_driver_net ( & self , index : usize ) -> Option < MutBorrowReq < I > > {
532572 let net = self . get_driver_net ( index) ?;
533573 let operand = self . get_driver ( index) . unwrap ( ) ;
@@ -599,6 +639,9 @@ where
599639 }
600640
601641 /// Returns `true` if this circuit node drives a top-level output.
642+ ///
643+ /// # Panics
644+ /// Panics if the weak reference to the netlist is lost.
602645 pub fn drives_an_top_output ( & self ) -> bool {
603646 let netlist = self
604647 . netref
@@ -620,6 +663,10 @@ where
620663 }
621664
622665 /// Deletes the uses of this circuit node from the netlist.
666+ ///
667+ /// # Panics
668+ ///
669+ /// Panics if the reference to the netlist is lost.
623670 pub fn delete_uses ( self ) -> Result < Object < I > , String > {
624671 let netlist = self
625672 . netref
@@ -631,7 +678,11 @@ where
631678 }
632679
633680 /// Replaces the uses of this circuit node in the netlist with another circuit node.
681+ ///
682+ /// # Panics
683+ ///
634684 /// Panics if either `self` or `other` is a multi-output circuit node.
685+ /// Panics if the weak reference to the netlist is lost.
635686 pub fn replace_uses_with ( self , other : & Self ) -> Result < Object < I > , String > {
636687 let netlist = self
637688 . netref
@@ -1053,6 +1104,21 @@ where
10531104 Ok ( NetRef :: wrap ( owned_object) )
10541105 }
10551106
1107+ /// Returns the driving net at input position `index` for `netref`
1108+ ///
1109+ /// # Panics
1110+ ///
1111+ /// Panics if `index` is out of bounds
1112+ pub fn get_driver_net ( & self , netref : NetRef < I > , index : usize ) -> Option < Net > {
1113+ let op = netref. unwrap ( ) . borrow ( ) . operands [ index] . clone ( ) ?;
1114+ Some (
1115+ self . index_weak ( & op. root ( ) )
1116+ . borrow ( )
1117+ . get_net ( op. secondary ( ) )
1118+ . clone ( ) ,
1119+ )
1120+ }
1121+
10561122 /// Set an added object as a top-level output.
10571123 /// Panics if `net`` is a multi-output node.
10581124 pub fn expose_net_with_name ( & self , net : DrivenNet < I > , name : String ) -> DrivenNet < I > {
@@ -1513,10 +1579,28 @@ pub mod iter {
15131579 }
15141580
15151581 /// A depth-first iterator over the circuit nodes in a netlist
1582+ /// # Examples
1583+ ///
1584+ /// ```
1585+ /// use circuit::netlist::iter::DFSIterator;
1586+ /// use circuit::netlist::GateNetlist;
1587+ ///
1588+ /// let netlist = GateNetlist::new("example".to_string());
1589+ /// netlist.insert_input("input1".into());
1590+ /// let mut nodes = Vec::new();
1591+ /// let mut dfs = DFSIterator::new(&netlist, netlist.last().unwrap());
1592+ /// while let Some(n) = dfs.next() {
1593+ /// if dfs.check_cycles() {
1594+ /// panic!("Cycle detected in the netlist");
1595+ /// }
1596+ /// nodes.push(n);
1597+ /// }
1598+ /// ```
15161599 pub struct DFSIterator < ' a , I : Instantiable > {
15171600 netlist : & ' a Netlist < I > ,
15181601 stack : Vec < NetRef < I > > ,
15191602 visited : HashSet < usize > ,
1603+ cycles : bool ,
15201604 }
15211605
15221606 impl < ' a , I > DFSIterator < ' a , I >
@@ -1529,7 +1613,33 @@ pub mod iter {
15291613 netlist,
15301614 stack : vec ! [ from] ,
15311615 visited : HashSet :: new ( ) ,
1616+ cycles : false ,
1617+ }
1618+ }
1619+ }
1620+
1621+ impl < I > DFSIterator < ' _ , I >
1622+ where
1623+ I : Instantiable ,
1624+ {
1625+ /// Check if the DFS traversal has encountered a cycle yet.
1626+ pub fn check_cycles ( & self ) -> bool {
1627+ self . cycles
1628+ }
1629+
1630+ /// Consumes the iterator to detect cycles in the netlist.
1631+ pub fn detect_cycles ( mut self ) -> bool {
1632+ if self . cycles {
1633+ return true ;
15321634 }
1635+
1636+ while let Some ( _) = self . next ( ) {
1637+ if self . cycles {
1638+ return true ;
1639+ }
1640+ }
1641+
1642+ self . cycles
15331643 }
15341644 }
15351645
@@ -1544,6 +1654,7 @@ pub mod iter {
15441654 let uw = item. clone ( ) . unwrap ( ) ;
15451655 let index = uw. borrow ( ) . get_index ( ) ;
15461656 if !self . visited . insert ( index) {
1657+ self . cycles = true ;
15471658 return self . next ( ) ;
15481659 }
15491660 let operands = & uw. borrow ( ) . operands ;
0 commit comments