diff --git a/controller.sv b/controller.sv index 92c36206..4637242a 100644 --- a/controller.sv +++ b/controller.sv @@ -433,14 +433,19 @@ module riscv_controller end end - // TODO: make sure this is not done multiple times in a row!!! + // TODO: make sure this is not done multiple times in a row (RI5CY)!!! // maybe with an assertion? // handle conditional branches // CONFIG_REGION: SPLITTED_ADDER `ifdef SPLITTED_ADDER if (branch_taken_ex_i & ex_valid_i) begin `else + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + if (branch_taken_ex_i & ex_valid_i) begin + `else if (branch_taken_ex_i) begin + `endif `endif // there is a branch in the EX stage that is taken pc_mux_o = PC_BRANCH; diff --git a/decoder.sv b/decoder.sv index 4d1dda76..7cc15f79 100644 --- a/decoder.sv +++ b/decoder.sv @@ -273,6 +273,20 @@ module riscv_decoder ////////////////////////////////////// OPCODE_JAL: begin // Jump and Link + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + jump_in_id = BRANCH_JAL; + // Calculate and store PC+4 + alu_op_a_mux_sel_o = OP_A_CURRPC; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_UJ; + alu_operator_o = ALU_ADD; + regfile_alu_we = 1'b1; + + alu_op_c_mux_sel_o = OP_C_JT; // Pipeline return address to EX + + `else // NO_JUMP_ADDER + jump_target_mux_sel_o = JT_JAL; jump_in_id = BRANCH_JAL; // Calculate and store PC+4 @@ -286,10 +300,31 @@ module riscv_decoder `ifndef JUMP_IN_ID alu_op_c_mux_sel_o = OP_C_JT; // Pipeline to EX `endif - // Calculate jump target (= PC + UJ imm) + `endif end OPCODE_JALR: begin // Jump and Link Register + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + jump_in_id = BRANCH_JALR; + // Calculate and store PC+4 + alu_op_a_mux_sel_o = OP_A_CURRPC; + alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; + imm_b_mux_sel_o = IMMB_SB; + alu_operator_o = ALU_ADD; + regfile_alu_we = 1'b1; + rega_used_o = 1'b1; + + if (instr_rdata_i[14:12] != 3'b0) begin + jump_in_id = BRANCH_NONE; + regfile_alu_we = 1'b0; + illegal_insn_o = 1'b1; + end + + alu_op_c_mux_sel_o = OP_C_JT; // Pipeline return address to EX + + `else // NO_JUMP_ADDER + jump_target_mux_sel_o = JT_JALR; jump_in_id = BRANCH_JALR; // Calculate and store PC+4 @@ -311,9 +346,15 @@ module riscv_decoder `ifndef JUMP_IN_ID alu_op_c_mux_sel_o = OP_C_JT; // Pipeline to EX `endif + `endif end OPCODE_BRANCH: begin // Branch + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + illegal_insn_o = 1'b1; + + `else jump_target_mux_sel_o = JT_COND; jump_in_id = BRANCH_COND; alu_op_c_mux_sel_o = OP_C_JT; @@ -344,6 +385,7 @@ module riscv_decoder illegal_insn_o = 1'b1; end endcase + `endif // NO_JUMP_ADDER end @@ -1274,8 +1316,8 @@ module riscv_decoder `ifdef HWLP_SUPPORT assign hwloop_we_o = (deassert_we_i) ? 3'b0 : hwloop_we; `endif // HWLP_SUPPORT - assign csr_op_o = (deassert_we_i) ? CSR_OP_NONE : csr_op; - assign jump_in_id_o = (deassert_we_i) ? BRANCH_NONE : jump_in_id; + assign csr_op_o = (deassert_we_i) ? CSR_OP_NONE : csr_op; + assign jump_in_id_o = (deassert_we_i) ? BRANCH_NONE : jump_in_id; assign ebrk_insn_o = (deassert_we_i) ? 1'b0 : ebrk_insn; assign eret_insn_o = (deassert_we_i) ? 1'b0 : eret_insn; // TODO: do not deassert? assign pipe_flush_o = (deassert_we_i) ? 1'b0 : pipe_flush; // TODO: do not deassert? diff --git a/id_stage.sv b/id_stage.sv index 0c019842..ae6800fc 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -323,7 +323,10 @@ module riscv_id_stage logic [31:0] imm_a; // contains the immediate for operand b logic [31:0] imm_b; // contains the immediate for operand b + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER logic [31:0] jump_target; // calculated jump target (-> EX -> IF) + `endif // Signals running between controller and exception controller @@ -363,7 +366,10 @@ module riscv_id_stage logic [0:0] imm_a_mux_sel; logic [3:0] imm_b_mux_sel; + // CONFIG_REGION: NO_JUMP_ADDER + `if NO_JUMP_ADDER logic [1:0] jump_target_mux_sel; + `endif // CONFIG_REGION: MUL_SUPPORT `ifdef MUL_SUPPORT @@ -623,67 +629,70 @@ module riscv_id_stage // // /////////////////////////////////////////////// + // hwloop register id + assign hwloop_regid_int = instr[7]; // rd contains hwloop register id - // hwloop register id - assign hwloop_regid_int = instr[7]; // rd contains hwloop register id - - // hwloop target mux - always_comb - begin - case (hwloop_target_mux_sel) - 1'b0: hwloop_target = pc_id_i + {imm_iz_type[30:0], 1'b0}; - 1'b1: hwloop_target = pc_id_i + {imm_z_type[30:0], 1'b0}; - endcase - end - - // hwloop start mux - always_comb - begin - case (hwloop_start_mux_sel) - 1'b0: hwloop_start_int = hwloop_target; // for PC + I imm - 1'b1: hwloop_start_int = pc_if_i; // for next PC - endcase - end - - - // hwloop cnt mux - always_comb - begin : hwloop_cnt_mux - case (hwloop_cnt_mux_sel) - 1'b0: hwloop_cnt_int = imm_iz_type; - 1'b1: hwloop_cnt_int = operand_a_fw_id; - endcase; - end - - // multiplex between access from instructions and access via CSR registers - assign hwloop_start = hwloop_we_int[0] ? hwloop_start_int : csr_hwlp_data_i; - assign hwloop_end = hwloop_we_int[1] ? hwloop_target : csr_hwlp_data_i; - assign hwloop_cnt = hwloop_we_int[2] ? hwloop_cnt_int : csr_hwlp_data_i; - assign hwloop_regid = (|hwloop_we_int) ? hwloop_regid_int : csr_hwlp_regid_i; - assign hwloop_we = (|hwloop_we_int) ? hwloop_we_int : csr_hwlp_we_i; - `endif // HWLP_SUPPORT - - ////////////////////////////////////////////////////////////////// - // _ _____ _ // - // | |_ _ _ __ ___ _ __ |_ _|_ _ _ __ __ _ ___| |_ // - // _ | | | | | '_ ` _ \| '_ \ | |/ _` | '__/ _` |/ _ \ __| // - // | |_| | |_| | | | | | | |_) | | | (_| | | | (_| | __/ |_ // - // \___/ \__,_|_| |_| |_| .__/ |_|\__,_|_| \__, |\___|\__| // - // |_| |___/ // - ////////////////////////////////////////////////////////////////// - - always_comb - begin : jump_target_mux - unique case (jump_target_mux_sel) - JT_JAL: jump_target = pc_id_i + imm_uj_type; - JT_COND: jump_target = pc_id_i + imm_sb_type; - - // JALR: Cannot forward RS1, since the path is too long - JT_JALR: jump_target = regfile_data_ra_id + imm_i_type; - default: jump_target = regfile_data_ra_id + imm_i_type; + // hwloop target mux + always_comb + begin + case (hwloop_target_mux_sel) + 1'b0: hwloop_target = pc_id_i + {imm_iz_type[30:0], 1'b0}; + 1'b1: hwloop_target = pc_id_i + {imm_z_type[30:0], 1'b0}; endcase end + // hwloop start mux + always_comb + begin + case (hwloop_start_mux_sel) + 1'b0: hwloop_start_int = hwloop_target; // for PC + I imm + 1'b1: hwloop_start_int = pc_if_i; // for next PC + endcase + end + + + // hwloop cnt mux + always_comb + begin : hwloop_cnt_mux + case (hwloop_cnt_mux_sel) + 1'b0: hwloop_cnt_int = imm_iz_type; + 1'b1: hwloop_cnt_int = operand_a_fw_id; + endcase; + end + + // multiplex between access from instructions and access via CSR registers + assign hwloop_start = hwloop_we_int[0] ? hwloop_start_int : csr_hwlp_data_i; + assign hwloop_end = hwloop_we_int[1] ? hwloop_target : csr_hwlp_data_i; + assign hwloop_cnt = hwloop_we_int[2] ? hwloop_cnt_int : csr_hwlp_data_i; + assign hwloop_regid = (|hwloop_we_int) ? hwloop_regid_int : csr_hwlp_regid_i; + assign hwloop_we = (|hwloop_we_int) ? hwloop_we_int : csr_hwlp_we_i; + `endif // HWLP_SUPPORT + + + ////////////////////////////////////////////////////////////////// + // _ _____ _ // + // | |_ _ _ __ ___ _ __ |_ _|_ _ _ __ __ _ ___| |_ // + // _ | | | | | '_ ` _ \| '_ \ | |/ _` | '__/ _` |/ _ \ __| // + // | |_| | |_| | | | | | | |_) | | | (_| | | | (_| | __/ |_ // + // \___/ \__,_|_| |_| |_| .__/ |_|\__,_|_| \__, |\___|\__| // + // |_| |___/ // + ////////////////////////////////////////////////////////////////// + + // CONFIG_REGION: NO_JUMP_ADDER + `ifndef NO_JUMP_ADDER + always_comb + begin : jump_target_mux + unique case (jump_target_mux_sel) + JT_JAL: jump_target = pc_id_i + imm_uj_type; + JT_COND: jump_target = pc_id_i + imm_sb_type; + + // JALR: Cannot forward RS1, since the path is too long + JT_JALR: jump_target = regfile_data_ra_id + imm_i_type; + default: jump_target = regfile_data_ra_id + imm_i_type; + endcase + end + `endif + // CONFIG_REGION: JUMP_IN_ID `ifdef JUMP_IN_ID assign jump_target_o = jump_target; @@ -752,24 +761,33 @@ module riscv_id_stage IMMB_I: imm_b = imm_i_type; IMMB_S: imm_b = imm_s_type; IMMB_U: imm_b = imm_u_type; + // CONFIG_REGION: NO_JUMP_ADDER + `ifndef NO_JUMP_ADDER // CONFIG_REGION: ONLY_ALIGNED `ifndef ONLY_ALIGNED IMMB_PCINCR: imm_b = (is_compressed_i && (~data_misaligned_i)) ? 32'h2 : 32'h4; `else IMMB_PCINCR: imm_b = (is_compressed_i) ? 32'h2 : 32'h4; `endif // ONLY_ALIGNED + `endif // NO_JUMP_ADDER IMMB_S2: imm_b = imm_s2_type; IMMB_BI: imm_b = imm_bi_type; IMMB_S3: imm_b = imm_s3_type; IMMB_VS: imm_b = imm_vs_type; IMMB_VU: imm_b = imm_vu_type; + IMMB_SB // CONFIG_REGION: MATH_SPECIAL_SUPPORT `ifdef MATH_SPECIAL_SUPPORT IMMB_SHUF: imm_b = imm_shuffle_type; IMMB_CLIP: imm_b = {1'b0, imm_clip_type[31:1]}; `endif // MATH_SPECIAL_SUPPORT - default: imm_b = imm_i_type; + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + IMMB_UJ: imm_b = imm_uj_type + IMMB_SB: imm_b = imm_sb_type; + `endif + default: imm_b = imm_i_type; endcase end @@ -856,7 +874,7 @@ module riscv_id_stage OP_C_REGC_OR_FWD: alu_operand_c = operand_c_fw_id; OP_C_REGB_OR_FWD: alu_operand_c = operand_b_fw_id; OP_C_JT: alu_operand_c = jump_target; - default: alu_operand_c = operand_c_fw_id; + default: alu_operand_c = operand_c_fw_id; endcase // case (alu_op_c_mux_sel) end @@ -877,7 +895,12 @@ module riscv_id_stage begin : alu_operand_c_mux case (alu_op_c_mux_sel) OP_C_REGB_OR_FWD: alu_operand_c = operand_b_fw_id; + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + OP_C_JT: alu_operand_c = pc_if_i; // this is the return address + `else OP_C_JT: alu_operand_c = jump_target; + `endif default: alu_operand_c = operand_b_fw_id; endcase // case (alu_op_c_mux_sel) end diff --git a/include/riscv_config.sv b/include/riscv_config.sv index a60cf22d..1db84c8b 100644 --- a/include/riscv_config.sv +++ b/include/riscv_config.sv @@ -111,15 +111,25 @@ // CONFIG: SPLITTED_ADDER // will split ALU Adder in half and use two cycles to add operands -`define SPLITTED_ADDER +//`define SPLITTED_ADDER `ifdef SMALL_IF `ifndef JUMP_IN_ID // CONFIG: NO_JUMP_ADDER -// will use ALU adder to calculate target and return address from prefetcher -`define NO_JUMP_ADDER +// (NOT IMPLEMENTED!!!) will use ALU adder to calculate target and return address from prefetcher +//`define NO_JUMP_ADDER +`endif +`endif +`ifndef SPLITTED_ADDER +`ifndef NO_JUMP_ADDER +`ifdef JUMP_IN_ID +// CONFIG: MERGE_ID_EX +// will merge the ID and EX stage +`define MERGE_ID_EX + +`endif `endif `endif diff --git a/include/riscv_defines.sv b/include/riscv_defines.sv index 8413cb1f..e4dd69e2 100644 --- a/include/riscv_defines.sv +++ b/include/riscv_defines.sv @@ -239,6 +239,8 @@ parameter IMMB_VU = 4'b0111; parameter IMMB_SHUF = 4'b1000; parameter IMMB_CLIP = 4'b1001; parameter IMMB_BI = 4'b1011; +parameter IMMB_UJ = 4'b1100; +parameter IMMB_SB = 4'b1101; // bit mask selection parameter BMASK_A_ZERO = 1'b0;