From be0d86f57fc657d0ae880b512860dd2b0c5cee93 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sat, 7 Jun 2014 12:24:19 +0200 Subject: [PATCH] initial Vivado support --- mibuild/platforms/kc705.py | 23 ++++-- mibuild/platforms/lx9_microboard.py | 3 +- mibuild/platforms/m1.py | 3 +- mibuild/platforms/mixxeo.py | 3 +- mibuild/platforms/ml605.py | 3 +- mibuild/platforms/papilio_pro.py | 3 +- mibuild/platforms/rhino.py | 3 +- mibuild/platforms/usrp_b100.py | 3 +- mibuild/platforms/zedboard.py | 3 +- mibuild/platforms/ztex_115d.py | 3 +- mibuild/xilinx_common.py | 25 +++++++ mibuild/xilinx_ise.py | 23 +----- mibuild/xilinx_vivado.py | 106 ++++++++++++++++++++++++++++ 13 files changed, 169 insertions(+), 35 deletions(-) create mode 100644 mibuild/xilinx_common.py create mode 100644 mibuild/xilinx_vivado.py diff --git a/mibuild/platforms/kc705.py b/mibuild/platforms/kc705.py index bb47edcc..e519fa9e 100644 --- a/mibuild/platforms/kc705.py +++ b/mibuild/platforms/kc705.py @@ -1,5 +1,7 @@ from mibuild.generic_platform import * -from mibuild.xilinx_ise import XilinxISEPlatform, CRG_DS +from mibuild.xilinx_common import CRG_SE, CRG_DS +from mibuild.xilinx_ise import XilinxISEPlatform +from mibuild.xilinx_vivado import XilinxVivadoPlatform _io = [ ("user_led", 0, Pins("AB8"), IOStandard("LVCMOS15")), @@ -79,6 +81,19 @@ _io = [ IOStandard("LVCMOS25")), ] -class Platform(XilinxISEPlatform): - def __init__(self, crg_factory=lambda p: CRG_DS(p, "user_clk", "cpu_reset", 6.4)): - XilinxISEPlatform.__init__(self, "xc7k325t-ffg900-1", _io, crg_factory) +def Platform(*args, toolchain=None, **kwargs): + if toolchain is None: + toolchain = "ise" + + if toolchain == "ise": + xilinx_platform = XilinxISEPlatform + elif toolchain == "vivado": + xilinx_platform = XilinxVivadoPlatform + else: + raise ValueError + + class RealPlatform(xilinx_platform): + def __init__(self, crg_factory=lambda p: CRG_DS(p, "clk156", "cpu_reset", 6.4)): + xilinx_platform.__init__(self, "xc7k325t-ffg900-1", _io, crg_factory) + + return RealPlatform(*args, **kwargs) diff --git a/mibuild/platforms/lx9_microboard.py b/mibuild/platforms/lx9_microboard.py index 70072a06..660256cd 100644 --- a/mibuild/platforms/lx9_microboard.py +++ b/mibuild/platforms/lx9_microboard.py @@ -1,5 +1,6 @@ from mibuild.generic_platform import * -from mibuild.xilinx_ise import XilinxISEPlatform, CRG_SE +from mibuild.xilinx_common import CRG_SE +from mibuild.xilinx_ise import XilinxISEPlatform _io = [ ("user_btn", 0, Pins("V4"), IOStandard("LVCMOS33"), diff --git a/mibuild/platforms/m1.py b/mibuild/platforms/m1.py index 094659a1..4d112d5b 100644 --- a/mibuild/platforms/m1.py +++ b/mibuild/platforms/m1.py @@ -1,5 +1,6 @@ from mibuild.generic_platform import * -from mibuild.xilinx_ise import XilinxISEPlatform, CRG_SE +from mibuild.xilinx_common import CRG_SE +from mibuild.xilinx_ise import XilinxISEPlatform _io = [ ("user_led", 0, Pins("B16"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), diff --git a/mibuild/platforms/mixxeo.py b/mibuild/platforms/mixxeo.py index bdc80698..298474a5 100644 --- a/mibuild/platforms/mixxeo.py +++ b/mibuild/platforms/mixxeo.py @@ -1,5 +1,6 @@ from mibuild.generic_platform import * -from mibuild.xilinx_ise import XilinxISEPlatform, CRG_SE +from mibuild.xilinx_common import CRG_SE +from mibuild.xilinx_ise import XilinxISEPlatform _io = [ ("user_led", 0, Pins("V5"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), diff --git a/mibuild/platforms/ml605.py b/mibuild/platforms/ml605.py index 72c49e67..6b649baf 100644 --- a/mibuild/platforms/ml605.py +++ b/mibuild/platforms/ml605.py @@ -1,5 +1,6 @@ from mibuild.generic_platform import * -from mibuild.xilinx_ise import XilinxISEPlatform, CRG_DS +from mibuild.xilinx_common import CRG_DS +from mibuild.xilinx_ise import XilinxISEPlatform _io = [ # System clock (Differential 200MHz) diff --git a/mibuild/platforms/papilio_pro.py b/mibuild/platforms/papilio_pro.py index 9b20530b..3e21f586 100644 --- a/mibuild/platforms/papilio_pro.py +++ b/mibuild/platforms/papilio_pro.py @@ -1,5 +1,6 @@ from mibuild.generic_platform import * -from mibuild.xilinx_ise import XilinxISEPlatform, CRG_SE +from mibuild.xilinx_common import CRG_SE +from mibuild.xilinx_ise import XilinxISEPlatform _io = [ ("user_led", 0, Pins("P112"), IOStandard("LVCMOS33"), Drive(24), Misc("SLEW=QUIETIO")), diff --git a/mibuild/platforms/rhino.py b/mibuild/platforms/rhino.py index 87a22d9d..5af6ea3f 100644 --- a/mibuild/platforms/rhino.py +++ b/mibuild/platforms/rhino.py @@ -1,5 +1,6 @@ from mibuild.generic_platform import * -from mibuild.xilinx_ise import XilinxISEPlatform, CRG_DS +from mibuild.xilinx_common import CRG_DS +from mibuild.xilinx_ise import XilinxISEPlatform _io = [ ("user_led", 0, Pins("Y3")), diff --git a/mibuild/platforms/usrp_b100.py b/mibuild/platforms/usrp_b100.py index 4dfded6f..97702555 100644 --- a/mibuild/platforms/usrp_b100.py +++ b/mibuild/platforms/usrp_b100.py @@ -1,5 +1,6 @@ from mibuild.generic_platform import * -from mibuild.xilinx_ise import XilinxISEPlatform, CRG_DS +from mibuild.xilinx_common import CRG_DS +from mibuild.xilinx_ise import XilinxISEPlatform _io = [ ("clk64", 0, diff --git a/mibuild/platforms/zedboard.py b/mibuild/platforms/zedboard.py index 8d6d7f3d..eb89066e 100644 --- a/mibuild/platforms/zedboard.py +++ b/mibuild/platforms/zedboard.py @@ -1,5 +1,6 @@ from mibuild.generic_platform import * -from mibuild.xilinx_ise import XilinxISEPlatform, CRG_SE +from mibuild.xilinx_common import CRG_SE +from mibuild.xilinx_ise import XilinxISEPlatform # Bank 34 and 35 voltage depend on J18 jumper setting _io = [ diff --git a/mibuild/platforms/ztex_115d.py b/mibuild/platforms/ztex_115d.py index ae488f8b..27de9362 100644 --- a/mibuild/platforms/ztex_115d.py +++ b/mibuild/platforms/ztex_115d.py @@ -1,5 +1,6 @@ from mibuild.generic_platform import * -from mibuild.xilinx_ise import XilinxISEPlatform, CRG_SE +from mibuild.xilinx_common import CRG_SE +from mibuild.xilinx_ise import XilinxISEPlatform _io = [ ("clk_fx", 0, Pins("L22"), IOStandard("LVCMOS33")), diff --git a/mibuild/xilinx_common.py b/mibuild/xilinx_common.py new file mode 100644 index 00000000..aaec951f --- /dev/null +++ b/mibuild/xilinx_common.py @@ -0,0 +1,25 @@ +from migen.fhdl.std import * +from mibuild.crg import SimpleCRG + +class CRG_SE(SimpleCRG): + def __init__(self, platform, clk_name, rst_name, period=None, rst_invert=False): + SimpleCRG.__init__(self, platform, clk_name, rst_name, rst_invert) + platform.add_period_constraint(platform, self._clk, period) + +class CRG_DS(Module): + def __init__(self, platform, clk_name, rst_name, period=None, rst_invert=False): + reset_less = rst_name is None + self.clock_domains.cd_sys = ClockDomain(reset_less=reset_less) + self._clk = platform.request(clk_name) + platform.add_period_constraint(platform, self._clk.p, period) + self.specials += Instance("IBUFGDS", + Instance.Input("I", self._clk.p), + Instance.Input("IB", self._clk.n), + Instance.Output("O", self.cd_sys.clk) + ) + if not reset_less: + if rst_invert: + self.comb += self.cd_sys.rst.eq(~platform.request(rst_name)) + else: + self.comb += self.cd_sys.rst.eq(platform.request(rst_name)) + diff --git a/mibuild/xilinx_ise.py b/mibuild/xilinx_ise.py index 2789358d..5733a877 100644 --- a/mibuild/xilinx_ise.py +++ b/mibuild/xilinx_ise.py @@ -7,30 +7,9 @@ from migen.genlib.cdc import * from migen.fhdl.structure import _Fragment from mibuild.generic_platform import * -from mibuild.crg import SimpleCRG from mibuild import tools -class CRG_SE(SimpleCRG): - def __init__(self, platform, clk_name, rst_name, period=None, rst_invert=False): - SimpleCRG.__init__(self, platform, clk_name, rst_name, rst_invert) - platform.add_period_constraint(platform, self._clk, period) - -class CRG_DS(Module): - def __init__(self, platform, clk_name, rst_name, period=None, rst_invert=False): - reset_less = rst_name is None - self.clock_domains.cd_sys = ClockDomain(reset_less=reset_less) - self._clk = platform.request(clk_name) - platform.add_period_constraint(platform, self._clk.p, period) - self.specials += Instance("IBUFGDS", - Instance.Input("I", self._clk.p), - Instance.Input("IB", self._clk.n), - Instance.Output("O", self.cd_sys.clk) - ) - if not reset_less: - if rst_invert: - self.comb += self.cd_sys.rst.eq(~platform.request(rst_name)) - else: - self.comb += self.cd_sys.rst.eq(platform.request(rst_name)) +from mibuild.xilinx_common import CRG_SE, CRG_DS def _format_constraint(c): if isinstance(c, Pins): diff --git a/mibuild/xilinx_vivado.py b/mibuild/xilinx_vivado.py new file mode 100644 index 00000000..40c0a27d --- /dev/null +++ b/mibuild/xilinx_vivado.py @@ -0,0 +1,106 @@ +# This file is Copyright (c) 2014 Florent Kermarrec +# License: BSD + +import os, subprocess, sys + +from migen.fhdl.std import * +from migen.fhdl.structure import _Fragment + +from mibuild.generic_platform import * +from mibuild import tools + +from mibuild.xilinx_common import CRG_SE, CRG_DS + +def _format_constraint(c): + if isinstance(c, Pins): + return "set_property LOC " + c.identifiers[0] + elif isinstance(c, IOStandard): + return "set_property IOSTANDARD " + c.name + elif isinstance(c, Drive): + return "set property DRIVE " + + str(c.strength) + elif isinstance(c, Misc): + return c.misc + +def _format_xdc(signame, pin, others, resname): + fmt_c = [_format_constraint(c) for c in ([Pins(pin)] + others)] + fmt_r = resname[0] + ":" + str(resname[1]) + if resname[2] is not None: + fmt_r += "." + resname[2] + r = " ## %s\n" %fmt_r + for c in fmt_c: + r += c + " [get_ports " + signame + "]\n" + return r + +def _build_xdc(named_sc, named_pc): + r = "" + for sig, pins, others, resname in named_sc: + if len(pins) > 1: + for i, p in enumerate(pins): + r += _format_xdc(sig + "[" + str(i) + "]", p, others, resname) + else: + r += _format_xdc(sig, pins[0], others, resname) + if named_pc: + r += "\n" + "\n\n".join(named_pc) + return r + +def _build_files(device, sources, vincpaths, build_name): + tcl_contents = "" + for filename, language in sources: + tcl_contents += "add_files " + filename.replace("\\", "/") + "\n" + + tcl_contents += "read_xdc %s.xdc\n" %build_name + tcl_contents += "synth_design -top top -part %s -include_dirs {%s}\n" %(device, " ".join(vincpaths)) + tcl_contents += "place_design\n" + tcl_contents += "route_design\n" + tcl_contents += "report_timing_summary -file %s_timing.rpt\n" %(build_name) + tcl_contents += "report_utilization -file %s_utilization.rpt\n" %(build_name) + tcl_contents += "write_bitstream -force %s.bit \n" %build_name + tcl_contents += "quit\n" + tools.write_to_file(build_name + ".tcl", tcl_contents) + +def _run_vivado(build_name, vivado_path, source): + if sys.platform == "win32" or sys.platform == "cygwin": + source = False + build_script_contents = "# Autogenerated by mibuild\nset -e\n" + if source: + raise NotImplementedError + build_script_contents += """ +vivado -mode tcl -source {build_name}.tcl +""".format(build_name=build_name) + build_script_file = "build_" + build_name + ".sh" + tools.write_to_file(build_script_file, build_script_contents, force_unix=True) + + r = subprocess.call(["bash", build_script_file]) + if r != 0: + raise OSError("Subprocess failed") + +class XilinxVivadoPlatform(GenericPlatform): + bitstream_ext = ".bit" + def get_verilog(self, *args, special_overrides=dict(), **kwargs): + so = {} + so.update(special_overrides) + return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) + + def build(self, fragment, build_dir="build", build_name="top", + vivado_path="/opt/Xilinx", source=True, run=True): + tools.mkdir_noerror(build_dir) + os.chdir(build_dir) + + if not isinstance(fragment, _Fragment): + fragment = fragment.get_fragment() + self.finalize(fragment) + v_src, named_sc, named_pc = self.get_verilog(fragment) + v_file = build_name + ".v" + tools.write_to_file(v_file, v_src) + sources = self.sources + [(v_file, "verilog")] + _build_files(self.device, sources, self.verilog_include_paths, build_name) + tools.write_to_file(build_name + ".xdc", _build_xdc(named_sc, named_pc)) + if run: + _run_vivado(build_name, vivado_path, source) + + os.chdir("..") + + def add_period_constraint(self, clk, period): + if period is not None: + self.add_platform_command("""create_clock -name {clk} -period """ +\ + str(period) + """ [get_ports {clk}]""", clk=clk) -- 2.30.2