Skip to content

Commit d2f965e

Browse files
committed
Allow input enable for all processes
1 parent 73cc138 commit d2f965e

File tree

2 files changed

+79
-56
lines changed

2 files changed

+79
-56
lines changed

chipflow_lib/platforms/silicon.py

Lines changed: 78 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# amaranth: UnusedElaboratable=no
22

33
# SPDX-License-Identifier: BSD-2-Clause
4+
import copy
45
import logging
56
import os
67
import re
@@ -71,46 +72,50 @@ def elaborate(self, platform):
7172
class SiliconPlatformPort(io.PortLike):
7273
def __init__(self,
7374
name: str,
74-
port_desc: PortDesc,
75-
*,
76-
invert: bool = False):
75+
port_desc: PortDesc):
7776
self._port_desc = port_desc
78-
self._invert = invert
77+
if 'invert' in port_desc.iomodel:
78+
if isinstance(port_desc.iomodel['invert'], bool):
79+
self._invert = [port_desc.iomodel['invert']]*port_desc.iomodel['width']
80+
else:
81+
self._invert = port_desc.iomodel['invert']
82+
else:
83+
self._invert = [False]*port_desc.iomodel['width']
84+
7985
self._name = name
8086

8187
# Initialize signal attributes to None
8288
self._i = None
8389
self._o = None
8490
self._oe = None
91+
self._ie = None
8592

8693
# Create signals based on direction
8794
if self.direction in (io.Direction.Input, io.Direction.Bidir):
88-
self._i = Signal(self._port_desc.width, name=f"{self._name}__i")
95+
self._i = Signal(self._port_desc.width, name=f"{self._name}$i")
96+
self._ie = Signal(self._port_desc.width, name=f"{self._name}$inp_dis")
8997
if self.direction in (io.Direction.Output, io.Direction.Bidir):
90-
self._o = Signal(self._port_desc.width, name=f"{self._name}__o")
91-
if self.direction is io.Direction.Bidir:
92-
# the signals that get wired out to iocells. Always one per io.
98+
self._o = Signal(self._port_desc.width, name=f"{self._name}$o")
99+
100+
# the oe signals that get wired out to iocells. Always one per io.
93101
init_oe = -1
94102
if 'init_oe' in port_desc.iomodel and port_desc.iomodel['init_oe']:
95103
init_oe = port_desc.iomodel['init_oe']
96-
self._oes = Signal(self._port_desc.width, name=f"{self._name}__oe", init=init_oe)
104+
self._oes = Signal(self._port_desc.width, name=f"{self._name}$oe", init=init_oe)
105+
97106
# the oe on the user side.
98107
if "individual_oe" not in self.iomodel or not self.iomodel["individual_oe"]:
99-
self._oe = Signal(1, name=f"{self._name}__oe", init=-1)
108+
self._oe = Signal(1, name=f"{self._name}$oe", init=-1)
100109
else:
101110
self._oe = self._oes
102111

103-
elif self.direction is io.Direction.Output:
104-
# Always create an _oe for output ports
105-
self._oe = Signal(1, name=f"{self._name}__oe", init=-1)
106-
107-
logger.debug(f"Created SiliconPlatformPort {self._name}, invert={invert} with port description:\n{pformat(self._port_desc)}")
112+
logger.debug(f"Created SiliconPlatformPort {self._name}, with port description:\n{pformat(self._port_desc)}")
108113

109114
def wire(self, m: Module, interface: PureInterface):
110115
assert self.direction == interface.signature.direction #type: ignore
111116
if hasattr(interface, '_i'):
112117
m.d.comb += interface.i.eq(self.i) # type: ignore
113-
for d in ['_o', '_oe']:
118+
for d in ['_o', '_oe', '_ie']:
114119
if hasattr(interface, d):
115120
m.d.comb += getattr(self, d).eq(getattr(interface, d))
116121
if self._oe is not None \
@@ -122,12 +127,27 @@ def instantiate_toplevel(self):
122127
ports = []
123128
if self.direction in (io.Direction.Input, io.Direction.Bidir):
124129
ports.append((f"io${self._name}$i", self.i, PortDirection.Input))
130+
ports.append((f"io${self._name}$ie", self.ie, PortDirection.Output))
125131
if self.direction in (io.Direction.Output, io.Direction.Bidir):
126132
ports.append((f"io${self._name}$o", self.o, PortDirection.Output))
127-
if self.direction is io.Direction.Bidir:
128133
ports.append((f"io${self._name}$oe", self.oe, PortDirection.Output))
129134
return ports
130135

