Repository: amaranth-lang/amaranth
Pull request #1208 (2024-03-15 23:38:47)

lib.memory: Add `Signature.create` implementations.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/amaranth-lang/amaranth/pull/1208?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 89.42%. Comparing base [(`83701d7`)](https://app.codecov.io/gh/amaranth-lang/amaranth/commit/83701d74cfca7d684f1137a3eb5d277d1ef572ce?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=amaranth-lang) to head [(`e433ab7`)](https://app.codecov.io/gh/amaranth-lang/amaranth/pull/1208?dropdown=coverage&src=pr&el=desc&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    #1208      +/-   ##
==========================================
- Coverage   89.44%   89.42%   -0.02%     
==========================================
  Files          43       43              
  Lines        9067     9071       +4     
  Branches     2150     2150              
==========================================
+ Hits         8110     8112       +2     
- Misses        781      782       +1     
- Partials      176      177       +1     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/amaranth-lang/amaranth/pull/1208?dropdown=coverage&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/lib/memory.py b/amaranth/lib/memory.py
index 802671e..dc7aed3 100644
--- a/amaranth/lib/memory.py
+++ b/amaranth/lib/memory.py
@@ -98,6 +98,9 @@ class WritePort:
                 "en": wiring.In(en_width),
             })
 
+        def create(self, *, path=None, src_loc_at=0):
+            return WritePort(self, memory=None, domain="sync", path=path, src_loc_at=1 + src_loc_at)
+
         @property
         def addr_width(self):
             return self._addr_width
@@ -121,7 +124,7 @@ class WritePort:
             return f"WritePort.Signature(addr_width={self.addr_width}, shape={self.shape}{granularity})"
 
 
-    def __init__(self, signature, *, memory, domain):
+    def __init__(self, signature, *, memory, domain, path=None, src_loc_at=0):
         if not isinstance(signature, WritePort.Signature):
             raise TypeError(f"Expected `WritePort.Signature`, not {signature!r}")
         if memory is not None:
@@ -138,7 +141,7 @@ class WritePort:
         self._signature = signature
         self._memory = memory
         self._domain = domain
-        self.__dict__.update(signature.members.create())
+        self.__dict__.update(signature.members.create(path=path, src_loc_at=1 + src_loc_at))
         if memory is not None:
             memory._w_ports.append(self)
 
@@ -211,6 +214,9 @@ class ReadPort:
                 "en": wiring.In(1, init=1),
             })
 
+        def create(self, *, path=None, src_loc_at=0):
+            return ReadPort(self, memory=None, domain="sync", path=path, src_loc_at=1 + src_loc_at)
+
         @property
         def addr_width(self):
             return self._addr_width
@@ -228,7 +234,7 @@ class ReadPort:
             return f"ReadPort.Signature(addr_width={self.addr_width}, shape={self.shape})"
 
 
-    def __init__(self, signature, *, memory, domain, transparent_for=()):
+    def __init__(self, signature, *, memory, domain, transparent_for=(), path=None, src_loc_at=0):
         if not isinstance(signature, ReadPort.Signature):
             raise TypeError(f"Expected `ReadPort.Signature`, not {signature!r}")
         if memory is not None:
@@ -252,7 +258,7 @@ class ReadPort:
         self._memory = memory
         self._domain = domain
         self._transparent_for = transparent_for
-        self.__dict__.update(signature.members.create())
+        self.__dict__.update(signature.members.create(path=path, src_loc_at=1 + src_loc_at))
         if domain == "comb":
             self.en = Const(1)
         if memory is not None:


Test patch:
diff --git a/tests/test_lib_memory.py b/tests/test_lib_memory.py
index 357d90a..401b4bb 100644
--- a/tests/test_lib_memory.py
+++ b/tests/test_lib_memory.py
@@ -122,6 +122,15 @@ class WritePortTestCase(FHDLTestCase):
         self.assertIs(port.memory, m)
         self.assertEqual(m.w_ports, (port,))
 
+        signature = memory.WritePort.Signature(shape=MyStruct, addr_width=4)
+        port = signature.create()
+        self.assertEqual(port.signature, signature)
+        self.assertIsNone(port.memory)
+        self.assertEqual(port.domain, "sync")
+        self.assertRepr(port.addr, "(sig port__addr)")
+        port = signature.create(path=("abc",))
+        self.assertRepr(port.addr, "(sig abc__addr)")
+
     def test_constructor_wrong(self):
         signature = memory.ReadPort.Signature(shape=8, addr_width=4)
         with self.assertRaisesRegex(TypeError,
@@ -224,6 +233,15 @@ class ReadPortTestCase(FHDLTestCase):
         self.assertIs(port.memory, m)
         self.assertEqual(port.transparent_for, (write_port,))
 
+        signature = memory.ReadPort.Signature(shape=MyStruct, addr_width=4)
+        port = signature.create()
+        self.assertEqual(port.signature, signature)
+        self.assertIsNone(port.memory)
+        self.assertEqual(port.domain, "sync")
+        self.assertRepr(port.addr, "(sig port__addr)")
+        port = signature.create(path=("abc",))
+        self.assertRepr(port.addr, "(sig abc__addr)")
+
     def test_constructor_wrong(self):
         signature = memory.WritePort.Signature(shape=8, addr_width=4)
         with self.assertRaisesRegex(TypeError,