add Config Fetch interface and quick unit test
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 28 Jun 2020 19:37:07 +0000 (20:37 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 28 Jun 2020 19:37:07 +0000 (20:37 +0100)
src/soc/config/ifetch.py [new file with mode: 0644]
src/soc/config/test/test_fetch.py [new file with mode: 0644]
src/soc/config/test/test_loadstore.py
src/soc/experiment/imem.py

diff --git a/src/soc/config/ifetch.py b/src/soc/config/ifetch.py
new file mode 100644 (file)
index 0000000..0aea456
--- /dev/null
@@ -0,0 +1,22 @@
+"""ConfigureableFetchUnit and ConfigMemoryPortInterface
+
+allows the type of FetchUnit to be run-time selectable
+
+this allows the same code to be used for both small unit tests
+as well as larger ones and so on, without needing large amounts
+of unnecessarily-duplicated code
+"""
+from soc.experiment.imem import TestMemFetchUnit
+#from soc.bus.test.test_minerva import TestSRAMBareFetchUnit
+
+
+class ConfigFetchUnit:
+    def __init__(self, pspec):
+        fudict = {'testmem': TestMemFetchUnit,
+                   #'test_bare_wb': TestSRAMBareFetchUnit,
+                   #'test_cache_wb': TestCacheFetchUnit
+                  }
+        fukls = fudict[pspec.imem_ifacetype]
+        self.fu = fukls(addr_wid=pspec.addr_wid, # address range
+                          data_wid=pspec.reg_wid)  # data bus width
+
diff --git a/src/soc/config/test/test_fetch.py b/src/soc/config/test/test_fetch.py
new file mode 100644 (file)
index 0000000..e772eb8
--- /dev/null
@@ -0,0 +1,62 @@
+from soc.minerva.units.fetch import FetchUnitInterface
+from nmigen import Signal, Module, Elaboratable, Mux
+from nmigen.utils import log2_int
+import random
+from nmigen.back.pysim import Simulator, Settle
+from soc.config.ifetch import ConfigFetchUnit
+from collections import namedtuple
+from nmigen.cli import rtlil
+
+from soc.config.test.test_loadstore import TestMemPspec 
+
+
+def read_from_addr(dut, addr):
+    yield dut.a_pc_i.eq(addr)
+    yield dut.a_valid_i.eq(1)
+    yield dut.a_stall_i.eq(1)
+    yield
+    yield dut.a_stall_i.eq(0)
+    yield
+    yield Settle()
+    while (yield dut.f_busy_o):
+        yield
+    assert (yield dut.a_valid_i)
+    return (yield dut.f_instr_o)
+
+
+def tst_lsmemtype(ifacetype):
+    m = Module()
+    pspec = TestMemPspec(ldst_ifacetype=ifacetype, 
+                         imem_ifacetype=ifacetype, addr_wid=64,
+                                                   mask_wid=4,
+                                                   reg_wid=32)
+    dut = ConfigFetchUnit(pspec).fu
+    vl = rtlil.convert(dut, ports=[]) # TODOdut.ports())
+    with open("test_fetch_%s.il" % ifacetype, "w") as f:
+        f.write(vl)
+
+    m.submodules.dut = dut
+
+    sim = Simulator(m)
+    sim.add_clock(1e-6)
+
+    mem = dut.mem.mem
+
+    def process():
+
+        values = [random.randint(0, (1<<32)-1) for x in range(16)]
+        for addr, val in enumerate(values):
+            yield mem._array[addr].eq(val)
+
+        for addr, val in enumerate(values):
+            x = yield from read_from_addr(dut, addr << 2)
+            print ("addr, val", addr, hex(val), hex(x))
+            assert x == val
+
+    sim.add_sync_process(process)
+    with sim.write_vcd("test_fetch_%s.vcd" % ifacetype, traces=[]):
+        sim.run()
+
+if __name__ == '__main__':
+    #tst_lsmemtype('test_bare_wb')
+    tst_lsmemtype('testmem')
index 2e337e92f7ba0ac72d3a4b8ee00a5bf03c2b0ebf..d70c380764ac8c5afa67656b20b114aaf0957f61 100644 (file)
@@ -8,6 +8,7 @@ from collections import namedtuple
 from nmigen.cli import rtlil
 
 TestMemPspec = namedtuple('TestMemPspec', ['ldst_ifacetype',
+                             'imem_ifacetype',
                              'addr_wid', 'mask_wid', 'reg_wid'])
 
 def write_to_addr(dut, addr, value):
index 1662c48ffc68724f2501c9294778eabc2dded3cd..5f0f622c6b26d70467cc3fe27e3db7102886d21a 100644 (file)
@@ -6,13 +6,17 @@ from nmigen.cli import rtlil
 
 class TestMemFetchUnit(FetchUnitInterface, Elaboratable):
 
+    def __init__(self, addr_wid=32, data_wid=32):
+        super().__init__(addr_wid=addr_wid, data_wid=data_wid)
+        # limit TestMemory to 2^6 entries of regwid size
+        self.mem = TestMemory(self.data_wid, 6, readonly=True)
+
     def elaborate(self, platform):
         m = Module()
         regwid, addrwid = self.data_wid, self.addr_wid
         adr_lsb = self.adr_lsbs
 
-        # limit TestMemory to 2^6 entries of regwid size
-        m.submodules.mem = mem = TestMemory(regwid, 6, readonly=True)
+        m.submodules.mem = mem = self.mem
 
         do_fetch = Signal()  # set when fetch while valid and not stalled
         m.d.comb += do_fetch.eq(self.a_valid_i & ~self.a_stall_i)