move fetch_fsm to separate function in TestIssuer
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 21 Feb 2021 15:41:08 +0000 (15:41 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 21 Feb 2021 15:41:08 +0000 (15:41 +0000)
src/soc/simple/issuer.py
src/soc/simple/test/test_issuer.py

index cb6a3bfe09e8ed3863ed28bfa93bad8c3fc0c18c..53368bce0a2db4d6b6eff28234cde9b3e3eb5ca6 100644 (file)
@@ -146,6 +146,102 @@ class TestIssuerInternal(Elaboratable):
         self.state_nia = self.core.regs.rf['state'].w_ports['nia']
         self.state_nia.wen.name = 'state_nia_wen'
 
+    def fetch_fsm(self, m, core, dbg, pc, nia,
+                        core_rst, cur_state,
+                        fetch_pc_ready_o, fetch_pc_valid_i,
+                        fetch_insn_valid_o, fetch_insn_ready_i,
+                        msr_read, sv_read,
+                        fetch_insn_o):
+        """fetch FSM
+        this FSM performs fetch of raw instruction data, partial-decodes
+        it 32-bit at a time to detect SVP64 prefixes, and will optionally
+        read a 2nd 32-bit quantity if that occurs.
+        """
+        comb = m.d.comb
+        sync = m.d.sync
+        pdecode2 = self.pdecode2
+        svp64 = self.svp64
+
+        with m.FSM(name='fetch_fsm'):
+
+            # waiting (zzz)
+            with m.State("IDLE"):
+                with m.If(~dbg.core_stop_o & ~core_rst):
+                    comb += fetch_pc_ready_o.eq(1)
+                    with m.If(fetch_pc_valid_i):
+                        # instruction allowed to go: start by reading the PC
+                        # 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.imem.a_pc_i.eq(pc)
+                        comb += self.imem.a_valid_i.eq(1)
+                        comb += self.imem.f_valid_i.eq(1)
+                        sync += cur_state.pc.eq(pc)
+
+                        # initiate read of MSR/SVSTATE. arrives one clock later
+                        comb += self.state_r_msr.ren.eq(1 << StateRegs.MSR)
+                        comb += self.state_r_sv.ren.eq(1 << StateRegs.SVSTATE)
+                        sync += msr_read.eq(0)
+                        sync += sv_read.eq(0)
+
+                        m.next = "INSN_READ"  # move to "wait for bus" phase
+                with m.Else():
+                    comb += core.core_stopped_i.eq(1)
+                    comb += dbg.core_stopped_i.eq(1)
+
+            # dummy pause to find out why simulation is not keeping up
+            with m.State("INSN_READ"):
+                # one cycle later, msr/sv read arrives.  valid only once.
+                with m.If(~msr_read):
+                    sync += msr_read.eq(1) # yeah don't read it again
+                    sync += cur_state.msr.eq(self.state_r_msr.data_o)
+                with m.If(~sv_read):
+                    sync += sv_read.eq(1) # yeah don't read it again
+                    sync += cur_state.svstate.eq(self.state_r_sv.data_o)
+                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 = get_insn(self.imem.f_instr_o, cur_state.pc)
+                    # decode the SVP64 prefix, if any
+                    comb += svp64.raw_opcode_in.eq(insn)
+                    comb += svp64.bigendian.eq(self.core_bigendian_i)
+                    # pass the decoded prefix (if any) to PowerDecoder2
+                    sync += pdecode2.sv_rm.eq(svp64.svp64_rm)
+                    # calculate the address of the following instruction
+                    insn_size = Mux(svp64.is_svp64_mode, 8, 4)
+                    sync += nia.eq(cur_state.pc + insn_size)
+                    with m.If(~svp64.is_svp64_mode):
+                        # with no prefix, store the instruction
+                        # and hand it directly to the next FSM
+                        sync += fetch_insn_o.eq(insn)
+                        m.next = "INSN_READY"
+                    with m.Else():
+                        # fetch the rest of the instruction from memory
+                        comb += self.imem.a_pc_i.eq(cur_state.pc + 4)
+                        comb += self.imem.a_valid_i.eq(1)
+                        comb += self.imem.f_valid_i.eq(1)
+                        m.next = "INSN_READ2"
+
+            with m.State("INSN_READ2"):
+                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 = get_insn(self.imem.f_instr_o, cur_state.pc+4)
+                    sync += fetch_insn_o.eq(insn)
+                    m.next = "INSN_READY"
+
+            with m.State("INSN_READY"):
+                # hand over the instruction, to be decoded
+                comb += fetch_insn_valid_o.eq(1)
+                with m.If(fetch_insn_ready_i):
+                    m.next = "IDLE"
+
     def elaborate(self, platform):
         m = Module()
         comb, sync = m.d.comb, m.d.sync
@@ -224,7 +320,6 @@ class TestIssuerInternal(Elaboratable):
         # PC and instruction from I-Memory
         pc_changed = Signal() # note write to PC
         comb += self.pc_o.eq(cur_state.pc)
-        ilatch = Signal(32)
 
         # address of the next instruction, in the absence of a branch
         # depends on the instruction size
@@ -287,89 +382,12 @@ class TestIssuerInternal(Elaboratable):
         # (as opposed to using sync - which would be on a clock's delay)
         # this includes the actual opcode, valid flags and so on.
 
-        # this FSM performs fetch of raw instruction data, partial-decodes
-        # it 32-bit at a time to detect SVP64 prefixes, and will optionally
-        # read a 2nd 32-bit quantity if that occurs.
-
-        with m.FSM(name='fetch_fsm'):
-
-            # waiting (zzz)
-            with m.State("IDLE"):
-                with m.If(~dbg.core_stop_o & ~core_rst):
-                    comb += fetch_pc_ready_o.eq(1)
-                    with m.If(fetch_pc_valid_i):
-                        # instruction allowed to go: start by reading the PC
-                        # 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.imem.a_pc_i.eq(pc)
-                        comb += self.imem.a_valid_i.eq(1)
-                        comb += self.imem.f_valid_i.eq(1)
-                        sync += cur_state.pc.eq(pc)
-
-                        # initiate read of MSR/SVSTATE. arrives one clock later
-                        comb += self.state_r_msr.ren.eq(1 << StateRegs.MSR)
-                        comb += self.state_r_sv.ren.eq(1 << StateRegs.SVSTATE)
-                        sync += msr_read.eq(0)
-                        sync += sv_read.eq(0)
-
-                        m.next = "INSN_READ"  # move to "wait for bus" phase
-                with m.Else():
-                    comb += core.core_stopped_i.eq(1)
-                    comb += dbg.core_stopped_i.eq(1)
-
-            # dummy pause to find out why simulation is not keeping up
-            with m.State("INSN_READ"):
-                # one cycle later, msr/sv read arrives.  valid only once.
-                with m.If(~msr_read):
-                    sync += msr_read.eq(1) # yeah don't read it again
-                    sync += cur_state.msr.eq(self.state_r_msr.data_o)
-                with m.If(~sv_read):
-                    sync += sv_read.eq(1) # yeah don't read it again
-                    sync += cur_state.svstate.eq(self.state_r_sv.data_o)
-                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 = get_insn(self.imem.f_instr_o, cur_state.pc)
-                    # decode the SVP64 prefix, if any
-                    comb += svp64.raw_opcode_in.eq(insn)
-                    comb += svp64.bigendian.eq(self.core_bigendian_i)
-                    # pass the decoded prefix (if any) to PowerDecoder2
-                    sync += pdecode2.sv_rm.eq(svp64.svp64_rm)
-                    # calculate the address of the following instruction
-                    insn_size = Mux(svp64.is_svp64_mode, 8, 4)
-                    sync += nia.eq(cur_state.pc + insn_size)
-                    with m.If(~svp64.is_svp64_mode):
-                        # with no prefix, store the instruction
-                        # and hand it directly to the next FSM
-                        sync += fetch_insn_o.eq(insn)
-                        m.next = "INSN_READY"
-                    with m.Else():
-                        # fetch the rest of the instruction from memory
-                        comb += self.imem.a_pc_i.eq(cur_state.pc + 4)
-                        comb += self.imem.a_valid_i.eq(1)
-                        comb += self.imem.f_valid_i.eq(1)
-                        m.next = "INSN_READ2"
-
-            with m.State("INSN_READ2"):
-                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 = get_insn(self.imem.f_instr_o, cur_state.pc+4)
-                    sync += fetch_insn_o.eq(insn)
-                    m.next = "INSN_READY"
-
-            with m.State("INSN_READY"):
-                # hand over the instruction, to be decoded
-                comb += fetch_insn_valid_o.eq(1)
-                with m.If(fetch_insn_ready_i):
-                    m.next = "IDLE"
+        self.fetch_fsm(m, core, dbg, pc, nia,
+                       core_rst, cur_state,
+                       fetch_pc_ready_o, fetch_pc_valid_i,
+                       fetch_insn_valid_o, fetch_insn_ready_i,
+                       msr_read, sv_read,
+                       fetch_insn_o)
 
         # decode / issue / execute FSM.  this interacts with the "fetch" FSM
         # through fetch_pc_ready/valid (incoming) and fetch_insn_ready/valid
@@ -396,7 +414,6 @@ class TestIssuerInternal(Elaboratable):
                     sync += core.state.eq(cur_state)
                     sync += core.raw_insn_i.eq(dec_opcode_i)
                     sync += core.bigendian_i.eq(self.core_bigendian_i)
-                    sync += ilatch.eq(insn) # latch current insn
                     # also drop PC and MSR into decode "state"
                     m.next = "INSN_START" # move to "start"
 
index 79c9619e9e15d91e48dc12297f96ff66528d9b6f..ebe93b4b960d8b101c89497cb44705983c29a5fc 100644 (file)
@@ -28,14 +28,14 @@ if __name__ == "__main__":
     unittest.main(exit=False)
     suite = unittest.TestSuite()
     # suite.addTest(TestRunner(HelloTestCases.test_data))
-    #suite.addTest(TestRunner(DivTestCases().test_data))
+    suite.addTest(TestRunner(DivTestCases().test_data))
     # suite.addTest(TestRunner(AttnTestCase.test_data))
-    #suite.addTest(TestRunner(GeneralTestCases.test_data))
-    #suite.addTest(TestRunner(LDSTTestCase().test_data))
-    #suite.addTest(TestRunner(CRTestCase().test_data))
-    #suite.addTest(TestRunner(ShiftRotTestCase().test_data))
+    suite.addTest(TestRunner(GeneralTestCases.test_data))
+    suite.addTest(TestRunner(LDSTTestCase().test_data))
+    suite.addTest(TestRunner(CRTestCase().test_data))
+    suite.addTest(TestRunner(ShiftRotTestCase().test_data))
     suite.addTest(TestRunner(LogicalTestCase().test_data))
-    #suite.addTest(TestRunner(ALUTestCase().test_data))
+    suite.addTest(TestRunner(ALUTestCase().test_data))
     # suite.addTest(TestRunner(BranchTestCase.test_data))
     # suite.addTest(TestRunner(SPRTestCase.test_data))