+ exception = exc.happened
+ mmureq = Signal()
+
+ # copy of address, but gets over-ridden for OP_FETCH_FAILED
+ maddr = Signal(64)
+ m.d.comb += maddr.eq(self.addr)
+
+ # create a blip (single pulse) on valid read/write request
+ # this can be over-ridden in the FSM to get dcache to re-run
+ # a request when MMU_LOOKUP completes.
+ m.d.comb += self.d_validblip.eq(rising_edge(m, self.d_valid))
+ ldst_r = LDSTRequest("ldst_r")
+
+ comb += Display("MMUTEST: LoadStore1 d_in.error=%i",d_in.error)
+
+ # fsm skeleton
+ with m.Switch(self.state):
+ with m.Case(State.IDLE):
+ with m.If(self.d_validblip & ~exc.happened):
+ comb += self.busy.eq(1)
+ sync += self.state.eq(State.ACK_WAIT)
+ sync += ldst_r.eq(self.req) # copy of LDSTRequest on "blip"
+# sync += Display("validblip self.req.virt_mode=%i",
+# self.req.virt_mode)
+ with m.Else():
+ sync += ldst_r.eq(0)
+
+ # waiting for completion
+ with m.Case(State.ACK_WAIT):
+ comb += Display("MMUTEST: ACK_WAIT")
+ comb += self.busy.eq(~exc.happened)
+
+ with m.If(d_in.error):
+ # cache error is not necessarily "final", it could
+ # be that it was just a TLB miss
+ with m.If(d_in.cache_paradox):
+ comb += exception.eq(1)
+ sync += self.state.eq(State.IDLE)
+ sync += ldst_r.eq(0)
+ sync += Display("cache error -> update dsisr")
+ sync += self.dsisr[63 - 38].eq(~self.load)
+ # XXX there is no architected bit for this
+ # (probably should be a machine check in fact)
+ sync += self.dsisr[63 - 35].eq(d_in.cache_paradox)
+
+ with m.Else():
+ # Look up the translation for TLB miss
+ # and also for permission error and RC error
+ # in case the PTE has been updated.
+ comb += mmureq.eq(1)
+ sync += self.state.eq(State.MMU_LOOKUP)
+ with m.If(d_in.valid):
+ m.d.comb += self.done.eq(~mmureq) # done if not doing MMU
+ with m.If(self.done):
+ sync += Display("ACK_WAIT, done %x", self.addr)
+ sync += self.state.eq(State.IDLE)
+ sync += ldst_r.eq(0)
+ with m.If(self.load):
+ m.d.comb += self.load_data.eq(d_in.data)
+
+ # waiting here for the MMU TLB lookup to complete.
+ # either re-try the dcache lookup or throw MMU exception
+ with m.Case(State.MMU_LOOKUP):
+ comb += Display("MMUTEST: MMU_LOOKUP")
+ comb += self.busy.eq(1)
+ with m.If(m_in.done):
+ with m.If(~self.instr_fault):
+ sync += Display("MMU_LOOKUP, done %x -> %x",
+ self.addr, d_out.addr)
+ # retry the request now that the MMU has
+ # installed a TLB entry, if not exception raised
+ m.d.comb += self.d_out.valid.eq(~exception)
+ sync += self.state.eq(State.ACK_WAIT)
+ sync += ldst_r.eq(0)
+ with m.Else():
+ sync += Display("MMU_LOOKUP, exception %x", self.addr)
+ # instruction lookup fault: store address in DAR
+ comb += exc.happened.eq(1) # reason = MMU_LOOKUP
+ # mark dar as updated ?
+ sync += self.pi.dar_o.eq(self.addr)
+
+ with m.If(m_in.err):
+ # MMU RADIX exception thrown
+ comb += exception.eq(1)
+ sync += Display("MMU RADIX exception thrown")
+ sync += self.dsisr[63 - 33].eq(m_in.invalid)
+ sync += self.dsisr[63 - 36].eq(m_in.perm_error)
+ sync += self.dsisr[63 - 38].eq(self.load)
+ sync += self.dsisr[63 - 44].eq(m_in.badtree)
+ sync += self.dsisr[63 - 45].eq(m_in.rc_error)
+
+ with m.Case(State.TLBIE_WAIT):
+ pass
+
+ # alignment error: store address in DAR
+ with m.If(self.align_intr):
+ comb += exc.happened.eq(1) # reason = alignment
+ sync += Display("alignment error: store addr in DAR %x", self.addr)
+ sync += self.pi.dar_o.eq(self.addr)
+ # TODO report reason