Skip to content

Commit 1a2dbc9

Browse files
committed
Assign io power pins
1 parent e79a06d commit 1a2dbc9

File tree

3 files changed

+99
-67
lines changed

3 files changed

+99
-67
lines changed

chipflow_lib/platforms/_packages.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
from ._utils import QuadPackageDef, BareDiePackageDef, Package
1+
from ._utils import QuadPackageDef, BareDiePackageDef, GAPackageDef, Package
22
from ._openframe import OpenframePackageDef
33

44
# Add any new package types to both PACKAGE_DEFINITIONS and the PackageDef union
55
PACKAGE_DEFINITIONS = {
66
"pga144": QuadPackageDef(name="pga144", width=36, height=36),
77
"cf20": BareDiePackageDef(name="cf20", width=7, height=3),
8+
"bga144": GAPackageDef(name="bga144", width=36, height=36),
89
"openframe": OpenframePackageDef()
910
}
1011

chipflow_lib/platforms/_utils.py

Lines changed: 96 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
from enum import Enum, IntEnum, StrEnum, auto
1414
from math import ceil, floor
1515
from typing import (
16-
Any, Annotated, NamedTuple, Self,
17-
TYPE_CHECKING
16+
Any, Annotated, NamedTuple, Self, TYPE_CHECKING
1817
)
1918
from typing_extensions import (
2019
TypedDict, Unpack, NotRequired
@@ -267,8 +266,7 @@ def BidirIOSignature(width: int, **kwargs: Unpack[IOModelOptions]):
267266
model: IOModel = kwargs | {'width': width, 'direction': io.Direction.Bidir} # type: ignore[reportGeneralTypeIssues]
268267
return IOSignature(**model)
269268

270-
271-
Pin = Union[Tuple[Any,...], str, int]
269+
Pin = Any
272270
PinSet = Set[Pin]
273271
PinList = List[Pin]
274272
Pins = Union[PinSet, PinList]
@@ -403,7 +401,6 @@ def _group_consecutive_items(ordering: PinList, lst: PinList) -> OrderedDict[int
403401
d.setdefault(len(g), []).append(g)
404402
return d
405403

406-
407404
def _find_contiguous_sequence(ordering: PinList, lst: PinList, total: int) -> PinList:
408405
"""Find the next sequence of n consecutive numbers in a sorted list
409406
@@ -664,8 +661,8 @@ def _allocate_bringup(self, config: 'Config') -> Component:
664661
vss = "vss"
665662
vdd = "vdd"
666663
if pp.name:
667-
vss = f"vss{pp.name}"
668-
vdd = f"vdd{pp.name}"
664+
vss = f"{pp.name}vss"
665+
vdd = f"{pp.name}vdd"
669666
powerpins[vss].append(pp.power)
670667
powerpins[vdd].append(pp.ground)
671668

@@ -769,12 +766,14 @@ def model_post_init(self, __context):
769766

770767
@property
771768
def bringup_pins(self) -> BringupPins:
772-
core_power = PowerPins(
773-
(_Side.N, 1),
774-
(_Side.N, 2)
775-
)
769+
#TODO, this makes no sense for anything that isn't tiny..
770+
core_power = [
771+
PowerPins((_Side.N, 1), (_Side.N, 2)),
772+
PowerPins((_Side.W, 1), (_Side.W, 2), name='d')
773+
]
774+
776775
return BringupPins(
777-
core_power=[core_power],
776+
core_power=core_power,
778777
core_clock=(_Side.N, 3),
779778
core_reset=(_Side.N, 3),
780779
core_heartbeat=(_Side.E, 1),
@@ -849,27 +848,34 @@ def _power(self) -> List[PowerPins]:
849848
Power pins are always a matched pair in the middle of a side, with the number
850849
varying with the size of the package.
851850
We don't move power pins from these locations to allow for easier bring up test.
851+
returns two lists, core power pins and io power pins
852852
"""
853-
pins = []
853+
pins: List[PowerPins] = []
854+
# heuristic for sensible number of power pins for a given size
854855
n = (self.width + self.height)//12
855856
# Left
856857
p = self.height//2 + self.height//2
857-
pins.append(PowerPins(p, p +1))
858+
assert p > 3
859+
pins.append(PowerPins(p-2, p-1))
860+
pins.append(PowerPins(p, p+1, name='d'))
858861
# Bottom
859862
start = self.height
860863
if n > 2:
861-
p = start + self.width//2 + self.width//2
862-
pins.append(PowerPins(p, p+1))
864+
p = start + self.width//2
865+
pins.append(PowerPins(p-2, p-1))
866+
pins.append(PowerPins(p, p+1, name='d'))
863867
# Right
864868
start = start + self.width
865869
if n > 1:
866-
p = start + self.height//2 + self.height//2
867-
pins.append(PowerPins(p, p+1))
870+
p = start + self.height//2
871+
pins.append(PowerPins(p-2, p-1))
872+
pins.append(PowerPins(p, p+1, name='d'))
868873
# Top
869874
start = start + self.height
870875
if n > 3:
871-
p = start + self.width//2 + self.width//2
872-
pins.append(PowerPins(p, p+1))
876+
p = start + self.width//2
877+
pins.append(PowerPins(p-2, p-1))
878+
pins.append(PowerPins(p, p+1, name='d'))
873879
return pins
874880

875881

@@ -961,75 +967,77 @@ class GAPackageDef(BasePackageDef):
961967
width:int
962968
height: int
963969
layout_type: GALayout= GALayout.FULL
964-
channel_width: Optional[int]
965-
island_width: Optional[int]
966-
missing_pins: Optional[Set[GAPin]]
967-
additional_pins: Optional[Set[GAPin]]
968-
969-
def model_post_init(self, __context):
970-
def int_to_alpha(i: int):
971-
"Covert int to alpha representation, starting at 1"
972-
valid_letters = "ABCDEFGHJKLMPRSTUVWXY"
973-
out = ''
974-
while i > 0:
975-
char = i % len(valid_letters)
976-
i = i // len(valid_letters)
977-
out = valid_letters[char-1] + out
978-
return out
979-
970+
channel_width: Optional[int] = None
971+
island_width: Optional[int] = None
972+
missing_pins: Optional[Set[GAPin]] = None
973+
additional_pins: Optional[Set[GAPin]] = None
974+
975+
@staticmethod
976+
def _int_to_alpha(i: int):
977+
"Covert int to alpha representation, starting at 1"
978+
valid_letters = "ABCDEFGHJKLMPRSTUVWXY"
979+
out = ''
980+
while i > 0:
981+
char = i % len(valid_letters)
982+
i = i // len(valid_letters)
983+
out = valid_letters[char-1] + out
984+
return out
985+
986+
def _get_all_pins(self) -> Tuple[Set[GAPin], Set[GAPin] | None]:
980987
def pins_for_range(h1: int, h2: int, w1: int, w2: int) -> Set[GAPin]:
981-
pins = [GAPin(int_to_alpha(h),w) for h in range(h1, h2) for w in range(w1, w2)]
988+
pins = [GAPin(self._int_to_alpha(h),w) for h in range(h1, h2) for w in range(w1, w2)]
982989
return set(pins)
983990

984-
def sort_by_quadrant(pins: Set[GAPin]) -> List[Pin]:
985-
quadrants:List[Set[GAPin]] = [set(), set(), set(), set()]
986-
midline_h = int_to_alpha(self.height // 2)
987-
midline_w = self.width // 2
988-
for pin in pins:
989-
if pin.h < midline_h and pin.w < midline_w:
990-
quadrants[0].add(pin)
991-
if pin.h >= midline_h and pin.w < midline_w:
992-
quadrants[1].add(pin)
993-
if pin.h < midline_h and pin.w >= midline_w:
994-
quadrants[2].add(pin)
995-
if pin.h >= midline_h and pin.w >= midline_w:
996-
quadrants[3].add(pin)
997-
ret = []
998-
for q in range(0,3):
999-
ret.append(sorted(quadrants[q]))
1000-
return ret
1001991

1002-
self._ordered_pins: List[Pin] = []
1003992
match self.layout_type:
1004993
case GALayout.FULL:
1005994
pins = pins_for_range(1, self.height, 1, self.width)
1006-
pins -= self.bringup_pins.to_set()
1007-
self._ordered_pins = sort_by_quadrant(pins)
995+
return (pins, None)
1008996

1009997
case GALayout.PERIMETER:
1010998
assert self.channel_width is not None
1011999
pins = pins_for_range(1, self.height, 1, self.width) - \
10121000
pins_for_range(1 + self.channel_width, self.height-self.channel_width, 1 + self.channel_width, self.width - self.channel_width)
1013-
pins -= self.bringup_pins.to_set()
1014-
self._ordered_pins = sort_by_quadrant(pins)
1001+
return (pins, None)
10151002

10161003
case GALayout.ISLAND:
10171004
assert self.channel_width is not None
10181005
assert self.island_width is not None
10191006
outer_pins = pins_for_range(1, self.height, 1, self.width) - \
10201007
pins_for_range(1 + self.channel_width, self.height-self.channel_width, 1 + self.channel_width, self.width - self.channel_width)
1021-
outer_pins -= self.bringup_pins.to_set()
10221008
inner_pins = pins_for_range(ceil(self.height/ 2 - self.island_width /2), floor(self.height/2 + self.island_width /2),
10231009
ceil(self.width / 2 - self.island_width /2), floor(self.width /2 + self.island_width /2))
1024-
# TODO, allocate island as power
1025-
self._ordered_pins = sort_by_quadrant(outer_pins) + sorted(inner_pins)
1010+
return (outer_pins, inner_pins)
10261011

10271012
case GALayout.CHANNEL:
10281013
assert self.channel_width is not None
10291014
pins = pins_for_range(1, self.channel_width + 1, 1, self.width) | \
10301015
pins_for_range(self.height - self.channel_width, self.height, 1, self.width)
1031-
pins -= self.bringup_pins.to_set()
1032-
self._ordered_pins = sort_by_quadrant(pins)
1016+
return (pins, None)
1017+
1018+
def model_post_init(self, __context):
1019+
def sort_by_quadrant(pins: Set[GAPin]) -> List[GAPin]:
1020+
quadrants:List[Set[GAPin]] = [set(), set(), set(), set()]
1021+
midline_h = self._int_to_alpha(self.height // 2)
1022+
midline_w = self.width // 2
1023+
for pin in pins:
1024+
if pin.h < midline_h and pin.w < midline_w:
1025+
quadrants[0].add(pin)
1026+
if pin.h >= midline_h and pin.w < midline_w:
1027+
quadrants[1].add(pin)
1028+
if pin.h < midline_h and pin.w >= midline_w:
1029+
quadrants[2].add(pin)
1030+
if pin.h >= midline_h and pin.w >= midline_w:
1031+
quadrants[3].add(pin)
1032+
ret = []
1033+
for q in range(0,3):
1034+
ret.extend(sorted(quadrants[q]))
1035+
return ret
1036+
1037+
self._ordered_pins: List[GAPin] = []
1038+
pins, _ = self._get_all_pins()
1039+
pins -= self.bringup_pins.to_set()
1040+
self._ordered_pins = sort_by_quadrant(pins)
10331041

10341042
return super().model_post_init(__context)
10351043

@@ -1061,8 +1069,31 @@ def bringup_pins(self) -> BringupPins:
10611069

10621070
@property
10631071
def _power(self) -> List[PowerPins]:
1064-
return [PowerPins(1,2)]
1072+
#TODO build an internal padring mapping
1073+
# for now, just distribute evenly
1074+
power_pins = []
10651075

1076+
pins, inner = self._get_all_pins()
1077+
#allocate all of inner to core pins, alternating
1078+
try:
1079+
if inner:
1080+
it = iter(sorted(inner))
1081+
for p in it:
1082+
power_pins.append(PowerPins(p, next(it)))
1083+
except StopIteration:
1084+
pass
1085+
# distribute the rest evenly
1086+
try:
1087+
it = iter(sorted(pins))
1088+
for p in it:
1089+
for name in ('','d'):
1090+
power_pins.append(PowerPins(p, next(it)))
1091+
for i in range(0,15):
1092+
next(it)
1093+
except StopIteration:
1094+
pass
1095+
1096+
return power_pins
10661097

10671098
@property
10681099
def _jtag(self) -> JTAGPins:

chipflow_lib/platforms/silicon.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from amaranth import Module, Signal, ClockDomain, ClockSignal, ResetSignal, unsigned
1515
from amaranth.lib import wiring, io, data
1616
from amaranth.lib.cdc import FFSynchronizer
17-
from amaranth.lib.wiring import Component, In, PureInterface
17+
from amaranth.lib.wiring import Component, In
1818
from amaranth.back import rtlil #type: ignore[reportAttributeAccessIssue]
1919
from amaranth.hdl import Fragment
2020
from amaranth.hdl._ir import PortDirection

0 commit comments

Comments
 (0)