X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsoc%2Fsimple%2Fissuer.py;h=6aa790191c38a96d01d608a817d09417c50b6bdb;hb=ed1504b692c40bed445a48fbb58fdde32dea4da6;hp=dad804d4e2fbd7471821805690d999c54f9726a9;hpb=1467f945051d5b967d1232fec7ee5539f8675870;p=soc.git diff --git a/src/soc/simple/issuer.py b/src/soc/simple/issuer.py index dad804d4..6aa79019 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 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 @@ -49,6 +52,7 @@ from openpower.sv.svstate import SVSTATERec from nmutil.util import rising_edge + def get_insn(f_instr_o, pc): if f_instr_o.width == 32: return f_instr_o @@ -57,6 +61,8 @@ 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): comb = m.d.comb sync = m.d.sync @@ -70,12 +76,13 @@ def state_get(m, core_rst, state_i, name, regfile, regnum): comb += res.eq(state_i.data) with m.Else(): # otherwise read StateRegs regfile for PC... - comb += regfile.ren.eq(1< 0: # at least one exception - comb += exc_happened.eq(Cat(*el).bool()) + exc_happened = self.core.o.exc_happened + # also note instruction fetch failed + if hasattr(core, "icache"): + fetch_failed = core.icache.i_out.fetch_failed + else: + fetch_failed = Const(0, 1) + # set to zero initially + sync += pdecode2.instr_fault.eq(0) with m.FSM(name="issue_fsm"): @@ -620,7 +710,7 @@ class TestIssuerInternal(Elaboratable): # wait on "core stop" release, before next fetch # need to do this here, in case we are in a VL==0 loop with m.If(~dbg.core_stop_o & ~core_rst): - comb += fetch_pc_i_valid.eq(1) # tell fetch to start + comb += fetch_pc_i_valid.eq(1) # tell fetch to start with m.If(fetch_pc_o_ready): # fetch acknowledged us m.next = "INSN_WAIT" with m.Else(): @@ -638,25 +728,33 @@ class TestIssuerInternal(Elaboratable): # wait for an instruction to arrive from Fetch with m.State("INSN_WAIT"): - comb += fetch_insn_i_ready.eq(1) - with m.If(fetch_insn_o_valid): - # loop into ISSUE_START if it's a SVP64 instruction - # and VL == 0. this because VL==0 is a for-loop - # from 0 to 0 i.e. always, always a NOP. - cur_vl = cur_state.svstate.vl - with m.If(is_svp64_mode & (cur_vl == 0)): - # update the PC before fetching the next instruction - # since we are in a VL==0 loop, no instruction was - # executed that we could be overwriting - comb += self.state_w_pc.wen.eq(1 << StateRegs.PC) - comb += self.state_w_pc.i_data.eq(nia) - comb += self.insn_done.eq(1) - m.next = "ISSUE_START" - with m.Else(): - if self.svp64_en: - m.next = "PRED_START" # start fetching predicate - else: - m.next = "DECODE_SV" # skip predication + if self.allow_overlap: + stopping = dbg.stopping_o + else: + stopping = Const(0) + with m.If(stopping): + # stopping: jump back to idle + m.next = "ISSUE_START" + with m.Else(): + comb += fetch_insn_i_ready.eq(1) + with m.If(fetch_insn_o_valid): + # loop into ISSUE_START if it's a SVP64 instruction + # and VL == 0. this because VL==0 is a for-loop + # from 0 to 0 i.e. always, always a NOP. + cur_vl = cur_state.svstate.vl + with m.If(is_svp64_mode & (cur_vl == 0)): + # update the PC before fetching the next instruction + # since we are in a VL==0 loop, no instruction was + # executed that we could be overwriting + comb += self.state_w_pc.wen.eq(1 << StateRegs.PC) + comb += self.state_w_pc.i_data.eq(nia) + comb += self.insn_done.eq(1) + m.next = "ISSUE_START" + with m.Else(): + if self.svp64_en: + m.next = "PRED_START" # fetching predicate + else: + m.next = "DECODE_SV" # skip predication with m.State("PRED_START"): comb += pred_insn_i_valid.eq(1) # tell fetch_pred to start @@ -664,8 +762,8 @@ class TestIssuerInternal(Elaboratable): m.next = "MASK_WAIT" with m.State("MASK_WAIT"): - comb += pred_mask_i_ready.eq(1) # ready to receive the masks - with m.If(pred_mask_o_valid): # predication masks are ready + comb += pred_mask_i_ready.eq(1) # ready to receive the masks + with m.If(pred_mask_o_valid): # predication masks are ready m.next = "PRED_SKIP" # skip zeros in predicate @@ -733,32 +831,38 @@ class TestIssuerInternal(Elaboratable): # pass predicate mask bits through to satellite decoders # TODO: for SIMD this will be *multiple* bits - sync += core.sv_pred_sm.eq(self.srcmask[0]) - sync += core.sv_pred_dm.eq(self.dstmask[0]) + sync += core.i.sv_pred_sm.eq(self.srcmask[0]) + sync += core.i.sv_pred_dm.eq(self.dstmask[0]) # after src/dst step have been updated, we are ready # to decode the instruction with m.State("DECODE_SV"): # decode the instruction - sync += core.e.eq(pdecode2.e) - 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 += core.i.e.eq(pdecode2.e) + sync += core.i.state.eq(cur_state) + sync += core.i.raw_insn_i.eq(dec_opcode_i) + sync += core.i.bigendian_i.eq(self.core_bigendian_i) if self.svp64_en: - sync += core.sv_rm.eq(pdecode2.sv_rm) + sync += core.i.sv_rm.eq(pdecode2.sv_rm) # set RA_OR_ZERO detection in satellite decoders - sync += core.sv_a_nz.eq(pdecode2.sv_a_nz) + sync += core.i.sv_a_nz.eq(pdecode2.sv_a_nz) # and svp64 detection - sync += core.is_svp64_mode.eq(is_svp64_mode) + sync += core.i.is_svp64_mode.eq(is_svp64_mode) # and svp64 bit-rev'd ldst mode ldst_dec = pdecode2.use_svp64_ldst_dec - sync += core.use_svp64_ldst_dec.eq(ldst_dec) + sync += core.i.use_svp64_ldst_dec.eq(ldst_dec) + # after decoding, reset any previous exception condition, + # allowing it to be set again during the next execution + sync += pdecode2.ldst_exc.eq(0) + + # update (highest priority) instruction fault + sync += pdecode2.instr_fault.eq(fetch_failed) m.next = "INSN_EXECUTE" # move to "execute" # handshake with execution FSM, move to "wait" once acknowledged with m.State("INSN_EXECUTE"): - comb += exec_insn_i_valid.eq(1) # trigger execute + comb += exec_insn_i_valid.eq(1) # trigger execute with m.If(exec_insn_o_ready): # execute acknowledged us m.next = "EXECUTE_WAIT" @@ -768,11 +872,8 @@ class TestIssuerInternal(Elaboratable): 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 - #with m.If(exec_pc_o_valid & exc_happened): - # probably something like this: - # sync += pdecode2.ldst_exc.eq(core.fus.get_exc("ldst0") - # TODO: the exception info needs to be blatted - # into pdecode.ldst_exc, and the instruction "re-run". + # 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 @@ -780,18 +881,25 @@ class TestIssuerInternal(Elaboratable): # 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.Elif(exec_pc_o_valid): - with m.If(exec_pc_o_valid): # replace with Elif (above) + 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) + # return directly to Decode if Execute generated an + # exception. + with m.If(pdecode2.ldst_exc.happened): + m.next = "DECODE_SV" + # if either PC or SVSTATE were changed by the previous # instruction, go directly back to Fetch, without # updating either PC or SVSTATE - with m.If(pc_changed | sv_changed): + with m.Elif(pc_changed | sv_changed): m.next = "ISSUE_START" # also return to Fetch, when no output was a vector @@ -839,9 +947,9 @@ class TestIssuerInternal(Elaboratable): # 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<