Skip to content

Commit f4740de

Browse files
committed
Fix: actually wire up ports. NB this also changes the port_map layout
1 parent 04fc508 commit f4740de

File tree

4 files changed

+56
-20
lines changed

4 files changed

+56
-20
lines changed

chipflow_lib/pin_lock.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,40 +32,42 @@ def count_member_pins(name: str, member: Dict[str, Any]) -> int:
3232
return member['width']
3333

3434

35-
def allocate_pins(name: str, member: Dict[str, Any], pins: List[str]) -> Tuple[Dict[str, Port], List[str]]:
35+
def allocate_pins(name: str, member: Dict[str, Any], pins: List[str], port_name: str = None) -> Tuple[Dict[str, Port], List[str]]:
3636
"Allocate pins based of Amaranth member metadata"
3737

3838
pin_map = {}
39+
3940
logger.debug(f"allocate_pins: name={name}, pins={pins}")
4041
logger.debug(f"member={pformat(member)}")
4142

4243
if member['type'] == 'interface' and 'annotations' in member \
4344
and PIN_ANNOTATION_SCHEMA in member['annotations']:
4445
logger.debug("matched PinSignature {sig}")
45-
name = name
4646
sig = member['annotations'][PIN_ANNOTATION_SCHEMA]
4747
width = sig['width']
4848
options = sig['options']
4949
pin_map[name] = {'pins': pins[0:width],
50-
'direction': sig['direction'],
51-
'type': 'io',
52-
'options': options}
50+
'direction': sig['direction'],
51+
'type': 'io',
52+
'port_name': port_name,
53+
'options': options}
5354
logger.debug(f"added '{name}':{pin_map[name]} to pin_map")
5455
return pin_map, pins[width:]
5556
elif member['type'] == 'interface':
5657
for k, v in member['members'].items():
57-
n = '_'.join([name, k])
58-
_map, pins = allocate_pins(n, v, pins)
58+
port_name = '_'.join([name, k])
59+
_map, pins = allocate_pins(k, v, pins, port_name=port_name)
5960
pin_map |= _map
6061
logger.debug(f"{pin_map},{_map}")
6162
return pin_map, pins
6263
elif member['type'] == 'port':
6364
logger.warning(f"Port '{name}' has no PinSignature, pin allocation likely to be wrong")
64-
name = name
6565
width = member['width']
6666
pin_map[name] = {'pins': pins[0:width],
67-
'direction': member['dir'],
68-
'type': 'io'}
67+
'direction': member['dir'],
68+
'type': 'io',
69+
'port_name': port_name
70+
}
6971
logger.debug(f"added '{name}':{pin_map[name]} to pin_map")
7072
return pin_map, pins[width:]
7173
else:

chipflow_lib/platforms/silicon.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from amaranth.lib import wiring, io
1111
from amaranth.lib.cdc import FFSynchronizer
12-
from amaranth.lib.wiring import Component, In
12+
from amaranth.lib.wiring import Component, In, PureInterface, flipped, connect
1313

