Skip to content

Commit

Permalink
bp: add BHT with private history
Browse files Browse the repository at this point in the history
Co-authored-by: Riccardo Tedeschi <[email protected]>
  • Loading branch information
OttG and ricted98 committed Mar 4, 2025
1 parent d971232 commit 88ed8a7
Show file tree
Hide file tree
Showing 27 changed files with 234 additions and 2 deletions.
1 change: 1 addition & 0 deletions Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ sources:
# Frontend (i.e., fetch, decode, dispatch)
- core/frontend/btb.sv
- core/frontend/bht.sv
- core/frontend/bht2lvl.sv
- core/frontend/ras.sv
- core/frontend/instr_scan.sv
- core/frontend/instr_queue.sv
Expand Down
1 change: 1 addition & 0 deletions Flist.ariane
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ core/decoder.sv
core/ex_stage.sv
core/frontend/btb.sv
core/frontend/bht.sv
core/frontend/bht2lvl.sv
core/frontend/ras.sv
core/frontend/instr_scan.sv
core/frontend/instr_queue.sv
Expand Down
1 change: 1 addition & 0 deletions core/Flist.cva6
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ ${CVA6_REPO_DIR}/core/cva6_fifo_v3.sv
// What is "frontend"?
${CVA6_REPO_DIR}/core/frontend/btb.sv
${CVA6_REPO_DIR}/core/frontend/bht.sv
${CVA6_REPO_DIR}/core/frontend/bht2lvl.sv
${CVA6_REPO_DIR}/core/frontend/ras.sv
${CVA6_REPO_DIR}/core/frontend/instr_scan.sv
${CVA6_REPO_DIR}/core/frontend/instr_queue.sv
Expand Down
135 changes: 135 additions & 0 deletions core/frontend/bht2lvl.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright 2025 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Original author: Gianmarco Ottavi, University of Bologna
// Description: Private history BHT

module bht2lvl #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter int unsigned NR_ENTRIES = 256,
parameter int unsigned HISTORY_LENGTH = 3,
parameter type bht_update_t = logic
) (
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic [ CVA6Cfg.VLEN-1:0] vpc_i,
input bht_update_t bht_update_i,
// we potentially need INSTR_PER_FETCH predictions/cycle
output ariane_pkg::bht_prediction_t [CVA6Cfg.INSTR_PER_FETCH-1:0] bht_prediction_o
);

// the last bit is always zero, we don't need it for indexing
localparam OFFSET = CVA6Cfg.RVC == 1'b1 ? 1 : 2;
// re-shape the branch history table
localparam NR_ROWS = NR_ENTRIES / CVA6Cfg.INSTR_PER_FETCH;
// number of bits needed to index the row
localparam ROW_ADDR_BITS = $clog2(CVA6Cfg.INSTR_PER_FETCH);
localparam ROW_INDEX_BITS = CVA6Cfg.RVC == 1'b1 ? $clog2(CVA6Cfg.INSTR_PER_FETCH) : 1;
// number of bits we should use for prediction
localparam PREDICTION_BITS = $clog2(NR_ROWS) + OFFSET + ROW_ADDR_BITS;

struct packed {
logic valid;
logic [HISTORY_LENGTH-1:0] hist;
logic [2**HISTORY_LENGTH-1:0][1:0] saturation_counter;
}
bht_d[NR_ROWS-1:0][CVA6Cfg.INSTR_PER_FETCH-1:0],
bht_q[NR_ROWS-1:0][CVA6Cfg.INSTR_PER_FETCH-1:0];


logic [$clog2(NR_ROWS)-1:0] index, update_pc;
logic [HISTORY_LENGTH-1:0] update_hist;
logic [ROW_INDEX_BITS-1:0] update_row_index;

assign index = vpc_i[PREDICTION_BITS-1:ROW_ADDR_BITS+OFFSET];
assign update_pc = bht_update_i.pc[PREDICTION_BITS-1:ROW_ADDR_BITS+OFFSET];
assign update_hist = bht_q[update_pc][update_row_index].hist;

if (CVA6Cfg.RVC) begin : gen_update_row_index
assign update_row_index = bht_update_i.pc[ROW_ADDR_BITS+OFFSET-1:OFFSET];
end else begin
assign update_row_index = '0;
end


logic [1:0] saturation_counter;

// Get the current history of the entry
logic [CVA6Cfg.INSTR_PER_FETCH-1:0][HISTORY_LENGTH-1:0] read_history;
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin
assign read_history[i] = bht_q[index][i].hist;
end

// prediction assignment
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_bht_output
assign bht_prediction_o[i].valid = bht_q[index][i].valid;
assign bht_prediction_o[i].taken = bht_q[index][i].saturation_counter[read_history[i]][1] == 1'b1;
end

always_comb begin : update_bht
bht_d = bht_q;
saturation_counter = bht_q[update_pc][update_row_index].saturation_counter[update_hist];

if (bht_update_i.valid) begin
bht_d[update_pc][update_row_index].valid = 1'b1;

if (saturation_counter == 2'b11) begin
// we can safely decrease it
if (!bht_update_i.taken)
bht_d[update_pc][update_row_index].saturation_counter[update_hist] = saturation_counter - 1;
// then check if it saturated in the negative regime e.g.: branch not taken
end else if (saturation_counter == 2'b00) begin
// we can safely increase it
if (bht_update_i.taken)
bht_d[update_pc][update_row_index].saturation_counter[update_hist] = saturation_counter + 1;
end else begin // otherwise we are not in any boundaries and can decrease or increase it
if (bht_update_i.taken)
bht_d[update_pc][update_row_index].saturation_counter[update_hist] = saturation_counter + 1;
else
bht_d[update_pc][update_row_index].saturation_counter[update_hist] = saturation_counter - 1;
end

bht_d[update_pc][update_row_index].hist = {
update_hist[HISTORY_LENGTH-2:0], bht_update_i.taken
};
end
end

always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
for (int unsigned i = 0; i < NR_ROWS; i++) begin
for (int j = 0; j < CVA6Cfg.INSTR_PER_FETCH; j++) begin
bht_q[i][j] <= '0;
for (int k = 0; k < 2 ** HISTORY_LENGTH; k++) begin
bht_q[i][j].saturation_counter[k] <= 2'b10;
end
end
end
end else begin
// evict all entries
if (flush_i) begin
for (int i = 0; i < NR_ROWS; i++) begin
for (int j = 0; j < CVA6Cfg.INSTR_PER_FETCH; j++) begin
bht_q[i][j].valid <= 1'b0;
bht_q[i][j].hist <= '0;
for (int k = 0; k < 2 ** HISTORY_LENGTH; k++) begin
bht_q[i][j].saturation_counter[k] <= 2'b10;
end
end
end
end else begin
bht_q <= bht_d;
end
end
end


endmodule
16 changes: 15 additions & 1 deletion core/frontend/frontend.sv
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ module frontend

if (CVA6Cfg.BHTEntries == 0) begin
assign bht_prediction = '0;
end else begin : bht_gen
end else if (CVA6Cfg.BPType == config_pkg::BHT) begin : bht_gen
bht #(
.CVA6Cfg (CVA6Cfg),
.bht_update_t(bht_update_t),
Expand All @@ -524,6 +524,20 @@ module frontend
.bht_update_i (bht_update),
.bht_prediction_o(bht_prediction)
);
end else if (CVA6Cfg.BPType == config_pkg::PH_BHT) begin : bht2lvl_gen
bht2lvl #(
.CVA6Cfg (CVA6Cfg),
.NR_ENTRIES (CVA6Cfg.BHTEntries),
.HISTORY_LENGTH(CVA6Cfg.BHTHist),
.bht_update_t (bht_update_t)
) i_bht (
.clk_i,
.rst_ni,
.flush_i (flush_bp_i),
.vpc_i (icache_vaddr_q),
.bht_update_i (bht_update),
.bht_prediction_o(bht_prediction)
);
end

// we need to inspect up to CVA6Cfg.INSTR_PER_FETCH instructions for branches
Expand Down
2 changes: 2 additions & 0 deletions core/include/build_config_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ package build_config_pkg;
cfg.ExceptionAddress = CVA6Cfg.ExceptionAddress;
cfg.RASDepth = CVA6Cfg.RASDepth;
cfg.BTBEntries = CVA6Cfg.BTBEntries;
cfg.BPType = CVA6Cfg.BPType;
cfg.BHTEntries = CVA6Cfg.BHTEntries;
cfg.BHTHist = CVA6Cfg.BHTHist;
cfg.DmBaseAddress = CVA6Cfg.DmBaseAddress;
cfg.TvalEn = CVA6Cfg.TvalEn;
cfg.DirectVecOnly = CVA6Cfg.DirectVecOnly;
Expand Down
12 changes: 12 additions & 0 deletions core/include/config_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ package config_pkg;
HPDCACHE_WT_WB = 4
} cache_type_t;

