diff --git a/src/branch_engine.sv b/src/branch_engine.sv index 6eecc2227..3542b45e9 100644 --- a/src/branch_engine.sv +++ b/src/branch_engine.sv @@ -20,13 +20,15 @@ import ariane_pkg::*; module branch_engine ( + input fu_op operator_i, input logic [63:0] operand_a_i, input logic [63:0] operand_b_i, + input logic [63:0] operand_c_i, + input logic [63:0] imm_i, input logic [63:0] pc_i, input logic is_compressed_instr_i, input logic valid_i, - input logic comparison_result_i, // result of comparison input logic [63:0] predict_address_i, // this is the address we predicted input logic predict_branch_valid_i, // we predicted that this was a valid branch input logic predict_taken_i, @@ -35,6 +37,28 @@ module branch_engine ( ); logic [63:0] target_address; logic [63:0] next_pc; + logic comparison_result; // result of comparison + logic sgn; // sign extend + + always_comb begin : branch_resolve + // by default e.g.: when this is a jump, the branch is taken + // so set the comparison result to 1 + comparison_result = 1'b1; + // sign switch + sgn = 1'b1; + // if this is an unsigned operation clear the sign bit + // this should ease data-path extraction + if (operator_i inside {LTU, GEU}) + sgn = 1'b0; + // get the right comparison result + case (operator_i) + EQ: comparison_result = operand_a_i == operand_b_i; + NE: comparison_result = operand_a_i != operand_b_i; + LTS: comparison_result = ($signed({sgn & operand_a_i[63], operand_a_i}) < $signed({sgn & operand_b_i[63], operand_b_i})); + GES: comparison_result = ($signed({sgn & operand_a_i[63], operand_a_i}) >= $signed({sgn & operand_b_i[63], operand_b_i})); + default: comparison_result = 1'b1; + endcase + end always_comb begin : target_address_calc target_address = 64'b0; @@ -46,19 +70,19 @@ module branch_engine ( // calculate next PC, depending on whether the instruction is compressed or not this may be different next_pc = pc_i + (is_compressed_instr_i) ? 64'h2 : 64'h4; // calculate target address simple 64 bit addition - target_address = $signed(operand_a_i) + $signed(operand_b_i); + target_address = $signed(operand_c_i) + $signed(imm_i); // save pc branchpredict_o.pc = pc_i; // write target address which goes to pc gen - branchpredict_o.target_address = (comparison_result_i) ? target_address : next_pc; - branchpredict_o.is_taken = comparison_result_i; + branchpredict_o.target_address = (comparison_result) ? target_address : next_pc; + branchpredict_o.is_taken = comparison_result; if (valid_i) begin // we mis-predicted e.g.: the predicted address is unequal to the actual address if (target_address[1:0] == 2'b0) begin // TODO in case of branch which is not taken it is not necessary to check for the address if ( target_address != predict_address_i // we mis-predicted the address of the branch - || predict_taken_i != comparison_result_i // we mis-predicted the outcome of the branch + || predict_taken_i != comparison_result // we mis-predicted the outcome of the branch || predict_branch_valid_i == 1'b0 // this means branch-prediction thought it was no branch but in reality it was one ) begin branchpredict_o.is_mispredict = 1'b1; diff --git a/src/ex_stage.sv b/src/ex_stage.sv index 81b212739..e0d99af37 100644 --- a/src/ex_stage.sv +++ b/src/ex_stage.sv @@ -43,11 +43,11 @@ module ex_stage #( output logic [TRANS_ID_BITS-1:0] alu_trans_id_o, // ID of scoreboard entry at which to write back output exception alu_exception_o, // Branches and Jumps - input logic branch_valid_i, + input logic branch_valid_i, // we are using the branch unit input logic predict_branch_valid_i, input logic [63:0] predict_address_i, input logic predict_taken_i, - output branchpredict branchpredict_o, + output branchpredict branchpredict_o, // the branch engine uses the write back from the ALU // LSU output logic lsu_ready_o, // FU is ready input logic lsu_valid_i, // Input is valid @@ -99,8 +99,6 @@ module ex_stage #( output logic mult_ready_o, // FU is ready input logic mult_valid_i // Output is valid ); - // Wires - logic comparison_result_alu_branch; // ALU is a single cycle instructions, hence it is always ready assign alu_ready_o = 1'b1; @@ -113,8 +111,8 @@ module ex_stage #( .adder_result_o ( ), .adder_result_ext_o ( ), .result_o ( alu_result_o ), - .comparison_result_o ( comparison_result_alu_branch ), .is_equal_result_o ( ), + .comparison_result_o( ), .* ); @@ -122,10 +120,7 @@ module ex_stage #( // Branch Engine // -------------------- branch_engine branch_engine_i ( - .operand_a_i ( operand_c_i ), - .operand_b_i ( imm_i ), .valid_i ( branch_valid_i ), - .comparison_result_i ( comparison_result_alu_branch ), .branch_ex_o ( alu_exception_o ), .* );