hdl.dsl: cases wider than switch test value are unreachable.

In 3083c1d6 they were erroneously fixed via truncation.
This commit is contained in:
whitequark 2019-01-13 08:51:49 +00:00
parent 3083c1d6dd
commit 664b4bcb3a
3 changed files with 13 additions and 11 deletions

View file

@ -219,17 +219,19 @@ class Module(_ModuleBuilderRoot):
if isinstance(value, str) and len(value) != len(switch_data["test"]):
raise SyntaxError("Case value '{}' must have the same width as test (which is {})"
.format(value, len(switch_data["test"])))
omit_case = False
if isinstance(value, int) and bits_for(value) > len(switch_data["test"]):
warnings.warn("Case value '{:b}' is wider than test (which has width {}); "
"comparison will be made against truncated value"
"comparison will never be true"
.format(value, len(switch_data["test"])), SyntaxWarning, stacklevel=3)
value &= (1 << len(switch_data["test"])) - 1
omit_case = True
try:
_outer_case, self._statements = self._statements, []
self._ctrl_context = None
yield
self._flush_ctrl()
switch_data["cases"][value] = self._statements
if not omit_case:
switch_data["cases"][value] = self._statements
finally:
self._ctrl_context = "Switch"
self._statements = _outer_case

View file

@ -289,14 +289,12 @@ class DSLTestCase(FHDLTestCase):
pass
with self.assertWarns(SyntaxWarning,
msg="Case value '10110' is wider than test (which has width 4); comparison "
"will be made against truncated value"):
"will never be true"):
with m.Case(0b10110):
pass
self.assertRepr(m._statements, """
(
(switch (sig w1)
(case 0110 )
)
(switch (sig w1) )
)
""")

View file

@ -12,10 +12,12 @@ __all__ = ["FHDLTestCase"]
class FHDLTestCase(unittest.TestCase):
def assertRepr(self, obj, repr_str):
obj = Statement.wrap(obj)
repr_str = re.sub(r"\s+", " ", repr_str)
repr_str = re.sub(r"\( (?=\()", "(", repr_str)
repr_str = re.sub(r"\) (?=\))", ")", repr_str)
self.assertEqual(repr(obj), repr_str.strip())
def prepare_repr(repr_str):
repr_str = re.sub(r"\s+", " ", repr_str)
repr_str = re.sub(r"\( (?=\()", "(", repr_str)
repr_str = re.sub(r"\) (?=\))", ")", repr_str)
return repr_str.strip()
self.assertEqual(prepare_repr(repr(obj)), prepare_repr(repr_str))
@contextmanager
def assertRaises(self, exception, msg=None):