diff --git a/README.md b/README.md index b27ab3b2..69b940c0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # RI5CY: RISC-V Core -RI5CY is a small 4-stage RISC-V core. It starte its life as a -fork of the OR10N cpu core that is based on the OpenRISC ISA. +RI5CY is a small 4-stage RISC-V core. It started its life as a +fork of the OR10N CPU core that is based on the OpenRISC ISA. RI5CY fully implements the RV32I instruction set, the multiply instruction from RV32M and many custom instruction set extensions that improve its performance @@ -19,4 +19,3 @@ in `docs/datasheet/`. It is written using LaTeX and can be generated as follows make all - diff --git a/alu.sv b/alu.sv index 8c11dc1b..45cc0730 100644 --- a/alu.sv +++ b/alu.sv @@ -107,7 +107,7 @@ module riscv_alu logic [35:0] adder_result_expanded; assign adder_op_b_negate = (operator_i == ALU_SUB) || (operator_i == ALU_SUBR) || - (operator_i == ALU_SUBU) || (operator_i == ALU_SUBR); + (operator_i == ALU_SUBU) || (operator_i == ALU_SUBUR); // prepare operand a assign adder_op_a = (operator_i == ALU_ABS) ? operand_a_neg : operand_a_i; @@ -472,8 +472,8 @@ module riscv_alu assign clip_is_lower_neg = adder_result[31]; assign clip_is_lower_u = (operator_i == ALU_CLIPU) && operand_a_i[31]; - assign clip_result = clip_is_lower_u ? '0 : (clip_is_lower_neg ? operand_b_neg : result_minmax); - + //assign clip_result = clip_is_lower_u ? '0 : (clip_is_lower_neg ? operand_b_neg : result_minmax); + assign clip_result = is_greater ? result_minmax: (clip_is_lower_u ? '0 : (clip_is_lower_neg ? operand_b_neg : result_minmax)); ////////////////////////////////////////////////// // ____ _ _ _ _ _____ _____ _ _____ // // / ___|| | | | | | | ___| ___| | | ____| // diff --git a/controller.sv b/controller.sv index c824eb1a..f8cc267e 100644 --- a/controller.sv +++ b/controller.sv @@ -76,10 +76,12 @@ module riscv_controller // Exception Controller Signals input logic exc_req_i, + input logic ext_req_i, output logic exc_ack_o, output logic exc_save_if_o, output logic exc_save_id_o, + output logic exc_save_takenbranch_o, output logic exc_restore_id_o, // Debug Signals @@ -175,6 +177,7 @@ module riscv_controller exc_ack_o = 1'b0; exc_save_if_o = 1'b0; exc_save_id_o = 1'b0; + exc_save_takenbranch_o = 1'b0; exc_restore_id_o = 1'b0; pc_mux_o = PC_BOOT; @@ -352,6 +355,20 @@ module riscv_controller end end + if (~instr_valid_i && (~branch_taken_ex_i)) begin + 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_if_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 + end + // TODO: make sure this is not done multiple times in a row!!! // maybe with an assertion? // handle conditional branches @@ -365,6 +382,17 @@ module riscv_controller // 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; @@ -600,5 +628,7 @@ module riscv_controller // possible without branch prediction in the IF stage assert property ( @(posedge clk) (branch_taken_ex_i) |=> (~branch_taken_ex_i) ) else $warning("Two branches back-to-back are taken"); + assert property ( + @(posedge clk) (~(dbg_req_i & ext_req_i)) ) else $warning("Both dbg_req_i and ext_req_i are active"); endmodule // controller diff --git a/cs_registers.sv b/cs_registers.sv index 3afde2b5..ce152603 100644 --- a/cs_registers.sv +++ b/cs_registers.sv @@ -63,9 +63,11 @@ module riscv_cs_registers input logic [31:0] pc_if_i, input logic [31:0] pc_id_i, input logic [31:0] pc_ex_i, + input logic [31:0] branch_target_i, input logic data_load_event_ex_i, input logic exc_save_if_i, input logic exc_save_id_i, + input logic exc_save_takenbranch_i, input logic exc_restore_i, input logic [5:0] exc_cause_i, @@ -222,12 +224,14 @@ module riscv_cs_registers endcase // exception controller gets priority over other writes - if (exc_save_if_i || exc_save_id_i) begin + if (exc_save_if_i || exc_save_id_i || exc_save_takenbranch_i) begin mestatus_n = mstatus_q; mstatus_n = 1'b0; if (data_load_event_ex_i) begin mepc_n = pc_ex_i; + end else if (exc_save_takenbranch_i) begin + mepc_n = branch_target_i; end else begin if (exc_save_if_i) mepc_n = pc_if_i; @@ -483,4 +487,7 @@ module riscv_cs_registers end end + assert property ( + @(posedge clk) (~(exc_save_takenbranch_i & data_load_event_ex_i)) ) else $display("Both exc_save_takenbranch_i and data_load_event_ex_i are active"); + endmodule diff --git a/decoder.sv b/decoder.sv index 420f78de..4a8d5c6f 100644 --- a/decoder.sv +++ b/decoder.sv @@ -53,7 +53,9 @@ module riscv_decoder `ifdef BIT_SUPPORT output logic bmask_needed_o, // registers for bit manipulation mask is needed output logic [ 0:0] bmask_a_mux_o, // bit manipulation mask a mux - output logic [ 1:0] bmask_b_mux_o, // bit manipulation mask a mux + output logic [ 1:0] bmask_b_mux_o, // bit manipulation mask b mux + output logic alu_bmask_a_mux_sel_o, // bit manipulation mask a mux (reg or imm) + output logic alu_bmask_b_mux_sel_o, // bit manipulation mask b mux (reg or imm) `endif // BIT_SUPPORT // from IF/ID pipeline @@ -62,8 +64,8 @@ module riscv_decoder // ALU signals output logic [ALU_OP_WIDTH-1:0] alu_operator_o, // ALU operation selection - output logic [1:0] alu_op_a_mux_sel_o, // operand a selection: reg value, PC, immediate or zero - output logic [1:0] alu_op_b_mux_sel_o, // operand b selection: reg value or immediate + 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 [1:0] alu_op_c_mux_sel_o, // operand c selection: reg value or jump target // CONFIG_REGION: VEC_SUPPORT `ifdef VEC_SUPPORT @@ -136,6 +138,8 @@ module riscv_decoder logic [1:0] csr_op; + logic davide; + ///////////////////////////////////////////// // ____ _ // @@ -215,6 +219,9 @@ module riscv_decoder bmask_needed_o = 1'b1; // TODO: only use when necessary bmask_a_mux_o = BMASK_A_ZERO; bmask_b_mux_o = BMASK_B_ZERO; + alu_bmask_a_mux_sel_o = BMASK_A_IMM; + alu_bmask_b_mux_sel_o = BMASK_B_IMM; + davide = '0; `endif // BIT_SUPPORT @@ -474,21 +481,33 @@ module riscv_decoder // CONFIG_REGION: BIT_SUPPORT `ifdef BIT_SUPPORT // bit-manipulation instructions - alu_op_b_mux_sel_o = OP_B_IMM; bmask_needed_o = 1'b1; bmask_a_mux_o = BMASK_A_S3; bmask_b_mux_o = BMASK_B_S2; + alu_op_b_mux_sel_o = OP_B_IMM; unique case (instr_rdata_i[14:12]) 3'b000: begin alu_operator_o = ALU_BEXT; imm_b_mux_sel_o = IMMB_S2; bmask_b_mux_o = BMASK_B_ZERO; + if (~instr_rdata_i[30]) begin + //register variant + alu_op_b_mux_sel_o = OP_B_BMASK; + alu_bmask_a_mux_sel_o = BMASK_A_REG; + regb_used_o = 1'b1; + end end 3'b001: begin alu_operator_o = ALU_BEXTU; imm_b_mux_sel_o = IMMB_S2; bmask_b_mux_o = BMASK_B_ZERO; + if (~instr_rdata_i[30]) begin + //register variant + alu_op_b_mux_sel_o = OP_B_BMASK; + alu_bmask_a_mux_sel_o = BMASK_A_REG; + regb_used_o = 1'b1; + end end 3'b010: begin @@ -496,10 +515,35 @@ module riscv_decoder imm_b_mux_sel_o = IMMB_S2; regc_used_o = 1'b1; regc_mux_o = REGC_RD; + if (~instr_rdata_i[30]) begin + //register variant + alu_op_b_mux_sel_o = OP_B_BMASK; + alu_bmask_a_mux_sel_o = BMASK_A_REG; + alu_bmask_b_mux_sel_o = BMASK_B_REG; + regb_used_o = 1'b1; + end end - 3'b011: begin alu_operator_o = ALU_BCLR; end - 3'b100: begin alu_operator_o = ALU_BSET; end + 3'b011: begin + alu_operator_o = ALU_BCLR; + if (~instr_rdata_i[30]) begin + //register variant + regb_used_o = 1'b1; + alu_bmask_a_mux_sel_o = BMASK_A_REG; + alu_bmask_b_mux_sel_o = BMASK_B_REG; + end + end + + 3'b100: begin + alu_operator_o = ALU_BSET; + davide = 1'b1; + if (~instr_rdata_i[30]) begin + //register variant + regb_used_o = 1'b1; + alu_bmask_a_mux_sel_o = BMASK_A_REG; + alu_bmask_b_mux_sel_o = BMASK_B_REG; + end + end default: illegal_insn_o = 1'b1; endcase @@ -640,17 +684,27 @@ module riscv_decoder {6'b00_1010, 3'b001}: begin // p.clip alu_operator_o = ALU_CLIP; - alu_op_b_mux_sel_o = OP_A_IMM; + alu_op_b_mux_sel_o = OP_B_IMM; imm_b_mux_sel_o = IMMB_CLIP; end {6'b00_1010, 3'b010}: begin // p.clipu alu_operator_o = ALU_CLIPU; - alu_op_b_mux_sel_o = OP_A_IMM; + alu_op_b_mux_sel_o = OP_B_IMM; imm_b_mux_sel_o = IMMB_CLIP; end `endif // MATH_SPECIAL_SUPPORT + {6'b00_1010, 3'b101}: begin // p.clipr + alu_operator_o = ALU_CLIP; + regb_used_o = 1'b1; + end + + {6'b00_1010, 3'b110}: begin // p.clipur + alu_operator_o = ALU_CLIPU; + regb_used_o = 1'b1; + end + default: begin illegal_insn_o = 1'b1; end @@ -710,6 +764,15 @@ module riscv_decoder bmask_a_mux_o = BMASK_A_ZERO; bmask_b_mux_o = BMASK_B_S3; + + if (instr_rdata_i[30]) begin + //register variant + regc_mux_o = REGC_RD; + alu_bmask_b_mux_sel_o = BMASK_B_REG; + alu_op_a_mux_sel_o = OP_A_REGC_OR_FWD; + alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; + end + end 2'b11: begin // sub with normalization and rounding @@ -724,6 +787,15 @@ module riscv_decoder bmask_a_mux_o = BMASK_A_ZERO; bmask_b_mux_o = BMASK_B_S3; + + if (instr_rdata_i[30]) begin + //register variant + regc_mux_o = REGC_RD; + alu_bmask_b_mux_sel_o = BMASK_B_REG; + alu_op_a_mux_sel_o = OP_A_REGC_OR_FWD; + alu_op_b_mux_sel_o = OP_B_REGA_OR_FWD; + end + end `endif // MATH_SPECIAL_SUPPORT diff --git a/exc_controller.sv b/exc_controller.sv index 6a3187c8..886b647e 100644 --- a/exc_controller.sv +++ b/exc_controller.sv @@ -31,6 +31,7 @@ module riscv_exc_controller // handshake signals to controller output logic req_o, + output logic ext_req_o, input logic ack_i, output logic trap_o, @@ -63,7 +64,7 @@ module riscv_exc_controller enum logic [0:0] { IDLE, WAIT_CONTROLLER } exc_ctrl_cs, exc_ctrl_ns; - logic req_int; + logic req_int, ext_req_int; logic [1:0] pc_mux_int, pc_mux_int_q; logic [5:0] cause_int, cause_int_q; @@ -85,12 +86,14 @@ module riscv_exc_controller | (illegal_insn_i & dbg_settings_i[DBG_SETS_EILL]) | (irq_enable_i & (|irq_i) & dbg_settings_i[DBG_SETS_IRQ]); - // request for exception/interrupt - assign req_int = ecall_insn_i - | lsu_load_err_i - | lsu_store_err_i +// request for exception/interrupt +assign req_int = ecall_insn_i | illegal_insn_i - | (irq_enable_i & (|irq_i)); + | ext_req_int; + +assign ext_req_int = lsu_load_err_i + | lsu_store_err_i + | irq_enable_i & (|irq_i); // Exception cause and ISR address selection @@ -164,13 +167,14 @@ module riscv_exc_controller begin exc_ctrl_ns = exc_ctrl_cs; req_o = 1'b0; + ext_req_o = 1'b0; save_cause_o = 1'b0; unique case (exc_ctrl_cs) IDLE: begin - req_o = req_int; - + req_o = req_int; + ext_req_o = ext_req_int; if (req_int) begin exc_ctrl_ns = WAIT_CONTROLLER; @@ -183,8 +187,8 @@ module riscv_exc_controller WAIT_CONTROLLER: begin - req_o = 1'b1; - + req_o = 1'b1; + ext_req_o = 1'b1; if (ack_i) begin save_cause_o = 1'b1; exc_ctrl_ns = IDLE; diff --git a/id_stage.sv b/id_stage.sv index 637dd933..2b87cc71 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -41,145 +41,186 @@ module riscv_id_stage #( parameter N_HWLP = 2, parameter N_HWLP_BITS = $clog2(N_HWLP) `endif // HWL_SUPPORT -) ( - input logic clk, - input logic rst_n, - input logic test_en_i, - input logic fetch_enable_i, - output logic ctrl_busy_o, - output logic is_decoding_o, - // Interface to IF stage - // CONFIG_REGION: HWL_SUPPORT - `ifdef HWL_SUPPORT - input logic [N_HWLP-1:0] hwlp_dec_cnt_i, - input logic is_hwlp_i, - `endif // HWL_SUPPORT - input logic instr_valid_i, - input logic [31:0] instr_rdata_i, // comes from pipeline of IF stage - output logic instr_req_o, - // Jumps and branches - output logic branch_in_ex_o, - input logic branch_decision_i, - output logic [31:0] jump_target_o, - // IF and ID stage signals - output logic clear_instr_valid_o, - output logic pc_set_o, - output logic [2:0] pc_mux_o, - output logic [1:0] exc_pc_mux_o, - output logic [4:0] exc_vec_pc_mux_o, - input logic illegal_c_insn_i, - input logic is_compressed_i, - input logic [31:0] pc_if_i, - input logic [31:0] pc_id_i, - // Stalls - output logic halt_if_o, // controller requests a halt of the IF stage - output logic id_ready_o, // ID stage is ready for the next instruction - input logic ex_ready_i, // EX stage is ready for the next instruction - input logic if_ready_i, // IF stage is done - input logic if_valid_i, // IF stage is done - output logic id_valid_o, // ID stage is done - input logic ex_valid_i, // EX stage is done - input logic wb_valid_i, // WB stage is done - // Pipeline ID/EX - output logic [31:0] pc_ex_o, - output logic [31:0] alu_operand_a_ex_o, - output logic [31:0] alu_operand_b_ex_o, - output logic [31:0] alu_operand_c_ex_o, - // CONFIG_REGION: BIT_SUPPORT - `ifdef BIT_SUPPORT - output logic [ 4:0] bmask_a_ex_o, - output logic [ 4:0] bmask_b_ex_o, - `endif // BIT_SUPPORT - // CONFIG_REGION: VEC_SUPPORT - `ifdef VEC_SUPPORT - output logic [ 1:0] imm_vec_ext_ex_o, - output logic [ 1:0] alu_vec_mode_ex_o, - `endif // VEC_SUPPORT - output logic [4:0] regfile_waddr_ex_o, - output logic regfile_we_ex_o, - output logic [4:0] regfile_alu_waddr_ex_o, - output logic regfile_alu_we_ex_o, - // ALU - output logic [ALU_OP_WIDTH-1:0] alu_operator_ex_o, - // CONFIG_REGION: MUL_SUPPORT - `ifdef MUL_SUPPORT - // MUL - output logic [ 2:0] mult_operator_ex_o, - output logic [31:0] mult_operand_a_ex_o, - output logic [31:0] mult_operand_b_ex_o, - output logic [31:0] mult_operand_c_ex_o, - output logic mult_en_ex_o, - output logic mult_sel_subword_ex_o, - output logic [ 1:0] mult_signed_mode_ex_o, - output logic [ 4:0] mult_imm_ex_o, - output logic [31:0] mult_dot_op_a_ex_o, - output logic [31:0] mult_dot_op_b_ex_o, - output logic [31:0] mult_dot_op_c_ex_o, - output logic [ 1:0] mult_dot_signed_ex_o, - `endif // MUL_SUPPORT - // CSR ID/EX - output logic csr_access_ex_o, - output logic [1:0] csr_op_ex_o, - // CONFIG_REGION: HWL_SUPPORT - `ifdef HWL_SUPPORT - // hwloop signals - output logic [N_HWLP-1:0] [31:0] hwlp_start_o, - output logic [N_HWLP-1:0] [31:0] hwlp_end_o, - output logic [N_HWLP-1:0] [31:0] hwlp_cnt_o, - // hwloop signals from CS register - input logic [N_HWLP_BITS-1:0] csr_hwlp_regid_i, - input logic [2:0] csr_hwlp_we_i, - input logic [31:0] csr_hwlp_data_i, - `endif // HWL_SUPPORT - // Interface to load store unit - output logic data_req_ex_o, - output logic data_we_ex_o, - output logic [1:0] data_type_ex_o, - output logic data_sign_ext_ex_o, - output logic [1:0] data_reg_offset_ex_o, - output logic data_load_event_ex_o, - output logic data_misaligned_ex_o, - output logic prepost_useincr_ex_o, - input logic data_misaligned_i, - // Interrupt signals - input logic [31:0] irq_i, - input logic irq_enable_i, - output logic [5:0] exc_cause_o, - output logic save_exc_cause_o, - output logic exc_save_if_o, - output logic exc_save_id_o, - output logic exc_restore_id_o, - input logic lsu_load_err_i, - input logic lsu_store_err_i, - // Debug Unit Signals - input logic [DBG_SETS_W-1:0] dbg_settings_i, - input logic dbg_req_i, - output logic dbg_ack_o, - input logic dbg_stall_i, - output logic dbg_trap_o, - input logic dbg_reg_rreq_i, - input logic [ 4:0] dbg_reg_raddr_i, - output logic [31:0] dbg_reg_rdata_o, - input logic dbg_reg_wreq_i, - input logic [ 4:0] dbg_reg_waddr_i, - input logic [31:0] dbg_reg_wdata_i, - input logic dbg_jump_req_i, - // Forward Signals - input logic [4:0] regfile_waddr_wb_i, - input logic regfile_we_wb_i, - input logic [31:0] regfile_wdata_wb_i, // From wb_stage: selects data from data memory, ex_stage result and sp rdata - input logic [4:0] regfile_alu_waddr_fw_i, - input logic regfile_alu_we_fw_i, - input logic [31:0] regfile_alu_wdata_fw_i, - // CONFIG_REGION: MUL_SUPPORT - `ifdef MUL_SUPPORT - // from ALU - input logic mult_multicycle_i, // when we need multiple cycles in the multiplier and use op c as storage - `endif // MUL_SUPPORT - // Performance Counters - output logic perf_jump_o, // we are executing a jump instruction - output logic perf_jr_stall_o, // jump-register-hazard - output logic perf_ld_stall_o // load-use-hazard +) +( + input logic clk, + input logic rst_n, + + input logic test_en_i, + + input logic fetch_enable_i, + output logic ctrl_busy_o, + output logic is_decoding_o, + + // Interface to IF stage + // CONFIG_REGION: HWL_SUPPORT + `ifdef HWL_SUPPORT + input logic [N_HWLP-1:0] hwlp_dec_cnt_i, + input logic is_hwlp_i, + `endif // HWL_SUPPORT + input logic instr_valid_i, + input logic [31:0] instr_rdata_i, // comes from pipeline of IF stage + output logic instr_req_o, + + + // Jumps and branches + output logic branch_in_ex_o, + input logic branch_decision_i, + output logic [31:0] jump_target_o, + + // IF and ID stage signals + output logic clear_instr_valid_o, + output logic pc_set_o, + output logic [2:0] pc_mux_o, + output logic [1:0] exc_pc_mux_o, + output logic [4:0] exc_vec_pc_mux_o, + + input logic illegal_c_insn_i, + input logic is_compressed_i, + + input logic [31:0] pc_if_i, + input logic [31:0] pc_id_i, + + // Stalls + output logic halt_if_o, // controller requests a halt of the IF stage + + output logic id_ready_o, // ID stage is ready for the next instruction + input logic ex_ready_i, // EX stage is ready for the next instruction + + input logic if_ready_i, // IF stage is done + input logic if_valid_i, // IF stage is done + output logic id_valid_o, // ID stage is done + input logic ex_valid_i, // EX stage is done + input logic wb_valid_i, // WB stage is done + + // Pipeline ID/EX + output logic [31:0] pc_ex_o, + + output logic [31:0] alu_operand_a_ex_o, + output logic [31:0] alu_operand_b_ex_o, + output logic [31:0] alu_operand_c_ex_o, + // CONFIG_REGION: BIT_SUPPORT + `ifdef BIT_SUPPORT + output logic [ 4:0] bmask_a_ex_o, + output logic [ 4:0] bmask_b_ex_o, + `endif // BIT_SUPPORT + + // CONFIG_REGION: VEC_SUPPORT + `ifdef VEC_SUPPORT + output logic [ 1:0] imm_vec_ext_ex_o, + output logic [ 1:0] alu_vec_mode_ex_o, + `endif // VEC_SUPPORT + + output logic [4:0] regfile_waddr_ex_o, + output logic regfile_we_ex_o, + + output logic [4:0] regfile_alu_waddr_ex_o, + output logic regfile_alu_we_ex_o, + + // ALU + output logic [ALU_OP_WIDTH-1:0] alu_operator_ex_o, + + + // CONFIG_REGION: MUL_SUPPORT + `ifdef MUL_SUPPORT + // MUL + output logic [ 2:0] mult_operator_ex_o, + output logic [31:0] mult_operand_a_ex_o, + output logic [31:0] mult_operand_b_ex_o, + output logic [31:0] mult_operand_c_ex_o, + output logic mult_en_ex_o, + output logic mult_sel_subword_ex_o, + output logic [ 1:0] mult_signed_mode_ex_o, + output logic [ 4:0] mult_imm_ex_o, + + output logic [31:0] mult_dot_op_a_ex_o, + output logic [31:0] mult_dot_op_b_ex_o, + output logic [31:0] mult_dot_op_c_ex_o, + output logic [ 1:0] mult_dot_signed_ex_o, + `endif // MUL_SUPPORT + + + // CSR ID/EX + output logic csr_access_ex_o, + output logic [1:0] csr_op_ex_o, + + // CONFIG_REGION: HWL_SUPPORT + `ifdef HWL_SUPPORT + // hwloop signals + output logic [N_HWLP-1:0] [31:0] hwlp_start_o, + output logic [N_HWLP-1:0] [31:0] hwlp_end_o, + output logic [N_HWLP-1:0] [31:0] hwlp_cnt_o, + + // hwloop signals from CS register + input logic [N_HWLP_BITS-1:0] csr_hwlp_regid_i, + input logic [2:0] csr_hwlp_we_i, + input logic [31:0] csr_hwlp_data_i, + `endif // HWL_SUPPORT + + // Interface to load store unit + output logic data_req_ex_o, + output logic data_we_ex_o, + output logic [1:0] data_type_ex_o, + output logic data_sign_ext_ex_o, + output logic [1:0] data_reg_offset_ex_o, + output logic data_load_event_ex_o, + + output logic data_misaligned_ex_o, + + output logic prepost_useincr_ex_o, + input logic data_misaligned_i, + + // Interrupt signals + input logic [31:0] irq_i, + input logic irq_enable_i, + + output logic [5:0] exc_cause_o, + output logic save_exc_cause_o, + + output logic exc_save_if_o, + output logic exc_save_id_o, + output logic exc_save_takenbranch_o, + output logic exc_restore_id_o, + + input logic lsu_load_err_i, + input logic lsu_store_err_i, + + // Debug Unit Signals + input logic [DBG_SETS_W-1:0] dbg_settings_i, + input logic dbg_req_i, + output logic dbg_ack_o, + input logic dbg_stall_i, + output logic dbg_trap_o, + + input logic dbg_reg_rreq_i, + input logic [ 4:0] dbg_reg_raddr_i, + output logic [31:0] dbg_reg_rdata_o, + + input logic dbg_reg_wreq_i, + input logic [ 4:0] dbg_reg_waddr_i, + input logic [31:0] dbg_reg_wdata_i, + + input logic dbg_jump_req_i, + + // Forward Signals + input logic [4:0] regfile_waddr_wb_i, + input logic regfile_we_wb_i, + input logic [31:0] regfile_wdata_wb_i, // From wb_stage: selects data from data memory, ex_stage result and sp rdata + + input logic [4:0] regfile_alu_waddr_fw_i, + input logic regfile_alu_we_fw_i, + input logic [31:0] regfile_alu_wdata_fw_i, + + // from ALU + // CONFIG_REGION: MUL_SUPPORT + `ifdef MUL_SUPPORT + input logic mult_multicycle_i, // when we need multiple cycles in the multiplier and use op c as storage + `endif // MUL_SUPPORT + + // Performance Counters + output logic perf_jump_o, // we are executing a jump instruction + output logic perf_jr_stall_o, // jump-register-hazard + output logic perf_ld_stall_o // load-use-hazard ); logic [31:0] instr; @@ -240,7 +281,7 @@ module riscv_id_stage #( // Signals running between controller and exception controller - logic exc_req, exc_ack; // handshake + logic exc_req, ext_req, exc_ack; // handshake // Register file interface logic [4:0] regfile_addr_ra_id; @@ -257,8 +298,8 @@ module riscv_id_stage #( // ALU Control logic [ALU_OP_WIDTH-1:0] alu_operator; - logic [1:0] alu_op_a_mux_sel; - logic [1:0] alu_op_b_mux_sel; + logic [2:0] alu_op_a_mux_sel; + logic [2:0] alu_op_b_mux_sel; logic [1:0] alu_op_c_mux_sel; logic [1:0] regc_mux; @@ -336,6 +377,7 @@ module riscv_id_stage #( `ifdef BIT_SUPPORT logic [0:0] bmask_a_mux; logic [1:0] bmask_b_mux; +<<<<<<< HEAD `endif // BIT_SUPPORT // CONFIG_REGION: MUL_SUPPORT `ifdef MUL_SUPPORT @@ -343,6 +385,14 @@ module riscv_id_stage #( `endif // MUL_SUPPORT // CONFIG_REGION: BIT_SUPPORT `ifdef BIT_SUPPORT +======= + logic alu_bmask_a_mux_sel; + logic alu_bmask_b_mux_sel; + logic [0:0] mult_imm_mux; + + logic [ 4:0] bmask_a_id_imm; + logic [ 4:0] bmask_b_id_imm; +>>>>>>> riscv/master logic [ 4:0] bmask_a_id; logic [ 4:0] bmask_b_id; `endif // BIT_SUPPORT @@ -545,6 +595,7 @@ module riscv_id_stage #( // ALU_Op_a Mux always_comb +<<<<<<< HEAD begin : alu_operand_a_mux case (alu_op_a_mux_sel) OP_A_REGA_OR_FWD: alu_operand_a = operand_a_fw_id; @@ -554,6 +605,18 @@ module riscv_id_stage #( default: alu_operand_a = operand_a_fw_id; endcase; // case (alu_op_a_mux_sel) end +======= + begin : alu_operand_a_mux + case (alu_op_a_mux_sel) + OP_A_REGA_OR_FWD: alu_operand_a = operand_a_fw_id; + OP_A_REGB_OR_FWD: alu_operand_a = operand_b_fw_id; + OP_A_REGC_OR_FWD: alu_operand_a = operand_c_fw_id; + OP_A_CURRPC: alu_operand_a = pc_id_i; + OP_A_IMM: alu_operand_a = imm_a; + default: alu_operand_a = operand_a_fw_id; + endcase; // case (alu_op_a_mux_sel) + end +>>>>>>> riscv/master always_comb begin : immediate_a_mux @@ -610,6 +673,7 @@ module riscv_id_stage #( // ALU_Op_b Mux always_comb +<<<<<<< HEAD begin : alu_operand_b_mux case (alu_op_b_mux_sel) OP_B_REGB_OR_FWD: operand_b = operand_b_fw_id; @@ -618,6 +682,18 @@ module riscv_id_stage #( default: operand_b = operand_b_fw_id; endcase // case (alu_op_b_mux_sel) end +======= + begin : alu_operand_b_mux + case (alu_op_b_mux_sel) + OP_B_REGA_OR_FWD: operand_b = operand_a_fw_id; + OP_B_REGB_OR_FWD: operand_b = operand_b_fw_id; + OP_B_REGC_OR_FWD: operand_b = operand_c_fw_id; + OP_B_IMM: operand_b = imm_b; + OP_B_BMASK: operand_b = $unsigned(operand_b_fw_id[4:0]); + default: operand_b = operand_b_fw_id; + endcase // case (alu_op_b_mux_sel) + end +>>>>>>> riscv/master // scalar replication for operand B and shuffle type @@ -712,6 +788,7 @@ module riscv_id_stage #( // CONFIG_REGION: BIT_SUPPORT `ifdef BIT_SUPPORT always_comb +<<<<<<< HEAD begin unique case (bmask_a_mux) BMASK_A_ZERO: bmask_a_id = '0; @@ -719,6 +796,46 @@ module riscv_id_stage #( default: bmask_a_id = '0; endcase end +======= + begin + unique case (bmask_a_mux) + BMASK_A_ZERO: bmask_a_id_imm = '0; + BMASK_A_S3: bmask_a_id_imm = imm_s3_type[4:0]; + default: bmask_a_id_imm = '0; + endcase + end + always_comb + begin + unique case (bmask_b_mux) + BMASK_B_ZERO: bmask_b_id_imm = '0; + BMASK_B_ONE: bmask_b_id_imm = 5'd1; + BMASK_B_S2: bmask_b_id_imm = imm_s2_type[4:0]; + BMASK_B_S3: bmask_b_id_imm = imm_s3_type[4:0]; + default: bmask_b_id_imm = '0; + endcase + end + + always_comb + begin + unique case (alu_bmask_a_mux_sel) + BMASK_A_IMM: bmask_a_id = bmask_a_id_imm; + BMASK_A_REG: bmask_a_id = operand_b_fw_id[9:5]; + default: bmask_a_id = bmask_a_id_imm; + endcase + end + always_comb + begin + unique case (alu_bmask_b_mux_sel) + BMASK_B_IMM: bmask_b_id = bmask_b_id_imm; + BMASK_B_REG: bmask_b_id = operand_b_fw_id[4:0]; + default: bmask_b_id = bmask_b_id_imm; + endcase + end + + assign imm_vec_ext_id = imm_vu_type[1:0]; + + +>>>>>>> riscv/master always_comb begin unique case (bmask_b_mux) @@ -799,6 +916,7 @@ module riscv_id_stage #( /////////////////////////////////////////////// riscv_decoder decoder_i +<<<<<<< HEAD ( // controller related signals .deassert_we_i ( deassert_we ), @@ -889,6 +1007,84 @@ module riscv_id_stage #( .jump_target_mux_sel_o ( jump_target_mux_sel ) ); +======= + ( + // controller related signals + .deassert_we_i ( deassert_we ), + .data_misaligned_i ( data_misaligned_i ), + .mult_multicycle_i ( mult_multicycle_i ), + + .illegal_insn_o ( illegal_insn_dec ), + .ebrk_insn_o ( ebrk_insn ), + .eret_insn_o ( eret_insn_dec ), + .ecall_insn_o ( ecall_insn_dec ), + .pipe_flush_o ( pipe_flush_dec ), + + .rega_used_o ( rega_used_dec ), + .regb_used_o ( regb_used_dec ), + .regc_used_o ( regc_used_dec ), + + .bmask_needed_o ( bmask_needed_dec ), + .bmask_a_mux_o ( bmask_a_mux ), + .bmask_b_mux_o ( bmask_b_mux ), + .alu_bmask_a_mux_sel_o ( alu_bmask_a_mux_sel ), + .alu_bmask_b_mux_sel_o ( alu_bmask_b_mux_sel ), + + // from IF/ID pipeline + .instr_rdata_i ( instr ), + .illegal_c_insn_i ( illegal_c_insn_i ), + + // 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 ), + .alu_vec_mode_o ( alu_vec_mode ), + .scalar_replication_o ( scalar_replication ), + .imm_a_mux_sel_o ( imm_a_mux_sel ), + .imm_b_mux_sel_o ( imm_b_mux_sel ), + .regc_mux_o ( regc_mux ), + + // MUL signals + .mult_operator_o ( mult_operator ), + .mult_int_en_o ( mult_int_en ), + .mult_sel_subword_o ( mult_sel_subword ), + .mult_signed_mode_o ( mult_signed_mode ), + .mult_imm_mux_o ( mult_imm_mux ), + .mult_dot_en_o ( mult_dot_en ), + .mult_dot_signed_o ( mult_dot_signed ), + + // Register file control signals + .regfile_mem_we_o ( regfile_we_id ), + .regfile_alu_we_o ( regfile_alu_we_id ), + .regfile_alu_waddr_sel_o ( regfile_alu_waddr_mux_sel ), + + // CSR control signals + .csr_access_o ( csr_access ), + .csr_op_o ( csr_op ), + + // Data bus interface + .data_req_o ( data_req_id ), + .data_we_o ( data_we_id ), + .prepost_useincr_o ( prepost_useincr ), + .data_type_o ( data_type_id ), + .data_sign_extension_o ( data_sign_ext_id ), + .data_reg_offset_o ( data_reg_offset_id ), + .data_load_event_o ( data_load_event_id ), + + // hwloop signals + .hwloop_we_o ( hwloop_we_int ), + .hwloop_target_mux_sel_o ( hwloop_target_mux_sel ), + .hwloop_start_mux_sel_o ( hwloop_start_mux_sel ), + .hwloop_cnt_mux_sel_o ( hwloop_cnt_mux_sel ), + + // jump/branches + .jump_in_dec_o ( jump_in_dec ), + .jump_in_id_o ( jump_in_id ), + .jump_target_mux_sel_o ( jump_target_mux_sel ) + + ); +>>>>>>> riscv/master //////////////////////////////////////////////////////////////////// // ____ ___ _ _ _____ ____ ___ _ _ _____ ____ // @@ -900,6 +1096,7 @@ module riscv_id_stage #( //////////////////////////////////////////////////////////////////// riscv_controller controller_i +<<<<<<< HEAD ( .clk ( clk ), .rst_n ( rst_n ), @@ -1004,6 +1201,111 @@ module riscv_id_stage #( .perf_jr_stall_o ( perf_jr_stall_o ), .perf_ld_stall_o ( perf_ld_stall_o ) ); +======= + ( + .clk ( clk ), + .rst_n ( rst_n ), + + .fetch_enable_i ( fetch_enable_i ), + .ctrl_busy_o ( ctrl_busy_o ), + .is_decoding_o ( is_decoding_o ), + + // decoder related signals + .deassert_we_o ( deassert_we ), + .illegal_insn_i ( illegal_insn_dec ), + .eret_insn_i ( eret_insn_dec ), + .pipe_flush_i ( pipe_flush_dec ), + + .rega_used_i ( rega_used_dec ), + .regb_used_i ( regb_used_dec ), + .regc_used_i ( regc_used_dec ), + + // from IF/ID pipeline + .instr_valid_i ( instr_valid_i ), + .instr_rdata_i ( instr ), + + // from prefetcher + .instr_req_o ( instr_req_o ), + + // to prefetcher + .pc_set_o ( pc_set_o ), + .pc_mux_o ( pc_mux_o ), + + // LSU + .data_req_ex_i ( data_req_ex_o ), + .data_misaligned_i ( data_misaligned_i ), + .data_load_event_i ( data_load_event_ex_o ), + + // ALU + .mult_multicycle_i ( mult_multicycle_i ), + + // jump/branch control + .branch_taken_ex_i ( branch_taken_ex ), + .jump_in_id_i ( jump_in_id ), + .jump_in_dec_i ( jump_in_dec ), + + // Exception Controller Signals + .exc_req_i ( exc_req ), + .ext_req_i ( ext_req ), + .exc_ack_o ( exc_ack ), + + .exc_save_if_o ( exc_save_if_o ), + .exc_save_id_o ( exc_save_id_o ), + .exc_save_takenbranch_o ( exc_save_takenbranch_o ), + .exc_restore_id_o ( exc_restore_id_o ), + + // Debug Unit Signals + .dbg_req_i ( dbg_req_i ), + .dbg_ack_o ( dbg_ack_o ), + .dbg_stall_i ( dbg_stall_i ), + .dbg_jump_req_i ( dbg_jump_req_i ), + + // Forwarding signals from regfile + .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 ), + + // Forwarding detection signals + .reg_d_ex_is_reg_a_i ( reg_d_ex_is_reg_a_id ), + .reg_d_ex_is_reg_b_i ( reg_d_ex_is_reg_b_id ), + .reg_d_ex_is_reg_c_i ( reg_d_ex_is_reg_c_id ), + .reg_d_wb_is_reg_a_i ( reg_d_wb_is_reg_a_id ), + .reg_d_wb_is_reg_b_i ( reg_d_wb_is_reg_b_id ), + .reg_d_wb_is_reg_c_i ( reg_d_wb_is_reg_c_id ), + .reg_d_alu_is_reg_a_i ( reg_d_alu_is_reg_a_id ), + .reg_d_alu_is_reg_b_i ( reg_d_alu_is_reg_b_id ), + .reg_d_alu_is_reg_c_i ( reg_d_alu_is_reg_c_id ), + + // 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 ), + + // Stall signals + .halt_if_o ( halt_if_o ), + .halt_id_o ( halt_id ), + + .misaligned_stall_o ( misaligned_stall ), + .jr_stall_o ( jr_stall ), + .load_stall_o ( load_stall ), + + .id_ready_i ( id_ready_o ), + + .if_valid_i ( if_valid_i ), + .ex_valid_i ( ex_valid_i ), + .wb_valid_i ( wb_valid_i ), + + // Performance Counters + .perf_jump_o ( perf_jump_o ), + .perf_jr_stall_o ( perf_jr_stall_o ), + .perf_ld_stall_o ( perf_ld_stall_o ) + ); +>>>>>>> riscv/master /////////////////////////////////////////////////////////////////////// // _____ ____ _ _ _ // @@ -1019,9 +1321,16 @@ module riscv_id_stage #( .clk ( clk ), .rst_n ( rst_n ), +<<<<<<< HEAD // to controller .req_o ( exc_req ), .ack_i ( exc_ack ), +======= + // to controller + .req_o ( exc_req ), + .ext_req_o ( ext_req ), + .ack_i ( exc_ack ), +>>>>>>> riscv/master .trap_o ( dbg_trap_o ), @@ -1159,6 +1468,7 @@ module riscv_id_stage #( branch_in_ex_o <= 1'b0; end +<<<<<<< HEAD else if (data_misaligned_i) begin // misaligned data access case if (ex_ready_i) @@ -1183,6 +1493,52 @@ module riscv_id_stage #( `ifdef MUL_SUPPORT else if (mult_multicycle_i) begin mult_operand_c_ex_o <= alu_operand_c; +======= + + mult_en_ex_o <= mult_en; + if (mult_int_en) begin // when we are multiplying we don't need the ALU + mult_operator_ex_o <= mult_operator; + mult_sel_subword_ex_o <= mult_sel_subword; + mult_signed_mode_ex_o <= mult_signed_mode; + mult_operand_a_ex_o <= alu_operand_a; + mult_operand_b_ex_o <= alu_operand_b; + mult_operand_c_ex_o <= alu_operand_c; + mult_imm_ex_o <= mult_imm_id; + end + if (mult_dot_en) begin + mult_operator_ex_o <= mult_operator; + mult_dot_signed_ex_o <= mult_dot_signed; + mult_dot_op_a_ex_o <= alu_operand_a; + mult_dot_op_b_ex_o <= alu_operand_b; + mult_dot_op_c_ex_o <= alu_operand_c; + end + + regfile_we_ex_o <= regfile_we_id; + if (regfile_we_id) begin + regfile_waddr_ex_o <= regfile_waddr_id; + end + + regfile_alu_we_ex_o <= regfile_alu_we_id; + if (regfile_alu_we_id) begin + regfile_alu_waddr_ex_o <= regfile_alu_waddr_id; + end + + prepost_useincr_ex_o <= prepost_useincr; + + csr_access_ex_o <= csr_access; + csr_op_ex_o <= csr_op; + + data_req_ex_o <= data_req_id; + if (data_req_id) + begin // only needed for LSU when there is an active request + data_we_ex_o <= data_we_id; + data_type_ex_o <= data_type_id; + data_sign_ext_ex_o <= data_sign_ext_id; + data_reg_offset_ex_o <= data_reg_offset_id; + data_load_event_ex_o <= data_load_event_id; + end else begin + data_load_event_ex_o <= 1'b0; +>>>>>>> riscv/master end `endif // MUL_SUPPORT else begin diff --git a/include/riscv_defines.sv b/include/riscv_defines.sv index 7a83e274..8413cb1f 100644 --- a/include/riscv_defines.sv +++ b/include/riscv_defines.sv @@ -210,19 +210,22 @@ parameter SEL_FW_EX = 2'b01; parameter SEL_FW_WB = 2'b10; // operand a selection -parameter OP_A_REGA_OR_FWD = 2'b00; -parameter OP_A_CURRPC = 2'b01; -parameter OP_A_IMM = 2'b10; -parameter OP_A_REGB_OR_FWD = 2'b11; +parameter OP_A_REGA_OR_FWD = 3'b000; +parameter OP_A_CURRPC = 3'b001; +parameter OP_A_IMM = 3'b010; +parameter OP_A_REGB_OR_FWD = 3'b011; +parameter OP_A_REGC_OR_FWD = 3'b100; // immediate a selection parameter IMMA_Z = 1'b0; parameter IMMA_ZERO = 1'b1; // operand b selection -parameter OP_B_REGB_OR_FWD = 2'b00; -parameter OP_B_REGC_OR_FWD = 2'b01; -parameter OP_B_IMM = 2'b10; +parameter OP_B_REGB_OR_FWD = 3'b000; +parameter OP_B_REGC_OR_FWD = 3'b001; +parameter OP_B_IMM = 3'b010; +parameter OP_B_REGA_OR_FWD = 3'b011; +parameter OP_B_BMASK = 3'b100; // immediate b selection parameter IMMB_I = 4'b0000; @@ -246,6 +249,12 @@ parameter BMASK_B_S3 = 2'b01; parameter BMASK_B_ZERO = 2'b10; parameter BMASK_B_ONE = 2'b11; +parameter BMASK_A_REG = 1'b0; +parameter BMASK_A_IMM = 1'b1; +parameter BMASK_B_REG = 1'b0; +parameter BMASK_B_IMM = 1'b1; + + // multiplication immediates parameter MIMM_ZERO = 1'b0; parameter MIMM_S3 = 1'b1; diff --git a/load_store_unit.sv b/load_store_unit.sv index 9383ad8e..835d3df3 100644 --- a/load_store_unit.sv +++ b/load_store_unit.sv @@ -329,7 +329,7 @@ module riscv_load_store_unit assign misaligned_st = data_misaligned_ex_i; - assign load_err_o = data_gnt_i && data_err_i && data_we_o; + assign load_err_o = data_gnt_i && data_err_i && ~data_we_o; assign store_err_o = data_gnt_i && data_err_i && data_we_o; // FSM diff --git a/riscv_core.sv b/riscv_core.sv index ffa2be52..266db0ee 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -224,6 +224,7 @@ module riscv_core logic save_exc_cause; logic exc_save_if; logic exc_save_id; + logic exc_save_takenbranch_ex; logic exc_restore_id; @@ -541,6 +542,7 @@ module riscv_core .save_exc_cause_o ( save_exc_cause ), .exc_save_if_o ( exc_save_if ), // control signal to save pc .exc_save_id_o ( exc_save_id ), // control signal to save pc + .exc_save_takenbranch_o ( exc_save_takenbranch_ex ), // control signal to save target taken branch .exc_restore_id_o ( exc_restore_id ), // control signal to restore pc .lsu_load_err_i ( lsu_load_err ), .lsu_store_err_i ( lsu_store_err ), @@ -762,9 +764,11 @@ module riscv_core .pc_if_i ( pc_if ), .pc_id_i ( pc_id ), // from IF stage .pc_ex_i ( pc_ex ), // from ID/EX pipeline + .branch_target_i ( jump_target_ex ), // from ID/EX pipeline .data_load_event_ex_i ( data_load_event_ex ), // from ID/EX pipeline .exc_save_if_i ( exc_save_if ), .exc_save_id_i ( exc_save_id ), + .exc_save_takenbranch_i ( exc_save_takenbranch_ex ), .exc_restore_i ( exc_restore_id ), .exc_cause_i ( exc_cause ),