Move branch comparisons to branch engine

This commit is contained in:
Florian Zaruba 2017-05-12 12:22:56 +02:00
parent 5ffb9ef36c
commit ea8fde0a3f
2 changed files with 32 additions and 13 deletions

View file

@ -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;

View file

@ -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 ),
.*
);