Available overrides:
* ``add_constraints``: inserts commands in XDC file.
+
+ .. rubric:: yosys_nextpnr toolchain
+
+ Required tools:
+ * ``yosys``
+ * ``nextpnr-xilinx``
+ * ``fasm2frames``
+ * ``xc7frames2bit``
+
+ The environment is populated by running the script specified in the environment variable
+ ``NMIGEN_ENV_ysosys_nextpnr``, if present.
+
+ Available overrides:
+ * ``nextpnr_dir``: overrides toolchain db path.
"""
toolchain = None # selected when creating platform
"""
]
+ # Yosys NextPNR prjxray templates
+
+ _yosys_nextpnr_part_map = {
+ "xc7a35ticsg324-1L": "xc7a35tcsg324-1", # Arty-A7 35t
+ "xc7a100ticsg324-1L": "xc7a100tcsg324-1", # Arty-A7 100t
+
+ }
+
+ _yosys_nextpnr_device = {
+ "xc7a35ti": "xc7a35t",
+ "xc7a100ti": "xc7a100t",
+ }
+
+ _yosys_nextpnr_family = {
+ "xc7a": "artix7",
+ "xc7z": "zynq7",
+ }
+
+ _yosys_nextpnr_required_tools = [
+ "yosys",
+ "nextpnr-xilinx",
+ "fasm2frames",
+ "xc7frames2bit"
+ ]
+ _yosys_nextpnr_file_templates = {
+ **TemplatedPlatform.build_script_templates,
+ "{{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 %}
+ """,
+ }
+ _yosys_nextpnr_command_templates = [
+ r"""
+ DB_DIR={{get_override("nextpnr_dir")|default("/usr/share/nextpnr")}}/prjxray-db
+ """,
+ r"""
+ CHIPDB_DIR={{get_override("nextpnr_dir")|default("/usr/share/nextpnr")}}/xilinx-chipdb
+ """,
+ r"""
+ PART={{platform._yosys_nextpnr_part_map.get(platform._part, platform._part)}}
+ """,
+ 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._yosys_nextpnr_device.get(platform.device, platform.device)}}.bin
+ --xdc {{name}}.xdc
+ --json {{name}}.json
+ --write {{name}}_routed.json
+ --fasm {{name}}.fasm
+ """,
+ r"""
+ {{invoke_tool("fasm2frames")}}
+ --part $PART
+ --db-root $DB_DIR/{{platform._yosys_nextpnr_family[platform.device[:4]]}} {{name}}.fasm > {{name}}.frames
+ """,
+ r"""
+ {{invoke_tool("xc7frames2bit")}}
+ --part_file $DB_DIR/{{platform._yosys_nextpnr_family[platform.device[:4]]}}/$PART/part.yaml
+ --part_name $PART
+ --frm_file {{name}}.frames
+ --output_file {{name}}.bit
+ """,
+ ]
+
# Common logic
def __init__(self, *, toolchain=None):
else:
toolchain = "Vivado"
- assert toolchain in ("Vivado", "ISE", "Symbiflow")
+ assert toolchain in ("Vivado", "ISE", "Symbiflow", "yosys_nextpnr")
+ self.oss_toolchain = False
if toolchain == "Vivado":
if self.family in ISE_FAMILIES:
raise ValueError("Family '{}' is not supported by the Vivado toolchain, please use ISE instead".format(self.family))
if self.family not in ISE_FAMILIES and self.family != "series7":
raise ValueError("Family '{}' is not supported by the ISE toolchain, please use Vivado instead".format(self.family))
elif toolchain == "Symbiflow":
+ self.oss_toolchain = True
if self.family != "series7":
raise ValueError("Family '{}' is not supported by the Symbiflow toolchain".format(self.family))
+ elif toolchain == "yosys_nextpnr":
+ self.oss_toolchain = True
+ if self.family != "series7":
+ raise ValueError("Family '{}' is not supported by the yosys nextpnr toolchain".format(self.family))
+
self.toolchain = toolchain
@property
return self._ise_required_tools
if self.toolchain == "Symbiflow":
return self._symbiflow_required_tools
+ if self.toolchain == "yosys_nextpnr":
+ return self._yosys_nextpnr_required_tools
assert False
@property
return self._ise_file_templates
if self.toolchain == "Symbiflow":
return self._symbiflow_file_templates
+ if self.toolchain == "yosys_nextpnr":
+ return self._yosys_nextpnr_file_templates
assert False
@property
return self._ise_command_templates
if self.toolchain == "Symbiflow":
return self._symbiflow_command_templates
+ if self.toolchain == "yosys_nextpnr":
+ return self._yosys_nextpnr_command_templates
assert False
def create_missing_domain(self, name):
"ultrascaleplus": "STARTUPE3",
}
- if self.family not in STARTUP_PRIMITIVE or self.toolchain == "Symbiflow":
+ if self.family not in STARTUP_PRIMITIVE or self.oss_toolchain:
# Spartan 3 and before lacks a STARTUP primitive with EOS output; use a simple ResetSynchronizer
# in that case, as is the default.
# Symbiflow does not support the STARTUPE2 primitive.
valid_xdrs=self._get_valid_xdrs(), valid_attrs=True)
m = Module()
i, o, t = self._get_xdr_buffer(m, pin, attrs.get("IOSTANDARD"), o_invert=invert)
- if self.toolchain != "Symbiflow":
+ if not self.oss_toolchain:
for bit in range(pin.width):
m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUF",
i_I=o[bit],
return m
def get_tristate(self, pin, port, attrs, invert):
- if self.toolchain == "Symbiflow":
+ if self.oss_toolchain:
return super().get_tristate(pin, port, attrs, invert)
self._check_feature("single-ended tristate", pin, attrs,
return m
def get_input_output(self, pin, port, attrs, invert):
- if self.toolchain == "Symbiflow":
+ if self.oss_toolchain:
return super().get_input_output(pin, port, attrs, invert)
self._check_feature("single-ended input/output", pin, attrs,
return m
def get_diff_input(self, pin, port, attrs, invert):
- if self.toolchain == "Symbiflow":
+ if self.oss_toolchain:
return super().get_diff_input(pin, port, attrs, invert)
self._check_feature("differential input", pin, attrs,
return m
def get_diff_output(self, pin, port, attrs, invert):
- if self.toolchain == "Symbiflow":
+ if self.toolchain == ["Symbiflow", "yosys_nextpnr"]:
return super().get_diff_output(pin, port, attrs, invert)
self._check_feature("differential output", pin, attrs,
return m
def get_diff_tristate(self, pin, port, attrs, invert):
- if self.toolchain == "Symbiflow":
+ if self.oss_toolchain:
return super().get_diff_tristate(pin, port, attrs, invert)
self._check_feature("differential tristate", pin, attrs,
return m
def get_diff_input_output(self, pin, port, attrs, invert):
- if self.toolchain == "Symbiflow":
+ if self.oss_toolchain:
return super().get_diff_input_output(pin, port, attrs, invert)
self._check_feature("differential input/output", pin, attrs,