Skip to content

Commit 31ceb99

Browse files
robtaylorclaude
andcommitted
Deduplicate allocate_pins implementation in package definitions
Move common allocate_pins() implementation from LinearAllocPackageDef and GAPackageDef to BasePackageDef to eliminate code duplication. Changes: - BasePackageDef.allocate_pins(): Now concrete method with common logic - BasePackageDef._allocate(): New abstract method for allocation strategy - LinearAllocPackageDef: Removed duplicate allocate_pins(), kept _allocate() - GAPackageDef: Removed duplicate allocate_pins(), kept _allocate() - Both subclasses now only implement their specific allocation strategies The method bodies were identical except for docstrings. Both used _linear_allocate_components with self._allocate callback and the same pattern for bringup pins and lockfile creation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent a1159e7 commit 31ceb99

File tree

3 files changed

+35
-38
lines changed

3 files changed

+35
-38
lines changed
16 KB
Binary file not shown.

chipflow_lib/packaging/base.py

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def model_post_init(self, __context):
4545
"""Initialize internal tracking structures"""
4646
self._interfaces: Dict[str, dict] = {}
4747
self._components: Dict[str, wiring.Component] = {}
48+
self._ordered_pins = None # Subclasses should set this
4849
return super().model_post_init(__context)
4950

5051
def register_component(self, name: str, component: wiring.Component) -> None:
@@ -130,14 +131,17 @@ def _allocate_bringup(self, config: 'Config') -> Component:
130131

131132
return {'bringup_pins': d}
132133

133-
@abc.abstractmethod
134134
def allocate_pins(self, config: 'Config', process: 'Process', lockfile: LockFile | None) -> LockFile:
135135
"""
136136
Allocate package pins to the registered components.
137137
138138
Pins should be allocated in the most usable way for users
139139
of the packaged IC.
140140
141+
This default implementation uses _linear_allocate_components with
142+
self._allocate for the allocation strategy. Subclasses can override
143+
if they need completely different allocation logic.
144+
141145
Args:
142146
config: ChipFlow configuration
143147
process: Semiconductor process
@@ -149,6 +153,35 @@ def allocate_pins(self, config: 'Config', process: 'Process', lockfile: LockFile
149153
Raises:
150154
UnableToAllocate: If the ports cannot be allocated
151155
"""
156+
assert self._ordered_pins is not None, "Subclass must set self._ordered_pins in model_post_init"
157+
portmap = _linear_allocate_components(
158+
self._interfaces,
159+
lockfile,
160+
self._allocate,
161+
set(self._ordered_pins)
162+
)
163+
bringup_pins = self._allocate_bringup(config)
164+
portmap.ports['_core'] = bringup_pins
165+
package = self._get_package()
166+
return LockFile(package=package, process=process, metadata=self._interfaces, port_map=portmap)
167+
168+
@abc.abstractmethod
169+
def _allocate(self, available, width: int):
170+
"""
171+
Allocate pins from available set.
172+
173+
Subclasses must implement this to define their allocation strategy.
174+
175+
Args:
176+
available: Set of available pins (type depends on package)
177+
width: Number of pins needed
178+
179+
Returns:
180+
List of allocated pins
181+
182+
Raises:
183+
UnableToAllocate: If allocation fails
184+
"""
152185
...
153186

154187
@property
@@ -186,24 +219,6 @@ class LinearAllocPackageDef(BasePackageDef):
186219
Not directly serializable - use concrete subclasses.
187220
"""
188221

189-
def __init__(self, **kwargs):
190-
self._ordered_pins = None
191-
super().__init__(**kwargs)
192-
193-
def allocate_pins(self, config: 'Config', process: 'Process', lockfile: LockFile | None) -> LockFile:
194-
"""Allocate pins linearly from the ordered pin list"""
195-
assert self._ordered_pins
196-
portmap = _linear_allocate_components(
197-
self._interfaces,
198-
lockfile,
199-
self._allocate,
200-
set(self._ordered_pins)
201-
)
202-
bringup_pins = self._allocate_bringup(config)
203-
portmap.ports['_core'] = bringup_pins
204-
package = self._get_package()
205-
return LockFile(package=package, process=process, metadata=self._interfaces, port_map=portmap)
206-
207222
def _allocate(self, available: Set[int], width: int) -> List[int]:
208223
"""
209224
Allocate pins from available set.

chipflow_lib/packaging/grid_array.py

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,10 @@
99
import logging
1010
from enum import StrEnum, auto
1111
from math import ceil, floor
12-
from typing import Dict, List, Literal, NamedTuple, Optional, Set, Tuple, TYPE_CHECKING
12+
from typing import Dict, List, Literal, NamedTuple, Optional, Set, Tuple
1313

1414
from .base import BasePackageDef
1515
from .pins import PowerPins, JTAGPins, BringupPins
16-
from .lockfile import LockFile
17-
from .allocation import _linear_allocate_components
18-
19-
if TYPE_CHECKING:
20-
from ..config_models import Config, Process
2116

2217
logger = logging.getLogger(__name__)
2318

@@ -187,19 +182,6 @@ def sort_by_quadrant(pins: Set[GAPin]) -> List[GAPin]:
187182

188183
return super().model_post_init(__context)
189184

190-
def allocate_pins(self, config: 'Config', process: 'Process', lockfile: LockFile | None) -> LockFile:
191-
"""Allocate pins from the grid array"""
192-
portmap = _linear_allocate_components(
193-
self._interfaces,
194-
lockfile,
195-
self._allocate,
196-
set(self._ordered_pins)
197-
)
198-
bringup_pins = self._allocate_bringup(config)
199-
portmap.ports['_core'] = bringup_pins
200-
package = self._get_package()
201-
return LockFile(package=package, process=process, metadata=self._interfaces, port_map=portmap)
202-
203185
def _allocate(self, available: Set[GAPin], width: int) -> List[GAPin]:
204186
"""Allocate pins from available grid array pins"""
205187
from .allocation import _find_contiguous_sequence

0 commit comments

Comments
 (0)