hdl.mem,lib.fifo: use keyword-only arguments for memory geometry.

Fixes #230.
This commit is contained in:
whitequark 2019-09-23 11:18:01 +00:00
parent 1aeb11d7e3
commit bc53bbf564
4 changed files with 53 additions and 27 deletions

View file

@ -1,6 +1,7 @@
from ...tools import deprecated, extend from ...tools import deprecated, extend
from ...lib.fifo import FIFOInterface as NativeFIFOInterface, \ from ...lib.fifo import (FIFOInterface as NativeFIFOInterface,
SyncFIFO, SyncFIFOBuffered, AsyncFIFO, AsyncFIFOBuffered SyncFIFO as NativeSyncFIFO, SyncFIFOBuffered as NativeSyncFIFOBuffered,
AsyncFIFO as NativeAsyncFIFO, AsyncFIFOBuffered as NativeAsyncFIFOBuffered)
__all__ = ["_FIFOInterface", "SyncFIFO", "SyncFIFOBuffered", "AsyncFIFO", "AsyncFIFOBuffered"] __all__ = ["_FIFOInterface", "SyncFIFO", "SyncFIFOBuffered", "AsyncFIFO", "AsyncFIFOBuffered"]
@ -9,13 +10,10 @@ __all__ = ["_FIFOInterface", "SyncFIFO", "SyncFIFOBuffered", "AsyncFIFO", "Async
class CompatFIFOInterface(NativeFIFOInterface): class CompatFIFOInterface(NativeFIFOInterface):
@deprecated("attribute `fwft` must be provided to FIFOInterface constructor") @deprecated("attribute `fwft` must be provided to FIFOInterface constructor")
def __init__(self, width, depth): def __init__(self, width, depth):
super().__init__(width, depth, fwft=False) super().__init__(width=width, depth=depth, fwft=False)
del self.fwft del self.fwft
_FIFOInterface = CompatFIFOInterface
@extend(NativeFIFOInterface) @extend(NativeFIFOInterface)
def read(self): def read(self):
"""Read method for simulation.""" """Read method for simulation."""
@ -36,3 +34,30 @@ def write(self, data):
yield yield
yield self.w_en.eq(0) yield self.w_en.eq(0)
yield yield
class CompatSyncFIFO(NativeSyncFIFO):
def __init__(self, width, depth, fwft=True):
super().__init__(width=width, depth=depth, fwft=fwft)
class CompatSyncFIFOBuffered(NativeSyncFIFOBuffered):
def __init__(self, width, depth):
super().__init__(width=width, depth=depth)
class CompatAsyncFIFO(NativeAsyncFIFO):
def __init__(self, width, depth):
super().__init__(width=width, depth=depth)
class CompatAsyncFIFOBuffered(NativeAsyncFIFOBuffered):
def __init__(self, width, depth):
super().__init__(width=width, depth=depth)
_FIFOInterface = CompatFIFOInterface
SyncFIFO = CompatSyncFIFO
SyncFIFOBuffered = CompatSyncFIFOBuffered
AsyncFIFO = CompatAsyncFIFO
AsyncFIFOBuffered = CompatAsyncFIFOBuffered

View file

@ -9,7 +9,7 @@ __all__ = ["Memory", "ReadPort", "WritePort", "DummyPort"]
class Memory: class Memory:
def __init__(self, width, depth, *, init=None, name=None, simulate=True): def __init__(self, *, width, depth, init=None, name=None, simulate=True):
if not isinstance(width, int) or width < 0: if not isinstance(width, int) or width < 0:
raise TypeError("Memory width must be a non-negative integer, not '{!r}'" raise TypeError("Memory width must be a non-negative integer, not '{!r}'"
.format(width)) .format(width))

View file

@ -60,7 +60,7 @@ class FIFOInterface:
w_attributes="", w_attributes="",
r_attributes="") r_attributes="")
def __init__(self, width, depth, *, fwft): def __init__(self, *, width, depth, fwft):
if not isinstance(width, int) or width < 0: if not isinstance(width, int) or width < 0:
raise TypeError("FIFO width must be a non-negative integer, not '{!r}'" raise TypeError("FIFO width must be a non-negative integer, not '{!r}'"
.format(width)) .format(width))
@ -184,8 +184,8 @@ class SyncFIFO(Elaboratable, FIFOInterface):
""".strip(), """.strip(),
w_attributes="") w_attributes="")
def __init__(self, width, depth, *, fwft=True): def __init__(self, *, width, depth, fwft=True):
super().__init__(width, depth, fwft=fwft) super().__init__(width=width, depth=depth, fwft=fwft)
self.level = Signal.range(depth + 1) self.level = Signal.range(depth + 1)
@ -199,7 +199,7 @@ class SyncFIFO(Elaboratable, FIFOInterface):
do_read = self.r_rdy & self.r_en do_read = self.r_rdy & self.r_en
do_write = self.w_rdy & self.w_en do_write = self.w_rdy & self.w_en
storage = Memory(self.width, self.depth) storage = Memory(width=self.width, depth=self.depth)
w_port = m.submodules.w_port = storage.write_port() w_port = m.submodules.w_port = storage.write_port()
r_port = m.submodules.r_port = storage.read_port( r_port = m.submodules.r_port = storage.read_port(
domain="comb" if self.fwft else "sync", transparent=self.fwft) domain="comb" if self.fwft else "sync", transparent=self.fwft)
@ -279,8 +279,8 @@ class SyncFIFOBuffered(Elaboratable, FIFOInterface):
""".strip(), """.strip(),
w_attributes="") w_attributes="")
def __init__(self, width, depth): def __init__(self, *, width, depth):
super().__init__(width, depth, fwft=True) super().__init__(width=width, depth=depth, fwft=True)
self.level = Signal.range(depth + 1) self.level = Signal.range(depth + 1)
@ -289,7 +289,8 @@ class SyncFIFOBuffered(Elaboratable, FIFOInterface):
# Effectively, this queue treats the output register of the non-FWFT inner queue as # Effectively, this queue treats the output register of the non-FWFT inner queue as
# an additional storage element. # an additional storage element.
m.submodules.unbuffered = fifo = SyncFIFO(self.width, self.depth - 1, fwft=False) m.submodules.unbuffered = fifo = SyncFIFO(width=self.width, depth=self.depth - 1,
fwft=False)
m.d.comb += [ m.d.comb += [
fifo.w_data.eq(self.w_data), fifo.w_data.eq(self.w_data),
@ -336,14 +337,14 @@ class AsyncFIFO(Elaboratable, FIFOInterface):
r_attributes="", r_attributes="",
w_attributes="") w_attributes="")
def __init__(self, width, depth, *, r_domain="read", w_domain="write", exact_depth=False): def __init__(self, *, width, depth, r_domain="read", w_domain="write", exact_depth=False):
try: try:
depth_bits = log2_int(depth, need_pow2=exact_depth) depth_bits = log2_int(depth, need_pow2=exact_depth)
except ValueError as e: except ValueError as e:
raise ValueError("AsyncFIFO only supports depths that are powers of 2; requested " raise ValueError("AsyncFIFO only supports depths that are powers of 2; requested "
"exact depth {} is not" "exact depth {} is not"
.format(depth)) from None .format(depth)) from None
super().__init__(width, 1 << depth_bits, fwft=True) super().__init__(width=width, depth=1 << depth_bits, fwft=True)
self._r_domain = r_domain self._r_domain = r_domain
self._w_domain = w_domain self._w_domain = w_domain
@ -397,7 +398,7 @@ class AsyncFIFO(Elaboratable, FIFOInterface):
r_empty.eq(consume_r_gry == produce_r_gry), r_empty.eq(consume_r_gry == produce_r_gry),
] ]
storage = Memory(self.width, self.depth) storage = Memory(width=self.width, depth=self.depth)
w_port = m.submodules.w_port = storage.write_port(domain=self._w_domain) w_port = m.submodules.w_port = storage.write_port(domain=self._w_domain)
r_port = m.submodules.r_port = storage.read_port (domain=self._r_domain, r_port = m.submodules.r_port = storage.read_port (domain=self._r_domain,
transparent=False) transparent=False)
@ -454,21 +455,21 @@ class AsyncFIFOBuffered(Elaboratable, FIFOInterface):
r_attributes="", r_attributes="",
w_attributes="") w_attributes="")
def __init__(self, width, depth, *, r_domain="read", w_domain="write", exact_depth=False): def __init__(self, *, width, depth, r_domain="read", w_domain="write", exact_depth=False):
try: try:
depth_bits = log2_int(max(0, depth - 1), need_pow2=exact_depth) depth_bits = log2_int(max(0, depth - 1), need_pow2=exact_depth)
except ValueError as e: except ValueError as e:
raise ValueError("AsyncFIFOBuffered only supports depths that are one higher " raise ValueError("AsyncFIFOBuffered only supports depths that are one higher "
"than powers of 2; requested exact depth {} is not" "than powers of 2; requested exact depth {} is not"
.format(depth)) from None .format(depth)) from None
super().__init__(width, (1 << depth_bits) + 1, fwft=True) super().__init__(width=width, depth=(1 << depth_bits) + 1, fwft=True)
self._r_domain = r_domain self._r_domain = r_domain
self._w_domain = w_domain self._w_domain = w_domain
def elaborate(self, platform): def elaborate(self, platform):
m = Module() m = Module()
m.submodules.unbuffered = fifo = AsyncFIFO(self.width, self.depth - 1, m.submodules.unbuffered = fifo = AsyncFIFO(width=self.width, depth=self.depth - 1,
r_domain=self._r_domain, w_domain=self._w_domain) r_domain=self._r_domain, w_domain=self._w_domain)
m.d.comb += [ m.d.comb += [

View file

@ -49,8 +49,8 @@ class FIFOModel(Elaboratable, FIFOInterface):
""" """
Non-synthesizable first-in first-out queue, implemented naively as a chain of registers. Non-synthesizable first-in first-out queue, implemented naively as a chain of registers.
""" """
def __init__(self, width, depth, *, fwft, r_domain, w_domain): def __init__(self, *, width, depth, fwft, r_domain, w_domain):
super().__init__(width, depth, fwft=fwft) super().__init__(width=width, depth=depth, fwft=fwft)
self.r_domain = r_domain self.r_domain = r_domain
self.w_domain = w_domain self.w_domain = w_domain
@ -60,7 +60,7 @@ class FIFOModel(Elaboratable, FIFOInterface):
def elaborate(self, platform): def elaborate(self, platform):
m = Module() m = Module()
storage = Memory(self.width, self.depth) storage = Memory(width=self.width, depth=self.depth)
w_port = m.submodules.w_port = storage.write_port(domain=self.w_domain) w_port = m.submodules.w_port = storage.write_port(domain=self.w_domain)
r_port = m.submodules.r_port = storage.read_port (domain="comb") r_port = m.submodules.r_port = storage.read_port (domain="comb")
@ -110,7 +110,7 @@ class FIFOModelEquivalenceSpec(Elaboratable):
def elaborate(self, platform): def elaborate(self, platform):
m = Module() m = Module()
m.submodules.dut = dut = self.fifo m.submodules.dut = dut = self.fifo
m.submodules.gold = gold = FIFOModel(dut.width, dut.depth, fwft=dut.fwft, m.submodules.gold = gold = FIFOModel(width=dut.width, depth=dut.depth, fwft=dut.fwft,
r_domain=self.r_domain, w_domain=self.w_domain) r_domain=self.r_domain, w_domain=self.w_domain)
m.d.comb += [ m.d.comb += [
@ -141,11 +141,11 @@ class FIFOContractSpec(Elaboratable):
consecutively, they must be read out consecutively at some later point, no matter all other consecutively, they must be read out consecutively at some later point, no matter all other
circumstances, with the exception of reset. circumstances, with the exception of reset.
""" """
def __init__(self, fifo, r_domain, w_domain, bound): def __init__(self, fifo, *, r_domain, w_domain, bound):
self.fifo = fifo self.fifo = fifo
self.r_domain = r_domain self.r_domain = r_domain
self.w_domain = w_domain self.w_domain = w_domain
self.bound = bound self.bound = bound
def elaborate(self, platform): def elaborate(self, platform):
m = Module() m = Module()