Skip to content

Commit efcd9a4

Browse files
wanda-phiwhitequark
authored andcommitted
hdl._ast: fix _value_repr computation.
Fixes fallout from #1165.
1 parent 11f7b88 commit efcd9a4

File tree

5 files changed

+33
-11
lines changed

5 files changed

+33
-11
lines changed

amaranth/hdl/_ast.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,9 +1972,11 @@ def __init__(self, shape=None, *, name=None, init=None, reset=None, reset_less=F
19721972

19731973
if decoder is not None:
19741974
# The value representation is specified explicitly. Since we do not expose `hdl._repr`,
1975-
# this is the only way to add a custom filter to the signal right now. The setter sets
1976-
# `self._value_repr` as well as the compatibility `self.decoder`.
1977-
pass
1975+
# this is the only way to add a custom filter to the signal right now.
1976+
if isinstance(decoder, type) and issubclass(decoder, Enum):
1977+
self._value_repr = (_repr.Repr(_repr.FormatEnum(decoder), self),)
1978+
else:
1979+
self._value_repr = (_repr.Repr(_repr.FormatCustom(decoder), self),)
19781980
else:
19791981
# If it's an enum, expose it via `self.decoder` for compatibility, whether it's a Python
19801982
# enum or an Amaranth enum. This also sets the value representation, even for custom
@@ -1995,20 +1997,16 @@ def __init__(self, shape=None, *, name=None, init=None, reset=None, reset_less=F
19951997
self._value_repr = (_repr.Repr(_repr.FormatInt(), self),)
19961998

19971999
# Compute the value representation that will be used by Amaranth.
1998-
if decoder is None:
1999-
self._value_repr = (_repr.Repr(_repr.FormatInt(), self),)
2000-
self._decoder = None
2001-
elif not (isinstance(decoder, type) and issubclass(decoder, Enum)):
2002-
self._value_repr = (_repr.Repr(_repr.FormatCustom(decoder), self),)
2003-
self._decoder = decoder
2004-
else: # Violence. In the name of backwards compatibility!
2005-
self._value_repr = (_repr.Repr(_repr.FormatEnum(decoder), self),)
2000+
if isinstance(decoder, type) and issubclass(decoder, Enum):
2001+
# Violence. In the name of backwards compatibility!
20062002
def enum_decoder(value):
20072003
try:
20082004
return "{0.name:}/{0.value:}".format(decoder(value))
20092005
except ValueError:
20102006
return str(value)
20112007
self._decoder = enum_decoder
2008+
else:
2009+
self._decoder = decoder
20122010

20132011
@property
20142012
def width(self):

amaranth/hdl/_repr.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ class FormatInt(Format):
1414
def format(self, value):
1515
return f"{value:d}"
1616

17+
def __repr__(self):
18+
return f"FormatInt()"
19+
1720

1821
class FormatEnum(Format):
1922
def __init__(self, enum):
@@ -25,6 +28,9 @@ def format(self, value):
2528
except ValueError:
2629
return f"?/{value:d}"
2730

31+
def __repr__(self):
32+
return f"FormatEnum({self.enum.__name__})"
33+
2834

2935
class FormatCustom(Format):
3036
def __init__(self, formatter):
@@ -33,6 +39,9 @@ def __init__(self, formatter):
3339
def format(self, value):
3440
return self.formatter(value)
3541

42+
def __repr__(self):
43+
return f"FormatCustom({self.formatter})"
44+
3645

3746
class Repr:
3847
def __init__(self, format, value, *, path=()):
@@ -44,3 +53,6 @@ def __init__(self, format, value, *, path=()):
4453
self.format = format
4554
self.value = value
4655
self.path = path
56+
57+
def __repr__(self):
58+
return f"Repr({self.format!r}, {self.value!r}, {self.path!r})"

tests/test_hdl_ast.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,20 +1321,26 @@ class Color(Enum):
13211321
s = Signal(decoder=Color)
13221322
self.assertEqual(s.decoder(1), "RED/1")
13231323
self.assertEqual(s.decoder(3), "3")
1324+
self.assertRepr(s._value_repr, "(Repr(FormatEnum(Color), (sig s), ()),)")
13241325

13251326
def test_enum(self):
13261327
s1 = Signal(UnsignedEnum)
13271328
self.assertEqual(s1.shape(), unsigned(2))
13281329
s2 = Signal(SignedEnum)
13291330
self.assertEqual(s2.shape(), signed(2))
13301331
self.assertEqual(s2.decoder(SignedEnum.FOO), "FOO/-1")
1332+
self.assertRepr(s2._value_repr, "(Repr(FormatEnum(SignedEnum), (sig s2), ()),)")
13311333

13321334
def test_const_wrong(self):
13331335
s1 = Signal()
13341336
with self.assertRaisesRegex(TypeError,
13351337
r"^Value \(sig s1\) cannot be converted to an Amaranth constant$"):
13361338
Const.cast(s1)
13371339

1340+
def test_value_repr(self):
1341+
s = Signal()
1342+
self.assertRepr(s._value_repr, "(Repr(FormatInt(), (sig s), ()),)")
1343+
13381344

13391345
class ClockSignalTestCase(FHDLTestCase):
13401346
def test_domain(self):

tests/test_lib_data.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,11 @@ def test_construct_signal(self):
458458
self.assertIsInstance(cv, Signal)
459459
self.assertEqual(cv.shape(), unsigned(3))
460460
self.assertEqual(cv.name, "v")
461+
self.assertRepr(cv._value_repr, """
462+
(Repr(FormatInt(), (sig v), ()),
463+
Repr(FormatInt(), (slice (sig v) 0:1), ('a',)),
464+
Repr(FormatInt(), (slice (sig v) 1:3), ('b',)))
465+
""")
461466

462467
def test_construct_signal_init(self):
463468
v1 = Signal(data.StructLayout({"a": unsigned(1), "b": unsigned(2)}),

tests/test_lib_enum.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class EnumA(IntEnum, shape=signed(4)):
137137
B = -3
138138
a = Signal(EnumA)
139139
self.assertRepr(a, "(sig a)")
140+
self.assertRepr(a._value_repr, "(Repr(FormatEnum(EnumA), (sig a), ()),)")
140141

141142
def test_enum_view(self):
142143
class EnumA(Enum, shape=signed(4)):

0 commit comments

Comments
 (0)