Skip to content

Commit 089ebe6

Browse files
committed
build.plat: use lib.io.*Buffer in default platform.
1 parent d94c979 commit 089ebe6

File tree

2 files changed

+90
-46
lines changed

2 files changed

+90
-46
lines changed

amaranth/build/plat.py

Lines changed: 72 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from ..hdl._ir import IOBufferInstance, Design
1313
from ..hdl._xfrm import DomainLowerer
1414
from ..lib.cdc import ResetSynchronizer
15+
from ..lib import io
1516
from ..back import rtlil, verilog
1617
from .res import *
1718
from .run import *
@@ -138,8 +139,13 @@ def prepare(self, elaboratable, name="top", **kwargs):
138139
fragment._propagate_domains(self.create_missing_domain, platform=self)
139140
fragment = DomainLowerer()(fragment)
140141

142+
def missing_domain_error(name):
143+
raise RuntimeError("Missing domain in pin fragment")
144+
141145
def add_pin_fragment(pin, pin_fragment):
142146
pin_fragment = Fragment.get(pin_fragment, self)
147+
pin_fragment._propagate_domains(missing_domain_error)
148+
pin_fragment = DomainLowerer()(pin_fragment)
143149
fragment.add_subfragment(pin_fragment, name=f"pin_{pin.name}")
144150

145151
for pin, port, attrs, invert in self.iter_single_ended_pins():
@@ -162,8 +168,7 @@ def add_pin_fragment(pin, pin_fragment):
162168
if pin.dir == "io":
163169
add_pin_fragment(pin, self.get_diff_input_output(pin, port, attrs, invert))
164170

165-
ports = [(None, signal, None) for signal in self.iter_ports()]
166-
fragment = Design(fragment, ports, hierarchy=(name,))
171+
fragment = Design(fragment, [], hierarchy=(name,))
167172
return self.toolchain_prepare(fragment, name, **kwargs)
168173

169174
@abstractmethod
@@ -201,63 +206,87 @@ def _invert_if(invert, value):
201206
return value
202207

203208
def get_input(self, pin, port, attrs, invert):
204-
self._check_feature("single-ended input", pin, attrs,
205-
valid_xdrs=(0,), valid_attrs=None)
209+
self._check_feature("input", pin, attrs,
210+
valid_xdrs=(0, 1, 2), valid_attrs=True)
206211

207212
m = Module()
208-
m.d.comb += pin.i.eq(self._invert_if(invert, port))
213+
if pin.xdr == 0:
214+
m.submodules.buf = buf = io.Buffer(io.Direction.Input, port)
215+
m.d.comb += pin.i.eq(buf.i)
216+
elif pin.xdr == 1:
217+
m.domains.input = cd_input = ClockDomain(reset_less=True)
218+
m.submodules.buf = buf = io.FFBuffer(io.Direction.Input, port, i_domain="input")
219+
m.d.comb += pin.i.eq(buf.i)
220+
m.d.comb += cd_input.clk.eq(pin.i_clk)
221+
elif pin.xdr == 2:
222+
m.domains.input = cd_input = ClockDomain(reset_less=True)
223+
m.submodules.buf = buf = io.DDRBuffer(io.Direction.Input, port, i_domain="input")
224+
m.d.comb += pin.i0.eq(buf.i[0])
225+
m.d.comb += pin.i1.eq(buf.i[1])
226+
m.d.comb += cd_input.clk.eq(pin.i_clk)
209227
return m
210228

211229
def get_output(self, pin, port, attrs, invert):
212-
self._check_feature("single-ended output", pin, attrs,
213-
valid_xdrs=(0,), valid_attrs=None)
230+
self._check_feature("output", pin, attrs,
231+
valid_xdrs=(0, 1, 2), valid_attrs=True)
214232

215233
m = Module()
216-
m.d.comb += port.eq(self._invert_if(invert, pin.o))
234+
if pin.xdr == 0:
235+
m.submodules.buf = buf = io.Buffer(io.Direction.Output, port)
236+
m.d.comb += buf.o.eq(pin.o)
237+
elif pin.xdr == 1:
238+
m.domains.output = cd_output = ClockDomain(reset_less=True)
239+
m.submodules.buf = buf = io.FFBuffer(io.Direction.Output, port, o_domain="output")
240+
m.d.comb += buf.o.eq(pin.o)
241+
m.d.comb += cd_output.clk.eq(pin.o_clk)
242+
elif pin.xdr == 2:
243+
m.domains.output = cd_output = ClockDomain(reset_less=True)
244+
m.submodules.buf = buf = io.DDRBuffer(io.Direction.Output, port, o_domain="output")
245+
m.d.comb += buf.o[0].eq(pin.o0)
246+
m.d.comb += buf.o[1].eq(pin.o1)
247+
m.d.comb += cd_output.clk.eq(pin.o_clk)
248+
if pin.dir == "oe":
249+
m.d.comb += buf.oe.eq(pin.oe)
217250
return m
218251

219-
def get_tristate(self, pin, port, attrs, invert):
220-
self._check_feature("single-ended tristate", pin, attrs,
221-
valid_xdrs=(0,), valid_attrs=None)
222-
223-
m = Module()
224-
m.submodules += IOBufferInstance(
225-
port=port,
226-
o=self._invert_if(invert, pin.o),
227-
oe=pin.oe,
228-
)
229-
return m
252+
get_tristate = get_output
230253

