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:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user