From 754e561f30404c87521229379a4b84a884948887 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sun, 21 Feb 2021 15:41:08 +0000 Subject: [PATCH] move fetch_fsm to separate function in TestIssuer --- src/soc/simple/issuer.py | 187 ++++++++++++++++------------- src/soc/simple/test/test_issuer.py | 12 +- 2 files changed, 108 insertions(+), 91 deletions(-) diff --git a/src/soc/simple/issuer.py b/src/soc/simple/issuer.py index cb6a3bfe..53368bce 100644 --- a/src/soc/simple/issuer.py +++ b/src/soc/simple/issuer.py @@ -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" diff --git a/src/soc/simple/test/test_issuer.py b/src/soc/simple/test/test_issuer.py index 79c9619e..ebe93b4b 100644 --- a/src/soc/simple/test/test_issuer.py +++ b/src/soc/simple/test/test_issuer.py @@ -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)) -- 2.30.2