From cf8a2129f2622c99e28703a9049e697ec83b67f2 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 31 May 2019 21:37:52 +0100 Subject: [PATCH] use instruction issue queue to get instructions into engine --- src/experiment/score6600.py | 176 +++++++++++++++++++++++++++++++++--- src/scoreboard/test_iq.py | 6 +- 2 files changed, 165 insertions(+), 17 deletions(-) diff --git a/src/experiment/score6600.py b/src/experiment/score6600.py index 9724210e..4ed9acbd 100644 --- a/src/experiment/score6600.py +++ b/src/experiment/score6600.py @@ -9,14 +9,17 @@ from scoreboard.global_pending import GlobalPending from scoreboard.group_picker import GroupPicker from scoreboard.issue_unit import IssueUnitGroup, IssueUnitArray, RegDecode from scoreboard.shadow import ShadowMatrix, BranchSpeculationRecord +from scoreboard.instruction_q import Instruction, InstructionQ from compalu import ComputationUnitNoDelay from alu_hier import ALU, BranchALU from nmutil.latch import SRLatch +from nmutil.nmoperator import eq from random import randint, seed from copy import deepcopy +from math import log class CompUnitsBase(Elaboratable): @@ -292,6 +295,13 @@ class Scoreboard(Elaboratable): self.intregs = RegFileArray(rwid, n_regs) self.fpregs = RegFileArray(rwid, n_regs) + # issue q needs to get at these + self.aluissue = IssueUnitGroup(4) + self.brissue = IssueUnitGroup(1) + # and these + self.alu_oper_i = Signal(4, reset_less=True) + self.br_oper_i = Signal(4, reset_less=True) + # inputs self.int_dest_i = Signal(max=n_regs, reset_less=True) # Dest R# in self.int_src1_i = Signal(max=n_regs, reset_less=True) # oper1 R# in @@ -349,9 +359,7 @@ class Scoreboard(Elaboratable): # INT/FP Issue Unit regdecode = RegDecode(self.n_regs) m.submodules.regdecode = regdecode - aluissue = IssueUnitGroup(4) - brissue = IssueUnitGroup(1) - issueunit = IssueUnitArray([aluissue, brissue]) + issueunit = IssueUnitArray([self.aluissue, self.brissue]) m.submodules.issueunit = issueunit # Shadow Matrix. currently n_intfus shadows, to be used for @@ -385,11 +393,9 @@ class Scoreboard(Elaboratable): self.issue_o.eq(issueunit.issue_o) ] - # take these to outside (for testing) - self.aluissue = aluissue - self.brissue = brissue - self.alu_oper_i = cua.oper_i - self.br_oper_i = cub.oper_i + # take these to outside (issue needs them) + comb += cua.oper_i.eq(self.alu_oper_i) + comb += cub.oper_i.eq(self.br_oper_i) # TODO: issueunit.f (FP) @@ -536,7 +542,6 @@ class Scoreboard(Elaboratable): return m - def __iter__(self): yield from self.intregs yield from self.fpregs @@ -551,6 +556,123 @@ class Scoreboard(Elaboratable): def ports(self): return list(self) +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 + # also tell the unit-group to stop accepting the instruction + # and disable the regfile + 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) + comb += wait_issue_br.eq(0) + comb += sc.brissue.insn_i.eq(0) + comb += sc.int_dest_i.eq(0) + comb += sc.int_src1_i.eq(0) + comb += sc.int_src2_i.eq(0) + comb += sc.reg_enable_i.eq(0) + 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) + comb += wait_issue_alu.eq(0) + comb += sc.aluissue.insn_i.eq(0) + comb += sc.int_dest_i.eq(0) + comb += sc.int_src1_i.eq(0) + comb += sc.int_src2_i.eq(0) + comb += sc.reg_enable_i.eq(0) + + # 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 + 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 + + # 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(op & 0x3) + comb += wait_issue_br.eq(1) + with m.Else(): # alu + comb += sc.aluissue.insn_i.eq(1) + comb += sc.alu_oper_i.eq(op & 0x3) + 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) + IADD = 0 ISUB = 1 IMUL = 2 @@ -607,6 +729,24 @@ class RegSim: yield from self.dump(dut) assert False +def instr_q(dut, op, src1, src2, dest, branch_success, branch_fail): + instrs = [{'oper_i': op, 'dest_i': dest, 'src1_i': src1, 'src2_i': src2}] + + sendlen = 1 + for idx in range(sendlen): + yield from eq(dut.data_i[idx], instrs[idx]) + di = yield dut.data_i[idx] + print ("senddata %d %x" % (idx, di)) + yield dut.p_add_i.eq(sendlen) + yield + o_p_ready = yield dut.p_ready_o + while not o_p_ready: + yield + o_p_ready = yield dut.p_ready_o + + yield dut.p_add_i.eq(0) + + def int_instr(dut, op, src1, src2, dest, branch_success, branch_fail): yield from disable_issue(dut) yield dut.int_dest_i.eq(dest) @@ -796,9 +936,9 @@ def scoreboard_branch_sim(dut, alusim): def scoreboard_sim(dut, alusim): - seed(0) + #seed(2) - for i in range(20): + for i in range(1): # set random values in the registers for i in range(1, dut.n_regs): @@ -811,7 +951,7 @@ def scoreboard_sim(dut, alusim): # create some instructions (some random, some regression tests) instrs = [] if True: - instrs = create_random_ops(dut, 10, True, 4) + instrs = create_random_ops(dut, 15, True, 3) if False: instrs.append( (7, 3, 2, 4, (0, 0)) ) @@ -909,9 +1049,17 @@ def scoreboard_sim(dut, alusim): print ("instr %d: (%d, %d, %d, %d)" % (i, src1, src2, dest, op)) alusim.op(op, src1, src2, dest) - yield from int_instr(dut, op, src1, src2, dest, br_ok, br_fail) + yield from instr_q(dut, op, src1, src2, dest, br_ok, br_fail) # wait for all instructions to stop before checking + while True: + iqlen = yield dut.qlen_o + if iqlen == 0: + break + yield + yield + yield + yield yield yield from wait_for_busy_clear(dut) @@ -921,7 +1069,7 @@ def scoreboard_sim(dut, alusim): def test_scoreboard(): - dut = Scoreboard(16, 8) + dut = IssueToScoreboard(2, 1, 1, 16, 8, 8) alusim = RegSim(16, 8) vl = rtlil.convert(dut, ports=dut.ports()) with open("test_scoreboard6600.il", "w") as f: diff --git a/src/scoreboard/test_iq.py b/src/scoreboard/test_iq.py index 9ad5e192..06e1511e 100644 --- a/src/scoreboard/test_iq.py +++ b/src/scoreboard/test_iq.py @@ -102,9 +102,9 @@ def mk_insns(n_insns, wid, opwid): def test_iq(): wid = 8 opwid = 4 - qlen = 4 - n_in = 2 - n_out = 3 + qlen = 2 + n_in = 1 + n_out = 1 dut = InstructionQ(wid, opwid, qlen, n_in, n_out) insns = mk_insns(1000, wid, opwid) -- 2.30.2