mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 13:47:13 -04:00
Move branch comparisons to branch engine
This commit is contained in:
parent
5ffb9ef36c
commit
ea8fde0a3f
2 changed files with 32 additions and 13 deletions
|
@ -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;
|
||||
|
|
|
@ -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 ),
|
||||
.*
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue