@@ -15,20 +15,23 @@ use std::collections::hash_map::Entry;
1515use std:: collections:: { HashMap , HashSet } ;
1616
1717/// A common trait of analyses than can be performed on a netlist.
18+ /// An analysis becomes stale when the netlist is modified.
1819pub trait Analysis < ' a , I : Instantiable >
1920where
2021 Self : Sized + ' a ,
2122{
22- /// Construct the analysis
23+ /// Construct the analysis to the current state of the netlist.
2324 fn build ( netlist : & ' a Netlist < I > ) -> Result < Self , String > ;
2425}
2526
2627/// A table that maps nets to the circuit nodes they drive
2728pub struct FanOutTable < ' a , I : Instantiable > {
2829 // A reference to the underlying netlist
2930 _netlist : & ' a Netlist < I > ,
30- // Maps a net to the list of nets it drives
31- fan_out : HashMap < Net , Vec < NetRef < I > > > ,
31+ // Maps a net to the list of nodes it drives
32+ net_fan_out : HashMap < Net , Vec < NetRef < I > > > ,
33+ /// Maps a node to the list of nodes it drives
34+ node_fan_out : HashMap < NetRef < I > , Vec < NetRef < I > > > ,
3235 /// Contains nets which are outputs
3336 is_an_output : HashSet < Net > ,
3437}
@@ -38,17 +41,25 @@ where
3841 I : Instantiable ,
3942{
4043 /// Returns an iterator to the circuit nodes that use `net`.
41- pub fn get_users ( & self , net : & Net ) -> impl Iterator < Item = NetRef < I > > {
42- self . fan_out
44+ pub fn get_net_users ( & self , net : & Net ) -> impl Iterator < Item = NetRef < I > > {
45+ self . net_fan_out
4346 . get ( net)
4447 . into_iter ( )
4548 . flat_map ( |users| users. iter ( ) . cloned ( ) )
4649 }
4750
51+ /// Returns an iterator to the circuit nodes that use `node`.
52+ pub fn get_node_users ( & self , node : & NetRef < I > ) -> impl Iterator < Item = NetRef < I > > {
53+ self . node_fan_out
54+ . get ( node)
55+ . into_iter ( )
56+ . flat_map ( |users| users. iter ( ) . cloned ( ) )
57+ }
58+
4859 /// Returns `true` if the net has any used by any cells in the circuit
4960 /// This does incude nets that are only used as outputs.
50- pub fn has_uses ( & self , net : & Net ) -> bool {
51- ( self . fan_out . contains_key ( net) && !self . fan_out . get ( net) . unwrap ( ) . is_empty ( ) )
61+ pub fn net_has_uses ( & self , net : & Net ) -> bool {
62+ ( self . net_fan_out . contains_key ( net) && !self . net_fan_out . get ( net) . unwrap ( ) . is_empty ( ) )
5263 || self . is_an_output . contains ( net)
5364 }
5465}
@@ -58,14 +69,28 @@ where
5869 I : Instantiable ,
5970{
6071 fn build ( netlist : & ' a Netlist < I > ) -> Result < Self , String > {
61- let mut fan_out: HashMap < Net , Vec < NetRef < I > > > = HashMap :: new ( ) ;
72+ let mut net_fan_out: HashMap < Net , Vec < NetRef < I > > > = HashMap :: new ( ) ;
73+ #[ allow( clippy:: mutable_key_type) ]
74+ let mut node_fan_out: HashMap < NetRef < I > , Vec < NetRef < I > > > = HashMap :: new ( ) ;
6275 let mut is_an_output: HashSet < Net > = HashSet :: new ( ) ;
6376
6477 for c in netlist. connections ( ) {
65- if let Entry :: Vacant ( e) = fan_out. entry ( c. net ( ) ) {
78+ if let Entry :: Vacant ( e) = net_fan_out. entry ( c. net ( ) ) {
79+ e. insert ( vec ! [ c. target( ) . unwrap( ) ] ) ;
80+ } else {
81+ net_fan_out
82+ . get_mut ( & c. net ( ) )
83+ . unwrap ( )
84+ . push ( c. target ( ) . unwrap ( ) ) ;
85+ }
86+
87+ if let Entry :: Vacant ( e) = node_fan_out. entry ( c. src ( ) . unwrap ( ) ) {
6688 e. insert ( vec ! [ c. target( ) . unwrap( ) ] ) ;
6789 } else {
68- fan_out. get_mut ( & c. net ( ) ) . unwrap ( ) . push ( c. target ( ) . unwrap ( ) ) ;
90+ node_fan_out
91+ . get_mut ( & c. src ( ) . unwrap ( ) )
92+ . unwrap ( )
93+ . push ( c. target ( ) . unwrap ( ) ) ;
6994 }
7095 }
7196
76101
77102 Ok ( FanOutTable {
78103 _netlist : netlist,
79- fan_out,
104+ net_fan_out,
105+ node_fan_out,
80106 is_an_output,
81107 } )
82108 }
@@ -88,7 +114,7 @@ pub struct SimpleCombDepth<'a, I: Instantiable> {
88114 // A reference to the underlying netlist
89115 _netlist : & ' a Netlist < I > ,
90116 // Maps a net to its logic level as a DAG
91- comb_depth : HashMap < Net , usize > ,
117+ comb_depth : HashMap < NetRef < I > , usize > ,
92118 /// The maximum depth of the circuit
93119 max_depth : usize ,
94120}
@@ -97,9 +123,9 @@ impl<I> SimpleCombDepth<'_, I>
97123where
98124 I : Instantiable ,
99125{
100- /// Returns the logic level of a net in the circuit.
101- pub fn get_comb_depth ( & self , net : & Net ) -> Option < usize > {
102- self . comb_depth . get ( net ) . cloned ( )
126+ /// Returns the logic level of a node in the circuit.
127+ pub fn get_comb_depth ( & self , node : & NetRef < I > ) -> Option < usize > {
128+ self . comb_depth . get ( node ) . cloned ( )
103129 }
104130
105131 /// Returns the maximum logic level of the circuit.
@@ -113,7 +139,8 @@ where
113139 I : Instantiable ,
114140{
115141 fn build ( netlist : & ' a Netlist < I > ) -> Result < Self , String > {
116- let mut comb_depth: HashMap < Net , usize > = HashMap :: new ( ) ;
142+ #[ allow( clippy:: mutable_key_type) ]
143+ let mut comb_depth: HashMap < NetRef < I > , usize > = HashMap :: new ( ) ;
117144
118145 let mut nodes = Vec :: new ( ) ;
119146 for ( driven, _) in netlist. outputs ( ) {
@@ -129,18 +156,17 @@ where
129156
130157 for node in nodes {
131158 if node. is_an_input ( ) {
132- comb_depth. insert ( node. as_net ( ) . clone ( ) , 0 ) ;
159+ comb_depth. insert ( node. clone ( ) , 0 ) ;
133160 } else {
134161 // TODO(matth2k): get_driver_net() relies on a weak reference. Rewrite without it.
135162 let max_depth: usize = ( 0 ..node. get_num_input_ports ( ) )
136- . filter_map ( |i| netlist. get_driver_net ( node. clone ( ) , i) )
163+ . filter_map ( |i| netlist. get_driver ( node. clone ( ) , i) )
137164 . filter_map ( |n| comb_depth. get ( & n) )
138165 . max ( )
139166 . cloned ( )
140167 . unwrap_or ( usize:: MAX ) ;
141- for net in node. nets ( ) {
142- comb_depth. insert ( net, max_depth + 1 ) ;
143- }
168+
169+ comb_depth. insert ( node, max_depth + 1 ) ;
144170 }
145171 }
146172
0 commit comments