From 97136d71397f420479d601dcb80f0df4abf73d22 Mon Sep 17 00:00:00 2001 From: Cesar Strauss Date: Sat, 6 Mar 2021 16:29:34 -0300 Subject: [PATCH] Begin to implement the Simple-V loop After returning from executing an instruction, decide whether to return to Fetch, or go repeat Execute again. 1) If PC or SVSTATE were updated, go directly to Fetch, without updating either 2) If there is no vector output, or it's the last VL loop iteration, go back to Fetch as well, but update the PC. In the latter case, also reset SRCSTEP 3) Otherwise, we are still in the loop, so increment SVSTEP, and go back to Execute. But, first, pass through a new state, DECODE_SV, so the new register numbers can be decoded. --- src/soc/simple/issuer.py | 59 ++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/src/soc/simple/issuer.py b/src/soc/simple/issuer.py index f1e197ea..6ba8b39d 100644 --- a/src/soc/simple/issuer.py +++ b/src/soc/simple/issuer.py @@ -310,29 +310,57 @@ class TestIssuerInternal(Elaboratable): with m.If(~dbg.core_stop_o & ~core_rst): comb += exec_pc_ready_i.eq(1) with m.If(exec_pc_valid_o): - # TODO: update SRCSTEP here (in new_svstate) - # and set update_svstate to True *as long as* - # PC / SVSTATE was not modified. that's an - # exception (or setvl was called) - # TODO: loop into INSN_EXECUTE if it's a vector - # instruction and SRCSTEP != VL-1 and - # PowerDecoder.no_out_vec is True - # unless PC / SVSTATE was modified, in that - # case do go back to INSN_FETCH. - - # before fetch, update the PC state register with - # the NIA, unless PC was modified in execute - with m.If(~pc_changed): + # precalculate srcstep+1 + next_srcstep = Signal.like(cur_state.svstate.srcstep) + comb += next_srcstep.eq(cur_state.svstate.srcstep+1) + # was this the last loop iteration? + is_last = Signal() + cur_vl = cur_state.svstate.vl + comb += is_last.eq(next_srcstep == cur_vl) + + # 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): + m.next = "INSN_FETCH" + + # 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.no_out_vec | 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.data_i.eq(nia) - m.next = "INSN_FETCH" + # reset SRCSTEP before returning to Fetch + with m.If(~pdecode2.no_out_vec): + comb += new_svstate.srcstep.eq(0) + comb += update_svstate.eq(1) + m.next = "INSN_FETCH" + + # returning to Execute? then, first update SRCSTEP + with m.Else(): + comb += new_svstate.srcstep.eq(next_srcstep) + comb += update_svstate.eq(1) + m.next = "DECODE_SV" + with m.Else(): comb += core.core_stopped_i.eq(1) comb += dbg.core_stopped_i.eq(1) + # need to decode the instruction again, after updating SRCSTEP + # in the previous state. + # mostly a copy of INSN_WAIT, but without the actual wait + with m.State("DECODE_SV"): + # decode the instruction + sync += core.e.eq(pdecode2.e) + sync += core.state.eq(cur_state) + sync += core.bigendian_i.eq(self.core_bigendian_i) + m.next = "INSN_EXECUTE" # move to "execute" + # 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<