From 8bf655121ba1f657ac2f7e3f910847d48e3ce7a1 Mon Sep 17 00:00:00 2001 From: Staf Verhaegen Date: Sat, 16 Nov 2019 13:38:25 +0100 Subject: [PATCH] class Memory: add reset_less parameter that will not initialize memories with 0 value in generated RTL. This is to simulate better the behavior for ASIC memory implementation where memory blocks will have random value after startup. This parameter can be configured on class level so it can be set for all generated memory blocks if generating code for ASICs. --- nmigen/back/rtlil.py | 8 +++++--- nmigen/hdl/mem.py | 9 ++++++++- nmigen/test/test_hdl_mem.py | 13 +++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py index 5cd9f97f..e4774018 100644 --- a/nmigen/back/rtlil.py +++ b/nmigen/back/rtlil.py @@ -826,10 +826,12 @@ def _convert_fragment(builder, fragment, name_map, hierarchy): data_mask = (1 << memory.width) - 1 for addr in range(memory.depth): if addr < len(memory.init): - data = memory.init[addr] & data_mask + data = "{:0{}b}".format( + memory.init[addr] & data_mask, memory.width + ) else: - data = 0 - data_parts.append("{:0{}b}".format(data, memory.width)) + data = ("0" if not memory.reset_less else "x") * memory.width + data_parts.append(data) module.cell("$meminit", ports={ "\\ADDR": rhs_compiler(ast.Const(0, addr_bits)), "\\DATA": "{}'".format(memory.width * memory.depth) + diff --git a/nmigen/hdl/mem.py b/nmigen/hdl/mem.py index 93d5d160..da475d24 100644 --- a/nmigen/hdl/mem.py +++ b/nmigen/hdl/mem.py @@ -9,7 +9,11 @@ class Memory: - def __init__(self, *, width, depth, init=None, name=None, simulate=True): + # Configuration options to configure default behaviour for all generated memories + # These options should only be set in top level of code and not in modules + reset_less = False + + def __init__(self, *, width, depth, init=None, name=None, simulate=True, reset_less=None): if not isinstance(width, int) or width < 0: raise TypeError("Memory width must be a non-negative integer, not {!r}" .format(width)) @@ -30,6 +34,9 @@ def __init__(self, *, width, depth, init=None, name=None, simulate=True): self._array.append(Signal(self.width, name="{}({})" .format(name or "memory", addr))) + if reset_less is not None: + self.reset_less = reset_less + self.init = init @property diff --git a/nmigen/test/test_hdl_mem.py b/nmigen/test/test_hdl_mem.py index e7fc232a..3b13bf5e 100644 --- a/nmigen/test/test_hdl_mem.py +++ b/nmigen/test/test_hdl_mem.py @@ -42,6 +42,19 @@ def test_init_wrong_type(self): "'str' object cannot be interpreted as an integer"): m = Memory(width=8, depth=4, init=[1, "0"]) + def test_reset_less(self): + mem = Memory(width=8, depth=4, reset_less=True) + self.assertEqual(mem.reset_less, True) + + orig_reset_less = Memory.reset_less + Memory.reset_less = True + mem = Memory(width=8, depth=4) + self.assertEqual(mem.reset_less, True) + Memory.reset_less = False + mem = Memory(width=8, depth=4) + self.assertEqual(mem.reset_less, False) + Memory.reset_less = orig_reset_less + def test_read_port_transparent(self): mem = Memory(width=8, depth=4) rdport = mem.read_port()