From: Florent Kermarrec Date: Thu, 26 Feb 2015 11:10:41 +0000 (+0100) Subject: mibuild: better file organization (create directory for each vendor and move programm... X-Git-Tag: 24jan2021_ls180~2099^2~245 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b3faf5f0da631575917c5e27a88256a2cc1c7cb0;p=litex.git mibuild: better file organization (create directory for each vendor and move programmers in it) --- diff --git a/examples/cordic/cordic_impl.py b/examples/cordic/cordic_impl.py index d4c2e066..a1f329b5 100644 --- a/examples/cordic/cordic_impl.py +++ b/examples/cordic/cordic_impl.py @@ -6,7 +6,7 @@ from migen.genlib.cordic import Cordic from mibuild.tools import mkdir_noerror from mibuild.generic_platform import * from mibuild.crg import SimpleCRG -from mibuild.xilinx_ise import XilinxISEPlatform +from mibuild.xilinx.ise import XilinxISEPlatform class CordicImpl(Module): def __init__(self, name, **kwargs): diff --git a/mibuild/altera/__init__.py b/mibuild/altera/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/mibuild/altera/programmer.py b/mibuild/altera/programmer.py new file mode 100644 index 00000000..c6f25cbe --- /dev/null +++ b/mibuild/altera/programmer.py @@ -0,0 +1,10 @@ +import subprocess + +from mibuild.generic_programmer import GenericProgrammer + +class USBBlaster(GenericProgrammer): + needs_bitreverse = False + + def load_bitstream(self, bitstream_file, port=0): + usb_port = "[USB-"+str(port)+"]" + subprocess.call(["quartus_pgm", "-m", "jtag", "-c", "USB-Blaster"+usb_port, "-o", "p;"+bitstream_file]) diff --git a/mibuild/altera/quartus.py b/mibuild/altera/quartus.py new file mode 100644 index 00000000..348596a5 --- /dev/null +++ b/mibuild/altera/quartus.py @@ -0,0 +1,98 @@ +# This file is Copyright (c) 2013 Florent Kermarrec +# License: BSD + +import os, subprocess + +from migen.fhdl.structure import _Fragment +from mibuild.generic_platform import * +from mibuild import tools + +def _format_constraint(c): + if isinstance(c, Pins): + return "set_location_assignment PIN_" + c.identifiers[0] + elif isinstance(c, IOStandard): + return "set_instance_assignment -name IO_STANDARD " + "\"" + c.name + "\"" + elif isinstance(c, Misc): + return c.misc + +def _format_qsf(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 = "" + for c in fmt_c: + r += c + " -to " + signame + " # " + fmt_r + "\n" + return r + +def _build_qsf(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_qsf(sig + "[" + str(i) + "]", p, others, resname) + else: + r += _format_qsf(sig, pins[0], others, resname) + if named_pc: + r += "\n" + "\n\n".join(named_pc) + r += "set_global_assignment -name top_level_entity top\n" + return r + +def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name): + qsf_contents = "" + for filename, language in sources: + # Enforce use of SystemVerilog (Quartus does not support global parameters in Verilog) + if language == "verilog": + language = "systemverilog" + qsf_contents += "set_global_assignment -name "+language.upper()+"_FILE " + filename.replace("\\","/") + "\n" + + for path in vincpaths: + qsf_contents += "set_global_assignment -name SEARCH_PATH " + path.replace("\\","/") + "\n" + + qsf_contents += _build_qsf(named_sc, named_pc) + qsf_contents += "set_global_assignment -name DEVICE " + device + tools.write_to_file(build_name + ".qsf", qsf_contents) + +def _run_quartus(build_name, quartus_path): + build_script_contents = """# Autogenerated by mibuild + +quartus_map --read_settings_files=on --write_settings_files=off {build_name} -c {build_name} +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} + +""".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 AlteraQuartusPlatform(GenericPlatform): + bitstream_ext = ".sof" + def build(self, fragment, build_dir="build", build_name="top", + quartus_path="/opt/Altera", 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, vns = self.get_verilog(fragment) + named_sc, named_pc = self.resolve_signals(vns) + 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, named_sc, named_pc, build_name) + if run: + _run_quartus(build_name, quartus_path) + + os.chdir("..") + + return vns + + def add_period_constraint(self, clk, period): + self.add_platform_command("""set_global_assignment -name DUTY_CYCLE 50 -section_id {clk}""", clk=clk) + self.add_platform_command("""set_global_assignment -name FMAX_REQUIREMENT "{freq} MHz" -section_id {clk}\n""".format(freq=str(float(1/period)*1000), clk="{clk}"), clk=clk) diff --git a/mibuild/altera_quartus.py b/mibuild/altera_quartus.py deleted file mode 100644 index 348596a5..00000000 --- a/mibuild/altera_quartus.py +++ /dev/null @@ -1,98 +0,0 @@ -# This file is Copyright (c) 2013 Florent Kermarrec -# License: BSD - -import os, subprocess - -from migen.fhdl.structure import _Fragment -from mibuild.generic_platform import * -from mibuild import tools - -def _format_constraint(c): - if isinstance(c, Pins): - return "set_location_assignment PIN_" + c.identifiers[0] - elif isinstance(c, IOStandard): - return "set_instance_assignment -name IO_STANDARD " + "\"" + c.name + "\"" - elif isinstance(c, Misc): - return c.misc - -def _format_qsf(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 = "" - for c in fmt_c: - r += c + " -to " + signame + " # " + fmt_r + "\n" - return r - -def _build_qsf(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_qsf(sig + "[" + str(i) + "]", p, others, resname) - else: - r += _format_qsf(sig, pins[0], others, resname) - if named_pc: - r += "\n" + "\n\n".join(named_pc) - r += "set_global_assignment -name top_level_entity top\n" - return r - -def _build_files(device, sources, vincpaths, named_sc, named_pc, build_name): - qsf_contents = "" - for filename, language in sources: - # Enforce use of SystemVerilog (Quartus does not support global parameters in Verilog) - if language == "verilog": - language = "systemverilog" - qsf_contents += "set_global_assignment -name "+language.upper()+"_FILE " + filename.replace("\\","/") + "\n" - - for path in vincpaths: - qsf_contents += "set_global_assignment -name SEARCH_PATH " + path.replace("\\","/") + "\n" - - qsf_contents += _build_qsf(named_sc, named_pc) - qsf_contents += "set_global_assignment -name DEVICE " + device - tools.write_to_file(build_name + ".qsf", qsf_contents) - -def _run_quartus(build_name, quartus_path): - build_script_contents = """# Autogenerated by mibuild - -quartus_map --read_settings_files=on --write_settings_files=off {build_name} -c {build_name} -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} - -""".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 AlteraQuartusPlatform(GenericPlatform): - bitstream_ext = ".sof" - def build(self, fragment, build_dir="build", build_name="top", - quartus_path="/opt/Altera", 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, vns = self.get_verilog(fragment) - named_sc, named_pc = self.resolve_signals(vns) - 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, named_sc, named_pc, build_name) - if run: - _run_quartus(build_name, quartus_path) - - os.chdir("..") - - return vns - - def add_period_constraint(self, clk, period): - self.add_platform_command("""set_global_assignment -name DUTY_CYCLE 50 -section_id {clk}""", clk=clk) - self.add_platform_command("""set_global_assignment -name FMAX_REQUIREMENT "{freq} MHz" -section_id {clk}\n""".format(freq=str(float(1/period)*1000), clk="{clk}"), clk=clk) diff --git a/mibuild/generic_programmer.py b/mibuild/generic_programmer.py new file mode 100644 index 00000000..da3b0c26 --- /dev/null +++ b/mibuild/generic_programmer.py @@ -0,0 +1,30 @@ +import os + +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"] + + def set_flash_proxy_dir(self, flash_proxy_dir): + if flash_proxy_dir is not None: + self.flash_proxy_dirs = [flash_proxy_dir] + + 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) + if os.path.exists(fullname): + return fullname + raise OSError("Failed to find flash proxy bitstream") + + # must be overloaded by specific programmer + def load_bitstream(self, bitstream_file): + raise NotImplementedError + + # must be overloaded by specific programmer + def flash(self, address, data_file): + raise NotImplementedError + + diff --git a/mibuild/platforms/apf27.py b/mibuild/platforms/apf27.py index 23c99cdd..048b857b 100644 --- a/mibuild/platforms/apf27.py +++ b/mibuild/platforms/apf27.py @@ -1,6 +1,6 @@ from mibuild.generic_platform import * from mibuild.crg import SimpleCRG -from mibuild.xilinx_ise import XilinxISEPlatform +from mibuild.xilinx.ise import XilinxISEPlatform _ios = [ ("clk0", 0, Pins("N9"), IOStandard("LVCMOS18")), diff --git a/mibuild/platforms/apf51.py b/mibuild/platforms/apf51.py index 78c8dc1f..e15eb27a 100644 --- a/mibuild/platforms/apf51.py +++ b/mibuild/platforms/apf51.py @@ -1,6 +1,6 @@ from mibuild.generic_platform import * from mibuild.crg import SimpleCRG -from mibuild.xilinx_ise import XilinxISEPlatform +from mibuild.xilinx.ise import XilinxISEPlatform _ios = [ ("clk3", 0, Pins("N8"), IOStandard("LVCMOS33")), diff --git a/mibuild/platforms/de0nano.py b/mibuild/platforms/de0nano.py index 0d567c15..d0c99046 100644 --- a/mibuild/platforms/de0nano.py +++ b/mibuild/platforms/de0nano.py @@ -3,8 +3,8 @@ from mibuild.generic_platform import * from mibuild.crg import SimpleCRG -from mibuild.altera_quartus import AlteraQuartusPlatform -from mibuild.programmer import USBBlaster +from mibuild.altera.quartus import AlteraQuartusPlatform +from mibuild.altera.programmer import USBBlaster _io = [ ("clk50", 0, Pins("R8"), IOStandard("3.3-V LVTTL")), diff --git a/mibuild/platforms/kc705.py b/mibuild/platforms/kc705.py index 468fc1dd..1deab34a 100644 --- a/mibuild/platforms/kc705.py +++ b/mibuild/platforms/kc705.py @@ -1,9 +1,9 @@ from mibuild.generic_platform import * from mibuild.crg import SimpleCRG from mibuild.xilinx_common import CRG_DS -from mibuild.xilinx_ise import XilinxISEPlatform -from mibuild.xilinx_vivado import XilinxVivadoPlatform -from mibuild.programmer import XC3SProg +from mibuild.xilinx.ise import XilinxISEPlatform +from mibuild.xilinx.vivado import XilinxVivadoPlatform +from mibuild.xilinx.programmer import XC3SProg _io = [ ("user_led", 0, Pins("AB8"), IOStandard("LVCMOS15")), diff --git a/mibuild/platforms/lx9_microboard.py b/mibuild/platforms/lx9_microboard.py index 08d61249..a46d6319 100644 --- a/mibuild/platforms/lx9_microboard.py +++ b/mibuild/platforms/lx9_microboard.py @@ -1,6 +1,6 @@ from mibuild.generic_platform import * from mibuild.crg import SimpleCRG -from mibuild.xilinx_ise import XilinxISEPlatform +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 6f1e3655..37b12cf0 100644 --- a/mibuild/platforms/m1.py +++ b/mibuild/platforms/m1.py @@ -1,7 +1,7 @@ from mibuild.generic_platform import * from mibuild.crg import SimpleCRG -from mibuild.xilinx_ise import XilinxISEPlatform -from mibuild.programmer import UrJTAG +from mibuild.xilinx.ise import XilinxISEPlatform +from mibuild.xilinx.programmer import UrJTAG _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 69ea30c0..d09f546a 100644 --- a/mibuild/platforms/mixxeo.py +++ b/mibuild/platforms/mixxeo.py @@ -1,7 +1,7 @@ from mibuild.generic_platform import * from mibuild.crg import SimpleCRG -from mibuild.xilinx_ise import XilinxISEPlatform -from mibuild.programmer import UrJTAG +from mibuild.xilinx.ise import XilinxISEPlatform +from mibuild.xilinx.programmer import UrJTAG _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 ab263909..f8236800 100644 --- a/mibuild/platforms/ml605.py +++ b/mibuild/platforms/ml605.py @@ -1,6 +1,6 @@ from mibuild.generic_platform import * from mibuild.xilinx_common import CRG_DS -from mibuild.xilinx_ise import XilinxISEPlatform +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 4e29ba5d..82315552 100644 --- a/mibuild/platforms/papilio_pro.py +++ b/mibuild/platforms/papilio_pro.py @@ -1,7 +1,7 @@ from mibuild.generic_platform import * from mibuild.crg import SimpleCRG -from mibuild.xilinx_ise import XilinxISEPlatform -from mibuild.programmer import XC3SProg +from mibuild.xilinx.ise import XilinxISEPlatform +from mibuild.xilinx.programmer import XC3SProg _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 8aafa55d..f1af075e 100644 --- a/mibuild/platforms/rhino.py +++ b/mibuild/platforms/rhino.py @@ -1,6 +1,6 @@ from mibuild.generic_platform import * from mibuild.xilinx_common import CRG_DS -from mibuild.xilinx_ise import XilinxISEPlatform +from mibuild.xilinx.ise import XilinxISEPlatform _io = [ ("user_led", 0, Pins("Y3")), diff --git a/mibuild/platforms/roach.py b/mibuild/platforms/roach.py index 495b808f..d20d611b 100644 --- a/mibuild/platforms/roach.py +++ b/mibuild/platforms/roach.py @@ -1,5 +1,5 @@ from mibuild.generic_platform import * -from mibuild.xilinx_ise import XilinxISEPlatform +from mibuild.xilinx.ise import XilinxISEPlatform _io = [ ("epb", 0, diff --git a/mibuild/platforms/usrp_b100.py b/mibuild/platforms/usrp_b100.py index 9972d5b7..1fb30080 100644 --- a/mibuild/platforms/usrp_b100.py +++ b/mibuild/platforms/usrp_b100.py @@ -1,6 +1,6 @@ from mibuild.generic_platform import * from mibuild.xilinx_common import CRG_DS -from mibuild.xilinx_ise import XilinxISEPlatform +from mibuild.xilinx.ise import XilinxISEPlatform _io = [ ("clk64", 0, diff --git a/mibuild/platforms/zedboard.py b/mibuild/platforms/zedboard.py index 33c9fc16..2a3e91c6 100644 --- a/mibuild/platforms/zedboard.py +++ b/mibuild/platforms/zedboard.py @@ -1,6 +1,6 @@ from mibuild.generic_platform import * from mibuild.crg import SimpleCRG -from mibuild.xilinx_ise import XilinxISEPlatform +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 ece202f6..970b1e7d 100644 --- a/mibuild/platforms/ztex_115d.py +++ b/mibuild/platforms/ztex_115d.py @@ -1,6 +1,6 @@ from mibuild.generic_platform import * from mibuild.crg import SimpleCRG -from mibuild.xilinx_ise import XilinxISEPlatform +from mibuild.xilinx.ise import XilinxISEPlatform _io = [ ("clk_fx", 0, Pins("L22"), IOStandard("LVCMOS33")), diff --git a/mibuild/programmer.py b/mibuild/programmer.py deleted file mode 100644 index 71a67281..00000000 --- a/mibuild/programmer.py +++ /dev/null @@ -1,74 +0,0 @@ -import subprocess -import os - -class Programmer: - 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"] - - def set_flash_proxy_dir(self, flash_proxy_dir): - if flash_proxy_dir is not None: - self.flash_proxy_dirs = [flash_proxy_dir] - - 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) - if os.path.exists(fullname): - return fullname - raise OSError("Failed to find flash proxy bitstream") - -def _run_urjtag(cmds): - with subprocess.Popen("jtag", stdin=subprocess.PIPE) as process: - process.stdin.write(cmds.encode("ASCII")) - process.communicate() - -class UrJTAG(Programmer): - needs_bitreverse = True - - def load_bitstream(self, bitstream_file): - cmds = """cable milkymist -detect -pld load {bitstream} -quit -""".format(bitstream=bitstream_file) - _run_urjtag(cmds) - - def flash(self, address, data_file): - flash_proxy = self.find_flash_proxy() - cmds = """cable milkymist -detect -pld load "{flash_proxy}" -initbus fjmem opcode=000010 -frequency 6000000 -detectflash 0 -endian big -flashmem "{address}" "{data_file}" noverify -""".format(flash_proxy=flash_proxy, address=address, data_file=data_file) - _run_urjtag(cmds) - -class XC3SProg(Programmer): - needs_bitreverse = False - - def __init__(self, cable, flash_proxy_basename=None): - Programmer.__init__(self, flash_proxy_basename) - self.cable = cable - - def load_bitstream(self, bitstream_file): - subprocess.call(["xc3sprog", "-v", "-c", self.cable, bitstream_file]) - - def flash(self, address, data_file): - flash_proxy = self.find_flash_proxy() - subprocess.call(["xc3sprog", "-v", "-c", self.cable, "-I"+flash_proxy, "{}:w:0x{:x}:BIN".format(data_file, address)]) - -class USBBlaster(Programmer): - needs_bitreverse = False - - def load_bitstream(self, bitstream_file, port=0): - usb_port = "[USB-"+str(port)+"]" - subprocess.call(["quartus_pgm", "-m", "jtag", "-c", "USB-Blaster"+usb_port, "-o", "p;"+bitstream_file]) - - def flash(self, address, data_file): - raise NotImplementedError diff --git a/mibuild/xilinx/__init__.py b/mibuild/xilinx/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/mibuild/xilinx/common.py b/mibuild/xilinx/common.py new file mode 100644 index 00000000..507a8cb8 --- /dev/null +++ b/mibuild/xilinx/common.py @@ -0,0 +1,98 @@ +import os +from distutils.version import StrictVersion + +from migen.fhdl.std import * +from migen.fhdl.specials import SynthesisDirective +from migen.genlib.cdc import * +from migen.genlib.resetsync import AsyncResetSynchronizer +from mibuild.generic_platform import GenericPlatform +from mibuild import tools + +def settings(path, ver=None, sub=None): + vers = list(tools.versions(path)) + if ver is None: + ver = max(vers) + else: + ver = StrictVersion(ver) + assert ver in vers + + full = os.path.join(path, str(ver)) + if sub: + full = os.path.join(full, sub) + + search = [64, 32] + if tools.arch_bits() == 32: + search.reverse() + + for b in search: + settings = os.path.join(full, "settings{0}.sh".format(b)) + if os.path.exists(settings): + return settings + + raise ValueError("no settings file found") + +class CRG_DS(Module): + def __init__(self, platform, clk_name, rst_name, 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) + 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)) + +class XilinxNoRetimingImpl(Module): + def __init__(self, reg): + self.specials += SynthesisDirective("attribute register_balancing of {r} is no", r=reg) + +class XilinxNoRetiming: + @staticmethod + def lower(dr): + return XilinxNoRetimingImpl(dr.reg) + +class XilinxMultiRegImpl(MultiRegImpl): + def __init__(self, *args, **kwargs): + MultiRegImpl.__init__(self, *args, **kwargs) + self.specials += [SynthesisDirective("attribute shreg_extract of {r} is no", r=r) + for r in self.regs] + +class XilinxMultiReg: + @staticmethod + def lower(dr): + return XilinxMultiRegImpl(dr.i, dr.o, dr.odomain, dr.n) + +class XilinxAsyncResetSynchronizerImpl(Module): + def __init__(self, cd, async_reset): + rst1 = Signal() + self.specials += [ + Instance("FDPE", p_INIT=1, i_D=0, i_PRE=async_reset, + i_CE=1, i_C=cd.clk, o_Q=rst1), + Instance("FDPE", p_INIT=1, i_D=rst1, i_PRE=async_reset, + i_CE=1, i_C=cd.clk, o_Q=cd.rst) + ] + +class XilinxAsyncResetSynchronizer: + @staticmethod + def lower(dr): + return XilinxAsyncResetSynchronizerImpl(dr.cd, dr.async_reset) + +class XilinxGenericPlatform(GenericPlatform): + bitstream_ext = ".bit" + + def get_verilog(self, *args, special_overrides=dict(), **kwargs): + so = { + NoRetiming: XilinxNoRetiming, + MultiReg: XilinxMultiReg, + AsyncResetSynchronizer: XilinxAsyncResetSynchronizer + } + so.update(special_overrides) + return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) + + def get_edif(self, fragment, **kwargs): + return GenericPlatform.get_edif(self, fragment, "UNISIMS", "Xilinx", self.device, **kwargs) diff --git a/mibuild/xilinx/ise.py b/mibuild/xilinx/ise.py new file mode 100644 index 00000000..5935c1a0 --- /dev/null +++ b/mibuild/xilinx/ise.py @@ -0,0 +1,183 @@ +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 import common + +def _format_constraint(c): + if isinstance(c, Pins): + return "LOC=" + c.identifiers[0] + elif isinstance(c, IOStandard): + return "IOSTANDARD=" + c.name + elif isinstance(c, Drive): + return "DRIVE=" + str(c.strength) + elif isinstance(c, Misc): + return c.misc + +def _format_ucf(signame, pin, others, resname): + fmt_c = [] + for c in [Pins(pin)] + others: + fc = _format_constraint(c) + if fc is not None: + fmt_c.append(fc) + fmt_r = resname[0] + ":" + str(resname[1]) + if resname[2] is not None: + fmt_r += "." + resname[2] + return "NET \"" + signame + "\" " + " | ".join(fmt_c) + "; # " + fmt_r + "\n" + +def _build_ucf(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_ucf(sig + "(" + str(i) + ")", p, others, resname) + else: + r += _format_ucf(sig, pins[0], others, resname) + if named_pc: + r += "\n" + "\n\n".join(named_pc) + return r + +def _build_xst_files(device, sources, vincpaths, build_name, xst_opt): + prj_contents = "" + for filename, language in sources: + prj_contents += language + " work " + filename + "\n" + tools.write_to_file(build_name + ".prj", prj_contents) + + xst_contents = """run +-ifn {build_name}.prj +-top top +{xst_opt} +-ofn {build_name}.ngc +-p {device} +""".format(build_name=build_name, xst_opt=xst_opt, device=device) + for path in vincpaths: + xst_contents += "-vlgincdir " + path + "\n" + tools.write_to_file(build_name + ".xst", xst_contents) + +def _run_yosys(device, sources, vincpaths, build_name): + ys_contents = "" + incflags = "" + for path in vincpaths: + incflags += " -I" + path + for filename, language in sources: + ys_contents += "read_{}{} {}\n".format(language, incflags, 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 _run_ise(build_name, ise_path, source, mode, ngdbuild_opt, + bitgen_opt, ise_commands, map_opt, par_opt, ver=None): + if sys.platform == "win32" or sys.platform == "cygwin": + source = False + build_script_contents = "# Autogenerated by mibuild\nset -e\n" + if source: + settings = common.settings(ise_path, ver, "ISE_DS") + build_script_contents += "source " + settings + "\n" + if mode == "edif": + ext = "edif" + else: + ext = "ngc" + build_script_contents += """ +xst -ifn {build_name}.xst +""" + + build_script_contents += """ +ngdbuild {ngdbuild_opt} -uc {build_name}.ucf {build_name}.{ext} {build_name}.ngd +map {map_opt} -o {build_name}_map.ncd {build_name}.ngd {build_name}.pcf +par {par_opt} {build_name}_map.ncd {build_name}.ncd {build_name}.pcf +bitgen {bitgen_opt} {build_name}.ncd {build_name}.bit +""" + build_script_contents = build_script_contents.format(build_name=build_name, + ngdbuild_opt=ngdbuild_opt, bitgen_opt=bitgen_opt, ext=ext, + par_opt=par_opt, map_opt=map_opt) + build_script_contents += ise_commands.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 XilinxISEPlatform(common.XilinxGenericPlatform): + xst_opt = """-ifmt MIXED +-opt_mode SPEED +-register_balancing yes""" + map_opt = "-ol high -w" + par_opt = "-ol high -w" + ngdbuild_opt = "" + bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w" + ise_commands = "" + + def build(self, fragment, build_dir="build", build_name="top", + ise_path="/opt/Xilinx", source=True, run=True, mode="xst"): + tools.mkdir_noerror(build_dir) + os.chdir(build_dir) + + if not isinstance(fragment, _Fragment): + fragment = fragment.get_fragment() + self.finalize(fragment) + + ngdbuild_opt = self.ngdbuild_opt + + vns = None + + if mode == "xst" or mode == "yosys": + v_src, vns = self.get_verilog(fragment) + named_sc, named_pc = self.resolve_signals(vns) + v_file = build_name + ".v" + tools.write_to_file(v_file, v_src) + sources = self.sources + [(v_file, "verilog")] + if mode == "xst": + _build_xst_files(self.device, sources, self.verilog_include_paths, build_name, self.xst_opt) + isemode = "xst" + else: + _run_yosys(self.device, sources, self.verilog_include_paths, build_name) + isemode = "edif" + ngdbuild_opt += "-p " + self.device + + if mode == "mist": + from mist import synthesize + synthesize(fragment, self.constraint_manager.get_io_signals()) + + if mode == "edif" or mode == "mist": + e_src, vns = self.get_edif(fragment) + named_sc, named_pc = self.resolve_signals(vns) + e_file = build_name + ".edif" + tools.write_to_file(e_file, e_src) + 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, self.bitgen_opt, self.ise_commands, + self.map_opt, self.par_opt) + + os.chdir("..") + + return vns + + def add_period_constraint(self, clk, period): + self.add_platform_command("""NET "{clk}" TNM_NET = "GRP{clk}"; +TIMESPEC "TS{clk}" = PERIOD "GRP{clk}" """+str(period)+""" ns HIGH 50%;""", clk=clk) diff --git a/mibuild/xilinx/programmer.py b/mibuild/xilinx/programmer.py new file mode 100644 index 00000000..79cf1557 --- /dev/null +++ b/mibuild/xilinx/programmer.py @@ -0,0 +1,46 @@ +import subprocess + +from mibuild.generic_programmer import GenericProgrammer + +def _run_urjtag(cmds): + with subprocess.Popen("jtag", stdin=subprocess.PIPE) as process: + process.stdin.write(cmds.encode("ASCII")) + process.communicate() + +class UrJTAG(GenericProgrammer): + needs_bitreverse = True + + def load_bitstream(self, bitstream_file): + cmds = """cable milkymist +detect +pld load {bitstream} +quit +""".format(bitstream=bitstream_file) + _run_urjtag(cmds) + + def flash(self, address, data_file): + flash_proxy = self.find_flash_proxy() + cmds = """cable milkymist +detect +pld load "{flash_proxy}" +initbus fjmem opcode=000010 +frequency 6000000 +detectflash 0 +endian big +flashmem "{address}" "{data_file}" noverify +""".format(flash_proxy=flash_proxy, address=address, data_file=data_file) + _run_urjtag(cmds) + +class XC3SProg(GenericProgrammer): + needs_bitreverse = False + + def __init__(self, cable, flash_proxy_basename=None): + Programmer.__init__(self, flash_proxy_basename) + self.cable = cable + + def load_bitstream(self, bitstream_file): + subprocess.call(["xc3sprog", "-v", "-c", self.cable, bitstream_file]) + + def flash(self, address, data_file): + flash_proxy = self.find_flash_proxy() + subprocess.call(["xc3sprog", "-v", "-c", self.cable, "-I"+flash_proxy, "{}:w:0x{:x}:BIN".format(data_file, address)]) diff --git a/mibuild/xilinx/vivado.py b/mibuild/xilinx/vivado.py new file mode 100644 index 00000000..49747179 --- /dev/null +++ b/mibuild/xilinx/vivado.py @@ -0,0 +1,123 @@ +# 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 import common + +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 "set_property " + c.misc.replace("=", " ") + +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, bitstream_commands, additional_commands): + tcl = [] + for filename, language in sources: + tcl.append("add_files " + filename.replace("\\", "/")) + + tcl.append("read_xdc %s.xdc" %build_name) + tcl.append("synth_design -top top -part %s -include_dirs {%s}" %(device, " ".join(vincpaths))) + tcl.append("report_utilization -hierarchical -file %s_utilization_hierarchical_synth.rpt" %(build_name)) + tcl.append("report_utilization -file %s_utilization_synth.rpt" %(build_name)) + tcl.append("place_design") + tcl.append("report_utilization -hierarchical -file %s_utilization_hierarchical_place.rpt" %(build_name)) + tcl.append("report_utilization -file %s_utilization_place.rpt" %(build_name)) + tcl.append("report_io -file %s_io.rpt" %(build_name)) + tcl.append("report_control_sets -verbose -file %s_control_sets.rpt" %(build_name)) + tcl.append("report_clock_utilization -file %s_clock_utilization.rpt" %(build_name)) + tcl.append("route_design") + tcl.append("report_route_status -file %s_route_status.rpt" %(build_name)) + tcl.append("report_drc -file %s_drc.rpt" %(build_name)) + tcl.append("report_timing_summary -max_paths 10 -file %s_timing.rpt" %(build_name)) + tcl.append("report_power -file %s_power.rpt" %(build_name)) + for bitstream_command in bitstream_commands: + tcl.append(bitstream_command.format(build_name=build_name)) + tcl.append("write_bitstream -force %s.bit " %build_name) + for additional_command in additional_commands: + tcl.append(additional_command.format(build_name=build_name)) + tcl.append("quit") + tools.write_to_file(build_name + ".tcl", "\n".join(tcl)) + +def _run_vivado(build_name, vivado_path, source, ver=None): + if sys.platform == "win32" or sys.platform == "cygwin": + build_script_contents = "REM Autogenerated by mibuild\n" + build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n" + build_script_file = "build_" + build_name + ".bat" + tools.write_to_file(build_script_file, build_script_contents) + r = subprocess.call([build_script_file]) + else: + build_script_contents = "# Autogenerated by mibuild\nset -e\n" + settings = common.settings(vivado_path, ver) + build_script_contents += "source " + settings + "\n" + build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n" + build_script_file = "build_" + build_name + ".sh" + tools.write_to_file(build_script_file, build_script_contents) + r = subprocess.call(["bash", build_script_file]) + + if r != 0: + raise OSError("Subprocess failed") + +class XilinxVivadoPlatform(common.XilinxGenericPlatform): + def __init__(self, *args, **kwargs): + common.XilinxGenericPlatform.__init__(self, *args, **kwargs) + self.bitstream_commands = [] + self.additional_commands = [] + + def build(self, fragment, build_dir="build", build_name="top", + vivado_path="/opt/Xilinx/Vivado", 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, vns = self.get_verilog(fragment) + named_sc, named_pc = self.resolve_signals(vns) + 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, + self.bitstream_commands, self.additional_commands) + tools.write_to_file(build_name + ".xdc", _build_xdc(named_sc, named_pc)) + if run: + _run_vivado(build_name, vivado_path, source) + + os.chdir("..") + + return vns + + def add_period_constraint(self, clk, period): + self.add_platform_command("""create_clock -name {clk} -period """ +\ + str(period) + """ [get_ports {clk}]""", clk=clk) diff --git a/mibuild/xilinx_common.py b/mibuild/xilinx_common.py deleted file mode 100644 index 507a8cb8..00000000 --- a/mibuild/xilinx_common.py +++ /dev/null @@ -1,98 +0,0 @@ -import os -from distutils.version import StrictVersion - -from migen.fhdl.std import * -from migen.fhdl.specials import SynthesisDirective -from migen.genlib.cdc import * -from migen.genlib.resetsync import AsyncResetSynchronizer -from mibuild.generic_platform import GenericPlatform -from mibuild import tools - -def settings(path, ver=None, sub=None): - vers = list(tools.versions(path)) - if ver is None: - ver = max(vers) - else: - ver = StrictVersion(ver) - assert ver in vers - - full = os.path.join(path, str(ver)) - if sub: - full = os.path.join(full, sub) - - search = [64, 32] - if tools.arch_bits() == 32: - search.reverse() - - for b in search: - settings = os.path.join(full, "settings{0}.sh".format(b)) - if os.path.exists(settings): - return settings - - raise ValueError("no settings file found") - -class CRG_DS(Module): - def __init__(self, platform, clk_name, rst_name, 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) - 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)) - -class XilinxNoRetimingImpl(Module): - def __init__(self, reg): - self.specials += SynthesisDirective("attribute register_balancing of {r} is no", r=reg) - -class XilinxNoRetiming: - @staticmethod - def lower(dr): - return XilinxNoRetimingImpl(dr.reg) - -class XilinxMultiRegImpl(MultiRegImpl): - def __init__(self, *args, **kwargs): - MultiRegImpl.__init__(self, *args, **kwargs) - self.specials += [SynthesisDirective("attribute shreg_extract of {r} is no", r=r) - for r in self.regs] - -class XilinxMultiReg: - @staticmethod - def lower(dr): - return XilinxMultiRegImpl(dr.i, dr.o, dr.odomain, dr.n) - -class XilinxAsyncResetSynchronizerImpl(Module): - def __init__(self, cd, async_reset): - rst1 = Signal() - self.specials += [ - Instance("FDPE", p_INIT=1, i_D=0, i_PRE=async_reset, - i_CE=1, i_C=cd.clk, o_Q=rst1), - Instance("FDPE", p_INIT=1, i_D=rst1, i_PRE=async_reset, - i_CE=1, i_C=cd.clk, o_Q=cd.rst) - ] - -class XilinxAsyncResetSynchronizer: - @staticmethod - def lower(dr): - return XilinxAsyncResetSynchronizerImpl(dr.cd, dr.async_reset) - -class XilinxGenericPlatform(GenericPlatform): - bitstream_ext = ".bit" - - def get_verilog(self, *args, special_overrides=dict(), **kwargs): - so = { - NoRetiming: XilinxNoRetiming, - MultiReg: XilinxMultiReg, - AsyncResetSynchronizer: XilinxAsyncResetSynchronizer - } - so.update(special_overrides) - return GenericPlatform.get_verilog(self, *args, special_overrides=so, **kwargs) - - def get_edif(self, fragment, **kwargs): - return GenericPlatform.get_edif(self, fragment, "UNISIMS", "Xilinx", self.device, **kwargs) diff --git a/mibuild/xilinx_ise.py b/mibuild/xilinx_ise.py deleted file mode 100644 index d291f72f..00000000 --- a/mibuild/xilinx_ise.py +++ /dev/null @@ -1,182 +0,0 @@ -import os, subprocess, sys - -from migen.fhdl.std import * -from migen.fhdl.structure import _Fragment - -from mibuild.generic_platform import * -from mibuild import tools, xilinx_common - -def _format_constraint(c): - if isinstance(c, Pins): - return "LOC=" + c.identifiers[0] - elif isinstance(c, IOStandard): - return "IOSTANDARD=" + c.name - elif isinstance(c, Drive): - return "DRIVE=" + str(c.strength) - elif isinstance(c, Misc): - return c.misc - -def _format_ucf(signame, pin, others, resname): - fmt_c = [] - for c in [Pins(pin)] + others: - fc = _format_constraint(c) - if fc is not None: - fmt_c.append(fc) - fmt_r = resname[0] + ":" + str(resname[1]) - if resname[2] is not None: - fmt_r += "." + resname[2] - return "NET \"" + signame + "\" " + " | ".join(fmt_c) + "; # " + fmt_r + "\n" - -def _build_ucf(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_ucf(sig + "(" + str(i) + ")", p, others, resname) - else: - r += _format_ucf(sig, pins[0], others, resname) - if named_pc: - r += "\n" + "\n\n".join(named_pc) - return r - -def _build_xst_files(device, sources, vincpaths, build_name, xst_opt): - prj_contents = "" - for filename, language in sources: - prj_contents += language + " work " + filename + "\n" - tools.write_to_file(build_name + ".prj", prj_contents) - - xst_contents = """run --ifn {build_name}.prj --top top -{xst_opt} --ofn {build_name}.ngc --p {device} -""".format(build_name=build_name, xst_opt=xst_opt, device=device) - for path in vincpaths: - xst_contents += "-vlgincdir " + path + "\n" - tools.write_to_file(build_name + ".xst", xst_contents) - -def _run_yosys(device, sources, vincpaths, build_name): - ys_contents = "" - incflags = "" - for path in vincpaths: - incflags += " -I" + path - for filename, language in sources: - ys_contents += "read_{}{} {}\n".format(language, incflags, 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 _run_ise(build_name, ise_path, source, mode, ngdbuild_opt, - bitgen_opt, ise_commands, map_opt, par_opt, ver=None): - if sys.platform == "win32" or sys.platform == "cygwin": - source = False - build_script_contents = "# Autogenerated by mibuild\nset -e\n" - if source: - settings = xilinx_common.settings(ise_path, ver, "ISE_DS") - build_script_contents += "source " + settings + "\n" - if mode == "edif": - ext = "edif" - else: - ext = "ngc" - build_script_contents += """ -xst -ifn {build_name}.xst -""" - - build_script_contents += """ -ngdbuild {ngdbuild_opt} -uc {build_name}.ucf {build_name}.{ext} {build_name}.ngd -map {map_opt} -o {build_name}_map.ncd {build_name}.ngd {build_name}.pcf -par {par_opt} {build_name}_map.ncd {build_name}.ncd {build_name}.pcf -bitgen {bitgen_opt} {build_name}.ncd {build_name}.bit -""" - build_script_contents = build_script_contents.format(build_name=build_name, - ngdbuild_opt=ngdbuild_opt, bitgen_opt=bitgen_opt, ext=ext, - par_opt=par_opt, map_opt=map_opt) - build_script_contents += ise_commands.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 XilinxISEPlatform(xilinx_common.XilinxGenericPlatform): - xst_opt = """-ifmt MIXED --opt_mode SPEED --register_balancing yes""" - map_opt = "-ol high -w" - par_opt = "-ol high -w" - ngdbuild_opt = "" - bitgen_opt = "-g LCK_cycle:6 -g Binary:Yes -w" - ise_commands = "" - - def build(self, fragment, build_dir="build", build_name="top", - ise_path="/opt/Xilinx", source=True, run=True, mode="xst"): - tools.mkdir_noerror(build_dir) - os.chdir(build_dir) - - if not isinstance(fragment, _Fragment): - fragment = fragment.get_fragment() - self.finalize(fragment) - - ngdbuild_opt = self.ngdbuild_opt - - vns = None - - if mode == "xst" or mode == "yosys": - v_src, vns = self.get_verilog(fragment) - named_sc, named_pc = self.resolve_signals(vns) - v_file = build_name + ".v" - tools.write_to_file(v_file, v_src) - sources = self.sources + [(v_file, "verilog")] - if mode == "xst": - _build_xst_files(self.device, sources, self.verilog_include_paths, build_name, self.xst_opt) - isemode = "xst" - else: - _run_yosys(self.device, sources, self.verilog_include_paths, build_name) - isemode = "edif" - ngdbuild_opt += "-p " + self.device - - if mode == "mist": - from mist import synthesize - synthesize(fragment, self.constraint_manager.get_io_signals()) - - if mode == "edif" or mode == "mist": - e_src, vns = self.get_edif(fragment) - named_sc, named_pc = self.resolve_signals(vns) - e_file = build_name + ".edif" - tools.write_to_file(e_file, e_src) - 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, self.bitgen_opt, self.ise_commands, - self.map_opt, self.par_opt) - - os.chdir("..") - - return vns - - def add_period_constraint(self, clk, period): - self.add_platform_command("""NET "{clk}" TNM_NET = "GRP{clk}"; -TIMESPEC "TS{clk}" = PERIOD "GRP{clk}" """+str(period)+""" ns HIGH 50%;""", clk=clk) diff --git a/mibuild/xilinx_vivado.py b/mibuild/xilinx_vivado.py deleted file mode 100644 index d55c930e..00000000 --- a/mibuild/xilinx_vivado.py +++ /dev/null @@ -1,122 +0,0 @@ -# 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, xilinx_common - -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 "set_property " + c.misc.replace("=", " ") - -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, bitstream_commands, additional_commands): - tcl = [] - for filename, language in sources: - tcl.append("add_files " + filename.replace("\\", "/")) - - tcl.append("read_xdc %s.xdc" %build_name) - tcl.append("synth_design -top top -part %s -include_dirs {%s}" %(device, " ".join(vincpaths))) - tcl.append("report_utilization -hierarchical -file %s_utilization_hierarchical_synth.rpt" %(build_name)) - tcl.append("report_utilization -file %s_utilization_synth.rpt" %(build_name)) - tcl.append("place_design") - tcl.append("report_utilization -hierarchical -file %s_utilization_hierarchical_place.rpt" %(build_name)) - tcl.append("report_utilization -file %s_utilization_place.rpt" %(build_name)) - tcl.append("report_io -file %s_io.rpt" %(build_name)) - tcl.append("report_control_sets -verbose -file %s_control_sets.rpt" %(build_name)) - tcl.append("report_clock_utilization -file %s_clock_utilization.rpt" %(build_name)) - tcl.append("route_design") - tcl.append("report_route_status -file %s_route_status.rpt" %(build_name)) - tcl.append("report_drc -file %s_drc.rpt" %(build_name)) - tcl.append("report_timing_summary -max_paths 10 -file %s_timing.rpt" %(build_name)) - tcl.append("report_power -file %s_power.rpt" %(build_name)) - for bitstream_command in bitstream_commands: - tcl.append(bitstream_command.format(build_name=build_name)) - tcl.append("write_bitstream -force %s.bit " %build_name) - for additional_command in additional_commands: - tcl.append(additional_command.format(build_name=build_name)) - tcl.append("quit") - tools.write_to_file(build_name + ".tcl", "\n".join(tcl)) - -def _run_vivado(build_name, vivado_path, source, ver=None): - if sys.platform == "win32" or sys.platform == "cygwin": - build_script_contents = "REM Autogenerated by mibuild\n" - build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n" - build_script_file = "build_" + build_name + ".bat" - tools.write_to_file(build_script_file, build_script_contents) - r = subprocess.call([build_script_file]) - else: - build_script_contents = "# Autogenerated by mibuild\nset -e\n" - settings = xilinx_common.settings(vivado_path, ver) - build_script_contents += "source " + settings + "\n" - build_script_contents += "vivado -mode batch -source " + build_name + ".tcl\n" - build_script_file = "build_" + build_name + ".sh" - tools.write_to_file(build_script_file, build_script_contents) - r = subprocess.call(["bash", build_script_file]) - - if r != 0: - raise OSError("Subprocess failed") - -class XilinxVivadoPlatform(xilinx_common.XilinxGenericPlatform): - def __init__(self, *args, **kwargs): - xilinx_common.XilinxGenericPlatform.__init__(self, *args, **kwargs) - self.bitstream_commands = [] - self.additional_commands = [] - - def build(self, fragment, build_dir="build", build_name="top", - vivado_path="/opt/Xilinx/Vivado", 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, vns = self.get_verilog(fragment) - named_sc, named_pc = self.resolve_signals(vns) - 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, - self.bitstream_commands, self.additional_commands) - tools.write_to_file(build_name + ".xdc", _build_xdc(named_sc, named_pc)) - if run: - _run_vivado(build_name, vivado_path, source) - - os.chdir("..") - - return vns - - def add_period_constraint(self, clk, period): - self.add_platform_command("""create_clock -name {clk} -period """ +\ - str(period) + """ [get_ports {clk}]""", clk=clk)