/// Branch predictor parameter
typedef enum logic {
BHT = 0, // Bimodal predictor
PH_BHT = 1 // Private History Bimodal predictor
} bp_type_t;

/// Data and Address length
typedef enum logic [3:0] {
ModeOff = 0,
Expand Down Expand Up @@ -214,8 +220,12 @@ package config_pkg;
int unsigned RASDepth;
// Branch target buffer entries
int unsigned BTBEntries;
// Branch predictor type
bp_type_t BPType;
// Branch history entries
int unsigned BHTEntries;
// Branch history bits
int unsigned BHTHist;
// MMU instruction TLB entries
int unsigned InstrTlbEntries;
// MMU data TLB entries
Expand Down Expand Up @@ -299,7 +309,9 @@ package config_pkg;
logic [63:0] ExceptionAddress;
int unsigned RASDepth;
int unsigned BTBEntries;
bp_type_t BPType;
int unsigned BHTEntries;
int unsigned BHTHist;
int unsigned InstrTlbEntries;
int unsigned DataTlbEntries;
bit unsigned UseSharedTlb;
Expand Down
2 changes: 2 additions & 0 deletions core/include/cv32a60x_config_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ package cva6_config_pkg;
ExceptionAddress: 64'h808,
RASDepth: unsigned'(2),
BTBEntries: unsigned'(0),
BPType: config_pkg::BHT,
BHTEntries: unsigned'(32),
BHTHist: unsigned'(3),
DmBaseAddress: 64'h0,
TvalEn: bit'(0),
DirectVecOnly: bit'(1),
Expand Down
2 changes: 2 additions & 0 deletions core/include/cv32a65x_config_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ package cva6_config_pkg;
ExceptionAddress: 64'h808,
RASDepth: unsigned'(2),
BTBEntries: unsigned'(0),
BPType: config_pkg::BHT,
BHTEntries: unsigned'(32),
BHTHist: unsigned'(3),
DmBaseAddress: 64'h0,
TvalEn: bit'(0),
DirectVecOnly: bit'(1),
Expand Down
4 changes: 4 additions & 0 deletions core/include/cv32a6_embedded_config_pkg_deprecated.sv
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ package cva6_config_pkg;
localparam CVA6ConfigRASDepth = 2;
localparam CVA6ConfigBTBEntries = 0;
localparam CVA6ConfigBHTEntries = 32;
localparam CVA6ConfigBHTHist = 3;
localparam config_pkg::bp_type_t CVA6ConfigBPType = config_pkg::BHT;

localparam CVA6ConfigTvalEn = 0;

Expand Down Expand Up @@ -117,7 +119,9 @@ package cva6_config_pkg;
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: CVA6ConfigBPType,
BHTEntries: unsigned'(CVA6ConfigBHTEntries),
BHTHist: unsigned'(CVA6ConfigBHTHist),
DmBaseAddress: 64'h0,
TvalEn: bit'(CVA6ConfigTvalEn),
DirectVecOnly: bit'(0),
Expand Down
4 changes: 4 additions & 0 deletions core/include/cv32a6_ima_sv32_fpga_config_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ package cva6_config_pkg;
localparam CVA6ConfigRASDepth = 2;
localparam CVA6ConfigBTBEntries = 32;
localparam CVA6ConfigBHTEntries = 128;
localparam CVA6ConfigBHTHist = 3;
localparam config_pkg::bp_type_t CVA6ConfigBPType = config_pkg::BHT;

localparam CVA6ConfigTvalEn = 1;

Expand Down Expand Up @@ -115,7 +117,9 @@ package cva6_config_pkg;
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: CVA6ConfigBPType,
BHTEntries: unsigned'(CVA6ConfigBHTEntries),
BHTHist: unsigned'(CVA6ConfigBHTHist),
DmBaseAddress: 64'h0,
TvalEn: unsigned'(CVA6ConfigTvalEn),
DirectVecOnly: bit'(0),
Expand Down
4 changes: 4 additions & 0 deletions core/include/cv32a6_imac_sv0_config_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ package cva6_config_pkg;
localparam CVA6ConfigRASDepth = 2;
localparam CVA6ConfigBTBEntries = 32;
localparam CVA6ConfigBHTEntries = 128;
localparam CVA6ConfigBHTHist = 3;
localparam config_pkg::bp_type_t CVA6ConfigBPType = config_pkg::BHT;

localparam CVA6ConfigTvalEn = 1;

Expand Down Expand Up @@ -115,7 +117,9 @@ package cva6_config_pkg;
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: CVA6ConfigBPType,
BHTEntries: unsigned'(CVA6ConfigBHTEntries),
BHTHist: unsigned'(CVA6ConfigBHTHist),
DmBaseAddress: 64'h0,
TvalEn: unsigned'(CVA6ConfigTvalEn),
DirectVecOnly: bit'(0),
Expand Down
4 changes: 4 additions & 0 deletions core/include/cv32a6_imac_sv32_config_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ package cva6_config_pkg;
localparam CVA6ConfigRASDepth = 2;
localparam CVA6ConfigBTBEntries = 32;
localparam CVA6ConfigBHTEntries = 128;
localparam CVA6ConfigBHTHist = 3;
localparam config_pkg::bp_type_t CVA6ConfigBPType = config_pkg::BHT;

localparam CVA6ConfigTvalEn = 1;

Expand Down Expand Up @@ -114,7 +116,9 @@ package cva6_config_pkg;
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: CVA6ConfigBPType,
BHTEntries: unsigned'(CVA6ConfigBHTEntries),
BHTHist: unsigned'(CVA6ConfigBHTHist),
DmBaseAddress: 64'h0,
TvalEn: bit'(CVA6ConfigTvalEn),
DirectVecOnly: bit'(0),
Expand Down
4 changes: 4 additions & 0 deletions core/include/cv32a6_imafc_sv32_config_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ package cva6_config_pkg;
localparam CVA6ConfigRASDepth = 2;
localparam CVA6ConfigBTBEntries = 32;
localparam CVA6ConfigBHTEntries = 128;
localparam CVA6ConfigBHTHist = 3;
localparam config_pkg::bp_type_t CVA6ConfigBPType = config_pkg::BHT;

localparam CVA6ConfigTvalEn = 1;

Expand Down Expand Up @@ -115,7 +117,9 @@ package cva6_config_pkg;
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: CVA6ConfigBPType,
BHTEntries: unsigned'(CVA6ConfigBHTEntries),
BHTHist: unsigned'(CVA6ConfigBHTHist),
DmBaseAddress: 64'h0,
TvalEn: bit'(CVA6ConfigTvalEn),
DirectVecOnly: bit'(0),
Expand Down
2 changes: 2 additions & 0 deletions core/include/cv64a60ax_config_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
ExceptionAddress: 64'h808,
RASDepth: unsigned'(4),
BTBEntries: unsigned'(16),
BPType: config_pkg::BHT,
BHTEntries: unsigned'(64),
BHTHist: unsigned'(3),
DmBaseAddress: 64'h0,
TvalEn: bit'(1),
DirectVecOnly: bit'(0),
Expand Down
4 changes: 4 additions & 0 deletions core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ package cva6_config_pkg;
localparam CVA6ConfigRASDepth = 2;
localparam CVA6ConfigBTBEntries = 32;
localparam CVA6ConfigBHTEntries = 128;
localparam CVA6ConfigBHTHist = 3;
localparam config_pkg::bp_type_t CVA6ConfigBPType = config_pkg::BHT;

localparam CVA6ConfigTvalEn = 1;

Expand Down Expand Up @@ -118,7 +120,9 @@ package cva6_config_pkg;
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: CVA6ConfigBPType,
BHTEntries: unsigned'(CVA6ConfigBHTEntries),
BHTHist: unsigned'(CVA6ConfigBHTHist),
DmBaseAddress: 64'h0,
TvalEn: bit'(CVA6ConfigTvalEn),
DirectVecOnly: bit'(0),
Expand Down
4 changes: 4 additions & 0 deletions core/include/cv64a6_imafdc_sv39_config_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ package cva6_config_pkg;
localparam CVA6ConfigRASDepth = 2;
localparam CVA6ConfigBTBEntries = 32;
localparam CVA6ConfigBHTEntries = 128;
localparam CVA6ConfigBHTHist = 3;
localparam config_pkg::bp_type_t CVA6ConfigBPType = config_pkg::BHT;

localparam CVA6ConfigTvalEn = 1;

Expand Down Expand Up @@ -118,7 +120,9 @@ package cva6_config_pkg;
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BPType: CVA6ConfigBPType,
BHTEntries: unsigned'(CVA6ConfigBHTEntries),
BHTHist: unsigned'(CVA6ConfigBHTHist),
DmBaseAddress: 64'h0,
TvalEn: bit'(CVA6ConfigTvalEn),
DirectVecOnly: bit'(0),
Expand Down
Loading

0 comments on commit 88ed8a7

Please sign in to comment.