build: merge more migen changes
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 12 Nov 2018 10:26:35 +0000 (11:26 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 12 Nov 2018 10:26:35 +0000 (11:26 +0100)
12 files changed:
litex/build/altera/programmer.py
litex/build/altera/quartus.py
litex/build/generic_programmer.py
litex/build/lattice/diamond.py
litex/build/lattice/icestorm.py
litex/build/lattice/programmer.py
litex/build/lattice/trellis.py
litex/build/tools.py
litex/build/xilinx/__init__.py
litex/build/xilinx/ise.py
litex/build/xilinx/programmer.py
litex/build/xilinx/vivado.py

index 43d6ff9cdea4509fe51812fe9161f809b06aa1ab..d4871c631f1b0911aeae8a42b9b013d57f04c836 100644 (file)
@@ -6,7 +6,11 @@ from litex.build.generic_programmer import GenericProgrammer
 class USBBlaster(GenericProgrammer):
     needs_bitreverse = False
 
+    def __init__(self, cable_name="USB-Blaster", device_id=1):
+        self.cable_name = cable_name
+        self.device_id = device_id
+
     def load_bitstream(self, bitstream_file, cable_suffix=""):
         subprocess.call(["quartus_pgm", "-m", "jtag", "-c",
-                         "USB-Blaster{}".format(cable_suffix), "-o",
-                         "p;{}".format(bitstream_file)])
+                         "{}{}".format(self.cable_name, cable_suffix), "-o",
+                         "p;{}@{}".format(bitstream_file, self.device_id)])
index 76ec775c8e35f01765684f1ede803b58943761b4..ef30e78be05d93d155d90403eac7b3ab36f5bfd3 100644 (file)
@@ -100,7 +100,10 @@ quartus_map --read_settings_files=on --write_settings_files=off {build_name} -c
 quartus_fit --read_settings_files=off --write_settings_files=off {build_name} -c {build_name}
 quartus_asm --read_settings_files=off --write_settings_files=off {build_name} -c {build_name}
 quartus_sta {build_name} -c {build_name}
