hdl.ast: deprecate UserValue in favor of ValueCastable.

Closes #527.
This commit is contained in:
whitequark 2020-11-06 02:21:53 +00:00
parent c9fd000103
commit bde37fe2f2
3 changed files with 27 additions and 15 deletions

View file

@ -1237,6 +1237,7 @@ class ArrayProxy(Value):
return "(proxy (array [{}]) {!r})".format(", ".join(map(repr, self.elems)), self.index) return "(proxy (array [{}]) {!r})".format(", ".join(map(repr, self.elems)), self.index)
# TODO(nmigen-0.4): remove
class UserValue(Value): class UserValue(Value):
"""Value with custom lowering. """Value with custom lowering.
@ -1257,6 +1258,7 @@ class UserValue(Value):
* Indexing or iterating through individual bits; * Indexing or iterating through individual bits;
* Adding an assignment to the value to a ``Module`` using ``m.d.<domain> +=``. * Adding an assignment to the value to a ``Module`` using ``m.d.<domain> +=``.
""" """
@deprecated("instead of `UserValue`, use `ValueCastable`", stacklevel=3)
def __init__(self, *, src_loc_at=0): def __init__(self, *, src_loc_at=0):
super().__init__(src_loc_at=1 + src_loc_at) super().__init__(src_loc_at=1 + src_loc_at)
self.__lowered = None self.__lowered = None
@ -1292,7 +1294,7 @@ class ValueCastable:
providing fixed semantics upfront, it is kept abstract for as long as possible, only being providing fixed semantics upfront, it is kept abstract for as long as possible, only being
cast to a concrete nMigen value when required. cast to a concrete nMigen value when required.
Note that it is necessary to ensure that nMigen's view of representation of all values stays Note that it is necessary to ensure that nMigen's view of representation of all values stays
internally consistent. The class deriving from ``ValueCastable`` must decorate the ``as_value`` internally consistent. The class deriving from ``ValueCastable`` must decorate the ``as_value``
method with the ``lowermethod`` decorator, which ensures that all calls to ``as_value``return the method with the ``lowermethod`` decorator, which ensures that all calls to ``as_value``return the
same ``Value`` representation. If the class deriving from ``ValueCastable`` is mutable, it is same ``Value`` representation. If the class deriving from ``ValueCastable`` is mutable, it is

View file

@ -1009,20 +1009,24 @@ class MockUserValue(UserValue):
class UserValueTestCase(FHDLTestCase): class UserValueTestCase(FHDLTestCase):
def test_shape(self): def test_shape(self):
uv = MockUserValue(1) with warnings.catch_warnings():
self.assertEqual(uv.shape(), unsigned(1)) warnings.filterwarnings(action="ignore", category=DeprecationWarning)
self.assertIsInstance(uv.shape(), Shape) uv = MockUserValue(1)
uv.lowered = 2 self.assertEqual(uv.shape(), unsigned(1))
self.assertEqual(uv.shape(), unsigned(1)) self.assertIsInstance(uv.shape(), Shape)
self.assertEqual(uv.lower_count, 1) uv.lowered = 2
self.assertEqual(uv.shape(), unsigned(1))
self.assertEqual(uv.lower_count, 1)
def test_lower_to_user_value(self): def test_lower_to_user_value(self):
uv = MockUserValue(MockUserValue(1)) with warnings.catch_warnings():
self.assertEqual(uv.shape(), unsigned(1)) warnings.filterwarnings(action="ignore", category=DeprecationWarning)
self.assertIsInstance(uv.shape(), Shape) uv = MockUserValue(MockUserValue(1))
uv.lowered = MockUserValue(2) self.assertEqual(uv.shape(), unsigned(1))
self.assertEqual(uv.shape(), unsigned(1)) self.assertIsInstance(uv.shape(), Shape)
self.assertEqual(uv.lower_count, 1) uv.lowered = MockUserValue(2)
self.assertEqual(uv.shape(), unsigned(1))
self.assertEqual(uv.lower_count, 1)
class MockValueCastableChanges(ValueCastable): class MockValueCastableChanges(ValueCastable):

View file

@ -1,5 +1,7 @@
# nmigen: UnusedElaboratable=no # nmigen: UnusedElaboratable=no
import warnings
from nmigen.hdl.ast import * from nmigen.hdl.ast import *
from nmigen.hdl.cd import * from nmigen.hdl.cd import *
from nmigen.hdl.ir import * from nmigen.hdl.ir import *
@ -614,7 +616,9 @@ class UserValueTestCase(FHDLTestCase):
def setUp(self): def setUp(self):
self.s = Signal() self.s = Signal()
self.c = Signal() self.c = Signal()
self.uv = MockUserValue(self.s) with warnings.catch_warnings():
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
self.uv = MockUserValue(self.s)
def test_lower(self): def test_lower(self):
sync = ClockDomain() sync = ClockDomain()
@ -645,6 +649,8 @@ class UserValueRecursiveTestCase(UserValueTestCase):
def setUp(self): def setUp(self):
self.s = Signal() self.s = Signal()
self.c = Signal() self.c = Signal()
self.uv = MockUserValue(MockUserValue(self.s)) with warnings.catch_warnings():
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
self.uv = MockUserValue(MockUserValue(self.s))
# inherit the test_lower method from UserValueTestCase because the checks are the same # inherit the test_lower method from UserValueTestCase because the checks are the same