Perform a number of decode and prediction operations unconditionally on

the vector of instructions outside of the decode loop to improve timing.
Specifically, the branch direction prediction is lifted out and depends
only on whether there is agreement between direction prediction and a
branch being predicted by fetch, not on the actual predicted next PC.
This appears to keep the global history clean enough to
perform on-par with the old design in CoreMark.
This is a general timing improvement and should be upstreamed.
This commit is contained in:
Jonathan Woodruff
2022-01-14 11:53:40 +00:00
parent 1f8181d595
commit dac5c99100

View File

@@ -658,16 +658,44 @@ module mkFetchStage(FetchStage);
// Note that only 1 redirection may happen in a cycle
Maybe#(IType) redirectInst = Invalid;
`endif
// Vector functions to generate all PCs, predicted next PCs, decode all instructions,
// and perform direction prediction for all. Taking these out of the following loop
// makes them unconditional, not depending on previous iterations, improving timing.
function t valid (Maybe#(t) v) = v.Valid;
function CapMem getPc(Integer i) = decompressPc(valid(decodeIn[i]).pc);
Vector#(SupSize, CapMem) pcs = genWith(getPc);
function CapMem getPpc(Integer i) = decompressPc(valid(decodeIn[i]).ppc);
Vector#(SupSize, CapMem) ppcs = genWith(getPpc);
function DecodeResult getDecodeResult(Integer i) = decode(valid(decodeIn[i]).inst, getFlags(pcs[i])==1);
Vector#(SupSize, DecodeResult) decode_results = genWith(getDecodeResult);
function DecodedInst getDInst(Integer i) = decode_results[i].dInst;
Vector#(SupSize, DecodedInst) dInsts = genWith(getDInst);
Vector#(SupSize, DirPredResult#(DirPredTrainInfo)) pred_ress =
replicate(DirPredResult{taken: False, train: ?});
Bool fetch_branch_misprediction = False;
for (Integer i = 0; i < valueof(SupSize); i=i+1) begin
if(dInsts[i].iType == Br && !fetch_branch_misprediction) begin
pred_ress[i] <- dirPred.pred[i].pred(getAddr(pcs[i]));
fetch_branch_misprediction = (pred_ress[i].taken != valid(decodeIn[i]).pred_jump);
end
end
function Maybe#(CapMem) getBranchNextPc(Integer i) =
decodeBrPred(pcs[i], dInsts[i], pred_ress[i].taken, (valid(decodeIn[i]).inst_kind == Inst_32b));
Vector#(SupSize, Maybe#(CapMem)) nextPcsBranch = genWith(getBranchNextPc);
for (Integer i = 0; i < valueof(SupSize); i=i+1) begin
if (decodeIn[i] matches tagged Valid .in) begin
let cause = in.cause;
CapMem pc = decompressPc(in.pc);
CapMem ppc = decompressPc(in.ppc);
CapMem pc = pcs[i];//decompressPc(in.pc);
CapMem ppc = ppcs[i];//decompressPc(in.ppc);
pcBlocks.rPort[i].remove(in.pc.idx);
if (verbose)
$display("Decode: %0d in = ", i, fshow (in));
let decode_result = decode_results[i];//decode(in.inst, getFlags(pc)==1); // Decode 32b inst, or 32b expansion of 16b inst
let dInst = dInsts[i];//decode_result.dInst;
let regs = decode_result.regs;
// do decode and branch prediction
// Drop here if does not match the decode_epoch.
if (in.decode_epoch == decode_epoch_local && in.mispred_first_half) begin
@@ -684,28 +712,15 @@ module mkFetchStage(FetchStage);
end else if (in.decode_epoch == decode_epoch_local) begin
doAssert(in.main_epoch == f_main_epoch, "main epoch must match");
let decode_result = decode(in.inst, getFlags(pc)==1); // Decode 32b inst, or 32b expansion of 16b inst
// update cause if decode exception and no earlier (TLB) exception
if (!isValid(cause)) begin
cause = decode_result.illegalInst ? tagged Valid excIllegalInst : tagged Invalid;
end
let dInst = decode_result.dInst;
let regs = decode_result.regs;
DirPredTrainInfo dp_train = ?; // dir pred training bookkeeping
// update predicted next pc
if (!isValid(cause)) begin
// direction predict
Bool pred_taken = False;
if(dInst.iType == Br) begin
let pred_res <- dirPred.pred[i].pred(getAddr(pc));
pred_taken = pred_res.taken;
dp_train = pred_res.train;
end
Maybe#(CapMem) nextPc = decodeBrPred(pc, dInst, pred_taken, (in.inst_kind == Inst_32b));
Maybe#(CapMem) nextPc = nextPcsBranch[i];
// return address stack link reg is x1 or x5
function Bool linkedR(Maybe#(ArchRIndx) register);
Bool res = False;
@@ -750,7 +765,7 @@ module mkFetchStage(FetchStage);
end
if(verbose) begin
$display("Branch prediction: ", fshow(dInst.iType), " ; ", fshow(pc), " ; ",
fshow(ppc), " ; ", fshow(pred_taken), " ; ", fshow(nextPc));
fshow(ppc), " ; ", fshow(nextPc));
end
// If we don't have a good guess about where we are going, don't proceed.
@@ -783,7 +798,7 @@ module mkFetchStage(FetchStage);
`endif
ppc: ppc,
main_epoch: in.main_epoch,
dpTrain: dp_train,
dpTrain: pred_ress[i].train,
inst: in.inst,
dInst: dInst,
orig_inst: in.orig_inst,