Skip to content

Commit 21dd21f

Browse files
committed
maybe working...
1 parent c3a2d29 commit 21dd21f

File tree

5 files changed

+53
-56
lines changed

5 files changed

+53
-56
lines changed

chipflow_lib/pin_lock.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@ def lock_pins() -> None:
2929
# Get package definition from dict instead of Pydantic model
3030
package_name = config_dict["chipflow"]["silicon"]["package"]
3131
package_def = PACKAGE_DEFINITIONS[package_name]
32+
process = config_dict["chipflow"]["silicon"]["process"]
3233

3334
top = top_components(config_dict)
3435

3536
# Use the PackageDef to allocate the pins:
3637
for name, component in top.items():
3738
package_def.register_component(name, component)
3839

39-
newlock = package_def.allocate_pins(oldlock)
40+
newlock = package_def.allocate_pins(process, oldlock)
4041

4142
with open(lockfile, 'w') as f:
4243
f.write(newlock.model_dump_json(indent=2, serialize_as_any=True))
@@ -47,9 +48,10 @@ def __init__(self, config):
4748
self.config = config
4849

4950
def build_cli_parser(self, parser):
51+
assert inspect.getdoc(self.lock) is not None
5052
action_argument = parser.add_subparsers(dest="action")
5153
action_argument.add_parser(
52-
"lock", help=inspect.getdoc(self.lock).splitlines()[0])
54+
"lock", help=inspect.getdoc(self.lock).splitlines()[0]) # type: ignore
5355

5456
def run_cli(self, args):
5557
logger.debug(f"command {args}")

chipflow_lib/platforms/utils.py

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class IOModel(TypedDict):
8888
"""
8989

9090
width: NotRequired[int]
91-
direction: NotRequired[io.Direction]
91+
direction: NotRequired[Annotated[io.Direction, PlainSerializer(lambda x: str(x))]]
9292
all_have_oe: NotRequired[bool]
9393
allocate_power: NotRequired[bool]
9494
power_voltage: NotRequired[VoltageRange]
@@ -214,7 +214,7 @@ def BidirIOSignature(width:int , **kwargs: Unpack[IOModel]):
214214
return IOSignature(**kwargs)
215215

216216

217-
Pin = Union[tuple, str, int]
217+
Pin = Union[Tuple[Any,...], str, int]
218218
PinSet = Set[Pin]
219219
PinList = List[Pin]
220220
Pins = Union[PinSet, PinList]
@@ -400,12 +400,9 @@ def _allocate_pins(name: str, member: Dict[str, Any], pins: List[str], port_name
400400
logger.debug(f"matched PinSignature {sig}")
401401
name = name
402402
width = sig['width']
403-
options = sig['options']
404403
pin_map[name] = {'pins': pins[0:width],
405-
'direction': sig['direction'],
406404
'type': 'io',
407-
'port_name': port_name,
408-
'options': options}
405+
'port_name': port_name } | sig
409406
logger.debug(f"added '{name}':{pin_map[name]} to pin_map")
410407
return pin_map, pins[width:]
411408
elif member['type'] == 'interface':
@@ -501,17 +498,16 @@ class LockFile(pydantic.BaseModel):
501498
metadata: dict
502499

503500

504-
PackageDef = Union['GAPackageDef', 'QuadPackageDef', 'BareDiePackageDef', 'BasePackageDef']
505-
501+
PackageDef = Union['GAPackageDef', 'QuadPackageDef', 'BareDiePackageDef']
506502

507503
class Package(pydantic.BaseModel):
508504
"""
509505
Serialisable identifier for a defined packaging option
510506
"""
511-
package_type: PackageDef = pydantic.Field(discriminator="package_type")
507+
type: PackageDef = pydantic.Field(discriminator="package_type")
512508

513509

514-
def _linear_allocate_components(interfaces: dict, lockfile: LockFile , allocate, unallocated) -> PortMap:
510+
def _linear_allocate_components(interfaces: dict, lockfile: LockFile | None, allocate, unallocated) -> PortMap:
515511
port_map = PortMap()
516512
for component, iface in interfaces.items():
517513
for k, v in iface['interface']['members'].items():
@@ -534,7 +530,7 @@ def _linear_allocate_components(interfaces: dict, lockfile: LockFile , allocate,
534530
else:
535531
pins = allocate(unallocated, width)
536532
if len(pins) == 0:
537-
raise ChipFlowError("No pins were allocated by {package}")
533+
raise ChipFlowError("No pins were allocated")
538534
logger.debug(f"allocated range: {pins}")
539535
unallocated = unallocated - set(pins)
540536
_map, _ = _allocate_pins(k, v, pins)
@@ -558,9 +554,6 @@ class BasePackageDef(pydantic.BaseModel, abc.ABC):
558554
559555
"""
560556

