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 BTBValidF;
logic [1:0] DirPredictionF; logic [1:0] DirPredictionF;
logic [4:0] BPInstrClassF, BPInstrClassD, BPInstrClassE; logic [4:0] PredInstrClassF, PredInstrClassD, PredInstrClassE;
logic [`XLEN-1:0] BTBPredPCF, RASPCF; logic [`XLEN-1:0] BTBPredPCF, RASPCF;
logic TargetWrongE; logic TargetWrongE;
logic FallThroughWrongE; logic FallThroughWrongE;
@ -95,7 +95,7 @@ module bpred (
end else if (`BPTYPE == "BPSPECULATIVEGLOBAL") begin:Predictor end else if (`BPTYPE == "BPSPECULATIVEGLOBAL") begin:Predictor
speculativeglobalhistory #(10) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, speculativeglobalhistory #(10) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
.PCNextF, .PCF, .PCD, .PCE, .PCM, .DirPredictionF, .DirPredictionWrongE, .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); .BranchInstrW(InstrClassW[0]), .PCSrcE);
end else if (`BPTYPE == "BPGSHARE") begin:Predictor end else if (`BPTYPE == "BPGSHARE") begin:Predictor
@ -106,7 +106,7 @@ module bpred (
end else if (`BPTYPE == "BPSPECULATIVEGSHARE") begin:Predictor end else if (`BPTYPE == "BPSPECULATIVEGSHARE") begin:Predictor
speculativegshare DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, speculativegshare DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
.PCNextF, .PCF, .PCD, .PCE, .PCM, .DirPredictionF, .DirPredictionWrongE, .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); .BranchInstrW(InstrClassW[0]), .PCSrcE);
end else if (`BPTYPE == "BPLOCALPAg") begin:Predictor end else if (`BPTYPE == "BPLOCALPAg") begin:Predictor
@ -129,10 +129,10 @@ module bpred (
// 1) A direction (1 = Taken, 0 = Not Taken) // 1) A direction (1 = Taken, 0 = Not Taken)
// 2) Any information which is necessary for the predictor to build its next state. // 2) Any information which is necessary for the predictor to build its next state.
// For a 2 bit table this is the prediction count. // For a 2 bit table this is the prediction count.
assign SelBPPredF = ((BPInstrClassF[0] & DirPredictionF[1] & BTBValidF) | assign SelBPPredF = ((PredInstrClassF[0] & DirPredictionF[1] & BTBValidF) |
BPInstrClassF[3] | PredInstrClassF[3] |
(BPInstrClassF[2] & BTBValidF) | (PredInstrClassF[2] & BTBValidF) |
BPInstrClassF[1] & BTBValidF) ; PredInstrClassF[1] & BTBValidF) ;
// Part 2 Branch target address prediction // Part 2 Branch target address prediction
// *** For now the BTB will house the direct and indirect targets // *** For now the BTB will house the direct and indirect targets
@ -143,7 +143,7 @@ module bpred (
.*, // Stalls and flushes .*, // Stalls and flushes
.LookUpPC(PCNextF), .LookUpPC(PCNextF),
.TargetPC(BTBPredPCF), .TargetPC(BTBPredPCF),
.InstrClass(BPInstrClassF), .InstrClass(PredInstrClassF),
.Valid(BTBValidF), .Valid(BTBValidF),
// update // update
.UpdateEN((|InstrClassE | (PredictionInstrClassWrongE)) & ~StallE), .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. // *** need to add the logic to restore RAS on flushes. We will use incr for this.
RASPredictor RASPredictor(.clk(clk), RASPredictor RASPredictor(.clk(clk),
.reset(reset), .reset(reset),
.pop(BPInstrClassF[3] & ~StallF), .pop(PredInstrClassF[3] & ~StallF),
.popPC(RASPCF), .popPC(RASPCF),
.push(InstrClassE[4] & ~StallE), .push(InstrClassE[4] & ~StallE),
.incr(1'b0), .incr(1'b0),
.pushPC(PCLinkE)); .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. // the branch predictor needs a compact decoding of the instruction class.
// *** consider adding in the alternate return address x5 for returns. // *** consider adding in the alternate return address x5 for returns.
@ -182,8 +182,8 @@ module bpred (
{DirPredictionWrongM, BTBPredPCWrongM, RASPredPCWrongM, PredictionInstrClassWrongM}); {DirPredictionWrongM, BTBPredPCWrongM, RASPredPCWrongM, PredictionInstrClassWrongM});
// pipeline the class // pipeline the class
flopenrc #(5) BPInstrClassRegD(clk, reset, FlushD, ~StallD, BPInstrClassF, BPInstrClassD); flopenrc #(5) PredInstrClassRegD(clk, reset, FlushD, ~StallD, PredInstrClassF, PredInstrClassD);
flopenrc #(5) BPInstrClassRegE(clk, reset, FlushE, ~StallE, BPInstrClassD, BPInstrClassE); flopenrc #(5) PredInstrClassRegE(clk, reset, FlushE, ~StallE, PredInstrClassD, PredInstrClassE);
// Check the prediction // Check the prediction
// first check if the target or fallthrough address matches what was predicted. // 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. // 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. // 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 // 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 // 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 input logic PCSrcE
); );
logic MatchF, MatchD, MatchE, MatchM, MatchW; logic MatchF, MatchD, MatchE, MatchM;
logic MatchNextX, MatchXF; logic MatchNextX, MatchXF;
logic [1:0] TableDirPredictionF, DirPredictionD, DirPredictionE; 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-1:0] GHRF;
logic [k:0] GHRD, OldGHRE, GHRE, GHRM, GHRW; logic [k:0] GHRD, OldGHRE, GHRE, GHRM, GHRW;
logic [k-1:0] GHRNextF; logic [k-1:0] GHRNextF;
logic [k:0] GHRNextD, GHRNextE, GHRNextM, GHRNextW; logic [k:0] GHRNextD, GHRNextE, GHRNextM, GHRNextW;
logic [k-1:0] IndexNextF, IndexF; 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 PCSrcM, PCSrcW;
logic [`XLEN-1:0] PCW; logic [`XLEN-1:0] PCW;
@ -67,15 +67,14 @@ module speculativegshare
assign IndexD = GHRD[k-1:0] ^ {PCD[k+1] ^ PCD[1], PCD[k:2]}; 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 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 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), ram2p1r1wbefix #(2**k, 2) PHT(.clk(clk),
.ce1(~StallF | reset), .ce2(~StallW & ~FlushW), .ce1(~StallF | reset), .ce2(~StallW & ~FlushW),
.ra1(IndexNextF), .ra1(IndexNextF),
.rd1(TableDirPredictionF), .rd1(TableDirPredictionF),
.wa2(IndexW), .wa2(IndexM),
.wd2(NewDirPredictionW), .wd2(NewDirPredictionM),
.we2(BranchInstrW & ~StallW & ~FlushW), .we2(BranchInstrM & ~StallW & ~FlushW),
.bwe2(1'b1)); .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 // if there are non-flushed branches in the pipeline we need to forward the prediction from that stage to the NextF demi stage
@ -84,16 +83,14 @@ module speculativegshare
assign MatchD = BranchInstrD & ~FlushE & (IndexNextF == IndexD); assign MatchD = BranchInstrD & ~FlushE & (IndexNextF == IndexD);
assign MatchE = BranchInstrE & ~FlushM & (IndexNextF == IndexE); assign MatchE = BranchInstrE & ~FlushM & (IndexNextF == IndexE);
assign MatchM = BranchInstrM & ~FlushW & (IndexNextF == IndexM); assign MatchM = BranchInstrM & ~FlushW & (IndexNextF == IndexM);
assign MatchW = BranchInstrW & (IndexNextF == IndexW); assign MatchNextX = MatchF | MatchD | MatchE | MatchM;
assign MatchNextX = MatchF | MatchD | MatchE | MatchM | MatchW;
flopenr #(1) MatchReg(clk, reset, ~StallF, MatchNextX, MatchXF); flopenr #(1) MatchReg(clk, reset, ~StallF, MatchNextX, MatchXF);
assign ForwardNewDirPrediction = MatchF ? NewDirPredictionF : assign ForwardNewDirPrediction = MatchF ? NewDirPredictionF :
MatchD ? NewDirPredictionD : MatchD ? NewDirPredictionD :
MatchE ? NewDirPredictionE : MatchE ? NewDirPredictionE :
MatchM ? NewDirPredictionM : NewDirPredictionM;
NewDirPredictionW;
flopenr #(2) ForwardDirPredicitonReg(clk, reset, ~StallF, ForwardNewDirPrediction, ForwardDirPredictionF); flopenr #(2) ForwardDirPredicitonReg(clk, reset, ~StallF, ForwardNewDirPrediction, ForwardDirPredictionF);
@ -109,7 +106,6 @@ module speculativegshare
flopenr #(2) NewPredDReg(clk, reset, ~StallD, NewDirPredictionF, NewDirPredictionD); flopenr #(2) NewPredDReg(clk, reset, ~StallD, NewDirPredictionF, NewDirPredictionD);
satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE)); satCounter2 BPDirUpdateE(.BrDir(PCSrcE), .OldState(DirPredictionE), .NewState(NewDirPredictionE));
flopenr #(2) NewPredMReg(clk, reset, ~StallM, NewDirPredictionE, NewDirPredictionM); flopenr #(2) NewPredMReg(clk, reset, ~StallM, NewDirPredictionE, NewDirPredictionM);
flopenr #(2) NewPredWReg(clk, reset, ~StallW, NewDirPredictionM, NewDirPredictionW);
// PCSrc pipeline // PCSrc pipeline
flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, PCSrcM); flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, PCSrcM);