Skip to content

Commit f7d351e

Browse files
committed
Allow input enable for all processes
1 parent 616a5e4 commit f7d351e

File tree

2 files changed

+73
-44
lines changed

2 files changed

+73
-44
lines changed

chipflow_lib/platforms/silicon.py

Lines changed: 72 additions & 37 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,23 +72,31 @@ 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
79-
self._name = name
8077
width = port_desc.width
8178

79+
if 'invert' in port_desc.iomodel:
80+
if isinstance(port_desc.iomodel['invert'], bool):
81+
self._invert = [port_desc.iomodel['invert']]*width
82+
else:
83+
self._invert = port_desc.iomodel['invert']
84+
else:
85+
self._invert = [False]*width
86+
87+
self._name = name
88+
8289
# Initialize signal attributes to None
8390
self._i = None
8491
self._ie = None
8592
self._o = None
8693
self._oe = None
94+
self._ie = None
8795

8896
# Create signals based on direction
8997
if self.direction in (io.Direction.Input, io.Direction.Bidir):
90-
self._i = Signal(self._port_desc.width, name=f"{self._name}__i")
98+
self._i = Signal(width, name=f"{self._name}$i")
99+
self._ie = Signal(width, name=f"{self._name}$inp_dis", init=-1)
91100
if self.direction in (io.Direction.Output, io.Direction.Bidir):
92101
self._o = Signal(width, name=f"{self._name}$o")
93102

@@ -104,17 +113,13 @@ def __init__(self,
104113
self._oes = Signal(width, name=f"{self._name}$oe", init=init_oe)
105114
self._oe = self._oes
106115

107-
elif self.direction is io.Direction.Output:
108-
# Always create an _oe for output ports
109-
self._oe = Signal(1, name=f"{self._name}__oe", init=-1)
110-
111-
logger.debug(f"Created SiliconPlatformPort {self._name}, invert={invert} with port description:\n{pformat(self._port_desc)}")
116+
logger.debug(f"Created SiliconPlatformPort {self._name}, with port description:\n{pformat(self._port_desc)}")
112117

113118
def wire(self, m: Module, interface: PureInterface):
114119
assert self.direction == interface.signature.direction #type: ignore
115120
if hasattr(interface, '_i'):
116121
m.d.comb += interface.i.eq(self.i) # type: ignore
117-
for d in ['_o', '_oe']:
122+
for d in ['_o', '_oe', '_ie']:
118123
if hasattr(interface, d):
119124
m.d.comb += getattr(self, d).eq(getattr(interface, d))
120125
# wire user side _oe to _oes if necessary
@@ -134,6 +139,21 @@ def instantiate_toplevel(self):
134139
ports.append((f"io${self._name}$oe", self._oe, PortDirection.Output))
135140
return ports
136141

142+
def wire_up(self, m, wire):
143+
inv_mask = sum(inv << bit for bit, inv in enumerate(self.invert))
144+
if hasattr(wire, 'i'):
145+
m.d.comb += wire.i.eq(self.i ^ inv_mask)
146+
if hasattr(wire, 'o'):
147+
m.d.comb += self.o.eq(wire.o ^ inv_mask)
148+
if hasattr(wire, 'oe'):
149+
m.d.comb += self.oe.eq(wire.oe)
150+
151+
if hasattr(wire, 'ie'):
152+
m.d.comb += self.ie.eq(wire.ie)
153+
elif hasattr(wire, 'oe'):
154+
m.d.comb += self.ie.eq(wire.oe)
155+
156+
137157
@property
138158
def name(self) -> str:
139159
return self._name
@@ -168,6 +188,13 @@ def oe(self):
168188
"output enable signal")
169189
return self._oe
170190

191+
@property
192+
def ie(self):
193+
if self._ie is None:
194+
raise AttributeError("SiliconPlatformPort with input direction does not have an "
195+
"input enable signal")
196+
return self._ie
197+
171198
@property
172199
def direction(self):
173200
return self._port_desc.iomodel['direction']
@@ -195,14 +222,16 @@ def __getitem__(self, key):
195222
return NotImplemented
196223

197224
def __invert__(self):
198-
result = SiliconPlatformPort(self._name, self._port_desc, invert=not self.invert)
225+
new_port_desc = copy.deepcopy(self._port_desc)
226+
new_port_desc.iomodel['invert'] = tuple([ not i for i in self.invert ])
227+
result = SiliconPlatformPort(self._name, new_port_desc)
199228
return result
200229

201230
def __add__(self, other):
202231
return NotImplemented
203232

204233
def __repr__(self):
205-
return (f"SiliconPlatformPort(name={self._name}, invert={self._invert}, iomode={self.iomodel})")
234+
return (f"SiliconPlatformPort(name={self._name}, iomodel={self.iomodel})")
206235

207236

208237
class Sky130Port(SiliconPlatformPort):
@@ -243,26 +272,24 @@ class Sky130Port(SiliconPlatformPort):
243272
# TODO: slew rate, hold points
244273
def __init__(self,
245274
name: str,
246-
port_desc: PortDesc,
247-
*,
248-
invert: bool = False):
249-
super().__init__(name, port_desc, invert=invert)
275+
port_desc: PortDesc):
276+
super().__init__(name, port_desc)
250277

251278
width = port_desc.width
252279

253280
# keep a list of signals we create
254281
self._signals = []
255282

256-
# Now create the signals for ``gpio_oeb`` (``oe_n``), ``gpio_inp_dis`` (``ie``)
283+
# Now create the signals for ``gpio_oeb`` (``oe_n``), ``gpio_inp_dis`` (``ie_n``)
257284
self._oe_n = None
258-
self._ie = None
259285

260286
if self._oe is not None:
261287
self._oe_n = Signal(self._oe.shape().width, name=f"{self._name}$oeb")
262288
self._signals.append((self._oe_n, PortDirection.Output))
263-
if self._i is not None:
264-
self._ie = Signal(self._i.shape().width, name=f"{self._name}$inp_dis")
265-
self._signals.append((self._ie, PortDirection.Output))
289+
290+
if self._ie is not None:
291+
self._ie_n = Signal(self._ie.shape().width, name=f"{self._name}$inp_dis")
292+
self._signals.append((self._ie_n, PortDirection.Output))
266293

267294
# Port Configuration
268295
# Input voltage trip level
@@ -318,12 +345,19 @@ def instantiate_toplevel(self):
318345
ports.append((f"io${s.name}", s, d))
319346
return ports
320347

321-
@property
322-
def ie(self):
323-
if self._ie is None:
324-
raise AttributeError("SiliconPlatformPort with input direction does not have an "
325-
"input enable signal")
326-
return self._ie
348+
def wire_up(self, m, wire):
349+
super().wire_up(m, wire)
350+
# wire up oe_n = ~oe
351+
if self._oe is not None:
352+
assert self._oe_n is not None
353+
m.d.comb += self._oe_n.eq(~self._oe)
354+
355+
if self._ie is not None:
356+
assert self._ie_n is not None
357+
m.d.comb += self._ie_n.eq(~self._ie)
358+
359+
if hasattr(wire, 'drive_mode'):
360+
m.d.comb += self.drive_mode.eq(wire.drive_mode)
327361

328362
@property
329363
def drive_mode(self):
@@ -334,11 +368,13 @@ def drive_mode(self):
334368
#TODO: trip selection
335369

336370
def __invert__(self):
337-
result = Sky130Port(self._name, self._port_desc, invert=not self.invert)
371+
new_port_desc = copy.deepcopy(self._port_desc)
372+
new_port_desc.iomodel['invert'] = tuple([ not i for i in self.invert ])
373+
result = SiliconPlatformPort(self._name, new_port_desc)
338374
return result
339375

340376
def __repr__(self):
341-
return (f"Sky130Port(name={self._name}, invert={self._invert}, iomode={self.iomodel})")
377+
return (f"Sky130Port(name={self._name}, iomodel={self.iomodel})")
342378

343379

344380

@@ -356,18 +392,17 @@ def elaborate(self, platform):
356392
raise TypeError(f"Cannot elaborate SiliconPlatform buffer with port {self.port!r}")
357393

358394
m = Module()
359-
395+
invert = sum(bit << idx for idx, bit in enumerate(self.port.invert))
360396
if self.direction is not io.Direction.Input:
361-
if self.port.invert:
397+
if invert != 0:
362398
o_inv = Signal.like(self.o)
363-
m.d.comb += o_inv.eq(~self.o)
399+
m.d.comb += o_inv.eq(self.o ^ invert)
364400
else:
365401
o_inv = self.o
366-
367402
if self.direction is not io.Direction.Output:
368-
if self.port.invert:
403+
if invert:
369404
i_inv = Signal.like(self.i)
370-
m.d.comb += self.i.eq(~i_inv)
405+
m.d.comb += self.i.eq(i_inv ^ invert)
371406
else:
372407
i_inv = self.i
373408

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)