diff --git a/src/btb.sv b/src/btb.sv index e68caaf40..88df84aff 100644 --- a/src/btb.sv +++ b/src/btb.sv @@ -46,13 +46,11 @@ module btb #( logic [$clog2(NR_ENTRIES)-1:0] index, update_pc; logic [BITS_SATURATION_COUNTER-1:0] saturation_counter; - // branch-predict input register - branchpredict branch_predict_q; // get actual index positions // we ignore the 0th bit since all instructions are aligned on // a half word boundary - assign update_pc = branch_predict_q.pc[$clog2(NR_ENTRIES) + OFFSET - 1:OFFSET]; + assign update_pc = branch_predict_i.pc[$clog2(NR_ENTRIES) + OFFSET - 1:OFFSET]; assign index = vpc_i[$clog2(NR_ENTRIES) + OFFSET - 1:OFFSET]; // we combinatorially predict the branch and the target address @@ -66,32 +64,32 @@ module btb #( btb_n = btb_q; saturation_counter = btb_q[update_pc].saturation_counter; - if (branch_predict_q.valid) begin + if (branch_predict_i.valid) begin btb_n[update_pc].valid = 1'b1; // update saturation counter // first check if counter is already saturated in the positive regime e.g.: branch taken if (saturation_counter == {BITS_SATURATION_COUNTER{1'b1}}) begin // we can safely decrease it - if (~branch_predict_q.is_taken) + if (~branch_predict_i.is_taken) btb_n[update_pc].saturation_counter = saturation_counter - 1; // then check if it saturated in the negative regime e.g.: branch not taken end else if (saturation_counter == {BITS_SATURATION_COUNTER{1'b0}}) begin // we can safely increase it - if (branch_predict_q.is_taken) + if (branch_predict_i.is_taken) btb_n[update_pc].saturation_counter = saturation_counter + 1; end else begin // otherwise we are not in any boundaries and can decrease or increase it - if (branch_predict_q.is_taken) + if (branch_predict_i.is_taken) btb_n[update_pc].saturation_counter = saturation_counter + 1; else btb_n[update_pc].saturation_counter = saturation_counter - 1; end // the target address is simply updated - btb_n[update_pc].target_address = branch_predict_q.target_address; + btb_n[update_pc].target_address = branch_predict_i.target_address; // as is the information whether this was a compressed branch - btb_n[update_pc].is_lower_16 = branch_predict_q.is_lower_16; + btb_n[update_pc].is_lower_16 = branch_predict_i.is_lower_16; // check if we should invalidate this entry, this happens in case we predicted a branch // where actually none-is (aliasing) - if (branch_predict_q.clear) begin + if (branch_predict_i.clear) begin btb_n[update_pc].valid = 1'b0; end end @@ -103,8 +101,6 @@ module btb #( // Bias the branches to be taken upon first arrival for (int i = 0; i < NR_ENTRIES; i++) btb_q[i] <= '{1'b0, 64'b0, 2'b10, 1'b0}; - - branch_predict_q <= '0; end else begin // evict all entries if (flush_i) begin @@ -115,7 +111,7 @@ module btb #( end else begin btb_q <= btb_n; end - branch_predict_q <= branch_predict_i; + end end endmodule \ No newline at end of file diff --git a/src/issue_read_operands.sv b/src/issue_read_operands.sv index b76fa19b4..8b3987d41 100644 --- a/src/issue_read_operands.sv +++ b/src/issue_read_operands.sv @@ -338,7 +338,7 @@ module issue_read_operands ( `ifndef verilator assert property ( @(posedge clk_i) (alu_valid_q || lsu_valid_q || csr_valid_q) |-> (!$isunknown(operand_a_q) && !$isunknown(operand_b_q))) - else $error ("Got unknown value in one of the operands"); + else $warning ("Got unknown value in one of the operands"); `endif `endif endmodule diff --git a/src/pcgen.sv b/src/pcgen.sv index 5fb12d406..5b36f4a3d 100644 --- a/src/pcgen.sv +++ b/src/pcgen.sv @@ -44,9 +44,10 @@ module pcgen ( ); logic [63:0] npc_n, npc_q; + logic set_pc_n, set_pc_q; branchpredict_sbe branch_predict_btb; - - assign fetch_address_o = npc_q; + // branch-predict input register -> this path is critical + branchpredict resolved_branch_q; btb #( .NR_ENTRIES ( BTB_ENTRIES ), @@ -57,7 +58,7 @@ module pcgen ( // Use the PC from last cycle to perform branch lookup for the current cycle .flush_i ( flush_bp_i ), .vpc_i ( npc_q ), - .branch_predict_i ( resolved_branch_i ), // update port + .branch_predict_i ( resolved_branch_q ), // update port .branch_predict_o ( branch_predict_btb ), // read port .* ); @@ -73,8 +74,12 @@ module pcgen ( // 5. Return from exception // 6. Pipeline Flush because of CSR side effects always_comb begin : npc_select + // set fetch address + fetch_address_o = npc_q; branch_predict_o = branch_predict_btb; fetch_valid_o = 1'b1; + // this tells us whether it is a consecutive PC or a completely new PC + set_pc_n = 1'b0; // ------------------------------- // 0. Default assignment @@ -103,9 +108,11 @@ module pcgen ( // ------------------------------- // 3. Control flow change request // ------------------------------- - if (resolved_branch_i.is_mispredict) begin + // check if had a mis-predict the cycle earlier and if we can reset the PC (e.g.: it was a predicted or consecutive PC + // which was set a cycle earlier) + if (resolved_branch_q.is_mispredict && !set_pc_q) begin // we already got the correct target address - npc_n = resolved_branch_i.target_address; + fetch_address_o = resolved_branch_q.target_address; end // ------------------------------- @@ -114,6 +121,7 @@ module pcgen ( if (ex_i.valid) begin npc_n = trap_vector_base_i; branch_predict_o.valid = 1'b0; + set_pc_n = 1'b1; end // ------------------------------- @@ -121,6 +129,7 @@ module pcgen ( // ------------------------------- if (eret_i) begin npc_n = epc_i; + set_pc_n = 1'b1; end // ----------------------------------------------- @@ -133,6 +142,7 @@ module pcgen ( // as CSR instructions do not exist in a compressed form // we can unconditionally do PC + 4 here npc_n = pc_commit_i + 64'h4; + set_pc_n = 1'b1; end // fetch enable @@ -146,9 +156,13 @@ module pcgen ( // PCGEN -> IF Pipeline Stage always_ff @(posedge clk_i or negedge rst_ni) begin if(~rst_ni) begin - npc_q <= boot_addr_i; + npc_q <= boot_addr_i; + set_pc_q <= 1'b0; + resolved_branch_q <= '0; end else begin - npc_q <= npc_n; + npc_q <= npc_n; + set_pc_q <= set_pc_n; + resolved_branch_q <= resolved_branch_i; end end