diff --git a/src/frontend/frontend.sv b/src/frontend/frontend.sv index 75226d9345152a067895f1e8cbc0ca7eb374308b..d38908a636f44487628f921d32639696dc87f803 100644 --- a/src/frontend/frontend.sv +++ b/src/frontend/frontend.sv @@ -146,6 +146,7 @@ module frontend import ariane_pkg::*; #( logic [INSTR_PER_FETCH-1:0] is_jump; logic [INSTR_PER_FETCH-1:0] is_return; logic [INSTR_PER_FETCH-1:0] is_jalr; + logic [INSTR_PER_FETCH-1:0] is_cf; for (genvar i = 0; i < INSTR_PER_FETCH; i++) begin // branch history table -> BHT @@ -158,6 +159,9 @@ module frontend import ariane_pkg::*; #( assign is_jump[i] = instruction_valid[i] & (rvi_jump[i] | rvc_jump[i]); // unconditional jumps with unknown target -> BTB assign is_jalr[i] = instruction_valid[i] & ~is_return[i] & ~is_call[i] & (rvi_jalr[i] | rvc_jalr[i] | rvc_jr[i]); + + // cf that needs a prediction + assign is_cf[i] = instruction_valid[i] & (rvi_branch[i] | rvc_branch[i] | rvi_jalr[i] | rvc_jalr[i] | rvc_jr[i]); end // taken/not taken @@ -423,6 +427,7 @@ module frontend import ariane_pkg::*; #( .flush_i ( flush_i ), .instr_i ( instr ), // from re-aligner .addr_i ( addr ), // from re-aligner + .is_cf_i ( is_cf ), .exception_i ( icache_ex_valid_q ), // from I$ .exception_addr_i ( icache_vaddr_q ), .predict_address_i ( predict_address ), diff --git a/src/frontend/instr_queue.sv b/src/frontend/instr_queue.sv index a31b096b995398fe8ee42f00933db9592f0581cc..51c612624865dd19ef3ae4201c6338f018fd0759 100644 --- a/src/frontend/instr_queue.sv +++ b/src/frontend/instr_queue.sv @@ -49,6 +49,7 @@ module instr_queue ( input logic flush_i, input logic [ariane_pkg::INSTR_PER_FETCH-1:0][31:0] instr_i, input logic [ariane_pkg::INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr_i, + input logic [ariane_pkg::INSTR_PER_FETCH-1:0] is_cf_i, input logic [ariane_pkg::INSTR_PER_FETCH-1:0] valid_i, output logic ready_o, output logic [ariane_pkg::INSTR_PER_FETCH-1:0] consumed_o, @@ -73,6 +74,7 @@ module instr_queue ( typedef struct packed { logic [31:0] instr; // instruction word ariane_pkg::cf_t cf; // branch was taken + logic is_cf; // instruction is a cf that needs a prediction (ie. not a jump) ariane_pkg::frontend_exception_t ex; // exception happened logic [riscv::VLEN-1:0] ex_vaddr; // lower VLEN bits of tval for exception } instr_data_t; @@ -127,7 +129,7 @@ module instr_queue ( logic output_is_mem; // cf count - logic [ariane_pkg::INSTR_PER_FETCH-1:0] input_is_cf; + logic [ariane_pkg::INSTR_PER_FETCH*2-1:0] input_is_cf; logic [ariane_pkg::INSTR_PER_FETCH-1:0] fifo_has_no_cf; logic output_is_cf; @@ -220,6 +222,8 @@ module instr_queue ( assign instr[i + ariane_pkg::INSTR_PER_FETCH] = instr_i[i]; assign cf[i] = cf_type_i[i]; assign cf[i + ariane_pkg::INSTR_PER_FETCH] = cf_type_i[i]; + assign input_is_cf[i] = is_cf_i[i]; + assign input_is_cf[i + ariane_pkg::INSTR_PER_FETCH] = is_cf_i[i]; end // shift the inputs @@ -230,7 +234,7 @@ module instr_queue ( assign instr_data_in[i].ex = exception_i; // exceptions hold for the whole fetch packet assign instr_data_in[i].ex_vaddr = exception_addr_i; assign input_is_mem_in[i] = input_is_mem[i + idx_is_q]; - assign input_is_cf[i] = !(cf[i + idx_is_q] inside {ariane_pkg::NoCF, ariane_pkg::Jump}); + assign instr_data_in[i].is_cf = input_is_cf[i + idx_is_q]; /* verilator lint_on WIDTH */ end @@ -346,8 +350,6 @@ module instr_queue ( (instr_data_out[i].instr[6:0] == riscv::OpcodeStoreFp) | (instr_data_out[i].instr[6:0] == riscv::OpcodeAmo)); - assign fifo_output_is_cf[i] = !(instr_data_out[i].cf inside {ariane_pkg::NoCF, ariane_pkg::Jump}); - fifo_v3 #( .DEPTH ( ariane_pkg::FETCH_FIFO_DEPTH ), .dtype (logic) @@ -377,9 +379,9 @@ module instr_queue ( .empty_o (fifo_has_no_cf[i]), .usage_o (), .data_i (1'b1), - .push_i (push_instr_fifo[i] & !(instr_data_in[i].cf inside {ariane_pkg::NoCF, ariane_pkg::Jump})), + .push_i (push_instr_fifo[i] & instr_data_in[i].is_cf), .data_o (), - .pop_i (pop_instr[i] & fifo_output_is_cf[i]) + .pop_i (pop_instr[i] & instr_data_out[i].is_cf) ); end // or reduce and check whether we are retiring a taken branch (might be that the corresponding)