1414
from amaranth.back import rtlil
1515
from amaranth.hdl import Fragment
@@ -72,21 +72,29 @@ def __init__(self,
7272
self._invert = invert
7373
self._options = port.options
7474

75-
self._i = self._o = self._oe = Signal(1)
7675
if self._direction in (io.Direction.Input, io.Direction.Bidir):
7776
self._i = Signal(port.width, name=f"{component}_{name}__i")
7877
if self._direction in (io.Direction.Output, io.Direction.Bidir):
7978
self._o = Signal(port.width, name=f"{component}_{name}__o")
8079
if self._direction is io.Direction.Bidir:
8180
if "all_have_oe" in self._options and self._options["all_have_oe"]:
82-
self._oe = Signal(port.width, name=f"{component}_{name}__oe")
81+
self._oe = Signal(port.width, name=f"{component}_{name}__oe", init=-1)
8382
else:
84-
self._oe = Signal(1, name=f"{component}_{name}__oe")
83+
self._oe = Signal(1, name=f"{component}_{name}__oe", init=-1)
8584

8685
self._pins = port.pins
8786
logger.debug(f"Created SiliconPlatformPort {name}, width={len(port.pins)},dir{self._direction}")
8887

88+
def wire(self, m: Module, interface: PureInterface):
89+
assert self._direction == interface.signature.direction
90+
if hasattr(interface, 'i'):
91+
m.d.comb += interface.i.eq(self.i)
92+
for d in ['o', 'oe']:
93+
if hasattr(interface, d):
94+
m.d.comb += getattr(self, d).eq(getattr(interface, d))
95+
8996
@property
97+
9098
def i(self):
9199
if self._i is None:
92100
raise AttributeError("SiliconPlatformPort with output direction does not have an "
@@ -229,6 +237,10 @@ def __init__(self, config):
229237
self._ports = {}
230238
self._files = {}
231239

240+
@property
241+
def ports(self):
242+
return self._ports
243+
232244
def instantiate_ports(self, m: Module):
233245
if hasattr(self, "pinlock"):
234246
return
@@ -237,7 +249,7 @@ def instantiate_ports(self, m: Module):
237249
for component, iface in pinlock.port_map.items():
238250
for k, v in iface.items():
239251
for name, port in v.items():
240-
self._ports[name] = SiliconPlatformPort(component, name, port)
252+
self._ports[port.port_name] = SiliconPlatformPort(component, name, port)
241253

242254
for clock, name in self._config["chipflow"]["clocks"].items():
243255
if name not in pinlock.package.clocks:
@@ -246,6 +258,7 @@ def instantiate_ports(self, m: Module):
246258
port_data = pinlock.package.clocks[name]
247259
port = SiliconPlatformPort(component, name, port_data, invert=True)
248260
self._ports[name] = port
261+
249262
if clock == 'default':
250263
clock = 'sync'
251264
setattr(m.domains, clock, ClockDomain(name=clock))
@@ -311,13 +324,14 @@ def _prepare(self, elaboratable, name="top"):
311324
# Check that only a single clock domain is used.
312325
self._check_clock_domains(fragment)
313326

314-
# Prepare toplevel ports according to chipflow.toml.
327+
# Prepare toplevel ports according to pinlock
315328
ports = []
316329
for port_name, port in self._ports.items():
317330
if port.direction in (io.Direction.Input, io.Direction.Bidir):
318331
ports.append((f"io${port_name}$i", port.i, PortDirection.Input))
319332
if port.direction in (io.Direction.Output, io.Direction.Bidir):
320333
ports.append((f"io${port_name}$o", port.o, PortDirection.Output))
334+
if port.direction is io.Direction.Bidir:
321335
ports.append((f"io${port_name}$oe", port.oe, PortDirection.Output))
322336

323337
# Prepare design for RTLIL conversion.

chipflow_lib/platforms/utils.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@ def __init__(self, direction: io.Direction, width: int = 1, all_have_oe: bool =
9898

9999
super().__init__(sig)
100100

101+
@property
102+
def direction(self):
103+
return self._direction
104+
105+
def width(self):
106+
return self._width
107+
108+
def options(self):
109+
return self._options
110+
101111
def annotations(self, *args):
102112
annotations = wiring.Signature.annotations(self, *args)
103113
pin_annotation = _PinAnnotation(direction=self._direction, width=self._width, options=self._options)
@@ -307,6 +317,7 @@ def sortpins(self, pins: Union[List[str], Set[str]]) -> List[str]:
307317
class Port(pydantic.BaseModel):
308318
type: str
309319
pins: List[str]
320+
port_name: str
310321
direction: Optional[str] = None
311322
options: Optional[dict] = None
312323

@@ -337,13 +348,13 @@ def check_pad(self, name: str, defn: dict):
337348
def add_pad(self, name: str, defn: dict):
338349
match defn:
339350
case {"type": "clock", "loc": loc}:
340-
self.clocks[name] = Port(type="clock", pins=[loc], direction=io.Direction.Input)
351+
self.clocks[name] = Port(type="clock", pins=[loc], direction=io.Direction.Input, port_name=name)
341352
case {"type": "reset", "loc": loc}:
342-
self.resets[name] = Port(type="reset", pins=[loc], direction=io.Direction.Input)
353+
self.resets[name] = Port(type="reset", pins=[loc], direction=io.Direction.Input, port_name=name)
343354
case {"type": "power", "loc": loc}:
344-
self.power[name] = Port(type="power", pins=[loc])
355+
self.power[name] = Port(type="power", pins=[loc], port_name=name)
345356
case {"type": "ground", "loc": loc}:
346-
self.power[name] = Port(type="ground", pins=[loc])
357+
self.power[name] = Port(type="ground", pins=[loc], port_name=name)
347358
case _:
348359
pass
349360

chipflow_lib/steps/silicon.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
import time
1313

1414
import dotenv
15+
from pprint import pprint
1516
from amaranth import *
17+
from amaranth.lib.wiring import connect, flipped
1618

1719
from .. import ChipFlowError
1820
from ..platforms import SiliconPlatform, top_interfaces
@@ -43,6 +45,13 @@ def elaborate(self, platform: SiliconPlatform):
4345
for n, t in top.items():
4446
setattr(m.submodules, n, t)
4547

48+
for component, iface in platform.pinlock.port_map.items():
49+
for iface_name, member, in iface.items():
50+
for name, port in member.items():
51+
platform.ports[port.port_name].wire(
52+
m,
53+
getattr(getattr(top[component], iface_name), name)
54+
)
4655
return m
4756

4857

0 commit comments

Comments
 (0)