hdl.dsl: accept (but warn on) cases wider than switch test value.
Fixes #13.
This commit is contained in:
parent
cbf7bd6e31
commit
3083c1d6dd
|
@ -882,6 +882,7 @@ class Switch(Statement):
|
|||
for key, stmts in cases.items():
|
||||
if isinstance(key, (bool, int)):
|
||||
key = "{:0{}b}".format(key, len(self.test))
|
||||
assert len(key) <= len(self.test)
|
||||
elif isinstance(key, str):
|
||||
assert len(key) == len(self.test)
|
||||
else:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from collections import OrderedDict, namedtuple
|
||||
from collections.abc import Iterable
|
||||
from contextlib import contextmanager
|
||||
import warnings
|
||||
|
||||
from ..tools import flatten, bits_for
|
||||
from .ast import *
|
||||
|
@ -8,13 +9,17 @@ from .ir import *
|
|||
from .xfrm import *
|
||||
|
||||
|
||||
__all__ = ["Module", "SyntaxError"]
|
||||
__all__ = ["Module", "SyntaxError", "SyntaxWarning"]
|
||||
|
||||
|
||||
class SyntaxError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class SyntaxWarning(Warning):
|
||||
pass
|
||||
|
||||
|
||||
class _ModuleBuilderProxy:
|
||||
def __init__(self, builder, depth):
|
||||
object.__setattr__(self, "_builder", builder)
|
||||
|
@ -195,7 +200,7 @@ class Module(_ModuleBuilderRoot):
|
|||
@contextmanager
|
||||
def Switch(self, test):
|
||||
self._check_context("Switch", context=None)
|
||||
switch_data = self._set_ctrl("Switch", {"test": test, "cases": OrderedDict()})
|
||||
switch_data = self._set_ctrl("Switch", {"test": Value.wrap(test), "cases": OrderedDict()})
|
||||
try:
|
||||
self._ctrl_context = "Switch"
|
||||
self.domain._depth += 1
|
||||
|
@ -211,9 +216,14 @@ class Module(_ModuleBuilderRoot):
|
|||
switch_data = self._get_ctrl("Switch")
|
||||
if value is None:
|
||||
value = "-" * len(switch_data["test"])
|
||||
if isinstance(value, str) and len(switch_data["test"]) != len(value):
|
||||
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"])))
|
||||
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"
|
||||
.format(value, len(switch_data["test"])), SyntaxWarning, stacklevel=3)
|
||||
value &= (1 << len(switch_data["test"])) - 1
|
||||
try:
|
||||
_outer_case, self._statements = self._statements, []
|
||||
self._ctrl_context = None
|
||||
|
|
|
@ -287,6 +287,18 @@ class DSLTestCase(FHDLTestCase):
|
|||
msg="Case value '--' must have the same width as test (which is 4)"):
|
||||
with m.Case("--"):
|
||||
pass
|
||||
with self.assertWarns(SyntaxWarning,
|
||||
msg="Case value '10110' is wider than test (which has width 4); comparison "
|
||||
"will be made against truncated value"):
|
||||
with m.Case(0b10110):
|
||||
pass
|
||||
self.assertRepr(m._statements, """
|
||||
(
|
||||
(switch (sig w1)
|
||||
(case 0110 )
|
||||
)
|
||||
)
|
||||
""")
|
||||
|
||||
def test_Case_outside_Switch_wrong(self):
|
||||
m = Module()
|
||||
|
|
Loading…
Reference in a new issue