hdl.{ast,dsl}, back.{pysim,rtlil}: allow multiple case values.

This means that instead of:

    with m.Case(0b00):
        <body>
    with m.Case(0b01):
        <body>

it is legal to write:

    with m.Case(0b00, 0b01):
        <body>

with no change in semantics, and slightly nicer RTLIL or Verilog
output.

Fixes #103.
This commit is contained in:
whitequark 2019-06-28 04:37:08 +00:00
parent 48d4ee4031
commit 32446831b4
6 changed files with 73 additions and 55 deletions

View file

@ -318,20 +318,22 @@ class _StatementCompiler(StatementVisitor):
def on_Switch(self, stmt):
test = self.rrhs_compiler(stmt.test)
cases = []
for value, stmts in stmt.cases.items():
if value is None:
for values, stmts in stmt.cases.items():
if values == ():
check = lambda test: True
else:
if "-" in value:
mask = "".join("0" if b == "-" else "1" for b in value)
value = "".join("0" if b == "-" else b for b in value)
else:
mask = "1" * len(value)
mask = int(mask, 2)
value = int(value, 2)
def make_check(mask, value):
return lambda test: test & mask == value
check = make_check(mask, value)
check = lambda test: False
def make_check(mask, value, prev_check):
return lambda test: prev_check(test) or test & mask == value
for value in values:
if "-" in value:
mask = "".join("0" if b == "-" else "1" for b in value)
value = "".join("0" if b == "-" else b for b in value)
else:
mask = "1" * len(value)
mask = int(mask, 2)
value = int(value, 2)
check = make_check(mask, value, check)
cases.append((check, self.on_statements(stmts)))
def run(state):
test_value = test(state)

View file

@ -188,12 +188,12 @@ class _SwitchBuilder:
def __exit__(self, *args):
self.rtlil._append("{}end\n", " " * self.indent)
def case(self, value=None):
if value is None:
def case(self, *values):
if values == ():
self.rtlil._append("{}case\n", " " * (self.indent + 1))
else:
self.rtlil._append("{}case {}'{}\n", " " * (self.indent + 1),
len(value), value)
self.rtlil._append("{}case {}\n", " " * (self.indent + 1),
", ".join("{}'{}".format(len(value), value) for value in values))
return _CaseBuilder(self.rtlil, self.indent + 2)
@ -590,10 +590,10 @@ class _StatementCompiler(xfrm.StatementVisitor):
self._has_rhs = False
@contextmanager
def case(self, switch, value):
def case(self, switch, values):
try:
old_case = self._case
with switch.case(value) as self._case:
with switch.case(*values) as self._case:
yield
finally:
self._case = old_case
@ -645,8 +645,8 @@ class _StatementCompiler(xfrm.StatementVisitor):
test_sigspec = self._test_cache[stmt]
with self._case.switch(test_sigspec) as switch:
for value, stmts in stmt.cases.items():
with self.case(switch, value):
for values, stmts in stmt.cases.items():
with self.case(switch, values):
self.on_statements(stmts)
def on_statement(self, stmt):