From 53731b792b43766655a3d3361754c22dd8c68284 Mon Sep 17 00:00:00 2001 From: Tim 'mithro' Ansell Date: Thu, 20 Dec 2018 11:31:07 -0800 Subject: [PATCH] Integrate latest migen changes for lattice/icestorm. Integrated up to 37db6bb52532b6d1c6bc8b724c2e8c6a38546c2a. --- litex/build/lattice/common.py | 20 ++++++++-- litex/build/lattice/icestorm.py | 65 ++++++++++++++++++--------------- 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/litex/build/lattice/common.py b/litex/build/lattice/common.py index a4f211309..e807bb601 100644 --- a/litex/build/lattice/common.py +++ b/litex/build/lattice/common.py @@ -86,15 +86,27 @@ class LatticeiCE40AsyncResetSynchronizer: class LatticeiCE40TristateImpl(Module): def __init__(self, io, o, oe, i): nbits, sign = value_bits_sign(io) - for bit in range(nbits): + if nbits == 1: + # If `io` is an expression like `port[x]`, it is not legal to index further + # into it if it is only 1 bit wide. self.specials += \ Instance("SB_IO", p_PIN_TYPE=C(0b101001, 6), - io_PACKAGE_PIN=io[bit], + io_PACKAGE_PIN=io, i_OUTPUT_ENABLE=oe, - i_D_OUT_0=o[bit], - o_D_IN_0=i[bit], + i_D_OUT_0=o, + o_D_IN_0=i, ) + else: + for bit in range(nbits): + self.specials += \ + Instance("SB_IO", + p_PIN_TYPE=C(0b101001, 6), + io_PACKAGE_PIN=io[bit], + i_OUTPUT_ENABLE=oe, + i_D_OUT_0=o[bit], + o_D_IN_0=i[bit], + ) class LatticeiCE40Tristate(Module): diff --git a/litex/build/lattice/icestorm.py b/litex/build/lattice/icestorm.py index 5b57a4302..ad2620910 100644 --- a/litex/build/lattice/icestorm.py +++ b/litex/build/lattice/icestorm.py @@ -12,29 +12,27 @@ from litex.build import tools from litex.build.lattice import common -def _format_constraint(c): - pass - - -def _format_pcf(signame, pin, others, resname): - return "set_io " + signame + " " + pin + "\n" - - def _build_pcf(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_pcf(sig + "[" + str(i) + "]", p, others, resname) + for bit, pin in enumerate(pins): + r += "set_io {}[{}] {}\n".format(sig, bit, pin) else: - r += _format_pcf(sig, pins[0], others, resname) + r += "set_io {} {}\n".format(sig, pins[0]) if named_pc: r += "\n" + "\n\n".join(named_pc) return r -def _build_script(source, build_template, build_name, pnr_pkg_opts, - icetime_pkg_opts, freq_constraint): +def _build_pre_pack(vns, freq_cstrs): + r = "" + for sig in freq_cstrs: + r += """ctx.addClock("{}", {})\n""".format(vns.get_name(sig), freq_cstrs[sig]) + return r + + +def _build_script(source, build_template, build_name, **kwargs): if sys.platform in ("win32", "cygwin"): script_ext = ".bat" build_script_contents = "@echo off\nrem Autogenerated by Migen\n\n" @@ -47,10 +45,8 @@ def _build_script(source, build_template, build_name, pnr_pkg_opts, for s in build_template: s_fail = s + "{fail_stmt}\n" # Required so Windows scripts fail early. build_script_contents += s_fail.format(build_name=build_name, - pnr_pkg_opts=pnr_pkg_opts, - icetime_pkg_opts=icetime_pkg_opts, - freq_constraint=freq_constraint, - fail_stmt=fail_stmt) + fail_stmt=fail_stmt, + **kwargs) build_script_file = "build_" + build_name + script_ext tools.write_to_file(build_script_file, build_script_contents, @@ -101,7 +97,7 @@ class LatticeIceStormToolchain: self.yosys_template = [ "{read_files}", "attrmap -tocase keep -imap keep=\"true\" keep=1 -imap keep=\"false\" keep=0 -remove keep=0", - "synth_ice40 -top top -blif {build_name}.blif", + "synth_ice40 -top {build_name} -blif {build_name}.blif", ] self.build_template = [ @@ -114,12 +110,12 @@ class LatticeIceStormToolchain: self.nextpnr_yosys_template = [ "{read_files}", "attrmap -tocase keep -imap keep=\"true\" keep=1 -imap keep=\"false\" keep=0 -remove keep=0", - "synth_ice40 -top top -json {build_name}.json", + "synth_ice40 {synth_opts} -top {build_name} -json {build_name}.json", ] self.nextpnr_build_template = [ "yosys -q -l {build_name}.rpt {build_name}.ys", - "nextpnr-ice40 {pnr_pkg_opts} --pcf {build_name}.pcf --json {build_name}.json --asc {build_name}.txt --freq {freq_constraint}", + "nextpnr-ice40 {pnr_pkg_opts} --pcf {build_name}.pcf --json {build_name}.json --asc {build_name}.txt --pre-pack {build_name}_pre_pack.py", "icepack {build_name}.txt {build_name}.bin" ] @@ -127,7 +123,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, **kwargs): + toolchain_path=None, use_nextpnr=True, synth_opts="", run=True, **kwargs): os.makedirs(build_dir, exist_ok=True) cwd = os.getcwd() os.chdir(build_dir) @@ -146,7 +142,8 @@ class LatticeIceStormToolchain: else: chosen_yosys_template = self.yosys_template ys_contents = "\n".join(_.format(build_name=build_name, - read_files=self.gen_read_files(platform, v_file)) + read_files=self.gen_read_files(platform, v_file), + synth_opts=synth_opts) for _ in chosen_yosys_template) ys_name = build_name + ".ys" @@ -161,6 +158,13 @@ class LatticeIceStormToolchain: pnr_pkg_opts = "-d " + self.get_size_string(series_size) + \ " -P " + package icetime_pkg_opts = "-P " + package + " -d " + series_size + + if use_nextpnr: + tools.write_to_file(build_name + "_pre_pack.py", + _build_pre_pack(v_output.ns, self.freq_constraints)) + # icetime can only handle a single global constraint, so we test against the fastest + # clock; though imprecise, if the global design satisfies the fastest clock, we can + # be sure all other constraints are satisfied. freq_constraint = str(max(self.freq_constraints.values(), default=0.0)) @@ -168,8 +172,12 @@ class LatticeIceStormToolchain: chosen_build_template = self.nextpnr_build_template else: chosen_build_template = self.build_template - script = _build_script(False, chosen_build_template, build_name, - pnr_pkg_opts, icetime_pkg_opts, freq_constraint) + script = _build_script(source=False, + build_template=chosen_build_template, + build_name=build_name, + pnr_pkg_opts=pnr_pkg_opts, + icetime_pkg_opts=icetime_pkg_opts, + freq_constraint=freq_constraint) if run: _run_script(script) @@ -190,7 +198,9 @@ class LatticeIceStormToolchain: "hx1k": ["vq100", "cb132", "tq144"], "lp8k": ["cm81", "cm81:4k", "cm121", "cm121:4k", "cm225", "cm225:4k"], - "hx8k": ["cb132", "cb132:4k", "tq144:4k", "cm225", "ct256"], + "hx8k": ["bg121", "bg121:4k", "cb132", "cb132:4k", "cm121", + "cm121:4k", "cm225", "cm225:4k", "cm81", "cm81:4k", + "ct256", "tq144:4k"], "up3k": ["sg48", "uwg30"], "up5k": ["sg48", "uwg30"], } @@ -219,11 +229,6 @@ class LatticeIceStormToolchain: filename)) return "\n".join(read_files) - # icetime can only handle a single global constraint. Pending more - # finely-tuned analysis features in arachne-pnr and IceStorm, save - # all the constraints in a dictionary and test against the fastest clk. - # Though imprecise, if the global design satisfies the fastest clock, - # we can be sure all other constraints are satisfied. def add_period_constraint(self, platform, clk, period): new_freq = 1000.0/period