Merge pull request #15 from raulbehl/alu_brn_resolve

✂️ Changes for #1
This commit is contained in:
Florian Zaruba 2018-03-06 17:48:43 +01:00 committed by GitHub
commit c74bb21d21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 28 deletions

View file

@ -27,6 +27,7 @@ module alu
input logic [63:0] operand_a_i,
input logic [63:0] operand_b_i,
output logic [63:0] result_o,
output logic alu_branch_res_o,
output logic alu_valid_o,
output logic alu_ready_o,
output logic [TRANS_ID_BITS-1:0] alu_trans_id_o
@ -41,6 +42,8 @@ module alu
logic [31:0] operand_a_rev32;
logic [64:0] operand_b_neg;
logic [65:0] adder_result_ext_o;
logic less; // handles both signed and unsigned forms
// bit reverse operand_a for left shifts and bit counting
generate
genvar k;
@ -55,6 +58,7 @@ module alu
// Adder
// ------
logic adder_op_b_negate;
logic adder_z_flag;
logic [64:0] adder_in_a, adder_in_b;
logic [63:0] adder_result;
@ -63,6 +67,7 @@ module alu
unique case (operator_i)
// ADDER OPS
EQ, NE,
SUB, SUBW: adder_op_b_negate = 1'b1;
default: ;
@ -79,6 +84,20 @@ module alu
// actual adder
assign adder_result_ext_o = $unsigned(adder_in_a) + $unsigned(adder_in_b);
assign adder_result = adder_result_ext_o[64:1];
assign adder_z_flag = ~|adder_result;
// get the right branch comparison result
always_comb begin : branch_resolve
// set comparison by default
alu_branch_res_o = 1'b1;
case (operator_i)
EQ: alu_branch_res_o = adder_z_flag;
NE: alu_branch_res_o = ~adder_z_flag;
LTS, LTU: alu_branch_res_o = less;
GES, GEU: alu_branch_res_o = ~less;
default: alu_branch_res_o = 1'b1;
endcase
end
// ---------
// Shifts
@ -138,14 +157,14 @@ module alu
// ------------
// Comparisons
// ------------
logic less; // handles both signed and unsigned forms
always_comb begin
logic sgn;
sgn = 1'b0;
if (operator_i == SLTS)
if ((operator_i == SLTS) ||
(operator_i == LTS) ||
(operator_i == GES))
sgn = 1'b1;
less = ($signed({sgn & operand_a_i[63], operand_a_i}) < $signed({sgn & operand_b_i[63], operand_b_i}));

View file

@ -123,6 +123,7 @@ module ariane #(
logic [TRANS_ID_BITS-1:0] alu_trans_id_ex_id;
logic alu_valid_ex_id;
logic [63:0] alu_result_ex_id;
logic alu_branch_res_ex_id;
exception_t alu_exception_ex_id;
// Branches and Jumps
logic branch_ready_ex_id;
@ -421,6 +422,7 @@ module ariane #(
.alu_result_o ( alu_result_ex_id ),
.alu_trans_id_o ( alu_trans_id_ex_id ),
.alu_valid_o ( alu_valid_ex_id ),
.alu_branch_res_o ( alu_branch_res_ex_id ),
.alu_exception_o ( ),
// Branches and Jumps
.branch_ready_o ( branch_ready_ex_id ),

View file

@ -24,6 +24,7 @@ module branch_unit (
input logic is_compressed_instr_i,
input logic fu_valid_i, // any functional unit is valid, check that there is no accidental mis-predict
input logic branch_valid_i,
input logic branch_comp_res_i, // branch comparison result from ALU
output logic branch_ready_o,
output logic branch_valid_o,
output logic [63:0] branch_result_o,
@ -37,32 +38,11 @@ module branch_unit (
);
logic [63:0] target_address;
logic [63:0] next_pc;
logic comparison_result; // result of comparison
logic sgn; // sign extend
// branches are single cycle at the moment, feed-through the control signals
assign branch_trans_id_o = trans_id_i;
assign branch_valid_o = branch_valid_i;
assign branch_ready_o = 1'b1; // we are always ready
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, LTU: comparison_result = ($signed({sgn & operand_a_i[63], operand_a_i}) < $signed({sgn & operand_b_i[63], operand_b_i}));
GES, GEU: 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
// here we handle the various possibilities of mis-predicts
always_comb begin : mispredict_handler
// set the jump base, for JALR we need to look at the register, for all other control flow instructions we can take the current PC
@ -104,15 +84,15 @@ module branch_unit (
// the other case is a misaligned uncompressed instruction which we only predict in the next cycle (see notes above)
resolved_branch_o.is_lower_16 = (is_compressed_instr_i && pc_i[1] == 1'b0) || (!is_compressed_instr_i && pc_i[1] == 1'b1);
// write target address which goes to pc gen
resolved_branch_o.target_address = (comparison_result) ? target_address : next_pc;
resolved_branch_o.is_taken = comparison_result;
resolved_branch_o.target_address = (branch_comp_res_i) ? target_address : next_pc;
resolved_branch_o.is_taken = branch_comp_res_i;
// we've detected a branch in ID with the following parameters
// we mis-predicted e.g.: the predicted address is unequal to the actual address
if (target_address[0] == 1'b0) begin
// we've got a valid branch prediction
if (branch_predict_i.valid) begin
// if the outcome doesn't match we've got a mis-predict
if (branch_predict_i.predict_taken != comparison_result) begin
if (branch_predict_i.predict_taken != branch_comp_res_i) begin
resolved_branch_o.is_mispredict = 1'b1;
end
// check if the address of the predict taken branch is correct
@ -122,7 +102,7 @@ module branch_unit (
// branch-prediction didn't do anything (e.g.: it fetched PC + 2/4), so if this branch is taken
// we also have a mis-predict
end else begin
if (comparison_result) begin
if (branch_comp_res_i) begin
resolved_branch_o.is_mispredict = 1'b1;
end
end

View file

@ -38,6 +38,7 @@ module ex_stage #(
output logic alu_ready_o, // FU is ready
input logic alu_valid_i, // Output is valid
output logic alu_valid_o, // ALU result is valid
output logic alu_branch_res_o, // Branch comparison result
output logic [63:0] alu_result_o,
output logic [TRANS_ID_BITS-1:0] alu_trans_id_o, // ID of scoreboard entry at which to write back
output exception_t alu_exception_o,
@ -127,6 +128,7 @@ module ex_stage #(
// --------------------
branch_unit branch_unit_i (
.fu_valid_i ( alu_valid_i || lsu_valid_i || csr_valid_i || mult_valid_i), // any functional unit is valid, check that there is no accidental mis-predict
.branch_comp_res_i ( alu_branch_res_o),
.*
);