From dd1d0efb42238f9141c89bf42c18ec67f83d2df4 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 23 Sep 2019 11:18:01 +0000 Subject: [PATCH] hdl.mem,lib.fifo: use keyword-only arguments for memory geometry. Fixes #230. --- nmigen/compat/genlib/fifo.py | 37 ++++++++++++++++++++++++++++++------ nmigen/hdl/mem.py | 2 +- nmigen/lib/fifo.py | 27 +++++++++++++------------- nmigen/test/test_lib_fifo.py | 14 +++++++------- 4 files changed, 53 insertions(+), 27 deletions(-) diff --git a/nmigen/compat/genlib/fifo.py b/nmigen/compat/genlib/fifo.py index c7d8c36..d491fd1 100644 --- a/nmigen/compat/genlib/fifo.py +++ b/nmigen/compat/genlib/fifo.py @@ -1,6 +1,7 @@ from ...tools import deprecated, extend -from ...lib.fifo import FIFOInterface as NativeFIFOInterface, \ - SyncFIFO, SyncFIFOBuffered, AsyncFIFO, AsyncFIFOBuffered +from ...lib.fifo import (FIFOInterface as NativeFIFOInterface, + SyncFIFO as NativeSyncFIFO, SyncFIFOBuffered as NativeSyncFIFOBuffered, + AsyncFIFO as NativeAsyncFIFO, AsyncFIFOBuffered as NativeAsyncFIFOBuffered) __all__ = ["_FIFOInterface", "SyncFIFO", "SyncFIFOBuffered", "AsyncFIFO", "AsyncFIFOBuffered"] @@ -9,13 +10,10 @@ __all__ = ["_FIFOInterface", "SyncFIFO", "SyncFIFOBuffered", "AsyncFIFO", "Async class CompatFIFOInterface(NativeFIFOInterface): @deprecated("attribute `fwft` must be provided to FIFOInterface constructor") def __init__(self, width, depth): - super().__init__(width, depth, fwft=False) + super().__init__(width=width, depth=depth, fwft=False) del self.fwft -_FIFOInterface = CompatFIFOInterface - - @extend(NativeFIFOInterface) def read(self): """Read method for simulation.""" @@ -36,3 +34,30 @@ def write(self, data): yield yield self.w_en.eq(0) 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 diff --git a/nmigen/hdl/mem.py b/nmigen/hdl/mem.py index 8335cc0..47a4386 100644 --- a/nmigen/hdl/mem.py +++ b/nmigen/hdl/mem.py @@ -9,7 +9,7 @@ __all__ = ["Memory", "ReadPort", "WritePort", "DummyPort"] 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: raise TypeError("Memory width must be a non-negative integer, not '{!r}'" .format(width)) diff --git a/nmigen/lib/fifo.py b/nmigen/lib/fifo.py index c96288a..60f8a3b 100644 --- a/nmigen/lib/fifo.py +++ b/nmigen/lib/fifo.py @@ -60,7 +60,7 @@ class FIFOInterface: w_attributes="", r_attributes="") - def __init__(self, width, depth, *, fwft): + def __init__(self, *, width, depth, fwft): if not isinstance(width, int) or width < 0: raise TypeError("FIFO width must be a non-negative integer, not '{!r}'" .format(width)) @@ -184,8 +184,8 @@ class SyncFIFO(Elaboratable, FIFOInterface): """.strip(), w_attributes="") - def __init__(self, width, depth, *, fwft=True): - super().__init__(width, depth, fwft=fwft) + def __init__(self, *, width, depth, fwft=True): + super().__init__(width=width, depth=depth, fwft=fwft) self.level = Signal.range(depth + 1) @@ -199,7 +199,7 @@ class SyncFIFO(Elaboratable, FIFOInterface): do_read = self.r_rdy & self.r_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() r_port = m.submodules.r_port = storage.read_port( domain="comb" if self.fwft else "sync", transparent=self.fwft) @@ -279,8 +279,8 @@ class SyncFIFOBuffered(Elaboratable, FIFOInterface): """.strip(), w_attributes="") - def __init__(self, width, depth): - super().__init__(width, depth, fwft=True) + def __init__(self, *, width, depth): + super().__init__(width=width, depth=depth, fwft=True) 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 # 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 += [ fifo.w_data.eq(self.w_data), @@ -336,14 +337,14 @@ class AsyncFIFO(Elaboratable, FIFOInterface): r_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: depth_bits = log2_int(depth, need_pow2=exact_depth) except ValueError as e: raise ValueError("AsyncFIFO only supports depths that are powers of 2; requested " "exact depth {} is not" .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._w_domain = w_domain @@ -397,7 +398,7 @@ class AsyncFIFO(Elaboratable, FIFOInterface): 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) r_port = m.submodules.r_port = storage.read_port (domain=self._r_domain, transparent=False) @@ -454,21 +455,21 @@ class AsyncFIFOBuffered(Elaboratable, FIFOInterface): r_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: depth_bits = log2_int(max(0, depth - 1), need_pow2=exact_depth) except ValueError as e: raise ValueError("AsyncFIFOBuffered only supports depths that are one higher " "than powers of 2; requested exact depth {} is not" .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._w_domain = w_domain def elaborate(self, platform): 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) m.d.comb += [ diff --git a/nmigen/test/test_lib_fifo.py b/nmigen/test/test_lib_fifo.py index 835d7b7..d1d465f 100644 --- a/nmigen/test/test_lib_fifo.py +++ b/nmigen/test/test_lib_fifo.py @@ -49,8 +49,8 @@ class FIFOModel(Elaboratable, FIFOInterface): """ Non-synthesizable first-in first-out queue, implemented naively as a chain of registers. """ - def __init__(self, width, depth, *, fwft, r_domain, w_domain): - super().__init__(width, depth, fwft=fwft) + def __init__(self, *, width, depth, fwft, r_domain, w_domain): + super().__init__(width=width, depth=depth, fwft=fwft) self.r_domain = r_domain self.w_domain = w_domain @@ -60,7 +60,7 @@ class FIFOModel(Elaboratable, FIFOInterface): def elaborate(self, platform): 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) r_port = m.submodules.r_port = storage.read_port (domain="comb") @@ -110,7 +110,7 @@ class FIFOModelEquivalenceSpec(Elaboratable): def elaborate(self, platform): m = Module() 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) 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 circumstances, with the exception of reset. """ - def __init__(self, fifo, r_domain, w_domain, bound): - self.fifo = fifo + def __init__(self, fifo, *, r_domain, w_domain, bound): + self.fifo = fifo self.r_domain = r_domain self.w_domain = w_domain - self.bound = bound + self.bound = bound def elaborate(self, platform): m = Module() -- 2.30.2