Fix a minor bug in BHT

This commit is contained in:
zachzzc 2019-08-28 01:27:29 +08:00 committed by Florian Zaruba
parent f70c961e7a
commit c9537f8221
3 changed files with 15 additions and 15 deletions

View file

@ -24,14 +24,14 @@ module bht #(
input logic flush_ftq_i,
input logic debug_mode_i,
input logic [63:0] vpc_i,
input logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] push_instr_cnt_i,
input logic instr_queue_overflow_i,
input logic [63:0] instr_queue_replay_addr_i,
input logic serving_unaligned_i, // we have an unalinged instruction at the beginning
input ariane_pkg::bht_update_t bht_update_i,
input logic [ariane_pkg::INSTR_PER_FETCH-1:0] valid_i,
input logic [ariane_pkg::INSTR_PER_FETCH-1:0] is_branch_i,
input logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken_rvi_cf_i,
input logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken_rvc_cf_i,
input cf_t [ariane_pkg::INSTR_PER_FETCH-1:0] cf_type_i,
output logic ftq_overflow_o,
// we potentially need INSTR_PER_FETCH predictions/cycle
output ariane_pkg::bht_prediction_t [ariane_pkg::INSTR_PER_FETCH-1:0] bht_prediction_o
@ -74,7 +74,6 @@ module bht #(
logic [ariane_pkg::INSTR_PER_FETCH-1:0] valid_taken_cf;
logic [ariane_pkg::INSTR_PER_FETCH-1:0] is_replay; // replay logic per instruction
logic [ariane_pkg::INSTR_PER_FETCH-1:0] is_valid_branch;
logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] replay_pos;
// fetch target queue signals
logic [$clog2(ariane_pkg::FETCH_FIFO_DEPTH)-1:0] ftq_usage;
@ -113,8 +112,6 @@ module bht #(
end
end
// check if the instructions are valid control flows
assign valid_taken_cf = valid_i & (taken_rvc_cf_i | taken_rvi_cf_i);
// realigned pc address to fetch block width
assign realigned_vpc = {vpc_i[63:ROW_ADDR_BITS+1], (ROW_ADDR_BITS+1)'(0)};
assign ftq_entry_i = { gshare_index, // gshare index
@ -124,25 +121,25 @@ module bht #(
};
assign push_ftq = (|is_valid_branch);
assign realigned_update_pc = bht_update_i.pc + (1<<$clog2(ariane_pkg::INSTR_PER_FETCH));
assign is_unaligned_instr = ftq_entry_o.serving_unaligned
& (bht_update_i.pc[ROW_ADDR_BITS + OFFSET - 1:OFFSET] == {ROW_ADDR_BITS{1'b1}});
assign realigned_update_pc = bht_update_i.pc + 2;
assign is_unaligned_instr = ftq_entry_o.serving_unaligned & (&bht_update_i.pc[ROW_ADDR_BITS + OFFSET - 1:OFFSET]);
assign pop_ftq = bht_update_i.valid & ((bp_count_q == 1) || ftq_entry_o.bp_count == 1);
assign update_row_index = is_unaligned_instr ? 0 : bht_update_i.pc[ROW_ADDR_BITS + OFFSET - 1:OFFSET];
assign update_pc = ftq_entry_o.gshare_index;
assign ftq_overflow_o = full_ftq & push_ftq;
// if replay starts from an unaglined address, replay position should be 0.
assign replay_pos = serving_unaligned_i ? 0 : instr_queue_replay_addr_i[$clog2(ariane_pkg::INSTR_PER_FETCH):1];
// if the incoming instruction is a replay at the replay address, then the rest of the fetched
// instruction should also be replay. For example, in 64 bit fetch if the replay starts from 0x42,
// the replay mask should be 1 1 1 0 from the highest to lowest.
assign is_replay = {ariane_pkg::INSTR_PER_FETCH{instr_queue_overflow_i}} << replay_pos;
assign is_replay = {ariane_pkg::INSTR_PER_FETCH{instr_queue_overflow_i}} << push_instr_cnt_i;
// an instruction is a valid branch instruction to push to fetch target queue if:
// 1) it is a valid branch instruction
// 2) it is not a replay
// 3) no taken control flow before it in the same fetch block
for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin
// check if the instructions are valid control flows
assign valid_taken_cf[i] = valid_i[i] & (cf_type_i[i] != ariane_pkg::NoCF);
if (i == 0) begin
assign is_valid_branch[i] = is_branch_i[i] & ~is_replay[i];
end else begin
@ -217,8 +214,7 @@ module bht #(
bht_d[update_pc][update_row_index].saturation_counter = 2'b01;
else
bht_d[update_pc][update_row_index].saturation_counter = 2'b10;
end else
if (saturation_counter == 2'b11) begin
end else 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 = saturation_counter - 1;

View file

@ -68,6 +68,7 @@ module frontend #(
logic [63:0] replay_addr;
logic [63:0] instr_queue_replay_addr;
logic instr_queue_overflow, ftq_overflow;
logic [$clog2(INSTR_PER_FETCH)-1:0] push_instr_cnt;
// replay if any of the queue overflows
assign replay = instr_queue_overflow | ftq_overflow;
assign replay_addr = ftq_overflow ? addr[0] : instr_queue_replay_addr;
@ -388,13 +389,13 @@ module frontend #(
.flush_ftq_i ( flush_i ),
.debug_mode_i,
.vpc_i ( icache_vaddr_q ),
.push_instr_cnt_i ( push_instr_cnt ),
.instr_queue_overflow_i ( instr_queue_overflow ), // from instruction queue
.instr_queue_replay_addr_i ( instr_queue_replay_addr ),
.is_branch_i ( is_branch ),
.valid_i ( instruction_valid ),
.serving_unaligned_i ( serving_unaligned ),
.taken_rvc_cf_i ( taken_rvc_cf ),
.taken_rvi_cf_i ( taken_rvi_cf ),
.cf_type_i ( cf_type ),
.bht_update_i ( bht_update ),
.ftq_overflow_o ( ftq_overflow ),
.bht_prediction_o ( bht_prediction )
@ -432,6 +433,7 @@ module frontend #(
.cf_type_i ( cf_type ),
.valid_i ( instruction_valid ), // from re-aligner
.consumed_o ( instr_queue_consumed ),
.push_instr_cnt_o ( push_instr_cnt ),
.ftq_overflow_i ( ftq_overflow ), // from branch predictor
.ready_o ( instr_queue_ready ),
.overflow_o ( instr_queue_overflow ),

View file

@ -61,6 +61,7 @@ module instr_queue (
input logic ftq_overflow_i,
// replay instruction because one of the FIFO was already full
output logic overflow_o,
output logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] push_instr_cnt_o,
output logic [63:0] replay_addr_o, // address at which to replay this instruction
// to processor backend
output ariane_pkg::fetch_entry_t fetch_entry_o,
@ -154,6 +155,7 @@ module instr_queue (
.popcount_o ( popcount )
);
assign shamt = popcount[$bits(shamt)-1:0];
assign push_instr_cnt_o = shamt_push_instr;
// save the shift amount for next cycle
assign idx_is_d = idx_is_q + shamt;