136+
def wire_up(self, m, wire):
137+
inv_mask = sum(inv << bit for bit, inv in enumerate(self.invert))
138+
if hasattr(wire, 'i'):
139+
m.d.comb += wire.i.eq(self.i ^ inv_mask)
140+
if hasattr(wire, 'o'):
141+
m.d.comb += self.o.eq(wire.o ^ inv_mask)
142+
if hasattr(wire, 'oe'):
143+
m.d.comb += self.oe.eq(wire.oe)
144+
145+
if hasattr(wire, 'ie'):
146+
m.d.comb += self.ie.eq(wire.ie)
147+
elif hasattr(wire, 'oe'):
148+
m.d.comb += self.ie.eq(wire.oe)
149+
150+
131151
@property
132152
def name(self) -> str:
133153
return self._name
@@ -162,6 +182,13 @@ def oe(self):
162182
"output enable signal")
163183
return self._oe
164184

185+
@property
186+
def ie(self):
187+
if self._ie is None:
188+
raise AttributeError("SiliconPlatformPort with input direction does not have an "
189+
"input enable signal")
190+
return self._ie
191+
165192
@property
166193
def direction(self):
167194
return self._port_desc.iomodel['direction']
@@ -189,14 +216,16 @@ def __getitem__(self, key):
189216
return NotImplemented
190217

191218
def __invert__(self):
192-
result = SiliconPlatformPort(self._name, self._port_desc, invert=not self.invert)
219+
new_port_desc = copy.deepcopy(self._port_desc)
220+
new_port_desc.iomodel['invert'] = tuple([ not i for i in self.invert ])
221+
result = SiliconPlatformPort(self._name, new_port_desc)
193222
return result
194223

195224
def __add__(self, other):
196225
return NotImplemented
197226

198227
def __repr__(self):
199-
return (f"SiliconPlatformPort(name={self._name}, invert={self._invert}, iomode={self.iomodel})")
228+
return (f"SiliconPlatformPort(name={self._name}, iomodel={self.iomodel})")
200229

201230

202231
class Sky130Port(SiliconPlatformPort):
@@ -237,24 +266,22 @@ class Sky130Port(SiliconPlatformPort):
237266
# TODO: slew rate, hold points
238267
def __init__(self,
239268
name: str,
240-
port_desc: PortDesc,
241-
*,
242-
invert: bool = False):
243-
super().__init__(name, port_desc, invert=invert)
269+
port_desc: PortDesc):
270+
super().__init__(name, port_desc)
244271

245272
# keep a list of signals we create
246273
self._signals = []
247274

248-
# Now create the signals for ``gpio_oeb`` (``oe_n``), ``gpio_inp_dis`` (``ie``)
275+
# Now create the signals for ``gpio_oeb`` (``oe_n``), ``gpio_inp_dis`` (``ie_n``)
249276
self._oe_n = None
250-
self._ie = None
251277

252278
if self._oe is not None:
253279
self._oe_n = Signal(self._oe.shape().width, name=f"{self._name}$oeb")
254280
self._signals.append((self._oe_n, PortDirection.Output))
255-
if self._i is not None:
256-
self._ie = Signal(self._i.shape().width, name=f"{self._name}$inp_dis")
257-
self._signals.append((self._ie, PortDirection.Output))
281+
282+
if self._ie is not None:
283+
self._ie_n = Signal(self._ie.shape().width, name=f"{self._name}$inp_dis")
284+
self._signals.append((self._ie_n, PortDirection.Output))
258285

