99
1010from amaranth import Shape
1111from chipflow_lib import _parse_config , _get_cls_by_reference
12- from chipflow_lib .platforms import PACKAGE_DEFINITIONS , Schemas
12+ from chipflow_lib .platforms import PACKAGE_DEFINITIONS , PIN_ANNOTATION_SCHEMA
1313
14- # logging.basicConfig(stream=sys.stdout, level=logging.WARNING)
15- logging .basicConfig (stream = sys .stdout , level = logging .DEBUG )
14+ # logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
1615logger = logging .getLogger (__name__ )
1716
1817
19- def count_pins (member ):
20- if member ['type' ] == 'interface' :
18+ def count_pins (name , member ):
19+ logger .debug (f"count_pins { name } { member ['type' ]} { member ['annotations' ] if 'annotations' in member else 'no annotations' } " )
20+ if member ['type' ]== 'interface' and 'annotations' in member \
21+ and PIN_ANNOTATION_SCHEMA in member ['annotations' ]:
22+ return member ['annotations' ][PIN_ANNOTATION_SCHEMA ]['width' ]
23+ elif member ['type' ] == 'interface' :
2124 width = 0
22- for _ , v in member ['members' ].items ():
23- width += count_pins (v )
25+ for n , v in member ['members' ].items ():
26+ width += count_pins ('_' . join ([ name , n ]), v )
2427 return width
2528 elif member ['type' ] == 'port' :
2629 return member ['width' ]
2730
31+ def count_old_pins (d ):
32+ match d :
33+ case {'type' :t , 'pins' :p }:
34+ return len (p )
35+ case _:
36+ return sum ([count_old_pins (v ) for v in d .values ()])
2837
2938def allocate_pins (name , member , pins :list ):
3039 pin_map = {}
31- logger .debug (f"allocate_pins: name={ name } , member={ member } , pins={ pins } " )
32-
33- match member :
34- case {'type' :'interface' , 'annotations' :{Schemas .PIN_ANNOTATION : sig }}:
35- logger .debug ("matched PinSignature {sig}" )
36- name = name
37- width = sig ['width' ]
38- direction = sig ['direction' ]
39- if width == 1 :
40- pin_map [name ] = {'pin' :pins [0 ], 'direction' :direction }
41- else :
42- pin_map [name ] = {'pins' :pins ,
43- 'direction' :direction }
44- return pin_map , pins [width :]
45- case {'type' : 'interface' }:
46- for k , v in member ['members' ].items ():
47- n = '_' .join ([name ,k ])
48- _map , pins = allocate_pins (n , v , pins )
49- pin_map |= _map
50- logger .debug (f"{ pin_map } ,{ _map } " )
51- return pin_map , pins
52- case {'type' : 'port' }:
53- logging .warning (f"Component `{ name } ` in this design is not using PinSignature" )
54- name = name
55- width = member ['width' ]
56- direction = member ['dir' ]
57- if width == 1 :
58- pin_map [name ] = {'pin' :pins [0 ], 'direction' :direction }
59- else :
60- pin_map [name ] = {'pins' :pins ,
61- 'direction' :direction }
62- return pin_map , pins [width :]
63- case _:
64- logging .debug (f"Shouldnt get here. member = { member } " )
65- assert False
40+ logger .debug (f"allocate_pins: name={ name } , pins={ pins } " )
41+ logger .debug (f"member={ pformat (member )} " )
42+
43+ if member ['type' ]== 'interface' and 'annotations' in member \
44+ and PIN_ANNOTATION_SCHEMA in member ['annotations' ]:
45+ logger .debug ("matched PinSignature {sig}" )
46+ name = name
47+ sig = member ['annotations' ][PIN_ANNOTATION_SCHEMA ]
48+ width = sig ['width' ]
49+ direction = sig ['direction' ]
50+ pin_map [name ] = {'pins' :pins [0 :width ],
51+ 'direction' :direction ,
52+ 'type' :'io' }
53+ return pin_map , pins [width :]
54+ elif member ['type' ] == 'interface' :
55+ logger .warning ("member without PinSignature, pin allocation likely to be wrong" )
56+ for k , v in member ['members' ].items ():
57+ n = '_' .join ([name ,k ])
58+ _map , pins = allocate_pins (n , v , pins )
59+ pin_map |= _map
60+ logger .debug (f"{ pin_map } ,{ _map } " )
61+ return pin_map , pins
62+ elif member ['type' ] == 'port' :
63+ logger .warning (f"Component `{ name } ` in this design is not using PinSignature" )
64+ name = name
65+ width = member ['width' ]
66+ direction = member ['dir' ]
67+ pin_map [name ] = {'pins' :pins [0 :width ],
68+ 'direction' :direction ,
69+ 'type' : 'io' }
70+ return pin_map , pins [width :]
71+ else :
72+ logging .debug (f"Shouldnt get here. member = { member } " )
73+ assert False
6674
6775
6876def check_pins (name , member , old_map , new_map ):
@@ -72,11 +80,8 @@ def check_pins(name, member, old_map, new_map):
7280 check_pins (n , v , old_map , new_map )
7381 elif member ['type' ] == 'port' :
7482 width = member ['width' ]
75- if width == 1 :
76- assert 'pin' in old_map [name ]
77- else :
78- assert 'pins' in old_map [name ]
79- assert len (old_map [name ]['pins' ]) == width
83+ assert 'pins' in old_map [name ]
84+ assert len (old_map [name ]['pins' ]) == width
8085 new_map [name ] = old_map [name ]
8186
8287def lock_pins ():
@@ -87,13 +92,10 @@ def lock_pins():
8792 if lockfile .exists ():
8893 with open (lockfile ) as f :
8994 old_lock = json .load (f )
90- old_interfaces = old_lock ['interfaces' ]
9195 old_map = old_lock ['map' ]
9296 else :
9397 old_map = {}
94- old_interfaces = {}
95-
96- print (f"Locking pins: { 'using pins.lock' if lockfile else '' } " )
98+ print (f"Locking pins: { 'using pins.lock' if lockfile .exists () else '' } " )
9799 package_name = config ["chipflow" ]["silicon" ]["pad_ring" ]
98100
99101 if package_name not in PACKAGE_DEFINITIONS :
@@ -103,14 +105,14 @@ def lock_pins():
103105 for d in ("pads" , "power" ):
104106 logger .debug (f"Checking [chipflow.silicon.{ d } ]:" )
105107 for k , v in config ["chipflow" ]["silicon" ][d ].items ():
106- pin = v ['loc' ]
108+ pin = str ( v ['loc' ])
107109 used_pins .add (pin )
108- if k in old_map and old_map [k ]['pin ' ] != pin :
110+ if k in old_map and old_map [k ]['pins ' ] != [ pin ] :
109111 print (f"chipflow.toml conflicts with pins.lock: "
110- f"{ k } had pin { old_map [k ]} , now { pin } ." )
112+ f"{ k } had pin { old_map [k ][ 'pins' ] } , now { [ pin ] } ." )
111113 exit (1 )
112114 pin_map [k ] = {
113- 'pin ' : pin ,
115+ 'pins ' : [ pin ] ,
114116 'type' : v ['type' ] if 'type' in v else None }
115117
116118
@@ -147,29 +149,30 @@ def lock_pins():
147149 for k ,v in interfaces .items ():
148150 logger .debug (f"Interface { k } :" )
149151 logger .debug (pformat (v ))
150- width = count_pins (v )
151- logger .debug (f"member { k } total width = { width } " )
152- pins = package .allocate (unallocated , width )
153- logger .debug (f"allocated range: { pins } " )
154- if len (pins ) == 0 :
155- logger .error ("No pins were allocation by {package}" )
156- exit (1 )
157- if k in old_interfaces :
158- if len (old_interfaces [k ]['pins' ]) != len (pins ):
152+ width = count_pins (k , v )
153+ print (f" { k } : total { width } pins" )
154+ if k in old_map :
155+ print (f" { k } found in pins.lock, reusing" )
156+ logger .debug (pformat (old_map [k ]))
157+ old_width = count_old_pins (old_map [k ])
158+ if old_width != width :
159159 # TODO: option to allocate new pins nonconsecutively
160- print ("top level interface has changed size" )
160+ print (f "top level interface has changed size. Old size = { old_width } , new size = { width } " )
161161 exit (1 )
162- check_pins (k , v , old_map , pin_map )
163- pin_map_interfaces [k ] = {'top' : True , 'pins' :pins }
162+ pin_map [k ] = old_map [k ]
164163 else :
165- pin_map_interfaces [k ] = {'top' : True , 'pins' :pins }
164+ pins = package .allocate (unallocated , width )
165+ if len (pins ) == 0 :
166+ print ("ERROR: No pins were allocation by {package}" )
167+ exit (1 )
168+ logger .debug (f"allocated range: { pins } " )
166169 unallocated = unallocated - set (pins )
167- _map ,_ = allocate_pins (k , v , pins )
168- pin_map | = _map
170+ _map , _ = allocate_pins (k , v , pins )
171+ pin_map [ k ] = _map
169172
170173 with open ('pins.lock' , 'w' ) as f :
171- newlock = {'interfaces ' : pin_map_interfaces ,
172- 'map ' : pin_map }
174+ newlock = {'map ' : pin_map ,
175+ 'metadata ' : metadata }
173176
174177 json .dump (newlock , f , indent = 2 , sort_keys = True )
175178
0 commit comments