77use crate :: {
88 attribute:: { Attribute , AttributeKey , AttributeValue , Parameter } ,
99 circuit:: { Identifier , Instantiable , Net , Object } ,
10+ error:: Error ,
1011 graph:: { Analysis , FanOutTable } ,
1112 logic:: Logic ,
1213} ;
@@ -614,7 +615,7 @@ where
614615 ///
615616 /// Panics if cell is a multi-output circuit node.
616617 /// Panics if the reference to the netlist is lost.
617- pub fn expose_as_output ( self ) -> Result < Self , String > {
618+ pub fn expose_as_output ( self ) -> Result < Self , Error > {
618619 let netlist = self
619620 . netref
620621 . borrow ( )
@@ -647,17 +648,18 @@ where
647648 ///
648649 /// # Panics
649650 /// Panics if the reference to the netlist is lost.
650- pub fn expose_net ( & self , net : & Net ) -> Result < ( ) , String > {
651+ pub fn expose_net ( & self , net : & Net ) -> Result < ( ) , Error > {
651652 let netlist = self
652653 . netref
653654 . borrow ( )
654655 . owner
655656 . upgrade ( )
656657 . expect ( "NetRef is unlinked from netlist" ) ;
657- let net_index = self . netref . borrow ( ) . find_net ( net) . ok_or ( format ! (
658- "Net {} not found in circuit node" ,
659- net. get_identifier( )
660- ) ) ?;
658+ let net_index = self
659+ . netref
660+ . borrow ( )
661+ . find_net ( net)
662+ . ok_or ( Error :: NetNotFound ( net. clone ( ) ) ) ?;
661663 let dr = DrivenNet :: new ( net_index, self . clone ( ) ) ;
662664 netlist. expose_net ( dr) ?;
663665 Ok ( ( ) )
@@ -782,7 +784,7 @@ where
782784 /// # Panics
783785 ///
784786 /// Panics if the reference to the netlist is lost.
785- pub fn delete_uses ( self ) -> Result < Object < I > , String > {
787+ pub fn delete_uses ( self ) -> Result < Object < I > , Error > {
786788 let netlist = self
787789 . netref
788790 . borrow ( )
@@ -798,7 +800,7 @@ where
798800 ///
799801 /// Panics if either `self` or `other` is a multi-output circuit node.
800802 /// Panics if the weak reference to the netlist is lost.
801- pub fn replace_uses_with ( self , other : & Self ) -> Result < Object < I > , String > {
803+ pub fn replace_uses_with ( self , other : & Self ) -> Result < Object < I > , Error > {
802804 let netlist = self
803805 . netref
804806 . borrow ( )
@@ -1157,7 +1159,7 @@ where
11571159 self : & Rc < Self > ,
11581160 object : Object < I > ,
11591161 operands : & [ DrivenNet < I > ] ,
1160- ) -> Result < NetRef < I > , String > {
1162+ ) -> Result < NetRef < I > , Error > {
11611163 let index = self . objects . borrow ( ) . len ( ) ;
11621164 let weak = Rc :: downgrade ( self ) ;
11631165 let operands = operands
@@ -1199,19 +1201,15 @@ where
11991201 inst_type : I ,
12001202 inst_name : Identifier ,
12011203 operands : & [ DrivenNet < I > ] ,
1202- ) -> Result < NetRef < I > , String > {
1204+ ) -> Result < NetRef < I > , Error > {
12031205 let nets = inst_type
12041206 . get_output_ports ( )
12051207 . into_iter ( )
12061208 . map ( |pnet| pnet. with_name ( & inst_name + pnet. get_identifier ( ) ) )
12071209 . collect :: < Vec < _ > > ( ) ;
12081210 let input_count = inst_type. get_input_ports ( ) . into_iter ( ) . count ( ) ;
12091211 if operands. len ( ) != input_count {
1210- return Err ( format ! (
1211- "Expected {} operands, got {}" ,
1212- input_count,
1213- operands. len( )
1214- ) ) ;
1212+ return Err ( Error :: ArgumentMismatch ( input_count, operands. len ( ) ) ) ;
12151213 }
12161214 let obj = Object :: Instance ( nets, inst_name, inst_type) ;
12171215 self . insert_object ( obj, operands)
@@ -1282,22 +1280,20 @@ where
12821280 }
12831281
12841282 /// Set an added object as a top-level output.
1285- pub fn expose_net ( & self , net : DrivenNet < I > ) -> Result < DrivenNet < I > , String > {
1283+ pub fn expose_net ( & self , net : DrivenNet < I > ) -> Result < DrivenNet < I > , Error > {
12861284 if net. is_an_input ( ) {
1287- return Err (
1288- "Cannot expose an input net as output without a new name to bind to" . to_string ( ) ,
1289- ) ;
1285+ return Err ( Error :: InputNeedsAlias ( net. as_net ( ) . clone ( ) ) ) ;
12901286 }
12911287 let mut outputs = self . outputs . borrow_mut ( ) ;
12921288 outputs. insert ( net. get_operand ( ) , net. as_net ( ) . clone ( ) ) ;
12931289 Ok ( net)
12941290 }
12951291
12961292 /// Unlink a circuit node from the rest of the netlist. Return the object that was being stored.
1297- pub fn delete_net_uses ( & self , netref : NetRef < I > ) -> Result < Object < I > , String > {
1293+ pub fn delete_net_uses ( & self , netref : NetRef < I > ) -> Result < Object < I > , Error > {
12981294 let unwrapped = netref. clone ( ) . unwrap ( ) ;
12991295 if Rc :: strong_count ( & unwrapped) > 3 {
1300- return Err ( "Cannot delete. References still exist on this node" . to_string ( ) ) ;
1296+ return Err ( Error :: DanglingReference ( netref . nets ( ) . collect ( ) ) ) ;
13011297 }
13021298 let old_index = unwrapped. borrow ( ) . get_index ( ) ;
13031299 let objects = self . objects . borrow ( ) ;
@@ -1336,10 +1332,10 @@ where
13361332
13371333 /// Replaces the uses of a circuit node with another circuit node. The [Object] stored at `of` is returned.
13381334 /// Panics if `of` and `with` are not single-output nodes.
1339- pub fn replace_net_uses ( & self , of : NetRef < I > , with : & NetRef < I > ) -> Result < Object < I > , String > {
1335+ pub fn replace_net_uses ( & self , of : NetRef < I > , with : & NetRef < I > ) -> Result < Object < I > , Error > {
13401336 let unwrapped = of. clone ( ) . unwrap ( ) ;
13411337 if Rc :: strong_count ( & unwrapped) > 3 {
1342- return Err ( "Cannot replace. References still exist on this node" . to_string ( ) ) ;
1338+ return Err ( Error :: DanglingReference ( of . nets ( ) . collect ( ) ) ) ;
13431339 }
13441340
13451341 let old_tag: DrivenNet < I > = of. clone ( ) . into ( ) ;
@@ -1405,7 +1401,7 @@ where
14051401 }
14061402
14071403 /// Constructs an analysis of the netlist.
1408- pub fn get_analysis < ' a , A : Analysis < ' a , I > > ( & ' a self ) -> Result < A , String > {
1404+ pub fn get_analysis < ' a , A : Analysis < ' a , I > > ( & ' a self ) -> Result < A , Error > {
14091405 A :: build ( self )
14101406 }
14111407
@@ -1450,7 +1446,7 @@ where
14501446 }
14511447
14521448 /// Cleans unused nodes from the netlist, returning `Ok(true)` if the netlist changed.
1453- pub fn clean_once ( & self ) -> Result < bool , String > {
1449+ pub fn clean_once ( & self ) -> Result < bool , Error > {
14541450 let mut dead_objs = HashSet :: new ( ) ;
14551451 {
14561452 let fan_out = self . get_analysis :: < FanOutTable < I > > ( ) ?;
@@ -1477,11 +1473,10 @@ where
14771473 let mut remap: HashMap < usize , usize > = HashMap :: new ( ) ;
14781474 for ( old_index, obj) in old_objects. into_iter ( ) . enumerate ( ) {
14791475 if dead_objs. contains ( & old_index) {
1476+ // 1. this ref, 2. as an output
14801477 if Rc :: strong_count ( & obj) > 2 {
1481- return Err ( format ! (
1482- "Cannot delete object {} as a NetRef still exists, or it is an output. SC = {}" ,
1483- obj. borrow( ) . get( ) ,
1484- Rc :: strong_count( & obj)
1478+ return Err ( Error :: DanglingReference (
1479+ obj. borrow ( ) . get ( ) . get_nets ( ) . to_vec ( ) ,
14851480 ) ) ;
14861481 }
14871482 continue ;
@@ -1513,7 +1508,7 @@ where
15131508
15141509 /// Greedly removes unused nodes from the netlist, until it stops changing.
15151510 /// Returns true if the netlist was changed.
1516- pub fn clean ( & self ) -> Result < bool , String > {
1511+ pub fn clean ( & self ) -> Result < bool , Error > {
15171512 if !self . clean_once ( ) ? {
15181513 Ok ( false )
15191514 } else {
@@ -1526,42 +1521,39 @@ where
15261521 }
15271522
15281523 /// Returns `true` if all the nets are uniquely named
1529- fn nets_unique ( & self ) -> bool {
1524+ fn nets_unique ( & self ) -> Result < ( ) , Error > {
15301525 let mut nets = HashSet :: new ( ) ;
15311526 for net in self . into_iter ( ) {
1532- if !nets. insert ( net. take_identifier ( ) ) {
1533- return false ;
1527+ if !nets. insert ( net. clone ( ) . take_identifier ( ) ) {
1528+ return Err ( Error :: NonuniqueNets ( vec ! [ net ] ) ) ;
15341529 }
15351530 }
1536- true
1531+ Ok ( ( ) )
15371532 }
15381533
15391534 /// Returns `true` if all the nets are uniquely named
1540- fn insts_unique ( & self ) -> bool {
1535+ fn insts_unique ( & self ) -> Result < ( ) , Error > {
15411536 let mut insts = HashSet :: new ( ) ;
15421537 for inst in self . objects ( ) {
15431538 if let Some ( name) = inst. get_instance_name ( )
1544- && !insts. insert ( name)
1539+ && !insts. insert ( name. clone ( ) )
15451540 {
1546- return false ;
1541+ return Err ( Error :: NonuniqueInsts ( vec ! [ name ] ) ) ;
15471542 }
15481543 }
1549- true
1544+ Ok ( ( ) )
15501545 }
15511546
15521547 /// Verifies that a netlist is well-formed.
1553- pub fn verify ( & self ) -> Result < ( ) , String > {
1548+ pub fn verify ( & self ) -> Result < ( ) , Error > {
15541549 if self . outputs . borrow ( ) . is_empty ( ) {
1555- return Err ( "Netlist has no outputs" . to_string ( ) ) ;
1550+ return Err ( Error :: NoOutputs ) ;
15561551 }
15571552
1558- if ! self . nets_unique ( ) {
1559- return Err ( "Netlist contains non-unique nets (multiple drivers)" . to_string ( ) ) ;
1560- }
1553+ self . nets_unique ( ) ? ;
1554+
1555+ self . insts_unique ( ) ? ;
15611556
1562- if !self . insts_unique ( ) {
1563- return Err ( "Netlist contains non-unique instances" . to_string ( ) ) ;
1564- }
15651557 Ok ( ( ) )
15661558 }
15671559}
0 commit comments