Integrate latest migen changes for lattice/icestorm.
authorTim 'mithro' Ansell <me@mith.ro>
Thu, 20 Dec 2018 19:31:07 +0000 (11:31 -0800)
committerTim 'mithro' Ansell <me@mith.ro>
Thu, 20 Dec 2018 19:33:19 +0000 (11:33 -0800)
Integrated up to 37db6bb52532b6d1c6bc8b724c2e8c6a38546c2a.

litex/build/lattice/common.py
litex/build/lattice/icestorm.py

index a4f211309fc73854edb3ecef883cd6d178cbe97b..e807bb601a07f4dcdf8c459ca9588e9ce5343446 100644 (file)
@@ -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):
index 5b57a4302cbb326d55028d3c8164b3c55ee37af1..ad26209104815030f42f365b6c65f898a4de3b79 100644 (file)
@@ -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