move instruction decoder out of core
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 14 Aug 2020 14:26:10 +0000 (15:26 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 14 Aug 2020 14:26:10 +0000 (15:26 +0100)
src/soc/decoder/power_decoder2.py
src/soc/simple/core.py
src/soc/simple/issuer.py
src/soc/simple/test/test_core.py
src/soc/simple/test/test_issuer.py

index 97f2b530ed449d22364308aa200ec17ea95e55f3..838cb121197db57bffe58e28ab02c50e5a1d57fb 100644 (file)
@@ -578,7 +578,6 @@ class PowerDecode2(Elaboratable):
 
         self.dec = dec
         self.e = Decode2ToExecute1Type()
-        self.valid = Signal()  # sync signal
 
         # state information needed by the Decoder (TODO: this as a Record)
         self.state = CoreState("dec2")
index 477eb78a98a9b2e278d3635424bd722e195178a6..19f076ba96906b075e77c58b92917321704561c8 100644 (file)
@@ -30,8 +30,8 @@ from nmutil.util import treereduce
 
 from soc.fu.compunits.compunits import AllFunctionUnits
 from soc.regfile.regfiles import RegFiles
-from soc.decoder.power_decoder import create_pdecode
-from soc.decoder.power_decoder2 import PowerDecode2, get_rdflags
+from soc.decoder.decode2execute1 import Decode2ToExecute1Type
+from soc.decoder.power_decoder2 import get_rdflags
 from soc.decoder.decode2execute1 import Data
 from soc.experiment.l0_cache import TstL0CacheBuffer  # test only
 from soc.config.test.test_loadstore import TestMemPspec
@@ -76,18 +76,13 @@ class NonProductionCore(Elaboratable):
         self.regs = RegFiles()
 
         # instruction decoder
-        pdecode = create_pdecode()
-        self.pdecode2 = PowerDecode2(pdecode)   # instruction decoder
+        self.e = Decode2ToExecute1Type() # decoded instruction
 
         # issue/valid/busy signalling
-        self.ivalid_i = self.pdecode2.valid   # instruction is valid
+        self.ivalid_i = Signal(reset_less=True) # instruction is valid
         self.issue_i = Signal(reset_less=True)
         self.busy_o = Signal(name="corebusy_o", reset_less=True)
 
-        # instruction input
-        self.bigendian_i = self.pdecode2.dec.bigendian
-        self.raw_opcode_i = self.pdecode2.dec.raw_opcode_in
-
         # start/stop and terminated signalling
         self.core_stopped_i = Signal(reset_less=True)
         self.core_reset_i = Signal()
@@ -96,7 +91,6 @@ class NonProductionCore(Elaboratable):
     def elaborate(self, platform):
         m = Module()
 
-        m.submodules.pdecode2 = dec2 = self.pdecode2
         m.submodules.fus = self.fus
         m.submodules.l0 = l0 = self.l0
         self.regs.elaborate_into(m, platform)
@@ -127,8 +121,7 @@ class NonProductionCore(Elaboratable):
         """
         comb, sync = m.d.comb, m.d.sync
         fus = self.fus.fus
-        dec2 = self.pdecode2
-        e = dec2.e # to execute
+        e = self.e # to execute
 
         # enable-signals for each FU, get one bit for each FU (by name)
         fu_enable = Signal(len(fus), reset_less=True)
@@ -142,7 +135,7 @@ class NonProductionCore(Elaboratable):
         for funame, fu in fus.items():
             fnunit = fu.fnunit.value
             enable = Signal(name="en_%s" % funame, reset_less=True)
-            comb += enable.eq((dec2.e.do.fn_unit & fnunit).bool())
+            comb += enable.eq((e.do.fn_unit & fnunit).bool())
             comb += fu_bitdict[funame].eq(enable)
 
         # sigh - need a NOP counter
@@ -152,7 +145,7 @@ class NonProductionCore(Elaboratable):
             comb += self.busy_o.eq(1)
 
         with m.If(self.ivalid_i): # run only when valid
-            with m.Switch(dec2.e.do.insn_type):
+            with m.Switch(e.do.insn_type):
                 # check for ATTN: halt if true
                 with m.Case(MicrOp.OP_ATTN):
                     m.d.sync += self.core_terminate_o.eq(1)
@@ -169,7 +162,7 @@ class NonProductionCore(Elaboratable):
                         # run this FunctionUnit if enabled
                         with m.If(enable):
                             # route op, issue, busy, read flags and mask to FU
-                            comb += fu.oper_i.eq_from_execute1(dec2.e)
+                            comb += fu.oper_i.eq_from_execute1(e)
                             comb += fu.issue_i.eq(self.issue_i)
                             comb += self.busy_o.eq(fu.busy_o)
                             rdmask = get_rdflags(e, fu)
@@ -427,10 +420,9 @@ class NonProductionCore(Elaboratable):
     def get_byregfiles(self, readmode):
 
         mode = "read" if readmode else "write"
-        dec2 = self.pdecode2
         regs = self.regs
         fus = self.fus.fus
-        e = dec2.e # decoded instruction to execute
+        e = self.e # decoded instruction to execute
 
         # dictionary of lists of regfile ports
         byregfiles = {}
@@ -479,7 +471,7 @@ class NonProductionCore(Elaboratable):
 
     def __iter__(self):
         yield from self.fus.ports()
-        yield from self.pdecode2.ports()
+        yield from self.e.ports()
         yield from self.l0.ports()
         # TODO: regs
 
index ae6ec356b8f43c94156970a4665d6b4795eed8f6..485d7e0007d0750967bbcfe015268c6d32861f77 100644 (file)
@@ -21,6 +21,8 @@ from nmigen.cli import rtlil
 from nmigen.cli import main
 import sys
 
+from soc.decoder.power_decoder import create_pdecode
+from soc.decoder.power_decoder2 import PowerDecode2
 from soc.decoder.decode2execute1 import Data
 from soc.experiment.testmem import TestMemory # test only for instructions
 from soc.regfile.regfiles import StateRegs
@@ -43,6 +45,10 @@ class TestIssuer(Elaboratable):
         # main instruction core
         self.core = core = NonProductionCore(pspec)
 
+        # instruction decoder
+        pdecode = create_pdecode()
+        self. pdecode2 = PowerDecode2(pdecode)   # decoder
+
         # Test Instruction memory
         self.imem = ConfigFetchUnit(pspec).fu
         # one-row cache of instruction read
@@ -80,6 +86,10 @@ class TestIssuer(Elaboratable):
         m.submodules.imem = imem = self.imem
         m.submodules.dbg = dbg = self.dbg
 
+        # instruction decoder
+        pdecode = create_pdecode()
+        m.submodules.dec2 = pdecode2 = self.pdecode2
+
         # convenience
         dmi = dbg.dmi
         d_reg = dbg.dbg_gpr
@@ -101,7 +111,7 @@ class TestIssuer(Elaboratable):
 
         # busy/halted signals from core
         comb += self.busy_o.eq(core.busy_o)
-        comb += core.bigendian_i.eq(self.core_bigendian_i)
+        comb += pdecode2.dec.bigendian.eq(self.core_bigendian_i)
 
         # current state (MSR/PC at the moment
         cur_state = CoreState("cur")
@@ -147,15 +157,18 @@ class TestIssuer(Elaboratable):
         comb += dbg.state.pc.eq(pc)
         comb += dbg.state.msr.eq(cur_state.msr)
 
+        # temporarily connect up core execute decode to pdecode2
+        comb += core.e.eq(pdecode2.e)
+
         # temporaries
-        core_busy_o = core.busy_o         # core is busy
-        core_ivalid_i = core.ivalid_i     # instruction is valid
-        core_issue_i = core.issue_i       # instruction is issued
-        core_be_i = core.bigendian_i      # bigendian mode
-        core_opcode_i = core.raw_opcode_i # raw opcode
-
-        insn_type = core.pdecode2.e.do.insn_type
-        insn_state = core.pdecode2.state
+        core_busy_o = core.busy_o                  # core is busy
+        core_ivalid_i = core.ivalid_i              # instruction is valid
+        core_issue_i = core.issue_i                # instruction is issued
+        core_be_i = pdecode2.dec.bigendian         # bigendian mode
+        core_opcode_i = pdecode2.dec.raw_opcode_in # raw opcode
+
+        insn_type = pdecode2.e.do.insn_type
+        insn_state = pdecode2.state
 
         # actually use a nmigen FSM for the first time (w00t)
         # this FSM is perhaps unusual in that it detects conditions
index 21ffa2e8a0a0e269749f7cf756a96e807b03bd10..af7487926cfbbf7c887d2e626479b737a4d15a12 100644 (file)
@@ -34,7 +34,7 @@ from soc.fu.ldst.test.test_pipe_caller import LDSTTestCase
 from soc.regfile.util import spr_to_fast_reg
 
 
-def setup_regs(core, test):
+def setup_regs(pdecode2, core, test):
 
     # set up INT regfile, "direct" write (bypass rd/write ports)
     intregs = core.regs.int
@@ -112,7 +112,6 @@ def setup_regs(core, test):
     yield Settle()
 
     # XER
-    pdecode2 = core.pdecode2
     so = yield xregs.regs[xregs.SO].reg
     ov = yield xregs.regs[xregs.OV].reg
     ca = yield xregs.regs[xregs.CA].reg
index f25b61ce75788681cc19d6071070f99ebc22bf5a..4a34ff17d5fb6a4fbdd4c63f45c3a286ae6bb5d8 100644 (file)
@@ -144,7 +144,7 @@ class TestRunner(FHDLTestCase):
         imem = issuer.imem._get_memory()
         core = issuer.core
         dmi = issuer.dbg.dmi
-        pdecode2 = core.pdecode2
+        pdecode2 = issuer.pdecode2
         l0 = core.l0
 
         # copy of the decoder for simulator
@@ -202,7 +202,7 @@ class TestRunner(FHDLTestCase):
 
                 yield from setup_i_memory(imem, pc, instructions)
                 yield from setup_test_memory(l0, sim)
-                yield from setup_regs(core, test)
+                yield from setup_regs(pdecode2, core, test)
 
                 yield pc_i.eq(pc)
                 yield issuer.pc_i.ok.eq(1)