diff --git a/controller.sv b/controller.sv index 1f94b13a..9d00b9fb 100644 --- a/controller.sv +++ b/controller.sv @@ -86,9 +86,11 @@ module controller input logic data_rvalid_i, // rvalid from data memory // hwloop signals - output logic [2:0] hwloop_we_o, // write enables for hwloop regs - output logic hwloop_wb_mux_sel_o, // select data to write to hwloop regs - output logic [1:0] hwloop_cnt_mux_sel_o, // selects hwloop counter input + output logic [2:0] hwloop_we_o, // write enable for hwloop regs + output logic hwloop_start_mux_sel_o, // selects hwloop start address input + output logic hwloop_end_mux_sel_o, // selects hwloop end address input + output logic hwloop_cnt_mux_sel_o, // selects hwloop counter input + input logic hwloop_jump_i, // modify pc_mux_sel to select the hwloop addr // Interrupt signals @@ -120,6 +122,7 @@ module controller output logic [1:0] operand_c_fw_mux_sel_o, // regfile rc data selector form ID stage // Jump target calcuation done decision + output logic [1:0] jump_target_mux_sel_o, // jump target selection input logic [1:0] jump_in_ex_i, // jump is being calculated in ALU output logic [1:0] jump_in_id_o, // jump is being calculated in ALU input logic branch_decision_i, @@ -191,12 +194,15 @@ module controller always_comb begin jump_in_id = `BRANCH_NONE; + jump_target_mux_sel_o = `JT_JAL; alu_operator = `ALU_NOP; alu_op_a_mux_sel_o = `OP_A_REGA_OR_FWD; alu_op_b_mux_sel_o = `OP_B_REGB_OR_FWD; alu_op_c_mux_sel_o = `OP_C_REGC_OR_FWD; + immediate_mux_sel_o = `IMM_I; + vector_mode_o = `VEC_MODE32; scalar_replication_o = 1'b0; alu_cmp_mode_o = `ALU_CMP_FULL; @@ -213,9 +219,9 @@ module controller prepost_useincr_o = 1'b1; hwloop_we_o = 3'b0; - hwloop_wb_mux_sel_o = 1'b0; - hwloop_cnt_mux_sel_o = 2'b00; - immediate_mux_sel_o = `IMM_I; + hwloop_start_mux_sel_o = 1'b0; + hwloop_end_mux_sel_o = 1'b0; + hwloop_cnt_mux_sel_o = 1'b0; csr_access_o = 1'b0; csr_op = `CSR_OP_NONE; @@ -249,43 +255,44 @@ module controller ////////////////////////////////////// `OPCODE_JAL: begin // Jump and Link - if (instr_rdata_i ==? `INSTR_JAL) begin - 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; - immediate_mux_sel_o = `IMM_PCINCR; - alu_operator = `ALU_ADD; - regfile_alu_we = 1'b1; - // Calculate jump target (= PC + UJ imm) - alu_op_c_mux_sel_o = `OP_C_JT; - end else begin - illegal_insn_int = 1'b1; - end + jump_target_mux_sel_o = `JT_JAL; + 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; + immediate_mux_sel_o = `IMM_PCINCR; + alu_operator = `ALU_ADD; + regfile_alu_we = 1'b1; + // Calculate jump target (= PC + UJ imm) + alu_op_c_mux_sel_o = `OP_C_JT; end `OPCODE_JALR: begin // Jump and Link Register - if (instr_rdata_i ==? `INSTR_JALR) begin - 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_IMM; - immediate_mux_sel_o = `IMM_PCINCR; - alu_operator = `ALU_ADD; - regfile_alu_we = 1'b1; - // Calculate jump target (= RS1 + I imm) - rega_used = 1'b1; - alu_op_c_mux_sel_o = `OP_C_JT; - end else begin - illegal_insn_int = 1'b1; + jump_target_mux_sel_o = `JT_JALR; + 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_IMM; + immediate_mux_sel_o = `IMM_PCINCR; + alu_operator = `ALU_ADD; + regfile_alu_we = 1'b1; + // Calculate jump target (= RS1 + I imm) + rega_used = 1'b1; + alu_op_c_mux_sel_o = `OP_C_JT; + + if (instr_rdata_i[14:12] != 3'b0) begin + jump_in_id = `BRANCH_NONE; + regfile_alu_we = 1'b0; + illegal_insn_int = 1'b0; end end `OPCODE_BRANCH: begin // Branch - jump_in_id = `BRANCH_COND; - alu_op_c_mux_sel_o = `OP_C_JT; - rega_used = 1'b1; - regb_used = 1'b1; + jump_target_mux_sel_o = `JT_COND; + jump_in_id = `BRANCH_COND; + alu_op_c_mux_sel_o = `OP_C_JT; + rega_used = 1'b1; + regb_used = 1'b1; unique case (instr_rdata_i[14:12]) 3'b000: alu_operator = `ALU_EQ; @@ -828,54 +835,54 @@ module controller // // /////////////////////////////////////////////// - `OPCODE_HWLOOP: begin // hardware loop instructions + `OPCODE_HWLOOP: begin + jump_target_mux_sel_o = `JT_HWLP; // get PC + I imm from jump target adder + unique case (instr_rdata_i[14:12]) - 3'b000: begin // lp.starti set start address - hwloop_wb_mux_sel_o = 1'b1; - hwloop_we_o[0] = 1'b1; // set we for start addr reg - alu_op_a_mux_sel_o = `OP_A_CURRPC; - alu_op_b_mux_sel_o = `OP_B_IMM; - alu_operator = `ALU_ADD; + 3'b000: begin + // lp.starti: set start address to PC + I-type immediate + hwloop_we_o[0] = 1'b1; + hwloop_start_mux_sel_o = 1'b0; // $display("%t: hwloop start address: %h", $time, instr_rdata_i); end - 3'b001: begin // lp.endi set end address - hwloop_wb_mux_sel_o = 1'b1; - hwloop_we_o[1] = 1'b1; // set we for end addr reg - alu_op_a_mux_sel_o = `OP_A_CURRPC; - alu_op_b_mux_sel_o = `OP_B_IMM; - alu_operator = `ALU_ADD; + 3'b001: begin + // lp.endi: set end address to PC + I-type immediate + hwloop_we_o[1] = 1'b1; + hwloop_end_mux_sel_o = 1'b0; // jump target // $display("%t: hwloop end address: %h", $time, instr_rdata_i); end - 3'b010: begin // lp.count initialize counter from register - hwloop_cnt_mux_sel_o = 2'b11; - hwloop_we_o[2] = 1'b1; // set we for counter reg + 3'b010: begin + // lp.count initialize counter from rs1 + hwloop_we_o[2] = 1'b1; + hwloop_cnt_mux_sel_o = 1'b1; rega_used = 1'b1; // $display("%t: hwloop counter: %h", $time, instr_rdata_i); end - 3'b011: begin // lp.counti initialize counter from immediate - hwloop_cnt_mux_sel_o = 2'b01; - hwloop_we_o[2] = 1'b1; // set we for counter reg + 3'b011: begin + // lp.counti initialize counter from I-type immediate + hwloop_we_o[2] = 1'b1; + hwloop_cnt_mux_sel_o = 1'b0; // $display("%t: hwloop counter imm: %h", $time, instr_rdata_i); end - 3'b100: begin // lp.setup - hwloop_wb_mux_sel_o = 1'b0; - hwloop_cnt_mux_sel_o = 2'b11; - hwloop_we_o = 3'b111; // set we for counter/start/end reg - alu_op_a_mux_sel_o = `OP_A_CURRPC; - alu_op_b_mux_sel_o = `OP_B_IMM; - alu_operator = `ALU_ADD; - // TODO: immediate_mux_sel_o = `IMM_16Z; - rega_used = 1'b1; + 3'b100: begin + // lp.setup: initialize counter from rs1, set start address to + // next instruction and end address to PC + I-type immediate + hwloop_we_o = 3'b111; + hwloop_start_mux_sel_o = 1'b1; + hwloop_end_mux_sel_o = 1'b0; + hwloop_cnt_mux_sel_o = 1'b1; + rega_used = 1'b1; // $display("%t: hwloop setup: %h", $time, instr_rdata_i); end - 3'b101: begin // lp.setupi - hwloop_wb_mux_sel_o = 1'b0; - hwloop_cnt_mux_sel_o = 2'b10; - hwloop_we_o = 3'b111; // set we for counter/start/end reg - alu_op_a_mux_sel_o = `OP_A_CURRPC; - alu_op_b_mux_sel_o = `OP_B_IMM; - alu_operator = `ALU_ADD; - // TODO: immediate_mux_sel_o = `IMM_8Z; + 3'b101: begin + // lp.setupi: initialize counter from I-type immediate, set start + // address to next instruction and end address to PC + shifted + // z-type immediate + hwloop_we_o = 3'b111; + hwloop_start_mux_sel_o = 1'b1; + hwloop_end_mux_sel_o = 1'b1; + hwloop_cnt_mux_sel_o = 1'b0; + illegal_insn_int = 1'b1; // TODO: PC + z-imm currently not supported // $display("%t: hwloop setup imm: %h", $time, instr_rdata_i); end default: begin @@ -922,10 +929,9 @@ module controller always_ff @(negedge clk) begin // print warning in case of decoding errors - // note: this is done intentionally before checking RVC decoding, to - // suppress wrong (and annoying) messages during simulation if (illegal_insn_o) begin - $warning("%t: Illegal instruction (core %0d) at PC 0x%h:", $time, riscv_core.core_id_i); + $display("%t: Illegal instruction (core %0d) at PC 0x%h:", $time, riscv_core.core_id_i, + id_stage.current_pc_id_i); //prettyPrintInstruction(instr_rdata_i, id_stage.current_pc_id_i); end end @@ -1023,6 +1029,11 @@ module controller ctrl_fsm_ns = BRANCH_DELAY; end + // handle hwloops + if (hwloop_jump_i) begin + pc_mux_sel_o = `PC_HWLOOP; + end + // handle illegal instructions if (illegal_insn_int) begin illegal_insn_o = 1'b1; diff --git a/cs_registers.sv b/cs_registers.sv index 0f423a9d..d01ef2b5 100644 --- a/cs_registers.sv +++ b/cs_registers.sv @@ -96,7 +96,6 @@ module cs_registers logic is_pcmr; // Generic CSRs - int csr_index; logic [31:0] csr [0:`CSR_MAX_IDX]; logic [31:0] csr_n [0:`CSR_MAX_IDX]; diff --git a/ex_stage.sv b/ex_stage.sv index 8c893b4e..9036666c 100644 --- a/ex_stage.sv +++ b/ex_stage.sv @@ -62,12 +62,6 @@ module ex_stage input logic regfile_we_i, input logic [4:0] regfile_waddr_i, - input logic [31:0] regfile_rb_data_i, - - input logic hwloop_wb_mux_sel_i, - input logic [31:0] hwloop_pc_plus4_i, - input logic [31:0] hwloop_cnt_i, - // CSR access input logic csr_access_i, input logic [31:0] csr_rdata_i, @@ -75,11 +69,6 @@ module ex_stage // Output of EX stage pipeline output logic [4:0] regfile_waddr_wb_o, output logic regfile_we_wb_o, - output logic [31:0] regfile_rb_data_wb_o, - - output logic [31:0] hwloop_start_data_o, - output logic [31:0] hwloop_end_data_o, - output logic [31:0] hwloop_cnt_data_o, // Forwarding ports : to ID stage output logic [4:0] regfile_alu_waddr_fw_o, @@ -113,21 +102,6 @@ module ex_stage regfile_alu_wdata_fw_o = csr_rdata_i; end - // hwloop mux. selects the right data to be sent to the hwloop registers (start/end-address and counter) - always_comb - begin : hwloop_start_mux - case (hwloop_wb_mux_sel_i) - 1'b0: hwloop_start_data_o = hwloop_pc_plus4_i; - 1'b1: hwloop_start_data_o = alu_result; - endcase - end - - // assign alu result to hwloop end data - assign hwloop_end_data_o = alu_result; - - // assign hwloop mux. selects the right data to be sent to the hwloop registers (start/end-address and counter) - assign hwloop_cnt_data_o = hwloop_cnt_i; - // Branch is taken when result[0] == 1'b1 assign branch_decision_o = alu_flag; assign jump_target_o = alu_operand_c_i; @@ -188,7 +162,6 @@ module ex_stage begin regfile_waddr_wb_o <= 5'b0_0000; regfile_we_wb_o <= 1'b0; - regfile_rb_data_wb_o <= 32'h0000_0000; end else begin @@ -196,7 +169,6 @@ module ex_stage begin regfile_we_wb_o <= regfile_we_i; regfile_waddr_wb_o <= regfile_waddr_i; - regfile_rb_data_wb_o <= regfile_rb_data_i; end end end diff --git a/exc_controller.sv b/exc_controller.sv index 5176255e..ac7dbc6f 100644 --- a/exc_controller.sv +++ b/exc_controller.sv @@ -48,7 +48,6 @@ module exc_controller // SPR output logic save_pc_if_o, // saves current_pc_if before entering interrupt routine output logic save_pc_id_o, // saves current_pc_id before entering interrupt routine - output logic save_sr_o, // saves status register // Controller input logic core_busy_i, // Is the controller currently in the IDLE state? @@ -146,14 +145,14 @@ module exc_controller end end - ////////////////////////////////////////////////////////////////////// - // _____ _ _ ____ _ _ // - // | ____|_ _____ ___ _ __ | |_(_) ___ _ __ / ___| |_ _ __| | // - // | _| \ \/ / __/ _ \ '_ \| __| |/ _ \| '_ \ | | | __| '__| | // - // | |___ > < (_| __/ |_) | |_| | (_) | | | | | |___| |_| | | | // - // |_____/_/\_\___\___| .__/ \__|_|\___/|_| |_| \____|\__|_| |_| // - // |_| // - ////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + // _____ _ _ ____ _ _ // + // | ____|_ _____ ___ _ __ | |_(_) ___ _ __ / ___| |_ _ __| | // + // | _| \ \/ / __/ _ \ '_ \| __| |/ _ \| '_ \ | | | __| '__| | // + // | |___ > < (_| __/ |_) | |_| | (_) | | | | | |___| |_| | | | // + // |_____/_/\_\___\___| .__/ \__|_|\___/|_| |_| \____|\__|_| |_| // + // |_| // + ///////////////////////////////////////////////////////////////////// // exception control FSM always_comb begin @@ -163,7 +162,6 @@ module exc_controller clear_exc_reason = 1'b0; save_pc_if_o = 1'b0; save_pc_id_o = 1'b0; - save_sr_o = 1'b0; force_nop_o = 1'b0; pc_valid_o = 1'b1; exc_pc_sel_o = 1'b0; @@ -184,7 +182,6 @@ module exc_controller force_nop_o = 1'b1; exc_pc_sel_o = 1'b1; save_pc_if_o = 1'b1; // save current PC - save_sr_o = 1'b1; // save Supervision Register if (irq_nm_i == 1'b1) // emergency IRQ has higher priority exc_pc_mux_o = `EXC_PC_IRQ_NM; @@ -208,7 +205,6 @@ module exc_controller exc_pc_sel_o = 1'b1; exc_pc_mux_o = `EXC_PC_ILLINSN; save_pc_id_o = 1'b1; // save current PC - save_sr_o = 1'b1; // save Supervision Register exc_running_n = 1'b1; clear_exc_reason = 1'b1; @@ -224,7 +220,6 @@ module exc_controller force_nop_o = 1'b1; exc_pc_sel_o = 1'b1; save_pc_if_o = 1'b1; // save current PC - save_sr_o = 1'b1; // save Supervision Register if (irq_nm_i == 1'b1) // emergency IRQ has higher priority exc_pc_mux_o = `EXC_PC_IRQ_NM; diff --git a/hwloop_controller.sv b/hwloop_controller.sv index 35f583f2..683edbc7 100644 --- a/hwloop_controller.sv +++ b/hwloop_controller.sv @@ -50,8 +50,11 @@ module hwloop_controller logic [`HWLOOP_REGS-1:0] pc_is_end_addr; + // end address detection + integer j; - // generate comparators. check for end address and the loop counter + + // generate comparators. check for end address and the loop counter genvar i; for (i = 0; i < `HWLOOP_REGS; i++) begin assign pc_is_end_addr[i] = ( @@ -65,30 +68,18 @@ module hwloop_controller assign hwloop_jump_o = |pc_is_end_addr; - // select corresponding start address and decrement counter. give highest priority to register 0 + // select corresponding start address and decrement counter always_comb begin hwloop_targ_addr_o = 32'b0; hwloop_dec_cnt_o = '0; - if (pc_is_end_addr[0]) begin - hwloop_targ_addr_o = hwloop_start_addr_i[0]; - hwloop_dec_cnt_o[0] = 1'b1; + for (j = `HWLOOP_REGS-1; j >= 0; j--) begin + if (pc_is_end_addr[j]) begin + hwloop_targ_addr_o = hwloop_start_addr_i[j]; + hwloop_dec_cnt_o[j] = 1'b1; + end end - else if (pc_is_end_addr[1]) begin - hwloop_targ_addr_o = hwloop_start_addr_i[1]; - hwloop_dec_cnt_o[1] = 1'b1; - end -/* -----\/----- EXCLUDED -----\/----- - else if (pc_is_end_addr[2]) begin - hwloop_targ_addr_o = hwloop_start_addr_i[2]; - hwloop_dec_cnt_o[2] = 1'b1; - end - else if (pc_is_end_addr[3]) begin - hwloop_targ_addr_o = hwloop_start_addr_i[3]; - hwloop_dec_cnt_o[3] = 1'b1; - end - -----/\----- EXCLUDED -----/\----- */ end endmodule diff --git a/id_stage.sv b/id_stage.sv index 91c64030..3934403d 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -93,12 +93,8 @@ module id_stage output logic prepost_useincr_ex_o, input logic data_misaligned_i, - output logic [2:0] hwloop_we_ex_o, - output logic [1:0] hwloop_regid_ex_o, - output logic hwloop_wb_mux_sel_ex_o, - output logic [31:0] hwloop_cnt_o, - output logic [`HWLOOP_REGS-1:0] hwloop_dec_cnt_o, - output logic [31:0] hwloop_targ_addr_o, + output logic [31:0] hwloop_targ_addr_o, + output logic hwloop_jump_o, output logic csr_access_ex_o, output logic [1:0] csr_op_ex_o, @@ -119,12 +115,6 @@ module id_stage input logic irq_enable_i, output logic save_pc_if_o, output logic save_pc_id_o, - output logic save_sr_o, - - // from hwloop regs - input logic [`HWLOOP_REGS-1:0] [31:0] hwloop_start_addr_i, - input logic [`HWLOOP_REGS-1:0] [31:0] hwloop_end_addr_i, - input logic [`HWLOOP_REGS-1:0] [31:0] hwloop_counter_i, // Debug Unit Signals input logic dbg_flush_pipe_i, @@ -169,8 +159,6 @@ module id_stage logic [31:0] immediate_b; // contains the immediate for operand b - logic [31:0] current_pc; // PC to be used in ALU (either IF or ID) - logic [31:0] jump_target; // calculated jump target (-> EX -> IF) logic exc_pc_sel; @@ -215,6 +203,8 @@ module id_stage logic [2:0] immediate_mux_sel; + logic [1:0] jump_target_mux_sel; + // Multiplier Control logic mult_en; // multiplication is used instead of ALU logic [1:0] mult_sel_subword; // Select a subword when doing multiplications @@ -235,11 +225,21 @@ module id_stage // hwloop signals logic [1:0] hwloop_regid; logic [2:0] hwloop_we; - logic hwloop_wb_mux_sel; - logic [1:0] hwloop_cnt_mux_sel; - logic [31:0] hwloop_cnt; logic hwloop_jump; logic hwloop_enable; + logic hwloop_start_mux_sel; + logic hwloop_end_mux_sel; + logic hwloop_cnt_mux_sel; + + logic [31:0] hwloop_start; + logic [31:0] hwloop_end; + logic [31:0] hwloop_cnt; + + // hwloop reg signals + logic [`HWLOOP_REGS-1:0] hwloop_dec_cnt; + logic [`HWLOOP_REGS-1:0] [31:0] hwloop_start_addr; + logic [`HWLOOP_REGS-1:0] [31:0] hwloop_end_addr; + logic [`HWLOOP_REGS-1:0] [31:0] hwloop_counter; // CSR control logic csr_access; @@ -296,25 +296,12 @@ module id_stage //assign alu_vec_ext = instr[9:8]; TODO assign alu_vec_ext = '0; - // Second Register Write Adress Selection // Used for prepost load/store and multiplier assign regfile_alu_waddr_id = regfile_alu_waddr_mux_sel ? regfile_waddr_id : regfile_addr_ra_id; - /////////////////////////////////////////////////////////////////////////////////////// - // ____ ____ _ // - // | _ \ _ __ ___ __ _ _ __ __ _ _ __ ___ / ___|___ _ _ _ __ | |_ ___ _ __ // - // | |_) | '__/ _ \ / _` | '__/ _` | '_ ` _ \ | | / _ \| | | | '_ \| __/ _ \ '__| // - // | __/| | | (_) | (_| | | | (_| | | | | | | | |__| (_) | |_| | | | | || __/ | // - // |_| |_| \___/ \__, |_| \__,_|_| |_| |_| \____\___/ \__,_|_| |_|\__\___|_| // - // |___/ // - /////////////////////////////////////////////////////////////////////////////////////// - - assign current_pc = current_pc_id_i; - - /////////////////////////////////////////////// // _ ___ ___ ___ ___ ____ // // | | | \ \ / / | / _ \ / _ \| _ \ // @@ -324,23 +311,39 @@ module id_stage // // /////////////////////////////////////////////// - // hwloop_cnt_mux + // hwloop register id + assign hwloop_regid = instr[8:7]; // rd contains hwloop register id + + // hwloop start mux + always_comb + begin + unique case (hwloop_start_mux_sel) + 1'b0: hwloop_start = jump_target; // for PC + I imm + 1'b1: hwloop_start = current_pc_if_i; // for next PC + endcase + end + + // hwloop end mux + always_comb + begin + unique case (hwloop_end_mux_sel) + 1'b0: hwloop_end = jump_target; // for PC + I imm + 1'b1: hwloop_end = jump_target; // TODO: PC + (Z imm << 1) for lp.setupi + endcase + end + + // hwloop cnt mux always_comb begin : hwloop_cnt_mux unique case (hwloop_cnt_mux_sel) - 2'b00: hwloop_cnt = 32'b0; - 2'b01: hwloop_cnt = imm_i_type; - 2'b10: hwloop_cnt = 32'b0; - 2'b11: hwloop_cnt = operand_a_fw_id; - endcase; // case (hwloop_cnt_mux_sel) + 1'b0: hwloop_cnt = imm_i_type; + 1'b1: hwloop_cnt = operand_a_fw_id; + endcase; end - // hwloop register id - assign hwloop_regid = instr[8:7]; // rd contains hwloop register id - ////////////////////////////////////////////////////////////////// - // _ _____ _ // + // _ _____ _ // // | |_ _ _ __ ___ _ __ |_ _|_ _ _ __ __ _ ___| |_ // // _ | | | | | '_ ` _ \| '_ \ | |/ _` | '__/ _` |/ _ \ __| // // | |_| | |_| | | | | | | |_) | | | (_| | | | (_| | __/ |_ // @@ -349,12 +352,12 @@ module id_stage ////////////////////////////////////////////////////////////////// always_comb - begin - unique case (jump_in_id_o) - `BRANCH_JAL: jump_target = current_pc_id_i + imm_uj_type; - `BRANCH_JALR: jump_target = regfile_data_ra_id + imm_i_type; // cannot forward rs1 as path is too long - `BRANCH_COND: jump_target = current_pc_id_i + imm_sb_type; - default: jump_target = current_pc_id_i + imm_sb_type; // replicate this as default to avoid another case + begin : jump_target_mux + unique case (jump_target_mux_sel) + `JT_JAL: jump_target = current_pc_id_i + imm_uj_type; + `JT_JALR: jump_target = regfile_data_ra_id + imm_i_type; // cannot forward rs1 as path is too long + `JT_COND: jump_target = current_pc_id_i + imm_sb_type; + `JT_HWLP: jump_target = current_pc_id_i + imm_i_type; endcase end @@ -373,24 +376,24 @@ module id_stage // ALU_Op_a Mux always_comb begin : alu_operand_a_mux - case (alu_op_a_mux_sel) - default: alu_operand_a = operand_a_fw_id; - `OP_A_REGA_OR_FWD: alu_operand_a = operand_a_fw_id; - `OP_A_CURRPC: alu_operand_a = current_pc; - `OP_A_ZIMM: alu_operand_a = imm_z_type; - `OP_A_ZERO: alu_operand_a = 32'b0; - endcase; // case (alu_op_a_mux_sel) + case (alu_op_a_mux_sel) + `OP_A_REGA_OR_FWD: alu_operand_a = operand_a_fw_id; + `OP_A_CURRPC: alu_operand_a = current_pc_id_i; + `OP_A_ZIMM: alu_operand_a = imm_z_type; + `OP_A_ZERO: alu_operand_a = 32'b0; + default: alu_operand_a = operand_a_fw_id; + endcase; // case (alu_op_a_mux_sel) end // Operand a forwarding mux always_comb begin : operand_a_fw_mux - case (operand_a_fw_mux_sel) - `SEL_FW_EX: operand_a_fw_id = regfile_alu_wdata_fw_i; - `SEL_FW_WB: operand_a_fw_id = regfile_wdata_wb_i; - `SEL_REGFILE: operand_a_fw_id = regfile_data_ra_id; - default: operand_a_fw_id = regfile_data_ra_id; - endcase; // case (operand_a_fw_mux_sel) + case (operand_a_fw_mux_sel) + `SEL_FW_EX: operand_a_fw_id = regfile_alu_wdata_fw_i; + `SEL_FW_WB: operand_a_fw_id = regfile_wdata_wb_i; + `SEL_REGFILE: operand_a_fw_id = regfile_data_ra_id; + default: operand_a_fw_id = regfile_data_ra_id; + endcase; // case (operand_a_fw_mux_sel) end ////////////////////////////////////////////////////// @@ -405,25 +408,25 @@ module id_stage // Immediate Mux for operand B always_comb begin : immediate_mux - unique case (immediate_mux_sel) - //`IMM_VEC: immediate_b = immediate_vec_id; - `IMM_I: immediate_b = imm_i_type; - `IMM_S: immediate_b = imm_s_type; - `IMM_U: immediate_b = imm_u_type; - `IMM_PCINCR: immediate_b = compressed_instr_o ? 32'h2 : 32'h4; - default: immediate_b = imm_i_type; - endcase; // case (immediate_mux_sel) + unique case (immediate_mux_sel) + //`IMM_VEC: immediate_b = immediate_vec_id; + `IMM_I: immediate_b = imm_i_type; + `IMM_S: immediate_b = imm_s_type; + `IMM_U: immediate_b = imm_u_type; + `IMM_PCINCR: immediate_b = compressed_instr_o ? 32'h2 : 32'h4; + default: immediate_b = imm_i_type; + endcase; // case (immediate_mux_sel) end // ALU_Op_b Mux always_comb begin : alu_operand_b_mux - case (alu_op_b_mux_sel) - default: operand_b = operand_b_fw_id; - `OP_B_REGB_OR_FWD: operand_b = operand_b_fw_id; - `OP_B_REGC_OR_FWD: operand_b = alu_operand_c; - `OP_B_IMM: operand_b = immediate_b; - endcase // case (alu_op_b_mux_sel) + case (alu_op_b_mux_sel) + `OP_B_REGB_OR_FWD: operand_b = operand_b_fw_id; + `OP_B_REGC_OR_FWD: operand_b = alu_operand_c; + `OP_B_IMM: operand_b = immediate_b; + default: operand_b = operand_b_fw_id; + endcase // case (alu_op_b_mux_sel) end // scalar replication for operand B @@ -436,12 +439,12 @@ module id_stage // Operand b forwarding mux always_comb begin : operand_b_fw_mux - case (operand_b_fw_mux_sel) - `SEL_FW_EX: operand_b_fw_id = regfile_alu_wdata_fw_i; - `SEL_FW_WB: operand_b_fw_id = regfile_wdata_wb_i; - `SEL_REGFILE: operand_b_fw_id = regfile_data_rb_id; - default: operand_b_fw_id = regfile_data_rb_id; - endcase; // case (operand_b_fw_mux_sel) + case (operand_b_fw_mux_sel) + `SEL_FW_EX: operand_b_fw_id = regfile_alu_wdata_fw_i; + `SEL_FW_WB: operand_b_fw_id = regfile_wdata_wb_i; + `SEL_REGFILE: operand_b_fw_id = regfile_data_rb_id; + default: operand_b_fw_id = regfile_data_rb_id; + endcase; // case (operand_b_fw_mux_sel) end @@ -466,12 +469,12 @@ module id_stage // Operand c forwarding mux always_comb begin : operand_c_fw_mux - case (operand_c_fw_mux_sel) - `SEL_FW_EX: alu_operand_c = regfile_alu_wdata_fw_i; - `SEL_FW_WB: alu_operand_c = regfile_wdata_wb_i; - `SEL_REGFILE: alu_operand_c = operand_c; - default: alu_operand_c = operand_c; - endcase; // case (operand_b_fw_mux_sel) + case (operand_c_fw_mux_sel) + `SEL_FW_EX: alu_operand_c = regfile_alu_wdata_fw_i; + `SEL_FW_WB: alu_operand_c = regfile_wdata_wb_i; + `SEL_REGFILE: alu_operand_c = operand_c; + default: alu_operand_c = operand_c; + endcase; // case (operand_b_fw_mux_sel) end @@ -523,115 +526,117 @@ module id_stage //////////////////////////////////////////////////////////////////// controller controller_i ( - .clk ( clk ), - .rst_n ( rst_n ), - .fetch_enable_i ( fetch_enable_i ), - .core_busy_o ( core_busy_o ), + .clk ( clk ), + .rst_n ( rst_n ), + .fetch_enable_i ( fetch_enable_i ), + .core_busy_o ( core_busy_o ), - // Signal from-to PC pipe (instr rdata) and instr mem system (req and ack) - .instr_rdata_i ( instr ), - .instr_req_o ( instr_req_o ), - .instr_gnt_i ( instr_gnt_i ), - .instr_ack_i ( instr_ack_i ), - .pc_mux_sel_o ( pc_mux_sel_int ), + // Signal from-to PC pipe (instr rdata) and instr mem system (req and ack) + .instr_rdata_i ( instr ), + .instr_req_o ( instr_req_o ), + .instr_gnt_i ( instr_gnt_i ), + .instr_ack_i ( instr_ack_i ), + .pc_mux_sel_o ( pc_mux_sel_int ), - // Alu signals - .alu_operator_o ( alu_operator ), - .alu_op_a_mux_sel_o ( alu_op_a_mux_sel ), - .alu_op_b_mux_sel_o ( alu_op_b_mux_sel ), - .alu_op_c_mux_sel_o ( alu_op_c_mux_sel ), - .immediate_mux_sel_o ( immediate_mux_sel ), + // Alu signals + .alu_operator_o ( alu_operator ), + .alu_op_a_mux_sel_o ( alu_op_a_mux_sel ), + .alu_op_b_mux_sel_o ( alu_op_b_mux_sel ), + .alu_op_c_mux_sel_o ( alu_op_c_mux_sel ), + .immediate_mux_sel_o ( immediate_mux_sel ), - .scalar_replication_o ( scalar_replication ), - .vector_mode_o ( vector_mode ), - .alu_cmp_mode_o ( alu_cmp_mode ), + .scalar_replication_o ( scalar_replication ), + .vector_mode_o ( vector_mode ), + .alu_cmp_mode_o ( alu_cmp_mode ), - // mult signals - .mult_en_o ( mult_en ), - .mult_sel_subword_o ( mult_sel_subword ), - .mult_signed_mode_o ( mult_signed_mode ), - .mult_mac_en_o ( mult_mac_en ), + // mult signals + .mult_en_o ( mult_en ), + .mult_sel_subword_o ( mult_sel_subword ), + .mult_signed_mode_o ( mult_signed_mode ), + .mult_mac_en_o ( mult_mac_en ), - // Register file control signals - .regfile_we_o ( regfile_we_id ), + // Register file control signals + .regfile_we_o ( regfile_we_id ), - .regfile_alu_we_o ( regfile_alu_we_id ), - .regfile_alu_waddr_mux_sel_o ( regfile_alu_waddr_mux_sel ), + .regfile_alu_we_o ( regfile_alu_we_id ), + .regfile_alu_waddr_mux_sel_o ( regfile_alu_waddr_mux_sel ), - .prepost_useincr_o ( prepost_useincr ), - .data_misaligned_i ( data_misaligned_i ), + .prepost_useincr_o ( prepost_useincr ), + .data_misaligned_i ( data_misaligned_i ), - // CSR control signals - .csr_access_o ( csr_access ), - .csr_op_o ( csr_op ), + // CSR control signals + .csr_access_o ( csr_access ), + .csr_op_o ( csr_op ), - // Data bus interface - .data_we_o ( data_we_id ), - .data_type_o ( data_type_id ), - .data_sign_extension_o ( data_sign_ext_id ), - .data_reg_offset_o ( data_reg_offset_id ), - .data_req_o ( data_req_id ), - .data_ack_i ( data_ack_i ), - .data_req_ex_i ( data_req_ex_o ), - .data_rvalid_i ( data_rvalid_i ), + // Data bus interface + .data_we_o ( data_we_id ), + .data_type_o ( data_type_id ), + .data_sign_extension_o ( data_sign_ext_id ), + .data_reg_offset_o ( data_reg_offset_id ), + .data_req_o ( data_req_id ), + .data_ack_i ( data_ack_i ), + .data_req_ex_i ( data_req_ex_o ), + .data_rvalid_i ( data_rvalid_i ), - // hwloop signals - .hwloop_we_o ( hwloop_we ), - .hwloop_wb_mux_sel_o ( hwloop_wb_mux_sel ), - .hwloop_cnt_mux_sel_o ( hwloop_cnt_mux_sel ), - .hwloop_jump_i ( hwloop_jump ), + // hwloop signals + .hwloop_we_o ( hwloop_we ), + .hwloop_start_mux_sel_o ( hwloop_start_mux_sel ), + .hwloop_end_mux_sel_o ( hwloop_end_mux_sel ), + .hwloop_cnt_mux_sel_o ( hwloop_cnt_mux_sel ), + .hwloop_jump_i ( hwloop_jump ), - // Interrupt signals - .irq_present_i ( irq_present ), + // Interrupt signals + .irq_present_i ( irq_present ), - // Exception Controller Signals - .illegal_c_insn_i ( illegal_c_insn ), - .illegal_insn_o ( illegal_insn ), - .trap_insn_o ( trap_insn ), - .pc_valid_i ( pc_valid ), - .clear_isr_running_o ( clear_isr_running ), - .trap_hit_i ( trap_hit ), - .exc_pipe_flush_i ( exc_pipe_flush ), + // Exception Controller Signals + .illegal_c_insn_i ( illegal_c_insn ), + .illegal_insn_o ( illegal_insn ), + .trap_insn_o ( trap_insn ), + .pc_valid_i ( pc_valid ), + .clear_isr_running_o ( clear_isr_running ), + .trap_hit_i ( trap_hit ), + .exc_pipe_flush_i ( exc_pipe_flush ), - // Debug Unit Signals - .dbg_stall_i ( dbg_stall_i ), - .dbg_set_npc_i ( dbg_set_npc_i ), - .dbg_trap_o ( dbg_trap_o ), + // Debug Unit Signals + .dbg_stall_i ( dbg_stall_i ), + .dbg_set_npc_i ( dbg_set_npc_i ), + .dbg_trap_o ( dbg_trap_o ), - // regfile port 1 - .regfile_waddr_ex_i ( regfile_waddr_ex_o ), // Write address for register file from ex-wb- pipeline registers - .regfile_we_ex_i ( regfile_we_ex_o ), - .regfile_waddr_wb_i ( regfile_waddr_wb_i ), // Write address for register file from ex-wb- pipeline registers - .regfile_we_wb_i ( regfile_we_wb_i ), + // regfile port 1 + .regfile_waddr_ex_i ( regfile_waddr_ex_o ), // Write address for register file from ex-wb- pipeline registers + .regfile_we_ex_i ( regfile_we_ex_o ), + .regfile_waddr_wb_i ( regfile_waddr_wb_i ), // Write address for register file from ex-wb- pipeline registers + .regfile_we_wb_i ( regfile_we_wb_i ), - // regfile port 2 - .regfile_alu_waddr_fw_i ( regfile_alu_waddr_fw_i ), - .regfile_alu_we_fw_i ( regfile_alu_we_fw_i ), + // regfile port 2 + .regfile_alu_waddr_fw_i ( regfile_alu_waddr_fw_i ), + .regfile_alu_we_fw_i ( regfile_alu_we_fw_i ), - // Forwarding signals - .operand_a_fw_mux_sel_o ( operand_a_fw_mux_sel ), - .operand_b_fw_mux_sel_o ( operand_b_fw_mux_sel ), - .operand_c_fw_mux_sel_o ( operand_c_fw_mux_sel ), + // Forwarding signals + .operand_a_fw_mux_sel_o ( operand_a_fw_mux_sel ), + .operand_b_fw_mux_sel_o ( operand_b_fw_mux_sel ), + .operand_c_fw_mux_sel_o ( operand_c_fw_mux_sel ), - // To controller (TODO: Remove when control/decode separated and moved) - .jump_in_ex_i ( jump_in_ex_o ), + // To controller (TODO: Remove when control/decode separated and moved) + .jump_target_mux_sel_o ( jump_target_mux_sel ), + .jump_in_ex_i ( jump_in_ex_o ), - .branch_decision_i ( branch_decision_i ), + .branch_decision_i ( branch_decision_i ), - // To exception controller and EX: Jump/Branch indication - .jump_in_id_o ( jump_in_id_o ), + // To exception controller and EX: Jump/Branch indication + .jump_in_id_o ( jump_in_id_o ), - // Stall signals - .stall_if_o ( stall_if_o ), - .stall_id_o ( stall_id_o ), - .stall_ex_o ( stall_ex_o ), - .stall_wb_o ( stall_wb_o ), + // Stall signals + .stall_if_o ( stall_if_o ), + .stall_id_o ( stall_id_o ), + .stall_ex_o ( stall_ex_o ), + .stall_wb_o ( stall_wb_o ), - // Performance Counters - .perf_jump_o ( perf_jump_o ), - .perf_branch_o ( perf_branch_o ), - .perf_jr_stall_o ( perf_jr_stall_o ), - .perf_ld_stall_o ( perf_ld_stall_o ) + // Performance Counters + .perf_jump_o ( perf_jump_o ), + .perf_branch_o ( perf_branch_o ), + .perf_jr_stall_o ( perf_jr_stall_o ), + .perf_ld_stall_o ( perf_ld_stall_o ) ); @@ -646,48 +651,47 @@ module id_stage exc_controller exc_controller_i ( - .clk ( clk ), - .rst_n ( rst_n ), + .clk ( clk ), + .rst_n ( rst_n ), - .fetch_enable_i ( fetch_enable_i ), + .fetch_enable_i ( fetch_enable_i ), - // to IF stage - .exc_pc_sel_o ( exc_pc_sel ), - .exc_pc_mux_o ( exc_pc_mux_o ), - .force_nop_o ( force_nop_exc ), + // to IF stage + .exc_pc_sel_o ( exc_pc_sel ), + .exc_pc_mux_o ( exc_pc_mux_o ), + .force_nop_o ( force_nop_exc ), - // hwloop signals - .hwloop_enable_o ( hwloop_enable ), + // hwloop signals + .hwloop_enable_o ( hwloop_enable ), - // Interrupt signals - .irq_i ( irq_i ), - .irq_nm_i ( irq_nm_i ), - .irq_enable_i ( irq_enable_i ), - .irq_present_o ( irq_present ), + // Interrupt signals + .irq_i ( irq_i ), + .irq_nm_i ( irq_nm_i ), + .irq_enable_i ( irq_enable_i ), + .irq_present_o ( irq_present ), - // CSR - .save_pc_if_o ( save_pc_if_o ), - .save_pc_id_o ( save_pc_id_o ), - .save_sr_o ( save_sr_o ), + // CSR + .save_pc_if_o ( save_pc_if_o ), + .save_pc_id_o ( save_pc_id_o ), - // Controller - .core_busy_i ( core_busy_o ), - .jump_in_id_i ( jump_in_id_o ), - .jump_in_ex_i ( jump_in_ex_o ), - .stall_id_i ( stall_id_o ), - .illegal_insn_i ( illegal_insn ), - .trap_insn_i ( trap_insn ), - .drop_instruction_i ( 1'b0 ), - .pc_valid_o ( pc_valid ), - .clear_isr_running_i ( clear_isr_running ), - .trap_hit_o ( trap_hit ), - .exc_pipe_flush_o ( exc_pipe_flush ), + // Controller + .core_busy_i ( core_busy_o ), + .jump_in_id_i ( jump_in_id_o ), + .jump_in_ex_i ( jump_in_ex_o ), + .stall_id_i ( stall_id_o ), + .illegal_insn_i ( illegal_insn ), + .trap_insn_i ( trap_insn ), + .drop_instruction_i ( 1'b0 ), + .pc_valid_o ( pc_valid ), + .clear_isr_running_i ( clear_isr_running ), + .trap_hit_o ( trap_hit ), + .exc_pipe_flush_o ( exc_pipe_flush ), - // Debug Unit Signals - .dbg_flush_pipe_i ( dbg_flush_pipe_i ), - .dbg_st_en_i ( dbg_st_en_i ), - .dbg_dsr_i ( dbg_dsr_i ) - ); + // Debug Unit Signals + .dbg_flush_pipe_i ( dbg_flush_pipe_i ), + .dbg_st_en_i ( dbg_st_en_i ), + .dbg_dsr_i ( dbg_dsr_i ) + ); ////////////////////////////////////////////////////////////////////////// @@ -700,25 +704,49 @@ module id_stage ////////////////////////////////////////////////////////////////////////// hwloop_controller hwloop_controller_i - ( - // from ID stage - .enable_i ( hwloop_enable ), - .current_pc_i ( current_pc_if_i ), + ( + // from ID stage + .enable_i ( hwloop_enable ), + .current_pc_i ( current_pc_if_i ), - // to ID controller - .hwloop_jump_o ( hwloop_jump ), + // to IF stage/controller + .hwloop_jump_o ( hwloop_jump ), + .hwloop_targ_addr_o ( hwloop_targ_addr_o ), - // to if stage - .hwloop_targ_addr_o ( hwloop_targ_addr_o ), + // from hwloop_regs + .hwloop_start_addr_i ( hwloop_start_addr ), + .hwloop_end_addr_i ( hwloop_end_addr ), + .hwloop_counter_i ( hwloop_counter ), - // from hwloop_regs - .hwloop_start_addr_i ( hwloop_start_addr_i ), - .hwloop_end_addr_i ( hwloop_end_addr_i ), - .hwloop_counter_i ( hwloop_counter_i ), + // to hwloop_regs + .hwloop_dec_cnt_o ( hwloop_dec_cnt ) + ); - // to hwloop_regs - .hwloop_dec_cnt_o ( hwloop_dec_cnt_o ) - ); + assign hwloop_jump_o = hwloop_jump; + + hwloop_regs hwloop_regs_i + ( + .clk ( clk ), + .rst_n ( rst_n ), + + // from ID + .hwloop_start_data_i ( hwloop_start ), + .hwloop_end_data_i ( hwloop_end ), + .hwloop_cnt_data_i ( hwloop_cnt ), + .hwloop_we_i ( hwloop_we ), + .hwloop_regid_i ( hwloop_regid ), + + // from controller + .stall_id_i ( stall_id_o ), + + // to hwloop controller + .hwloop_start_addr_o ( hwloop_start_addr ), + .hwloop_end_addr_o ( hwloop_end_addr ), + .hwloop_counter_o ( hwloop_counter ), + + // from hwloop controller + .hwloop_dec_cnt_i ( hwloop_dec_cnt ) + ); ///////////////////////////////////////////////////////////////////////////////// @@ -767,11 +795,6 @@ module id_stage data_misaligned_ex_o <= 1'b0; - hwloop_we_ex_o <= 3'b0; - hwloop_regid_ex_o <= 2'b0; - hwloop_wb_mux_sel_ex_o <= 1'b0; - hwloop_cnt_o <= 32'b0; - jump_in_ex_o <= 2'b0; end @@ -830,13 +853,7 @@ module id_stage data_misaligned_ex_o <= 1'b0; - hwloop_we_ex_o <= hwloop_we; - hwloop_regid_ex_o <= hwloop_regid; - hwloop_wb_mux_sel_ex_o <= hwloop_wb_mux_sel; - hwloop_cnt_o <= hwloop_cnt; - jump_in_ex_o <= jump_in_id_o; - end end diff --git a/if_stage.sv b/if_stage.sv index 24704715..1d28afde 100644 --- a/if_stage.sv +++ b/if_stage.sv @@ -61,7 +61,6 @@ module if_stage // Forwarding ports - control signals input logic force_nop_i, // insert a NOP in the pipe input logic [31:0] exception_pc_reg_i, // address used to restore PC when the interrupt/exception is served - input logic [31:0] pc_from_hwloop_i, // pc from hwloop start addr input logic [2:0] pc_mux_sel_i, // sel for pc multiplexer input logic [1:0] exc_pc_mux_i, // select which exception to execute @@ -72,6 +71,10 @@ module if_stage input logic [31:0] jump_target_ex_i, // jump target address input logic branch_decision_i, + // from hwloop controller + input logic hwloop_jump_i, + input logic [31:0] hwloop_target_i, // pc from hwloop start addr + // from debug unit input logic [31:0] dbg_npc_i, input logic dbg_set_npc_i, @@ -160,7 +163,7 @@ module if_stage `PC_INCR: fetch_addr_n = fetch_addr_Q + 32'd4; // incremented PC `PC_EXCEPTION: fetch_addr_n = exc_pc; // set PC to exception handler `PC_ERET: fetch_addr_n = exception_pc_reg_i; // PC is restored when returning from IRQ/exception - `PC_HWLOOP: fetch_addr_n = pc_from_hwloop_i; // PC is taken from hwloop start addr + `PC_HWLOOP: fetch_addr_n = hwloop_target_i; // PC is taken from hwloop start addr `PC_DBG_NPC: fetch_addr_n = dbg_npc_i; // PC is taken from debug unit default: begin @@ -180,7 +183,7 @@ module if_stage `PC_JUMP: unaligned_jump = jump_target_id_i[1]; `PC_BRANCH: unaligned_jump = jump_target_ex_i[1]; `PC_ERET: unaligned_jump = exception_pc_reg_i[1]; - `PC_HWLOOP: unaligned_jump = pc_from_hwloop_i[1]; + `PC_HWLOOP: unaligned_jump = hwloop_target_i[1]; `PC_DBG_NPC: unaligned_jump = dbg_npc_i[1]; endcase end @@ -389,7 +392,10 @@ module if_stage offset_fsm_ns = WAIT_JUMPED_ALIGNED; end - end else if (jump_in_id_i == `BRANCH_JAL || jump_in_id_i == `BRANCH_JALR || dbg_set_npc_i) begin + end else if (jump_in_id_i == `BRANCH_JAL || jump_in_id_i == `BRANCH_JALR + || dbg_set_npc_i + || hwloop_jump_i) begin + // switch to new PC from ID stage fetch_req = 1'b1; if (unaligned_jump) offset_fsm_ns = WAIT_JUMPED_UNALIGNED; diff --git a/include/defines.sv b/include/defines.sv index ec1fe205..70b234b2 100644 --- a/include/defines.sv +++ b/include/defines.sv @@ -341,6 +341,12 @@ endfunction // prettyPrintInstruction `define BRANCH_JALR 2'b10 `define BRANCH_COND 2'b11 // conditional branches +// jump target mux +`define JT_HWLP 2'b00 +`define JT_JAL 2'b01 +`define JT_JALR 2'b10 +`define JT_COND 2'b11 + /////////////////////////////////////////////// // ___ _____ ____ _ // diff --git a/riscv_core.sv b/riscv_core.sv index a5b8da56..a003d465 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -116,7 +116,6 @@ module riscv_core // Register Data logic [31:0] regfile_rb_data_ex; // from id stage to load/store unit and ex stage - logic [31:0] regfile_rb_data_wb; // from ex stage to sp register // ALU Control @@ -165,7 +164,6 @@ module riscv_core logic data_sign_ext_ex; logic [1:0] data_reg_offset_ex; logic data_req_ex; - logic [31:0] data_addr_ex; logic data_misaligned_ex; logic data_ack_int; @@ -180,28 +178,9 @@ module riscv_core logic save_pc_id; - // hwloop data from ALU - logic [31:0] hwlp_cnt_ex; // from id to ex stage (hwloop_regs) - logic [2:0] hwlp_we_ex; // from id to ex stage (hwloop_regs) - logic [1:0] hwlp_regid_ex; // from id to ex stage (hwloop_regs) - logic hwlp_wb_mux_sel_ex; // from id to ex stage (hwloop_regs) - logic [31:0] hwlp_start_data_ex; // hwloop data to write to hwloop_regs - logic [31:0] hwlp_end_data_ex; // hwloop data to write to hwloop_regs - logic [31:0] hwlp_cnt_data_ex; // hwloop data to write to hwloop_regs - - // Access to hwloop registers - logic [31:0] hwlp_start_data; - logic [31:0] hwlp_end_data; - logic [31:0] hwlp_cnt_data; - logic [2:0] hwlp_we; - logic [1:0] hwlp_regid; - - // hwloop controller signals - logic [`HWLOOP_REGS-1:0] [31:0] hwlp_start_addr; // to hwloop controller - logic [`HWLOOP_REGS-1:0] [31:0] hwlp_end_addr; // to hwloop controller - logic [`HWLOOP_REGS-1:0] [31:0] hwlp_counter; // to hwloop controller - logic [`HWLOOP_REGS-1:0] hwlp_dec_cnt; // from hwloop controller to hwloop regs - logic [31:0] hwlp_targ_addr; // from hwloop controller to if stage + // Hardware loop controller signals + logic hwloop_jump; + logic [31:0] hwloop_target; // from hwloop controller to if stage // Debug Unit @@ -268,10 +247,13 @@ module riscv_core // Forwrding ports - control signals .force_nop_i ( force_nop_id ), // select incoming instr or NOP .exception_pc_reg_i ( epcr ), // Exception PC register - .pc_from_hwloop_i ( hwlp_targ_addr ), // pc from hwloop start address .pc_mux_sel_i ( pc_mux_sel_id ), // sel for pc multiplexer .exc_pc_mux_i ( exc_pc_mux_id ), // selector for exception multiplexer + // from hwloop controller + .hwloop_jump_i ( hwloop_jump ), + .hwloop_target_i ( hwloop_target ), // pc from hwloop start address + // from debug unit .dbg_npc_i ( dbg_npc ), .dbg_set_npc_i ( dbg_set_npc ), @@ -301,126 +283,117 @@ module riscv_core ///////////////////////////////////////////////// id_stage id_stage_i ( - .clk ( clk ), - .rst_n ( rst_n ), + .clk ( clk ), + .rst_n ( rst_n ), // Processor Enable - .fetch_enable_i ( fetch_enable_i ), + .fetch_enable_i ( fetch_enable_i ), - .jump_in_id_o ( jump_in_id ), - .jump_in_ex_o ( jump_in_ex ), - .branch_decision_i ( branch_decision ), + .jump_in_id_o ( jump_in_id ), + .jump_in_ex_o ( jump_in_ex ), + .branch_decision_i ( branch_decision ), - .jump_target_o ( jump_target_id ), + .jump_target_o ( jump_target_id ), - .core_busy_o ( core_busy ), + .core_busy_o ( core_busy ), // Interface to instruction memory - .instr_rdata_i ( instr_rdata_id ), - .instr_req_o ( instr_req_int ), - .instr_gnt_i ( instr_grant_i ), - .instr_ack_i ( instr_ack_int ), + .instr_rdata_i ( instr_rdata_id ), + .instr_req_o ( instr_req_int ), + .instr_gnt_i ( instr_grant_i ), + .instr_ack_i ( instr_ack_int ), - .pc_mux_sel_o ( pc_mux_sel_id ), - .exc_pc_mux_o ( exc_pc_mux_id ), - .force_nop_o ( force_nop_id ), + .pc_mux_sel_o ( pc_mux_sel_id ), + .exc_pc_mux_o ( exc_pc_mux_id ), + .force_nop_o ( force_nop_id ), - .current_pc_if_i ( current_pc_if ), - .current_pc_id_i ( current_pc_id ), + .current_pc_if_i ( current_pc_if ), + .current_pc_id_i ( current_pc_id ), - .compressed_instr_o ( compressed_instr ), + .compressed_instr_o ( compressed_instr ), // STALLS - .stall_if_o ( stall_if ), - .stall_id_o ( stall_id ), - .stall_ex_o ( stall_ex ), - .stall_wb_o ( stall_wb ), + .stall_if_o ( stall_if ), + .stall_id_o ( stall_id ), + .stall_ex_o ( stall_ex ), + .stall_wb_o ( stall_wb ), // From the Pipeline ID/EX - .regfile_rb_data_ex_o ( regfile_rb_data_ex ), + .regfile_rb_data_ex_o ( regfile_rb_data_ex ), - .alu_operand_a_ex_o ( alu_operand_a_ex ), - .alu_operand_b_ex_o ( alu_operand_b_ex ), - .alu_operand_c_ex_o ( alu_operand_c_ex ), - .alu_operator_ex_o ( alu_operator_ex ), + .alu_operand_a_ex_o ( alu_operand_a_ex ), + .alu_operand_b_ex_o ( alu_operand_b_ex ), + .alu_operand_c_ex_o ( alu_operand_c_ex ), + .alu_operator_ex_o ( alu_operator_ex ), - .vector_mode_ex_o ( vector_mode_ex ), // from ID to EX stage - .alu_cmp_mode_ex_o ( alu_cmp_mode_ex ), // from ID to EX stage - .alu_vec_ext_ex_o ( alu_vec_ext_ex ), // from ID to EX stage + .vector_mode_ex_o ( vector_mode_ex ), // from ID to EX stage + .alu_cmp_mode_ex_o ( alu_cmp_mode_ex ), // from ID to EX stage + .alu_vec_ext_ex_o ( alu_vec_ext_ex ), // from ID to EX stage - .mult_en_ex_o ( mult_en_ex ), // from ID to EX stage - .mult_sel_subword_ex_o ( mult_sel_subword_ex ), // from ID to EX stage - .mult_signed_mode_ex_o ( mult_signed_mode_ex ), // from ID to EX stage - .mult_mac_en_ex_o ( mult_mac_en_ex ), // from ID to EX stage + .mult_en_ex_o ( mult_en_ex ), // from ID to EX stage + .mult_sel_subword_ex_o ( mult_sel_subword_ex ), // from ID to EX stage + .mult_signed_mode_ex_o ( mult_signed_mode_ex ), // from ID to EX stage + .mult_mac_en_ex_o ( mult_mac_en_ex ), // from ID to EX stage - .regfile_waddr_ex_o ( regfile_waddr_ex ), - .regfile_we_ex_o ( regfile_we_ex ), + .regfile_waddr_ex_o ( regfile_waddr_ex ), + .regfile_we_ex_o ( regfile_we_ex ), - .regfile_alu_we_ex_o ( regfile_alu_we_ex ), - .regfile_alu_waddr_ex_o ( regfile_alu_waddr_ex ), + .regfile_alu_we_ex_o ( regfile_alu_we_ex ), + .regfile_alu_waddr_ex_o ( regfile_alu_waddr_ex ), // CSR ID/EX - .csr_access_ex_o ( csr_access_ex ), - .csr_op_ex_o ( csr_op_ex ), + .csr_access_ex_o ( csr_access_ex ), + .csr_op_ex_o ( csr_op_ex ), // hwloop signals - .hwloop_we_ex_o ( hwlp_we_ex ), - .hwloop_regid_ex_o ( hwlp_regid_ex ), - .hwloop_wb_mux_sel_ex_o ( hwlp_wb_mux_sel_ex ), - .hwloop_cnt_o ( hwlp_cnt_ex ), - .hwloop_dec_cnt_o ( hwlp_dec_cnt ), - .hwloop_targ_addr_o ( hwlp_targ_addr ), + .hwloop_jump_o ( hwloop_jump ), + .hwloop_targ_addr_o ( hwloop_target ), - .prepost_useincr_ex_o ( useincr_addr_ex ), - .data_misaligned_i ( data_misaligned ), + .prepost_useincr_ex_o ( useincr_addr_ex ), + .data_misaligned_i ( data_misaligned ), - .data_we_ex_o ( data_we_ex ), // to load store unit - .data_type_ex_o ( data_type_ex ), // to load store unit - .data_sign_ext_ex_o ( data_sign_ext_ex ), // to load store unit - .data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit - .data_req_ex_o ( data_req_ex ), // to load store unit - .data_misaligned_ex_o ( data_misaligned_ex ), // to load store unit - .data_ack_i ( data_ack_int ), // from load store unit - .data_rvalid_i ( data_r_valid_i ), + .data_we_ex_o ( data_we_ex ), // to load store unit + .data_type_ex_o ( data_type_ex ), // to load store unit + .data_sign_ext_ex_o ( data_sign_ext_ex ), // to load store unit + .data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit + .data_req_ex_o ( data_req_ex ), // to load store unit + .data_misaligned_ex_o ( data_misaligned_ex ), // to load store unit + .data_ack_i ( data_ack_int ), // from load store unit + .data_rvalid_i ( data_r_valid_i ), // Interrupt Signals - .irq_i ( irq_i ), // incoming interrupts - .irq_nm_i ( irq_nm_i ), // incoming interrupts - .irq_enable_i ( irq_enable ), // global interrupt enable - .save_pc_if_o ( save_pc_if ), // control signal to save pc - .save_pc_id_o ( save_pc_id ), // control signal to save pc - - // from hwloop regs - .hwloop_start_addr_i ( hwlp_start_addr ), - .hwloop_end_addr_i ( hwlp_end_addr ), - .hwloop_counter_i ( hwlp_counter ), + .irq_i ( irq_i ), // incoming interrupts + .irq_nm_i ( irq_nm_i ), // incoming interrupts + .irq_enable_i ( irq_enable ), // global interrupt enable + .save_pc_if_o ( save_pc_if ), // control signal to save pc + .save_pc_id_o ( save_pc_id ), // control signal to save pc // Debug Unit Signals - .dbg_flush_pipe_i ( dbg_flush_pipe ), - .dbg_st_en_i ( dbg_st_en ), - .dbg_dsr_i ( dbg_dsr ), - .dbg_stall_i ( dbg_stall ), - .dbg_trap_o ( dbg_trap ), - .dbg_reg_mux_i ( dbg_reg_mux ), - .dbg_reg_we_i ( dbg_reg_we ), - .dbg_reg_addr_i ( dbg_reg_addr[4:0] ), - .dbg_reg_wdata_i ( dbg_reg_wdata ), - .dbg_reg_rdata_o ( dbg_reg_rdata ), - .dbg_set_npc_i ( dbg_set_npc ), + .dbg_flush_pipe_i ( dbg_flush_pipe ), + .dbg_st_en_i ( dbg_st_en ), + .dbg_dsr_i ( dbg_dsr ), + .dbg_stall_i ( dbg_stall ), + .dbg_trap_o ( dbg_trap ), + .dbg_reg_mux_i ( dbg_reg_mux ), + .dbg_reg_we_i ( dbg_reg_we ), + .dbg_reg_addr_i ( dbg_reg_addr[4:0] ), + .dbg_reg_wdata_i ( dbg_reg_wdata ), + .dbg_reg_rdata_o ( dbg_reg_rdata ), + .dbg_set_npc_i ( dbg_set_npc ), // Forward Signals - .regfile_alu_waddr_fw_i ( regfile_alu_waddr_fw ), - .regfile_alu_we_fw_i ( regfile_alu_we_fw ), - .regfile_alu_wdata_fw_i ( regfile_alu_wdata_fw ), + .regfile_alu_waddr_fw_i ( regfile_alu_waddr_fw ), + .regfile_alu_we_fw_i ( regfile_alu_we_fw ), + .regfile_alu_wdata_fw_i ( regfile_alu_wdata_fw ), - .regfile_waddr_wb_i ( regfile_waddr_fw_wb_o ), // Write address ex-wb pipeline - .regfile_we_wb_i ( regfile_we_wb ), // write enable for the register file - .regfile_wdata_wb_i ( regfile_wdata ), // write data to commit in the register file + .regfile_waddr_wb_i ( regfile_waddr_fw_wb_o), // Write address ex-wb pipeline + .regfile_we_wb_i ( regfile_we_wb ), // write enable for the register file + .regfile_wdata_wb_i ( regfile_wdata ), // write data to commit in the register file - .perf_jump_o ( perf_jump ), - .perf_branch_o ( perf_branch ), - .perf_jr_stall_o ( perf_jr_stall ), - .perf_ld_stall_o ( perf_ld_stall ) + .perf_jump_o ( perf_jump ), + .perf_branch_o ( perf_branch ), + .perf_jr_stall_o ( perf_jr_stall ), + .perf_ld_stall_o ( perf_ld_stall ) ); @@ -468,23 +441,9 @@ module riscv_core .regfile_alu_we_i ( regfile_alu_we_ex ), .regfile_alu_waddr_i ( regfile_alu_waddr_ex ), - // From ID stage: hwloop wb reg signals - .hwloop_wb_mux_sel_i ( hwlp_wb_mux_sel_ex ), - .hwloop_pc_plus4_i ( current_pc_id ), - .hwloop_cnt_i ( hwlp_cnt_ex ), - - //From ID stage.Controller - .regfile_rb_data_i ( regfile_rb_data_ex ), - // Output of ex stage pipeline .regfile_waddr_wb_o ( regfile_waddr_fw_wb_o ), .regfile_we_wb_o ( regfile_we_wb ), - .regfile_rb_data_wb_o ( regfile_rb_data_wb ), - - // To hwloop regs - .hwloop_start_data_o ( hwlp_start_data_ex ), - .hwloop_end_data_o ( hwlp_end_data_ex ), - .hwloop_cnt_data_o ( hwlp_cnt_data_ex ), // To IF: Jump and branch target and decision .jump_target_o ( jump_target_ex ), @@ -603,40 +562,6 @@ module riscv_core assign dbg_rdata = (dbg_sp_mux == 1'b0) ? dbg_reg_rdata : csr_rdata; - ////////////////////////////////////////////// - // Hardware Loop Registers // - ////////////////////////////////////////////// - hwloop_regs hwloop_regs_i - ( - .clk ( clk ), - .rst_n ( rst_n ), - - // from ex stage - .hwloop_start_data_i ( hwlp_start_data ), - .hwloop_end_data_i ( hwlp_end_data ), - .hwloop_cnt_data_i ( hwlp_cnt_data ), - .hwloop_we_i ( hwlp_we ), - .hwloop_regid_i ( hwlp_regid ), - - // from controller - .stall_id_i ( stall_id ), - - // to hwloop controller - .hwloop_start_addr_o ( hwlp_start_addr ), - .hwloop_end_addr_o ( hwlp_end_addr ), - .hwloop_counter_o ( hwlp_counter ), - - // from hwloop controller - .hwloop_dec_cnt_i ( hwlp_dec_cnt ) - ); - - assign hwlp_start_data = hwlp_start_data_ex; - assign hwlp_end_data = hwlp_end_data_ex; - assign hwlp_cnt_data = hwlp_cnt_data_ex; - assign hwlp_regid = hwlp_regid_ex; - assign hwlp_we = hwlp_we_ex; - - ///////////////////////////////////////////////////////////// // ____ _____ ____ _ _ ____ _ _ _ _ ___ _____ // // | _ \| ____| __ )| | | |/ ___| | | | | \ | |_ _|_ _| //