gen/fhdl/verilog: add regular comb parameter to allow implementation of simulation...
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 2 Dec 2015 11:37:53 +0000 (12:37 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 2 Dec 2015 13:16:23 +0000 (14:16 +0100)
We will remove that when we will be using new migen simulator

litex/gen/fhdl/verilog.py
litex/gen/sim/generic.py
litex/soc/integration/builder.py

index 018e48aa5e2d49cd9a38ab85a47f92170aa2a68d..bb0c4443b976258779d3ba19a0121d4357adaa8b 100644 (file)
@@ -9,7 +9,7 @@ from litex.gen.fhdl.bitcontainer import bits_for
 from litex.gen.fhdl.namer import build_namespace
 from litex.gen.fhdl.conv_output import ConvOutput
 
-# TODO: clean up simulation hack
+# TODO: remove printcomb_simulation when we will be using new migen simulator
 
 _reserved_keywords = {
     "always", "and", "assign", "automatic", "begin", "buf", "bufif0", "bufif1",
@@ -207,10 +207,10 @@ def _printheader(f, ios, name, ns,
     return r
 
 
-def _printcomb(f, ns,
-               display_run,
-               dummy_signal,
-               blocking_assign):
+def _printcomb_simulation(f, ns,
+            display_run,
+            dummy_signal,
+            blocking_assign):
     r = ""
     if f.comb:
         if dummy_signal:
@@ -251,20 +251,44 @@ def _printcomb(f, ns,
                 if display_run:
                     r += "\t$display(\"Running comb block #" + str(n) + "\");\n"
                 if blocking_assign:
-                       r += "\t" + ns.get_name(t) + " = " + _printexpr(ns, t.reset)[0] + ";\n"
-                       r += _printnode(ns, _AT_BLOCKING, 1, stmts, t)
+                    r += "\t" + ns.get_name(t) + " = " + _printexpr(ns, t.reset)[0] + ";\n"
+                    r += _printnode(ns, _AT_BLOCKING, 1, stmts, t)
                 else:
-                       r += "\t" + ns.get_name(t) + " <= " + _printexpr(ns, t.reset)[0] + ";\n"
-                       r += _printnode(ns, _AT_NONBLOCKING, 1, stmts, t)
+                    r += "\t" + ns.get_name(t) + " <= " + _printexpr(ns, t.reset)[0] + ";\n"
+                    r += _printnode(ns, _AT_NONBLOCKING, 1, stmts, t)
                 if dummy_signal:
-                       r += syn_off
-                       r += "\t" + ns.get_name(dummy_d) + " = " + ns.get_name(dummy_s) + ";\n"
-                       r += syn_on
+                    r += syn_off
+                    r += "\t" + ns.get_name(dummy_d) + " = " + ns.get_name(dummy_s) + ";\n"
+                    r += syn_on
                 r += "end\n"
     r += "\n"
     return r
 
 
+def _printcomb_regular(f, ns, blocking_assign):
+    r = ""
+    if f.comb:
+        groups = group_by_targets(f.comb)
+
+        for n, g in enumerate(groups):
+            if len(g[1]) == 1 and isinstance(g[1][0], _Assign):
+                r += "assign " + _printnode(ns, _AT_BLOCKING, 0, g[1][0])
+            else:
+                r += "always @(*) begin\n"
+                if blocking_assign:
+                    for t in g[0]:
+                        r += "\t" + ns.get_name(t) + " = " + _printexpr(ns, t.reset)[0] + ";\n"
+                    r += _printnode(ns, _AT_BLOCKING, 1, g[1])
+                else:
+                    for t in g[0]:
+                        r += "\t" + ns.get_name(t) + " <= " + _printexpr(ns, t.reset)[0] + ";\n"
+                    r += _printnode(ns, _AT_NONBLOCKING, 1, g[1])
+                r += "end\n"
+    r += "\n"
+    return r
+
+
+
 def _printsync(f, ns):
     r = ""
     for k, v in sorted(f.sync.items(), key=itemgetter(0)):
@@ -331,7 +355,8 @@ def convert(f, ios=None, name="top",
   display_run=False,
   reg_initialization=True,
   dummy_signal=True,
-  blocking_assign=False):
+  blocking_assign=False,
+  regular_comb=True):
     r = ConvOutput()
     if not isinstance(f, _Fragment):
         f = f.get_fragment()
@@ -361,10 +386,16 @@ def convert(f, ios=None, name="top",
     ns.clock_domains = f.clock_domains
     r.ns = ns
 
-    src = "/* Machine-generated using LiteX gen*/\n"
+    src = "/* Machine-generated using LiteX gen "
+    src += "(regular)" if regular_comb else "(simulation)"
+    src += " */\n"
     src += _printheader(f, ios, name, ns,
                         reg_initialization=reg_initialization)
-    src += _printcomb(f, ns,
+    if regular_comb:
+        src += _printcomb_regular(f, ns,
+                      blocking_assign=blocking_assign)
+    else:
+        src += _printcomb_simulation(f, ns,
                       display_run=display_run,
                       dummy_signal=dummy_signal,
                       blocking_assign=blocking_assign)
index c0ed3c54eb833df29b2f2c66cb7fb4834e6682e5..1144ac88df51572dc0e7596f20e95c80285aa710 100644 (file)
@@ -102,6 +102,7 @@ class Simulator:
         c_fragment = verilog.convert(fragment,
             ios=self.top_level.ios,
             name=self.top_level.dut_type,
+            regular_comb=False,
             **vopts)
         self.namespace = c_fragment.ns
 
index b209e7065fc18bf7e25796415bc174a3b79a6256..9b2117fcda62a7e5d36f211ef97ee1e6f50063cc 100644 (file)
@@ -130,7 +130,7 @@ class Builder:
                     boot_data.append(struct.unpack(">I", w)[0])
             self.soc.initialize_rom(boot_data)
 
-    def build(self):
+    def build(self, toolchain_path=None, **kwargs):
         self.soc.finalize()
 
         os.makedirs(self.output_dir, exist_ok=True)
@@ -145,12 +145,11 @@ class Builder:
             self._generate_software()
             self._initialize_rom()
 
-        if self.gateware_toolchain_path is None:
-            kwargs = dict()
-        else:
-            kwargs = {"toolchain_path": self.gateware_toolchain_path}
+        if self.gateware_toolchain_path is not None:
+            toolchain_path = self.gateware_toolchain_path
         self.soc.build(build_dir=os.path.join(self.output_dir, "gateware"),
-                       run=self.compile_gateware, **kwargs)
+                       run=self.compile_gateware, toolchain_path=toolchain_path,
+                       **kwargs)
 
 
 def builder_args(parser):