diff --git a/controller.sv b/controller.sv index 5aaf308f..502fc700 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 @@ -192,13 +194,15 @@ module controller always_comb begin jump_in_id = `BRANCH_NONE; - jump_target_mux_sel_o = `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; @@ -215,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; @@ -251,7 +255,7 @@ module controller ////////////////////////////////////// `OPCODE_JAL: begin // Jump and Link - jump_target_mux_sel_o = `BRANCH_JAL; + 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; @@ -264,7 +268,7 @@ module controller end `OPCODE_JALR: begin // Jump and Link Register - jump_target_mux_sel_o = `BRANCH_JALR; + 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; @@ -284,7 +288,7 @@ module controller end `OPCODE_BRANCH: begin // Branch - jump_target_mux_sel_o = `BRANCH_COND; + 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; @@ -831,65 +835,54 @@ module controller // // /////////////////////////////////////////////// - `OPCODE_HWLOOP: begin // hardware loop instructions - jump_target_mux_sel_o = `BRANCH_JALR; // reuse jump target adder to calculate PC + I imm + `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; + // 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; + // 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 rs1 - hwloop_cnt_mux_sel_o = 2'b11; 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 I-type immediate - hwloop_cnt_mux_sel_o = 2'b01; 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: initialize counter from rs1, set start address to // next instruction and end address to PC + I-type immediate - 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; + 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: initialize counter from I-type immediate, set start // address to next instruction and end address to PC + shifted // z-type immediate - 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; + 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 @@ -936,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("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 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/id_stage.sv b/id_stage.sv index 93effb8a..d7f794ca 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -93,12 +93,7 @@ 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 csr_access_ex_o, output logic [1:0] csr_op_ex_o, @@ -119,12 +114,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, @@ -237,11 +226,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; @@ -326,22 +325,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 = imm_i_type; - 2'b01: hwloop_cnt = { imm_z_type[30:0], 1'b0 }; - 2'b11: hwloop_cnt = operand_a_fw_id; + 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 - ////////////////////////////////////////////////////////////////// - // _ _____ _ // + // _ _____ _ // // | |_ _ _ __ ___ _ __ |_ _|_ _ _ __ __ _ ___| |_ // // _ | | | | | '_ ` _ \| '_ \ | |/ _` | '__/ _` |/ _ \ __| // // | |_| | |_| | | | | | | |_) | | | (_| | | | (_| | __/ |_ // @@ -352,10 +368,10 @@ module id_stage always_comb begin : jump_target_mux unique case (jump_target_mux_sel) - `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 + `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 @@ -375,11 +391,11 @@ module id_stage 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; + default: alu_operand_a = operand_a_fw_id; endcase; // case (alu_op_a_mux_sel) end @@ -420,10 +436,10 @@ module id_stage 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; + default: operand_b = operand_b_fw_id; endcase // case (alu_op_b_mux_sel) end @@ -578,7 +594,8 @@ module id_stage // hwloop signals .hwloop_we_o ( hwloop_we ), - .hwloop_wb_mux_sel_o ( hwloop_wb_mux_sel ), + .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 ), @@ -615,6 +632,7 @@ module id_stage .operand_c_fw_mux_sel_o ( operand_c_fw_mux_sel ), // 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 ), @@ -669,12 +687,11 @@ module id_stage // CSR .save_pc_if_o ( save_pc_if_o ), .save_pc_id_o ( save_pc_id_o ), - .save_sr_o ( save_sr_o ), // Controller .core_busy_i ( core_busy_o ), .jump_in_id_i ( jump_in_id_o ), - .jump_in_ex_i ( jump_in_ex_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 ), @@ -703,23 +720,23 @@ module id_stage hwloop_controller hwloop_controller_i ( // from ID stage - .enable_i ( hwloop_enable ), + .enable_i ( hwloop_enable ), - .current_pc_i ( current_pc_if_i ), + .current_pc_i ( current_pc_if_i ), - // to ID controller - .hwloop_jump_o ( hwloop_jump ), + // to controller + .hwloop_jump_o ( hwloop_jump ), // to if stage - .hwloop_targ_addr_o ( hwloop_targ_addr_o ), + .hwloop_targ_addr_o ( hwloop_targ_addr_o ), // 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 ), + .hwloop_start_addr_i ( hwloop_start_addr ), + .hwloop_end_addr_i ( hwloop_end_addr ), + .hwloop_counter_i ( hwloop_counter ), // to hwloop_regs - .hwloop_dec_cnt_o ( hwloop_dec_cnt_o ) + .hwloop_dec_cnt_o ( hwloop_dec_cnt ) ); hwloop_regs hwloop_regs_i @@ -727,23 +744,23 @@ module id_stage .clk ( clk ), .rst_n ( rst_n ), - // from ex stage - .hwloop_start_data_i ( hwlp_start_data_ex ), - .hwloop_end_data_i ( hwlp_end_data_ex ), - .hwloop_cnt_data_i ( hwlp_cnt_data_ex ), - .hwloop_we_i ( hwlp_we_ex ), - .hwloop_regid_i ( hwlp_regid_ex ), + // 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 ), + .stall_id_i ( stall_id_o ), // to hwloop controller - .hwloop_start_addr_o ( hwlp_start_addr ), - .hwloop_end_addr_o ( hwlp_end_addr ), - .hwloop_counter_o ( hwlp_counter ), + .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 ( hwlp_dec_cnt ) + .hwloop_dec_cnt_i ( hwloop_dec_cnt ) ); @@ -793,11 +810,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 @@ -856,13 +868,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/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 d73e6fb1..9e9613cf 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -180,21 +180,8 @@ module riscv_core logic save_pc_id; - // Hardware loop 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 - // Hardware loop 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 + logic [31:0] hwlp_targ_addr; // from hwloop controller to if stage // Debug Unit @@ -357,11 +344,6 @@ module riscv_core .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 ), .prepost_useincr_ex_o ( useincr_addr_ex ), @@ -383,11 +365,6 @@ module riscv_core .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 ), - // Debug Unit Signals .dbg_flush_pipe_i ( dbg_flush_pipe ), .dbg_st_en_i ( dbg_st_en ),