561-
# Used by pydantic to differentate when deserialising,
562-
# override appropriately when you subclass
563-
package_type: Literal["BasePackageDef"] = "BasePackageDef"
564557
name: str
565558

566559
def model_post_init(self, __context):
@@ -579,7 +572,7 @@ def register_component(self, name: str, component: wiring.Component) -> None:
579572

580573

581574
@abc.abstractmethod
582-
def allocate_pins(self, lockfile: Optional[LockFile]) -> LockFile:
575+
def allocate_pins(self, process: 'Process', lockfile: Optional[LockFile]) -> LockFile:
583576
"""
584577
Allocate package pins to the registered component.
585578
Pins should be allocated in the most usable way for *users* of the packaged IC.
@@ -622,16 +615,16 @@ class BareDiePackageDef(BasePackageDef):
622615
height: int
623616

624617
def model_post_init(self, __context):
625-
pins = (
626-
set(itertools.product((_Side.N, _Side.S), range(self.width)))
627-
| set(itertools.product((_Side.W, _Side.E), range(self.height)))
628-
- set(self.bringup_pins.to_set())
629-
)
630-
self._ordered_pins = sorted(pins)
618+
pins = set(itertools.product((_Side.N, _Side.S), range(self.width)))
619+
pins |= set(itertools.product((_Side.W, _Side.E), range(self.height)))
620+
pins -= set(self.bringup_pins.to_set())
621+
622+
self._ordered_pins: List[Pin] = sorted(pins)
631623
return super().model_post_init(__context)
632624

633-
def allocate_pins(self, lockfile: LockFile|None) -> 'LockFile':
634-
return _linear_allocate_components(self._interfaces, lockfile, self._allocate, set(self._ordered_pins))
625+
def allocate_pins(self, process: 'Process', lockfile: LockFile|None) -> LockFile:
626+
portmap = _linear_allocate_components(self._interfaces, lockfile, self._allocate, set(self._ordered_pins))
627+
return LockFile(package=Package(type=self), process=process, metadata=self._interfaces, port_map=portmap)
635628

636629
@property
637630
def bringup_pins(self) -> BringupPins:
@@ -703,19 +696,20 @@ class QuadPackageDef(BasePackageDef):
703696
allocate_jtag: bool = True
704697

705698
def model_post_init(self, __context):
706-
pins =(
707-
set([i for i in range(1, self.width * 2 + self.height * 2)])
708-
- set(self._power)
709-
- self._jtag.to_set()
710-
)
711-
self._ordered_pins = sorted(pins)
699+
pins = set([i for i in range(1, self.width * 2 + self.height * 2)])
700+
pins.difference_update(*[x.to_set() for x in self._power])
701+
pins.difference_update(self._jtag.to_set())
702+
703+
self._ordered_pins: List[Pin] = sorted(pins)
712704
return super().model_post_init(__context)
713705

714-
def allocate_pins(self, lockfile: LockFile|None) -> 'LockFile':
715-
return _linear_allocate_components(self._interfaces, lockfile, self._allocate, set(self._ordered_pins))
706+
def allocate_pins(self, process: 'Process', lockfile: LockFile|None) -> 'LockFile':
707+
portmap = _linear_allocate_components(self._interfaces, lockfile, self._allocate, set(self._ordered_pins))
708+
return LockFile(package=Package(type=self), process=process, metadata=self._interfaces, port_map=portmap)
716709

717-
def _allocate(self, available: Set[int], width: int) -> List[int]:
718-
avail_n = sorted(available)
710+
711+
def _allocate(self, available: Set[int], width: int) -> List[Pin]:
712+
avail_n: List[Pin] = sorted(available)
719713
logger.debug(f"QuadPackageDef.allocate {width} from {len(avail_n)} remaining: {available}")
720714
ret = _find_contiguous_sequence(self._ordered_pins, avail_n, width)
721715
logger.debug(f"QuadPackageDef.returned {ret}")
@@ -743,19 +737,23 @@ def _power(self) -> List[PowerPins]:
743737
pins = []
744738
n = (self.width + self.height)//12
745739
# Left
746-
pins.append(self.height//2 + self.height//2 +1)
740+
p = self.height//2 + self.height//2
741+
pins.append(PowerPins(p, p +1))
747742
# Bottom
748743
start = self.height
749744
if n > 2:
750-
pins.append(start + self.width//2 + self.width//2 +1)
745+
p = start + self.width//2 + self.width//2
746+
pins.append(PowerPins(p, p+1))
751747
# Right
752748
start = start + self.width
753749
if n > 1:
754-
pins.append(start + self.height//2 + self.height//2 +1)
750+
p = start + self.height//2 + self.height//2
751+
pins.append(PowerPins(p, p+1))
755752
# Top
756753
start = start + self.height
757754
if n > 3:
758-
pins.append(start + self.width//2 + self.width//2 +1)
755+
p = start + self.width//2 + self.width//2
756+
pins.append(PowerPins(p, p+1))
759757
return pins
760758

761759

@@ -861,11 +859,11 @@ def int_to_alpha(i: int):
861859
out = valid_letters[char-1] + out
862860
return out
863861

864-
def pins_for_range(h1: int, h2: int, w1: int, w2: int) -> Set[GAPin]:
862+
def pins_for_range(h1: int, h2: int, w1: int, w2: int) -> Set[Pin]:
865863
pins = [GAPin(int_to_alpha(h),w) for h in range(h1, h2) for w in range(w1, w2)]
866864
return set(pins)
867865

868-
def sort_by_quadrant(pins: Set[GAPin]) -> List[GAPin]:
866+
def sort_by_quadrant(pins: Set[GAPin]) -> List[Pin]:
869867
quadrants:List[Set[GAPin]] = [set(), set(), set(), set()]
870868
midline_h = int_to_alpha(self.height // 2)
871869
midline_w = self.width // 2
@@ -883,6 +881,7 @@ def sort_by_quadrant(pins: Set[GAPin]) -> List[GAPin]:
883881
ret.append(sorted(quadrants[q]))
884882
return ret
885883

884+
self._ordered_pins: List[Pin] = []
886885
match self.layout_type:
887886
case GALayout.FULL:
888887
pins = pins_for_range(1, self.height, 1, self.width)
@@ -917,8 +916,9 @@ def sort_by_quadrant(pins: Set[GAPin]) -> List[GAPin]:
917916
return super().model_post_init(__context)
918917

919918

920-
def allocate_pins(self, lockfile: LockFile|None) -> 'LockFile':
921-
return _linear_allocate_components(self._interfaces, lockfile, self._allocate, set(self._ordered_pins))
919+
def allocate_pins(self, process: 'Process', lockfile: LockFile|None) -> 'LockFile':
920+
portmap = _linear_allocate_components(self._interfaces, lockfile, self._allocate, set(self._ordered_pins))
921+
return LockFile(package=Package(type=self), process=process, metadata=self._interfaces, port_map=portmap)
922922

923923
def _allocate(self, available: Set[str], width: int) -> List[str]:
924924
avail_n = sorted(available)

docs/package_pins.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ tms_pin = jtag_pins[JTAGWireName.TMS] # Get the TMS pin
4242
### Creating a Package with Default Pins
4343

4444
```python
45-
from chipflow_lib.platforms.utils import Package, PACKAGE_DEFINITIONS
45+
from chipflow_lib.platforms.utils import PACKAGE_DEFINITIONS
4646

4747
# Create a package with a specific package definition
4848
package = Package(package_type=PACKAGE_DEFINITIONS["pga144"])

tests/test_package_pins.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,26 +78,23 @@ def test_bringup_pins(self):
7878
class TestPackage(unittest.TestCase):
7979
def setUp(self):
8080
self.package_def = BareDiePackageDef(name="test_package", width=8, height=4)
81-
self.package = Package(package_type=self.package_def)
81+
self.package = Package(type=self.package_def)
8282

8383
def test_package_initialization(self):
8484
"""Test basic package initialization"""
85-
self.assertIsNotNone(self.package.package_type)
86-
self.assertEqual(self.package.package_type.name, "test_package")
87-
self.assertEqual(self.package.package_type.width, 8)
88-
self.assertEqual(self.package.package_type.height, 4)
85+
self.assertIsNotNone(self.package.type)
86+
self.assertEqual(self.package.type.name, "test_package")
87+
self.assertEqual(self.package.type.width, 8)
88+
self.assertEqual(self.package.type.height, 4)
8989

9090
def test_package_type_access(self):
9191
"""Test accessing package type properties through Package"""
9292
# Should be able to access package type bringup pins
93-
bringup_pins = self.package.package_type.bringup_pins
93+
bringup_pins = self.package.type.bringup_pins
9494
self.assertIsNotNone(bringup_pins)
9595

9696
# Test package discriminator
97-
self.assertEqual(self.package.package_type.package_type, "BareDiePackageDef")
98-
99-
# Basic test of Package structure
100-
self.assertIsInstance(self.package.package_type, BareDiePackageDef)
97+
self.assertEqual(self.package.type.package_type, "BareDiePackageDef")
10198

10299

103100
class TestGAPackage(unittest.TestCase):

tests/test_steps_silicon.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,10 @@
2525
DEFAULT_PINLOCK = {
2626
"process" : "ihp_sg13g2",
2727
"package" : {
28-
"package_type": {
2928
"package_type": "QuadPackageDef",
3029
"name": "pga144",
3130
"width": 36,
3231
"height": 36
33-
},
3432
},
3533
"port_map" : {},
3634
"metadata" : {},

0 commit comments

Comments
 (0)