diff --git a/src/ariane.sv b/src/ariane.sv index a932a042ca911408047f81aac477d1b99d94a6e0..b1a75757d1b8d4bb941de06978d04bda0787b5d2 100644 --- a/src/ariane.sv +++ b/src/ariane.sv @@ -80,6 +80,7 @@ module ariane import ariane_pkg::*; #( // IF -> verifier // -------------- logic has_mem_access_if_verif; + logic has_ctrl_flow_if_icache; logic bsp_if_perf; // -------------- @@ -280,6 +281,7 @@ module ariane import ariane_pkg::*; #( .fetch_entry_valid_o ( fetch_valid_if_id ), .fetch_entry_ready_i ( fetch_ready_id_if ), .has_mem_access_o ( has_mem_access_if_verif ), + .has_cf_o ( has_ctrl_flow_if_icache ), .branch_speculation_o( bsp_if_perf ), .* ); diff --git a/src/frontend/frontend.sv b/src/frontend/frontend.sv index 991db6561e8205fbc641e80476b390c316ebeb6f..75226d9345152a067895f1e8cbc0ca7eb374308b 100644 --- a/src/frontend/frontend.sv +++ b/src/frontend/frontend.sv @@ -46,7 +46,8 @@ module frontend import ariane_pkg::*; #( input logic fetch_entry_ready_i, // ID acknowledged this instruction output logic has_mem_access_o, - output logic branch_speculation_o + output logic branch_speculation_o, + output logic has_cf_o ); // Instruction Cache Registers, from I$ logic [FETCH_WIDTH-1:0] icache_data_q; @@ -434,7 +435,8 @@ module frontend import ariane_pkg::*; #( .fetch_entry_o ( fetch_entry_o ), // to back-end .fetch_entry_valid_o ( fetch_entry_valid_o ), // to back-end .fetch_entry_ready_i ( fetch_entry_ready_i ), // to back-end - .has_mem_access_o ( has_mem_access_o ) // to verifier + .has_mem_access_o ( has_mem_access_o ), // to verifier + .has_cf_o ( has_cf_o ) // to I$ ); // pragma translate_off diff --git a/src/frontend/instr_queue.sv b/src/frontend/instr_queue.sv index 15f3269db11af574f1296eecdccb19eab4892fdd..a31b096b995398fe8ee42f00933db9592f0581cc 100644 --- a/src/frontend/instr_queue.sv +++ b/src/frontend/instr_queue.sv @@ -66,7 +66,8 @@ module instr_queue ( output logic fetch_entry_valid_o, input logic fetch_entry_ready_i, - output logic has_mem_access_o + output logic has_mem_access_o, + output logic has_cf_o ); typedef struct packed { @@ -125,6 +126,11 @@ module instr_queue ( logic [ariane_pkg::INSTR_PER_FETCH-1:0] fifo_output_is_mem, fifo_has_no_mem; logic output_is_mem; + // cf count + logic [ariane_pkg::INSTR_PER_FETCH-1:0] input_is_cf; + logic [ariane_pkg::INSTR_PER_FETCH-1:0] fifo_has_no_cf; + logic output_is_cf; + assign ready_o = ~(|instr_queue_full) & ~full_address; for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_unpack_taken @@ -199,6 +205,15 @@ module instr_queue ( assign has_mem_access_o = (|input_is_mem[ariane_pkg::INSTR_PER_FETCH-1:0]) | output_is_mem | ~(&fifo_has_no_mem); + // ---------------------- + // Memory access detector + // ---------------------- + assign output_is_cf = fetch_entry_valid_o & + (fetch_entry_o.instruction[6:0] inside {riscv::OpcodeJalr, riscv::OpcodeBranch}); + + assign has_cf_o = (|input_is_cf) | output_is_cf | + ~(&fifo_has_no_cf); + // duplicate the entries for easier selection e.g.: 3 2 1 0 3 2 1 0 for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_duplicate_instr_input assign instr[i] = instr_i[i]; @@ -215,6 +230,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}); /* verilator lint_on WIDTH */ end @@ -330,6 +346,8 @@ 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) @@ -346,6 +364,23 @@ module instr_queue ( .data_o (), .pop_i (pop_instr[i] & fifo_output_is_mem[i]) ); + + fifo_v3 #( + .DEPTH (ariane_pkg::FETCH_FIFO_DEPTH), + .dtype (logic) + ) i_fifo_cf ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .flush_i (flush_i), + .testmode_i (1'b0), + .full_o (), + .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})), + .data_o (), + .pop_i (pop_instr[i] & fifo_output_is_cf[i]) + ); end // or reduce and check whether we are retiring a taken branch (might be that the corresponding) // fifo is full.