Implement RFC 46: Change Shape.cast(range(1)) to unsigned(0).

This commit is contained in:
Wanda 2024-02-03 03:13:51 +01:00 committed by Catherine
parent 1fe7bd010f
commit 089213e19f
3 changed files with 12 additions and 4 deletions

View file

@ -93,8 +93,8 @@ class Shape:
* a :class:`Shape`, where the result is itself;
* an :class:`int`, where the result is :func:`unsigned(obj) <unsigned>`;
* a :class:`range`, where the result is wide enough to represent any element of the range,
and is signed if any element of the range is signed;
* a :class:`range`, where the result has minimal width required to represent all elements
of the range, and is signed if any element of the range is signed;
* an :class:`enum.Enum` whose members are all :ref:`constant-castable <lang-constcasting>`
or :class:`enum.IntEnum`, where the result is wide enough to represent any member of
the enumeration, and is signed if any member of the enumeration is signed;
@ -121,6 +121,8 @@ class Shape:
signed = obj[0] < 0 or obj[-1] < 0
width = max(bits_for(obj[0], signed),
bits_for(obj[-1], signed))
if obj[0] == obj[-1] == 0:
width = 0
return Shape(width, signed)
elif isinstance(obj, type) and issubclass(obj, Enum):
# For compatibility with third party enumerations, handle them as if they were

View file

@ -36,9 +36,11 @@ Implemented RFCs
.. _RFC 17: https://amaranth-lang.org/rfcs/0017-remove-log2-int.html
.. _RFC 39: https://amaranth-lang.org/rfcs/0039-empty-case.html
.. _RFC 46: https://amaranth-lang.org/rfcs/0046-shape-range-1.html
* `RFC 17`_: Remove ``log2_int``
* `RFC 39`_: Change semantics of no-argument ``m.Case()``
* `RFC 46`_: Change ``Shape.cast(range(1))`` to ``unsigned(0)``
Language changes
@ -52,6 +54,7 @@ Language changes
* Changed: ``Value.matches()`` with no patterns is ``Const(0)`` instead of ``Const(1)``. (`RFC 39`_)
* Changed: ``Signal(range(stop), reset=stop)`` warning has been changed into a hard error and made to trigger on any out-of range value.
* Changed: ``Signal(range(0))`` is now valid without a warning.
* Changed: ``Shape.cast(range(1))`` is now ``unsigned(0)``. (`RFC 46`_)
* Deprecated: :func:`amaranth.utils.log2_int`. (`RFC 17`_)
* Removed: (deprecated in 0.4) :meth:`Const.normalize`. (`RFC 5`_)
* Removed: (deprecated in 0.4) :class:`Repl`. (`RFC 10`_)

View file

@ -115,7 +115,7 @@ class ShapeTestCase(FHDLTestCase):
self.assertEqual(s3.width, 4)
self.assertEqual(s3.signed, True)
s4 = Shape.cast(range(0, 1))
self.assertEqual(s4.width, 1)
self.assertEqual(s4.width, 0)
self.assertEqual(s4.signed, False)
s5 = Shape.cast(range(-1, 0))
self.assertEqual(s5.width, 1)
@ -129,6 +129,9 @@ class ShapeTestCase(FHDLTestCase):
s8 = Shape.cast(range(0, 10, 3))
self.assertEqual(s8.width, 4)
self.assertEqual(s8.signed, False)
s9 = Shape.cast(range(0, 3, 3))
self.assertEqual(s9.width, 0)
self.assertEqual(s9.signed, False)
def test_cast_enum(self):
s1 = Shape.cast(UnsignedEnum)
@ -1088,7 +1091,7 @@ class SignalTestCase(FHDLTestCase):
s10 = Signal(range(0))
self.assertEqual(s10.shape(), unsigned(0))
s11 = Signal(range(1))
self.assertEqual(s11.shape(), unsigned(1))
self.assertEqual(s11.shape(), unsigned(0))
def test_shape_wrong(self):
with self.assertRaisesRegex(TypeError,