X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fexperiment%2Fscore6600.py;h=ed953e8b71a3b80ff82fde4c93a115d8fcd39303;hb=9160489ce48a008af3e07fdc81d458a0b366f997;hp=4ed9acbd1aa215b05a61046979426ad7bd32bdb8;hpb=cf8a2129f2622c99e28703a9049e697ec83b67f2;p=soc.git diff --git a/src/experiment/score6600.py b/src/experiment/score6600.py index 4ed9acbd..ed953e8b 100644 --- a/src/experiment/score6600.py +++ b/src/experiment/score6600.py @@ -1,6 +1,6 @@ from nmigen.compat.sim import run_simulation from nmigen.cli import verilog, rtlil -from nmigen import Module, Const, Signal, Array, Cat, Elaboratable +from nmigen import Module, Const, Signal, Array, Cat, Elaboratable, Memory from regfile.regfile import RegFileArray, treereduce from scoreboard.fu_fu_matrix import FUFUDepMatrix @@ -10,8 +10,10 @@ 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 scoreboard.memfu import MemFunctionUnits from compalu import ComputationUnitNoDelay +from compldst import LDSTCompUnit from alu_hier import ALU, BranchALU from nmutil.latch import SRLatch @@ -22,6 +24,44 @@ from copy import deepcopy from math import log +class TestMemory(Elaboratable): + def __init__(self, regwid, addrw): + self.ddepth = 1 # regwid //8 + depth = (1<>self.ddepth] + + def st(self, addr, data): + self.mem[addr>>self.ddepth] = data & ((1< Mem FUs + comb += memfus.addr_we_i.eq(cul.adr_rel_o) # Match enable on adr rel + + comb += memfus.addrs_i[0].eq(cul.units[0].data_o) + comb += memfus.addrs_i[1].eq(cul.units[1].data_o) + + #comb += cu.go_rd_i[0:n_intfus].eq(go_rd_o[0:n_intfus]) + #comb += cu.go_wr_i[0:n_intfus].eq(go_wr_o[0:n_intfus]) + #comb += cu.issue_i[0:n_intfus].eq(fn_issue_o[0:n_intfus]) + #--------- # merge shadow matrices outputs #--------- @@ -470,10 +606,6 @@ class Scoreboard(Elaboratable): for i in range(n_intfus): comb += shadows.s_good_i[i][0:n_intfus].eq(go_wr_o[0:n_intfus]) - # work out the current-activated busy unit (by recording the old one) - with m.If(fn_issue_o): # only update prev bit if instruction issued - sync += fn_issue_prev.eq(fn_issue_o) - # *previous* instruction shadows *current* instruction, and, obviously, # if the previous is completed (!busy) don't cast the shadow! comb += prev_shadow.eq(~fn_issue_o & cu.busy_o) @@ -505,9 +637,9 @@ class Scoreboard(Elaboratable): with m.If(br1.issue_i): sync += bspec.active_i.eq(1) with m.If(self.branch_succ_i): - comb += bspec.good_i.eq(fn_issue_o & 0x1f) + comb += bspec.good_i.eq(fn_issue_o & 0x1f) # XXX MAGIC CONSTANT with m.If(self.branch_fail_i): - comb += bspec.fail_i.eq(fn_issue_o & 0x1f) + comb += bspec.fail_i.eq(fn_issue_o & 0x1f) # XXX MAGIC CONSTANT # branch is active (TODO: a better signal: this is over-using the # go_write signal - actually the branch should not be "writing") @@ -556,6 +688,7 @@ class Scoreboard(Elaboratable): def ports(self): return list(self) + class IssueToScoreboard(Elaboratable): def __init__(self, qlen, n_in, n_out, rwid, opwid, n_regs): @@ -581,8 +714,10 @@ class IssueToScoreboard(Elaboratable): iq = InstructionQ(self.rwid, self.opw, self.qlen, self.n_in, self.n_out) sc = Scoreboard(self.rwid, self.n_regs) + mem = TestMemory(self.rwid, 8) # not too big, takes too long m.submodules.iq = iq m.submodules.sc = sc + m.submodules.mem = mem # get at the regfile for testing self.intregs = sc.intregs @@ -604,29 +739,19 @@ class IssueToScoreboard(Elaboratable): # in "waiting" state wait_issue_br = Signal() wait_issue_alu = Signal() + wait_issue_ls = Signal() - with m.If(wait_issue_br | wait_issue_alu): + with m.If(wait_issue_br | wait_issue_alu | wait_issue_ls): # 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_ls & (sc.lsissue.fn_issue_o != 0)): + with m.If(iq.qlen_o != 0): + comb += iq.n_sub_i.eq(1) 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 @@ -634,10 +759,12 @@ class IssueToScoreboard(Elaboratable): # "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) @@ -647,12 +774,24 @@ class IssueToScoreboard(Elaboratable): # choose a Function-Unit-Group with m.If((op & (0x3<<2)) != 0): # branch + comb += sc.br_oper_i.eq(Cat(op[0:2], opi)) + comb += sc.br_imm_i.eq(imm) 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 + with m.Elif((op & (0x3<<4)) != 0): # ld/st + # see compldst.py + # bit 0: ADD/SUB + # bit 1: immed + # bit 4: LD + # bit 5: ST + comb += sc.ls_oper_i.eq(Cat(op[0], opi[0], op[4:6])) + comb += sc.ls_imm_i.eq(imm) + comb += sc.lsissue.insn_i.eq(1) + comb += wait_issue_ls.eq(1) + with m.Else(): # alu + comb += sc.alu_oper_i.eq(Cat(op[0:2], opi)) + comb += sc.alu_imm_i.eq(imm) comb += sc.aluissue.insn_i.eq(1) - comb += sc.alu_oper_i.eq(op & 0x3) comb += wait_issue_alu.eq(1) # XXX TODO @@ -673,6 +812,7 @@ class IssueToScoreboard(Elaboratable): def ports(self): return list(self) + IADD = 0 ISUB = 1 IMUL = 2 @@ -682,15 +822,19 @@ IBLT = 5 IBEQ = 6 IBNE = 7 + class RegSim: def __init__(self, rwidth, nregs): self.rwidth = rwidth self.regs = [0] * nregs - def op(self, op, src1, src2, dest): + def op(self, op, op_imm, imm, src1, src2, dest): maxbits = (1 << self.rwidth) - 1 src1 = self.regs[src1] & maxbits - src2 = self.regs[src2] & maxbits + if op_imm: + src2 = imm + else: + src2 = self.regs[src2] & maxbits if op == IADD: val = src1 + src2 elif op == ISUB: @@ -707,6 +851,8 @@ class RegSim: val = int(src1 == src2) elif op == IBNE: val = int(src1 != src2) + else: + return 0 # LD/ST TODO val &= maxbits self.setval(dest, val) return val @@ -729,8 +875,10 @@ 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}] +def instr_q(dut, op, op_imm, imm, src1, src2, dest, + branch_success, branch_fail): + instrs = [{'oper_i': op, 'dest_i': dest, 'imm_i': imm, 'opim_i': op_imm, + 'src1_i': src1, 'src2_i': src2}] sendlen = 1 for idx in range(sendlen): @@ -747,7 +895,7 @@ def instr_q(dut, op, src1, src2, dest, branch_success, branch_fail): yield dut.p_add_i.eq(0) -def int_instr(dut, op, src1, src2, dest, branch_success, branch_fail): +def int_instr(dut, op, imm, src1, src2, dest, branch_success, branch_fail): yield from disable_issue(dut) yield dut.int_dest_i.eq(dest) yield dut.int_src1_i.eq(src1) @@ -755,10 +903,12 @@ def int_instr(dut, op, src1, src2, dest, branch_success, branch_fail): if (op & (0x3<<2)) != 0: # branch yield dut.brissue.insn_i.eq(1) yield dut.br_oper_i.eq(Const(op & 0x3, 2)) + yield dut.br_imm_i.eq(imm) dut_issue = dut.brissue else: yield dut.aluissue.insn_i.eq(1) yield dut.alu_oper_i.eq(Const(op & 0x3, 2)) + yield dut.alu_imm_i.eq(imm) dut_issue = dut.aluissue yield dut.reg_enable_i.eq(1) @@ -785,13 +935,15 @@ def create_random_ops(dut, n_ops, shadowing=False, max_opnums=3): for i in range(n_ops): src1 = randint(1, dut.n_regs-1) src2 = randint(1, dut.n_regs-1) + imm = randint(1, (1<