mibuild: add support for Yosys
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 1 Dec 2013 16:07:48 +0000 (17:07 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 1 Dec 2013 16:07:48 +0000 (17:07 +0100)
mibuild/xilinx_ise.py

index 8df2cfba28f33437a79ecd1d73e3bfbbf02b25c5..69944ad8b8528623ed48f4c4b5472a730f8a6395 100644 (file)
@@ -70,9 +70,7 @@ def _build_ucf(named_sc, named_pc):
                r += "\n" + "\n\n".join(named_pc)
        return r
 
-def _build_files(device, sources, named_sc, named_pc, build_name):
-       tools.write_to_file(build_name + ".ucf", _build_ucf(named_sc, named_pc))
-
+def _build_xst_files(device, sources, build_name):
        prj_contents = ""
        for filename, language in sources:
                prj_contents += language + " work " + filename + "\n"
@@ -89,6 +87,33 @@ def _build_files(device, sources, named_sc, named_pc, build_name):
 -p %s""" % (build_name, build_name, device)
        tools.write_to_file(build_name + ".xst", xst_contents)
 
+def _run_yosys(device, sources, build_name):
+       ys_contents = ""
+       for filename, language in sources:
+               ys_contents += "read_{} {}\n".format(language, filename)
+       
+       if device[:2] == "xc":
+               archcode = device[2:4]
+       else:
+               archcode = device[0:2]
+       arch = {
+               "6s": "spartan6",
+               "7a": "artix7",
+               "7k": "kintex7",
+               "7v": "virtex7",
+               "7z": "zynq7000"
+       }[archcode]
+       
+       ys_contents += """hierarchy -check -top top
+proc; memory; opt; fsm; opt
+synth_xilinx -arch {arch} -top top -edif {build_name}.edif""".format(arch=arch, build_name=build_name)
+       
+       ys_name = build_name + ".ys"
+       tools.write_to_file(ys_name, ys_contents)
+       r = subprocess.call(["yosys", ys_name])
+       if r != 0:
+               raise OSError("Subprocess failed")
+
 def _is_valid_version(path, v):
        try: 
                Decimal(v)
@@ -96,7 +121,7 @@ def _is_valid_version(path, v):
        except:
                return False
 
-def _run_ise(build_name, ise_path, source, mode="verilog"):
+def _run_ise(build_name, ise_path, source, mode, ngdbuild_opt):
        if sys.platform == "win32" or sys.platform == "cygwin":
                source = False
        build_script_contents = "# Autogenerated by mibuild\nset -e\n"
@@ -112,7 +137,7 @@ def _run_ise(build_name, ise_path, source, mode="verilog"):
                build_script_contents += "source " + xilinx_settings_file + "\n"
        if mode == "edif":
                build_script_contents += """
-ngdbuild -uc {build_name}.ucf {build_name}.edif {build_name}.ngd"""
+ngdbuild {ngdbuild_opt} -uc {build_name}.ucf {build_name}.edif {build_name}.ngd"""
        else:
                build_script_contents += """
 xst -ifn {build_name}.xst
@@ -123,7 +148,7 @@ map -ol high -w -o {build_name}_map.ncd {build_name}.ngd {build_name}.pcf
 par -ol high -w {build_name}_map.ncd {build_name}.ncd {build_name}.pcf
 bitgen -g LCK_cycle:6 -g Binary:Yes -w {build_name}.ncd {build_name}.bit
 """
-       build_script_contents = build_script_contents.format(build_name=build_name)
+       build_script_contents = build_script_contents.format(build_name=build_name, ngdbuild_opt=ngdbuild_opt)
        build_script_file = "build_" + build_name + ".sh"
        tools.write_to_file(build_script_file, build_script_contents)
 
@@ -164,7 +189,7 @@ class XilinxISEPlatform(GenericPlatform):
                return GenericPlatform.get_edif(self, fragment, "UNISIMS", "Xilinx", self.device, **kwargs)
 
        def build(self, fragment, build_dir="build", build_name="top",
-                       ise_path="/opt/Xilinx", source=True, run=True, mode="verilog"):
+                       ise_path="/opt/Xilinx", source=True, run=True, mode="xst"):
                tools.mkdir_noerror(build_dir)
                os.chdir(build_dir)
 
@@ -172,14 +197,20 @@ class XilinxISEPlatform(GenericPlatform):
                        fragment = fragment.get_fragment()
                self.finalize(fragment)
 
-               if mode == "verilog":
+               ngdbuild_opt = ""
+
+               if mode == "xst" or mode == "yosys":
                        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, named_sc, named_pc, build_name)
-                       if run:
-                               _run_ise(build_name, ise_path, source, mode="verilog")
+                       if mode == "xst":
+                               _build_xst_files(self.device, sources, build_name)
+                               isemode = "xst"
+                       else:
+                               _run_yosys(self.device, sources, build_name)
+                               isemode = "edif"
+                               ngdbuild_opt = "-p " + self.device
 
                if mode == "mist":
                        from mist import synthesize
@@ -189,10 +220,11 @@ class XilinxISEPlatform(GenericPlatform):
                        e_src, named_sc, named_pc = self.get_edif(fragment)
                        e_file = build_name + ".edif"
                        tools.write_to_file(e_file, e_src)
-                       sources = self.sources + [(e_file, "edif")]
-                       tools.write_to_file(build_name + ".ucf", _build_ucf(named_sc, named_pc))
-                       if run:
-                               _run_ise(build_name, ise_path, source, mode="edif")
+                       isemode = "edif"
+
+               tools.write_to_file(build_name + ".ucf", _build_ucf(named_sc, named_pc))
+               if run:
+                       _run_ise(build_name, ise_path, source, isemode, ngdbuild_opt)
 
                os.chdir("..")