build.dsl: replace extras= with Attrs().
This change proved more tricky than expected due to downstream dependencies, so it also includes some secondary refactoring.
This commit is contained in:
parent
c52cd72d3e
commit
ab3f103e5a
7 changed files with 262 additions and 253 deletions
102
nmigen/vendor/lattice_ice40.py
vendored
102
nmigen/vendor/lattice_ice40.py
vendored
|
|
@ -70,7 +70,7 @@ class LatticeICE40Platform(TemplatedPlatform):
|
|||
""",
|
||||
"{{name}}.pcf": r"""
|
||||
# {{autogenerated}}
|
||||
{% for port_name, pin_name, extras in platform.iter_port_constraints_bits() -%}
|
||||
{% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
|
||||
set_io {{port_name}} {{pin_name}}
|
||||
{% endfor %}
|
||||
""",
|
||||
|
|
@ -110,33 +110,17 @@ class LatticeICE40Platform(TemplatedPlatform):
|
|||
"""
|
||||
]
|
||||
|
||||
def iter_ports(self):
|
||||
for res, pin, port in self._ports:
|
||||
if isinstance(res.io[0], Pins):
|
||||
yield port.io
|
||||
elif isinstance(res.io[0], DiffPairs):
|
||||
if res.extras.get("IO_STANDARD", "SB_LVCMOS") == "SB_LVDS_INPUT":
|
||||
yield port.p
|
||||
else:
|
||||
yield port.p
|
||||
yield port.n
|
||||
else:
|
||||
assert False
|
||||
def should_skip_port_component(self, port, attrs, component):
|
||||
# On iCE40, a differential input is placed by only instantiating an SB_IO primitive for
|
||||
# the pin with z=0, which is the non-inverting pin. The pinout unfortunately differs
|
||||
# between LP/HX and UP series:
|
||||
# * for LP/HX, z=0 is DPxxB (B is non-inverting, A is inverting)
|
||||
# * for UP, z=0 is IOB_xxA (A is non-inverting, B is inverting)
|
||||
if attrs.get("IO_STANDARD", "SB_LVCMOS") == "SB_LVDS_INPUT" and component == "n":
|
||||
return True
|
||||
return False
|
||||
|
||||
def iter_port_constraints(self):
|
||||
for res, pin, port in self._ports:
|
||||
if isinstance(res.io[0], Pins):
|
||||
yield port.io.name, list(res.io[0].map_names(self._mapping, res)), res.extras
|
||||
elif isinstance(res.io[0], DiffPairs):
|
||||
if res.extras.get("IO_STANDARD", "SB_LVCMOS") == "SB_LVDS_INPUT":
|
||||
yield port.p.name, list(res.io[0].p.map_names(self._mapping, res)), res.extras
|
||||
else:
|
||||
yield port.p.name, list(res.io[0].p.map_names(self._mapping, res)), res.extras
|
||||
yield port.n.name, list(res.io[0].n.map_names(self._mapping, res)), res.extras
|
||||
else:
|
||||
assert False
|
||||
|
||||
def _get_io_buffer(self, m, pin, port, extras, o_invert=None):
|
||||
def _get_io_buffer(self, m, pin, port, attrs, o_invert=None):
|
||||
def _get_dff(clk, d, q):
|
||||
m.submodules += Instance("$dff",
|
||||
p_CLK_POLARITY=0,
|
||||
|
|
@ -160,9 +144,9 @@ class LatticeICE40Platform(TemplatedPlatform):
|
|||
o_O=y[bit])
|
||||
return y
|
||||
|
||||
if "GLOBAL" in extras:
|
||||
is_global_input = bool(extras["GLOBAL"])
|
||||
del extras["GLOBAL"]
|
||||
if "GLOBAL" in attrs:
|
||||
is_global_input = bool(attrs["GLOBAL"])
|
||||
del attrs["GLOBAL"]
|
||||
else:
|
||||
is_global_input = False
|
||||
|
||||
|
|
@ -185,7 +169,7 @@ class LatticeICE40Platform(TemplatedPlatform):
|
|||
for bit in range(len(port)):
|
||||
io_args = [
|
||||
("io", "PACKAGE_PIN", port[bit]),
|
||||
*(("p", key, value) for key, value in extras.items()),
|
||||
*(("p", key, value) for key, value in attrs.items()),
|
||||
]
|
||||
|
||||
if "i" not in pin.dir:
|
||||
|
|
@ -242,56 +226,52 @@ class LatticeICE40Platform(TemplatedPlatform):
|
|||
else:
|
||||
m.submodules += Instance("SB_IO", *io_args)
|
||||
|
||||
def get_input(self, pin, port, extras):
|
||||
self._check_feature("single-ended input", pin, extras,
|
||||
valid_xdrs=(0, 1, 2), valid_extras=True)
|
||||
def get_input(self, pin, port, attrs):
|
||||
self._check_feature("single-ended input", pin, attrs,
|
||||
valid_xdrs=(0, 1, 2), valid_attrs=True)
|
||||
m = Module()
|
||||
self._get_io_buffer(m, pin, port, extras)
|
||||
self._get_io_buffer(m, pin, port, attrs)
|
||||
return m
|
||||
|
||||
def get_output(self, pin, port, extras):
|
||||
self._check_feature("single-ended output", pin, extras,
|
||||
valid_xdrs=(0, 1, 2), valid_extras=True)
|
||||
def get_output(self, pin, port, attrs):
|
||||
self._check_feature("single-ended output", pin, attrs,
|
||||
valid_xdrs=(0, 1, 2), valid_attrs=True)
|
||||
m = Module()
|
||||
self._get_io_buffer(m, pin, port, extras)
|
||||
self._get_io_buffer(m, pin, port, attrs)
|
||||
return m
|
||||
|
||||
def get_tristate(self, pin, port, extras):
|
||||
self._check_feature("single-ended tristate", pin, extras,
|
||||
valid_xdrs=(0, 1, 2), valid_extras=True)
|
||||
def get_tristate(self, pin, port, attrs):
|
||||
self._check_feature("single-ended tristate", pin, attrs,
|
||||
valid_xdrs=(0, 1, 2), valid_attrs=True)
|
||||
m = Module()
|
||||
self._get_io_buffer(m, pin, port, extras)
|
||||
self._get_io_buffer(m, pin, port, attrs)
|
||||
return m
|
||||
|
||||
def get_input_output(self, pin, port, extras):
|
||||
self._check_feature("single-ended input/output", pin, extras,
|
||||
valid_xdrs=(0, 1, 2), valid_extras=True)
|
||||
def get_input_output(self, pin, port, attrs):
|
||||
self._check_feature("single-ended input/output", pin, attrs,
|
||||
valid_xdrs=(0, 1, 2), valid_attrs=True)
|
||||
m = Module()
|
||||
self._get_io_buffer(m, pin, port, extras)
|
||||
self._get_io_buffer(m, pin, port, attrs)
|
||||
return m
|
||||
|
||||
def get_diff_input(self, pin, p_port, n_port, extras):
|
||||
self._check_feature("differential input", pin, extras,
|
||||
valid_xdrs=(0, 1, 2), valid_extras=True)
|
||||
# On iCE40, a differential input is placed by only instantiating an SB_IO primitive for
|
||||
# the pin with z=0, which is the non-inverting pin. The pinout unfortunately differs
|
||||
# between LP/HX and UP series:
|
||||
# * for LP/HX, z=0 is DPxxB (B is non-inverting, A is inverting)
|
||||
# * for UP, z=0 is IOB_xxA (A is non-inverting, B is inverting)
|
||||
def get_diff_input(self, pin, p_port, n_port, attrs):
|
||||
self._check_feature("differential input", pin, attrs,
|
||||
valid_xdrs=(0, 1, 2), valid_attrs=True)
|
||||
m = Module()
|
||||
self._get_io_buffer(m, pin, p_port, extras)
|
||||
# See comment in should_skip_port_component above.
|
||||
self._get_io_buffer(m, pin, p_port, attrs)
|
||||
return m
|
||||
|
||||
def get_diff_output(self, pin, p_port, n_port, extras):
|
||||
self._check_feature("differential output", pin, extras,
|
||||
valid_xdrs=(0, 1, 2), valid_extras=True)
|
||||
def get_diff_output(self, pin, p_port, n_port, attrs):
|
||||
self._check_feature("differential output", pin, attrs,
|
||||
valid_xdrs=(0, 1, 2), valid_attrs=True)
|
||||
m = Module()
|
||||
# Note that the non-inverting output pin is not driven the same way as a regular
|
||||
# output pin. The inverter introduces a delay, so for a non-inverting output pin,
|
||||
# an identical delay is introduced by instantiating a LUT. This makes the waveform
|
||||
# perfectly symmetric in the xdr=0 case.
|
||||
self._get_io_buffer(m, pin, p_port, extras, o_invert=False)
|
||||
self._get_io_buffer(m, pin, n_port, extras, o_invert=True)
|
||||
self._get_io_buffer(m, pin, p_port, attrs, o_invert=False)
|
||||
self._get_io_buffer(m, pin, n_port, attrs, o_invert=True)
|
||||
return m
|
||||
|
||||
# Tristate and bidirectional buffers are not supported on iCE40 because it requires external
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue