X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fexperiment%2Fscore6600.py;h=47101d1e90f68b6ab4fa15308a53349bcf1c0ad8;hb=b7bf7a2a8d87f206cbbad676f889562c4ed4ec0f;hp=3b0b69f956ae3e7fda799f7ebb7f8ac4902d50cc;hpb=ed0aecafcaac4a6218c1ba85d1bb9d03200879be;p=soc.git diff --git a/src/experiment/score6600.py b/src/experiment/score6600.py index 3b0b69f9..47101d1e 100644 --- a/src/experiment/score6600.py +++ b/src/experiment/score6600.py @@ -3,60 +3,130 @@ from nmigen.cli import verilog, rtlil from nmigen import Module, Const, Signal, Array, Cat, Elaboratable from regfile.regfile import RegFileArray, treereduce -from scoreboard.fn_unit import IntFnUnit, FPFnUnit, LDFnUnit, STFnUnit from scoreboard.fu_fu_matrix import FUFUDepMatrix from scoreboard.fu_reg_matrix import FURegDepMatrix from scoreboard.global_pending import GlobalPending from scoreboard.group_picker import GroupPicker -from scoreboard.issue_unit import IntFPIssueUnit, RegDecode +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 +from alu_hier import ALU, BranchALU from nmutil.latch import SRLatch +from nmutil.nmoperator import eq -from random import randint +from random import randint, seed +from copy import deepcopy +from math import log -class CompUnits(Elaboratable): - def __init__(self, rwid, n_units): +class Memory(Elaboratable): + def __init__(self, regwid, addrw): + self.ddepth = regwid/8 + depth = (1<>self.ddepth] + + def st(self, addr, data): + self.mem[addr>>self.ddepth] = data & ((1<> (src2 & maxbits) + elif op == IBGT: + val = int(src1 > src2) + elif op == IBLT: + val = int(src1 < src2) + elif op == IBEQ: + val = int(src1 == src2) + elif op == IBNE: + val = int(src1 != src2) + val &= maxbits + self.setval(dest, val) + return val def setval(self, dest, val): + print ("sim setval", dest, hex(val)) self.regs[dest] = val def dump(self, dut): @@ -356,15 +746,47 @@ class RegSim: yield from self.dump(dut) assert False -def int_instr(dut, alusim, op, src1, src2, dest): - for i in range(len(dut.int_insn_i)): - yield dut.int_insn_i[i].eq(0) +def instr_q(dut, op, op_imm, src1, src2, dest, branch_success, branch_fail): + instrs = [{'oper_i': op, 'dest_i': dest, 'opim_i': op_imm, + '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) yield dut.int_src1_i.eq(src1) yield dut.int_src2_i.eq(src2) - yield dut.int_insn_i[op].eq(1) + if (op & (0x3<<2)) != 0: # branch + yield dut.brissue.insn_i.eq(1) + yield dut.br_oper_i.eq(Const(op & 0x3, 2)) + dut_issue = dut.brissue + else: + yield dut.aluissue.insn_i.eq(1) + yield dut.alu_oper_i.eq(Const(op & 0x3, 2)) + dut_issue = dut.aluissue yield dut.reg_enable_i.eq(1) - alusim.op(op, src1, src2, dest) + + # these indicate that the instruction is to be made shadow-dependent on + # (either) branch success or branch fail + yield dut.branch_fail_i.eq(branch_fail) + yield dut.branch_succ_i.eq(branch_success) + + yield + yield from wait_for_issue(dut, dut_issue) def print_reg(dut, rnums): @@ -376,106 +798,300 @@ def print_reg(dut, rnums): print ("reg %s: %s" % (','.join(rnums), ','.join(rs))) -def scoreboard_sim(dut, alusim): - yield dut.int_store_i.eq(0) +def create_random_ops(dut, n_ops, shadowing=False, max_opnums=3): + insts = [] + for i in range(n_ops): + src1 = randint(1, dut.n_regs-1) + src2 = randint(1, dut.n_regs-1) + dest = randint(1, dut.n_regs-1) + op = randint(0, max_opnums) + opi = 0 if randint(0, 3) else 1 # set true if random is nonzero + + if shadowing: + insts.append((src1, src2, dest, op, opi, (0, 0))) + else: + insts.append((src1, src2, dest, op, opi)) + return insts + + +def wait_for_busy_clear(dut): + while True: + busy_o = yield dut.busy_o + if not busy_o: + break + print ("busy",) + yield - for i in range(1, dut.n_regs): - yield dut.intregs.regs[i].reg.eq(4+i*2) - alusim.setval(i, 4+i*2) +def disable_issue(dut): + yield dut.aluissue.insn_i.eq(0) + yield dut.brissue.insn_i.eq(0) - instrs = [] - if True: - for i in range(200): - src1 = randint(1, dut.n_regs-1) - src2 = randint(1, dut.n_regs-1) - while True: - dest = randint(1, dut.n_regs-1) - if dest not in [src1, src2]: - break - #src1 = 2 - #src2 = 3 - #dest = 2 - - op = randint(0, 2) - #op = i % 2 - #op = 0 - - instrs.append((src1, src2, dest, op)) - - if False: - instrs.append((2, 3, 3, 0)) - instrs.append((5, 3, 3, 1)) - - if False: - instrs.append((5, 6, 2, 1)) - instrs.append((2, 2, 4, 0)) - #instrs.append((2, 2, 3, 1)) - - if False: - instrs.append((2, 1, 2, 3)) - - if False: - instrs.append((2, 6, 2, 1)) - instrs.append((2, 1, 2, 0)) - - if False: - instrs.append((1, 2, 7, 2)) - instrs.append((7, 1, 5, 0)) - instrs.append((4, 4, 1, 1)) - - if False: - instrs.append((5, 6, 2, 2)) - instrs.append((1, 1, 4, 1)) - instrs.append((6, 5, 3, 0)) - - for i, (src1, src2, dest, op) in enumerate(instrs): - - print ("instr %d: %d %d %d %d\n" % (i, op, src1, src2, dest)) - yield from int_instr(dut, alusim, op, src1, src2, dest) + +def wait_for_issue(dut, dut_issue): + while True: + issue_o = yield dut_issue.fn_issue_o + if issue_o: + yield from disable_issue(dut) + yield dut.reg_enable_i.eq(0) + break + print ("busy",) + #yield from print_reg(dut, [1,2,3]) yield - while True: - issue_o = yield dut.issue_o - if issue_o: - for i in range(len(dut.int_insn_i)): - yield dut.int_insn_i[i].eq(0) - yield dut.reg_enable_i.eq(0) - break - print ("busy",) - yield from print_reg(dut, [1,2,3]) - yield - yield from print_reg(dut, [1,2,3]) + #yield from print_reg(dut, [1,2,3]) - yield - yield from print_reg(dut, [1,2,3]) - yield - yield from print_reg(dut, [1,2,3]) - yield - yield from print_reg(dut, [1,2,3]) - yield - yield from print_reg(dut, [1,2,3]) - yield - yield - yield - yield - yield from alusim.check(dut) - yield from alusim.dump(dut) +def scoreboard_branch_sim(dut, alusim): + iseed = 3 -def explore_groups(dut): - from nmigen.hdl.ir import Fragment - from nmigen.hdl.xfrm import LHSGroupAnalyzer + for i in range(1): - fragment = dut.elaborate(platform=None) - fr = Fragment.get(fragment, platform=None) + print ("rseed", iseed) + seed(iseed) + iseed += 1 - groups = LHSGroupAnalyzer()(fragment._statements) + yield dut.branch_direction_o.eq(0) - print (groups) + # set random values in the registers + for i in range(1, dut.n_regs): + val = 31+i*3 + val = randint(0, (1<= 4 + if is_branch: + branch_ok, branch_fail = dest + dest = src2 + # ok zip up the branch success / fail instructions and + # drop them into the queue, one marked "to have branch success" + # the other to be marked shadow branch "fail". + # one out of each of these will be cancelled + for ok, fl in zip(branch_ok, branch_fail): + if ok: + instrs.append((ok[0], ok[1], ok[2], ok[3], (1, 0))) + if fl: + instrs.append((fl[0], fl[1], fl[2], fl[3], (0, 1))) + print ("instr %d: (%d, %d, %d, %d, (%d, %d))" % \ + (i, src1, src2, dest, op, shadow_on, shadow_off)) + yield from int_instr(dut, op, src1, src2, dest, + shadow_on, shadow_off) + + # wait for all instructions to stop before checking + yield + yield from wait_for_busy_clear(dut) + + i = -1 + while siminsts: + instr = siminsts.pop(0) + if instr is None: + continue + (src1, src2, dest, op, (shadow_on, shadow_off)) = instr + i += 1 + is_branch = op >= 4 + if is_branch: + branch_ok, branch_fail = dest + dest = src2 + print ("sim %d: (%d, %d, %d, %d, (%d, %d))" % \ + (i, src1, src2, dest, op, shadow_on, shadow_off)) + branch_res = alusim.op(op, src1, src2, dest) + if is_branch: + if branch_res: + siminsts += branch_ok + else: + siminsts += branch_fail + + # check status + yield from alusim.check(dut) + yield from alusim.dump(dut) + + +def scoreboard_sim(dut, alusim): + + #seed(2) + + for i in range(1): + + # set random values in the registers + for i in range(1, dut.n_regs): + val = randint(0, (1<