Repository: amaranth-lang/amaranth (python)

Issue:
Signal reset cannot be set to a const value
Consider this code

```
CYCLE_OVERFLOW = Const(742500, Shape(width=22))
audgen_accum = Signal(22, reset=CYCLE_OVERFLOW) # Master clock
```

Amaranth prints this error/exception from the build/generate step:

```
    audgen_accum = Signal(22, reset=CYCLE_OVERFLOW) # Master clock
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
TypeError: Reset value must be a constant-castable expression, not (const 22'd742500)
```

**Expected behavior:**
Consts of matching shape should be allowed as a reset value. If they are not allowed, then the error message should be changed (language "constant-castable" is unclear and sounds wrong).

I do not have an opinion on what happens if you set a signal's reset value to a const of non-matching shape.

Pull request description:
ast: fix const-castable expression handling in `Signal(reset=)`.
The code to accept const-castable expressions was previously added in 0c4fda92fecb0f6b1a3dce8960f8d13459c7eef1, but it was untested and had a few bugs.

Fixes #911.

Patch:
diff --git a/amaranth/hdl/ast.py b/amaranth/hdl/ast.py
index ed93347..45941e6 100644
--- a/amaranth/hdl/ast.py
+++ b/amaranth/hdl/ast.py
@@ -1056,12 +1056,15 @@ class Signal(Value, DUID, metaclass=_SignalMeta):
                                  .format(orig_shape, Shape.cast(orig_shape),
                                          reset.shape()))
         else:
+            if reset is None:
+                reset = 0
             try:
-                reset = Const.cast(reset or 0)
+                reset = Const.cast(reset)
             except TypeError:
                 raise TypeError("Reset value must be a constant-castable expression, not {!r}"
                                 .format(orig_reset))
-        if orig_reset not in (None, 0, -1): # Avoid false positives for all-zeroes and all-ones
+        # Avoid false positives for all-zeroes and all-ones
+        if orig_reset is not None and not (isinstance(orig_reset, int) and orig_reset in (0, -1)):
             if reset.shape().signed and not self.signed:
                 warnings.warn(
                     message="Reset value {!r} is signed, but the signal shape is {!r}"


Test patch:
diff --git a/tests/test_hdl_ast.py b/tests/test_hdl_ast.py
index 8745a53..c1ad320 100644
--- a/tests/test_hdl_ast.py
+++ b/tests/test_hdl_ast.py
@@ -1053,6 +1053,10 @@ class SignalTestCase(FHDLTestCase):
                 r"not <StringEnum\.FOO: 'a'>$"):
             Signal(1, reset=StringEnum.FOO)
 
+    def test_reset_const_castable(self):
+        s1 = Signal(4, reset=Cat(Const(0, 1), Const(1, 1), Const(0, 2)))
+        self.assertEqual(s1.reset, 2)
+
     def test_reset_shape_castable_const(self):
         class CastableFromHex(ShapeCastable):
             def as_shape(self):