back.verilog: omit Verilog initial trigger only if Yosys adds it.
authorwhitequark <whitequark@whitequark.org>
Wed, 26 Aug 2020 09:01:57 +0000 (09:01 +0000)
committerwhitequark <whitequark@whitequark.org>
Wed, 26 Aug 2020 16:51:12 +0000 (16:51 +0000)
Verilog has an edge case where an `always @*` process, which is used
to describe a combinatorial function procedurally, may not execute
at time zero because none of the signals in its implicit sensitivity
list change, i.e. when the process doesn't read any signals. This
causes the wires driven by the process to stay undefined.

The workaround to this problem (assuming SystemVerilog `always_comb`
is not available) is to introduce a dummy signal that changes only
at time zero and is optimized out during synthesis. nMigen has had
its own workaround, `$verilog_initial_trigger`, for a while. However,
`proc_prune`, while increasing readability, pulls references to this
signal out of the process. Because of this, a similar workaround was
implemented in Yosys' `write_verilog` itself.

This commit ensures we use our workaround on versions of Yosys
without the updated `write_verilog`, and Yosys' workaround on later
versions.

Fixes #418.

nmigen/back/verilog.py

index 31db02bfc75ccf8e97b764c25ebc69df908968a4..9f813d0de061380bcae42dc1e2aba6792abad774 100644 (file)
@@ -13,8 +13,9 @@ def _convert_rtlil_text(rtlil_text, *, strip_internal_attrs=False, write_verilog
     script = []
     script.append("read_ilang <<rtlil\n{}\nrtlil".format(rtlil_text))
 
-    if yosys_version >= (0, 9, 231):
-        # Yosys 0.9 release has buggy proc_prune.
+    if yosys_version >= (0, 9, 3468):
+        # Yosys >=0.9+3468 (since commit f3d7e9a1) emits Verilog without a possible sim/synth
+        # mismatch, making $verilog_initial_trigger unnecessary.
         script.append("delete w:$verilog_initial_trigger")
         script.append("proc_prune")
     script.append("proc_init")