More branch predictor cleanup.

Found small bug. The decode stage was using the predicted instruction class rather than the decoded instruction class.
This commit is contained in:
Ross Thompson 2023-01-13 12:57:18 -06:00
parent cf608ee45f
commit de7f3b14fc
2 changed files with 23 additions and 27 deletions

View File

@ -65,7 +65,7 @@ module bpred (
logic BTBValidF;
logic [1:0] DirPredictionF;
logic [4:0] BPInstrClassF, BPInstrClassD, BPInstrClassE;
logic [4:0] PredInstrClassF, PredInstrClassD, PredInstrClassE;
logic [`XLEN-1:0] BTBPredPCF, RASPCF;
logic TargetWrongE;
logic FallThroughWrongE;
@ -95,7 +95,7 @@ module bpred (
end else if (`BPTYPE == "BPSPECULATIVEGLOBAL") begin:Predictor
speculativeglobalhistory #(10) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
.PCNextF, .PCF, .PCD, .PCE, .PCM, .DirPredictionF, .DirPredictionWrongE,
.BranchInstrF(BPInstrClassF[0]), .BranchInstrD(BPInstrClassD[0]), .BranchInstrE(InstrClassE[0]), .BranchInstrM(InstrClassM[0]),
.BranchInstrF(PredInstrClassF[0]), .BranchInstrD(InstrClassD[0]), .BranchInstrE(InstrClassE[0]), .BranchInstrM(InstrClassM[0]),
.BranchInstrW(InstrClassW[0]), .PCSrcE);
end else if (`BPTYPE == "BPGSHARE") begin:Predictor
@ -106,7 +106,7 @@ module bpred (
end else if (`BPTYPE == "BPSPECULATIVEGSHARE") begin:Predictor
speculativegshare DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
.PCNextF, .PCF, .PCD, .PCE, .PCM, .DirPredictionF, .DirPredictionWrongE,
.BranchInstrF(BPInstrClassF[0]), .BranchInstrD(BPInstrClassD[0]), .BranchInstrE(InstrClassE[0]), .BranchInstrM(InstrClassM[0]),
.BranchInstrF(PredInstrClassF[0]), .BranchInstrD(InstrClassD[0]), .BranchInstrE(InstrClassE[0]), .BranchInstrM(InstrClassM[0]),
.BranchInstrW(InstrClassW[0]), .PCSrcE);
end else if (`BPTYPE == "BPLOCALPAg") begin:Predictor
@ -129,10 +129,10 @@ module bpred (
// 1) A direction (1 = Taken, 0 = Not Taken)
// 2) Any information which is necessary for the predictor to build its next state.
// For a 2 bit table this is the prediction count.
assign SelBPPredF = ((BPInstrClassF[0] & DirPredictionF[1] & BTBValidF) |
BPInstrClassF[3] |
(BPInstrClassF[2] & BTBValidF) |
BPInstrClassF[1] & BTBValidF) ;
assign SelBPPredF = ((PredInstrClassF[0] & DirPredictionF[1] & BTBValidF) |
PredInstrClassF[3] |
(PredInstrClassF[2] & BTBValidF) |
PredInstrClassF[1] & BTBValidF) ;
// Part 2 Branch target address prediction
// *** For now the BTB will house the direct and indirect targets
@ -143,7 +143,7 @@ module bpred (
.*, // Stalls and flushes
.LookUpPC(PCNextF),
.TargetPC(BTBPredPCF),
.InstrClass(BPInstrClassF),
.InstrClass(PredInstrClassF),
.Valid(BTBValidF),
// update
.UpdateEN((|InstrClassE | (PredictionInstrClassWrongE)) & ~StallE),
@ -156,13 +156,13 @@ module bpred (
// *** need to add the logic to restore RAS on flushes. We will use incr for this.
RASPredictor RASPredictor(.clk(clk),
.reset(reset),
.pop(BPInstrClassF[3] & ~StallF),
.pop(PredInstrClassF[3] & ~StallF),
.popPC(RASPCF),
.push(InstrClassE[4] & ~StallE),
.incr(1'b0),
.pushPC(PCLinkE));
assign BPPredPCF = BPInstrClassF[3] ? RASPCF : BTBPredPCF;
assign BPPredPCF = PredInstrClassF[3] ? RASPCF : BTBPredPCF;
// the branch predictor needs a compact decoding of the instruction class.
// *** consider adding in the alternate return address x5 for returns.
@ -182,8 +182,8 @@ module bpred (
{DirPredictionWrongM, BTBPredPCWrongM, RASPredPCWrongM, PredictionInstrClassWrongM});
// pipeline the class
flopenrc #(5) BPInstrClassRegD(clk, reset, FlushD, ~StallD, BPInstrClassF, BPInstrClassD);
flopenrc #(5) BPInstrClassRegE(clk, reset, FlushE, ~StallE, BPInstrClassD, BPInstrClassE);
flopenrc #(5) PredInstrClassRegD(clk, reset, FlushD, ~StallD, PredInstrClassF, PredInstrClassD);
flopenrc #(5) PredInstrClassRegE(clk, reset, FlushE, ~StallE, PredInstrClassD, PredInstrClassE);
// Check the prediction
// first check if the target or fallthrough address matches what was predicted.
@ -201,7 +201,7 @@ module bpred (
// Finally we need to check if the class is wrong. When the class is wrong the BTB needs to be updated.
// Also we want to track this in a performance counter.
assign PredictionInstrClassWrongE = InstrClassE != BPInstrClassE;
assign PredictionInstrClassWrongE = InstrClassE != PredInstrClassE;
// We want to output to the instruction fetch if the PC fetched was wrong. If by chance the predictor was wrong about
// the direction or class, but correct about the target we don't have the flush the pipeline. However we still

View File

@ -44,18 +44,18 @@ module speculativegshare
input logic PCSrcE
);
logic MatchF, MatchD, MatchE, MatchM, MatchW;
logic MatchF, MatchD, MatchE, MatchM;
logic MatchNextX, MatchXF;
logic [1:0] TableDirPredictionF, DirPredictionD, DirPredictionE;
logic [1:0] NewDirPredictionF, NewDirPredictionD, NewDirPredictionE, NewDirPredictionM, NewDirPredictionW;
logic [1:0] NewDirPredictionF, NewDirPredictionD, NewDirPredictionE, NewDirPredictionM;
logic [k-1:0] GHRF;
logic [k:0] GHRD, OldGHRE, GHRE, GHRM, GHRW;
logic [k-1:0] GHRNextF;
logic [k:0] GHRNextD, GHRNextE, GHRNextM, GHRNextW;
logic [k-1:0] IndexNextF, IndexF;
logic [k-1:0] IndexD, IndexE, IndexM, IndexW;
logic [k-1:0] IndexD, IndexE, IndexM;
logic PCSrcM, PCSrcW;
logic [`XLEN-1:0] PCW;
@ -67,34 +67,31 @@ module speculativegshare
assign IndexD = GHRD[k-1:0] ^ {PCD[k+1] ^ PCD[1], PCD[k:2]};
assign IndexE = GHRE[k-1:0] ^ {PCE[k+1] ^ PCE[1], PCE[k:2]};
assign IndexM = GHRM[k-1:0] ^ {PCM[k+1] ^ PCM[1], PCM[k:2]};
assign IndexW = GHRW[k-1:0] ^ {PCW[k+1] ^ PCW[1], PCW[k:2]};
ram2p1r1wbefix #(2**k, 2) PHT(.clk(clk),
.ce1(~StallF | reset), .ce2(~StallW & ~FlushW),
.ra1(IndexNextF),
.rd1(TableDirPredictionF),
.wa2(IndexW),
.wd2(NewDirPredictionW),
.we2(BranchInstrW & ~StallW & ~FlushW),
.wa2(IndexM),
.wd2(NewDirPredictionM),
.we2(BranchInstrM & ~StallW & ~FlushW),
.bwe2(1'b1));
// if there are non-flushed branches in the pipeline we need to forward the prediction from that stage to the NextF demi stage
// and then register for use in the Fetch stage.
// and then register for use in the Fetch stage.
assign MatchF = BranchInstrF & ~FlushD & (IndexNextF == IndexF);
assign MatchD = BranchInstrD & ~FlushE & (IndexNextF == IndexD);
assign MatchE = BranchInstrE & ~FlushM & (IndexNextF == IndexE);
assign MatchM = BranchInstrM & ~FlushW & (IndexNextF == IndexM);
assign MatchW = BranchInstrW & (IndexNextF == IndexW);
assign MatchNextX = MatchF | MatchD | MatchE | MatchM | MatchW;
assign MatchNextX = MatchF | MatchD | MatchE | MatchM;
flopenr #(1) MatchReg(clk, reset, ~StallF, MatchNextX, MatchXF);
assign ForwardNewDirPrediction = MatchF ? NewDirPredictionF :
MatchD ? NewDirPredictionD :
MatchE ? NewDirPredictionE :
MatchM ? NewDirPredictionM :
NewDirPredictionW;
NewDirPredictionM;
flopenr #(2) ForwardDirPredicitonReg(clk, reset, ~StallF, ForwardNewDirPrediction, ForwardDirPredictionF);
assign DirPredictionF = MatchXF ? ForwardDirPredictionF : TableDirPredictionF;
@ -109,7 +106,6 @@ module speculativegshare
flopenr #(2) NewPredDReg(clk, reset, ~StallD, NewDirPredictionF, NewDirPredictionD);
satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE));
flopenr #(2) NewPredMReg(clk, reset, ~StallM, NewDirPredictionE, NewDirPredictionM);
flopenr #(2) NewPredWReg(clk, reset, ~StallW, NewDirPredictionM, NewDirPredictionW);
// PCSrc pipeline
flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, PCSrcM);