-quartus_cpf -c {build_name}.sof {build_name}.rbf
+if [ -f "{build_name}.sof" ]
+then
+    quartus_cpf -c {build_name}.sof {build_name}.rbf
+fi
 
 """.format(build_name=build_name)  # noqa
     build_script_file = "build_" + build_name + ".sh"
@@ -127,7 +130,7 @@ class AlteraQuartusToolchain:
         named_sc, named_pc = platform.resolve_signals(v_output.ns)
         v_file = build_name + ".v"
         v_output.write(v_file)
-        sources = platform.sources + [(v_file, "verilog", "work")]
+        sources = platform.sources | {(v_file, "verilog", "work")}
         _build_files(platform.device,
                      sources,
                      platform.verilog_include_paths,
index b9540415c2d240bbe3dcc736d6ba7db4e59747c9..0fac6f9440ef601c6e93a29c1028fa11505a31c1 100644 (file)
@@ -1,10 +1,13 @@
-import os
+import os, sys
+from litex.build import tools
 
 
 class GenericProgrammer:
     def __init__(self, flash_proxy_basename=None):
         self.flash_proxy_basename = flash_proxy_basename
         self.flash_proxy_dirs = [
+            "~/.migen", "/usr/local/share/migen", "/usr/share/migen",
+            "~/.mlabs", "/usr/local/share/mlabs", "/usr/share/mlabs",
             "~/.litex", "/usr/local/share/litex", "/usr/share/litex"]
 
     def set_flash_proxy_dir(self, flash_proxy_dir):
@@ -14,7 +17,7 @@ class GenericProgrammer:
     def find_flash_proxy(self):
         for d in self.flash_proxy_dirs:
             fulldir = os.path.abspath(os.path.expanduser(d))
-            fullname = os.path.join(fulldir, self.flash_proxy_basename)
+            fullname = tools.cygpath(os.path.join(fulldir, self.flash_proxy_basename))
             if os.path.exists(fullname):
                 return fullname
         raise OSError("Failed to find flash proxy bitstream")
index 1569f56738e8ddd7f89885acd4a1f1fedb1e2293..cee157bc4446b98490a479c84cdd1b49d0ed2191 100644 (file)
@@ -132,7 +132,7 @@ class LatticeDiamondToolchain:
     special_overrides = common.lattice_ecpx_special_overrides
 
     def build(self, platform, fragment, build_dir="build", build_name="top",
-              toolchain_path="/opt/Diamond", run=True):
+              toolchain_path="/opt/Diamond", run=True, **kwargs):
         os.makedirs(build_dir, exist_ok=True)
         cwd = os.getcwd()
         os.chdir(build_dir)
@@ -141,7 +141,7 @@ class LatticeDiamondToolchain:
             fragment = fragment.get_fragment()
         platform.finalize(fragment)
 
-        v_output = platform.get_verilog(fragment)
+        v_output = platform.get_verilog(fragment, name=build_name, **kwargs)
         named_sc, named_pc = platform.resolve_signals(v_output.ns)
         v_file = build_name + ".v"
         v_output.write(v_file)
index 72eb00239b84033eca5c842eed8aa092faea0e75..8afdaf61ced6fc7dd354932e3e57f142e33cd32c 100644 (file)
@@ -1,4 +1,4 @@
-# This file is Copyright (c) 2017 William D. Jones <thor0505@comcast.net>
+# This file is Copyright (c) 2016-2017 William D. Jones <thor0505@comcast.net>
 # License: BSD
 
 import os
@@ -37,11 +37,11 @@ def _build_script(source, build_template, build_name, pnr_pkg_opts,
                   icetime_pkg_opts, freq_constraint):
     if sys.platform in ("win32", "cygwin"):
         script_ext = ".bat"
-        build_script_contents = "@echo off\nrem Autogenerated by Migen\n"
+        build_script_contents = "@echo off\nrem Autogenerated by Migen\n\n"
         fail_stmt = " || exit /b"
     else:
         script_ext = ".sh"
-        build_script_contents = "# Autogenerated by Migen\nset -e\n"
+        build_script_contents = "# Autogenerated by Migen\nset -e\n\n"
         fail_stmt = ""
 
     for s in build_template:
@@ -127,7 +127,7 @@ class LatticeIceStormToolchain:
 
     # platform.device should be of the form "ice40-{lp384, hx1k, etc}-{tq144, etc}"
     def build(self, platform, fragment, build_dir="build", build_name="top",
-              toolchain_path=None, use_nextpnr=True, run=True):
+              use_nextpnr=True, run=True, **kwargs):
         os.makedirs(build_dir, exist_ok=True)
         cwd = os.getcwd()
         os.chdir(build_dir)
@@ -136,7 +136,7 @@ class LatticeIceStormToolchain:
             fragment = fragment.get_fragment()
         platform.finalize(fragment)
 
-        v_output = platform.get_verilog(fragment)
+        v_output = platform.get_verilog(fragment, name=build_name, **kwargs)
         named_sc, named_pc = platform.resolve_signals(v_output.ns)
         v_file = build_name + ".v"
         v_output.write(v_file)
@@ -207,7 +207,7 @@ class LatticeIceStormToolchain:
         return series_size_str[2:]
 
     def gen_read_files(self, platform, main):
-        sources = platform.sources + [(main, "verilog", "work")]
+        sources = platform.sources | {(main, "verilog", "work")}
         incflags = ""
         read_files = list()
         for path in platform.verilog_include_paths:
index 07cc0d1ff27b9535541c3e27a3be68fa8d9b2ee5..c1a14fefdd641bacf04002d302a7615d00b6cc65 100644 (file)
@@ -11,15 +11,11 @@ class LatticeProgrammer(GenericProgrammer):
     def __init__(self, xcf_template):
         self.xcf_template = xcf_template
 
-    def load_bitstream(self, bitstream_file, toolchain_path=''):
+    def load_bitstream(self, bitstream_file):
         xcf_file = bitstream_file.replace(".bit", ".xcf")
         xcf_content = self.xcf_template.format(bitstream_file=bitstream_file)
         tools.write_to_file(xcf_file, xcf_content)
-        if toolchain_path:
-            pgrcmd = os.path.join(toolchain_path, 'bin/lin64/pgrcmd')
-        else:
-            pgrcmr = 'pgrcmr'
-        subprocess.call([pgrcmd, "-infile", xcf_file])
+        subprocess.call(["pgrcmd", "-infile", xcf_file])
 
 
 class IceStormProgrammer(GenericProgrammer):
@@ -76,12 +72,22 @@ class TinyProgProgrammer(GenericProgrammer):
                 # Ditto with user data.
                 subprocess.call(["tinyprog", "-u", bitstream_file])
         else:
-            # Provide override so user can program wherever they wish (outside
-            # of bootloader region).
-            subprocess.call(["tinyprog", "-a", str(address), "--program-image",
+            # Provide override so user can program wherever they wish.
+            subprocess.call(["tinyprog", "-a", str(address), "-p",
                             bitstream_file])
 
     # Force user image to boot if a user reset tinyfpga, the bootloader
     # is active, and the user image need not be reprogrammed.
     def boot(self):
         subprocess.call(["tinyprog", "-b"])
+
+
+class MyStormProgrammer(GenericProgrammer):
+    def __init__(self, serial_port):
+        self.serial_port = serial_port
+
+    def load_bitstream(self, bitstream_file):
+        import serial
+        with serial.Serial(self.serial_port) as port:
+            with open(bitstream_file, "rb") as f:
+                port.write(f.read())
index 8f272920e2410ca145f03aa0f7ec03e0f63d4308..a395c367f1be2928ad2477efe84f85d9a0cb705c 100644 (file)
@@ -40,7 +40,6 @@ def _format_constraint(c):
 def _format_lpf(signame, pin, others, resname):
     fmt_c = [_format_constraint(c) for c in ([Pins(pin)] + others)]
     r = ""
-    print(fmt_c)
     for pre, suf in fmt_c:
         r += pre + "\"" + signame + "\"" + suf + ";\n"
     return r
@@ -138,7 +137,7 @@ class LatticeTrellisToolchain:
         self.freq_constraints = dict()
 
     def build(self, platform, fragment, build_dir="build", build_name="top",
-              toolchain_path=None, run=True):
+              toolchain_path=None, run=True, **kwargs):
         if toolchain_path is None:
             toolchain_path = "/usr/share/trellis/"
         os.makedirs(build_dir, exist_ok=True)
@@ -150,7 +149,7 @@ class LatticeTrellisToolchain:
             fragment = fragment.get_fragment()
         platform.finalize(fragment)
 
-        top_output = platform.get_verilog(fragment, name=build_name)
+        top_output = platform.get_verilog(fragment, name=build_name, **kwargs)
         named_sc, named_pc = platform.resolve_signals(top_output.ns)
         top_file = build_name + ".v"
         top_output.write(top_file)
index 2bfc1e77b28df84c8f43605de352a3d9d9cf34a3..313abaea4c409ead2e9cd1ecfacfeff75e7d9c63 100644 (file)
@@ -4,6 +4,7 @@ from distutils.version import StrictVersion
 import re
 import subprocess
 import sys
+import ctypes
 
 
 def language_by_filename(name):
@@ -55,3 +56,35 @@ def subprocess_call_filtered(command, rules, *, max_matches=1, **kwargs):
             for line in stdout:
                 print(sub_rules(line, rules, max_matches), end="")
         return proc.wait()
+
+
+if sys.platform == "cygwin":
+    cygwin1 = ctypes.CDLL("/usr/bin/cygwin1.dll")
+    cygwin_conv_path_proto = ctypes.CFUNCTYPE(
+        ctypes.c_ssize_t, # Return
+        ctypes.c_uint, # what
+        ctypes.c_void_p, # from
+        ctypes.c_void_p, # to
+        ctypes.c_size_t) # size
+    cygwin_conv_path = cygwin_conv_path_proto(("cygwin_conv_path", cygwin1),
+        ((1, "what"),
+        (1, "from"),
+        (1, "to"),
+        (1, "size")))
+
+
+    def cygpath_to_windows(path):
+        what = ctypes.c_uint(0) # CCP_POSIX_TO_WIN_A
+        fro = ctypes.c_char_p(path.encode('utf-8'))
+        to = ctypes.byref(ctypes.create_string_buffer(260))
+        size = ctypes.c_size_t(260)
+
+        cygwin_conv_path(what, fro, to, size)
+        return ctypes.cast(to, ctypes.c_char_p).value.decode('utf-8')
+
+    # Convert cygwin paths to Windows native paths. This is a noop otherwise.
+    def cygpath(p):
+        return cygpath_to_windows(p)
+else:
+    def cygpath(p):
+        return p
index 00e3072580837d4d546649ad7a372aa6355f0f30..53e6e840ae6dfcbb71a6f4d00d916e113a8d594c 100644 (file)
@@ -1,2 +1,2 @@
 from litex.build.xilinx.platform import XilinxPlatform
-from litex.build.xilinx.programmer import XC3SProg, FpgaProg, VivadoProgrammer, iMPACT
+from litex.build.xilinx.programmer import UrJTAG, XC3SProg, FpgaProg, VivadoProgrammer, iMPACT, Adept
index 1b5a6644a7060cc1102c8960c8255c49fdd39e7f..9bdaaa5c2694351c9f798ff9c4f9835cc1921d7e 100644 (file)
@@ -48,7 +48,7 @@ def _build_ucf(named_sc, named_pc):
 def _build_xst_files(device, sources, vincpaths, build_name, xst_opt):
     prj_contents = ""
     for filename, language, library in sources:
-        prj_contents += language + " " + library + " " + filename + "\n"
+        prj_contents += language + " " + library + " " + tools.cygpath(filename) + "\n"
     tools.write_to_file(build_name + ".prj", prj_contents)
 
     xst_contents = """run
