From 8a035104ac47678fc1de4fc1110511c5334233ae Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Thu, 27 May 2021 23:06:28 -0500 Subject: [PATCH] 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. --- wally-pipelined/config/rv64BP/wally-config.vh | 3 +- wally-pipelined/src/ifu/bpred.sv | 9 ++-- .../src/ifu/globalHistoryPredictor.sv | 47 +++++++++++++++++-- wally-pipelined/src/ifu/ifu.sv | 9 +--- 4 files changed, 51 insertions(+), 17 deletions(-) diff --git a/wally-pipelined/config/rv64BP/wally-config.vh b/wally-pipelined/config/rv64BP/wally-config.vh index 17a8c284..fd482bfd 100644 --- a/wally-pipelined/config/rv64BP/wally-config.vh +++ b/wally-pipelined/config/rv64BP/wally-config.vh @@ -110,5 +110,6 @@ `define TWO_BIT_PRELOAD "../config/rv64icfd/twoBitPredictor.txt" `define BTB_PRELOAD "../config/rv64icfd/BTBPredictor.txt" `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 diff --git a/wally-pipelined/src/ifu/bpred.sv b/wally-pipelined/src/ifu/bpred.sv index de0f8143..c5b4dde4 100644 --- a/wally-pipelined/src/ifu/bpred.sv +++ b/wally-pipelined/src/ifu/bpred.sv @@ -30,7 +30,8 @@ module bpred (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 // the prediction input logic [`XLEN-1:0] PCNextF, // *** forgot to include this one on the I/O list @@ -93,6 +94,8 @@ module bpred // update .UpdatePC(PCE), .UpdateEN(InstrClassE[0] & ~StallE), + .SpeculativeUpdateEn(BPInstrClassF[0] & ~StallF), + .BPPredDirWrongE(BPPredDirWrongE), .PCSrcE(PCSrcE), .UpdatePrediction(UpdateBPPredE)); end else if (`BPTYPE == "BPGSHARE") begin:Predictor @@ -190,14 +193,14 @@ module bpred flopenrc #(2) BPPredRegD(.clk(clk), .reset(reset), .en(~StallD), - .clear(FlushD), + .clear(1'b0), .d(BPPredF), .q(BPPredD)); flopenrc #(2) BPPredRegE(.clk(clk), .reset(reset), .en(~StallE), - .clear(FlushE), + .clear(1'b0), .d(BPPredD), .q(BPPredE)); diff --git a/wally-pipelined/src/ifu/globalHistoryPredictor.sv b/wally-pipelined/src/ifu/globalHistoryPredictor.sv index b2357ecc..fadbf004 100644 --- a/wally-pipelined/src/ifu/globalHistoryPredictor.sv +++ b/wally-pipelined/src/ifu/globalHistoryPredictor.sv @@ -37,29 +37,66 @@ module globalHistoryPredictor output logic [1:0] Prediction, // update input logic [`XLEN-1:0] UpdatePC, - input logic UpdateEN, PCSrcE, + input logic UpdateEN, PCSrcE, + input logic SpeculativeUpdateEn, BPPredDirWrongE, input logic [1:0] UpdatePrediction ); - logic [k-1:0] GHRF, GHRFNext; - assign GHRFNext = {PCSrcE, GHRF[k-1:1]}; + logic [k-1:0] GHRF, GHRFNext, GHRD, GHRE, GHRLookup; + + 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), .reset(reset), - .en(UpdateEN), + .en((UpdateEN & BPPredDirWrongE) | (SpeculativeUpdateEn)), .d(GHRFNext), .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 SRAM2P1R1W #(k, 2) PHT(.clk(clk), .reset(reset), .RA1(GHRF), .RD1(Prediction), .REN1(~StallF), - .WA1(GHRF), + .WA1(GHRE), .WD1(UpdatePrediction), .WEN1(UpdateEN), .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 diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 994288bd..0922f787 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -153,14 +153,7 @@ module ifu ( generate 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. - bpred bpred(.clk(clk), - .reset(reset), - .StallF(StallF), - .StallD(StallD), - .StallE(StallE), - .FlushF(FlushF), - .FlushD(FlushD), - .FlushE(FlushE), + bpred bpred(.*, .PCNextF(PCNextF), .BPPredPCF(BPPredPCF), .SelBPPredF(SelBPPredF),