Repository: amaranth-lang/amaranth (python)

Issue:
Unshaped enumeration values don't work when used in a constant initializer
To reproduce:

```python
from amaranth.lib import enum, data

class QSPIMode(enum.Enum):
    PutX1 = 0

data.StructLayout({"mode": QSPIMode}).const({"mode": QSPIMode.PutX1})
```

```
  File ".../bug.py", line 6, in <module>
    data.StructLayout({"mode": QSPIMode}).const({"mode": QSPIMode.PutX1})
  File ".../python3.12/site-packages/amaranth/lib/data.py", line 232, in const
    key_value = hdl.Const(key_value, cast_field_shape)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../python3.12/site-packages/amaranth/hdl/_ast.py", line 1551, in __call__
    return super().__call__(value, shape, **kwargs, src_loc_at=src_loc_at + 1)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../python3.12/site-packages/amaranth/hdl/_ast.py", line 1601, in __init__
    value = int(operator.index(value))
                ^^^^^^^^^^^^^^^^^^^^^
TypeError: 'QSPIMode' object cannot be interpreted as an integer
```

Pull request:
hdl: make `Const(enum_value)` work.
Fixes #1413.

Patch:
diff --git a/amaranth/hdl/_ast.py b/amaranth/hdl/_ast.py
index ef863a6..a490707 100644
--- a/amaranth/hdl/_ast.py
+++ b/amaranth/hdl/_ast.py
@@ -1580,6 +1580,10 @@ class Const(Value, metaclass=_ConstMeta):
 
     def __init__(self, value, shape=None, *, src_loc_at=0):
         # We deliberately do not call Value.__init__ here.
+        if isinstance(value, Enum):
+            if shape is None:
+                shape = Shape.cast(type(value))
+            value = value.value
         value = int(operator.index(value))
         if shape is None:
             shape = Shape(bits_for(value), signed=value < 0)


Test patch:
diff --git a/tests/test_hdl_ast.py b/tests/test_hdl_ast.py
index a7ba972..d74ad77 100644
--- a/tests/test_hdl_ast.py
+++ b/tests/test_hdl_ast.py
@@ -502,6 +502,20 @@ class ConstTestCase(FHDLTestCase):
         with self.assertRaises(TypeError):
             hash(Const(0))
 
+    def test_enum(self):
+        e1 = Const(UnsignedEnum.FOO)
+        self.assertIsInstance(e1, Const)
+        self.assertEqual(e1.shape(), unsigned(2))
+        e2 = Const(SignedEnum.FOO)
+        self.assertIsInstance(e2, Const)
+        self.assertEqual(e2.shape(), signed(2))
+        e3 = Const(TypedEnum.FOO)
+        self.assertIsInstance(e3, Const)
+        self.assertEqual(e3.shape(), unsigned(2))
+        e4 = Const(UnsignedEnum.FOO, 4)
+        self.assertIsInstance(e4, Const)
+        self.assertEqual(e4.shape(), unsigned(4))
+
     def test_shape_castable(self):
         class MockConstValue(ValueCastable):
             def __init__(self, value):