hdl.ast: Value.{wrap→cast}
authorwhitequark <whitequark@whitequark.org>
Fri, 11 Oct 2019 10:49:34 +0000 (10:49 +0000)
committerwhitequark <whitequark@whitequark.org>
Fri, 11 Oct 2019 10:49:34 +0000 (10:49 +0000)
Preparation for #225.

nmigen/compat/fhdl/structure.py
nmigen/hdl/ast.py
nmigen/hdl/dsl.py
nmigen/test/test_hdl_ast.py
nmigen/test/test_sim.py

index c56a89f7267bc4e2243526206af348befcc69fe2..2132e3bc6d1761829efd4e10ee54cf54757fd13e 100644 (file)
@@ -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())
index 2c997beb94874f1136073ea86cefda2a62a4de38..64e708268dc799a21378e504eaa3c38bc91cf255 100644 (file)
@@ -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)):
index 6934ed394f554cfb71990ed05e309368fe706be5..830aaa0290236dccf50ca778117779f10ce6c9d8 100644 (file)
@@ -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)
index 0bca37afc97153b28a1a8204e67ca7188f88e096..362e2a8bb48608365d7b461814136cf77c34ceb3 100644 (file)
@@ -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,
index 8126f1b251d73281280c6e974faa6f3dc83a324c..f8180692c3bba88bfd23214d5b7619d1701f0533 100644 (file)
@@ -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)