From a833193cd3eb6c24190256f203ca4c9868366771 Mon Sep 17 00:00:00 2001 From: Hans Baier Date: Mon, 23 Oct 2023 11:38:31 +0700 Subject: [PATCH 1/4] Xilinx: Initial openxc7 toolchain support --- litex/build/xilinx/openxc7.py | 146 ++++++++++++++++++++++++++++ litex/build/xilinx/platform.py | 5 +- litex/build/xilinx/yosys_nextpnr.py | 19 ++-- 3 files changed, 157 insertions(+), 13 deletions(-) create mode 100644 litex/build/xilinx/openxc7.py diff --git a/litex/build/xilinx/openxc7.py b/litex/build/xilinx/openxc7.py new file mode 100644 index 000000000..33bd242f6 --- /dev/null +++ b/litex/build/xilinx/openxc7.py @@ -0,0 +1,146 @@ +# +# This file is part of LiteX. +# +# Copyright (c) 2020 Antmicro +# Copyright (c) 2020 Florent Kermarrec +# Copyright (c) 2022 Victor Suarez Rovere +# Copyright (c) 2023 Hans Baier +# SPDX-License-Identifier: BSD-2-Clause + +import os +import subprocess +import sys +import math +from typing import NamedTuple, Union, List +import re +from shutil import which + +from migen.fhdl.structure import _Fragment, wrap, Constant +from migen.fhdl.specials import Instance + +from litex.build.yosys_nextpnr_toolchain import YosysNextPNRToolchain +from litex.build.generic_platform import * +from litex.build.xilinx.vivado import _xdc_separator, _format_xdc, _build_xdc +from litex.build import tools +from litex.build.xilinx import common + + +def _unwrap(value): + return value.value if isinstance(value, Constant) else value + + +# XilinxOpenXC7Toolchain ---------------------------------------------------------------------------- + +class XilinxOpenXC7Toolchain(YosysNextPNRToolchain): + attr_translate = {} + + synth_fmt = "json" + constr_fmt = "xdc" + pnr_fmt = "fasm" + packer_cmd = "xc7frames2bit" + + def __init__(self): + super().__init__() + self.dbpart = None + self.family = "xilinx" + self._xc7family = None + self._clock_constraints = "" + self.additional_xdc_commands = [] + self._pre_packer_cmd = ["fasm2frames"] + self._synth_opts = "-flatten -abc9 -arch xc7 " + + xc7_family_map = { + "a": "artix7", + "k": "kintex7", + "s": "spartan7", + "z": "zynq7" + } + + def _check_properties(self): + pattern = re.compile("xc7([aksz])([0-9]+)(.*)-([0-9])") + g = pattern.search(self.platform.device) + if not self.dbpart: + self.dbpart = f"xc7{g.group(1)}{g.group(2)}{g.group(3)}" + + if not self._xc7family: + fam = g.group(1) + self._xc7family = self.xc7_family_map[fam] + + def build_timing_constraints(self, vns): + xdc = [] + xdc.append(_xdc_separator("Clock constraints")) + + for clk, [period, name] in sorted(self.clocks.items(), key=lambda x: x[0].duid): + clk_sig = self._vns.get_name(clk) + if name is None: + name = clk_sig + xdc.append( + "create_clock -name {name} -period " + str(period) + + " [get_ports {clk}]".format(name=name, clk=clk_sig)) + + # generate sdc + xdc += self.additional_xdc_commands + self._clock_constraints = "\n".join(xdc) + + def build_io_constraints(self): + tools.write_to_file(self._build_name + ".xdc", _build_xdc(self.named_sc, self.named_pc) + self._clock_constraints) + return (self._build_name + ".xdc", "XDC") + + def _fix_instance(self, instance): + pass + + def finalize(self): + # toolchain-specific fixes + for instance in self.fragment.specials: + if isinstance(instance, Instance): + self._fix_instance(instance) + + chipdb_dir = os.environ.get('CHIPDB') + if chipdb_dir is None or chipdb_dir == "": + print("Error: please specify the directory, where you store your nextpnr-xilinx chipdb files in the environment variable CHIPDB (may be empty)") + exit(1) + + # pnr options + self._pnr_opts += "--chipdb {chipdb_dir}/{dbpart}.bin --write {top}_routed.json".format( + top = self._build_name, + chipdb_dir = chipdb_dir, + dbpart = self.dbpart, + ) + + prjxray_db_dir = os.environ.get('PRJXRAY_DB_DIR') + if prjxray_db_dir is None or prjxray_db_dir == "": + prjxray_db_dir = '/snap/openxc7/current/opt/nextpnr-xilinx/external/prjxray-db/' + + if not os.path.isdir(prjxray_db_dir): + print(f"{prjxray_db_dir} does not exist on your system. \n" + \ + "Do you have the openXC7 toolchain installed? \n" + \ + "You can get it here: https://github.com/openXC7/toolchain-installer") + exit(1) + + # pre packer options + self._pre_packer_opts["fasm2frames"] = "--part {part} --db-root {db_root} {top}.fasm > {top}.frames".format( + part = self.platform.device, + db_root = os.path.join(prjxray_db_dir, self._xc7family), + top = self._build_name + ) + # packer options + self._packer_opts += "--part_file {db_dir}/{part}/part.yaml --part_name {part} --frm_file {top}.frames --output_file {top}.bit".format( + db_dir = os.path.join(prjxray_db_dir, self._xc7family), + part = self.platform.device, + top = self._build_name + ) + + return YosysNextPNRToolchain.finalize(self) + + def build(self, platform, fragment, + enable_xpm = False, + **kwargs): + + self.platform = platform + self._check_properties() + + return YosysNextPNRToolchain.build(self, platform, fragment, **kwargs) + + def add_false_path_constraint(self, platform, from_, to): + # FIXME: false path constraints are currently not supported by the openXC7 toolchain + return diff --git a/litex/build/xilinx/platform.py b/litex/build/xilinx/platform.py index cfe1b2f94..3fec9e17c 100644 --- a/litex/build/xilinx/platform.py +++ b/litex/build/xilinx/platform.py @@ -21,7 +21,7 @@ class XilinxPlatform(GenericPlatform): _supported_toolchains = { "spartan6" : ["ise"], - "7series" : ["vivado", "f4pga", "yosys+nextpnr"], + "7series" : ["vivado", "f4pga", "yosys+nextpnr", "openxc7"], "ultrascale" : ["vivado"], "ultrascale+" : ["vivado"], } @@ -42,6 +42,9 @@ class XilinxPlatform(GenericPlatform): elif toolchain == "yosys+nextpnr": from litex.build.xilinx import yosys_nextpnr self.toolchain = yosys_nextpnr.XilinxYosysNextpnrToolchain() + elif toolchain == "openxc7": + from litex.build.xilinx import openxc7 + self.toolchain = openxc7.XilinxOpenXC7Toolchain() else: raise ValueError(f"Unknown toolchain {toolchain}") diff --git a/litex/build/xilinx/yosys_nextpnr.py b/litex/build/xilinx/yosys_nextpnr.py index 264fc3d11..b8ba75e42 100644 --- a/litex/build/xilinx/yosys_nextpnr.py +++ b/litex/build/xilinx/yosys_nextpnr.py @@ -45,7 +45,7 @@ class XilinxYosysNextpnrToolchain(YosysNextPNRToolchain): self.bitstream_device = None self._partname = None self._pre_packer_cmd = ["fasm2frames.py"] - self._synth_opts = "-flatten -abc9 -nobram -arch xc7 " + self._synth_opts = "-flatten -abc9 -arch xc7 " def _check_properties(self): if not self.f4pga_device: @@ -64,12 +64,14 @@ class XilinxYosysNextpnrToolchain(YosysNextPNRToolchain): # bitstream_device points to a directory in prjxray database # available bitstream_devices: artix7, kintex7, zynq7 self.bitstream_device = { - "xc7a": "artix7", # xc7a35t, xc7a50t, xc7a100t, xc7a200t - "xc7z": "zynq7", # xc7z010, xc7z020 + "xc7s": "spartan7", + "xc7a": "artix7", + "xc7k": "kintex7", + "xc7z": "zynq7", }[self.platform.device[:4]] except KeyError: raise ValueError(f"Unsupported device: {self.platform.device}") - # FIXME: prjxray-db doesn't have xc7a35ticsg324-1L - use closest replacement + self._partname = { "xc7a35ticsg324-1L" : "xc7a35tcsg324-1", "xc7a100tcsg324-1" : "xc7a100tcsg324-1", @@ -132,12 +134,5 @@ class XilinxYosysNextpnrToolchain(YosysNextPNRToolchain): return YosysNextPNRToolchain.build(self, platform, fragment, **kwargs) def add_false_path_constraint(self, platform, from_, to): - # FIXME: false path constraints are currently not supported by the F4PGA toolchain + # FIXME: false path constraints are currently not supported by nextpnr-xilinx return - -def f4pga_build_args(parser): - pass - - -def f4pga_build_argdict(args): - return dict() From 468375b119711e601fcfe1324b48fa9c34db7a7f Mon Sep 17 00:00:00 2001 From: Hans Baier Date: Tue, 24 Oct 2023 08:39:01 +0700 Subject: [PATCH 2/4] xilinx platform: add more ignored constraints for yosys+nextpnr --- litex/build/xilinx/openxc7.py | 146 ---------------------------- litex/build/xilinx/platform.py | 13 ++- litex/build/xilinx/yosys_nextpnr.py | 122 +++++++++++++---------- 3 files changed, 77 insertions(+), 204 deletions(-) delete mode 100644 litex/build/xilinx/openxc7.py diff --git a/litex/build/xilinx/openxc7.py b/litex/build/xilinx/openxc7.py deleted file mode 100644 index 33bd242f6..000000000 --- a/litex/build/xilinx/openxc7.py +++ /dev/null @@ -1,146 +0,0 @@ -# -# This file is part of LiteX. -# -# Copyright (c) 2020 Antmicro -# Copyright (c) 2020 Florent Kermarrec -# Copyright (c) 2022 Victor Suarez Rovere -# Copyright (c) 2023 Hans Baier -# SPDX-License-Identifier: BSD-2-Clause - -import os -import subprocess -import sys -import math -from typing import NamedTuple, Union, List -import re -from shutil import which - -from migen.fhdl.structure import _Fragment, wrap, Constant -from migen.fhdl.specials import Instance - -from litex.build.yosys_nextpnr_toolchain import YosysNextPNRToolchain -from litex.build.generic_platform import * -from litex.build.xilinx.vivado import _xdc_separator, _format_xdc, _build_xdc -from litex.build import tools -from litex.build.xilinx import common - - -def _unwrap(value): - return value.value if isinstance(value, Constant) else value - - -# XilinxOpenXC7Toolchain ---------------------------------------------------------------------------- - -class XilinxOpenXC7Toolchain(YosysNextPNRToolchain): - attr_translate = {} - - synth_fmt = "json" - constr_fmt = "xdc" - pnr_fmt = "fasm" - packer_cmd = "xc7frames2bit" - - def __init__(self): - super().__init__() - self.dbpart = None - self.family = "xilinx" - self._xc7family = None - self._clock_constraints = "" - self.additional_xdc_commands = [] - self._pre_packer_cmd = ["fasm2frames"] - self._synth_opts = "-flatten -abc9 -arch xc7 " - - xc7_family_map = { - "a": "artix7", - "k": "kintex7", - "s": "spartan7", - "z": "zynq7" - } - - def _check_properties(self): - pattern = re.compile("xc7([aksz])([0-9]+)(.*)-([0-9])") - g = pattern.search(self.platform.device) - if not self.dbpart: - self.dbpart = f"xc7{g.group(1)}{g.group(2)}{g.group(3)}" - - if not self._xc7family: - fam = g.group(1) - self._xc7family = self.xc7_family_map[fam] - - def build_timing_constraints(self, vns): - xdc = [] - xdc.append(_xdc_separator("Clock constraints")) - - for clk, [period, name] in sorted(self.clocks.items(), key=lambda x: x[0].duid): - clk_sig = self._vns.get_name(clk) - if name is None: - name = clk_sig - xdc.append( - "create_clock -name {name} -period " + str(period) + - " [get_ports {clk}]".format(name=name, clk=clk_sig)) - - # generate sdc - xdc += self.additional_xdc_commands - self._clock_constraints = "\n".join(xdc) - - def build_io_constraints(self): - tools.write_to_file(self._build_name + ".xdc", _build_xdc(self.named_sc, self.named_pc) + self._clock_constraints) - return (self._build_name + ".xdc", "XDC") - - def _fix_instance(self, instance): - pass - - def finalize(self): - # toolchain-specific fixes - for instance in self.fragment.specials: - if isinstance(instance, Instance): - self._fix_instance(instance) - - chipdb_dir = os.environ.get('CHIPDB') - if chipdb_dir is None or chipdb_dir == "": - print("Error: please specify the directory, where you store your nextpnr-xilinx chipdb files in the environment variable CHIPDB (may be empty)") - exit(1) - - # pnr options - self._pnr_opts += "--chipdb {chipdb_dir}/{dbpart}.bin --write {top}_routed.json".format( - top = self._build_name, - chipdb_dir = chipdb_dir, - dbpart = self.dbpart, - ) - - prjxray_db_dir = os.environ.get('PRJXRAY_DB_DIR') - if prjxray_db_dir is None or prjxray_db_dir == "": - prjxray_db_dir = '/snap/openxc7/current/opt/nextpnr-xilinx/external/prjxray-db/' - - if not os.path.isdir(prjxray_db_dir): - print(f"{prjxray_db_dir} does not exist on your system. \n" + \ - "Do you have the openXC7 toolchain installed? \n" + \ - "You can get it here: https://github.com/openXC7/toolchain-installer") - exit(1) - - # pre packer options - self._pre_packer_opts["fasm2frames"] = "--part {part} --db-root {db_root} {top}.fasm > {top}.frames".format( - part = self.platform.device, - db_root = os.path.join(prjxray_db_dir, self._xc7family), - top = self._build_name - ) - # packer options - self._packer_opts += "--part_file {db_dir}/{part}/part.yaml --part_name {part} --frm_file {top}.frames --output_file {top}.bit".format( - db_dir = os.path.join(prjxray_db_dir, self._xc7family), - part = self.platform.device, - top = self._build_name - ) - - return YosysNextPNRToolchain.finalize(self) - - def build(self, platform, fragment, - enable_xpm = False, - **kwargs): - - self.platform = platform - self._check_properties() - - return YosysNextPNRToolchain.build(self, platform, fragment, **kwargs) - - def add_false_path_constraint(self, platform, from_, to): - # FIXME: false path constraints are currently not supported by the openXC7 toolchain - return diff --git a/litex/build/xilinx/platform.py b/litex/build/xilinx/platform.py index 3fec9e17c..b188e36dd 100644 --- a/litex/build/xilinx/platform.py +++ b/litex/build/xilinx/platform.py @@ -39,12 +39,9 @@ class XilinxPlatform(GenericPlatform): elif toolchain == "symbiflow" or toolchain == "f4pga": from litex.build.xilinx import f4pga self.toolchain = f4pga.F4PGAToolchain() - elif toolchain == "yosys+nextpnr": + elif toolchain in ["yosys+nextpnr", "openxc7"]: from litex.build.xilinx import yosys_nextpnr - self.toolchain = yosys_nextpnr.XilinxYosysNextpnrToolchain() - elif toolchain == "openxc7": - from litex.build.xilinx import openxc7 - self.toolchain = openxc7.XilinxOpenXC7Toolchain() + self.toolchain = yosys_nextpnr.XilinxYosysNextpnrToolchain(toolchain) else: raise ValueError(f"Unknown toolchain {toolchain}") @@ -62,6 +59,12 @@ class XilinxPlatform(GenericPlatform): if "set_property INTERNAL_VREF" in command: print("WARNING: INTERNAL_VREF constraint removed since not yet supported by yosys-nextpnr flow.") skip = True + if "set_property CFGBVS" in command: + print("WARNING: CFGBVS constraint removed since not yet supported by yosys-nextpnr flow.") + skip = True + if "set_property CONFIG_VOLTAGE" in command: + print("WARNING: CONFIG_VOLTAGE constraint removed since not yet supported by yosys-nextpnr flow.") + skip = True if not skip: GenericPlatform.add_platform_command(self, command, **signals) diff --git a/litex/build/xilinx/yosys_nextpnr.py b/litex/build/xilinx/yosys_nextpnr.py index b8ba75e42..fde84df37 100644 --- a/litex/build/xilinx/yosys_nextpnr.py +++ b/litex/build/xilinx/yosys_nextpnr.py @@ -4,6 +4,7 @@ # Copyright (c) 2020 Antmicro # Copyright (c) 2020 Florent Kermarrec # Copyright (c) 2022 Victor Suarez Rovere +# Copyright (c) 2023 Hans Baier # SPDX-License-Identifier: BSD-2-Clause import os @@ -39,57 +40,52 @@ class XilinxYosysNextpnrToolchain(YosysNextPNRToolchain): pnr_fmt = "fasm" packer_cmd = "xc7frames2bit" - def __init__(self): + def __init__(self, toolchain): + assert toolchain in ["yosys+nextpnr", "openxc7"] + self.is_openxc7 = toolchain == "openxc7" super().__init__() - self.f4pga_device = None - self.bitstream_device = None - self._partname = None - self._pre_packer_cmd = ["fasm2frames.py"] + self.dbpart = None + self._xc7family = None + self._clock_constraints = "" + self.additional_xdc_commands = [] + self._pre_packer_cmd = ["fasm2frames" if self.is_openxc7 else "fasm2frames.py"] self._synth_opts = "-flatten -abc9 -arch xc7 " - def _check_properties(self): - if not self.f4pga_device: - try: - self.f4pga_device = { - # FIXME: fine for now since only a few devices are supported, do more clever device re-mapping. - "xc7a35ticsg324-1L" : "xc7a35t", - "xc7a100tcsg324-1" : "xc7a100t", - "xc7z010clg400-1" : "xc7z010", - "xc7z020clg400-1" : "xc7z020", - }[self.platform.device] - except KeyError: - raise ValueError(f"f4pga_device is not specified") - if not self.bitstream_device: - try: - # bitstream_device points to a directory in prjxray database - # available bitstream_devices: artix7, kintex7, zynq7 - self.bitstream_device = { - "xc7s": "spartan7", - "xc7a": "artix7", - "xc7k": "kintex7", - "xc7z": "zynq7", - }[self.platform.device[:4]] - except KeyError: - raise ValueError(f"Unsupported device: {self.platform.device}") + xc7_family_map = { + "a": "artix7", + "k": "kintex7", + "s": "spartan7", + "z": "zynq7" + } - self._partname = { - "xc7a35ticsg324-1L" : "xc7a35tcsg324-1", - "xc7a100tcsg324-1" : "xc7a100tcsg324-1", - "xc7a200t-sbg484-1" : "xc7a200tsbg484-1", - "xc7z010clg400-1" : "xc7z010clg400-1", - "xc7z020clg400-1" : "xc7z020clg400-1", - }.get(self.platform.device, self.platform.device) + def _check_properties(self): + pattern = re.compile("xc7([aksz])([0-9]+)(.*)-([0-9])") + g = pattern.search(self.platform.device) + if not self.dbpart: + self.dbpart = f"xc7{g.group(1)}{g.group(2)}{g.group(3)}" + + if not self._xc7family: + fam = g.group(1) + self._xc7family = self.xc7_family_map[fam] def build_timing_constraints(self, vns): - self.platform.add_platform_command(_xdc_separator("Clock constraints")) - #for clk, period in sorted(self.clocks.items(), key=lambda x: x[0].duid): - # platform.add_platform_command( - # "create_clock -period " + str(period) + - # " {clk}", clk=clk) - pass #clock constraints not supported + xdc = [] + xdc.append(_xdc_separator("Clock constraints")) + + for clk, [period, name] in sorted(self.clocks.items(), key=lambda x: x[0].duid): + clk_sig = self._vns.get_name(clk) + if name is None: + name = clk_sig + xdc.append( + "create_clock -name {name} -period " + str(period) + + " [get_ports {clk}]".format(name=name, clk=clk_sig)) + + # generate sdc + xdc += self.additional_xdc_commands + self._clock_constraints = "\n".join(xdc) def build_io_constraints(self): - tools.write_to_file(self._build_name + ".xdc", _build_xdc(self.named_sc, self.named_pc)) + tools.write_to_file(self._build_name + ".xdc", _build_xdc(self.named_sc, self.named_pc) + self._clock_constraints) return (self._build_name + ".xdc", "XDC") def _fix_instance(self, instance): @@ -101,23 +97,44 @@ class XilinxYosysNextpnrToolchain(YosysNextPNRToolchain): if isinstance(instance, Instance): self._fix_instance(instance) + if self.is_openxc7: + chipdb_dir = os.environ.get('CHIPDB') + if chipdb_dir is None or chipdb_dir == "": + print("Error: please specify the directory, where you store your nextpnr-xilinx chipdb files in the environment variable CHIPDB (may be empty)") + exit(1) + else: + chipdb_dir = "/usr/share/nextpnr/xilinx-chipdb" + # pnr options - self._pnr_opts += "--chipdb {chipdb_dir}/{device}.bin --write {top}_routed.json".format( + self._pnr_opts += "--chipdb {chipdb_dir}/{dbpart}.bin --write {top}_routed.json".format( top = self._build_name, - chipdb_dir = "/usr/share/nextpnr/xilinx-chipdb", - device = self.f4pga_device, + chipdb_dir = chipdb_dir, + dbpart = self.dbpart, ) + if self.is_openxc7: + prjxray_db_dir = os.environ.get('PRJXRAY_DB_DIR') + if prjxray_db_dir is None or prjxray_db_dir == "": + prjxray_db_dir = '/snap/openxc7/current/opt/nextpnr-xilinx/external/prjxray-db/' + else: + prjxray_db_dir = f"/usr/share/nextpnr/prjxray-db/ + + if not os.path.isdir(prjxray_db_dir): + print(f"{prjxray_db_dir} does not exist on your system. \n" + \ + "Do you have the openXC7 toolchain installed? \n" + \ + "You can get it here: https://github.com/openXC7/toolchain-installer") + exit(1) + # pre packer options - self._pre_packer_opts["fasm2frames.py"] = "--part {part} --db-root {db_root} {top}.fasm > {top}.frames".format( - part = self._partname, - db_root = f"/usr/share/nextpnr/prjxray-db/{self.bitstream_device}", + self._pre_packer_opts[self._pre_packer_cmd] = "--part {part} --db-root {db_root} {top}.fasm > {top}.frames".format( + part = self.platform.device, + db_root = os.path.join(prjxray_db_dir, self._xc7family), top = self._build_name ) # packer options self._packer_opts += "--part_file {db_dir}/{part}/part.yaml --part_name {part} --frm_file {top}.frames --output_file {top}.bit".format( - db_dir = f"/usr/share/nextpnr/prjxray-db/{self.bitstream_device}", - part = self._partname, + db_dir = os.path.join(prjxray_db_dir, self._xc7family), + part = self.platform.device, top = self._build_name ) @@ -127,12 +144,11 @@ class XilinxYosysNextpnrToolchain(YosysNextPNRToolchain): enable_xpm = False, **kwargs): - #FIXME self.platform = platform self._check_properties() return YosysNextPNRToolchain.build(self, platform, fragment, **kwargs) def add_false_path_constraint(self, platform, from_, to): - # FIXME: false path constraints are currently not supported by nextpnr-xilinx + # FIXME: false path constraints are currently not supported by the toolchain return From 8d0f08a57e66e0d2390ce404802de614244625ac Mon Sep 17 00:00:00 2001 From: Hans Baier Date: Tue, 24 Oct 2023 08:49:46 +0700 Subject: [PATCH 3/4] fix syntax errors --- litex/build/xilinx/yosys_nextpnr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litex/build/xilinx/yosys_nextpnr.py b/litex/build/xilinx/yosys_nextpnr.py index fde84df37..99cfb28a7 100644 --- a/litex/build/xilinx/yosys_nextpnr.py +++ b/litex/build/xilinx/yosys_nextpnr.py @@ -117,7 +117,7 @@ class XilinxYosysNextpnrToolchain(YosysNextPNRToolchain): if prjxray_db_dir is None or prjxray_db_dir == "": prjxray_db_dir = '/snap/openxc7/current/opt/nextpnr-xilinx/external/prjxray-db/' else: - prjxray_db_dir = f"/usr/share/nextpnr/prjxray-db/ + prjxray_db_dir = "/usr/share/nextpnr/prjxray-db/" if not os.path.isdir(prjxray_db_dir): print(f"{prjxray_db_dir} does not exist on your system. \n" + \ @@ -126,7 +126,7 @@ class XilinxYosysNextpnrToolchain(YosysNextPNRToolchain): exit(1) # pre packer options - self._pre_packer_opts[self._pre_packer_cmd] = "--part {part} --db-root {db_root} {top}.fasm > {top}.frames".format( + self._pre_packer_opts[self._pre_packer_cmd[0]] = "--part {part} --db-root {db_root} {top}.fasm > {top}.frames".format( part = self.platform.device, db_root = os.path.join(prjxray_db_dir, self._xc7family), top = self._build_name From f3f46e8cf10c7b1e72a6178a4d006890620d2eaf Mon Sep 17 00:00:00 2001 From: Hans Baier Date: Tue, 24 Oct 2023 12:01:35 +0700 Subject: [PATCH 4/4] openxc7 toolchain: auto generate chipdb, if missing --- litex/build/xilinx/yosys_nextpnr.py | 32 ++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/litex/build/xilinx/yosys_nextpnr.py b/litex/build/xilinx/yosys_nextpnr.py index 99cfb28a7..c8a017eb7 100644 --- a/litex/build/xilinx/yosys_nextpnr.py +++ b/litex/build/xilinx/yosys_nextpnr.py @@ -100,16 +100,38 @@ class XilinxYosysNextpnrToolchain(YosysNextPNRToolchain): if self.is_openxc7: chipdb_dir = os.environ.get('CHIPDB') if chipdb_dir is None or chipdb_dir == "": - print("Error: please specify the directory, where you store your nextpnr-xilinx chipdb files in the environment variable CHIPDB (may be empty)") + print("Error: please specify the directory, where you store your nextpnr-xilinx chipdb files in the environment variable CHIPDB (directory may be empty)") exit(1) else: chipdb_dir = "/usr/share/nextpnr/xilinx-chipdb" + chipdb = os.path.join(chipdb_dir, self.dbpart) + ".bin" + if not os.path.exists(chipdb): + if self.is_openxc7: + print(f"Chip database file '{chipdb}' not found, generating...") + pypy3 = os.environ.get('PYPY3') + if pypy3 is None or pypy3 == "": + pypy3 = which("pypy3") + if pypy3 is None: + pypy3 = "python3" + + nextpnr_xilinx_python_dir = os.environ.get('NEXTPNR_XILINX_PYTHON_DIR') + if nextpnr_xilinx_python_dir is None or nextpnr_xilinx_python_dir == "": + nextpnr_xilinx_python_dir = "/snap/openxc7/current/opt/nextpnr-xilinx/python" + bba = self.dbpart + ".bba" + bbaexport = [pypy3, os.path.join(nextpnr_xilinx_python_dir, "bbaexport.py"), "--device", self.platform.device, "--bba", bba] + print(str(bbaexport)) + subprocess.run(bbaexport) + subprocess.run(["bbasm", "-l", bba, chipdb]) + os.remove(bba) + else: + print("Chip database file '{chipdb}' not found. Please check your toolchain installation!") + exit(1) + # pnr options - self._pnr_opts += "--chipdb {chipdb_dir}/{dbpart}.bin --write {top}_routed.json".format( - top = self._build_name, - chipdb_dir = chipdb_dir, - dbpart = self.dbpart, + self._pnr_opts += "--chipdb {chipdb} --write {top}_routed.json".format( + top = self._build_name, + chipdb = chipdb ) if self.is_openxc7: