From: Luke Kenneth Casson Leighton Date: Sun, 12 Dec 2021 18:56:13 +0000 (+0000) Subject: starting to hack in fetch failed (including OP_FETCH_FAILED) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=efb661852d1f46548a46a88d271b13d95c869957;p=soc.git starting to hack in fetch failed (including OP_FETCH_FAILED) going really badly as far as code-readability and clean design is concerned but is progressing a truly dreadful hack: OP_TRAP works (LDST Exceptions) because the main decoder (PowerDecoder2) is used by core for the Trap pipeline. unnnnfortunately... for MMU, a *Satellite* decoder (PowerDecodeSubset) is used. and Satellite decoders *only* understand *instructions*. (which they part-decode locally). therefore a manual override of the satellite decoder insn_type and fn_unit is required when OP_FETCH_FAILED occurs. truly awful. --- diff --git a/src/soc/simple/core.py b/src/soc/simple/core.py index 6bca3bd8..bc2d0fbf 100644 --- a/src/soc/simple/core.py +++ b/src/soc/simple/core.py @@ -198,6 +198,7 @@ class NonProductionCore(ControlBase): svp64_en=self.svp64_en, regreduce_en=self.regreduce_en) self.des[funame] = self.decoders[funame].do + print ("create decoder subset", funame, opkls, self.des[funame]) # create per-Function Unit write-after-write hazard signals # yes, really, this should have been added in ReservationStations @@ -422,6 +423,20 @@ class NonProductionCore(ControlBase): # is a waw hazard. decoder has to still # be asserted in order to detect that, tho comb += fu.oper_i.eq_from(do) + if funame == 'mmu0': + # URRR this is truly dreadful. + # OP_FETCH_FAILED is a "fake" op. + # no instruction creates it. OP_TRAP + # uses the *main* decoder: this is + # a *Satellite* decoder that reacts + # on *insn_in*... not fake ops. gaah. + main_op = self.ireg.e.do + with m.If(main_op.insn_type == + MicrOp.OP_FETCH_FAILED): + comb += fu.oper_i.insn_type.eq( + MicrOp.OP_FETCH_FAILED) + comb += fu.oper_i.fn_unit.eq( + Function.MMU) # issue when valid (and no write-hazard) comb += fu.issue_i.eq(~self.waw_hazard) # instruction ok, indicate ready diff --git a/src/soc/simple/issuer.py b/src/soc/simple/issuer.py index 16646338..48cc6b7e 100644 --- a/src/soc/simple/issuer.py +++ b/src/soc/simple/issuer.py @@ -206,7 +206,7 @@ class FetchFSM(ControlBase): m = super().elaborate(platform) dbg = self.dbg - core = self.core, + core = self.core pc = self.i.pc svstate = self.svstate nia = self.nia @@ -224,6 +224,12 @@ class FetchFSM(ControlBase): msr_read = Signal(reset=1) + # also note instruction fetch failed + if hasattr(core, "icache"): + fetch_failed = core.icache.i_out.fetch_failed + else: + fetch_failed = Const(0, 1) + # don't read msr every cycle staterf = self.core.regs.rf['state'] state_r_msr = staterf.r_ports['msr'] # MSR rd @@ -234,9 +240,9 @@ class FetchFSM(ControlBase): # waiting (zzz) with m.State("IDLE"): - with m.If(~dbg.stopping_o): + with m.If(~dbg.stopping_o & ~fetch_failed): comb += fetch_pc_o_ready.eq(1) - with m.If(fetch_pc_i_valid): + with m.If(fetch_pc_i_valid & ~fetch_failed): # 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 @@ -267,13 +273,15 @@ class FetchFSM(ControlBase): with m.If(~msr_read): sync += msr_read.eq(1) # yeah don't read it again sync += cur_state.msr.eq(state_r_msr.o_data) - with m.If(self.imem.f_busy_o): # zzz... - # busy: stay in wait-read + with m.If(self.imem.f_busy_o & ~fetch_failed): # zzz... + # busy but not fetch failed: stay in wait-read comb += self.imem.a_i_valid.eq(1) comb += self.imem.f_i_valid.eq(1) with m.Else(): - # not busy: instruction fetched - insn = get_insn(self.imem.f_instr_o, cur_state.pc) + # not busy (or fetch failed!): instruction fetched + # when fetch failed, the instruction gets ignored + # by the decoder + insn = ~get_insn(self.imem.f_instr_o, cur_state.pc) if self.svp64_en: svp64 = self.svp64 # decode the SVP64 prefix, if any