From 665fff8390e87b9314a88729bf1800669dee3954 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 12 Nov 2018 11:26:35 +0100 Subject: [PATCH] build: merge more migen changes --- litex/build/altera/programmer.py | 8 ++++++-- litex/build/altera/quartus.py | 7 +++++-- litex/build/generic_programmer.py | 7 +++++-- litex/build/lattice/diamond.py | 4 ++-- litex/build/lattice/icestorm.py | 12 +++++------ litex/build/lattice/programmer.py | 24 +++++++++++++--------- litex/build/lattice/trellis.py | 5 ++--- litex/build/tools.py | 33 +++++++++++++++++++++++++++++++ litex/build/xilinx/__init__.py | 2 +- litex/build/xilinx/ise.py | 16 ++++++++------- litex/build/xilinx/programmer.py | 27 +++++++++++++++++++++++++ litex/build/xilinx/vivado.py | 11 ++--------- 12 files changed, 113 insertions(+), 43 deletions(-) diff --git a/litex/build/altera/programmer.py b/litex/build/altera/programmer.py index 43d6ff9c..d4871c63 100644 --- a/litex/build/altera/programmer.py +++ b/litex/build/altera/programmer.py @@ -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)]) diff --git a/litex/build/altera/quartus.py b/litex/build/altera/quartus.py index 76ec775c..ef30e78b 100644 --- a/litex/build/altera/quartus.py +++ b/litex/build/altera/quartus.py @@ -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, diff --git a/litex/build/generic_programmer.py b/litex/build/generic_programmer.py index b9540415..0fac6f94 100644 --- a/litex/build/generic_programmer.py +++ b/litex/build/generic_programmer.py @@ -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") diff --git a/litex/build/lattice/diamond.py b/litex/build/lattice/diamond.py index 1569f567..cee157bc 100644 --- a/litex/build/lattice/diamond.py +++ b/litex/build/lattice/diamond.py @@ -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) diff --git a/litex/build/lattice/icestorm.py b/litex/build/lattice/icestorm.py index 72eb0023..8afdaf61 100644 --- a/litex/build/lattice/icestorm.py +++ b/litex/build/lattice/icestorm.py @@ -1,4 +1,4 @@ -# This file is Copyright (c) 2017 William D. Jones +# This file is Copyright (c) 2016-2017 William D. Jones # 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: diff --git a/litex/build/lattice/programmer.py b/litex/build/lattice/programmer.py index 07cc0d1f..c1a14fef 100644 --- a/litex/build/lattice/programmer.py +++ b/litex/build/lattice/programmer.py @@ -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()) diff --git a/litex/build/lattice/trellis.py b/litex/build/lattice/trellis.py index 8f272920..a395c367 100644 --- a/litex/build/lattice/trellis.py +++ b/litex/build/lattice/trellis.py @@ -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) diff --git a/litex/build/tools.py b/litex/build/tools.py index 2bfc1e77..313abaea 100644 --- a/litex/build/tools.py +++ b/litex/build/tools.py @@ -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 diff --git a/litex/build/xilinx/__init__.py b/litex/build/xilinx/__init__.py index 00e30725..53e6e840 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.programmer import XC3SProg, FpgaProg, VivadoProgrammer, iMPACT +from litex.build.xilinx.programmer import UrJTAG, XC3SProg, FpgaProg, VivadoProgrammer, iMPACT, Adept diff --git a/litex/build/xilinx/ise.py b/litex/build/xilinx/ise.py index 1b5a6644..9bdaaa5c 100644 --- a/litex/build/xilinx/ise.py +++ b/litex/build/xilinx/ise.py @@ -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 diff --git a/litex/build/xilinx/programmer.py b/litex/build/xilinx/programmer.py index 38c95364..4c60b091 100644 --- a/litex/build/xilinx/programmer.py +++ b/litex/build/xilinx/programmer.py @@ -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") diff --git a/litex/build/xilinx/vivado.py b/litex/build/xilinx/vivado.py index 4859c149..501c4417 100644 --- a/litex/build/xilinx/vivado.py +++ b/litex/build/xilinx/vivado.py @@ -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) -- 2.30.2