hdl.ast: make Slice const-castable.

Fixes #1006.
This commit is contained in:
Wanda 2023-12-30 12:10:29 +01:00 committed by Catherine
parent 6780c838b2
commit 0849e1af0b
4 changed files with 21 additions and 0 deletions

View file

@ -731,6 +731,9 @@ class Const(Value):
value |= part_value << width
width += len(const)
return Const(value, width)
elif type(obj) is Slice:
value = Const.cast(obj.value)
return Const(value.value >> obj.start, unsigned(obj.stop - obj.start))
else:
raise TypeError(f"Value {obj!r} cannot be converted to an Amaranth constant")

View file

@ -15,6 +15,7 @@ Language changes
.. currentmodule:: amaranth.hdl
* Added: `class:ast.Slice` objects have been made const-castable.
* Removed: (deprecated in 0.4) :meth:`Const.normalize`. (`RFC 5`_)
* Removed: (deprecated in 0.4) :class:`ast.Sample`, :class:`ast.Past`, :class:`ast.Stable`, :class:`ast.Rose`, :class:`ast.Fell`.

View file

@ -325,6 +325,7 @@ They may also be provided as a pattern to the :ref:`match operator <lang-matchop
* :class:`Const`
* :class:`Cat`
* :class:`Slice`
This list will be expanded in the future.

View file

@ -799,6 +799,16 @@ class SliceTestCase(FHDLTestCase):
s1 = Const(10)[2]
self.assertEqual(repr(s1), "(slice (const 4'd10) 2:3)")
def test_const(self):
a = Const.cast(Const(0x1234, 16)[4:12])
self.assertEqual(a.value, 0x23)
self.assertEqual(a.width, 8)
self.assertEqual(a.signed, False)
a = Const.cast(Const(-4, signed(8))[1:6])
self.assertEqual(a.value, 0x1e)
self.assertEqual(a.width, 5)
self.assertEqual(a.signed, False)
class BitSelectTestCase(FHDLTestCase):
def setUp(self):
@ -1197,6 +1207,12 @@ class SignalTestCase(FHDLTestCase):
self.assertEqual(s2.shape(), signed(2))
self.assertEqual(s2.decoder(SignedEnum.FOO), "FOO/-1")
def test_const_wrong(self):
s1 = Signal()
with self.assertRaisesRegex(TypeError,
r"^Value \(sig s1\) cannot be converted to an Amaranth constant$"):
Const.cast(s1)
class ClockSignalTestCase(FHDLTestCase):
def test_domain(self):