---
 migen/build/lattice/icestorm.py | 59 ++++++++++++++++++++++++++++++-----------
 1 file changed, 44 insertions(+), 15 deletions(-)

diff --git a/migen/build/lattice/icestorm.py b/migen/build/lattice/icestorm.py
index 1ab1d93..b3dcf9a 100644
--- a/migen/build/lattice/icestorm.py
+++ b/migen/build/lattice/icestorm.py
@@ -9,7 +9,6 @@ from migen.fhdl.structure import _Fragment
 
 from migen.build.generic_platform import *
 from migen.build import tools
-from migen.build.lattice import common
 
 
 def _format_constraint(c):
@@ -41,13 +40,15 @@ def _build_yosys(device, sources, vincpaths, build_name):
     for filename, language, library in sources:
         ys_contents += "read_{}{} {}\n".format(language, incflags, filename)
 
-    ys_contents += """synth_ice40 -top top -blif 
{build_name}.blif""".format(build_name=build_name)
+    ys_contents += """synth_ice40 -top top -blif {build_name}.blif""".format(
+        build_name=build_name)
 
     ys_name = build_name + ".ys"
     tools.write_to_file(ys_name, ys_contents)
 
 
-def _run_icestorm(build_name, source, yosys_opt, pnr_opt, icepack_opt):
+def _run_icestorm(build_name, source, yosys_opt, pnr_opt,
+                  icetime_opt, icepack_opt):
     if sys.platform == "win32" or sys.platform == "cygwin":
         source_cmd = "call "
         script_ext = ".bat"
@@ -62,15 +63,18 @@ def _run_icestorm(build_name, source, yosys_opt, pnr_opt, 
icepack_opt):
         fail_stmt = ""
 
     build_script_contents += """
-yosys {yosys_opt} {build_name}.ys
+yosys {yosys_opt} -l {build_name}.rpt {build_name}.ys{fail_stmt}
 arachne-pnr {pnr_opt} -p {build_name}.pcf {build_name}.blif -o 
{build_name}.txt{fail_stmt}
+icetime {icetime_opt} -t -p {build_name}.pcf -r {build_name}.tim 
{build_name}.txt{fail_stmt}
 icepack {icepack_opt} {build_name}.txt {build_name}.bin{fail_stmt}
 """
-    build_script_contents = build_script_contents.format(build_name=build_name,
+    build_script_contents = build_script_contents.format(
+        build_name=build_name,
         yosys_opt=yosys_opt, pnr_opt=pnr_opt, icepack_opt=icepack_opt,
-        fail_stmt=fail_stmt)
+        icetime_opt=icetime_opt, fail_stmt=fail_stmt)
     build_script_file = "build_" + build_name + script_ext
-    tools.write_to_file(build_script_file, build_script_contents, 
force_unix=False)
+    tools.write_to_file(build_script_file, build_script_contents,
+                        force_unix=False)
     command = shell + [build_script_file]
     r = subprocess.call(command)
     if r != 0:
@@ -80,12 +84,14 @@ icepack {icepack_opt} {build_name}.txt 
{build_name}.bin{fail_stmt}
 class LatticeIceStormToolchain:
     def __init__(self):
         self.yosys_opt = "-q"
-        self.pnr_opt = ""
+        self.pnr_opt = "-q"
+        self.icetime_opt = ""
         self.icepack_opt = ""
+        self.freq_constraint = dict()
 
     # platform.device should be of the form "ice40-{1k,8k}-{tq144, etc}""
     def build(self, platform, fragment, build_dir="build", build_name="top",
-        run=True):
+              run=True):
         tools.mkdir_noerror(build_dir)
         cwd = os.getcwd()
         os.chdir(build_dir)
@@ -99,14 +105,20 @@ class LatticeIceStormToolchain:
         v_file = build_name + ".v"
         v_output.write(v_file)
         sources = platform.sources | {(v_file, "verilog", "work")}
-        _build_yosys(platform.device, sources, platform.verilog_include_paths, 
build_name)
+        _build_yosys(platform.device, sources, platform.verilog_include_paths,
+                     build_name)
 
-        tools.write_to_file(build_name + ".pcf", _build_pcf(named_sc, 
named_pc))
+        tools.write_to_file(build_name + ".pcf",
+                            _build_pcf(named_sc, named_pc))
         if run:
             (family, size, package) = self.parse_device_string(platform.device)
-            new_pnr_opts = self.pnr_opt + " -d " + size + " -P " + package
-            _run_icestorm(build_name, False, self.yosys_opt, new_pnr_opts,
-                self.icepack_opt)
+            pnr_opt = self.pnr_opt + " -d " + size + " -P " + package
+            # TODO: PNR will probably eventually support LP devices.
+            icetime_opt = self.icetime_opt + " -P " + package + \
+                " -d " + "hx" + size + " -c " + \
+                str(self.get_max_frequency_constraint())
+            _run_icestorm(build_name, False, self.yosys_opt, pnr_opt,
+                          icetime_opt, self.icepack_opt)
 
         os.chdir(cwd)
 
@@ -122,5 +134,22 @@ class LatticeIceStormToolchain:
             raise ValueError("Invalid device package")
         return (family, size, package)
 
+    # 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):
-        pass
+        new_freq = 1000.0/period
+
+        if clk not in self.freq_constraint.keys():
+            self.freq_constraint[clk] = new_freq
+        else:
+            raise ConstraintError("Period constraint already added to signal.")
+
+    def get_max_frequency_constraint(self):
+        max_f = 0.0
+        for _, f in self.freq_constraint.items():
+            if max_f < f:
+                max_f = f
+        return max_f
-- 
2.6.3

_______________________________________________
M-Labs devel mailing list
https://ssl.serverraum.org/lists/listinfo/devel

Reply via email to