X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fexperiment%2Fscore6600.py;h=47101d1e90f68b6ab4fa15308a53349bcf1c0ad8;hb=b7bf7a2a8d87f206cbbad676f889562c4ed4ec0f;hp=dc067472efe207062ba824ded95ddd790b7300f3;hpb=d888bf3415f6aca6aa31148445065dc89f0c5ce2;p=soc.git diff --git a/src/experiment/score6600.py b/src/experiment/score6600.py index dc067472..47101d1e 100644 --- a/src/experiment/score6600.py +++ b/src/experiment/score6600.py @@ -3,63 +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.shadow import ShadowMatrix +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.regs[dest] = val + 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): @@ -374,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): @@ -394,12 +798,59 @@ def print_reg(dut, rnums): print ("reg %s: %s" % (','.join(rnums), ','.join(rs))) -def scoreboard_sim(dut, alusim): +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 + +def disable_issue(dut): + yield dut.aluissue.insn_i.eq(0) + yield dut.brissue.insn_i.eq(0) + - yield dut.int_store_i.eq(0) +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 + #yield from print_reg(dut, [1,2,3]) + +def scoreboard_branch_sim(dut, alusim): + + iseed = 3 for i in range(1): + print ("rseed", iseed) + seed(iseed) + iseed += 1 + + yield dut.branch_direction_o.eq(0) + # set random values in the registers for i in range(1, dut.n_regs): val = 31+i*3 @@ -407,30 +858,132 @@ def scoreboard_sim(dut, alusim): yield dut.intregs.regs[i].reg.eq(val) alusim.setval(i, val) + if False: + # create some instructions: branches create a tree + insts = create_random_ops(dut, 1, True, 1) + #insts.append((6, 6, 1, 2, (0, 0))) + #insts.append((4, 3, 3, 0, (0, 0))) + + src1 = randint(1, dut.n_regs-1) + src2 = randint(1, dut.n_regs-1) + #op = randint(4, 7) + op = 4 # only BGT at the moment + + branch_ok = create_random_ops(dut, 1, True, 1) + branch_fail = create_random_ops(dut, 1, True, 1) + + insts.append((src1, src2, (branch_ok, branch_fail), op, (0, 0))) + + if True: + insts = [] + insts.append( (3, 5, 2, 0, (0, 0)) ) + branch_ok = [] + branch_fail = [] + #branch_ok.append ( (5, 7, 5, 1, (1, 0)) ) + branch_ok.append( None ) + branch_fail.append( (1, 1, 2, 0, (0, 1)) ) + #branch_fail.append( None ) + insts.append( (6, 4, (branch_ok, branch_fail), 4, (0, 0)) ) + + siminsts = deepcopy(insts) + + # issue instruction(s) + i = -1 + instrs = insts + branch_direction = 0 + while instrs: + yield + yield + i += 1 + branch_direction = yield dut.branch_direction_o # way branch went + (src1, src2, dest, op, (shadow_on, shadow_off)) = insts.pop(0) + if branch_direction == 1 and shadow_on: + print ("skip", i, src1, src2, dest, op, shadow_on, shadow_off) + continue # branch was "success" and this is a "failed"... skip + if branch_direction == 2 and shadow_off: + print ("skip", i, src1, src2, dest, op, shadow_on, shadow_off) + continue # branch was "fail" and this is a "success"... skip + if branch_direction != 0: + shadow_on = 0 + shadow_off = 0 + is_branch = op >= 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<