diff --git a/include/ariane_pkg.svh b/include/ariane_pkg.svh index 6e4b8a9d1..93d55f48c 100644 --- a/include/ariane_pkg.svh +++ b/include/ariane_pkg.svh @@ -17,7 +17,7 @@ package ariane_pkg; localparam NR_SB_ENTRIES = 4; // number of scoreboard entries localparam TRANS_ID_BITS = $clog2(NR_SB_ENTRIES); // depending on the number of scoreboard entries we need that many bits // to uniquely identify the entry in the scoreboard - localparam NR_WB_PORTS = 3; + localparam NR_WB_PORTS = 4; localparam ASID_WIDTH = 1; localparam ISA_CODE = (1 << 2) // C - Compressed extension | (1 << 8) // I - RV32I/64I/128I base ISA diff --git a/src/ariane.sv b/src/ariane.sv index a88ee052f..0ed304455 100644 --- a/src/ariane.sv +++ b/src/ariane.sv @@ -122,7 +122,6 @@ 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; logic [63:0] pc_id_ex; logic is_compressed_instr_id_ex; // ALU @@ -133,7 +132,13 @@ module ariane logic [63:0] alu_result_ex_id; exception alu_exception_ex_id; // Branches and Jumps + logic branch_ready_ex_id; + logic [TRANS_ID_BITS-1:0] branch_trans_id_ex_id; + logic [63:0] branch_result_ex_id; + exception branch_exception_ex_id; + logic branch_valid_ex_id; logic branch_valid_id_ex; + branchpredict_sbe branch_predict_id_ex; logic resolve_branch_ex_id; // LSU @@ -280,7 +285,6 @@ 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 ), .pc_o ( pc_id_ex ), @@ -289,6 +293,7 @@ module ariane .alu_ready_i ( alu_ready_ex_id ), .alu_valid_o ( alu_valid_id_ex ), // Branches and Jumps + .branch_ready_i ( branch_ready_ex_id ), .branch_valid_o ( branch_valid_id_ex ), // branch is valid .branch_predict_o ( branch_predict_id_ex ), // branch predict to ex .resolve_branch_i ( resolve_branch_ex_id ), // in order to resolve the branch @@ -302,10 +307,10 @@ module ariane .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 ( {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 }), + .trans_id_i ( {alu_trans_id_ex_id, lsu_trans_id_ex_id, branch_trans_id_ex_id, csr_trans_id_ex_id }), + .wdata_i ( {alu_result_ex_id, lsu_result_ex_id, branch_result_ex_id, csr_result_ex_id }), + .ex_ex_i ( {{$bits(exception){1'b0}}, lsu_exception_ex_id, branch_exception_ex_id, {$bits(exception){1'b0}} }), + .wb_valid_i ( {alu_valid_ex_id, lsu_valid_ex_id, branch_valid_ex_id, csr_valid_ex_id }), .waddr_a_i ( waddr_a_commit_id ), .wdata_a_i ( wdata_a_commit_id ), @@ -325,7 +330,6 @@ 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 ), .pc_i ( pc_id_ex ), @@ -336,9 +340,14 @@ 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_exception_o ( alu_exception_ex_id ), + .alu_exception_o ( ), // Branches and Jumps + .branch_ready_o ( branch_ready_ex_id ), + .branch_valid_o ( branch_valid_ex_id ), .branch_valid_i ( branch_valid_id_ex ), + .branch_trans_id_o ( branch_trans_id_ex_id ), + .branch_result_o ( branch_result_ex_id ), + .branch_exception_o ( branch_exception_ex_id ), .branch_predict_i ( branch_predict_id_ex ), // branch predict to ex .resolved_branch_o ( resolved_branch ), .resolve_branch_o ( resolve_branch_ex_id ), diff --git a/src/branch_unit.sv b/src/branch_unit.sv index 65eb6627d..b0e9d7be7 100644 --- a/src/branch_unit.sv +++ b/src/branch_unit.sv @@ -20,26 +20,34 @@ import ariane_pkg::*; module branch_unit ( - 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 fu_valid_i, // any functional unit is valid, check that there is no accidental mis-predict - input logic valid_i, + input logic [TRANS_ID_BITS-1:0] trans_id_i, + input fu_op operator_i, // comparison operation to perform + input logic [63:0] operand_a_i, // contains content of RS 1 + input logic [63:0] operand_b_i, // contains content of RS 2 + input logic [63:0] imm_i, // immediate to add to PC + input logic [63:0] pc_i, // PC of instruction + 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, + output logic branch_ready_o, + output logic branch_valid_o, + output logic [63:0] branch_result_o, + output logic [TRANS_ID_BITS-1:0] branch_trans_id_o, - input branchpredict_sbe branch_predict_i, // this is the address we predicted - output branchpredict resolved_branch_o, // this is the actual address we are targeting - output logic resolve_branch_o, // to ID to clear that we resolved the branch and we can - // accept new entries to the scoreboard - output exception branch_ex_o // branch exception out + input branchpredict_sbe branch_predict_i, // this is the address we predicted + output branchpredict resolved_branch_o, // this is the actual address we are targeting + output logic resolve_branch_o, // to ID to clear that we resolved the branch and we can + // accept new entries to the scoreboard + output exception branch_exception_o // branch exception out ); 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 @@ -66,16 +74,18 @@ module branch_unit ( resolved_branch_o.pc = 64'b0; resolved_branch_o.target_address = 64'b0; resolved_branch_o.is_taken = 1'b0; - resolved_branch_o.valid = valid_i; + resolved_branch_o.valid = branch_valid_i; resolved_branch_o.is_mispredict = 1'b0; resolved_branch_o.is_lower_16 = 1'b0; resolve_branch_o = 1'b0; // 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 = $unsigned($signed(operand_c_i) + $signed(imm_i)); + target_address = $unsigned($signed(pc_i) + $signed(imm_i)); + // if we need to put the branch target address in a destination register, output it here to WB + branch_result_o = target_address; - if (valid_i) begin + if (branch_valid_i) begin // save PC - we need this to get the target row in the branch target buffer // we play this trick with the branch instruction which wraps a byte boundary: // |---------- Place the prediction on this PC @@ -118,11 +128,11 @@ module branch_unit ( // use ALU exception signal for storing instruction fetch exceptions if // the target address is not aligned to a 2 byte boundary always_comb begin : exception_handling - branch_ex_o.cause = INSTR_ADDR_MISALIGNED; - branch_ex_o.valid = 1'b0; - branch_ex_o.tval = pc_i; + branch_exception_o.cause = INSTR_ADDR_MISALIGNED; + branch_exception_o.valid = 1'b0; + branch_exception_o.tval = pc_i; // only throw exception if this is indeed a branch - if (valid_i && target_address[0] != 1'b0) - branch_ex_o.valid = 1'b1; + if (branch_valid_i && target_address[0] != 1'b0) + branch_exception_o.valid = 1'b1; end endmodule \ No newline at end of file diff --git a/src/decoder.sv b/src/decoder.sv index e3be7ed17..b3c16fc16 100644 --- a/src/decoder.sv +++ b/src/decoder.sv @@ -362,18 +362,14 @@ module decoder ( // Jump and link register OPCODE_JALR: begin instruction_o.fu = CTRL_FLOW; - instruction_o.op = JALR; imm_select = UIMM; - instruction_o.use_pc = 1'b1; instruction_o.rd = instr.itype.rd; is_control_flow_instr_o = 1'b1; end // Jump and link OPCODE_JAL: begin instruction_o.fu = CTRL_FLOW; - instruction_o.op = JAL; imm_select = JIMM; - instruction_o.use_pc = 1'b1; instruction_o.rd = instr.utype.rd; is_control_flow_instr_o = 1'b1; end diff --git a/src/ex_stage.sv b/src/ex_stage.sv index a2da5644d..459243d12 100644 --- a/src/ex_stage.sv +++ b/src/ex_stage.sv @@ -30,7 +30,6 @@ 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, input logic [63:0] pc_i, // PC of current instruction @@ -44,8 +43,14 @@ 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 + output logic branch_ready_o, input logic branch_valid_i, // we are using the branch unit + output logic branch_valid_o, // the calculated branch target is valid + output logic [63:0] branch_result_o, // branch target address out input branchpredict_sbe branch_predict_i, // branch prediction in + output logic [TRANS_ID_BITS-1:0] branch_trans_id_o, + output exception branch_exception_o, // branch unit detected an exception + output branchpredict resolved_branch_o, // the branch engine uses the write back from the ALU output logic resolve_branch_o, // to ID signaling that we resolved the branch // LSU @@ -116,8 +121,6 @@ module ex_stage #( // -------------------- branch_unit branch_unit_i ( .fu_valid_i ( alu_valid_i | lsu_valid_i | csr_valid_i ), // any functional unit is valid, check that there is no accidental mis-predict - .valid_i ( branch_valid_i ), - .branch_ex_o ( alu_exception_o ), // we use the ALU exception WB for the branch exception .* ); diff --git a/src/id_stage.sv b/src/id_stage.sv index 1e2b14ba7..ab8f811cf 100644 --- a/src/id_stage.sv +++ b/src/id_stage.sv @@ -42,7 +42,6 @@ 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, output logic [63:0] pc_o, @@ -50,16 +49,18 @@ module id_stage #( input logic alu_ready_i, output logic alu_valid_o, - output logic branch_valid_o, // use branch prediction unit // ex just resolved our predicted branch, we are ready to accept new requests input logic resolve_branch_i, input logic lsu_ready_i, output logic lsu_valid_o, + // branch prediction + input logic branch_ready_i, + output logic branch_valid_o, // use branch prediction unit + output branchpredict_sbe branch_predict_o, input logic mult_ready_i, output logic mult_valid_o, // Branch predict Out - output branchpredict_sbe branch_predict_o, input logic csr_ready_i, output logic csr_valid_o, diff --git a/src/issue_read_operands.sv b/src/issue_read_operands.sv index d38d4c2ad..08d0cb011 100644 --- a/src/issue_read_operands.sv +++ b/src/issue_read_operands.sv @@ -43,7 +43,6 @@ module issue_read_operands ( 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 immediate for the LSU output logic [TRANS_ID_BITS-1:0] trans_id_o, output logic [63:0] pc_o, @@ -52,6 +51,7 @@ module issue_read_operands ( input logic alu_ready_i, // FU is ready output logic alu_valid_o, // Output is valid // Branches and Jumps + input logic branch_ready_i, output logic branch_valid_o, // this is a valid branch instruction output branchpredict_sbe branch_predict_o, // LSU @@ -75,7 +75,6 @@ module issue_read_operands ( // output flipflop (ID <-> EX) logic [63:0] operand_a_n, operand_a_q, operand_b_n, operand_b_q, - operand_c_n, operand_c_q, imm_n, imm_q; logic alu_valid_n, alu_valid_q; @@ -93,7 +92,6 @@ module issue_read_operands ( // ID <-> EX registers assign operand_a_o = operand_a_q; assign operand_b_o = operand_b_q; - assign operand_c_o = operand_c_q; assign fu_o = fu_q; assign operator_o = operator_q; assign alu_valid_o = alu_valid_q; @@ -148,9 +146,10 @@ module issue_read_operands ( unique case (issue_instr_i.fu) NONE: fu_busy = 1'b0; - ALU, CTRL_FLOW: // control flow instruction also need the ALU - // and they are always ready if the ALU is ready + ALU: fu_busy = ~alu_ready_i; + CTRL_FLOW: + fu_busy = ~branch_ready_i; MULT: fu_busy = ~mult_ready_i; LOAD, STORE: @@ -201,8 +200,6 @@ module issue_read_operands ( // default is regfile operand_a_n = operand_a_regfile; operand_b_n = operand_b_regfile; - // set PC as default operand c - operand_c_n = issue_instr_i.pc; // immediates are the third operands in the store case imm_n = issue_instr_i.result; trans_id_n = issue_instr_i.trans_id; @@ -227,34 +224,34 @@ module issue_read_operands ( // zero extend operand a operand_a_n = {52'b0, issue_instr_i.rs1}; end - // or is it an immediate (including PC), this is not the case for a store - if (issue_instr_i.use_imm && (issue_instr_i.fu != STORE)) begin + // or is it an immediate (including PC), this is not the case for a store and control flow instructions + if (issue_instr_i.use_imm && (issue_instr_i.fu != STORE) && (issue_instr_i.fu != CTRL_FLOW)) begin operand_b_n = issue_instr_i.result; end - // special assignments in the JAL and JALR case - case (issue_instr_i.op) - // re-write the operator since - // we need the ALU for addition - JAL: begin - operator_n = ADD; - // output 4 as operand b as we - // need to save PC + 4 or in case of a compressed instruction PC + 4 - operand_b_n = (issue_instr_i.is_compressed) ? 64'h2 : 64'h4; - end + // // special assignments in the JAL and JALR case + // case (issue_instr_i.op) + // // re-write the operator since + // // we need the ALU for addition + // JAL: begin + // operator_n = ADD; + // // output 4 as operand b as we + // // need to save PC + 4 or in case of a compressed instruction PC + 4 + // operand_b_n = (issue_instr_i.is_compressed) ? 64'h2 : 64'h4; + // end - JALR: begin - operator_n = ADD; - // output 4 as operand b as we - // need to save PC + 4 or in case of a compressed instruction PC + 4 - operand_b_n = (issue_instr_i.is_compressed) ? 64'h2 : 64'h4; - // get RS1 as operand C - operand_c_n = operand_a_regfile; - // forward rs1 - if (forward_rs1) begin - operand_c_n = rs1_i; - end - end - endcase + // JALR: begin + // operator_n = ADD; + // // output 4 as operand b as we + // // need to save PC + 4 or in case of a compressed instruction PC + 4 + // operand_b_n = (issue_instr_i.is_compressed) ? 64'h2 : 64'h4; + // // get RS1 as operand C + // operand_c_n = operand_a_regfile; + // // forward rs1 + // if (forward_rs1) begin + // operand_c_n = rs1_i; + // end + // end + // endcase end // FU select, assert the correct valid out signal (in the next cycle) always_comb begin : unit_valid @@ -269,20 +266,16 @@ module issue_read_operands ( if (~issue_instr_i.ex.valid && issue_instr_valid_i && issue_ack_o) begin case (issue_instr_i.fu) ALU: - alu_valid_n = 1'b1; - MULT: - mult_valid_n = 1'b1; - LOAD, STORE: - lsu_valid_n = 1'b1; - CSR: - csr_valid_n = 1'b1; - CTRL_FLOW: begin alu_valid_n = 1'b1; + CTRL_FLOW: branch_valid_n = 1'b1; - end - default: begin - - end + MULT: + mult_valid_n = 1'b1; + LOAD, STORE: + lsu_valid_n = 1'b1; + CSR: + csr_valid_n = 1'b1; + default:; endcase end // if we got a flush request, de-assert the valid flag, otherwise we will start this @@ -326,7 +319,6 @@ module issue_read_operands ( if(~rst_ni) begin operand_a_q <= '{default: 0}; operand_b_q <= '{default: 0}; - operand_c_q <= '{default: 0}; imm_q <= 64'b0; alu_valid_q <= 1'b0; branch_valid_q <= 1'b0; @@ -342,7 +334,6 @@ module issue_read_operands ( end else begin operand_a_q <= operand_a_n; operand_b_q <= operand_b_n; - operand_c_q <= operand_c_n; imm_q <= imm_n; alu_valid_q <= alu_valid_n; branch_valid_q <= branch_valid_n;