Repository: amaranth-lang/amaranth
Pull request #1119 (2024-02-13 05:00:15)

Require Yosys 0.38
This avoids the awkward requirement due to the bug in Yosys 0.37, and will soon be required anyway once the `$check` cell is emitted.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/amaranth-lang/amaranth/pull/1119?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang) Report
Attention: `1 lines` in your changes are missing coverage. Please review.
> Comparison is base [(`0056e98`)](https://app.codecov.io/gh/amaranth-lang/amaranth/commit/0056e982c5a85b26935b8c750cc00cf4b1e66ebc?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang) 85.60% compared to head [(`73e0fc2`)](https://app.codecov.io/gh/amaranth-lang/amaranth/pull/1119?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang) 85.57%.
> Report is 1 commits behind head on main.

| [Files](https://app.codecov.io/gh/amaranth-lang/amaranth/pull/1119?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang) | Patch % | Lines |
|---|---|---|
| [amaranth/back/verilog.py](https://app.codecov.io/gh/amaranth-lang/amaranth/pull/1119?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang#diff-YW1hcmFudGgvYmFjay92ZXJpbG9nLnB5) | 0.00% | [1 Missing :warning: ](https://app.codecov.io/gh/amaranth-lang/amaranth/pull/1119?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #1119      +/-   ##
==========================================
- Coverage   85.60%   85.57%   -0.03%     
==========================================
  Files          42       42              
  Lines        8336     8340       +4     
  Branches     1967     1969       +2     
==========================================
+ Hits         7136     7137       +1     
- Misses       1004     1006       +2     
- Partials      196      197       +1     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/amaranth-lang/amaranth/pull/1119?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang).


Patch:
diff --git a/amaranth/back/verilog.py b/amaranth/back/verilog.py
index d5c75a1..ef32555 100644
--- a/amaranth/back/verilog.py
+++ b/amaranth/back/verilog.py
@@ -9,9 +9,7 @@ __all__ = ["YosysError", "convert", "convert_fragment"]
 
 def _convert_rtlil_text(rtlil_text, *, strip_internal_attrs=False, write_verilog_opts=()):
     # this version requirement needs to be synchronized with the one in pyproject.toml!
-    # Yosys 0.37 has a critical miscompilation in Verilog backend:
-    # https://github.com/amaranth-lang/amaranth/issues/1049
-    yosys = find_yosys(lambda ver: ver >= (0, 35) and not (0, 36, 79) <= ver <= (0, 37, 29))
+    yosys = find_yosys(lambda ver: ver >= (0, 38))
 
     script = []
     script.append(f"read_ilang <<rtlil\n{rtlil_text}\nrtlil")
diff --git a/amaranth/hdl/_ast.py b/amaranth/hdl/_ast.py
index f8860e8..e19a280 100644
--- a/amaranth/hdl/_ast.py
+++ b/amaranth/hdl/_ast.py
@@ -1262,9 +1262,6 @@ class ValueCastable:
         if cls.shape is ValueCastable.shape:
             raise TypeError(f"Class '{cls.__name__}' deriving from 'ValueCastable' must override "
                             "the 'shape' method")
-        if not hasattr(cls.as_value, "_ValueCastable__memoized"):
-            raise TypeError(f"Class '{cls.__name__}' deriving from 'ValueCastable' must decorate "
-                            "the 'as_value' method with the 'ValueCastable.lowermethod' decorator")
 
     # The signatures and definitions of these methods are weird because they are present here for
     # documentation (and error checking above) purpose only and should not affect control flow.
@@ -1333,17 +1330,10 @@ class ValueCastable:
         """
         return super().shape(*args, **kwargs) # :nocov:
 
+    # TODO(amaranth-0.6): remove
     @staticmethod
+    @deprecated("`ValueCastable.lowermethod` is no longer required and will be removed in Amaranth 0.6")
     def lowermethod(func):
-        """Decorator to memoize lowering methods.
-
-        Ensures the decorated method is called only once, with subsequent method calls returning
-        the object returned by the first first method call.
-
-        This decorator is required to decorate the :pc:`as_value` method of :pc:`ValueCastable`
-        subclasses. This is to ensure that Amaranth's view of representation of all values stays
-        internally consistent.
-        """
         @functools.wraps(func)
         def wrapper_memoized(self, *args, **kwargs):
             # Use `in self.__dict__` instead of `hasattr` to avoid interfering with custom
diff --git a/amaranth/hdl/_rec.py b/amaranth/hdl/_rec.py
index a02b69b..f033fad 100644
--- a/amaranth/hdl/_rec.py
+++ b/amaranth/hdl/_rec.py
@@ -178,7 +178,6 @@ class Record(ValueCastable):
                 raise AttributeError("{} does not have a field '{}'. Did you mean one of: {}?"
                                      .format(reference, item, ", ".join(self.fields))) from None
 
-    @ValueCastable.lowermethod
     def as_value(self):
         return Cat(self.fields.values())
 
diff --git a/amaranth/lib/data.py b/amaranth/lib/data.py
index 1083fa3..978f83e 100644
--- a/amaranth/lib/data.py
+++ b/amaranth/lib/data.py
@@ -638,7 +638,6 @@ class View(ValueCastable):
         """
         return self.__orig_layout
 
-    @ValueCastable.lowermethod
     def as_value(self):
         """Get underlying value.
 
diff --git a/amaranth/lib/enum.py b/amaranth/lib/enum.py
index 998d54e..84b922d 100644
--- a/amaranth/lib/enum.py
+++ b/amaranth/lib/enum.py
@@ -232,7 +232,6 @@ class EnumView(ValueCastable):
         """Returns the underlying enum type."""
         return self.enum
 
-    @ValueCastable.lowermethod
     def as_value(self):
         """Returns the underlying value."""
         return self.target
diff --git a/pyproject.toml b/pyproject.toml
index b866af0..96f976e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,7 +20,7 @@ dependencies = [
 
 [project.optional-dependencies]
 # this version requirement needs to be synchronized with the one in amaranth.back.verilog!
-builtin-yosys = ["amaranth-yosys>=0.35,!=0.37.0.*"]
+builtin-yosys = ["amaranth-yosys>=0.38"]
 remote-build  = ["paramiko~=2.7"]
 
 [project.scripts]


Test patch:
diff --git a/tests/test_hdl_ast.py b/tests/test_hdl_ast.py
index bcb64f2..4b14f6b 100644
--- a/tests/test_hdl_ast.py
+++ b/tests/test_hdl_ast.py
@@ -1040,7 +1040,6 @@ class ArrayTestCase(FHDLTestCase):
 
     def test_index_value_castable(self):
         class MyValue(ValueCastable):
-            @ValueCastable.lowermethod
             def as_value(self):
                 return Signal()
 
@@ -1328,7 +1327,6 @@ class MockValueCastable(ValueCastable):
     def shape(self):
         return Value.cast(self.dest).shape()
 
-    @ValueCastable.lowermethod
     def as_value(self):
         return self.dest
 
@@ -1340,9 +1338,10 @@ class MockValueCastableChanges(ValueCastable):
     def shape(self):
         return unsigned(self.width)
 
-    @ValueCastable.lowermethod
-    def as_value(self):
-        return Signal(self.width)
+    with _ignore_deprecated():
+        @ValueCastable.lowermethod
+        def as_value(self):
+            return Signal(self.width)
 
 
 class MockValueCastableCustomGetattr(ValueCastable):
@@ -1352,29 +1351,16 @@ class MockValueCastableCustomGetattr(ValueCastable):
     def shape(self):
         assert False
 
-    @ValueCastable.lowermethod
-    def as_value(self):
-        return Const(0)
+    with _ignore_deprecated():
+        @ValueCastable.lowermethod
+        def as_value(self):
+            return Const(0)
 
     def __getattr__(self, attr):
         assert False
 
 
 class ValueCastableTestCase(FHDLTestCase):
-    def test_not_decorated(self):
-        with self.assertRaisesRegex(TypeError,
-                r"^Class 'MockValueCastableNotDecorated' deriving from 'ValueCastable' must "
-                r"decorate the 'as_value' method with the 'ValueCastable.lowermethod' decorator$"):
-            class MockValueCastableNotDecorated(ValueCastable):
-                def __init__(self):
-                    pass
-
-                def shape(self):
-                    pass
-
-                def as_value(self):
-                    return Signal()
-
     def test_no_override(self):
         with self.assertRaisesRegex(TypeError,
                 r"^Class 'MockValueCastableNoOverrideAsValue' deriving from 'ValueCastable' must "
diff --git a/tests/test_lib_wiring.py b/tests/test_lib_wiring.py
index 98f48c8..1682f78 100644
--- a/tests/test_lib_wiring.py
+++ b/tests/test_lib_wiring.py
@@ -4,7 +4,6 @@ import unittest
 from types import SimpleNamespace as NS
 
 from amaranth import *
-from amaranth.hdl._ast import ValueCastable
 from amaranth.lib import data, enum
 from amaranth.lib.wiring import Flow, In, Out, Member
 from amaranth.lib.wiring import SignatureError, SignatureMembers, FlippedSignatureMembers
diff --git a/tests/test_sim.py b/tests/test_sim.py
index fd90e8d..01e55d3 100644
--- a/tests/test_sim.py
+++ b/tests/test_sim.py
@@ -728,7 +728,6 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
 
     def test_value_castable(self):
         class MyValue(ValueCastable):
-            @ValueCastable.lowermethod
             def as_value(self):
                 return Signal()