@@ -59,7 +59,7 @@ def _build_xst_files(device, sources, vincpaths, build_name, xst_opt):
 -p {device}
 """.format(build_name=build_name, xst_opt=xst_opt, device=device)
     for path in vincpaths:
-        xst_contents += "-vlgincdir " + path + "\n"
+        xst_contents += "-vlgincdir " + tools.cygpath(path) + "\n"
     tools.write_to_file(build_name + ".xst", xst_contents)
 
 
@@ -98,10 +98,12 @@ def _run_ise(build_name, ise_path, source, mode, ngdbuild_opt,
         fail_stmt = ""
     if source:
         settings = common.settings(ise_path, ver, "ISE_DS")
-        build_script_contents += source_cmd + settings + "\n"
-
-    ext = "ngc"
-    build_script_contents += """
+        build_script_contents += source_cmd + tools.cygpath(settings) + "\n"
+    if mode == "edif":
+        ext = "edif"
+    else:
+        ext = "ngc"
+        build_script_contents += """
 xst -ifn {build_name}.xst{fail_stmt}
 """
 
@@ -181,7 +183,7 @@ class XilinxISEToolchain:
                 named_sc, named_pc = platform.resolve_signals(vns)
                 v_file = build_name + ".v"
                 v_output.write(v_file)
