build.res,vendor: place clock constraint on port, not net, if possible.
For most toolchains, these are functionally identical, although ports tend to work a bit better, being the common case. For Vivado, though, it is necessary to place them on the port because its timing analyzer considers input buffer delay. Fixes #301.
This commit is contained in:
parent
5888f29c1f
commit
3e2ecdf2fb
|
@ -226,4 +226,25 @@ class ResourceManager:
|
|||
self._clocks[clock] = float(frequency)
|
||||
|
||||
def iter_clock_constraints(self):
|
||||
return iter(self._clocks.items())
|
||||
# Back-propagate constraints through the input buffer. For clock constraints on pins
|
||||
# (the majority of cases), toolchains work better if the constraint is defined on the pin
|
||||
# and not on the buffered internal net; and if the toolchain is advanced enough that
|
||||
# it considers clock phase and delay of the input buffer, it is *necessary* to define
|
||||
# the constraint on the pin to match the designer's expectation of phase being referenced
|
||||
# to the pin.
|
||||
#
|
||||
# Constraints on nets with no corresponding input pin (e.g. PLL or SERDES outputs) are not
|
||||
# affected.
|
||||
pin_i_to_port = SignalDict()
|
||||
for res, pin, port, attrs in self._ports:
|
||||
if hasattr(pin, "i"):
|
||||
if isinstance(res.ios[0], Pins):
|
||||
pin_i_to_port[pin.i] = port.io
|
||||
elif isinstance(res.ios[0], DiffPairs):
|
||||
pin_i_to_port[pin.i] = port.p
|
||||
else:
|
||||
assert False
|
||||
|
||||
for net_signal, frequency in self._clocks.items():
|
||||
port_signal = pin_i_to_port.get(net_signal)
|
||||
yield net_signal, port_signal, frequency
|
||||
|
|
10
nmigen/vendor/intel.py
vendored
10
nmigen/vendor/intel.py
vendored
|
@ -107,15 +107,19 @@ class IntelPlatform(TemplatedPlatform):
|
|||
set_global_assignment -name GENERATE_RBF_FILE ON
|
||||
""",
|
||||
"{{name}}.sdc": r"""
|
||||
{% for signal, frequency in platform.iter_clock_constraints() -%}
|
||||
create_clock -period {{1000000000/frequency}} [get_nets {{signal|hierarchy("|")}}]
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
create_clock -name {{port_signal.name}} -period {{1000000000/frequency}} [get_ports {{port_signal.name}}]
|
||||
{% else -%}
|
||||
create_clock -name {{net_signal.name}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("|")}}]
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
""",
|
||||
"{{name}}.srf": r"""
|
||||
{% for warning in platform.quartus_suppressed_warnings %}
|
||||
{ "" "" "" "{{name}}.v" { } { } 0 {{warning}} "" 0 0 "Design Software" 0 -1 0 ""}
|
||||
{% endfor %}
|
||||
""",
|
||||
""",
|
||||
}
|
||||
command_templates = [
|
||||
r"""
|
||||
|
|
19
nmigen/vendor/lattice_ecp5.py
vendored
19
nmigen/vendor/lattice_ecp5.py
vendored
|
@ -135,8 +135,12 @@ class LatticeECP5Platform(TemplatedPlatform):
|
|||
{%- for key, value in extras.items() %} {{key}}={{value}}{% endfor %};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for signal, frequency in platform.iter_clock_constraints() -%}
|
||||
FREQUENCY NET "{{signal|hierarchy(".")}}" {{frequency}} HZ;
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
FREQUENCY PORT "{{port_signal.name}}" {{frequency}} HZ;
|
||||
{% else -%}
|
||||
FREQUENCY NET "{{net_signal|hierarchy(".")}}" {{frequency}} HZ;
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{get_override("add_preferences")|default("# (add_preferences placeholder)")}}
|
||||
"""
|
||||
|
@ -227,14 +231,15 @@ class LatticeECP5Platform(TemplatedPlatform):
|
|||
IOBUF PORT "{{port_name}}"
|
||||
{%- for key, value in extras.items() %} {{key}}={{value}}{% endfor %};
|
||||
{% endfor %}
|
||||
{% for signal, frequency in platform.iter_clock_constraints() -%}
|
||||
FREQUENCY NET "{{signal|hierarchy("/")}}" {{frequency/1000000}} MHZ;
|
||||
{% endfor %}
|
||||
{{get_override("add_preferences")|default("# (add_preferences placeholder)")}}
|
||||
""",
|
||||
"{{name}}.sdc": r"""
|
||||
{% for signal, frequency in platform.iter_clock_constraints() -%}
|
||||
create_clock -period {{1000000000/frequency}} [get_nets {{signal|hierarchy("/")}}]
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
create_clock -name {{port_signal.name}} -period {{1000000000/frequency}} [get_ports {{port_signal.name}}]
|
||||
{% else -%}
|
||||
create_clock -name {{net_signal.name}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")}}]
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
|
||||
""",
|
||||
|
|
12
nmigen/vendor/lattice_ice40.py
vendored
12
nmigen/vendor/lattice_ice40.py
vendored
|
@ -134,8 +134,8 @@ class LatticeICE40Platform(TemplatedPlatform):
|
|||
{% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
|
||||
set_io {{port_name}} {{pin_name}}
|
||||
{% endfor %}
|
||||
{% for signal, frequency in platform.iter_clock_constraints() -%}
|
||||
set_frequency {{signal|hierarchy(".")}} {{frequency/1000000}}
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
set_frequency {{net_signal|hierarchy(".")}} {{frequency/1000000}}
|
||||
{% endfor%}
|
||||
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
|
||||
""",
|
||||
|
@ -243,8 +243,12 @@ class LatticeICE40Platform(TemplatedPlatform):
|
|||
""",
|
||||
"{{name}}.sdc": r"""
|
||||
# {{autogenerated}}
|
||||
{% for signal, frequency in platform.iter_clock_constraints() -%}
|
||||
create_clock -name {{signal.name}} -period {{1000000000/frequency}} [get_nets {{signal|hierarchy("/")}}]
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
create_clock -name {{port_signal.name}} -period {{1000000000/frequency}} [get_ports {{port_signal.name}}]
|
||||
{% else -%}
|
||||
create_clock -name {{net_signal.name}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")}}]
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
|
||||
""",
|
||||
|
|
11
nmigen/vendor/lattice_machxo2.py
vendored
11
nmigen/vendor/lattice_machxo2.py
vendored
|
@ -91,14 +91,15 @@ class LatticeMachXO2Platform(TemplatedPlatform):
|
|||
{%- for key, value in extras.items() %} {{key}}={{value}}{% endfor %};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for signal, frequency in platform.iter_clock_constraints() -%}
|
||||
FREQUENCY NET "{{signal|hierarchy("/")}}" {{frequency/1000000}} MHZ;
|
||||
{% endfor %}
|
||||
{{get_override("add_preferences")|default("# (add_preferences placeholder)")}}
|
||||
""",
|
||||
"{{name}}.sdc": r"""
|
||||
{% for signal, frequency in platform.iter_clock_constraints() -%}
|
||||
create_clock -period {{1000000000/frequency}} [get_nets {{signal|hierarchy("/")}}]
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
create_clock -name {{port_signal.name}} -period {{1000000000/frequency}} [get_ports {{port_signal.name}}]
|
||||
{% else -%}
|
||||
create_clock -name {{net_signal.name}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")}}]
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
|
||||
""",
|
||||
|
|
8
nmigen/vendor/xilinx_7series.py
vendored
8
nmigen/vendor/xilinx_7series.py
vendored
|
@ -133,8 +133,12 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
|
|||
set_property {{attr_name}} {{attr_value}} [get_ports {{port_name}}]
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% for signal, frequency in platform.iter_clock_constraints() -%}
|
||||
create_clock -name {{signal.name}} -period {{1000000000/frequency}} [get_nets {{signal|hierarchy("/")}}]
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
create_clock -name {{port_signal.name}} -period {{1000000000/frequency}} [get_ports {{port_signal.name}}]
|
||||
{% else -%}
|
||||
create_clock -name {{net_signal.name}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")}}]
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
|
||||
"""
|
||||
|
|
6
nmigen/vendor/xilinx_spartan_3_6.py
vendored
6
nmigen/vendor/xilinx_spartan_3_6.py
vendored
|
@ -132,9 +132,9 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
|
|||
NET "{{port_name}}" {{attr_name}}={{attr_value}};
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% for signal, frequency in platform.iter_clock_constraints() -%}
|
||||
NET "{{signal|hierarchy("/")}}" TNM_NET="PRD{{signal|hierarchy("/")}}";
|
||||
TIMESPEC "TS{{signal|hierarchy("/")}}"=PERIOD "PRD{{signal|hierarchy("/")}}" {{1000000000/frequency}} ns HIGH 50%;
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
NET "{{net_signal|hierarchy("/")}}" TNM_NET="PRD{{net_signal|hierarchy("/")}}";
|
||||
TIMESPEC "TS{{net_signal|hierarchy("/")}}"=PERIOD "PRD{{net_signal|hierarchy("/")}}" {{1000000000/frequency}} ns HIGH 50%;
|
||||
{% endfor %}
|
||||
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
|
||||
"""
|
||||
|
|
8
nmigen/vendor/xilinx_ultrascale.py
vendored
8
nmigen/vendor/xilinx_ultrascale.py
vendored
|
@ -133,8 +133,12 @@ class XilinxUltraScalePlatform(TemplatedPlatform):
|
|||
set_property {{attr_name}} {{attr_value}} [get_ports {{port_name}}]
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% for signal, frequency in platform.iter_clock_constraints() -%}
|
||||
create_clock -name {{signal.name}} -period {{1000000000/frequency}} [get_nets {{signal|hierarchy("/")}}]
|
||||
{% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
|
||||
{% if port_signal is not none -%}
|
||||
create_clock -name {{port_signal.name}} -period {{1000000000/frequency}} [get_ports {{port_signal.name}}]
|
||||
{% else -%}
|
||||
create_clock -name {{net_signal.name}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")}}]
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
|
||||
"""
|
||||
|
|
Loading…
Reference in a new issue