diff --git a/controller.sv b/controller.sv index b8aa0be4..ee2767fc 100644 --- a/controller.sv +++ b/controller.sv @@ -163,6 +163,10 @@ module riscv_controller `endif // ONLY_ALIGNED output logic jr_stall_o, output logic load_stall_o, + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + output logic branch_stall_o, + `endif input logic id_ready_i, // ID stage is ready @@ -180,18 +184,25 @@ module riscv_controller // CONFIG_REGION: JUMP_IN_ID `ifdef JUMP_IN_ID + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + enum logic [3:0] { RESET, BOOT_SET, SLEEP, FIRST_FETCH, + DECODE, WAIT_BRANCH_EX + FLUSH_EX, FLUSH_WB, + DBG_SIGNAL, DBG_SIGNAL_SLEEP, DBG_WAIT, DBG_WAIT_BRANCH, DBG_WAIT_SLEEP } ctrl_fsm_cs, ctrl_fsm_ns; + + `else enum logic [3:0] { RESET, BOOT_SET, SLEEP, FIRST_FETCH, DECODE, FLUSH_EX, FLUSH_WB, DBG_SIGNAL, DBG_SIGNAL_SLEEP, DBG_WAIT, DBG_WAIT_BRANCH, DBG_WAIT_SLEEP } ctrl_fsm_cs, ctrl_fsm_ns; + `endif `else - enum logic [3:0] { RESET, BOOT_SET, SLEEP, FIRST_FETCH, DECODE, WAIT_JUMP_EX, FLUSH_EX, FLUSH_WB, DBG_SIGNAL, DBG_SIGNAL_SLEEP, DBG_WAIT, DBG_WAIT_BRANCH, DBG_WAIT_SLEEP } ctrl_fsm_cs, ctrl_fsm_ns; - `endif logic jump_done, jump_done_q; @@ -245,6 +256,12 @@ module riscv_controller halt_id_o = 1'b0; dbg_ack_o = 1'b0; + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + branch_stall_o = 1'b0, + `endif + + unique case (ctrl_fsm_cs) // We were just reset, wait for fetch_enable RESET: @@ -334,9 +351,16 @@ module riscv_controller // handle conditional branches if (branch_taken_ex_i & id_ready_i) begin + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + halt_if_o = 1'b1; + + if (id_ready_i) + ctrl_fsm = WAIT_BRANCH_EX; + `else // there is a branch in the EX stage that is taken - pc_mux_o = PC_BRANCH; - pc_set_o = 1'b1; + pc_mux_o = PC_BRANCH; + pc_set_o = 1'b1; // if we want to debug, flush the pipeline // the current_pc_if will take the value of the next instruction to @@ -352,10 +376,12 @@ module riscv_controller // that is served to the ID stage is the one of the jump to the // exception handler end + if (dbg_req_i) begin ctrl_fsm_ns = DBG_SIGNAL; end + `endif end // handle unconditional jumps @@ -575,12 +601,7 @@ module riscv_controller `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; @@ -642,6 +663,43 @@ module riscv_controller // CONFIG_REGION: MERGE_ID_EX `ifdef MERGE_ID_EX + `ifdef NO_JUMP_ADDER + WAIT_BRANCH_EX: + begin + // there is a branch in the EX stage that is taken + branch_stall_o = 1'b1; + halt_if_o = 1'b1; + if (id_ready_i) + begin + pc_mux_o = PC_BRANCH; + pc_set_o = 1'b1; + ctrl_fsm_cs = DECODE; + halt_if_o = 1'b0; + + // if we want to debug, flush the pipeline + // the current_pc_if will take the value of the next instruction to + // be executed (NPC) + if (ext_req_i) begin + pc_mux_o = PC_EXCEPTION; + pc_set_o = 1'b1; + exc_ack_o = 1'b1; + halt_id_o = 1'b1; // we don't want to propagate this instruction to EX + exc_save_takenbranch_o = 1'b1; + // we don't have to change our current state here as the prefetch + // buffer is automatically invalidated, thus the next instruction + // that is served to the ID stage is the one of the jump to the + // exception handler + end + + if (dbg_req_i) + begin + ctrl_fsm_ns = DBG_SIGNAL; + end + end + end + `endif // NO_JUMP_ADDER + + `else // a branch was in ID when a debug trap is hit DBG_WAIT_BRANCH: begin diff --git a/decoder.sv b/decoder.sv index 35afa8e6..275fcd31 100644 --- a/decoder.sv +++ b/decoder.sv @@ -41,6 +41,10 @@ module riscv_decoder `ifndef ONLY_ALIGNED input logic data_misaligned_i, // misaligned data load/store in progress `endif // ONLY_ALIGNED + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + input logic branch_stall_i, + `endif // CONFIG_REGION: MUL_SUPPORT `ifdef MUL_SUPPORT // MUL related control signals @@ -76,7 +80,7 @@ module riscv_decoder // ALU signals output logic [ALU_OP_WIDTH-1:0] alu_operator_o, // ALU operation selection output logic [2:0] alu_op_a_mux_sel_o, // operand a selection: reg value, PC, immediate or zero - output logic [2:0] alu_op_b_mux_sel_o, // operand b selection: reg value or immediate + output logic [2:0] alu_op_b_mux_sel_o, // oNOperand b selection: reg value or immediate output logic [1:0] alu_op_c_mux_sel_o, // operand c selection: reg value or jump target // CONFIG_REGION: VEC_SUPPORT @@ -280,14 +284,14 @@ module riscv_decoder // CONFIG_REGION: NO_JUMP_ADDER `ifdef NO_JUMP_ADDER jump_in_id = BRANCH_JAL; - // Calculate and store PC+4 + // Calculate jump target in EX 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 + alu_op_c_mux_sel_o = OP_C_RA; // Pipeline return address to EX `else // NO_JUMP_ADDER @@ -311,7 +315,7 @@ module riscv_decoder // CONFIG_REGION: NO_JUMP_ADDER `ifdef NO_JUMP_ADDER jump_in_id = BRANCH_JALR; - // Calculate and store PC+4 + // Calculate jump target in EX 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; @@ -325,7 +329,7 @@ module riscv_decoder illegal_insn_o = 1'b1; end - alu_op_c_mux_sel_o = OP_C_JT; // Pipeline return address to EX + alu_op_c_mux_sel_o = OP_C_RA; // Pipeline return address to EX `else // NO_JUMP_ADDER @@ -356,7 +360,46 @@ module riscv_decoder OPCODE_BRANCH: begin // Branch // CONFIG_REGION: NO_JUMP_ADDER `ifdef NO_JUMP_ADDER - illegal_insn_o = 1'b1; + jump_in_id = BRANCH_COND; + + rega_used_o = 1'b1; + regb_used_o = 1'b1; + + if (~branch_stall_i) + begin + unique case (instr_rdata_i[14:12]) + 3'b000: alu_operator_o = ALU_EQ; + 3'b001: alu_operator_o = ALU_NE; + 3'b100: alu_operator_o = ALU_LTS; + 3'b101: alu_operator_o = ALU_GES; + 3'b110: alu_operator_o = ALU_LTU; + 3'b111: alu_operator_o = ALU_GEU; + 3'b010: begin + alu_operator_o = ALU_EQ; + regb_used_o = 1'b0; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_BI; + end + 3'b011: begin + alu_operator_o = ALU_NE; + regb_used_o = 1'b0; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMMB_BI; + end + default: begin + illegal_insn_o = 1'b1; + end + endcase + end + else begin + // Calculate jump target in EX + 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'b0; + rega_used_o = 1'b1; + end `else jump_target_mux_sel_o = JT_COND; diff --git a/ex_stage.sv b/ex_stage.sv index aca0bae8..8ef59695 100644 --- a/ex_stage.sv +++ b/ex_stage.sv @@ -89,6 +89,10 @@ module riscv_ex_stage input logic branch_in_ex_i, input logic [(REG_ADDR_WIDTH-1):0] regfile_alu_waddr_i, input logic regfile_alu_we_i, + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + input logic jump_in_ex_i; + `endif // directly passed through to WB stage, not used in EX input logic regfile_we_i, @@ -126,10 +130,7 @@ module riscv_ex_stage `ifdef SPLITTED_ADDER output logic alu_ready_o, `endif - // CONFIG_REGION: MERGE_ID_EX - `ifdef MERGE_ID_EX - input logic id_wait_i, - `endif + output logic ex_ready_o, // EX stage ready for new data output logic ex_valid_o, // EX stage gets new data @@ -163,7 +164,12 @@ module riscv_ex_stage `ifdef MUL_SUPPORT assign regfile_alu_wdata_fw_o = mult_en_i ? mult_result : alu_csr_result; `else + // CONFIG_REGION + `ifdef NO_JUMP_ADDER + assign regfile_alu_wdata_fw_o = jump_in_ex_i ? operand_c_i : alu_csr_result; // Select return address + `else assign regfile_alu_wdata_fw_o = alu_csr_result; + `endif `endif // MUL_SUPPORT @@ -173,7 +179,13 @@ module riscv_ex_stage // branch handling assign branch_decision_o = alu_cmp_result; + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + assign jump_target_o = adder_result_o; + `else assign jump_target_o = alu_operand_c_i; + `endif + //////////////////////////// diff --git a/id_stage.sv b/id_stage.sv index 89c0fccb..b19dcb91 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -87,7 +87,10 @@ module riscv_id_stage input logic branch_decision_i, // CONFIG_REGION: JUMP_IN_ID `ifdef JUMP_IN_ID + // CONFIG_REGION: NO_JUMP_ADDER + `ifndef NO_JUMP_ADDER output logic [31:0] jump_target_o, + `endif `endif // JUMP_IN_ID // IF and ID stage signals @@ -122,6 +125,11 @@ module riscv_id_stage output logic [31:0] alu_operand_b_ex_o, output logic [31:0] alu_operand_c_ex_o, // Still needed if 2r1w reg file used + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + output logic jump_in_ex_o, // Select operand C as return address to save in regfile + `endif + // CONFIG_REGION: BIT_SUPPORT `ifdef BIT_SUPPORT output logic [ 4:0] bmask_a_ex_o, @@ -216,7 +224,6 @@ module riscv_id_stage `endif `endif // ONLY_ALIGNED - // Interrupt signals input logic [31:0] irq_i, input logic irq_enable_i, @@ -302,6 +309,10 @@ module riscv_id_stage `ifndef ONLY_ALIGNED logic misaligned_stall; `endif + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + logic branch_stall; + `endif logic jr_stall; logic load_stall; @@ -332,11 +343,13 @@ 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 + `ifndef NO_JUMP_ADDER // CONFIG_REGION: NO_JUMP_ADDER `ifndef NO_JUMP_ADDER logic [31:0] jump_target; // calculated jump target (-> EX -> IF) `endif - + `endif // Signals running between controller and exception controller logic exc_req, ext_req, exc_ack; // handshake @@ -377,8 +390,11 @@ module riscv_id_stage logic [3:0] imm_b_mux_sel; // CONFIG_REGION: NO_JUMP_ADDER `ifndef NO_JUMP_ADDER + // CONFIG_REGION: NO_JUMP_ADDER + `ifndef NO_JUMP_ADDER logic [1:0] jump_target_mux_sel; `endif + `endif // CONFIG_REGION: MUL_SUPPORT `ifdef MUL_SUPPORT @@ -714,7 +730,10 @@ module riscv_id_stage // CONFIG_REGION: JUMP_IN_ID `ifdef JUMP_IN_ID + // CONFIG_REGION: NO_JUMP_ADDER + `ifndef NO_JUMP_ADDER assign jump_target_o = jump_target; + `endif `endif // JUMP_IN_ID //////////////////////////////////////////////////////// @@ -1087,6 +1106,10 @@ module riscv_id_stage `ifndef ONLY_ALIGNED .data_misaligned_i ( data_misaligned_i ), `endif // ONLY_ALIGNED + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + .branch_stall_i ( branch_stall ), + `endif // CONFIG_REGION: MUL_SUPPORT `ifdef MUL_SUPPORT .mult_multicycle_i ( mult_multicycle_i ), @@ -1323,6 +1346,10 @@ module riscv_id_stage `ifndef ONLY_ALIGNED .misaligned_stall_o ( misaligned_stall ), `endif // ONLY_ALIGNED + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + .branch_stall_o ( branch_stall ), + `endif .jr_stall_o ( jr_stall ), .load_stall_o ( load_stall ), diff --git a/if_stage.sv b/if_stage.sv index 2eaf4844..8cd46179 100644 --- a/if_stage.sv +++ b/if_stage.sv @@ -72,8 +72,11 @@ module riscv_if_stage #( // CONFIG_REGION: JUMP_IN_ID `ifdef JUMP_IN_ID + // CONFIG_REGION: NO_JUMP_ADDER + `ifndef NO_JUMP_ADDER input logic [31:0] jump_target_id_i, // jump target address `endif + `endif input logic [31:0] jump_target_ex_i, // jump target address // from hwloop controller // CONFIG_REGION: HWLP_SUPPORT @@ -90,10 +93,6 @@ module riscv_if_stage #( output logic if_ready_o, input logic id_ready_i, output logic if_valid_o, - // CONFIG_REGION: JUMP_IN_ID - `ifndef JUMP_IN_ID - output logic fetch_valid_o, // intended for jump in EX to see whether it is safe so go back to decode state - `endif // misc signals output logic if_busy_o, // is the IF stage busy fetching instructions? output logic perf_imiss_o // Instruction Fetch Miss @@ -158,9 +157,14 @@ module riscv_if_stage #( PC_BOOT: fetch_addr_n = {boot_addr_i[31:8], EXC_OFF_RST}; // CONFIG_REGION: JUMP_IN_ID `ifdef JUMP_IN_ID + // CONFIG_REGION: NO_JUMP_ADDER + `ifndef NO_JUMP_ADDER PC_JUMP: fetch_addr_n = jump_target_id_i; `else PC_JUMP: fetch_addr_n = jump_target_ex_i; + `endif + `else + PC_JUMP: fetch_addr_n = jump_target_ex_i; `endif // JUMP_IN_ID PC_BRANCH: fetch_addr_n = jump_target_ex_i; PC_EXCEPTION: fetch_addr_n = exc_pc; // set PC to exception handler @@ -495,11 +499,6 @@ module riscv_if_stage #( assign if_ready_o = valid & id_ready_i; assign if_valid_o = (~halt_if_i) & if_ready_o; - // CONFIG_REGION: JUMP_IN_ID - `ifndef JUMP_IN_ID - assign fetch_valid_o = fetch_valid; - `endif - //---------------------------------------------------------------------------- // Assertions //---------------------------------------------------------------------------- diff --git a/include/riscv_config.sv b/include/riscv_config.sv index c88b6063..13a662d5 100644 --- a/include/riscv_config.sv +++ b/include/riscv_config.sv @@ -75,7 +75,7 @@ //`define MATH_SPECIAL_SUPPORT // CONFIG: JUMP_IN_ID -// will enable direct jump in ID. Might increase critical path of jump target. +// will enable direct jump in ID. Might increase critical path of jump target `define JUMP_IN_ID @@ -113,22 +113,19 @@ // will split ALU Adder in half and use two cycles to add operands //`define SPLITTED_ADDER -`ifdef SMALL_IF -`ifndef JUMP_IN_ID -// CONFIG: 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/fuse the ID and EX stage `define MERGE_ID_EX + +`ifdef SMALL_IF +// CONFIG: NO_JUMP_ADDER +// will use ALU adder to calculate target and get return address from prefetcher +`define NO_JUMP_ADDER `endif + `endif `endif diff --git a/include/riscv_defines.sv b/include/riscv_defines.sv index d7a33951..ac0299e6 100644 --- a/include/riscv_defines.sv +++ b/include/riscv_defines.sv @@ -266,6 +266,7 @@ parameter MIMM_S3 = 1'b1; parameter OP_C_REGC_OR_FWD = 2'b00; parameter OP_C_REGB_OR_FWD = 2'b01; parameter OP_C_JT = 2'b10; +parameter OP_C_RA = 2'b10; // same as OP_C_JT // branch types parameter BRANCH_NONE = 2'b00; diff --git a/riscv_core.sv b/riscv_core.sv index 1e5012fd..a2c9b625 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -143,7 +143,12 @@ module riscv_core // Jump and branch target and decision (EX->IF) // CONFIG_REGION: JUMP_IN_ID `ifdef JUMP_IN_ID + // CONFIG_REGION: NO_JUMP_ADDER + `ifndef NO_JUMP_ADDER logic [31:0] jump_target_id, jump_target_ex; + `else + logic [31:0] jump_target_ex; + `endif `else logic [31:0] jump_target_ex; `endif @@ -164,6 +169,10 @@ module riscv_core logic [31:0] alu_operand_a_ex; logic [31:0] alu_operand_b_ex; logic [31:0] alu_operand_c_ex; + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + logic jump_in_ex; + `endif // CONFIG_REGION: SPLITTED_ADDER `ifdef SPLITTED_ADDER @@ -436,7 +445,10 @@ module riscv_core // Jump targets // CONFIG_REGION: JUMP_IN_ID `ifdef JUMP_IN_ID + // CONFIG_REGION: NO_JUMP_ADDER + `ifndef NO_JUMP_ADDER .jump_target_id_i ( jump_target_id ), + `endif `endif // JUMP_IN_ID .jump_target_ex_i ( jump_target_ex ), @@ -493,8 +505,11 @@ module riscv_core .branch_decision_i ( branch_decision ), // CONFIG_REGION: JUMP_IN_ID `ifdef JUMP_IN_ID + // CONFIG_REGION: NO_JUMP_ADDER + `ifndef NO_JUMP_ADDER .jump_target_o ( jump_target_id ), `endif + `endif // IF and ID control signals .clear_instr_valid_o ( clear_instr_valid ), @@ -541,6 +556,11 @@ module riscv_core .alu_req_ex_o ( alu_req_ex ), `endif + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + .jump_in_ex_o ( jump_in_ex ), + `endif + // CONFIG_REGION: BIT_SUPPORT `ifdef BIT_SUPPORT .bmask_a_ex_o ( bmask_a_ex ), @@ -745,6 +765,10 @@ module riscv_core .branch_in_ex_i ( branch_in_ex ), .regfile_alu_waddr_i ( regfile_alu_waddr_ex ), .regfile_alu_we_i ( regfile_alu_we_ex ), + // CONFIG_REGION: NO_JUMP_ADDER + `ifdef NO_JUMP_ADDER + .jump_in_ex_i ( jump_in_ex ), + `endif // CONFIG_REGION: THREE_PORT_REG_FILE `ifdef THREE_PORT_REG_FILE