+
+class IssueToScoreboard(Elaboratable):
+
+ def __init__(self, qlen, n_in, n_out, rwid, opwid, n_regs):
+ self.qlen = qlen
+ self.n_in = n_in
+ self.n_out = n_out
+ self.rwid = rwid
+ self.opw = opwid
+ self.n_regs = n_regs
+
+ mqbits = (int(log(qlen) / log(2))+2, False)
+ self.p_add_i = Signal(mqbits) # instructions to add (from data_i)
+ self.p_ready_o = Signal() # instructions were added
+ self.data_i = Instruction.nq(n_in, "data_i", rwid, opwid)
+
+ self.busy_o = Signal(reset_less=True) # at least one CU is busy
+ self.qlen_o = Signal(mqbits, reset_less=True)
+
+ def elaborate(self, platform):
+ m = Module()
+ comb = m.d.comb
+ sync = m.d.sync
+
+ iq = InstructionQ(self.rwid, self.opw, self.qlen, self.n_in, self.n_out)
+ sc = Scoreboard(self.rwid, self.n_regs)
+ m.submodules.iq = iq
+ m.submodules.sc = sc
+
+ # get at the regfile for testing
+ self.intregs = sc.intregs
+
+ # and the "busy" signal and instruction queue length
+ comb += self.busy_o.eq(sc.busy_o)
+ comb += self.qlen_o.eq(iq.qlen_o)
+
+ # link up instruction queue
+ comb += iq.p_add_i.eq(self.p_add_i)
+ comb += self.p_ready_o.eq(iq.p_ready_o)
+ for i in range(self.n_in):
+ comb += eq(iq.data_i[i], self.data_i[i])
+
+ # take instruction and process it. note that it's possible to
+ # "inspect" the queue contents *without* actually removing the
+ # items. items are only removed when the
+
+ # in "waiting" state
+ wait_issue_br = Signal()
+ wait_issue_alu = Signal()
+
+ with m.If(wait_issue_br | wait_issue_alu):
+ # set instruction pop length to 1 if the unit accepted
+ with m.If(wait_issue_br & (sc.brissue.fn_issue_o != 0)):
+ with m.If(iq.qlen_o != 0):
+ comb += iq.n_sub_i.eq(1)
+ with m.If(wait_issue_alu & (sc.aluissue.fn_issue_o != 0)):
+ with m.If(iq.qlen_o != 0):
+ comb += iq.n_sub_i.eq(1)
+
+ # see if some instruction(s) are here. note that this is
+ # "inspecting" the in-place queue. note also that on the
+ # cycle following "waiting" for fn_issue_o to be set, the
+ # "resetting" done above (insn_i=0) could be re-ASSERTed.
+ with m.If(iq.qlen_o != 0):
+ # get the operands and operation
+ imm = iq.data_o[0].imm_i
+ dest = iq.data_o[0].dest_i
+ src1 = iq.data_o[0].src1_i
+ src2 = iq.data_o[0].src2_i
+ op = iq.data_o[0].oper_i
+ opi = iq.data_o[0].opim_i # immediate set
+
+ # set the src/dest regs
+ comb += sc.int_dest_i.eq(dest)
+ comb += sc.int_src1_i.eq(src1)
+ comb += sc.int_src2_i.eq(src2)
+ comb += sc.reg_enable_i.eq(1) # enable the regfile
+
+ # choose a Function-Unit-Group
+ with m.If((op & (0x3<<2)) != 0): # branch
+ comb += sc.brissue.insn_i.eq(1)
+ comb += sc.br_oper_i.eq(Cat(op[0:2], opi))
+ comb += sc.br_imm_i.eq(imm)
+ comb += wait_issue_br.eq(1)
+ with m.Else(): # alu
+ comb += sc.aluissue.insn_i.eq(1)
+ comb += sc.alu_oper_i.eq(Cat(op[0:2], opi))
+ comb += sc.alu_imm_i.eq(imm)
+ comb += wait_issue_alu.eq(1)
+
+ # XXX TODO
+ # these indicate that the instruction is to be made
+ # shadow-dependent on
+ # (either) branch success or branch fail
+ #yield sc.branch_fail_i.eq(branch_fail)
+ #yield sc.branch_succ_i.eq(branch_success)
+
+ return m
+
+ def __iter__(self):
+ yield self.p_ready_o
+ for o in self.data_i:
+ yield from list(o)
+ yield self.p_add_i
+
+ def ports(self):
+ return list(self)
+
+