diff --git a/include/ariane_pkg.svh b/include/ariane_pkg.svh index 44ef6442b..5df63e111 100644 --- a/include/ariane_pkg.svh +++ b/include/ariane_pkg.svh @@ -40,11 +40,12 @@ package ariane_pkg; // miss-predict typedef struct packed { - logic [63:0] pc; - logic [63:0] target_address; - logic is_taken; - logic valid; // is miss-predict - } mispredict; + logic [63:0] pc; // pc of predict or mis-predict + logic [63:0] target_address; // target address at which to jump, or not + logic is_mispredict; // set if this was a mis-predict + logic is_taken; // branch is taken + logic valid; // prediction with all its values is valid + } branchpredict; typedef enum logic[3:0] { NONE, LSU, ALU, MULT, CSR diff --git a/src/ariane.sv b/src/ariane.sv index c4f0fab93..afd763f20 100644 --- a/src/ariane.sv +++ b/src/ariane.sv @@ -93,7 +93,7 @@ module ariane // -------------- // PCGEN <-> EX // -------------- - mispredict mispredict_ex_pcgen; + branchpredict branchpredict_ex_pcgen; // -------------- // PCGEN <-> CSR // -------------- @@ -121,12 +121,18 @@ module ariane fu_op operator_id_ex; logic [63:0] operand_a_id_ex; logic [63:0] operand_b_id_ex; + logic [63:0] operand_c_id_ex; // ALU logic alu_ready_ex_id; logic alu_valid_id_ex; logic [TRANS_ID_BITS-1:0] alu_trans_id_ex_id; logic alu_valid_ex_id; logic [63:0] alu_result_ex_id; + exception alu_exception_ex_id; + // Branches and Jumps + logic branch_valid_id_ex; + logic [63:0] predict_address_id_ex; + logic predict_taken_id_ex; // LSU logic [TRANS_ID_BITS-1:0] lsu_trans_id_ex_id; logic lsu_valid_id_ex; @@ -205,7 +211,7 @@ module ariane pcgen pcgen_i ( .flush_i ( flush ), .pc_if_i ( pc_if ), - .mispredict_i ( mispredict_ex_pcgen ), + .branchpredict_i ( branchpredict_ex_pcgen ), .pc_if_o ( pc_pcgen_if ), .set_pc_o ( set_pc_pcgen_if ), .is_branch_o ( is_branch_o ), @@ -262,25 +268,30 @@ module ariane .operator_o ( operator_id_ex ), .operand_a_o ( operand_a_id_ex ), .operand_b_o ( operand_b_id_ex ), + .operand_c_o ( operand_c_id_ex ), .imm_o ( imm_id_ex ), .trans_id_o ( trans_id_id_ex ), - + // ALU .alu_ready_i ( alu_ready_ex_id ), .alu_valid_o ( alu_valid_id_ex ), - + // Branches and Jumps + .branch_valid_o ( branch_valid_id_ex ), + .predict_address_o ( predict_address_id_ex ), + .predict_taken_o ( predict_taken_id_ex ), + // LSU .lsu_ready_i ( lsu_ready_ex_id ), .lsu_valid_o ( lsu_valid_id_ex ), - + // Multiplier .mult_ready_i ( mult_ready_ex_id ), .mult_valid_o ( mult_valid_id_ex ), - + // CSR .csr_ready_i ( csr_ready_ex_id ), .csr_valid_o ( csr_valid_id_ex ), - .trans_id_i ( {alu_trans_id_ex_id, lsu_trans_id_ex_id , csr_trans_id_ex_id} ), - .wdata_i ( {alu_result_ex_id, lsu_result_ex_id, csr_result_ex_id} ), - .ex_ex_i ( {{$bits(exception){1'b0}}, lsu_exception_ex_id, {$bits(exception){1'b0}} } ), - .wb_valid_i ( {alu_valid_ex_id, lsu_valid_ex_id, csr_valid_ex_id} ), + .trans_id_i ( {alu_trans_id_ex_id, lsu_trans_id_ex_id, csr_trans_id_ex_id }), + .wdata_i ( {alu_result_ex_id, lsu_result_ex_id, csr_result_ex_id }), + .ex_ex_i ( {alu_exception_ex_id, lsu_exception_ex_id, {$bits(exception){1'b0}} }), + .wb_valid_i ( {alu_valid_ex_id, lsu_valid_ex_id, csr_valid_ex_id }), .waddr_a_i ( waddr_a_commit_id ), .wdata_a_i ( wdata_a_commit_id ), @@ -298,15 +309,21 @@ module ariane .operator_i ( operator_id_ex ), .operand_a_i ( operand_a_id_ex ), .operand_b_i ( operand_b_id_ex ), + .operand_c_i ( operand_c_id_ex ), .imm_i ( imm_id_ex ), .trans_id_i ( trans_id_id_ex ), - .comparison_result_o ( ), // ALU .alu_ready_o ( alu_ready_ex_id ), .alu_valid_i ( alu_valid_id_ex ), .alu_result_o ( alu_result_ex_id ), .alu_trans_id_o ( alu_trans_id_ex_id ), .alu_valid_o ( alu_valid_ex_id ), + .alu_exception_o ( alu_exception_ex_id ), + // Branches and Jumps + .branch_valid_i ( branch_valid_id_ex ), + .predict_address_i ( predict_address_id_ex ), + .predict_taken_i ( predict_taken_id_ex ), + .branchpredict_o ( branchpredict_ex_pcgen ), // LSU .lsu_ready_o ( lsu_ready_ex_id ), .lsu_valid_i ( lsu_valid_id_ex ), @@ -393,14 +410,13 @@ module ariane // Controller // ------------ logic flush_commit_i; - logic mispredict_i; - mispredict mispredict_o; + logic branchpredict_i; + controller i_controller ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .flush_commit_i(flush_commit_i), - .mispredict_i (mispredict_i ), - .mispredict_o (mispredict_o ) + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .flush_commit_i (flush_commit_i), + .branchpredict_i (branchpredict_i ) ); diff --git a/src/branch_engine.sv b/src/branch_engine.sv index b7847c5f6..b9dbe81f9 100644 --- a/src/branch_engine.sv +++ b/src/branch_engine.sv @@ -20,36 +20,37 @@ import ariane_pkg::*; module branch_engine ( - input logic clk_i, // Clock - input logic rst_ni, // Asynchronous reset active low + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low - input logic [63:0] operand_a, - input logic [63:0] operand_b, - input logic valid_i, + input logic [63:0] operand_a_i, + input logic [63:0] operand_b_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 - output mispredict mispredict_o, // this is the actual address we are targeting - output exception branch_ex_o // branch exception out + input logic comparison_result_i, // result of comparison + input logic [63:0] predict_address_i, // this is the address we predicted + output branchpredict branchpredict_o, // this is the actual address we are targeting + output exception branch_ex_o // branch exception out ); logic [63:0] target_address; always_comb begin : target_address_calc - target_address = 64'b0; - mispredict_o.pc = 64'b0; - mispredict_o.target_address = 64'b0; - mispredict_o.is_taken = 1'b0; - mispredict_o.valid = 1'b0; + target_address = 64'b0; + branchpredict_o.pc = 64'b0; + branchpredict_o.target_address = 64'b0; + branchpredict_o.is_taken = 1'b0; + branchpredict_o.valid = valid_i; + branchpredict_o.is_mispredict = 1'b0; if (valid_i) begin // calculate target address simple 64 bit addition - target_address = $signed(operand_a) + $signed(operand_b); + target_address = $signed(operand_a_i) + $signed(operand_b_i); + // write target address + branchpredict_o.target_address = target_address; + branchpredict_o.is_taken = comparison_result_i; // we mis-predicted e.g.: the predicted address is unequal to the actual address if (target_address != predict_address_i && target_address[1:0] == 2'b0) begin - // write target address - mispredict_o.target_address = target_address; - mispredict_o.is_taken = comparison_result_i; - mispredict_o.valid = 1'b1; + branchpredict_o.is_mispredict = 1'b0; end end end diff --git a/src/btb.sv b/src/btb.sv index 58b71b9cb..8df46cb06 100644 --- a/src/btb.sv +++ b/src/btb.sv @@ -28,7 +28,7 @@ module btb #( input logic flush_i, // flush the btb input logic [63:0] vpc_i, // virtual PC from IF stage - input mispredict mispredict_i, // a miss-predict happened -> update data structure + input branchpredict branchpredict_i, // a miss-predict happened -> update data structure output logic is_branch_o, // instruction at vpc_i is a branch output logic predict_taken_o, // the branch is taken @@ -51,7 +51,7 @@ module btb #( // get actual index positions // we ignore the 0th bit since all instructions are aligned on // a half word boundary - assign update_pc = mispredict_i.pc[$clog2(NR_ENTRIES) + OFFSET - 1:OFFSET]; + assign update_pc = branchpredict_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 @@ -60,29 +60,29 @@ module btb #( assign branch_target_address_o = btb_q[$unsigned(index)].target_address; // update on a miss-predict - always_comb begin : update_mispredict + always_comb begin : update_branchpredict btb_n = btb_q; saturation_counter = btb_q[$unsigned(update_pc)].saturation_counter; - if (mispredict_i.valid) begin + if (branchpredict_i.valid) begin btb_n[$unsigned(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}} && ~mispredict_i.is_taken) begin + if (saturation_counter == {BITS_SATURATION_COUNTER{1'b1}} && ~branchpredict_i.is_taken) begin // we can safely decrease it btb_n[$unsigned(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}} && mispredict_i.is_taken) begin + end else if (saturation_counter == {BITS_SATURATION_COUNTER{1'b0}} && branchpredict_i.is_taken) begin // we can safely increase it btb_n[$unsigned(update_pc)].saturation_counter = saturation_counter + 1; end else begin // otherwise we are not in any boundaries and can decrease or increase it - if (mispredict_i.is_taken) + if (branchpredict_i.is_taken) btb_n[$unsigned(update_pc)].saturation_counter = saturation_counter + 1; else btb_n[$unsigned(update_pc)].saturation_counter = saturation_counter - 1; end // the target address is simply updated - btb_n[$unsigned(update_pc)].target_address = mispredict_i.target_address; + btb_n[$unsigned(update_pc)].target_address = branchpredict_i.target_address; end end diff --git a/src/controller.sv b/src/controller.sv index 3f489f4f2..3db649da1 100644 --- a/src/controller.sv +++ b/src/controller.sv @@ -20,13 +20,11 @@ import ariane_pkg::*; module controller ( - input logic clk_i, // Clock - input logic rst_ni, // Asynchronous reset active low + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low - input logic flush_commit_i, // flush request from commit stage in - input logic mispredict_i, - - output mispredict mispredict_o // to pcgen update branch history table + input logic flush_commit_i, // flush request from commit stage in + input logic branchpredict_i ); // flush on mispredict diff --git a/src/ex_stage.sv b/src/ex_stage.sv index b69707fb3..5650b662d 100644 --- a/src/ex_stage.sv +++ b/src/ex_stage.sv @@ -29,6 +29,7 @@ module ex_stage #( 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 [TRANS_ID_BITS-1:0] trans_id_i, @@ -37,8 +38,13 @@ module ex_stage #( input logic alu_valid_i, // Output is valid output logic alu_valid_o, // ALU result is valid 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 logic comparison_result_o, + 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 [63:0] predict_address_i, + output branchpredict branchpredict_o, + input logic predict_taken_i, // LSU output logic lsu_ready_o, // FU is ready input logic lsu_valid_i, // Input is valid @@ -90,7 +96,8 @@ 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; @@ -100,17 +107,27 @@ module ex_stage #( // ALU // ----- alu alu_i ( - .adder_result_o ( ), - .adder_result_ext_o ( ), - .result_o ( alu_result_o ), - .comparison_result_o ( comparison_result_o ), - .is_equal_result_o ( ), + .adder_result_o ( ), + .adder_result_ext_o ( ), + .result_o ( alu_result_o ), + .comparison_result_o ( comparison_result_alu_branch ), + .is_equal_result_o ( ), .* ); - // -------------------- - // Control Flow Change - // ------------------- + // -------------------- + // 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 ), + .predict_address_i ( predict_address_i ), + .branchpredict_o ( branchpredict_o ), + .branch_ex_o ( alu_exception_o ), + .* + ); // ---------------- // Multiplication diff --git a/src/id_stage.sv b/src/id_stage.sv index 58408a52d..bbf454805 100644 --- a/src/id_stage.sv +++ b/src/id_stage.sv @@ -39,12 +39,17 @@ module id_stage #( output fu_op operator_o, output logic [63:0] operand_a_o, output logic [63:0] operand_b_o, + output logic [63:0] operand_c_o, output logic [63:0] imm_o, output logic [TRANS_ID_BITS-1:0] trans_id_o, input logic alu_ready_i, output logic alu_valid_o, + output logic branch_valid_o, + output logic [63:0] predict_address_o, + output logic predict_taken_o, + input logic lsu_ready_i, output logic lsu_valid_o, diff --git a/src/pcgen.sv b/src/pcgen.sv index cce5fd650..7a4d1e91c 100644 --- a/src/pcgen.sv +++ b/src/pcgen.sv @@ -20,22 +20,22 @@ import ariane_pkg::*; module pcgen ( - input logic clk_i, // Clock - input logic rst_ni, // Asynchronous reset active low + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low - input logic flush_i, - input logic [63:0] pc_if_i, - input mispredict mispredict_i, // from controller signaling a mispredict -> update BTB + input logic flush_i, + input logic [63:0] pc_if_i, + input branchpredict branchpredict_i, // from controller signaling a branchpredict -> update BTB // to IF - output logic [63:0] pc_if_o, // new PC - output logic set_pc_o, // request the PC to be set to pc_if_o - output logic is_branch_o, // to check if we mispredicted we need to save whether this was a branch or not + output logic [63:0] pc_if_o, // new PC + output logic set_pc_o, // request the PC to be set to pc_if_o + output logic is_branch_o, // to check if we branchpredicted we need to save whether this was a branch or not // global input - input logic [63:0] boot_addr_i, + input logic [63:0] boot_addr_i, // CSR input - input logic [63:0] epc_i, // return from exception - input logic [63:0] trap_vector_base_i, // base of trap vector - input exception ex_i // exception in - from commit + input logic [63:0] epc_i, // return from exception + input logic [63:0] trap_vector_base_i, // base of trap vector + input exception ex_i // exception in - from commit ); logic [63:0] branch_target_address; @@ -56,7 +56,7 @@ module pcgen ( btb_i ( .vpc_i ( pc_if_i ), - .mispredict_i ( mispredict_i ), + .branchpredict_i ( branchpredict_i ), .is_branch_o ( is_branch ), .predict_taken_o ( predict_taken ), .branch_target_address_o ( branch_target_address ),