import os, struct, subprocess from decimal import Decimal from migen.fhdl.structure import * from mibuild.generic_platform import * from mibuild.crg import CRG, SimpleCRG from mibuild import tools def _add_period_constraint(platform, clk, period): platform.add_platform_command("""NET "{clk}" TNM_NET = "GRPclk"; TIMESPEC "TSclk" = PERIOD "GRPclk" """+str(period)+""" ns HIGH 50%;""", clk=clk) class CRG_SE(SimpleCRG): def __init__(self, platform, clk_name, rst_name, period): SimpleCRG.__init__(self, platform, clk_name, rst_name) _add_period_constraint(platform, self.cd.clk, period) class CRG_DS(CRG): def __init__(self, platform, clk_name, rst_name, period): self.cd = ClockDomain("sys") self._clk = platform.request(clk_name) platform.request(rst_name, None, self.cd.rst) _add_period_constraint(platform, self._clk.p, period) def get_fragment(self): ibufg = Instance("IBUFGDS", Instance.Input("I", self._clk.p), Instance.Input("IB", self._clk.n), Instance.Output("O", self.cd.clk) ) return Fragment(instances=[ibufg]) 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 = [_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] 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(device, sources, named_sc, named_pc, build_name, xilinx_install_path): tools.write_to_file(build_name + ".ucf", _build_ucf(named_sc, named_pc)) prj_contents = "" for s in sources: prj_contents += s["type"] + " work " + s["path"] + "\n" tools.write_to_file(build_name + ".prj", prj_contents) xst_contents = """run -ifn %s.prj -top top -ifmt MIXED -opt_mode SPEED -reduce_control_sets auto -ofn %s.ngc -p %s""" % (build_name, build_name, device) tools.write_to_file(build_name + ".xst", xst_contents) def is_valid_version(v): try: Decimal(v) return os.path.isdir(os.path.join(xilinx_install_path, v)) except: return False vers = [ver for ver in os.listdir(xilinx_install_path) if is_valid_version(ver)] tools_version = max(vers) bits = struct.calcsize("P")*8 xilinx_settings_file = '%s/%s/ISE_DS/settings%d.sh' % (xilinx_install_path, tools_version, bits) build_script_contents = """# Autogenerated by mibuild set -e source {xilinx_settings_file} xst -ifn {build_name}.xst ngdbuild -uc {build_name}.ucf {build_name}.ngc map -ol high -w {build_name}.ngd par -ol high -w {build_name}.ncd {build_name}-routed.ncd bitgen -g Binary:Yes -w {build_name}-routed.ncd {build_name}.bit """.format(build_name=build_name, xilinx_settings_file=xilinx_settings_file) 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 XilinxISEPlatform(GenericPlatform): def build(self, fragment, clock_domains=None, build_dir="build", build_name="top", xilinx_install_path="/opt/Xilinx"): tools.mkdir_noerror(build_dir) os.chdir(build_dir) v_src, named_sc, named_pc = self.get_verilog(fragment, clock_domains) v_file = build_name + ".v" tools.write_to_file(v_file, v_src) sources = [{"type": "verilog", "path": v_file}] _build(self.device, sources, named_sc, named_pc, build_name, xilinx_install_path) os.chdir("..")