It's a bit sloppy, but the global history predictor is working correctly now.

There were two major bugs with the predictor.
First the update mechanism was completely wrong.  The PHT is updated with the GHR that was used to lookup the prediction.  PHT[GHR] = Sat2(PHT[GHR], branch outcome).
Second the GHR needs to be updated speculatively as the branch is predicted.  This is important so that back to back branches' GHRs are not the same.  The must be different to avoid aliasing.  Speculation of the GHR update allows them to be different.  On mis prediction the GHR must be reverted.
This implementation is a bit sloppy with names and now the GHR recovery is performed.  Updates to follow.
This commit is contained in:
Ross Thompson 2021-05-27 23:06:28 -05:00
parent 7e84c3f514
commit 8a035104ac
4 changed files with 51 additions and 17 deletions

View File

@ -110,5 +110,6 @@
`define TWO_BIT_PRELOAD "../config/rv64icfd/twoBitPredictor.txt" `define TWO_BIT_PRELOAD "../config/rv64icfd/twoBitPredictor.txt"
`define BTB_PRELOAD "../config/rv64icfd/BTBPredictor.txt" `define BTB_PRELOAD "../config/rv64icfd/BTBPredictor.txt"
`define BPRED_ENABLED 1 `define BPRED_ENABLED 1
`define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE //`define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE
`define BPTYPE "BPGLOBAL" // BPTWOBIT or "BPGSHARE" or BPLOCALPAg or BPGSHARE
`define TESTSBP 1 `define TESTSBP 1

View File

@ -30,7 +30,8 @@
module bpred module bpred
(input logic clk, reset, (input logic clk, reset,
input logic StallF, StallD, StallE, FlushF, FlushD, FlushE, input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushF, FlushD, FlushE, FlushM, FlushW,
// Fetch stage // Fetch stage
// the prediction // the prediction
input logic [`XLEN-1:0] PCNextF, // *** forgot to include this one on the I/O list input logic [`XLEN-1:0] PCNextF, // *** forgot to include this one on the I/O list
@ -93,6 +94,8 @@ module bpred
// update // update
.UpdatePC(PCE), .UpdatePC(PCE),
.UpdateEN(InstrClassE[0] & ~StallE), .UpdateEN(InstrClassE[0] & ~StallE),
.SpeculativeUpdateEn(BPInstrClassF[0] & ~StallF),
.BPPredDirWrongE(BPPredDirWrongE),
.PCSrcE(PCSrcE), .PCSrcE(PCSrcE),
.UpdatePrediction(UpdateBPPredE)); .UpdatePrediction(UpdateBPPredE));
end else if (`BPTYPE == "BPGSHARE") begin:Predictor end else if (`BPTYPE == "BPGSHARE") begin:Predictor
@ -190,14 +193,14 @@ module bpred
flopenrc #(2) BPPredRegD(.clk(clk), flopenrc #(2) BPPredRegD(.clk(clk),
.reset(reset), .reset(reset),
.en(~StallD), .en(~StallD),
.clear(FlushD), .clear(1'b0),
.d(BPPredF), .d(BPPredF),
.q(BPPredD)); .q(BPPredD));
flopenrc #(2) BPPredRegE(.clk(clk), flopenrc #(2) BPPredRegE(.clk(clk),
.reset(reset), .reset(reset),
.en(~StallE), .en(~StallE),
.clear(FlushE), .clear(1'b0),
.d(BPPredD), .d(BPPredD),
.q(BPPredE)); .q(BPPredE));

View File

@ -37,29 +37,66 @@ module globalHistoryPredictor
output logic [1:0] Prediction, output logic [1:0] Prediction,
// update // update
input logic [`XLEN-1:0] UpdatePC, input logic [`XLEN-1:0] UpdatePC,
input logic UpdateEN, PCSrcE, input logic UpdateEN, PCSrcE,
input logic SpeculativeUpdateEn, BPPredDirWrongE,
input logic [1:0] UpdatePrediction input logic [1:0] UpdatePrediction
); );
logic [k-1:0] GHRF, GHRFNext; logic [k-1:0] GHRF, GHRFNext, GHRD, GHRE, GHRLookup;
assign GHRFNext = {PCSrcE, GHRF[k-1:1]};
logic FlushedD, FlushedE;
// if the prediction is wrong we need to restore the ghr.
assign GHRFNext = BPPredDirWrongE ? {PCSrcE, GHRE[k-1:1]} :
{Prediction[1], GHRF[k-1:1]};
flopenr #(k) GlobalHistoryRegister(.clk(clk), flopenr #(k) GlobalHistoryRegister(.clk(clk),
.reset(reset), .reset(reset),
.en(UpdateEN), .en((UpdateEN & BPPredDirWrongE) | (SpeculativeUpdateEn)),
.d(GHRFNext), .d(GHRFNext),
.q(GHRF)); .q(GHRF));
// if actively updating the GHR at the time of prediction we want to us
// GHRFNext as the lookup rather than GHRF.
assign GHRLookup = UpdateEN ? GHRFNext : GHRF;
// Make Prediction by reading the correct address in the PHT and also update the new address in the PHT // Make Prediction by reading the correct address in the PHT and also update the new address in the PHT
SRAM2P1R1W #(k, 2) PHT(.clk(clk), SRAM2P1R1W #(k, 2) PHT(.clk(clk),
.reset(reset), .reset(reset),
.RA1(GHRF), .RA1(GHRF),
.RD1(Prediction), .RD1(Prediction),
.REN1(~StallF), .REN1(~StallF),
.WA1(GHRF), .WA1(GHRE),
.WD1(UpdatePrediction), .WD1(UpdatePrediction),
.WEN1(UpdateEN), .WEN1(UpdateEN),
.BitWEN1(2'b11)); .BitWEN1(2'b11));
flopenr #(k) GlobalHistoryRegisterD(.clk(clk),
.reset(reset),
.en(~StallD & ~FlushedE),
.d(GHRF),
.q(GHRD));
flopenr #(k) GlobalHistoryRegisterE(.clk(clk),
.reset(reset),
.en(~StallE & ~ FlushedE),
.d(GHRD),
.q(GHRE));
flopenr #(1) flushedDReg(.clk(clk),
.reset(reset),
.en(~StallD),
.d(FlushD),
.q(FlushedD));
flopenr #(1) flushedEReg(.clk(clk),
.reset(reset),
.en(~StallE),
.d(FlushE | FlushedD),
.q(FlushedE));
endmodule endmodule

View File

@ -153,14 +153,7 @@ module ifu (
generate generate
if (`BPRED_ENABLED == 1) begin : bpred if (`BPRED_ENABLED == 1) begin : bpred
// I am making the port connection explicit for now as I want to see them and they will be changing. // I am making the port connection explicit for now as I want to see them and they will be changing.
bpred bpred(.clk(clk), bpred bpred(.*,
.reset(reset),
.StallF(StallF),
.StallD(StallD),
.StallE(StallE),
.FlushF(FlushF),
.FlushD(FlushD),
.FlushE(FlushE),
.PCNextF(PCNextF), .PCNextF(PCNextF),
.BPPredPCF(BPPredPCF), .BPPredPCF(BPPredPCF),
.SelBPPredF(SelBPPredF), .SelBPPredF(SelBPPredF),