diff --git a/src/frontend/frontend.sv b/src/frontend/frontend.sv index 1cb10c1d9d6c618d5819604052574245e2b9e50c..821792c24afad9efed81151f6d06e629cb8a5a52 100644 --- a/src/frontend/frontend.sv +++ b/src/frontend/frontend.sv @@ -89,7 +89,9 @@ module frontend import ariane_pkg::*; #( // re-aligned instruction and address (coming from cache - combinationally) logic [INSTR_PER_FETCH-1:0][31:0] instr; logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr; - logic [INSTR_PER_FETCH-1:0] instruction_valid; + logic [INSTR_PER_FETCH-1:0] instruction_valid, instruction_really_valid; + logic [INSTR_PER_FETCH-1:0] instr_really_valid; + // BHT, BTB and RAS prediction bht_prediction_t [INSTR_PER_FETCH-1:0] bht_prediction; btb_prediction_t [INSTR_PER_FETCH-1:0] btb_prediction; @@ -239,13 +241,28 @@ module frontend import ariane_pkg::*; #( end end end + + logic has_speculative; + // or reduce struct always_comb begin bp_valid = 1'b0; + has_speculative = 1'b0; + instruction_really_valid = '0; + // BP cannot be valid if we have a return instruction and the RAS is not giving a valid address // Check that we encountered a control flow and that for a return the RAS // contains a valid prediction. - for (int i = 0; i < INSTR_PER_FETCH; i++) bp_valid |= ((cf_type[i] != NoCF & cf_type[i] != Return) | ((cf_type[i] == Return) & ras_predict.valid)); + for (int unsigned i = 0; i < INSTR_PER_FETCH; i++) begin + bp_valid |= ((cf_type[i] != NoCF & cf_type[i] != Return) | ((cf_type[i] == Return) & ras_predict.valid)); + has_speculative |= (!(cf_type[i] inside {NoCF, Return, Jump}) | ((cf_type[i] == Return) & ras_predict.valid)); + + if (enable_bp_i) begin + instruction_really_valid[i] = instruction_valid[i]; + end else begin + instruction_really_valid[i] = instruction_really_valid[i] && !(has_speculative); + end + end end assign is_mispredict = resolved_branch_i.valid & resolved_branch_i.is_mispredict; @@ -434,7 +451,7 @@ module frontend import ariane_pkg::*; #( .exception_addr_i ( icache_vaddr_q ), .predict_address_i ( predict_address ), .cf_type_i ( cf_type ), - .valid_i ( instruction_valid ), // from re-aligner + .valid_i ( instruction_really_valid ), // from re-aligner .consumed_o ( instr_queue_consumed ), .ready_o ( instr_queue_ready ), .replay_o ( replay ),