@ -14,6 +14,9 @@ class GrowingList(list):
				@@ -14,6 +14,9 @@ class GrowingList(list):
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            self . extend ( [ None ]  *  ( index  +  1  -  len ( self ) ) )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        super ( ) . __setitem__ ( index ,  value )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  free_index ( self ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        return  next ( ( i  for  i ,  x  in  enumerate ( self )  if  x  is  None ) ,  len ( self ) )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  IndexList ( list ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  __delitem__ ( self ,  index ) :  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -26,7 +29,7 @@ class IndexList(list):
				@@ -26,7 +29,7 @@ class IndexList(list):
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  Node :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    """ A named entity in a circuit (e.g. a gate, a standard cell,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    """ A node is a n amed entity in a circuit (e.g. a gate, a standard cell,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    a  named  signal ,  or  a  fan - out  point )  that  is  connected  to  other  nodes  via  lines .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    The  constructor  automatically  adds  the  new  node  to  the  given  circuit .  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -46,17 +49,17 @@ class Node:
				@@ -46,17 +49,17 @@ class Node:
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ The name of the node.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        Names  must  be  unique  among  all  forks  and  all  cells  in  the  circuit .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        However ,  a  fork  ( : code : ` kind == ' __fork__ ' ` )  and  a  cell  with  the  same  name  may  coexist .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        However ,  a  fork  ( : py : attr : ` kind `  is  set  to  ' __fork__ ' )  and  a  cell  with  the  same  name  may  coexist .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . kind  =  kind  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ A string describing the type of the node.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        Common  types  are  the  names  from  a  standard  cell  library  or  general  gate  names  like  ' AND '  or  ' NOR ' .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        If  : code : ` kind `  is  set  to  ' __fork__ ' ,  it  receives  special  treatment .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        If  : py : attr : ` kind `  is  set  to  ' __fork__ ' ,  it  receives  special  treatment .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        A  ` fork `  describes  a  named  signal  or  a  fan - out  point  in  the  circuit  and  not  a  physical  ` cell `  like  a  gate .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        In  the  circuit ,  the  namespaces  of  forks  and  cells  are  kept  separate .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        While  : code : ` name `  must  be  unique  among  all  forks  and  all  cells ,  a  fork  can  have  the  same  name  as  a  cell .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        The  : code : ` index ` ,  however ,  is  unique  among  all  nodes ;  a  fork  cannot  have  the  same  index  as  a  cell .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        While  : py : attr : ` name `  must  be  unique  among  all  forks  and  all  cells ,  a  fork  can  have  the  same  name  as  a  cell .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        The  : py : attr : ` index ` ,  however ,  is  unique  among  all  nodes ;  a  fork  cannot  have  the  same  index  as  a  cell .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . index  =  len ( circuit . nodes )  -  1  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ A unique and consecutive integer index of the node within the circuit.  
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -95,57 +98,67 @@ class Node:
				@@ -95,57 +98,67 @@ class Node:
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  Line :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    """ A directional 1:1 connection between two nodes.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    It  always  connects  an  output  of  a  node  ( called  ` driver ` )  to  an  input  of  a  node  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    ( called  ` reader ` )  and  has  a  circuit - unique  index  ( ` self . index ` ) .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    """ A line is a directional 1:1 connection between two nodes.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    Furthermore ,  ` self . driver_pin `  and  ` self . reader_pin `  are  the  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    integer  indices  of  the  connected  pins  of  the  nodes .  They  always  correspond  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    to  the  positions  of  the  line  in  the  connection  lists  of  the  nodes :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    It  always  connects  an  output  of  one  ` driver `  node  to  an  input  of  one  ` reader `  node .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    If  a  signal  fans  out  to  multiple  readers ,  a  ' __fork__ '  node  needs  to  be  added .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    *  ` self . driver . outs [ self . driver_pin ]  ==  self `  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    *  ` self . reader . ins [ self . reader_pin ]  ==  self `  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    The  constructor  automatically  adds  the  new  line  to  the  given  circuit  and  inserts  references  into  the  connection  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    lists  of  connected  nodes .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    A  Line  always  connects  a  single  driver  to  a  single  reader .  If  a  signal  fans  out  to  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    multiple  readers ,  a  ' __fork__ '  Node  needs  to  be  added .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    When  adding  a  line ,  input  and  output  pins  can  either  be  specified  explicitly  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    : code : ` Line ( circuit ,  ( driver ,  2 ) ,  ( reader ,  0 ) ) ` ,  or  implicitly  : code : ` Line ( circuit ,  driver ,  reader ) ` .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    In  the  implicit  case ,  the  line  will  be  connected  to  the  first  free  pin  of  the  node .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    Use  the  explicit  case  only  if  connections  to  specific  pins  are  required .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    It  may  overwrite  any  previous  line  references  in  the  connection  list  of  the  nodes .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  __init__ ( self ,  circuit ,  driver ,  reader ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . index  =  len ( circuit . lines )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        circuit . lines . append ( self )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  type ( driver )  is  Node :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            self . driver  =  driver  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            self . driver_pin  =  len ( driver . outs )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            for  pin ,  line  in  enumerate ( driver . outs ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  line  is  None :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    self . driver_pin  =  pin  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    break  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        else :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            self . driver ,  self . driver_pin  =  driver  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  type ( reader )  is  Node :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            self . reader  =  reader  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            self . reader_pin  =  len ( reader . ins )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            for  pin ,  line  in  enumerate ( reader . ins ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  line  is  None :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    self . reader_pin  =  pin  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    break  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        else :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            self . reader ,  self . reader_pin  =  reader  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . circuit  =  circuit  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ The :class:`Circuit` object the line is part of.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . circuit . lines . append ( self )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . index  =  len ( self . circuit . lines )  -  1  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ A unique and consecutive integer index of the line within the circuit.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        It  can  be  used  to  store  additional  data  about  the  line  : code : ` l `  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        by  allocating  an  array  or  list  : code : ` my_data `  of  length  : code : ` len ( l . circuit . lines ) `  and  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        accessing  it  by  : code : ` my_data [ l . index ] ` .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  not  isinstance ( driver ,  tuple ) :  driver  =  ( driver ,  driver . outs . free_index ( ) )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . driver  =  driver [ 0 ]  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ The :class:`Node` object that drives this line.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . driver_pin  =  driver [ 1 ]  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ The output pin position of the driver node this line is connected to.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        This  is  the  position  in  the  outs - list  of  the  driving  node  this  line  referenced  from :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        : code : ` self . driver . outs [ self . driver_pin ]  ==  self ` .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  not  isinstance ( reader ,  tuple ) :  reader  =  ( reader ,  reader . ins . free_index ( ) )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . reader  =  reader [ 0 ]  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ The :class:`Node` object that reads this line.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . reader_pin  =  reader [ 1 ]  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ The input pin position of the reader node this line is connected to.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        This  is  the  position  in  the  ins - list  of  the  reader  node  this  line  referenced  from :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        : code : ` self . reader . ins [ self . reader_pin ]  ==  self ` .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . driver . outs [ self . driver_pin ]  =  self  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . reader . ins [ self . reader_pin ]  =  self  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  remove ( self ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        circuit  =  None  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  self . driver  is  not  None :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            self . driver . outs [ self . driver_pin ]  =  None  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            circuit  =  self . driver . circuit  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  self . reader  is  not  None :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            self . reader . ins [ self . reader_pin ]  =  None  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            circuit  =  self . reader . circuit  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  circuit  is  not  None :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            del  circuit . lines [ self . index ]  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ Removes the line from its circuit and its referencing nodes.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        To  keep  the  indices  consecutive ,  the  line  with  the  highest  index  within  the  circuit  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        will  be  assigned  the  index  of  the  removed  line .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  self . driver  is  not  None :  self . driver . outs [ self . driver_pin ]  =  None  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  self . reader  is  not  None :  self . reader . ins [ self . reader_pin ]  =  None  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  self . circuit  is  not  None :  del  self . circuit . lines [ self . index ]  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . driver  =  None  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . reader  =  None  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . circuit  =  None  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  __repr__ ( self ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        return  f ' { self . index } '  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -157,27 +170,53 @@ class Line:
				@@ -157,27 +170,53 @@ class Line:
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					class  Circuit :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    """ A Circuit is a container for interconnected nodes and lines.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    All  contained  lines  have  unique  indices ,  so  have  all  contained  nodes .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    These  indices  can  be  used  to  store  additional  data  about  nodes  or  lines  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    by  allocating  an  array  ` my_data `  of  length  ` len ( self . nodes ) `  and  then  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    accessing  it  by  ` my_data [ n . index ] ` .  The  indices  may  change  iff  lines  or  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    nodes  are  removed  from  the  circuit .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    It  provides  access  to  lines  by  index  and  to  nodes  by  index  and  by  name .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    Nodes  come  in  two  flavors :  ` cells `  and  ` forks `  ( see  : py : attr : ` Node . kind ` ) .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    The  name  spaces  of  cells  and  forks  are  kept  separate .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    Nodes  come  in  two  flavors  ( cells  and  forks ,  see  ` Node ` ) .  The  names  of  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    these  nodes  are  kept  unique  within  these  two  flavors .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    The  indices  of  nodes  and  lines  are  kept  consecutive  and  unique .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    Whenever  lines  or  nodes  are  removed  from  the  circuit ,  the  indices  of  some  other  lines  or  nodes  may  change  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    to  enforce  consecutiveness .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    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 .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  __init__ ( self ,  name = None ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . name  =  name  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ The name of the circuit.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . nodes  =  IndexList ( )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ A list of all :class:`Node` objects contained in the circuit.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        The  position  of  a  node  in  this  list  equals  its  index  : code : ` self . nodes [ 42 ] . index  ==  42 ` .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . lines  =  IndexList ( )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ A list of all :class:`Line` objects contained in the circuit.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        The  position  of  a  line  in  this  list  equals  its  index  : code : ` self . lines [ 42 ] . index  ==  42 ` .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . interface  =  GrowingList ( )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ 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 ` .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        The  position  of  a  node  in  the  interface  list  corresponds  to  positions  of  logic  values  in  test  vectors .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        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 ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        and  nodes  without  any  lines  in  their  : py : attr : ` Node . outs `  list  are  regarded  as  primary  outputs .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . cells  =  { }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ A dictionary to access cells by name.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        self . forks  =  { }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ A dictionary to access forks by name.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  get_or_add_fork ( self ,  name ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        return  self . forks [ name ]  if  name  in  self . forks  else  Node ( self ,  name )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  copy ( self ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ Returns a deep copy of the circuit.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        c  =  Circuit ( self . name )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        for  node  in  self . nodes :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            Node ( c ,  node . name ,  node . kind )  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -194,6 +233,8 @@ class Circuit:
				@@ -194,6 +233,8 @@ class Circuit:
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        return  c  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  dump ( self ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ 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 '  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        return  header  +  ' \n ' . join ( [ str ( n )  for  n  in  self . nodes ] )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -202,6 +243,11 @@ class Circuit:
				@@ -202,6 +243,11 @@ class Circuit:
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        return  f ' <Circuit { name }  with  { len ( self . nodes ) }  nodes,  { len ( self . lines ) }  lines,  { len ( self . interface ) }  ports> '  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  topological_order ( self ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ Generator function to iterate over all nodes in topological order.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        Nodes  without  input  lines  and  nodes  whose  : py : attr : ` Node . kind `  contains  the  substring  ' DFF '  are  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        yielded  first .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        visit_count  =  [ 0 ]  *  len ( self . nodes )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        queue  =  deque ( n  for  n  in  self . nodes  if  len ( n . ins )  ==  0  or  ' DFF '  in  n . kind )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        while  len ( queue )  >  0 :  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -215,12 +261,19 @@ class Circuit:
				@@ -215,12 +261,19 @@ class Circuit:
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            yield  n  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  topological_line_order ( self ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ Generator function to iterate over all lines in topological order.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        for  n  in  self . topological_order ( ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            for  line  in  n . outs :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  line  is  not  None :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    yield  line  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  reversed_topological_order ( self ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ Generator function to iterate over all nodes in reversed topological order.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        Nodes  without  output  lines  and  nodes  whose  : py : attr : ` Node . kind `  contains  the  substring  ' DFF '  are  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        yielded  first .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        visit_count  =  [ 0 ]  *  len ( self . nodes )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        queue  =  deque ( n  for  n  in  self . nodes  if  len ( n . outs )  ==  0  or  ' DFF '  in  n . kind )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        while  len ( queue )  >  0 :  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -233,6 +286,10 @@ class Circuit:
				@@ -233,6 +286,10 @@ class Circuit:
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            yield  n  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    def  fanin ( self ,  origin_nodes ) :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """ Generator function to iterate over the fan-in cone of a given list of origin nodes.  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        Nodes  are  yielded  in  reversed  topological  order .  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        """  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        marks  =  [ False ]  *  len ( self . nodes )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        for  n  in  origin_nodes :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            marks [ n . index ]  =  True