vendor.xilinx: add support for Xray-based toolchain.
This commit is contained in:
parent
0a1ba22050
commit
e3b2ba4316
|
@ -102,6 +102,17 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
|
|
||||||
Available overrides:
|
Available overrides:
|
||||||
* ``add_constraints``: inserts commands in XDC file.
|
* ``add_constraints``: inserts commands in XDC file.
|
||||||
|
|
||||||
|
.. rubric:: Xray toolchain
|
||||||
|
|
||||||
|
Required tools:
|
||||||
|
* ``yosys``
|
||||||
|
* ``nextpnr-xilinx``
|
||||||
|
* ``fasm2frames``
|
||||||
|
* ``xc7frames2bit``
|
||||||
|
|
||||||
|
The environment is populated by running the script specified in the environment variable
|
||||||
|
``AMARANTH_ENV_Xray``, if present.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
toolchain = None # selected when creating platform
|
toolchain = None # selected when creating platform
|
||||||
|
@ -117,6 +128,10 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
else:
|
else:
|
||||||
return "{}{}-{}".format(self.device, self.package, self.speed)
|
return "{}{}-{}".format(self.device, self.package, self.speed)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def vendor_toolchain(self):
|
||||||
|
return self.toolchain in ["Vivado", "ISE"]
|
||||||
|
|
||||||
# Vivado templates
|
# Vivado templates
|
||||||
|
|
||||||
_vivado_required_tools = ["vivado"]
|
_vivado_required_tools = ["vivado"]
|
||||||
|
@ -426,6 +441,93 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
"""
|
"""
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Yosys NextPNR prjxray templates
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _xray_part(self):
|
||||||
|
return {
|
||||||
|
"xc7a35ticsg324-1L": "xc7a35tcsg324-1", # Arty-A7 35t
|
||||||
|
"xc7a100ticsg324-1L": "xc7a100tcsg324-1", # Arty-A7 100t
|
||||||
|
}.get(self._part, self._part)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _xray_device(self):
|
||||||
|
return {
|
||||||
|
"xc7a35ti": "xc7a35t",
|
||||||
|
"xc7a100ti": "xc7a100t",
|
||||||
|
}.get(self.device, self.device)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _xray_family(self):
|
||||||
|
return {
|
||||||
|
"xc7a": "artix7",
|
||||||
|
"xc7z": "zynq7",
|
||||||
|
}[self.device[:4]]
|
||||||
|
|
||||||
|
_xray_required_tools = [
|
||||||
|
"yosys",
|
||||||
|
"nextpnr-xilinx",
|
||||||
|
"fasm2frames",
|
||||||
|
"xc7frames2bit"
|
||||||
|
]
|
||||||
|
_xray_file_templates = {
|
||||||
|
**TemplatedPlatform.build_script_templates,
|
||||||
|
"build_{{name}}.sh": r"""
|
||||||
|
# {{autogenerated}}
|
||||||
|
set -e{{verbose("x")}}
|
||||||
|
[ -n "${{platform._deprecated_toolchain_env_var}}" ] && . "${{platform._deprecated_toolchain_env_var}}"
|
||||||
|
[ -n "${{platform._toolchain_env_var}}" ] && . "${{platform._toolchain_env_var}}"
|
||||||
|
: ${DB_DIR:=/usr/share/nextpnr/prjxray-db}
|
||||||
|
: ${CHIPDB_DIR:=/usr/share/nextpnr/xilinx-chipdb}
|
||||||
|
{{emit_commands("sh")}}
|
||||||
|
""",
|
||||||
|
"{{name}}.v": r"""
|
||||||
|
/* {{autogenerated}} */
|
||||||
|
{{emit_verilog()}}
|
||||||
|
""",
|
||||||
|
"{{name}}.debug.v": r"""
|
||||||
|
/* {{autogenerated}} */
|
||||||
|
{{emit_debug_verilog()}}
|
||||||
|
""",
|
||||||
|
"{{name}}.xdc": r"""
|
||||||
|
# {{autogenerated}}
|
||||||
|
{% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
|
||||||
|
{% for attr_name, attr_value in attrs.items() -%}
|
||||||
|
set_property {{attr_name}} {{attr_value}} [get_ports {{port_name|tcl_escape}}]
|
||||||
|
set_property LOC {{pin_name}} [get_ports {{port_name|tcl_escape}}]
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
""",
|
||||||
|
}
|
||||||
|
_xray_command_templates = [
|
||||||
|
r"""
|
||||||
|
{{invoke_tool("yosys")}}
|
||||||
|
-p "synth_xilinx -flatten -abc9 -nobram -arch xc7 -top {{name}}; write_json {{name}}.json"
|
||||||
|
{% for file in platform.iter_files(".v", ".sv", ".vhd", ".vhdl") -%} {{file}} {% endfor %}
|
||||||
|
{{name}}.v
|
||||||
|
""",
|
||||||
|
r"""
|
||||||
|
{{invoke_tool("nextpnr-xilinx")}}
|
||||||
|
--chipdb $CHIPDB_DIR/{{platform._xray_device}}.bin
|
||||||
|
--xdc {{name}}.xdc
|
||||||
|
--json {{name}}.json
|
||||||
|
--write {{name}}_routed.json
|
||||||
|
--fasm {{name}}.fasm
|
||||||
|
""",
|
||||||
|
r"""
|
||||||
|
{{invoke_tool("fasm2frames")}}
|
||||||
|
--part {{platform._xray_part}}
|
||||||
|
--db-root $DB_DIR/{{platform._xray_family}} {{name}}.fasm > {{name}}.frames
|
||||||
|
""",
|
||||||
|
r"""
|
||||||
|
{{invoke_tool("xc7frames2bit")}}
|
||||||
|
--part_file $DB_DIR/{{platform._xray_family}}/{{platform._xray_part}}/part.yaml
|
||||||
|
--part_name {{platform._xray_part}}
|
||||||
|
--frm_file {{name}}.frames
|
||||||
|
--output_file {{name}}.bit
|
||||||
|
""",
|
||||||
|
]
|
||||||
|
|
||||||
# Common logic
|
# Common logic
|
||||||
|
|
||||||
def __init__(self, *, toolchain=None):
|
def __init__(self, *, toolchain=None):
|
||||||
|
@ -499,7 +601,7 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
else:
|
else:
|
||||||
toolchain = "Vivado"
|
toolchain = "Vivado"
|
||||||
|
|
||||||
assert toolchain in ("Vivado", "ISE", "Symbiflow")
|
assert toolchain in ("Vivado", "ISE", "Symbiflow", "Xray")
|
||||||
if toolchain == "Vivado":
|
if toolchain == "Vivado":
|
||||||
if self.family in ISE_FAMILIES:
|
if self.family in ISE_FAMILIES:
|
||||||
raise ValueError("Family '{}' is not supported by the Vivado toolchain, please use ISE instead".format(self.family))
|
raise ValueError("Family '{}' is not supported by the Vivado toolchain, please use ISE instead".format(self.family))
|
||||||
|
@ -509,6 +611,10 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
elif toolchain == "Symbiflow":
|
elif toolchain == "Symbiflow":
|
||||||
if self.family != "series7":
|
if self.family != "series7":
|
||||||
raise ValueError("Family '{}' is not supported by the Symbiflow toolchain".format(self.family))
|
raise ValueError("Family '{}' is not supported by the Symbiflow toolchain".format(self.family))
|
||||||
|
elif toolchain == "Xray":
|
||||||
|
if self.family != "series7":
|
||||||
|
raise ValueError("Family '{}' is not supported by the yosys nextpnr toolchain".format(self.family))
|
||||||
|
|
||||||
self.toolchain = toolchain
|
self.toolchain = toolchain
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -519,6 +625,8 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
return self._ise_required_tools
|
return self._ise_required_tools
|
||||||
if self.toolchain == "Symbiflow":
|
if self.toolchain == "Symbiflow":
|
||||||
return self._symbiflow_required_tools
|
return self._symbiflow_required_tools
|
||||||
|
if self.toolchain == "Xray":
|
||||||
|
return self._xray_required_tools
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -529,6 +637,8 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
return self._ise_file_templates
|
return self._ise_file_templates
|
||||||
if self.toolchain == "Symbiflow":
|
if self.toolchain == "Symbiflow":
|
||||||
return self._symbiflow_file_templates
|
return self._symbiflow_file_templates
|
||||||
|
if self.toolchain == "Xray":
|
||||||
|
return self._xray_file_templates
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -539,6 +649,8 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
return self._ise_command_templates
|
return self._ise_command_templates
|
||||||
if self.toolchain == "Symbiflow":
|
if self.toolchain == "Symbiflow":
|
||||||
return self._symbiflow_command_templates
|
return self._symbiflow_command_templates
|
||||||
|
if self.toolchain == "Xray":
|
||||||
|
return self._xray_command_templates
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
def create_missing_domain(self, name):
|
def create_missing_domain(self, name):
|
||||||
|
@ -561,7 +673,7 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
"ultrascaleplus": "STARTUPE3",
|
"ultrascaleplus": "STARTUPE3",
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.family not in STARTUP_PRIMITIVE or self.toolchain == "Symbiflow":
|
if self.family not in STARTUP_PRIMITIVE or not self.vendor_toolchain:
|
||||||
# Spartan 3 and before lacks a STARTUP primitive with EOS output; use a simple ResetSynchronizer
|
# Spartan 3 and before lacks a STARTUP primitive with EOS output; use a simple ResetSynchronizer
|
||||||
# in that case, as is the default.
|
# in that case, as is the default.
|
||||||
# Symbiflow does not support the STARTUPE2 primitive.
|
# Symbiflow does not support the STARTUPE2 primitive.
|
||||||
|
@ -905,7 +1017,7 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
valid_xdrs=self._get_valid_xdrs(), valid_attrs=True)
|
valid_xdrs=self._get_valid_xdrs(), valid_attrs=True)
|
||||||
m = Module()
|
m = Module()
|
||||||
i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD"), o_invert=invert)
|
i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD"), o_invert=invert)
|
||||||
if self.toolchain != "Symbiflow":
|
if self.vendor_toolchain:
|
||||||
for bit in range(pin.width):
|
for bit in range(pin.width):
|
||||||
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUF",
|
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUF",
|
||||||
i_I=o[bit],
|
i_I=o[bit],
|
||||||
|
@ -916,7 +1028,7 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
return m
|
return m
|
||||||
|
|
||||||
def get_tristate(self, pin, port, attrs, invert):
|
def get_tristate(self, pin, port, attrs, invert):
|
||||||
if self.toolchain == "Symbiflow":
|
if not self.vendor_toolchain:
|
||||||
return super().get_tristate(pin, port, attrs, invert)
|
return super().get_tristate(pin, port, attrs, invert)
|
||||||
|
|
||||||
self._check_feature("single-ended tristate", pin, attrs,
|
self._check_feature("single-ended tristate", pin, attrs,
|
||||||
|
@ -932,7 +1044,7 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
return m
|
return m
|
||||||
|
|
||||||
def get_input_output(self, pin, port, attrs, invert):
|
def get_input_output(self, pin, port, attrs, invert):
|
||||||
if self.toolchain == "Symbiflow":
|
if not self.vendor_toolchain:
|
||||||
return super().get_input_output(pin, port, attrs, invert)
|
return super().get_input_output(pin, port, attrs, invert)
|
||||||
|
|
||||||
self._check_feature("single-ended input/output", pin, attrs,
|
self._check_feature("single-ended input/output", pin, attrs,
|
||||||
|
@ -949,7 +1061,7 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
return m
|
return m
|
||||||
|
|
||||||
def get_diff_input(self, pin, port, attrs, invert):
|
def get_diff_input(self, pin, port, attrs, invert):
|
||||||
if self.toolchain == "Symbiflow":
|
if not self.vendor_toolchain:
|
||||||
return super().get_diff_input(pin, port, attrs, invert)
|
return super().get_diff_input(pin, port, attrs, invert)
|
||||||
|
|
||||||
self._check_feature("differential input", pin, attrs,
|
self._check_feature("differential input", pin, attrs,
|
||||||
|
@ -964,7 +1076,7 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
return m
|
return m
|
||||||
|
|
||||||
def get_diff_output(self, pin, port, attrs, invert):
|
def get_diff_output(self, pin, port, attrs, invert):
|
||||||
if self.toolchain == "Symbiflow":
|
if not self.vendor_toolchain:
|
||||||
return super().get_diff_output(pin, port, attrs, invert)
|
return super().get_diff_output(pin, port, attrs, invert)
|
||||||
|
|
||||||
self._check_feature("differential output", pin, attrs,
|
self._check_feature("differential output", pin, attrs,
|
||||||
|
@ -979,7 +1091,7 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
return m
|
return m
|
||||||
|
|
||||||
def get_diff_tristate(self, pin, port, attrs, invert):
|
def get_diff_tristate(self, pin, port, attrs, invert):
|
||||||
if self.toolchain == "Symbiflow":
|
if not self.vendor_toolchain:
|
||||||
return super().get_diff_tristate(pin, port, attrs, invert)
|
return super().get_diff_tristate(pin, port, attrs, invert)
|
||||||
|
|
||||||
self._check_feature("differential tristate", pin, attrs,
|
self._check_feature("differential tristate", pin, attrs,
|
||||||
|
@ -995,7 +1107,7 @@ class XilinxPlatform(TemplatedPlatform):
|
||||||
return m
|
return m
|
||||||
|
|
||||||
def get_diff_input_output(self, pin, port, attrs, invert):
|
def get_diff_input_output(self, pin, port, attrs, invert):
|
||||||
if self.toolchain == "Symbiflow":
|
if not self.vendor_toolchain:
|
||||||
return super().get_diff_input_output(pin, port, attrs, invert)
|
return super().get_diff_input_output(pin, port, attrs, invert)
|
||||||
|
|
||||||
self._check_feature("differential input/output", pin, attrs,
|
self._check_feature("differential input/output", pin, attrs,
|
||||||
|
|
Loading…
Reference in a new issue