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.
This commit is contained in:
Jonathan Woodruff
2022-02-18 13:22:02 +00:00
parent 2b9ebb5b40
commit 75d1afe8b4
5 changed files with 45 additions and 53 deletions

View File

@@ -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

View File

@@ -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,

View File

@@ -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);

View File

@@ -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

View File

@@ -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;