From: whitequark Date: Fri, 11 Oct 2019 10:49:34 +0000 (+0000) Subject: hdl.ast: Value.{wrap→cast} X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c9711ea4b70ac95055af45c5de27ca16e7c8d171;p=nmigen.git hdl.ast: Value.{wrap→cast} Preparation for #225. --- diff --git a/nmigen/compat/fhdl/structure.py b/nmigen/compat/fhdl/structure.py index c56a89f..2132e3b 100644 --- a/nmigen/compat/fhdl/structure.py +++ b/nmigen/compat/fhdl/structure.py @@ -13,9 +13,9 @@ __all__ = ["DUID", "wrap", "Mux", "Cat", "Replicate", "Constant", "C", "Signal", "SPECIAL_INPUT", "SPECIAL_OUTPUT", "SPECIAL_INOUT"] -@deprecated("instead of `wrap`, use `Value.wrap`") +@deprecated("instead of `wrap`, use `Value.cast`") def wrap(v): - return Value.wrap(v) + return Value.cast(v) @extend(_Slice) @@ -52,14 +52,14 @@ def choices(self): class If(ast.Switch): @deprecated("instead of `If(cond, ...)`, use `with m.If(cond): ...`") def __init__(self, cond, *stmts): - cond = Value.wrap(cond) + cond = Value.cast(cond) if len(cond) != 1: cond = cond.bool() super().__init__(cond, {("1",): ast.Statement.wrap(stmts)}) @deprecated("instead of `.Elif(cond, ...)`, use `with m.Elif(cond): ...`") def Elif(self, cond, *stmts): - cond = Value.wrap(cond) + cond = Value.cast(cond) if len(cond) != 1: cond = cond.bool() self.cases = OrderedDict((("-" + k,), v) for (k,), v in self.cases.items()) diff --git a/nmigen/hdl/ast.py b/nmigen/hdl/ast.py index 2c997be..64e7082 100644 --- a/nmigen/hdl/ast.py +++ b/nmigen/hdl/ast.py @@ -47,9 +47,12 @@ def _enum_to_bits(enum_value): class Value(metaclass=ABCMeta): @staticmethod - def wrap(obj): - """Ensures that the passed object is an nMigen value. Booleans and integers - are automatically wrapped into ``Const``.""" + def cast(obj): + """Converts ``obj`` to an nMigen value. + + Booleans and integers are wrapped into a :class:`Const`. Enumerations whose members are + all integers are converted to a :class:`Const` with a shape that fits every member. + """ if isinstance(obj, Value): return obj elif isinstance(obj, (bool, int)): @@ -57,7 +60,13 @@ class Value(metaclass=ABCMeta): elif isinstance(obj, Enum): return Const(obj.value, _enum_shape(type(obj))) else: - raise TypeError("Object '{!r}' is not an nMigen value".format(obj)) + raise TypeError("Object {!r} is not an nMigen value".format(obj)) + + # TODO(nmigen-0.2): remove this + @classmethod + @deprecated("instead of `Value.wrap`, use `Value.cast`") + def wrap(cls, obj): + return cls.cast(obj) def __init__(self, *, src_loc_at=0): super().__init__() @@ -93,14 +102,14 @@ class Value(metaclass=ABCMeta): # completely by prohibiting such division operations. raise NotImplementedError("Division by a signed value is not supported") def __mod__(self, other): - other = Value.wrap(other) + other = Value.cast(other) other.__check_divisor() return Operator("%", [self, other]) def __rmod__(self, other): self.__check_divisor() return Operator("%", [other, self]) def __floordiv__(self, other): - other = Value.wrap(other) + other = Value.cast(other) other.__check_divisor() return Operator("//", [self, other]) def __rfloordiv__(self, other): @@ -452,7 +461,7 @@ class Operator(Value): def __init__(self, op, operands, *, src_loc_at=0): super().__init__(src_loc_at=1 + src_loc_at) self.op = op - self.operands = [Value.wrap(o) for o in operands] + self.operands = [Value.cast(o) for o in operands] @staticmethod def _bitwise_binary_shape(a_shape, b_shape): @@ -540,7 +549,7 @@ def Mux(sel, val1, val0): Value, out Output ``Value``. If ``sel`` is asserted, the Mux returns ``val1``, else ``val0``. """ - sel = Value.wrap(sel) + sel = Value.cast(sel) if len(sel) != 1: sel = sel.bool() return Operator("m", [sel, val1, val0]) @@ -567,7 +576,7 @@ class Slice(Value): raise IndexError("Slice start {} must be less than slice end {}".format(start, end)) super().__init__(src_loc_at=src_loc_at) - self.value = Value.wrap(value) + self.value = Value.cast(value) self.start = start self.end = end @@ -594,7 +603,7 @@ class Part(Value): super().__init__(src_loc_at=src_loc_at) self.value = value - self.offset = Value.wrap(offset) + self.offset = Value.cast(offset) self.width = width self.stride = stride @@ -639,7 +648,7 @@ class Cat(Value): """ def __init__(self, *args, src_loc_at=0): super().__init__(src_loc_at=src_loc_at) - self.parts = [Value.wrap(v) for v in flatten(args)] + self.parts = [Value.cast(v) for v in flatten(args)] def shape(self): return sum(len(part) for part in self.parts), False @@ -688,7 +697,7 @@ class Repl(Value): .format(count)) super().__init__(src_loc_at=src_loc_at) - self.value = Value.wrap(value) + self.value = Value.cast(value) self.count = count def shape(self): @@ -857,7 +866,7 @@ class Signal(Value, DUID): new_name = other.name + str(name_suffix) else: new_name = tracer.get_var_name(depth=2 + src_loc_at, default="$like") - kw = dict(shape=cls.wrap(other).shape(), name=new_name) + kw = dict(shape=cls.cast(other).shape(), name=new_name) if isinstance(other, cls): kw.update(reset=other.reset, reset_less=other.reset_less, attrs=other.attrs, decoder=other.decoder) @@ -1052,7 +1061,7 @@ class ArrayProxy(Value): def __init__(self, elems, index, *, src_loc_at=0): super().__init__(src_loc_at=1 + src_loc_at) self.elems = elems - self.index = Value.wrap(index) + self.index = Value.cast(index) def __getattr__(self, attr): return ArrayProxy([getattr(elem, attr) for elem in self.elems], self.index) @@ -1061,7 +1070,7 @@ class ArrayProxy(Value): return ArrayProxy([ elem[index] for elem in self.elems], self.index) def _iter_as_values(self): - return (Value.wrap(elem) for elem in self.elems) + return (Value.cast(elem) for elem in self.elems) def shape(self): width, signed = 0, False @@ -1113,7 +1122,7 @@ class UserValue(Value): def _lazy_lower(self): if self.__lowered is None: - self.__lowered = Value.wrap(self.lower()) + self.__lowered = Value.cast(self.lower()) return self.__lowered def shape(self): @@ -1136,7 +1145,7 @@ class Sample(Value): """ def __init__(self, expr, clocks, domain, *, src_loc_at=0): super().__init__(src_loc_at=1 + src_loc_at) - self.value = Value.wrap(expr) + self.value = Value.cast(expr) self.clocks = int(clocks) self.domain = domain if not isinstance(self.value, (Const, Signal, ClockSignal, ResetSignal, Initial)): @@ -1219,8 +1228,8 @@ class Statement: class Assign(Statement): def __init__(self, lhs, rhs, *, src_loc_at=0): super().__init__(src_loc_at=src_loc_at) - self.lhs = Value.wrap(lhs) - self.rhs = Value.wrap(rhs) + self.lhs = Value.cast(lhs) + self.rhs = Value.cast(rhs) def _lhs_signals(self): return self.lhs._lhs_signals() @@ -1235,7 +1244,7 @@ class Assign(Statement): class Property(Statement): def __init__(self, test, *, _check=None, _en=None, src_loc_at=0): super().__init__(src_loc_at=src_loc_at) - self.test = Value.wrap(test) + self.test = Value.cast(test) self._check = _check self._en = _en if self._check is None: @@ -1283,7 +1292,7 @@ class Switch(Statement): # be automatically traced, so whatever constructs a Switch may optionally provide it. self.case_src_locs = {} - self.test = Value.wrap(test) + self.test = Value.cast(test) self.cases = OrderedDict() for orig_keys, stmts in cases.items(): # Map: None -> (); key -> (key,); (key...) -> (key...) @@ -1466,7 +1475,7 @@ class _MappedKeySet(MutableSet, _MappedKeyCollection): class ValueKey: def __init__(self, value): - self.value = Value.wrap(value) + self.value = Value.cast(value) if isinstance(self.value, Const): self._hash = hash(self.value.value) elif isinstance(self.value, (Signal, AnyValue)): diff --git a/nmigen/hdl/dsl.py b/nmigen/hdl/dsl.py index 6934ed3..830aaa0 100644 --- a/nmigen/hdl/dsl.py +++ b/nmigen/hdl/dsl.py @@ -172,7 +172,7 @@ class Module(_ModuleBuilderRoot, Elaboratable): return data def _check_signed_cond(self, cond): - cond = Value.wrap(cond) + cond = Value.cast(cond) width, signed = cond.shape() if signed: warnings.warn("Signed values in If/Elif conditions usually result from inverting " @@ -249,7 +249,7 @@ class Module(_ModuleBuilderRoot, Elaboratable): def Switch(self, test): self._check_context("Switch", context=None) switch_data = self._set_ctrl("Switch", { - "test": Value.wrap(test), + "test": Value.cast(test), "cases": OrderedDict(), "src_loc": tracer.get_src_loc(src_loc_at=1), "case_src_locs": {}, @@ -383,7 +383,7 @@ class Module(_ModuleBuilderRoot, Elaboratable): tests, cases = [], OrderedDict() for if_test, if_case in zip(if_tests + [None], if_bodies): if if_test is not None: - if_test = Value.wrap(if_test) + if_test = Value.cast(if_test) if len(if_test) != 1: if_test = if_test.bool() tests.append(if_test) diff --git a/nmigen/test/test_hdl_ast.py b/nmigen/test/test_hdl_ast.py index 0bca37a..362e2a8 100644 --- a/nmigen/test/test_hdl_ast.py +++ b/nmigen/test/test_hdl_ast.py @@ -23,27 +23,27 @@ class StringEnum(Enum): class ValueTestCase(FHDLTestCase): - def test_wrap(self): - self.assertIsInstance(Value.wrap(0), Const) - self.assertIsInstance(Value.wrap(True), Const) + def test_cast(self): + self.assertIsInstance(Value.cast(0), Const) + self.assertIsInstance(Value.cast(True), Const) c = Const(0) - self.assertIs(Value.wrap(c), c) + self.assertIs(Value.cast(c), c) with self.assertRaises(TypeError, - msg="Object ''str'' is not an nMigen value"): - Value.wrap("str") + msg="Object 'str' is not an nMigen value"): + Value.cast("str") - def test_wrap_enum(self): - e1 = Value.wrap(UnsignedEnum.FOO) + def test_cast_enum(self): + e1 = Value.cast(UnsignedEnum.FOO) self.assertIsInstance(e1, Const) self.assertEqual(e1.shape(), (2, False)) - e2 = Value.wrap(SignedEnum.FOO) + e2 = Value.cast(SignedEnum.FOO) self.assertIsInstance(e2, Const) self.assertEqual(e2.shape(), (2, True)) - def test_wrap_enum_wrong(self): + def test_cast_enum_wrong(self): with self.assertRaises(TypeError, msg="Only enumerations with integer values can be converted to nMigen values"): - Value.wrap(StringEnum.FOO) + Value.cast(StringEnum.FOO) def test_bool(self): with self.assertRaises(TypeError, diff --git a/nmigen/test/test_sim.py b/nmigen/test/test_sim.py index 8126f1b..f818069 100644 --- a/nmigen/test/test_sim.py +++ b/nmigen/test/test_sim.py @@ -13,8 +13,8 @@ from ..back.pysim import * class SimulatorUnitTestCase(FHDLTestCase): def assertStatement(self, stmt, inputs, output, reset=0): - inputs = [Value.wrap(i) for i in inputs] - output = Value.wrap(output) + inputs = [Value.cast(i) for i in inputs] + output = Value.cast(output) isigs = [Signal(i.shape(), name=n) for i, n in zip(inputs, "abcd")] osig = Signal(output.shape(), name="y", reset=reset)