-                sources = platform.sources + [(v_file, "verilog", "work")]
+                sources = platform.sources | {(v_file, "verilog", "work")}
                 if mode in ("xst", "cpld"):
                     _build_xst_files(platform.device, sources, platform.verilog_include_paths, build_name, self.xst_opt)
                     isemode = mode
index 38c95364d8776ccd42c2d41bade6bc3d23e16ce7..4c60b091eaa665061c96054f4687a7303c2eefef 100644 (file)
@@ -183,3 +183,30 @@ endgroup
 quit
 """.format(data=data_file, flash_part=self.flash_part, device=device)
         _run_vivado(self.vivado_path, self.vivado_ver, cmds)
+
+
+class Adept(GenericProgrammer):
+    """Using the Adept tool with an onboard Digilent "USB JTAG" cable.
+
+    You need to install Adept Utilities V2 from
+    http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,66,828&Prod=ADEPT2
+    """
+
+    needs_bitreverse = False
+
+    def __init__(self, board, index, flash_proxy_basename=None):
+        GenericProgrammer.__init__(self, flash_proxy_basename)
+        self.board = board
+        self.index = index
+
+    def load_bitstream(self, bitstream_file):
+        subprocess.call([
+            "djtgcfg",
+            "--verbose",
+            "prog", "-d", self.board,
+            "-i", str(self.index),
+            "-f", bitstream_file,
+            ])
+
+    def flash(self, address, data_file):
+        raise ValueError("Flashing unsupported with DigilentAdept tools")
index 4859c149c35e8dc7f4ff182d3a5df193219fc2d0..501c4417d553708c514192eeee978e2f27929568 100644 (file)
@@ -214,14 +214,7 @@ class XilinxVivadoToolchain:
         )
 
     def build(self, platform, fragment, build_dir="build", build_name="top",
-            toolchain_path=None, source=True, run=True, synth_mode="vivado", **kwargs):
-        if toolchain_path is None:
-            if sys.platform == "win32":
-                toolchain_path = "C:\\Xilinx\\Vivado"
-            elif sys.platform == "cygwin":
-                toolchain_path = "/cygdrive/c/Xilinx/Vivado"
-            else:
-                toolchain_path = "/opt/Xilinx/Vivado"
+            toolchain_path="/opt/Xilinx/Vivado", source=True, run=True):
         os.makedirs(build_dir, exist_ok=True)
         cwd = os.getcwd()
         os.chdir(build_dir)
@@ -235,7 +228,7 @@ class XilinxVivadoToolchain:
         named_sc, named_pc = platform.resolve_signals(v_output.ns)
         v_file = build_name + ".v"
         v_output.write(v_file)
-        sources = platform.sources + [(v_file, "verilog", "work")]
+        sources = platform.sources | {(v_file, "verilog", "work")}
         edifs = platform.edifs
         ips = platform.ips
         self._build_batch(platform, sources, edifs, ips, build_name, synth_mode=synth_mode)