initial Vivado support
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Sat, 7 Jun 2014 10:24:19 +0000 (12:24 +0200)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Sat, 7 Jun 2014 10:24:28 +0000 (12:24 +0200)
13 files changed:
mibuild/platforms/kc705.py
mibuild/platforms/lx9_microboard.py
mibuild/platforms/m1.py
mibuild/platforms/mixxeo.py
mibuild/platforms/ml605.py
mibuild/platforms/papilio_pro.py
mibuild/platforms/rhino.py
mibuild/platforms/usrp_b100.py
mibuild/platforms/zedboard.py
mibuild/platforms/ztex_115d.py
mibuild/xilinx_common.py [new file with mode: 0644]
mibuild/xilinx_ise.py
mibuild/xilinx_vivado.py [new file with mode: 0644]

index bb47edccbbc455f966ee4ab75c44657dca680879..e519fa9e9e8bf80dabd0432782c35dc7fa9ffffe 100644 (file)
@@ -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)
index 70072a06f8792099c7145c9dc17ec37fa33b7043..660256cdbfdf1f22c55a15e44aa26dafd2fa0193 100644 (file)
@@ -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"),
index 094659a13baac8540aa24bbbd438080b2ae065a2..4d112d5b0cc64b9925857283671dd96b2a7c8b52 100644 (file)
@@ -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")),
index bdc80698a342cdd3dca4f7d0921ef0ca117a5aa7..298474a5c54f37169128a07cae5acb6ec9ca94f3 100644 (file)
@@ -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")),
index 72c49e670ae81d5a3b883fbfba36a18be4eef924..6b649baffd397106892a8442def03a0b69199363 100644 (file)
@@ -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)
index 9b20530bd3900a6796c6d132d2a6c4bf986cbb17..3e21f586af4be14180b93eaa1d8e9325e9f09f41 100644 (file)
@@ -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")),
index 87a22d9d117cf69d5e6ce2359bfe750f9b86ee16..5af6ea3f3669a2abbc776d9e9439f5e5b8acbb86 100644 (file)
@@ -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")),
index 4dfded6faf387bb393e5be0d95cb97d2a0bd2ee8..977025559d4ee7f0d09b597b9f86e0ac924655bc 100644 (file)
@@ -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,
index 8d6d7f3d573e1760b882cbc021c4647619edb197..eb89066e52ca987b22abf1e48fe077bc1358e2ce 100644 (file)
@@ -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 = [
index ae488f8b0d9fad15f62ef57b439c0bf3286b4eb5..27de93621f2f0e1beb6b07110e25a0e155d6bbd2 100644 (file)
@@ -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 (file)
index 0000000..aaec951
--- /dev/null
@@ -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))
+
index 2789358dbc75dd871ef026472bc10f2e9e0a17ce..5733a877a96e4dfe417818713b09b0081a884377 100644 (file)
@@ -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 (file)
index 0000000..40c0a27
--- /dev/null
@@ -0,0 +1,106 @@
+# This file is Copyright (c) 2014 Florent Kermarrec <florent@enjoy-digital.fr>
+# 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)