From e9299ccd0e3d3a32cdeb79810c29ae2458f67a23 Mon Sep 17 00:00:00 2001 From: Wanda Date: Mon, 29 Jan 2024 19:18:18 +0100 Subject: [PATCH] hdl.ast: change warning on out-of-range reset to an error, improve it. Fixes #1019. --- amaranth/hdl/ast.py | 15 ++++++++------- docs/changes.rst | 2 ++ tests/test_hdl_ast.py | 20 +++++++++++++++----- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/amaranth/hdl/ast.py b/amaranth/hdl/ast.py index 76643a0..9d4bb27 100644 --- a/amaranth/hdl/ast.py +++ b/amaranth/hdl/ast.py @@ -1170,13 +1170,14 @@ class Signal(Value, DUID, metaclass=_SignalMeta): self.reset = reset.value self.reset_less = bool(reset_less) - if isinstance(orig_shape, range) and self.reset == orig_shape.stop: - warnings.warn( - message="Reset value {!r} equals the non-inclusive end of the signal " - "shape {!r}; this is likely an off-by-one error" - .format(self.reset, orig_shape), - category=SyntaxWarning, - stacklevel=2) + if isinstance(orig_shape, range) and orig_reset is not None and orig_reset not in orig_shape: + if orig_reset == orig_shape.stop: + raise SyntaxError( + f"Reset value {orig_reset!r} equals the non-inclusive end of the signal " + f"shape {orig_shape!r}; this is likely an off-by-one error") + else: + raise SyntaxError( + f"Reset value {orig_reset!r} is not within the signal shape {orig_shape!r}") self.attrs = OrderedDict(() if attrs is None else attrs) diff --git a/docs/changes.rst b/docs/changes.rst index dbfe357..9cdf331 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -50,6 +50,8 @@ Language changes * Added: :func:`amaranth.utils.ceil_log2`, :func:`amaranth.utils.exact_log2`. (`RFC 17`_) * Changed: ``m.Case()`` with no patterns is never active instead of always active. (`RFC 39`_) * 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. * Deprecated: :func:`amaranth.utils.log2_int`. (`RFC 17`_) * 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`. diff --git a/tests/test_hdl_ast.py b/tests/test_hdl_ast.py index 3333a5a..1af21f2 100644 --- a/tests/test_hdl_ast.py +++ b/tests/test_hdl_ast.py @@ -1106,10 +1106,8 @@ class SignalTestCase(FHDLTestCase): self.assertEqual(s8.shape(), signed(5)) s9 = Signal(range(-20, 16)) self.assertEqual(s9.shape(), signed(6)) - with warnings.catch_warnings(): - warnings.filterwarnings(action="ignore", category=SyntaxWarning) - s10 = Signal(range(0)) - self.assertEqual(s10.shape(), unsigned(0)) + s10 = Signal(range(0)) + self.assertEqual(s10.shape(), unsigned(0)) s11 = Signal(range(1)) self.assertEqual(s11.shape(), unsigned(1)) @@ -1184,10 +1182,22 @@ class SignalTestCase(FHDLTestCase): Signal(signed(1), reset=-2) def test_reset_wrong_fencepost(self): - with self.assertWarnsRegex(SyntaxWarning, + with self.assertRaisesRegex(SyntaxError, r"^Reset value 10 equals the non-inclusive end of the signal shape " r"range\(0, 10\); this is likely an off-by-one error$"): Signal(range(0, 10), reset=10) + with self.assertRaisesRegex(SyntaxError, + r"^Reset value 0 equals the non-inclusive end of the signal shape " + r"range\(0, 0\); this is likely an off-by-one error$"): + Signal(range(0), reset=0) + + def test_reset_wrong_range(self): + with self.assertRaisesRegex(SyntaxError, + r"^Reset value 11 is not within the signal shape range\(0, 10\)$"): + Signal(range(0, 10), reset=11) + with self.assertRaisesRegex(SyntaxError, + r"^Reset value 0 is not within the signal shape range\(1, 10\)$"): + Signal(range(1, 10), reset=0) def test_attrs(self): s1 = Signal()