diff --git a/litex/build/altera/platform.py b/litex/build/altera/platform.py index 0e7f24d09..87471b58c 100644 --- a/litex/build/altera/platform.py +++ b/litex/build/altera/platform.py @@ -16,6 +16,8 @@ class AlteraPlatform(GenericPlatform): bitstream_ext = ".sof" create_rbf = True + _supported_toolchains = ["quartus"] + def __init__(self, *args, toolchain="quartus", **kwargs): GenericPlatform.__init__(self, *args, **kwargs) self.ips = set() diff --git a/litex/build/anlogic/platform.py b/litex/build/anlogic/platform.py index b5bfab63c..e857ce0a6 100644 --- a/litex/build/anlogic/platform.py +++ b/litex/build/anlogic/platform.py @@ -15,6 +15,8 @@ from litex.build.anlogic import common, anlogic class AnlogicPlatform(GenericPlatform): bitstream_ext = ".fs" + _supported_toolchains = ["td"] + def __init__(self, device, *args, toolchain="td", **kwargs): GenericPlatform.__init__(self, device, *args, **kwargs) if toolchain == "td": diff --git a/litex/build/efinix/platform.py b/litex/build/efinix/platform.py index 948b0033c..a186cae3d 100644 --- a/litex/build/efinix/platform.py +++ b/litex/build/efinix/platform.py @@ -18,6 +18,8 @@ from litex.build.efinix import EfinixDbParser class EfinixPlatform(GenericPlatform): bitstream_ext = ".bit" + _supported_toolchains = ["efinity"] + def __init__(self, *args, iobank_info=None, toolchain="efinity", **kwargs): GenericPlatform.__init__(self, *args, **kwargs) diff --git a/litex/build/generic_platform.py b/litex/build/generic_platform.py index 0826e4a28..c86287bee 100644 --- a/litex/build/generic_platform.py +++ b/litex/build/generic_platform.py @@ -322,6 +322,8 @@ class ConstraintManager: # Generic Platform --------------------------------------------------------------------------------- class GenericPlatform: + device_family = None + def __init__(self, device, io, connectors=[], name=None): self.toolchain = None self.device = device @@ -467,3 +469,54 @@ class GenericPlatform: @property def support_mixed_language(self): return self.toolchain.support_mixed_language + + @classmethod + def fill_args(cls, toolchain, parser): + """ + pass parser to the specific toolchain to + fill this with toolchain args + + Parameters + ========== + toolchain: str + toolchain name + parser: argparse.ArgumentParser + parser to be filled + """ + pass # pass must be overloaded (if required) + + @classmethod + def get_argdict(cls, toolchain, args): + """ + return a dict of args + + Parameters + ========== + toolchain: str + toolchain name + + Return + ====== + a dict of key/value for each args or an empty dict + """ + return {} # Empty must be overloaded (if required) + + @classmethod + def toolchains(cls, device): + """ + Returns list of toolchains compatible with device + + Parameters + ========== + device: str + device name (ice40, ecp5, nexus) + + Return + ====== + A list of compatible toolchains (str) or an empty list + """ + if type(cls._supported_toolchains) == dict: + assert device is not None + return cls._supported_toolchains[device] + else: + return cls._supported_toolchains diff --git a/litex/build/gowin/platform.py b/litex/build/gowin/platform.py index d130d7b8f..62525fe65 100644 --- a/litex/build/gowin/platform.py +++ b/litex/build/gowin/platform.py @@ -15,6 +15,8 @@ from litex.build.gowin import common, gowin class GowinPlatform(GenericPlatform): bitstream_ext = ".fs" + _supported_toolchains = ["gowin", "apicula"] + def __init__(self, device, *args, toolchain="gowin", devicename=None, **kwargs): GenericPlatform.__init__(self, device, *args, **kwargs) if not devicename: diff --git a/litex/build/lattice/__init__.py b/litex/build/lattice/__init__.py index 6b356c722..95b9e92f6 100644 --- a/litex/build/lattice/__init__.py +++ b/litex/build/lattice/__init__.py @@ -1,2 +1,2 @@ -from litex.build.lattice.platform import LatticePlatform +from litex.build.lattice.platform import LatticePlatform, LatticeiCE40Platform, LatticeECP5Platform, LatticeNexusPlatform from litex.build.lattice.programmer import LatticeProgrammer diff --git a/litex/build/lattice/icestorm.py b/litex/build/lattice/icestorm.py index 597e09003..db88daf12 100644 --- a/litex/build/lattice/icestorm.py +++ b/litex/build/lattice/icestorm.py @@ -106,7 +106,7 @@ class LatticeIceStormToolchain(YosysNextPNRToolchain): def icestorm_args(parser): - toolchain_group = parser.add_argument_group(title="Toolchain options") + toolchain_group = parser.add_argument_group(title="Icestorm toolchain options") yosys_nextpnr_args(toolchain_group) def icestorm_argdict(args): diff --git a/litex/build/lattice/oxide.py b/litex/build/lattice/oxide.py index 7bc2f094f..9fa2f2a1c 100644 --- a/litex/build/lattice/oxide.py +++ b/litex/build/lattice/oxide.py @@ -62,7 +62,7 @@ class LatticeOxideToolchain(YosysNextPNRToolchain): return (self._build_name + ".pdc", "PDC") def oxide_args(parser): - toolchain_group = parser.add_argument_group(title="Toolchain options") + toolchain_group = parser.add_argument_group(title="Oxide toolchain options") yosys_nextpnr_args(toolchain_group) toolchain_group.add_argument("--nexus-es-device", action="store_true", help="Use Nexus-ES1 part.") diff --git a/litex/build/lattice/platform.py b/litex/build/lattice/platform.py index 3e95f8322..b6bf94788 100644 --- a/litex/build/lattice/platform.py +++ b/litex/build/lattice/platform.py @@ -13,6 +13,12 @@ from litex.build.lattice import common, diamond, icestorm, trellis, radiant, oxi class LatticePlatform(GenericPlatform): bitstream_ext = ".bit" + _supported_toolchains = { + "ice40": ["icestorm"], + "ecp5": ["trellis", "diamond"], + "nexus": ["radiant", "oxide"], + } + def __init__(self, *args, toolchain="diamond", **kwargs): GenericPlatform.__init__(self, *args, **kwargs) if toolchain == "diamond": @@ -38,7 +44,6 @@ class LatticePlatform(GenericPlatform): attr_translate = self.toolchain.attr_translate, **kwargs) - def build(self, *args, **kwargs): return self.toolchain.build(self, *args, **kwargs) @@ -54,3 +59,67 @@ class LatticePlatform(GenericPlatform): if hasattr(to, "p"): to = to.p self.toolchain.add_false_path_constraint(self, from_, to) + + @classmethod + def fill_args(cls, toolchain, parser): + """ + pass parser to the specific toolchain to + fill this with toolchain args + + Parameters + ========== + toolchain: str + toolchain name + parser: argparse.ArgumentParser + parser to be filled + """ + if toolchain == "radiant": + radiant.radiant_build_args(parser) + elif toolchain == "oxide": + oxide.oxide_args(parser) + elif toolchain == "trellis": + trellis.trellis_args(parser) + elif toolchain == "icestorm": + icestorm.icestorm_args(parser) + # nothing for diamond + + @classmethod + def get_argdict(cls, toolchain, args): + """ + return a dict of args + + Parameters + ========== + toolchain: str + toolchain name + + Return + ====== + a dict of key/value for each args or an empty dict + """ + if toolchain == "radiant": + return radiant.radiant_build_argdict(args) + elif toolchain == "oxide": + return oxide.oxide_argdict(args) + elif toolchain == "trellis": + return trellis.trellis_argdict(args) + elif toolchain == "icestorm": + return icestorm.icestorm_argdict(args) + else: + return {} + # nothing for diamond + +# LatticeiCE40Platform ----------------------------------------------------------------------------- + +class LatticeiCE40Platform(LatticePlatform): + device_family = "ice40" + +# LatticeECP5Platform ------------------------------------------------------------------------------ + +class LatticeECP5Platform(LatticePlatform): + device_family = "ecp5" + +# LatticeNexusPlatform ----------------------------------------------------------------------------- + +class LatticeNexusPlatform(LatticePlatform): + device_family = "nexus" diff --git a/litex/build/lattice/radiant.py b/litex/build/lattice/radiant.py index 328a2dde6..9cb54b730 100644 --- a/litex/build/lattice/radiant.py +++ b/litex/build/lattice/radiant.py @@ -273,7 +273,7 @@ class LatticeRadiantToolchain(GenericToolchain): def radiant_build_args(parser): - toolchain_group = parser.add_argument_group(title="Toolchain options") + toolchain_group = parser.add_argument_group(title="Radiant toolchain options") toolchain_group.add_argument("--synth-mode", default="synplify", help="Synthesis mode (synplify or yosys).") def radiant_build_argdict(args): diff --git a/litex/build/lattice/trellis.py b/litex/build/lattice/trellis.py index 0a833613d..0f365c831 100644 --- a/litex/build/lattice/trellis.py +++ b/litex/build/lattice/trellis.py @@ -150,7 +150,7 @@ class LatticeTrellisToolchain(YosysNextPNRToolchain): freq=str(float(1/period)*1000), clk="{clk}"), clk=clk) def trellis_args(parser): - toolchain_group = parser.add_argument_group(title="Toolchain options") + toolchain_group = parser.add_argument_group(title="Trellis toolchain options") yosys_nextpnr_args(toolchain_group) toolchain_group.add_argument("--ecppack-bootaddr", default=0, help="Set boot address for next image.") toolchain_group.add_argument("--ecppack-spimode", default=None, help="Set slave SPI programming mode.") diff --git a/litex/build/microsemi/platform.py b/litex/build/microsemi/platform.py index ac4aa6938..a36ee7656 100644 --- a/litex/build/microsemi/platform.py +++ b/litex/build/microsemi/platform.py @@ -12,6 +12,8 @@ from litex.build.microsemi import common, libero_soc class MicrosemiPlatform(GenericPlatform): bitstream_ext = ".bit" + _supported_toolchains = ["libero_soc_polarfire"] + def __init__(self, *args, toolchain="libero_soc_polarfire", **kwargs): GenericPlatform.__init__(self, *args, **kwargs) if toolchain == "libero_soc_polarfire": diff --git a/litex/build/osfpga/platform.py b/litex/build/osfpga/platform.py index d04fc06f0..bdd576651 100644 --- a/litex/build/osfpga/platform.py +++ b/litex/build/osfpga/platform.py @@ -14,6 +14,8 @@ from litex.build.osfpga import common, osfpga class OSFPGAPlatform(GenericPlatform): bitstream_ext = ".bin" + _supported_toolchains = ["osfpga"] + def __init__(self, device, *args, toolchain="foedag", devicename=None, **kwargs): GenericPlatform.__init__(self, device, *args, **kwargs) self.devicename = devicename diff --git a/litex/build/quicklogic/platform.py b/litex/build/quicklogic/platform.py index 8142f22d4..506ac0bed 100644 --- a/litex/build/quicklogic/platform.py +++ b/litex/build/quicklogic/platform.py @@ -14,6 +14,8 @@ from litex.build.quicklogic import common, f4pga class QuickLogicPlatform(GenericPlatform): bitstream_ext = ".bit" + _supported_toolchains = ["f4pga"] + def __init__(self, *args, toolchain="f4pga", **kwargs): GenericPlatform.__init__(self, *args, **kwargs) if toolchain == "symbiflow" or toolchain == "f4pga": diff --git a/litex/build/sim/platform.py b/litex/build/sim/platform.py index 633a16892..bae83f907 100644 --- a/litex/build/sim/platform.py +++ b/litex/build/sim/platform.py @@ -16,6 +16,9 @@ from litex.soc.interconnect.csr import AutoCSR, CSR, CSRStorage class SimPlatform(GenericPlatform): + + _supported_toolchains = ["verilator"] + def __init__(self, device, io, name="sim", toolchain="verilator", **kwargs): if "sim_trace" not in (iface[0] for iface in io): io.append(("sim_trace", 0, Pins(1))) diff --git a/litex/build/xilinx/__init__.py b/litex/build/xilinx/__init__.py index 53e6e840a..9d9bc1801 100644 --- a/litex/build/xilinx/__init__.py +++ b/litex/build/xilinx/__init__.py @@ -1,2 +1,2 @@ -from litex.build.xilinx.platform import XilinxPlatform +from litex.build.xilinx.platform import XilinxPlatform, XilinxSpartan6Platform, Xilinx7SeriesPlatform from litex.build.xilinx.programmer import UrJTAG, XC3SProg, FpgaProg, VivadoProgrammer, iMPACT, Adept diff --git a/litex/build/xilinx/platform.py b/litex/build/xilinx/platform.py index 14f6092bb..ad392c05e 100644 --- a/litex/build/xilinx/platform.py +++ b/litex/build/xilinx/platform.py @@ -9,13 +9,18 @@ import os from litex.build.generic_platform import GenericPlatform -from litex.build.xilinx import common +from litex.build.xilinx import common, vivado, ise, yosys_nextpnr # XilinxPlatform ----------------------------------------------------------------------------------- class XilinxPlatform(GenericPlatform): bitstream_ext = ".bit" + _supported_toolchains = { + "serie7": ["vivado", "f4pga", "yosys+nextpnr"], + "spartan6": ["ise"], + } + def __init__(self, *args, toolchain="ise", **kwargs): GenericPlatform.__init__(self, *args, **kwargs) self.edifs = set() @@ -84,3 +89,49 @@ class XilinxPlatform(GenericPlatform): if hasattr(to, "p"): to = to.p self.toolchain.add_false_path_constraint(self, from_, to) + + @classmethod + def fill_args(cls, toolchain, parser): + """ + pass parser to the specific toolchain to + fill this with toolchain args + + Parameters + ========== + toolchain: str + toolchain name + parser: argparse.ArgumentParser + parser to be filled + """ + if toolchain == "vivado": + vivado.vivado_build_args(parser) + + @classmethod + def get_argdict(cls, toolchain, args): + """ + return a dict of args + + Parameters + ========== + toolchain: str + toolchain name + + Return + ====== + a dict of key/value for each args or an empty dict + """ + if toolchain == "vivado": + return vivado.vivado_build_argdict(args) + else: + return dict() + +# Xilinx7SeriesPlatform ----------------------------------------------------------------------------- + +class Xilinx7SeriesPlatform(XilinxPlatform): + device_family = "serie7" + +# XilinxSpartan6Platform --------------------------------------------------------------------------- + +class XilinxSpartan6Platform(XilinxPlatform): + device_family = "spartan6" +