X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsoc%2Fsimple%2Fissuer.py;h=15bd1760a5ab93f233d8cb7cdff813d7b0833096;hb=HEAD;hp=671f113f4b00dc4c4dba89462ec0eac8f4e6bb99;hpb=10c1b76d5fb1329faaaa4f61089a00420138673d;p=soc.git diff --git a/src/soc/simple/issuer.py b/src/soc/simple/issuer.py index 671f113f..15bd1760 100644 --- a/src/soc/simple/issuer.py +++ b/src/soc/simple/issuer.py @@ -21,6 +21,9 @@ from nmigen.cli import rtlil from nmigen.cli import main import sys +from nmutil.singlepipe import ControlBase +from soc.simple.core_data import FetchOutput, FetchInput + from nmigen.lib.coding import PriorityEncoder from openpower.decoder.power_decoder import create_pdecode @@ -28,10 +31,10 @@ from openpower.decoder.power_decoder2 import PowerDecode2, SVP64PrefixDecoder from openpower.decoder.decode2execute1 import IssuerDecode2ToOperand from openpower.decoder.decode2execute1 import Data from openpower.decoder.power_enums import (MicrOp, SVP64PredInt, SVP64PredCR, - SVP64PredMode) + SVP64PredMode) from openpower.state import CoreState -from openpower.consts import (CR, SVP64CROffs) -from soc.experiment.testmem import TestMemory # test only for instructions +from openpower.consts import (CR, SVP64CROffs, MSR) +from soc.experiment.testmem import TestMemory # test only for instructions from soc.regfile.regfiles import StateRegs, FastRegs from soc.simple.core import NonProductionCore from soc.config.test.test_loadstore import TestMemPspec @@ -45,10 +48,11 @@ from soc.bus.SPBlock512W64B8W import SPBlock512W64B8W from soc.clock.select import ClockSelect from soc.clock.dummypll import DummyPLL from openpower.sv.svstate import SVSTATERec - +from soc.experiment.icache import ICache from nmutil.util import rising_edge + def get_insn(f_instr_o, pc): if f_instr_o.width == 32: return f_instr_o @@ -57,11 +61,12 @@ def get_insn(f_instr_o, pc): return f_instr_o.word_select(pc[2], 32) # gets state input or reads from state regfile -def state_get(m, core_rst, state_i, name, regfile, regnum): + + +def state_get(m, res, core_rst, state_i, name, regfile, regnum): comb = m.d.comb sync = m.d.sync - # read the PC - res = Signal(64, reset_less=True, name=name) + # read the {insert state variable here} res_ok_delay = Signal(name="%s_ok_delay" % name) with m.If(~core_rst): sync += res_ok_delay.eq(~state_i.ok) @@ -69,12 +74,12 @@ def state_get(m, core_rst, state_i, name, regfile, regnum): # incoming override (start from pc_i) comb += res.eq(state_i.data) with m.Else(): - # otherwise read StateRegs regfile for PC... - comb += regfile.ren.eq(1<1 loop - with m.If(~dbg.core_stop_o & ~core_rst): - comb += exec_pc_i_ready.eq(1) - # see https://bugs.libre-soc.org/show_bug.cgi?id=636 - # the exception info needs to be blatted into - # pdecode.ldst_exc, and the instruction "re-run". - # when ldst_exc.happened is set, the PowerDecoder2 - # reacts very differently: it re-writes the instruction - # with a "trap" (calls PowerDecoder2.trap()) which - # will *overwrite* whatever was requested and jump the - # PC to the exception address, as well as alter MSR. - # nothing else needs to be done other than to note - # the change of PC and MSR (and, later, SVSTATE) - with m.If(exc_happened): - sync += pdecode2.ldst_exc.eq(core.fus.get_exc("ldst0")) - - with m.If(exec_pc_o_valid): - - # was this the last loop iteration? - is_last = Signal() - cur_vl = cur_state.svstate.vl - comb += is_last.eq(next_srcstep == cur_vl) + comb += exec_pc_i_ready.eq(1) + # see https://bugs.libre-soc.org/show_bug.cgi?id=636 + # the exception info needs to be blatted into + # pdecode.ldst_exc, and the instruction "re-run". + # when ldst_exc.happened is set, the PowerDecoder2 + # reacts very differently: it re-writes the instruction + # with a "trap" (calls PowerDecoder2.trap()) which + # will *overwrite* whatever was requested and jump the + # PC to the exception address, as well as alter MSR. + # nothing else needs to be done other than to note + # the change of PC and MSR (and, later, SVSTATE) + with m.If(exc_happened): + mmu = core.fus.get_exc("mmu0") + ldst = core.fus.get_exc("ldst0") + if mmu is not None: + with m.If(fetch_failed): + # instruction fetch: exception is from MMU + # reset instr_fault (highest priority) + sync += pdecode2.ldst_exc.eq(mmu) + sync += pdecode2.instr_fault.eq(0) + if flush_needed: + # request icache to stop asserting "failed" + comb += core.icache.flush_in.eq(1) + with m.If(~fetch_failed): + # otherwise assume it was a LDST exception + sync += pdecode2.ldst_exc.eq(ldst) + + with m.If(exec_pc_o_valid): + + # was this the last loop iteration? + is_last = Signal() + cur_vl = cur_state.svstate.vl + comb += is_last.eq(next_srcstep == cur_vl) - # return directly to Decode if Execute generated an - # exception. - with m.If(pdecode2.ldst_exc.happened): - m.next = "DECODE_SV" + with m.If(pdecode2.instr_fault): + # reset instruction fault, try again + sync += pdecode2.instr_fault.eq(0) + m.next = "ISSUE_START" - # if either PC or SVSTATE were changed by the previous - # instruction, go directly back to Fetch, without - # updating either PC or SVSTATE - with m.Elif(pc_changed | sv_changed): - m.next = "ISSUE_START" + # return directly to Decode if Execute generated an + # exception. + with m.Elif(pdecode2.ldst_exc.happened): + m.next = "DECODE_SV" - # also return to Fetch, when no output was a vector - # (regardless of SRCSTEP and VL), or when the last - # instruction was really the last one of the VL loop - with m.Elif((~pdecode2.loop_continue) | is_last): - # before going back to fetch, update the PC state - # register with the NIA. - # ok here we are not reading the branch unit. - # TODO: this just blithely overwrites whatever - # pipeline updated the PC - comb += self.state_w_pc.wen.eq(1 << StateRegs.PC) - comb += self.state_w_pc.i_data.eq(nia) - # reset SRCSTEP before returning to Fetch - if self.svp64_en: - with m.If(pdecode2.loop_continue): - comb += new_svstate.srcstep.eq(0) - comb += new_svstate.dststep.eq(0) - comb += update_svstate.eq(1) - else: + # if MSR, PC or SVSTATE were changed by the previous + # instruction, go directly back to Fetch, without + # updating either MSR PC or SVSTATE + with m.Elif(self.msr_changed | self.pc_changed | + self.sv_changed): + m.next = "ISSUE_START" + + # also return to Fetch, when no output was a vector + # (regardless of SRCSTEP and VL), or when the last + # instruction was really the last one of the VL loop + with m.Elif((~pdecode2.loop_continue) | is_last): + # before going back to fetch, update the PC state + # register with the NIA. + # ok here we are not reading the branch unit. + # TODO: this just blithely overwrites whatever + # pipeline updated the PC + comb += self.state_w_pc.wen.eq(1 << StateRegs.PC) + comb += self.state_w_pc.i_data.eq(nia) + # reset SRCSTEP before returning to Fetch + if self.svp64_en: + with m.If(pdecode2.loop_continue): comb += new_svstate.srcstep.eq(0) comb += new_svstate.dststep.eq(0) - comb += update_svstate.eq(1) - m.next = "ISSUE_START" + comb += self.update_svstate.eq(1) + else: + comb += new_svstate.srcstep.eq(0) + comb += new_svstate.dststep.eq(0) + comb += self.update_svstate.eq(1) + m.next = "ISSUE_START" - # returning to Execute? then, first update SRCSTEP - with m.Else(): - comb += new_svstate.srcstep.eq(next_srcstep) - comb += new_svstate.dststep.eq(next_dststep) - comb += update_svstate.eq(1) - # return to mask skip loop - m.next = "PRED_SKIP" + # returning to Execute? then, first update SRCSTEP + with m.Else(): + comb += new_svstate.srcstep.eq(next_srcstep) + comb += new_svstate.dststep.eq(next_dststep) + comb += self.update_svstate.eq(1) + # return to mask skip loop + m.next = "PRED_SKIP" - with m.Else(): - comb += dbg.core_stopped_i.eq(1) - # while stopped, allow updating the PC and SVSTATE - with m.If(self.pc_i.ok): - comb += self.state_w_pc.wen.eq(1 << StateRegs.PC) - comb += self.state_w_pc.i_data.eq(self.pc_i.data) - sync += pc_changed.eq(1) - with m.If(self.svstate_i.ok): - comb += new_svstate.eq(self.svstate_i.data) - comb += update_svstate.eq(1) - sync += sv_changed.eq(1) # check if svstate needs updating: if so, write it to State Regfile - with m.If(update_svstate): - comb += self.state_w_sv.wen.eq(1<