starting to hack in fetch failed (including OP_FETCH_FAILED)
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 12 Dec 2021 18:56:13 +0000 (18:56 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 12 Dec 2021 18:56:13 +0000 (18:56 +0000)
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.

src/soc/simple/core.py
src/soc/simple/issuer.py

index 6bca3bd8b02215bb0f61c8468cc8297582d0a699..bc2d0fbfdfcf3c650e232fdad3b0c09b100017e5 100644 (file)
@@ -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
index 16646338187409489788f800bf3cadc2f95ffadc..48cc6b7e3bfa988717f20df230f3dbf5df0f2114 100644 (file)
@@ -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