back.rtlil: fix sim-synth mismatch with assigns following switches.
Closes #155.
This commit is contained in:
parent
0a603b3844
commit
ee03eab52f
|
@ -605,6 +605,7 @@ class _StatementCompiler(xfrm.StatementVisitor):
|
||||||
self._case = None
|
self._case = None
|
||||||
self._test_cache = {}
|
self._test_cache = {}
|
||||||
self._has_rhs = False
|
self._has_rhs = False
|
||||||
|
self._wrap_assign = False
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def case(self, switch, values, attrs={}, src=""):
|
def case(self, switch, values, attrs={}, src=""):
|
||||||
|
@ -630,6 +631,14 @@ class _StatementCompiler(xfrm.StatementVisitor):
|
||||||
# In RTLIL, LHS and RHS of assignment must have exactly same width.
|
# In RTLIL, LHS and RHS of assignment must have exactly same width.
|
||||||
rhs_sigspec = self.rhs_compiler.match_shape(
|
rhs_sigspec = self.rhs_compiler.match_shape(
|
||||||
stmt.rhs, lhs_bits, lhs_sign)
|
stmt.rhs, lhs_bits, lhs_sign)
|
||||||
|
if self._wrap_assign:
|
||||||
|
# In RTLIL, all assigns are logically sequenced before all switches, even if they are
|
||||||
|
# interleaved in the source. In nMigen, the source ordering is used. To handle this
|
||||||
|
# mismatch, we wrap all assigns following a switch in a dummy switch.
|
||||||
|
with self._case.switch("{ }") as wrap_switch:
|
||||||
|
with wrap_switch.case() as wrap_case:
|
||||||
|
wrap_case.assign(self.lhs_compiler(stmt.lhs), rhs_sigspec)
|
||||||
|
else:
|
||||||
self._case.assign(self.lhs_compiler(stmt.lhs), rhs_sigspec)
|
self._case.assign(self.lhs_compiler(stmt.lhs), rhs_sigspec)
|
||||||
|
|
||||||
def on_Assert(self, stmt):
|
def on_Assert(self, stmt):
|
||||||
|
@ -675,7 +684,9 @@ class _StatementCompiler(xfrm.StatementVisitor):
|
||||||
decoded_values.append(stmt.test.decoder(int(value, 2)))
|
decoded_values.append(stmt.test.decoder(int(value, 2)))
|
||||||
case_attrs["nmigen.decoding"] = "|".join(decoded_values)
|
case_attrs["nmigen.decoding"] = "|".join(decoded_values)
|
||||||
with self.case(switch, values, attrs=case_attrs):
|
with self.case(switch, values, attrs=case_attrs):
|
||||||
|
self._wrap_assign = False
|
||||||
self.on_statements(stmts)
|
self.on_statements(stmts)
|
||||||
|
self._wrap_assign = True
|
||||||
|
|
||||||
def on_statement(self, stmt):
|
def on_statement(self, stmt):
|
||||||
try:
|
try:
|
||||||
|
@ -688,9 +699,11 @@ class _StatementCompiler(xfrm.StatementVisitor):
|
||||||
tests[-1] = "-" * bits
|
tests[-1] = "-" * bits
|
||||||
for branch, test in zip(legalize.branches, tests):
|
for branch, test in zip(legalize.branches, tests):
|
||||||
with self.case(switch, (test,)):
|
with self.case(switch, (test,)):
|
||||||
|
self._wrap_assign = False
|
||||||
branch_value = ast.Const(branch, (bits, sign))
|
branch_value = ast.Const(branch, (bits, sign))
|
||||||
with self.state.expand_to(legalize.value, branch_value):
|
with self.state.expand_to(legalize.value, branch_value):
|
||||||
super().on_statement(stmt)
|
super().on_statement(stmt)
|
||||||
|
self._wrap_assign = True
|
||||||
|
|
||||||
def on_statements(self, stmts):
|
def on_statements(self, stmts):
|
||||||
for stmt in stmts:
|
for stmt in stmts:
|
||||||
|
@ -827,6 +840,7 @@ def convert_fragment(builder, fragment, hierarchy):
|
||||||
# Convert statements into decision trees.
|
# Convert statements into decision trees.
|
||||||
stmt_compiler._case = case
|
stmt_compiler._case = case
|
||||||
stmt_compiler._has_rhs = False
|
stmt_compiler._has_rhs = False
|
||||||
|
stmt_compiler._wrap_assign = False
|
||||||
stmt_compiler(group_stmts)
|
stmt_compiler(group_stmts)
|
||||||
|
|
||||||
# Verilog `always @*` blocks will not run if `*` does not match anything, i.e.
|
# Verilog `always @*` blocks will not run if `*` does not match anything, i.e.
|
||||||
|
|
Loading…
Reference in a new issue