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:
parent
48d4ee4031
commit
32446831b4
6 changed files with 73 additions and 55 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue