Skip to content

Commit 2255cb7

Browse files
committed
Implement RFC 45: Move hdl.Memory to lib.Memory.
1 parent 24a3928 commit 2255cb7

File tree

17 files changed

+996
-141
lines changed

17 files changed

+996
-141
lines changed

amaranth/hdl/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from ._dsl import SyntaxError, SyntaxWarning, Module
55
from ._cd import DomainError, ClockDomain
66
from ._ir import UnusedElaboratable, Elaboratable, DriverConflict, Fragment, Instance
7-
from ._mem import Memory, ReadPort, WritePort, DummyPort
7+
from ._mem import MemoryIdentity, MemoryInstance, Memory, ReadPort, WritePort, DummyPort
88
from ._rec import Record
99
from ._xfrm import DomainRenamer, ResetInserter, EnableInserter
1010

@@ -21,7 +21,7 @@
2121
# _ir
2222
"UnusedElaboratable", "Elaboratable", "DriverConflict", "Fragment", "Instance",
2323
# _mem
24-
"Memory", "ReadPort", "WritePort", "DummyPort",
24+
"MemoryIdentity", "MemoryInstance", "Memory", "ReadPort", "WritePort", "DummyPort",
2525
# _rec
2626
"Record",
2727
# _xfrm

amaranth/hdl/_ir.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,7 @@ def emit_read_port(self, module_idx: int, fragment: '_mem.MemoryInstance',
11091109
en=en,
11101110
clk=clk,
11111111
clk_edge=cd.clk_edge,
1112-
transparent_for=tuple(write_ports[idx] for idx in port._transparency),
1112+
transparent_for=tuple(write_ports[idx] for idx in port._transparent_for),
11131113
src_loc=port._data.src_loc,
11141114
)
11151115
data = self.netlist.add_value_cell(len(port._data), cell)

amaranth/hdl/_mem.py

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from ._ast import *
66
from ._ir import Elaboratable, Fragment
77
from ..utils import ceil_log2
8+
from .._utils import deprecated
89

910

1011
__all__ = ["Memory", "ReadPort", "WritePort", "DummyPort"]
@@ -33,18 +34,19 @@ def __init__(self, identity, addr, data):
3334

3435
class MemoryInstance(Fragment):
3536
class _ReadPort:
36-
def __init__(self, *, domain, addr, data, en, transparency):
37+
def __init__(self, *, domain, addr, data, en, transparent_for):
3738
assert isinstance(domain, str)
3839
self._domain = domain
3940
self._addr = Value.cast(addr)
4041
self._data = Value.cast(data)
4142
self._en = Value.cast(en)
42-
self._transparency = tuple(transparency)
43+
self._transparent_for = tuple(transparent_for)
4344
assert len(self._en) == 1
4445
if domain == "comb":
4546
assert isinstance(self._en, Const)
4647
assert self._en.width == 1
4748
assert self._en.value == 1
49+
assert not self._transparent_for
4850

4951
class _WritePort:
5052
def __init__(self, *, domain, addr, data, en):
@@ -70,23 +72,25 @@ def __init__(self, *, identity, width, depth, init=None, attrs=None, src_loc=Non
7072
self._identity = identity
7173
self._width = operator.index(width)
7274
self._depth = operator.index(depth)
73-
self._init = tuple(init) if init is not None else ()
75+
mask = (1 << self._width) - 1
76+
self._init = tuple(item & mask for item in init) if init is not None else ()
7477
assert len(self._init) <= self._depth
7578
self._init += (0,) * (self._depth - len(self._init))
7679
for x in self._init:
7780
assert isinstance(x, int)
7881
self._attrs = attrs or {}
7982
self._src_loc = src_loc
80-
self._read_ports = []
81-
self._write_ports = []
83+
self._read_ports: "list[MemoryInstance._ReadPort]" = []
84+
self._write_ports: "list[MemoryInstance._WritePort]" = []
8285

83-
def read_port(self, *, domain, addr, data, en, transparency):
84-
port = self._ReadPort(domain=domain, addr=addr, data=data, en=en, transparency=transparency)
86+
def read_port(self, *, domain, addr, data, en, transparent_for):
87+
port = self._ReadPort(domain=domain, addr=addr, data=data, en=en, transparent_for=transparent_for)
8588
assert len(port._data) == self._width
8689
assert len(port._addr) == ceil_log2(self._depth)
87-
for x in port._transparency:
88-
assert isinstance(x, int)
89-
assert x in range(len(self._write_ports))
90+
for idx in port._transparent_for:
91+
assert isinstance(idx, int)
92+
assert idx in range(len(self._write_ports))
93+
assert self._write_ports[idx]._domain == port._domain
9094
for signal in port._data._rhs_signals():
9195
self.add_driver(signal, port._domain)
9296
self._read_ports.append(port)
@@ -125,6 +129,8 @@ class Memory(Elaboratable):
125129
init : list of int
126130
attrs : dict
127131
"""
132+
# TODO(amaranth-0.6): remove
133+
@deprecated("`amaranth.hdl.Memory` is deprecated, use `amaranth.lib.memory.Memory` instead")
128134
def __init__(self, *, width, depth, init=None, name=None, attrs=None, simulate=True):
129135
if not isinstance(width, int) or width < 0:
130136
raise TypeError("Memory width must be a non-negative integer, not {!r}"
@@ -133,8 +139,8 @@ def __init__(self, *, width, depth, init=None, name=None, attrs=None, simulate=T
133139
raise TypeError("Memory depth must be a non-negative integer, not {!r}"
134140
.format(depth))
135141

136-
self.name = name or tracer.get_var_name(depth=2, default="$memory")
137-
self.src_loc = tracer.get_src_loc()
142+
self.name = name or tracer.get_var_name(depth=3, default="$memory")
143+
self.src_loc = tracer.get_src_loc(src_loc_at=1)
138144

139145
self.width = width
140146
self.depth = depth
@@ -209,12 +215,12 @@ def elaborate(self, platform):
209215
for port in self._read_ports:
210216
port._MustUse__used = True
211217
if port.domain == "comb":
212-
f.read_port(domain="comb", addr=port.addr, data=port.data, en=Const(1), transparency=())
218+
f.read_port(domain="comb", addr=port.addr, data=port.data, en=Const(1), transparent_for=())
213219
else:
214-
transparency = []
220+
transparent_for = []
215221
if port.transparent:
216-
transparency = write_ports.get(port.domain, [])
217-
f.read_port(domain=port.domain, addr=port.addr, data=port.data, en=port.en, transparency=transparency)
222+
transparent_for = write_ports.get(port.domain, [])
223+
f.read_port(domain=port.domain, addr=port.addr, data=port.data, en=port.en, transparent_for=transparent_for)
218224
return f
219225

220226

@@ -347,13 +353,15 @@ class DummyPort:
347353
It does not include any read/write port specific attributes, i.e. none besides ``"domain"``;
348354
any such attributes may be set manually.
349355
"""
356+
# TODO(amaranth-0.6): remove
357+
@deprecated("`DummyPort` is deprecated, use `amaranth.lib.memory.ReadPort` or `amaranth.lib.memory.WritePort` instead")
350358
def __init__(self, *, data_width, addr_width, domain="sync", name=None, granularity=None):
351359
self.domain = domain
352360

353361
if granularity is None:
354362
granularity = data_width
355363
if name is None:
356-
name = tracer.get_var_name(depth=2, default="dummy")
364+
name = tracer.get_var_name(depth=3, default="dummy")
357365

358366
self.addr = Signal(addr_width,
359367
name=f"{name}_addr", src_loc_at=1)

amaranth/hdl/_xfrm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def on_fragment(self, fragment):
263263
addr=port._addr,
264264
data=port._data,
265265
en=port._en,
266-
transparency=port._transparency,
266+
transparent_for=port._transparent_for,
267267
)
268268
for port in fragment._read_ports
269269
]

amaranth/lib/fifo.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
"""First-in first-out queues."""
22

3-
import warnings
4-
53
from .. import *
64
from ..asserts import *
75
from ..utils import ceil_log2
86
from .coding import GrayEncoder, GrayDecoder
97
from .cdc import FFSynchronizer, AsyncFFSynchronizer
8+
from .memory import Memory
109

1110

1211
__all__ = ["FIFOInterface", "SyncFIFO", "SyncFIFOBuffered", "AsyncFIFO", "AsyncFIFOBuffered"]
@@ -130,7 +129,7 @@ def elaborate(self, platform):
130129
do_read = self.r_rdy & self.r_en
131130
do_write = self.w_rdy & self.w_en
132131

133-
storage = m.submodules.storage = Memory(width=self.width, depth=self.depth)
132+
storage = m.submodules.storage = Memory(shape=self.width, depth=self.depth, init=[])
134133
w_port = storage.write_port()
135134
r_port = storage.read_port(domain="comb")
136135
produce = Signal(range(self.depth))
@@ -257,9 +256,9 @@ def elaborate(self, platform):
257256

258257
do_inner_read = inner_r_rdy & (~self.r_rdy | self.r_en)
259258

260-
storage = m.submodules.storage = Memory(width=self.width, depth=inner_depth)
259+
storage = m.submodules.storage = Memory(shape=self.width, depth=inner_depth, init=[])
261260
w_port = storage.write_port()
262-
r_port = storage.read_port(domain="sync", transparent=False)
261+
r_port = storage.read_port(domain="sync")
263262
produce = Signal(range(inner_depth))
264263
consume = Signal(range(inner_depth))
265264

@@ -438,9 +437,9 @@ def elaborate(self, platform):
438437
m.d[self._w_domain] += self.w_level.eq(produce_w_bin - consume_w_bin)
439438
m.d.comb += self.r_level.eq(produce_r_bin - consume_r_bin)
440439

441-
storage = m.submodules.storage = Memory(width=self.width, depth=self.depth)
440+
storage = m.submodules.storage = Memory(shape=self.width, depth=self.depth, init=[])
442441
w_port = storage.write_port(domain=self._w_domain)
443-
r_port = storage.read_port (domain=self._r_domain, transparent=False)
442+
r_port = storage.read_port (domain=self._r_domain)
444443
m.d.comb += [
445444
w_port.addr.eq(produce_w_bin[:-1]),
446445
w_port.data.eq(self.w_data),

0 commit comments

Comments
 (0)