diff --git a/controller.sv b/controller.sv index e5a0acb8..97e21b64 100644 --- a/controller.sv +++ b/controller.sv @@ -141,7 +141,7 @@ module riscv_controller // print warning in case of decoding errors if (is_decoding_o && illegal_insn_i) begin $display("%t: Illegal instruction (core %0d) at PC 0x%h:", $time, riscv_core.core_id_i, - riscv_id_stage.current_pc_id_i); + riscv_id_stage.pc_id_i); end end // synopsys translate_on diff --git a/cs_registers.sv b/cs_registers.sv index 6069003a..a7fe5dc5 100644 --- a/cs_registers.sv +++ b/cs_registers.sv @@ -58,6 +58,8 @@ module riscv_cs_registers output logic [31:0] mepc_o, input logic [31:0] curr_pc_id_i, + input logic [31:0] data_pc_ex_i, + input logic data_load_event_ex_i, input logic exc_save_i, input logic exc_restore_i, @@ -204,7 +206,7 @@ module riscv_cs_registers // exception controller gets priority over other writes if (exc_save_i) begin - mepc_n = curr_pc_id_i; + mepc_n = data_load_event_ex_i ? data_pc_ex_i : curr_pc_id_i; // save EX PC if special event load mestatus_n = mstatus_q; mstatus_n = 1'b0; end diff --git a/decoder.sv b/decoder.sv index 9751e322..fe91bc08 100644 --- a/decoder.sv +++ b/decoder.sv @@ -81,6 +81,7 @@ module riscv_decoder output logic [1:0] data_type_o, // data type on data memory: byte, half word or word output logic data_sign_extension_o, // sign extension on read data from data memory output logic [1:0] data_reg_offset_o, // offset in byte inside register for stores + output logic data_load_event_o, // data request is in the special event range // hwloop signals output logic [2:0] hwloop_we_o, // write enable for hwloop regs @@ -159,6 +160,7 @@ module riscv_decoder data_sign_extension_o = 1'b0; data_reg_offset_o = 2'b00; data_req = 1'b0; + data_load_event_o = 1'b0; illegal_insn_o = 1'b0; trap_insn = 1'b0; @@ -345,12 +347,12 @@ module riscv_decoder endcase end - if (instr_rdata_i[14:12] == 3'b011 || instr_rdata_i[14:12] == 3'b110) - begin - // LD, LWU -> RV64 only - data_req = 1'b0; - regfile_mem_we = 1'b0; - regfile_alu_we = 1'b0; + // special p.elw (event load) + if (instr_rdata_i[14:12] == 3'b110) + data_load_event_o = 1'b1; + + if (instr_rdata_i[14:12] == 3'b011) begin + // LD -> RV64 only illegal_insn_o = 1'b1; end end diff --git a/id_stage.sv b/id_stage.sv index 23bfba6c..e3256fe4 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -66,8 +66,8 @@ module riscv_id_stage input logic illegal_c_insn_i, input logic is_compressed_i, - input logic [31:0] current_pc_if_i, - input logic [31:0] current_pc_id_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 @@ -132,6 +132,9 @@ module riscv_id_stage 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 [31:0] data_pc_ex_o, + output logic data_load_event_ex_o, + output logic data_misaligned_ex_o, output logic prepost_useincr_ex_o, @@ -269,6 +272,7 @@ module riscv_id_stage logic data_sign_ext_id; logic [1:0] data_reg_offset_id; logic data_req_id; + logic data_load_event_id; // hwloop signals logic [N_HWLP_BITS-1:0] hwloop_regid, hwloop_regid_int; @@ -405,8 +409,8 @@ module riscv_id_stage always_comb begin unique case (hwloop_target_mux_sel) - 1'b0: hwloop_target = current_pc_id_i + {imm_iz_type[30:0], 1'b0}; - 1'b1: hwloop_target = current_pc_id_i + {imm_z_type[30:0], 1'b0}; + 1'b0: hwloop_target = pc_id_i + {imm_iz_type[30:0], 1'b0}; + 1'b1: hwloop_target = pc_id_i + {imm_z_type[30:0], 1'b0}; endcase end @@ -415,7 +419,7 @@ module riscv_id_stage begin unique case (hwloop_start_mux_sel) 1'b0: hwloop_start_int = hwloop_target; // for PC + I imm - 1'b1: hwloop_start_int = current_pc_if_i; // for next PC + 1'b1: hwloop_start_int = pc_if_i; // for next PC endcase end @@ -449,8 +453,8 @@ module riscv_id_stage always_comb begin : jump_target_mux unique case (jump_target_mux_sel) - `JT_JAL: jump_target = current_pc_id_i + imm_uj_type; - `JT_COND: jump_target = current_pc_id_i + imm_sb_type; + `JT_JAL: jump_target = pc_id_i + imm_uj_type; + `JT_COND: jump_target = pc_id_i + imm_sb_type; // JALR: Cannot forward RS1, since the path is too long `JT_JALR: jump_target = regfile_data_ra_id + imm_i_type; @@ -475,7 +479,7 @@ module riscv_id_stage 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_CURRPC: alu_operand_a = current_pc_id_i; + `OP_A_CURRPC: alu_operand_a = 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; @@ -703,6 +707,7 @@ module riscv_id_stage .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 ), @@ -925,7 +930,7 @@ module riscv_id_stage end else begin if (jump_in_id == `BRANCH_COND && id_valid_o) - branch_pc_ex_o <= current_pc_id_i; + branch_pc_ex_o <= pc_id_i; end end @@ -966,6 +971,8 @@ module riscv_id_stage data_sign_ext_ex_o <= 1'b0; data_reg_offset_ex_o <= 2'b0; data_req_ex_o <= 1'b0; + data_pc_ex_o <= '0; + data_load_event_ex_o <= 1'b0; data_misaligned_ex_o <= 1'b0; @@ -1043,6 +1050,15 @@ module riscv_id_stage 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; + + if (data_load_event_id) begin + data_pc_ex_o <= pc_id_i; + data_load_event_ex_o <= 1'b1; + end else begin + data_load_event_ex_o <= 1'b0; + end + end else begin + data_load_event_ex_o <= 1'b0; end data_misaligned_ex_o <= 1'b0; @@ -1059,6 +1075,7 @@ module riscv_id_stage csr_op_ex_o <= `CSR_OP_NONE; data_req_ex_o <= 1'b0; + data_load_event_ex_o <= 1'b0; data_misaligned_ex_o <= 1'b0; diff --git a/if_stage.sv b/if_stage.sv index 40461209..cdc828b7 100644 --- a/if_stage.sv +++ b/if_stage.sv @@ -57,8 +57,8 @@ module riscv_if_stage output logic [31:0] instr_rdata_id_o, // read instruction is sampled and sent to ID stage for decoding output logic is_compressed_id_o, // compressed decoder thinks this is a compressed instruction output logic illegal_c_insn_id_o, // compressed decoder thinks this is an invalid instruction - output logic [31:0] current_pc_if_o, - output logic [31:0] current_pc_id_o, + output logic [31:0] pc_if_o, + output logic [31:0] pc_id_o, // Forwarding ports - control signals input logic clear_instr_valid_i, // clear instruction valid bit in IF/ID pipe @@ -304,7 +304,7 @@ module riscv_if_stage ); - assign current_pc_if_o = fetch_addr; + assign pc_if_o = fetch_addr; assign if_busy_o = prefetch_busy; @@ -351,7 +351,7 @@ module riscv_if_stage instr_rdata_id_o <= '0; illegal_c_insn_id_o <= 1'b0; is_compressed_id_o <= 1'b0; - current_pc_id_o <= '0; + pc_id_o <= '0; is_hwlp_id_q <= 1'b0; hwlp_dec_cnt_id_o <= '0; end @@ -364,7 +364,7 @@ module riscv_if_stage instr_rdata_id_o <= instr_decompressed; illegal_c_insn_id_o <= illegal_c_insn; is_compressed_id_o <= instr_compressed_int; - current_pc_id_o <= current_pc_if_o; + pc_id_o <= pc_if_o; is_hwlp_id_q <= fetch_is_hwlp; if (fetch_is_hwlp) diff --git a/include/riscv_defines.sv b/include/riscv_defines.sv index 0c16cc43..4418641c 100644 --- a/include/riscv_defines.sv +++ b/include/riscv_defines.sv @@ -29,7 +29,7 @@ // no traces for synthesis, they are not synthesizable `ifndef SYNTHESIS `define TRACE_EXECUTION -//`define SIMCHECKER +`define SIMCHECKER `endif diff --git a/riscv_core.sv b/riscv_core.sv index 85e1663b..1926a1a7 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -93,8 +93,8 @@ module riscv_core logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage logic is_compressed_id; logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage - logic [31:0] current_pc_if; // Current Program counter - logic [31:0] current_pc_id; // Current Program counter + logic [31:0] pc_if; // Program counter in IF stage + logic [31:0] pc_id; // Program counter in ID stage logic clear_instr_valid; logic pc_set; @@ -173,6 +173,8 @@ module riscv_core logic data_sign_ext_ex; logic [1:0] data_reg_offset_ex; logic data_req_ex; + logic [31:0] data_pc_ex; + logic data_load_event_ex; logic data_misaligned_ex; // stall control @@ -279,8 +281,8 @@ module riscv_core .instr_rdata_id_o ( instr_rdata_id ), .is_compressed_id_o ( is_compressed_id ), .illegal_c_insn_id_o ( illegal_c_insn_id ), - .current_pc_if_o ( current_pc_if ), - .current_pc_id_o ( current_pc_id ), + .pc_if_o ( pc_if ), + .pc_id_o ( pc_id ), // control signals .clear_instr_valid_i ( clear_instr_valid ), @@ -360,8 +362,8 @@ module riscv_core .illegal_c_insn_i ( illegal_c_insn_id ), .is_compressed_i ( is_compressed_id ), - .current_pc_if_i ( current_pc_if ), - .current_pc_id_i ( current_pc_id ), + .pc_if_i ( pc_if ), + .pc_id_i ( pc_id ), // Stalls .halt_if_o ( halt_if ), @@ -418,12 +420,15 @@ module riscv_core .csr_hwlp_data_i ( csr_hwlp_data ), // LSU - .data_req_ex_o ( data_req_ex ), // to load store unit - .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_misaligned_ex_o ( data_misaligned_ex ), // to load store unit + .data_req_ex_o ( data_req_ex ), // to load store unit + .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_pc_ex_o ( data_pc_ex ), // to load store unit + .data_load_event_ex_o ( data_load_event_ex ), // to load store unit + + .data_misaligned_ex_o ( data_misaligned_ex ), // to load store unit .prepost_useincr_ex_o ( useincr_addr_ex ), .data_misaligned_i ( data_misaligned ), @@ -607,52 +612,54 @@ module riscv_core ) cs_registers_i ( - .clk ( clk ), - .rst_n ( rst_n ), + .clk ( clk ), + .rst_n ( rst_n ), // Core and Cluster ID from outside - .core_id_i ( core_id_i ), - .cluster_id_i ( cluster_id_i ), + .core_id_i ( core_id_i ), + .cluster_id_i ( cluster_id_i ), // Interface to CSRs (SRAM like) - .csr_access_i ( csr_access_ex ), - .csr_addr_i ( csr_addr ), - .csr_wdata_i ( csr_wdata ), - .csr_op_i ( csr_op ), - .csr_rdata_o ( csr_rdata ), + .csr_access_i ( csr_access_ex ), + .csr_addr_i ( csr_addr ), + .csr_wdata_i ( csr_wdata ), + .csr_op_i ( csr_op ), + .csr_rdata_o ( csr_rdata ), // Interrupt related control signals - .irq_enable_o ( irq_enable ), - .mepc_o ( mepc ), + .irq_enable_o ( irq_enable ), + .mepc_o ( mepc ), - .curr_pc_id_i ( current_pc_id ), // from IF stage - .exc_save_i ( exc_save_id ), - .exc_restore_i ( exc_restore_id ), + .curr_pc_id_i ( pc_id ), // from IF stage + .data_pc_ex_i ( data_pc_ex ), // from ID/EX pipeline + .data_load_event_ex_i ( data_load_event_ex ), // from ID/EX pipeline + .exc_save_i ( exc_save_id ), + .exc_restore_i ( exc_restore_id ), - .exc_cause_i ( exc_cause ), - .save_exc_cause_i ( save_exc_cause ), + .exc_cause_i ( exc_cause ), + .save_exc_cause_i ( save_exc_cause ), // from hwloop registers - .hwlp_start_i ( hwlp_start ), - .hwlp_end_i ( hwlp_end ), - .hwlp_cnt_i ( hwlp_cnt ), + .hwlp_start_i ( hwlp_start ), + .hwlp_end_i ( hwlp_end ), + .hwlp_cnt_i ( hwlp_cnt ), - .hwlp_regid_o ( csr_hwlp_regid ), - .hwlp_we_o ( csr_hwlp_we ), - .hwlp_data_o ( csr_hwlp_data ), + .hwlp_regid_o ( csr_hwlp_regid ), + .hwlp_we_o ( csr_hwlp_we ), + .hwlp_data_o ( csr_hwlp_data ), // performance counter related signals - .id_valid_i ( id_valid ), - .is_compressed_i ( is_compressed_id ), - .is_decoding_i ( is_decoding ), + .id_valid_i ( id_valid ), + .is_compressed_i ( is_compressed_id ), + .is_decoding_i ( is_decoding ), - .imiss_i ( perf_imiss ), - .pc_set_i ( pc_set ), - .jump_i ( perf_jump ), - .branch_i ( branch_in_ex ), - .branch_taken_i ( branch_decision ), - .ld_stall_i ( perf_ld_stall ), - .jr_stall_i ( perf_jr_stall ), + .imiss_i ( perf_imiss ), + .pc_set_i ( pc_set ), + .jump_i ( perf_jump ), + .branch_i ( branch_in_ex ), + .branch_taken_i ( branch_decision ), + .ld_stall_i ( perf_ld_stall ), + .jr_stall_i ( perf_jr_stall ), .mem_load_i ( data_req_o & data_gnt_i & (~data_we_o) ), .mem_store_i ( data_req_o & data_gnt_i & data_we_o ), @@ -713,8 +720,8 @@ module riscv_core .regfile_rdata_i ( dbg_rdata ), // signals for PPC and NPC - .curr_pc_if_i ( current_pc_if ), // from IF stage - .curr_pc_id_i ( current_pc_id ), // from IF stage + .curr_pc_if_i ( pc_if ), // from IF stage + .curr_pc_id_i ( pc_id ), // from IF stage .branch_pc_i ( branch_pc_ex ), // PC of last executed branch (in EX stage) .branch_in_ex_i ( branch_in_ex ), @@ -735,7 +742,7 @@ module riscv_core .core_id ( core_id_i ), .cluster_id ( cluster_id_i ), - .pc ( id_stage_i.current_pc_id_i ), + .pc ( id_stage_i.pc_id_i ), .instr ( id_stage_i.instr ), .compressed ( id_stage_i.is_compressed_i ), .id_valid ( id_stage_i.id_valid_o ), @@ -794,7 +801,7 @@ module riscv_core .pc_set ( pc_set ), .if_valid ( if_valid ), - .pc ( id_stage_i.current_pc_id_i ), + .pc ( id_stage_i.pc_id_i ), .instr ( id_stage_i.instr ), .is_compressed ( is_compressed_id ), .id_valid ( id_stage_i.id_valid_o ),