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():
|
for key, stmts in cases.items():
|
||||||
if isinstance(key, (bool, int)):
|
if isinstance(key, (bool, int)):
|
||||||
key = "{:0{}b}".format(key, len(self.test))
|
key = "{:0{}b}".format(key, len(self.test))
|
||||||
|
assert len(key) <= len(self.test)
|
||||||
elif isinstance(key, str):
|
elif isinstance(key, str):
|
||||||
assert len(key) == len(self.test)
|
assert len(key) == len(self.test)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from collections import OrderedDict, namedtuple
|
from collections import OrderedDict, namedtuple
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
import warnings
|
||||||
|
|
||||||
from ..tools import flatten, bits_for
|
from ..tools import flatten, bits_for
|
||||||
from .ast import *
|
from .ast import *
|
||||||
|
@ -8,13 +9,17 @@ from .ir import *
|
||||||
from .xfrm import *
|
from .xfrm import *
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["Module", "SyntaxError"]
|
__all__ = ["Module", "SyntaxError", "SyntaxWarning"]
|
||||||
|
|
||||||
|
|
||||||
class SyntaxError(Exception):
|
class SyntaxError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SyntaxWarning(Warning):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class _ModuleBuilderProxy:
|
class _ModuleBuilderProxy:
|
||||||
def __init__(self, builder, depth):
|
def __init__(self, builder, depth):
|
||||||
object.__setattr__(self, "_builder", builder)
|
object.__setattr__(self, "_builder", builder)
|
||||||
|
@ -195,7 +200,7 @@ class Module(_ModuleBuilderRoot):
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def Switch(self, test):
|
def Switch(self, test):
|
||||||
self._check_context("Switch", context=None)
|
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:
|
try:
|
||||||
self._ctrl_context = "Switch"
|
self._ctrl_context = "Switch"
|
||||||
self.domain._depth += 1
|
self.domain._depth += 1
|
||||||
|
@ -211,9 +216,14 @@ class Module(_ModuleBuilderRoot):
|
||||||
switch_data = self._get_ctrl("Switch")
|
switch_data = self._get_ctrl("Switch")
|
||||||
if value is None:
|
if value is None:
|
||||||
value = "-" * len(switch_data["test"])
|
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 {})"
|
raise SyntaxError("Case value '{}' must have the same width as test (which is {})"
|
||||||
.format(value, len(switch_data["test"])))
|
.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:
|
try:
|
||||||
_outer_case, self._statements = self._statements, []
|
_outer_case, self._statements = self._statements, []
|
||||||
self._ctrl_context = None
|
self._ctrl_context = None
|
||||||
|
|
|
@ -287,6 +287,18 @@ class DSLTestCase(FHDLTestCase):
|
||||||
msg="Case value '--' must have the same width as test (which is 4)"):
|
msg="Case value '--' must have the same width as test (which is 4)"):
|
||||||
with m.Case("--"):
|
with m.Case("--"):
|
||||||
pass
|
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):
|
def test_Case_outside_Switch_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
|
|
Loading…
Reference in a new issue