+ # default to reading from incoming instruction: may be overridden
+ # by copy from latch when "waiting"
+ comb += self.ireg.eq(self.i)
+ # always say "ready" except if overridden
+ comb += self.p.o_ready.eq(1)
+
+ with m.FSM():
+ with m.State("READY"):
+ with m.If(self.p.i_valid): # run only when valid
+ with m.Switch(self.ireg.e.do.insn_type):
+ # check for ATTN: halt if true
+ with m.Case(MicrOp.OP_ATTN):
+ m.d.sync += self.o.core_terminate_o.eq(1)
+
+ # fake NOP - this isn't really used (Issuer detects NOP)
+ with m.Case(MicrOp.OP_NOP):
+ sync += counter.eq(2)
+ comb += busy_o.eq(1)
+
+ with m.Default():
+ comb += self.instr_active.eq(1)
+ comb += self.p.o_ready.eq(0)
+ # connect instructions. only one enabled at a time
+ for funame, fu in fus.items():
+ do = self.des[funame]
+ enable = fu_bitdict[funame]
+
+ # run this FunctionUnit if enabled route op,
+ # issue, busy, read flags and mask to FU
+ with m.If(enable):
+ # operand comes from the *local* decoder
+ # do not actually issue, though, if there
+ # 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
+ comb += self.p.o_ready.eq(1)
+
+ if self.allow_overlap:
+ with m.If(~fu_found | self.waw_hazard):
+ # latch copy of instruction
+ sync += ilatch.eq(self.i)
+ comb += self.p.o_ready.eq(1) # accept
+ comb += busy_o.eq(1)
+ m.next = "WAITING"
+
+ with m.State("WAITING"):
+ comb += self.instr_active.eq(1)
+ comb += self.p.o_ready.eq(0)
+ comb += busy_o.eq(1)
+ # using copy of instruction, keep waiting until an FU is free
+ comb += self.ireg.eq(ilatch)
+ with m.If(fu_found): # wait for conflict to clear
+ # connect instructions. only one enabled at a time