@ -5,7 +5,7 @@ A node is an instance of class :class:`Node`, 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					and  a  line  is  an  instance  of  class  : class : ` Line ` .  
					 
					 
					 
					and  a  line  is  an  instance  of  class  : class : ` Line ` .  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					"""  
					 
					 
					 
					"""  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					from  collections  import  deque  
					 
					 
					 
					from  collections  import  deque ,  defaultdict  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					import  re  
					 
					 
					 
					import  re  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -203,7 +203,7 @@ class Circuit: 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    to  enforce  consecutiveness .  
					 
					 
					 
					    to  enforce  consecutiveness .  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    A  subset  of  nodes  can  be  designated  as  primary  input -  or  output - ports  of  the  circuit .  
					 
					 
					 
					    A  subset  of  nodes  can  be  designated  as  primary  input -  or  output - ports  of  the  circuit .  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    This  is  done  by  adding  them  to  the  : py : attr : ` interface  `  list .  
					 
					 
					 
					    This  is  done  by  adding  them  to  the  : py : attr : ` io_nodes  `  list .  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					    """  
					 
					 
					 
					    """  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    def  __init__ ( self ,  name = None ) :  
					 
					 
					 
					    def  __init__ ( self ,  name = None ) :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        self . name  =  name  
					 
					 
					 
					        self . name  =  name  
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -219,13 +219,13 @@ class Circuit: 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        The  position  of  a  line  in  this  list  equals  its  index  : code : ` self . lines [ 42 ] . index  ==  42 ` .  
					 
					 
					 
					        The  position  of  a  line  in  this  list  equals  its  index  : code : ` self . lines [ 42 ] . index  ==  42 ` .  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        """  
					 
					 
					 
					        """  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        self . interface   =  GrowingList ( )  
					 
					 
					 
					        self . io_nodes   =  GrowingList ( )  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        """ A list of nodes that are designated as primary input- or output-ports.  
					 
					 
					 
					        """ A list of nodes that are designated as primary input- or output-ports.  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        Port - nodes  are  contained  in  : py : attr : ` nodes `  as  well  as  : py : attr : ` interface  ` .  
					 
					 
					 
					        Port - nodes  are  contained  in  : py : attr : ` nodes `  as  well  as  : py : attr : ` io_nodes  ` .  
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					        The  position  of  a  node  in  the  interface   list  corresponds  to  positions  of  logic  values  in  test  vectors .  
					 
					 
					 
					        The  position  of  a  node  in  the  io_nodes   list  corresponds  to  positions  of  logic  values  in  test  vectors .  
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        The  port  direction  is  not  stored  explicitly .  
					 
					 
					 
					        The  port  direction  is  not  stored  explicitly .  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        Usually ,  nodes  in  the  interface   list  without  any  lines  in  their  : py : attr : ` Node . ins `  list  are  primary  inputs ,  
					 
					 
					 
					        Usually ,  nodes  in  the  io_nodes   list  without  any  lines  in  their  : py : attr : ` Node . ins `  list  are  primary  inputs ,  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        and  nodes  without  any  lines  in  their  : py : attr : ` Node . outs `  list  are  regarded  as  primary  outputs .  
					 
					 
					 
					        and  nodes  without  any  lines  in  their  : py : attr : ` Node . outs `  list  are  regarded  as  primary  outputs .  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        """  
					 
					 
					 
					        """  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        self . cells  =  { }  
					 
					 
					 
					        self . cells  =  { }  
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -248,50 +248,57 @@ class Circuit: 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            d  =  c . forks [ line . driver . name ]  if  line . driver . kind  ==  ' __fork__ '  else  c . cells [ line . driver . name ]  
					 
					 
					 
					            d  =  c . forks [ line . driver . name ]  if  line . driver . kind  ==  ' __fork__ '  else  c . cells [ line . driver . name ]  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            r  =  c . forks [ line . reader . name ]  if  line . reader . kind  ==  ' __fork__ '  else  c . cells [ line . reader . name ]  
					 
					 
					 
					            r  =  c . forks [ line . reader . name ]  if  line . reader . kind  ==  ' __fork__ '  else  c . cells [ line . reader . name ]  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            Line ( c ,  ( d ,  line . driver_pin ) ,  ( r ,  line . reader_pin ) )  
					 
					 
					 
					            Line ( c ,  ( d ,  line . driver_pin ) ,  ( r ,  line . reader_pin ) )  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        for  node  in  self . interface  :  
					 
					 
					 
					        for  node  in  self . io_nodes  :  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					            if  node . kind  ==  ' __fork__ ' :  
					 
					 
					 
					            if  node . kind  ==  ' __fork__ ' :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                n  =  c . forks [ node . name ]  
					 
					 
					 
					                n  =  c . forks [ node . name ]  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            else :  
					 
					 
					 
					            else :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                n  =  c . cells [ node . name ]  
					 
					 
					 
					                n  =  c . cells [ node . name ]  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            c . interface  . append ( n )  
					 
					 
					 
					            c . io_nodes  . append ( n )  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        return  c  
					 
					 
					 
					        return  c  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    def  __getstate__ ( self ) :  
					 
					 
					 
					    def  __getstate__ ( self ) :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        nodes  =  [ ( node . name ,  node . kind )  for  node  in  self . nodes ]  
					 
					 
					 
					        nodes  =  [ ( node . name ,  node . kind )  for  node  in  self . nodes ]  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        lines  =  [ ( line . driver . index ,  line . driver_pin ,  line . reader . index ,  line . reader_pin )  for  line  in  self . lines ]  
					 
					 
					 
					        lines  =  [ ( line . driver . index ,  line . driver_pin ,  line . reader . index ,  line . reader_pin )  for  line  in  self . lines ]  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        interface   =  [ n . index  for  n  in  self . interface  ]  
					 
					 
					 
					        io_nodes   =  [ n . index  for  n  in  self . io_nodes  ]  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        return  { ' name ' :  self . name ,  
					 
					 
					 
					        return  { ' name ' :  self . name ,  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                ' nodes ' :  nodes ,  
					 
					 
					 
					                ' nodes ' :  nodes ,  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                ' lines ' :  lines ,  
					 
					 
					 
					                ' lines ' :  lines ,  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                ' interface ' :  interface   }  
					 
					 
					 
					                ' io_nodes ' :  io_nodes   }  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    def  __setstate__ ( self ,  state ) :  
					 
					 
					 
					    def  __setstate__ ( self ,  state ) :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        self . name  =  state [ ' name ' ]  
					 
					 
					 
					        self . name  =  state [ ' name ' ]  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        self . nodes  =  IndexList ( )  
					 
					 
					 
					        self . nodes  =  IndexList ( )  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        self . lines  =  IndexList ( )  
					 
					 
					 
					        self . lines  =  IndexList ( )  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        self . interface   =  GrowingList ( )  
					 
					 
					 
					        self . io_nodes   =  GrowingList ( )  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        self . cells  =  { }  
					 
					 
					 
					        self . cells  =  { }  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        self . forks  =  { }  
					 
					 
					 
					        self . forks  =  { }  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        for  s  in  state [ ' nodes ' ] :  
					 
					 
					 
					        for  s  in  state [ ' nodes ' ] :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            Node ( self ,  * s )  
					 
					 
					 
					            Node ( self ,  * s )  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        for  driver ,  driver_pin ,  reader ,  reader_pin  in  state [ ' lines ' ] :  
					 
					 
					 
					        for  driver ,  driver_pin ,  reader ,  reader_pin  in  state [ ' lines ' ] :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            Line ( self ,  ( self . nodes [ driver ] ,  driver_pin ) ,  ( self . nodes [ reader ] ,  reader_pin ) )  
					 
					 
					 
					            Line ( self ,  ( self . nodes [ driver ] ,  driver_pin ) ,  ( self . nodes [ reader ] ,  reader_pin ) )  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        for  n  in  state [ ' interface  ' ] :  
					 
					 
					 
					        for  n  in  state [ ' io_nodes  ' ] :  
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					            self . interface  . append ( self . nodes [ n ] )  
					 
					 
					 
					            self . io_nodes  . append ( self . nodes [ n ] )  
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    def  __eq__ ( self ,  other ) :  
					 
					 
					 
					    def  __eq__ ( self ,  other ) :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        return  self . nodes  ==  other . nodes  and  self . lines  ==  other . lines  and  self . interface   ==  other . interface   
					 
					 
					 
					        return  self . nodes  ==  other . nodes  and  self . lines  ==  other . lines  and  self . io_nodes   ==  other . io_nodes   
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    def  dump ( self ) :  
					 
					 
					 
					    def  dump ( self ) :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        """ Returns a string representation of the circuit and all its nodes.  
					 
					 
					 
					        """ Returns a string representation of the circuit and all its nodes.  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        """  
					 
					 
					 
					        """  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        header  =  f ' { self . name } ( { " , " . join ( [ str ( n . index )  for  n  in  self . interface  ] ) } ) \n '  
					 
					 
					 
					        header  =  f ' { self . name } ( { " , " . join ( [ str ( n . index )  for  n  in  self . io_nodes  ] ) } ) \n '  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        return  header  +  ' \n ' . join ( [ str ( n )  for  n  in  self . nodes ] )  
					 
					 
					 
					        return  header  +  ' \n ' . join ( [ str ( n )  for  n  in  self . nodes ] )  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    def  __repr__ ( self ) :  
					 
					 
					 
					    def  __repr__ ( self ) :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        name  =  f '   { self . name } '  if  self . name  else  ' '  
					 
					 
					 
					        name  =  f '   { self . name } '  if  self . name  else  ' '  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        return  f ' <Circuit { name }  cells= { len ( self . cells ) }  forks= { len ( self . forks ) }   '  +  \ 
					 
					 
					 
					        return  f ' <Circuit { name }  cells= { len ( self . cells ) }  forks= { len ( self . forks ) }   '  +  \ 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					               f ' lines= { len ( self . lines ) }  ports= { len ( self . interface ) } > '  
					 
					 
					 
					               f ' lines= { len ( self . lines ) }  ports= { len ( self . io_nodes ) } > '  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    @property  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    def  cell_counts ( self ) :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        counts  =  defaultdict ( int )  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        for  n  in  self . cells . values ( ) :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            counts [ n . kind ]  + =  1  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        return  counts  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    def  topological_order ( self ) :  
					 
					 
					 
					    def  topological_order ( self ) :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        """ Generator function to iterate over all nodes in topological order.  
					 
					 
					 
					        """ Generator function to iterate over all nodes in topological order.  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -375,8 +382,8 @@ class Circuit: 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    def  io_loc ( self ,  prefix ) :  
					 
					 
					 
					    def  io_loc ( self ,  prefix ) :  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        d_top  =  dict ( )  
					 
					 
					 
					        d_top  =  dict ( )  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        for  i ,  n  in  enumerate ( list ( self . interface  )  +  [ n  for  n  in  self . nodes  if  ' dff '  in  n . kind . lower ( ) ] ) :  
					 
					 
					 
					        for  i ,  n  in  enumerate ( list ( self . io_nodes  )  +  [ n  for  n  in  self . nodes  if  ' dff '  in  n . kind . lower ( ) ] ) :  
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					            if  m  :=  re . match ( fr ' ( { prefix } .*?)((?:[_ \ [ \ ]]  \ d+)* [_ \ [ \ ]]*$) ' ,  n . name ) :  
					 
					 
					 
					            if  m  :=  re . match ( fr ' ( { prefix } .*?)((?: \ d+[_ \ [ \ ]]) *$) ' ,  n . name ) :  
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					                path  =  [ m [ 1 ] ]  +  [ int ( v )  for  v  in  re . split ( r ' [_ \ [ \ ]]+ ' ,  m [ 2 ] )  if  len ( v )  >  0 ]  
					 
					 
					 
					                path  =  [ m [ 1 ] ]  +  [ int ( v )  for  v  in  re . split ( r ' [_ \ [ \ ]]+ ' ,  m [ 2 ] )  if  len ( v )  >  0 ]  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                d  =  d_top  
					 
					 
					 
					                d  =  d_top  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                for  j  in  path [ : - 1 ] :  
					 
					 
					 
					                for  j  in  path [ : - 1 ] :