back.rtlil: don't cache wires for legalized switch tests.
authorwhitequark <cz@m-labs.hk>
Wed, 2 Oct 2019 07:51:49 +0000 (07:51 +0000)
committerwhitequark <cz@m-labs.hk>
Wed, 2 Oct 2019 07:51:49 +0000 (07:51 +0000)
This causes miscompilation of code such as:

  r = Array([self.a, self.b])
  m = Module()
  with m.If(r[self.s]):
      m.d.comb += self.o.eq(1)
  return m

nmigen/back/rtlil.py

index 7424c9d89836a0346fd896cf8bf8fb8efd10510d..eb26bf8935f370736ce86c3b2c5528b3d718b906 100644 (file)
@@ -681,9 +681,17 @@ class _StatementCompiler(xfrm.StatementVisitor):
     def on_Switch(self, stmt):
         self._check_rhs(stmt.test)
 
-        if stmt not in self._test_cache:
-            self._test_cache[stmt] = self.rhs_compiler(stmt.test)
-        test_sigspec = self._test_cache[stmt]
+        if not self.state.expansions:
+            # We repeatedly translate the same switches over and over (see the LHSGroupAnalyzer
+            # related code below), and translating the switch test only once helps readability.
+            if stmt not in self._test_cache:
+                self._test_cache[stmt] = self.rhs_compiler(stmt.test)
+            test_sigspec = self._test_cache[stmt]
+        else:
+            # However, if the switch test contains an illegal value, then it may not be cached
+            # (since the illegal value will be repeatedly replaced with different constants), so
+            # don't cache anything in that case.
+            test_sigspec = self.rhs_compiler(stmt.test)
 
         with self._case.switch(test_sigspec, src=src(stmt.src_loc)) as switch:
             for values, stmts in stmt.cases.items():