259286
# Port Configuration
260287
# Input voltage trip level
@@ -303,13 +330,7 @@ def __init__(self,
303330

304331
def wire(self, m: Module, interface: PureInterface):
305332
super().wire(m, interface)
306-
# don't wire up oe_n
307-
if hasattr(interface, 'ie'):
308-
m.d.comb += interface.ie.eq(self._ie) # type: ignore
309-
# wire up oe_n = ~oe
310-
if self._oe is not None:
311-
assert self._oe_n is not None
312-
m.d.comb += self._oe_n.eq(~self._oe)
333+
313334
# wire up drive mode bits
314335
bit = 0
315336
for i in self._dms:
@@ -325,12 +346,19 @@ def instantiate_toplevel(self):
325346
ports.append((f"io${s.name}", s, d))
326347
return ports
327348

328-
@property
329-
def ie(self):
330-
if self._ie is None:
331-
raise AttributeError("SiliconPlatformPort with input direction does not have an "
332-
"input enable signal")
333-
return self._ie
349+
def wire_up(self, m, wire):
350+
super().wire_up(m, wire)
351+
# wire up oe_n = ~oe
352+
if self._oe is not None:
353+
assert self._oe_n is not None
354+
m.d.comb += self._oe_n.eq(~self._oe)
355+
356+
if self._ie is not None:
357+
assert self._ie_n is not None
358+
m.d.comb += self._ie_n.eq(~self._ie)
359+
360+
if hasattr(wire, 'drive_mode'):
361+
m.d.comb += self.drive_mode.eq(wire.drive_mode)
334362

335363
@property
336364
def drive_mode(self):
@@ -342,11 +370,13 @@ def drive_mode(self):
342370
#TODO: trip selection
343371

344372
def __invert__(self):
345-
result = Sky130Port(self._name, self._port_desc, invert=not self.invert)
373+
new_port_desc = copy.deepcopy(self._port_desc)
374+
new_port_desc.iomodel['invert'] = tuple([ not i for i in self.invert ])
375+
result = SiliconPlatformPort(self._name, new_port_desc)
346376
return result
347377

348378
def __repr__(self):
349-
return (f"Sky130Port(name={self._name}, invert={self._invert}, iomode={self.iomodel})")
379+
return (f"Sky130Port(name={self._name}, iomodel={self.iomodel})")
350380

351381

352382

@@ -368,18 +398,17 @@ def elaborate(self, platform):
368398
raise TypeError(f"Cannot elaborate SiliconPlatform buffer with port {self.port!r}")
369399

370400
m = Module()
371-
401+
invert = sum(bit << idx for idx, bit in enumerate(self.port.invert))
372402
if self.direction is not io.Direction.Input:
373-
if self.port.invert:
403+
if invert != 0:
374404
o_inv = Signal.like(self.o)
375-
m.d.comb += o_inv.eq(~self.o)
405+
m.d.comb += o_inv.eq(self.o ^ invert)
376406
else:
377407
o_inv = self.o
378-
379408
if self.direction is not io.Direction.Output:
380-
if self.port.invert:
409+
if invert:
381410
i_inv = Signal.like(self.i)
382-
m.d.comb += self.i.eq(~i_inv)
411+
m.d.comb += self.i.eq(i_inv ^ invert)
383412
else:
384413
i_inv = self.i
385414

chipflow_lib/steps/__init__.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,5 @@ def _wire_up_ports(m: Module, top, platform):
6565
iface = getattr(top[component], iface_name)
6666
wire = (iface if isinstance(iface.signature, IOSignature)
6767
else getattr(iface, name))
68-
inv_mask = sum(inv << bit for bit, inv in enumerate(port.invert))
6968
port = platform._ports[port.port_name]
70-
if hasattr(wire, 'i'):
71-
m.d.comb += wire.i.eq(port.i ^ inv_mask)
72-
if hasattr(wire, 'o'):
73-
m.d.comb += port.o.eq(wire.o ^ inv_mask)
74-
if hasattr(wire, 'oe'):
75-
m.d.comb += port.oe.eq(wire.oe)
69+
port.wire_up(m, wire)

0 commit comments

Comments
 (0)