From 75d1afe8b4278d317b2f61bf455d6fefca8eb823 Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Fri, 18 Feb 2022 13:22:02 +0000 Subject: [PATCH] Only push to RAS when the linking instruction is non-speculative. That is, don't push in Decode, push from the training structure coming from Execute, which is delayed until the instruction that issued it is non-speculative. --- src_Core/CPU/Core.bsv | 2 +- .../procs/RV64G_OOO/AluExePipeline.bsv | 18 +++++---- .../RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv | 37 ++++--------------- src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 8 ++++ src_Core/RISCY_OOO/procs/lib/Ras.bsv | 33 +++++++++-------- 5 files changed, 45 insertions(+), 53 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 6992529..31cb51e 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -465,7 +465,7 @@ module mkCore#(CoreId coreId)(Core); let train = trainBPQ[i].first.data; trainBPQ[i].deq; fetchStage.train_predictors( - train.pc, train.nextPc, train.iType, train.taken, + train.pc, train.nextPc, train.iType, train.taken, train.link, train.trainInfo, train.mispred, train.isCompressed ); endrule diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv index 177cc42..474761a 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv @@ -104,6 +104,7 @@ typedef struct { Maybe#(PhyDst) dst; InstTag tag; PredTrainInfo trainInfo; + Bool link; Bool isCompressed; // result CapPipe data; // alu compute result @@ -151,6 +152,7 @@ endmodule typedef struct { CapMem pc; CapMem nextPc; + Bool link; IType iType; Bool taken; PredTrainInfo trainInfo; @@ -364,15 +366,12 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); // execution ExecResult exec_result = basicExec(x.dInst, x.rVal1, x.rVal2, cast(x.pc), cast(x.ppc), x.orig_inst); + Bool link = (case (x.dInst.iType) + J, CJAL, CJALR, Jr: isValid(x.dst); + default: False; + endcase); `ifdef RAS_HIT_TRACING - function Bool linkedR(Bit#(5) r); - Bool res = False; - if ((r == 1 || r == 5)) begin - res = True; - end - return res; - endfunction - if (linkedR(x.orig_inst[19:15]) && (x.orig_inst[19:15] != x.orig_inst[11:7])) begin + if (link) begin case (x.dInst.iType) Jr, CJALR: $display("Jr/CJALR ra: PC: %x Mispredict: %x , %x vs %x src1: %d", getAddr(x.pc), exec_result.controlFlow.mispredict, getAddr(exec_result.controlFlow.nextPc), getAddr(x.ppc), x.orig_inst[19:15]); endcase @@ -416,6 +415,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); dst: x.dst, tag: x.tag, trainInfo: x.trainInfo, + link: link, isCompressed: x.orig_inst[1:0] != 2'b11, data: exec_result.data, csrData: is_scr_or_csr ? CSRData (exec_result.csrData) : PPC (cast(exec_result.controlFlow.nextPc)), @@ -493,6 +493,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); data: FetchTrainBP { pc: cast(x.controlFlow.pc), nextPc: cast(x.controlFlow.nextPc), + link: x.link, iType: x.iType, taken: x.controlFlow.taken, trainInfo: x.trainInfo, @@ -526,6 +527,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); data: FetchTrainBP { pc: cast(x.controlFlow.pc), nextPc: cast(x.controlFlow.nextPc), + link: x.link, iType: x.iType, taken: x.controlFlow.taken, trainInfo: x.trainInfo, diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index 4ca1d16..956fcc2 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -145,7 +145,7 @@ interface FetchStage; `endif method Action done_flushing(); method Action train_predictors( - CapMem pc, CapMem next_pc, IType iType, Bool taken, + CapMem pc, CapMem next_pc, IType iType, Bool taken, Bool link, PredTrainInfo trainInfo, Bool mispred, Bool isCompressed ); interface SpeculationUpdate specUpdate; @@ -728,51 +728,29 @@ module mkFetchStage(FetchStage); // direction predict Maybe#(CapMem) nextPc = dir_ppc; // return address stack link reg is x1 or x5 - function Bool linkedR(Maybe#(ArchRIndx) register); - Bool res = False; - if (register matches tagged Valid .r &&& (r == tagged Gpr 1 || r == tagged Gpr 5)) begin - res = True; - end - return res; - endfunction Bool dst_link = linkedR(regs.dst); Bool src1_link = linkedR(regs.src1); - CapMem push_addr = addPc(pc, ((in.inst_kind == Inst_32b) ? 4 : 2)); - Maybe#(CapMem) m_push_addr = Invalid; CapMem pop_addr = ras.ras[i].first; - Bool pop = False; - if ((dInst.iType == J || dInst.iType == CJAL) && dst_link) begin - // rs1 is invalid, i.e., not link: push - m_push_addr = Valid (push_addr); - end - else if (dInst.iType == Jr || dInst.iType == CJALR) begin // jalr TODO CCALL could be push + Bool doPop = False; + if (dInst.iType == Jr || dInst.iType == CJALR) begin // jalr TODO CCALL could be push // pop or nop (if to trampoline) // Add hint to architecture? if (!dst_link && src1_link) begin // rd is link while rs1 is not: pop - pop = True; + doPop = True; nextPc = Valid (pop_addr); end - else if (!src1_link && dst_link) begin - // rs1 is not link while rd is link: push - m_push_addr = Valid (push_addr); - end else if (dst_link && src1_link) begin // both rd and rs1 are links if (regs.src1 != regs.dst) begin // not same reg: first pop, then push nextPc = Valid (pop_addr); - pop = True; - m_push_addr = Valid (push_addr); - end - else begin - // same reg: push - m_push_addr = Valid (push_addr); + doPop = True; end end end - trainInfo.ras <- ras.ras[i].popPush(pop, m_push_addr); + trainInfo.ras <- ras.ras[i].pop(doPop); if(verbose) begin $display("Branch prediction: ", fshow(dInst.iType), " ; ", fshow(pc), " ; ", fshow(ppc), " ; ", fshow(nextPc)); @@ -967,7 +945,7 @@ module mkFetchStage(FetchStage); endmethod method Action train_predictors( - CapMem pc, CapMem next_pc, IType iType, Bool taken, + CapMem pc, CapMem next_pc, IType iType, Bool taken, Bool link, PredTrainInfo trainInfo, Bool mispred, Bool isCompressed ); //if (iType == J || iType == CJAL || (iType == Br && next_pc < pc)) begin @@ -975,6 +953,7 @@ module mkFetchStage(FetchStage); // // next_pc != pc + 4 is a substitute for taken // nextAddrPred.update(pc, next_pc, taken); //end + if (link) ras.push(addPc(pc, isCompressed ? 2 : 4)); if (iType == Br) begin // Train the direction predictor for all branches dirPred.update(taken, trainInfo.dir, mispred); diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index 9840277..77c5300 100644 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -664,6 +664,14 @@ typedef struct { Maybe#(ImmData) imm; } DecodedInst deriving(Bits, Eq, FShow); +function Bool linkedR(Maybe#(ArchRIndx) register); + Bool res = False; + if (register matches tagged Valid .r &&& (r == tagged Gpr 1 || r == tagged Gpr 5)) begin + res = True; + end + return res; +endfunction + function Maybe#(Data) getDInstImm(DecodedInst dInst); return dInst.imm matches tagged Valid .d ? Valid (signExtend(d)) : Invalid; endfunction diff --git a/src_Core/RISCY_OOO/procs/lib/Ras.bsv b/src_Core/RISCY_OOO/procs/lib/Ras.bsv index 9a7ecf4..8d07a92 100644 --- a/src_Core/RISCY_OOO/procs/lib/Ras.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Ras.bsv @@ -45,8 +45,7 @@ import CHERICap::*; interface RAS; method CapMem first; - // first pop, then push - method ActionValue#(RasIndex) popPush(Bool pop, Maybe#(CapMem) pushAddr); + method ActionValue#(RasIndex) pop(Bool doPop); endinterface // Local RAS Typedefs SHOULD BE A POWER OF TWO. @@ -56,6 +55,7 @@ typedef RasIndex RasPredTrainInfo; interface ReturnAddrStack; interface Vector#(SupSize, RAS) ras; + method Action push(CapMem pushAddr); method Action setHead(RasIndex h); method Action flush; method Bool flush_done; @@ -63,16 +63,16 @@ endinterface (* synthesize *) module mkRas(ReturnAddrStack) provisos(NumAlias#(TExp#(TLog#(RasEntries)), RasEntries)); - Vector#(RasEntries, Ehr#(TAdd#(SupSize, 1), CapMem)) stack <- replicateM(mkEhr(nullCap)); + Vector#(RasEntries, Ehr#(2, CapMem)) stack <- replicateM(mkEhr(nullCap)); // head points past valid data // to gracefully overflow, head is allowed to overflow to 0 and overwrite the oldest data - Ehr#(TAdd#(SupSize, 2), RasIndex) head <- mkEhr(0); + Ehr#(TAdd#(SupSize, 3), RasIndex) head <- mkEhr(0); `ifdef SECURITY Reg#(Bool) flushDone <- mkReg(True); rule doFlush(!flushDone); - writeVReg(getVEhrPort(stack, valueof(SupSize)), replicate(0)); + writeVReg(getVEhrPort(stack, 0), replicate(0)); head[valueof(SupSize) + 1] <= 0; flushDone <= True; endrule @@ -82,26 +82,29 @@ module mkRas(ReturnAddrStack) provisos(NumAlias#(TExp#(TLog#(RasEntries)), RasEn for(Integer i = 0; i < valueof(SupSize); i = i+1) begin rasIfc[i] = (interface RAS; method CapMem first; - return stack[head[i]][i]; + return stack[head[i]][0]; endmethod - method ActionValue#(RasIndex) popPush(Bool pop, Maybe#(CapMem) pushAddr); - // first pop, then push + method ActionValue#(RasIndex) pop(Bool doPop); RasIndex h = head[i]; - if(pop) begin - h = h - 1; + if (doPop) begin + head[i] <= head[i] - 1; + $display("RAS pop head<-%d, val:%x", head[i] - 1, stack[head[i]][0]); end - if(pushAddr matches tagged Valid .addr) begin - h = h + 1; - stack[h][i] <= addr; - end - head[i] <= h; return h; endmethod endinterface); end + method Action push(CapMem pushAddr); + Reg#(RasIndex) h = head[valueof(SupSize) + 2]; + stack[h+1][1] <= pushAddr; + $display("RAS push head<-%d, val:%x", h+1, pushAddr); + h <= h+1; + endmethod + method Action setHead(RasIndex h); head[valueof(SupSize)] <= h; + $display("RAS fixup head<-%d", h); endmethod interface ras = rasIfc;