read from instruction memory using FetchUnitInterface
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 28 Jun 2020 20:14:52 +0000 (21:14 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 28 Jun 2020 20:14:52 +0000 (21:14 +0100)
src/soc/bus/test/__init__.py [new file with mode: 0644]
src/soc/experiment/imem.py
src/soc/experiment/l0_cache.py
src/soc/minerva/units/fetch.py
src/soc/simple/__init__.py [new file with mode: 0644]
src/soc/simple/issuer.py
src/soc/simple/test/test_issuer.py

diff --git a/src/soc/bus/test/__init__.py b/src/soc/bus/test/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
index 5f0f622c6b26d70467cc3fe27e3db7102886d21a..17c5b1ebcb751fc9acdbf567eb3b3110441d3104 100644 (file)
@@ -7,6 +7,7 @@ from nmigen.cli import rtlil
 class TestMemFetchUnit(FetchUnitInterface, Elaboratable):
 
     def __init__(self, addr_wid=32, data_wid=32):
+        print ("testmemfetchunit", addr_wid, data_wid)
         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)
@@ -40,6 +41,12 @@ class TestMemFetchUnit(FetchUnitInterface, Elaboratable):
 
         return m
 
+    def __iter__(self): # TODO
+        yield self.a_pc_i
+        yield self.f_instr_o
+
+    def ports(self):
+        return list(self)
 
 if __name__ == '__main__':
     dut = TestMemFetchUnit(addr_wid=32, data_wid=32)
index f42545d5a2c480919e00603080fe82e6440538ce..cd779c886bee574a28e8edec777141aa68d0ce0a 100644 (file)
@@ -266,6 +266,7 @@ class L0CacheBuffer(Elaboratable):
 class TstL0CacheBuffer(Elaboratable):
     def __init__(self, n_units=3, regwid=16, addrwid=4, ifacetype='testpi'):
         pspec = TestMemPspec(ldst_ifacetype=ifacetype,
+                             imem_ifacetype='',
                              addr_wid=addrwid<<1,
                              mask_wid=8,
                              reg_wid=regwid)
index 9aa1ef29cabadd92f67cc076786d0f8ba2f1c9be..dd691aebd88dccc909f55aed70bb4bc8c2a74a92 100644 (file)
@@ -13,7 +13,7 @@ class FetchUnitInterface:
         self.addr_wid = addr_wid
         self.data_wid = data_wid
         self.adr_lsbs = log2_int(data_wid//8)
-        self.ibus = Record(make_wb_layout(addr_wid, self.adr_lsbs, data_wid))
+        self.ibus = Record(make_wb_layout(addr_wid, data_wid//8, data_wid))
         bad_wid = addr_wid - self.adr_lsbs # TODO: is this correct?
 
         # inputs: address to fetch PC, and valid/stall signalling
diff --git a/src/soc/simple/__init__.py b/src/soc/simple/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
index 7dfa9d6797732a4ed10da59cb4062f29f0f65925..8194b44a52a0c17ed55d9ed23bc83b4ad5b68186 100644 (file)
@@ -18,11 +18,12 @@ improved.
 from nmigen import Elaboratable, Module, Signal
 from nmigen.cli import rtlil
 
-
 from soc.decoder.decode2execute1 import Data
 from soc.experiment.testmem import TestMemory # test only for instructions
 from soc.regfile.regfiles import FastRegs
 from soc.simple.core import NonProductionCore
+from soc.config.test.test_loadstore import TestMemPspec
+from soc.config.ifetch import ConfigFetchUnit
 
 
 class TestIssuer(Elaboratable):
@@ -30,14 +31,18 @@ class TestIssuer(Elaboratable):
 
     efficiency and speed is not the main goal here: functional correctness is.
     """
-    def __init__(self, addrwid=6, idepth=6, ifacetype='testpi'):
+    def __init__(self, addrwid=6, idepth=6, ifacetype='testpi',
+                                            imemtype='testmem'):
         # main instruction core
         self.core = core = NonProductionCore(addrwid, ifacetype=ifacetype)
 
+        pspec = TestMemPspec(ldst_ifacetype=ifacetype,
+                             imem_ifacetype=imemtype,
+                             addr_wid=addrwid<<1,
+                             mask_wid=8,
+                             reg_wid=64) # instruction memory width
         # Test Instruction memory
-        self.imemwid = 64
-        self.imem = TestMemory(self.imemwid, idepth)
-        self.i_rd = self.imem.rdport
+        self.imem = ConfigFetchUnit(pspec).fu
         # one-row cache of instruction read
         self.iline = Signal(64) # one instruction line
         self.iprev_adr = Signal(64) # previous address: if different, do read
@@ -106,20 +111,28 @@ class TestIssuer(Elaboratable):
                     # capture the PC and also drop it into Insn Memory
                     # we have joined a pair of combinatorial memory
                     # lookups together.  this is Generally Bad.
-                    comb += self.i_rd.addr.eq(pc[3:]) # ignore last 3 bits
+                    comb += self.imem.a_pc_i.eq(pc)
+                    comb += self.imem.a_valid_i.eq(1)
+                    comb += self.imem.f_valid_i.eq(1)
                     sync += current_pc.eq(pc)
-                    m.next = "INSN_READ" # move to "issue" phase
+                    m.next = "INSN_READ" # move to "wait for bus" phase
 
-            # got the instruction: start issue
+            # waiting for instruction bus (stays there until not busy)
             with m.State("INSN_READ"):
-                insn = self.i_rd.data.word_select(current_pc[2], 32) #
-                comb += current_insn.eq(insn)
-                comb += core_ivalid_i.eq(1) # say instruction is valid
-                comb += core_issue_i.eq(1)  # and issued (ivalid_i redundant)
-                comb += core_be_i.eq(0)     # little-endian mode
-                comb += core_opcode_i.eq(current_insn) # actual opcode
-                sync += ilatch.eq(current_insn)
-                m.next = "INSN_ACTIVE" # move to "wait for completion" phase
+                with m.If(self.imem.f_busy_o): # zzz...
+                    # busy: stay in wait-read
+                    comb += self.imem.a_valid_i.eq(1)
+                    comb += self.imem.f_valid_i.eq(1)
+                with m.Else():
+                    # not busy: instruction fetched
+                    insn = self.imem.f_instr_o.word_select(current_pc[2], 32)
+                    comb += current_insn.eq(insn)
+                    comb += core_ivalid_i.eq(1) # say instruction is valid
+                    comb += core_issue_i.eq(1)  # and issued (ivalid redundant)
+                    comb += core_be_i.eq(0)     # little-endian mode
+                    comb += core_opcode_i.eq(current_insn) # actual opcode
+                    sync += ilatch.eq(current_insn)
+                    m.next = "INSN_ACTIVE" # move to "wait for completion" phase
 
             # instruction started: must wait till it finishes
             with m.State("INSN_ACTIVE"):
index 04a7bd437455374d4f000bb9aad6e47bf904fd09..48c802ec5fb24c26362d10a70f45cd0fa36fb561 100644 (file)
@@ -67,7 +67,7 @@ class TestRunner(FHDLTestCase):
         pc_i = Signal(32)
 
         m.submodules.issuer = issuer = TestIssuer(ifacetype="test_bare_wb")
-        imem = issuer.imem.mem
+        imem = issuer.imem.mem.mem
         core = issuer.core
         pdecode2 = core.pdecode2
         l0 = core.l0