@@ -416,7 +416,7 @@ def _find_contiguous_sequence(ordering: PinList, lst: PinList, total: int) -> Pi
416416 if unable to find a consecutive list, allocate as contigously as possible
417417 """
418418 if not lst or len (lst ) < total :
419- raise ChipFlowError ( "Invalid request to find_contiguous_argument " )
419+ raise ValueError ( f "Invalid request to _find_contiguous_sequence: lst= { lst } " )
420420
421421 grouped = _group_consecutive_items (ordering , lst )
422422
@@ -472,26 +472,37 @@ def _allocate_pins(name: str, member: Dict[str, Any], pins: List[Pin], port_name
472472 logger .debug (f"member={ pformat (member )} " )
473473
474474 if member ['type' ] == 'interface' and 'annotations' in member \
475- and IO_ANNOTATION_SCHEMA in member ['annotations' ]:
475+ and IO_ANNOTATION_SCHEMA in member ['annotations' ]:
476476 model :IOModel = member ['annotations' ][IO_ANNOTATION_SCHEMA ]
477477 logger .debug (f"matched IOSignature { model } " )
478478 name = name
479479 width = model ['width' ]
480480 pin_map [name ] = PortDesc (pins = pins [0 :width ], type = 'io' , port_name = port_name , iomodel = model )
481481 logger .debug (f"added '{ name } ':{ pin_map [name ]} to pin_map" )
482+ if len (pins ) - width < 0 :
483+ raise ChipFlowError (f"Ran out of available pins when allocating '{ port_name } `" )
482484 return pin_map , pins [width :]
483485 elif member ['type' ] == 'interface' :
484- for k , v in member ['members' ].items ():
485- port_name = '_' .join ([name , k ])
486- _map , pins = _allocate_pins (k , v , pins , port_name = port_name )
487- pin_map |= _map
488- logger .debug (f"{ pin_map } ,{ _map } " )
489- return pin_map , pins
486+ try :
487+ for k , v in member ['members' ].items ():
488+ port_name = '_' .join ([name , k ])
489+ _map , pins = _allocate_pins (k , v , pins , port_name = port_name )
490+ pin_map |= _map
491+ logger .debug (f"{ pin_map } ,{ _map } " )
492+ return pin_map , pins
493+ except ChipFlowError as e :
494+ e .add_note ("While allocating {name}" )
495+ raise e
496+ except ValueError as e :
497+ raise ChipFlowError (f"Ran out of available pins when allocating '{ port_name } `" )
498+
490499 elif member ['type' ] == 'port' :
491500 logger .warning (f"PortDesc '{ name } ' has no IOSignature, pin allocation likely to be wrong" )
492501 width = member ['width' ]
493502 model = IOModel (width = width , direction = io .Direction (member ['dir' ]))
494503 pin_map [name ] = PortDesc (pins = pins [0 :width ], type = 'io' , port_name = port_name , iomodel = model )
504+ if len (pins ) - width < 0 :
505+ raise ChipFlowError (f"Ran out of available pins when allocating '{ port_name } `" )
495506 logger .debug (f"added '{ name } ':{ pin_map [name ]} to pin_map" )
496507 return pin_map , pins [width :]
497508 else :
@@ -519,12 +530,27 @@ def _add_ports(self, component: str, interface: str, ports: Interface):
519530 self .ports [component ] = {}
520531 self .ports [component ][interface ] = ports
521532
522- def get_ports (self , component : str , interface : str ) -> Interface | None :
523-
533+ def get_ports (self , component : Optional [str ] = None , interface : Optional [str ] = None ) -> Interface | None :
524534 "List the ports allocated in this PortMap for the given `Component` and `Interface`"
525- if component not in self .ports or interface not in self .ports [component ]:
526- return None
527- return self .ports [component ][interface ]
535+ out : Interface = {}
536+ if not component :
537+ for c , v in self .ports .items ():
538+ for i , v in self .ports [c ].items ():
539+ vn = { f"{ c } .{ i } .{ pn } " : p for pn , p in v .items () }
540+ out |= vn
541+ return out
542+ elif not interface :
543+ if component not in self .ports :
544+ return None
545+ for i , v in self .ports [component ].items ():
546+ vn = { f"{ i } .{ pn } " : p for pn , p in v .items () }
547+ out |= vn
548+ return out
549+ else :
550+ if component not in self .ports or interface not in self .ports [component ]:
551+ return None
552+ return self .ports [component ][interface ]
553+
528554
529555 def get_clocks (self ) -> List [PortDesc ]:
530556 ret = []
@@ -572,6 +598,7 @@ class Package(pydantic.BaseModel):
572598
573599# TODO: minimise names into more traditional form
574600def _linear_allocate_components (interfaces : dict , lockfile : LockFile | None , allocate , unallocated ) -> PortMap :
601+ assert len (unallocated )
575602 port_map = PortMap ()
576603 for component , v in interfaces .items ():
577604 for interface , v in v ['interface' ]['members' ].items ():
@@ -592,9 +619,20 @@ def _linear_allocate_components(interfaces: dict, lockfile: LockFile | None, all
592619 )
593620 port_map ._add_ports (component , interface , old_ports )
594621 else :
622+ if len (unallocated ) == 0 :
623+ ports = port_map .get_ports ()
624+ errstr = ''
625+ total = 0
626+ assert ports
627+ for pn ,pd in ports .items ():
628+ errstr += f"\n { pn } : "
629+ assert pd .pins
630+ errstr += f"{ len (pd .pins )} pins"
631+ total += len (pd .pins )
632+ errstr += '\n '
633+ raise ChipFlowError (f"Ran out of available pins when allocating '{ component } .{ interface } `\n "
634+ f"Ports already allocated were:\n { errstr } \n Total pins: { total } " )
595635 pins = allocate (unallocated , width )
596- if len (pins ) == 0 :
597- raise ChipFlowError ("No pins were allocated" )
598636 logger .debug (f"allocated range: { pins } " )
599637 unallocated = unallocated - set (pins )
600638 _map , _ = _allocate_pins (f"{ component } _{ interface } " , v , pins )
0 commit comments