231254
def get_input_output(self, pin, port, attrs, invert):
232255
self._check_feature("single-ended input/output", pin, attrs,
233-
valid_xdrs=(0,), valid_attrs=None)
256+
valid_xdrs=(0, 1, 2), valid_attrs=True)
234257

235258
m = Module()
236-
i = Signal.like(pin.i)
237-
m.submodules += IOBufferInstance(
238-
port=port,
239-
i=i,
240-
o=self._invert_if(invert, pin.o),
241-
oe=pin.oe,
242-
)
243-
m.d.comb += pin.i.eq(self._invert_if(invert, i))
259+
if pin.xdr == 0:
260+
m.submodules.buf = buf = io.Buffer(io.Direction.Bidir, port)
261+
m.d.comb += pin.i.eq(buf.i)
262+
m.d.comb += buf.o.eq(pin.o)
263+
m.d.comb += buf.oe.eq(pin.oe)
264+
elif pin.xdr == 1:
265+
m.domains.input = cd_input = ClockDomain(reset_less=True)
266+
m.domains.output = cd_output = ClockDomain(reset_less=True)
267+
m.submodules.buf = buf = io.FFBuffer(io.Direction.Bidir, port, i_domain="input", o_domain="output")
268+
m.d.comb += pin.i.eq(buf.i)
269+
m.d.comb += buf.o.eq(pin.o)
270+
m.d.comb += buf.oe.eq(pin.oe)
271+
m.d.comb += cd_input.clk.eq(pin.i_clk)
272+
m.d.comb += cd_output.clk.eq(pin.o_clk)
273+
elif pin.xdr == 2:
274+
m.domains.input = cd_input = ClockDomain(reset_less=True)
275+
m.domains.output = cd_output = ClockDomain(reset_less=True)
276+
m.submodules.buf = buf = io.DDRBuffer(io.Direction.Bidir, port, i_domain="input", o_domain="output")
277+
m.d.comb += pin.i0.eq(buf.i[0])
278+
m.d.comb += pin.i1.eq(buf.i[1])
279+
m.d.comb += buf.o[0].eq(pin.o0)
280+
m.d.comb += buf.o[1].eq(pin.o1)
281+
m.d.comb += buf.oe.eq(pin.oe)
282+
m.d.comb += cd_input.clk.eq(pin.i_clk)
283+
m.d.comb += cd_output.clk.eq(pin.o_clk)
244284
return m
245285

246-
def get_diff_input(self, pin, port, attrs, invert):
247-
self._check_feature("differential input", pin, attrs,
248-
valid_xdrs=(), valid_attrs=None)
249-
250-
def get_diff_output(self, pin, port, attrs, invert):
251-
self._check_feature("differential output", pin, attrs,
252-
valid_xdrs=(), valid_attrs=None)
253-
254-
def get_diff_tristate(self, pin, port, attrs, invert):
255-
self._check_feature("differential tristate", pin, attrs,
256-
valid_xdrs=(), valid_attrs=None)
257-
258-
def get_diff_input_output(self, pin, port, attrs, invert):
259-
self._check_feature("differential input/output", pin, attrs,
260-
valid_xdrs=(), valid_attrs=None)
286+
get_diff_input = get_input
287+
get_diff_output = get_output
288+
get_diff_tristate = get_tristate
289+
get_diff_input_output = get_input_output
261290

262291

263292
class TemplatedPlatform(Platform):

amaranth/build/res.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ class PortGroup:
1818
pass
1919

2020

21+
class PortMetadata:
22+
def __init__(self, name, attrs):
23+
self.name = name
24+
self.attrs = attrs
25+
26+
2127
class ResourceManager:
2228
def __init__(self, resources, connectors):
2329
self.resources = OrderedDict()
@@ -133,12 +139,21 @@ def resolve(resource, dir, xdr, path, attrs):
133139
direction = phys.dir
134140
if isinstance(phys, Pins):
135141
phys_names = phys.names
136-
io = IOPort(len(phys), name="__".join(path) + "__io")
142+
io = IOPort(len(phys), name="__".join(path) + "__io", metadata=[
143+
PortMetadata(name, attrs)
144+
for name in phys.names
145+
])
137146
port = SingleEndedPort(io, invert=phys.invert, direction=direction)
138147
if isinstance(phys, DiffPairs):
139148
phys_names = []
140-
p = IOPort(len(phys), name="__".join(path) + "__p")
141-
n = IOPort(len(phys), name="__".join(path) + "__n")
149+
p = IOPort(len(phys), name="__".join(path) + "__p", metadata=[
150+
PortMetadata(name, attrs)
151+
for name in phys.p.names
152+
])
153+
n = IOPort(len(phys), name="__".join(path) + "__n", metadata=[
154+
PortMetadata(name, attrs)
155+
for name in phys.n.names
156+
])
142157
if not self.should_skip_port_component(None, attrs, "p"):
143158
phys_names += phys.p.names
144159
if not self.should_skip_port_component(None, attrs, "n"):

0 commit comments

Comments
 (0)