blob: 379b1daf41a49997a2a2844749b3bce55f3323a7 [file] [log] [blame]
// SPDX-FileCopyrightText: 2022 RIOSLab
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
module gshare
#(
parameter GSHARE_WIDTH = 4,
parameter PHT_LEN = 16
)
(
input clk,
input reset,
// from fetch: current instr
/* verilator lint_off UNUSED */
input [31:0] pc,
// from execute: last instr
input [31:0] prev_pc, // prev pc
input prev_branch_in, // whether prev instr is branch
input prev_taken, // whether prev instr taken
// input prev_pred, // prev instr pred result
// output prev_mispred, // whether prev instr mispred
// to out: taken or not taken
output cur_pred// cur instr pred
);
integer i =0;
// pattern history table
reg [1:0] PHT [0:PHT_LEN-1];
// global history register
reg [GSHARE_WIDTH-1:0] GHR = 0;
// reg [GSHARE_WIDTH-1:0] prev_idx = 0;
// previous instr's index into PHT; aliasing issue exists
wire [GSHARE_WIDTH-1:0] prev_idx = prev_pc[GSHARE_WIDTH+1:2] ^ GHR;
wire [GSHARE_WIDTH-1:0] cur_idx = pc[GSHARE_WIDTH+1:2] ^ GHR;
// cur pred result
assign cur_pred = PHT[cur_idx][1];
// whether last instr is mispred
// assign prev_mispred = (prev_taken != prev_pred);
always @(posedge clk) begin
if (reset) begin
// prev_idx <= 0;
GHR <= 0;
for (i = 0; i < PHT_LEN; i = i + 1) begin
PHT[i] <= 2'b10; // initial: weak taken
end
end
// update GHR using last pc from execute
if (prev_branch_in) begin
GHR <= {GHR[GSHARE_WIDTH-2:0], prev_taken};
end
// update PHT using previous taken or not taken result
if (prev_branch_in && prev_taken) begin
case (PHT[prev_idx])
2'b00:
PHT[prev_idx] <= 2'b01;
2'b01:
PHT[prev_idx] <= 2'b10;
2'b10:
PHT[prev_idx] <= 2'b11;
2'b11:
PHT[prev_idx] <= 2'b11;
endcase
end else if (prev_branch_in && !prev_taken) begin
case (PHT[prev_idx])
2'b00:
PHT[prev_idx] <= 2'b00;
2'b01:
PHT[prev_idx] <= 2'b00;
2'b10:
PHT[prev_idx] <= 2'b01;
2'b11:
PHT[prev_idx] <= 2'b10;
endcase
end
/* verilator lint_on UNUSED */
end
endmodule