From 6f57dd79572c177b775a934bee54ceb85a55c28a Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Sat, 7 Nov 2026 03:14:46 +0800 Subject: refactor: rename RTL source files --- rv64cpu/rtl/core/privileged/trap_controller.sv | 279 +++++++++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 rv64cpu/rtl/core/privileged/trap_controller.sv (limited to 'rv64cpu/rtl/core/privileged/trap_controller.sv') diff --git a/rv64cpu/rtl/core/privileged/trap_controller.sv b/rv64cpu/rtl/core/privileged/trap_controller.sv new file mode 100644 index 0000000..0969fdc --- /dev/null +++ b/rv64cpu/rtl/core/privileged/trap_controller.sv @@ -0,0 +1,279 @@ +// Richard CPU +// Copyright (C) 2026 Richard Qin + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// File path: rtl/core/trap_ctrl.sv +// Description: Privileged-level Trap Controller (Exception and Interrupt Handling) +// Detects exceptions/interrupts, triggers context saving, and generates global pipeline flush and PC jump signals + +module trap_ctrl + import rv64_pkg::*; + import csr_pkg::*; +( + // Submission signals from the WB stage (guarantee of precise exceptions) + input logic [XLEN-1:0] wb_pc, + input logic trap_illegal_instr, + input logic trap_is_ecall, + input logic trap_is_ebreak, + input logic trap_is_mret, + input logic trap_is_sret, + input logic trap_instr_access_fault, + input logic trap_load_fault, + input logic trap_store_fault, + input logic trap_instr_page_fault, + input logic trap_load_page_fault, + input logic trap_store_page_fault, + input logic [XLEN-1:0] trap_bad_addr, + input logic [INST_WIDTH-1:0] trap_bad_instr, + + // Status read from CSR Unit + input logic csr_mstatus_mie, // Global interrupt enable (MIE) + input logic [XLEN-1:0] csr_mie, // Machine interrupt enable CSR + input logic [XLEN-1:0] csr_sie, // Supervisor interrupt enable CSR view + input logic [XLEN-1:0] csr_mip, // Machine interrupt pending CSR + input logic [XLEN-1:0] csr_sip, // Supervisor interrupt pending CSR view + input logic [XLEN-1:0] csr_mstatus, // Machine status CSR + input logic [XLEN-1:0] csr_mtvec, // Machine trap vector + input logic [XLEN-1:0] csr_stvec, // Supervisor trap vector + input logic [XLEN-1:0] csr_mepc, // Machine exception PC (for MRET) + input logic [XLEN-1:0] csr_sepc, // Supervisor exception PC (for SRET) + input logic [XLEN-1:0] csr_medeleg, // Exception delegation mask + input logic [XLEN-1:0] csr_mideleg, // Interrupt delegation mask + input logic [1:0] csr_priv_mode, // Current privilege level + + // Status update signal sent to the CSR Unit + output logic trap_trigger, // Trigger exception/interrupt context save + output logic [XLEN-1:0] trap_mepc, // Saved PC (MEPC/SEPC selected by trap_to_s_mode) + output logic [XLEN-1:0] trap_mcause, // Cause code (bit63 indicates interrupt) + output logic [XLEN-1:0] trap_mtval, // Additional information saved to mtval/stval + output logic trap_to_s_mode, // 1: delegated to Supervisor mode + output logic mret_en, // Trigger MRET context restore + output logic sret_en, // Trigger SRET context restore + + // Control flow interference sent to the Hazard Unit and IF stage + output logic trap_flush_req, // Global pipeline flush request + output logic trap_pc_sel, // Forcibly take over PC MUX (0: normal, 1: Trap/Mret/Sret) + output logic [XLEN-1:0] trap_next_pc // Target address for forced jump +); + + typedef enum logic [1:0] { + PRIV_MODE_U = 2'b00, + PRIV_MODE_S = 2'b01, + PRIV_MODE_M = 2'b11 + } priv_mode_t; + + localparam logic [XLEN-1:0] INTERRUPT_BIT = {1'b1, {(XLEN-1){1'b0}}}; + localparam int INTERRUPT_M_SOFTWARE_BIT = int'(INTERRUPT_M_SOFTWARE); + localparam int INTERRUPT_M_TIMER_BIT = int'(INTERRUPT_M_TIMER); + localparam int INTERRUPT_M_EXTERNAL_BIT = int'(INTERRUPT_M_EXTERNAL); + localparam int INTERRUPT_S_SOFTWARE_BIT = int'(INTERRUPT_S_SOFTWARE); + localparam int INTERRUPT_S_TIMER_BIT = int'(INTERRUPT_S_TIMER); + localparam int INTERRUPT_S_EXTERNAL_BIT = int'(INTERRUPT_S_EXTERNAL); + localparam int MSTATUS_SIE_BIT = 1; + localparam int MSTATUS_TSR_BIT = 22; + + logic has_sync_exception; + logic [XLEN-1:0] sync_cause; + logic [XLEN-1:0] sync_mtval; + logic [XLEN-1:0] illegal_instr_value; + logic sret_tsr_illegal; + + assign illegal_instr_value = {{(XLEN-INST_WIDTH){1'b0}}, trap_bad_instr}; + assign sret_tsr_illegal = trap_is_sret && + (priv_mode_t'(csr_priv_mode) == PRIV_MODE_S) && + csr_mstatus[MSTATUS_TSR_BIT]; + + always_comb begin + has_sync_exception = 1'b0; + sync_cause = '0; + sync_mtval = '0; + + if (trap_instr_access_fault) begin + has_sync_exception = 1'b1; + sync_cause = EXC_INST_FAULT; + sync_mtval = trap_bad_addr; + end else if (trap_instr_page_fault) begin + has_sync_exception = 1'b1; + sync_cause = EXC_INSTR_PAGE_FAULT; + sync_mtval = trap_bad_addr; + end else if (trap_illegal_instr || sret_tsr_illegal) begin + has_sync_exception = 1'b1; + sync_cause = EXC_INST_ILLEGAL; + sync_mtval = illegal_instr_value; + end else if (trap_is_ebreak) begin + has_sync_exception = 1'b1; + sync_cause = EXC_BREAKPOINT; + sync_mtval = wb_pc; + end else if (trap_is_ecall) begin + has_sync_exception = 1'b1; + case (priv_mode_t'(csr_priv_mode)) + PRIV_MODE_U: sync_cause = EXC_ECALL_FROM_U; + PRIV_MODE_S: sync_cause = EXC_ECALL_FROM_S; + default: sync_cause = EXC_ECALL_FROM_M; + endcase + sync_mtval = '0; + end else if (trap_load_fault) begin + has_sync_exception = 1'b1; + sync_cause = EXC_LOAD_FAULT; + sync_mtval = trap_bad_addr; + end else if (trap_store_fault) begin + has_sync_exception = 1'b1; + sync_cause = EXC_STORE_FAULT; + sync_mtval = trap_bad_addr; + end else if (trap_load_page_fault) begin + has_sync_exception = 1'b1; + sync_cause = EXC_LOAD_PAGE_FAULT; + sync_mtval = trap_bad_addr; + end else if (trap_store_page_fault) begin + has_sync_exception = 1'b1; + sync_cause = EXC_STORE_PAGE_FAULT; + sync_mtval = trap_bad_addr; + end + end + + // Interrupt Detection - Asynchronous, gated by mie and privilege global-enable rules. + logic has_interrupt; + logic [XLEN-1:0] interrupt_cause; + logic machine_interrupts_globally_enabled; + logic supervisor_interrupts_globally_enabled; + logic interrupt_targets_s_mode; + + assign machine_interrupts_globally_enabled = (priv_mode_t'(csr_priv_mode) != PRIV_MODE_M) || + csr_mstatus_mie; + assign supervisor_interrupts_globally_enabled = (priv_mode_t'(csr_priv_mode) == PRIV_MODE_U) || + ((priv_mode_t'(csr_priv_mode) == PRIV_MODE_S) && + csr_mstatus[MSTATUS_SIE_BIT]); + + function automatic logic interrupt_pending_enabled( + input logic [XLEN-1:0] pending, + input logic [XLEN-1:0] enable, + input int cause + ); + interrupt_pending_enabled = pending[cause[5:0]] && enable[cause[5:0]]; + endfunction + + task automatic take_interrupt( + input logic [XLEN-1:0] cause, + input logic to_s_mode, + output logic taken, + output logic [XLEN-1:0] taken_cause, + output logic taken_targets_s_mode + ); + taken = 1'b1; + taken_cause = INTERRUPT_BIT | cause; + taken_targets_s_mode = to_s_mode; + endtask + + function automatic logic s_interrupt_cause_delegated(input int cause); + s_interrupt_cause_delegated = csr_mideleg[cause[5:0]]; + endfunction + + function automatic logic s_interrupt_cause_takeable(input int cause); + if (s_interrupt_cause_delegated(cause)) begin + s_interrupt_cause_takeable = supervisor_interrupts_globally_enabled && + interrupt_pending_enabled(csr_sip, csr_sie, cause); + end else begin + s_interrupt_cause_takeable = machine_interrupts_globally_enabled && + interrupt_pending_enabled(csr_mip, csr_mie, cause); + end + endfunction + + always_comb begin + has_interrupt = 1'b0; + interrupt_cause = '0; + interrupt_targets_s_mode = 1'b0; + + if (machine_interrupts_globally_enabled && + interrupt_pending_enabled(csr_mip, csr_mie, INTERRUPT_M_EXTERNAL_BIT)) begin + take_interrupt(INTERRUPT_M_EXTERNAL, 1'b0, has_interrupt, interrupt_cause, interrupt_targets_s_mode); + end else if (machine_interrupts_globally_enabled && + interrupt_pending_enabled(csr_mip, csr_mie, INTERRUPT_M_SOFTWARE_BIT)) begin + take_interrupt(INTERRUPT_M_SOFTWARE, 1'b0, has_interrupt, interrupt_cause, interrupt_targets_s_mode); + end else if (machine_interrupts_globally_enabled && + interrupt_pending_enabled(csr_mip, csr_mie, INTERRUPT_M_TIMER_BIT)) begin + take_interrupt(INTERRUPT_M_TIMER, 1'b0, has_interrupt, interrupt_cause, interrupt_targets_s_mode); + end else if (s_interrupt_cause_takeable(INTERRUPT_S_EXTERNAL_BIT)) begin + take_interrupt(INTERRUPT_S_EXTERNAL, s_interrupt_cause_delegated(INTERRUPT_S_EXTERNAL_BIT), + has_interrupt, interrupt_cause, interrupt_targets_s_mode); + end else if (s_interrupt_cause_takeable(INTERRUPT_S_SOFTWARE_BIT)) begin + take_interrupt(INTERRUPT_S_SOFTWARE, s_interrupt_cause_delegated(INTERRUPT_S_SOFTWARE_BIT), + has_interrupt, interrupt_cause, interrupt_targets_s_mode); + end else if (s_interrupt_cause_takeable(INTERRUPT_S_TIMER_BIT)) begin + take_interrupt(INTERRUPT_S_TIMER, s_interrupt_cause_delegated(INTERRUPT_S_TIMER_BIT), + has_interrupt, interrupt_cause, interrupt_targets_s_mode); + end + end + + logic [XLEN-1:0] trap_cause_value; + logic [XLEN-1:0] trap_mtval_value; + logic trap_is_interrupt; + + assign trap_is_interrupt = has_interrupt; + assign trap_cause_value = has_interrupt ? interrupt_cause : sync_cause; + assign trap_mtval_value = has_interrupt ? '0 : sync_mtval; + + assign trap_trigger = has_interrupt | has_sync_exception; + + logic [5:0] trap_cause_index; + logic delegate_to_s; + logic [XLEN-1:0] deleg_mask; + logic machine_interrupt_cause; + + assign trap_cause_index = trap_cause_value[5:0]; + assign deleg_mask = trap_is_interrupt ? csr_mideleg : csr_medeleg; + assign machine_interrupt_cause = trap_is_interrupt && + ((trap_cause_index == INTERRUPT_M_SOFTWARE_BIT[5:0]) || + (trap_cause_index == INTERRUPT_M_TIMER_BIT[5:0]) || + (trap_cause_index == INTERRUPT_M_EXTERNAL_BIT[5:0])); + assign delegate_to_s = trap_trigger && (priv_mode_t'(csr_priv_mode) != PRIV_MODE_M) && + ((trap_is_interrupt && interrupt_targets_s_mode) || + (!trap_is_interrupt && deleg_mask[trap_cause_index] && !machine_interrupt_cause)); + assign trap_to_s_mode = delegate_to_s; + + assign trap_mcause = trap_trigger ? trap_cause_value : '0; + assign trap_mtval = trap_trigger ? trap_mtval_value : '0; + assign trap_mepc = trap_trigger ? wb_pc : '0; + + assign mret_en = trap_is_mret & ~trap_trigger; + assign sret_en = trap_is_sret & ~trap_trigger; + + assign trap_flush_req = trap_trigger | mret_en | sret_en; + assign trap_pc_sel = trap_flush_req; + + logic [XLEN-1:0] trap_vector_base; + logic [1:0] trap_vector_mode; + logic [XLEN-1:0] trap_vector_aligned; + + assign trap_vector_base = delegate_to_s ? csr_stvec : csr_mtvec; + assign trap_vector_mode = trap_vector_base[1:0]; + assign trap_vector_aligned = {trap_vector_base[XLEN-1:2], 2'b00}; + + always_comb begin + if (trap_trigger) begin + if ((trap_vector_mode == 2'b01) && trap_is_interrupt) begin + trap_next_pc = trap_vector_aligned + (({{(XLEN-6){1'b0}}, trap_cause_index}) << 2); + end else begin + trap_next_pc = trap_vector_aligned; + end + end else if (mret_en) begin + trap_next_pc = csr_mepc; + end else if (sret_en) begin + trap_next_pc = csr_sepc; + end else begin + trap_next_pc = '0; + end + end + +endmodule -- cgit v1.2.3 From e0948e3fc10029ba4bb4d48d7b5daae94fe575b9 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Sat, 7 Nov 2026 03:16:17 +0800 Subject: refactor: align RTL module names with files --- rv64cpu/rtl/core/execute/instruction_decoder.sv | 2 +- rv64cpu/rtl/core/execute/integer_alu.sv | 2 +- rv64cpu/rtl/core/fpu/fpu.sv | 2 +- rv64cpu/rtl/core/mmu/mmu.sv | 2 +- rv64cpu/rtl/core/pipeline/ex_stage.sv | 2 +- rv64cpu/rtl/core/pipeline/id_stage.sv | 6 +++--- rv64cpu/rtl/core/privileged/trap_controller.sv | 2 +- rv64cpu/rtl/core/registers/fpr_file.sv | 2 +- rv64cpu/rtl/core/registers/gpr_file.sv | 2 +- rv64cpu/rtl/core/rv64_core.sv | 8 ++++---- 10 files changed, 15 insertions(+), 15 deletions(-) (limited to 'rv64cpu/rtl/core/privileged/trap_controller.sv') diff --git a/rv64cpu/rtl/core/execute/instruction_decoder.sv b/rv64cpu/rtl/core/execute/instruction_decoder.sv index c39a637..14d9559 100644 --- a/rv64cpu/rtl/core/execute/instruction_decoder.sv +++ b/rv64cpu/rtl/core/execute/instruction_decoder.sv @@ -19,7 +19,7 @@ // Translates 32-bit instructions into control signals for the pipeline. // C is handled by the IF-stage decompressor before this decoder. -module decoder +module instruction_decoder import rv64_pkg::*; ( input logic [31:0] instr, // 32-bit instruction diff --git a/rv64cpu/rtl/core/execute/integer_alu.sv b/rv64cpu/rtl/core/execute/integer_alu.sv index 08635ce..833f902 100644 --- a/rv64cpu/rtl/core/execute/integer_alu.sv +++ b/rv64cpu/rtl/core/execute/integer_alu.sv @@ -17,7 +17,7 @@ // File path: rtl/core/alu.sv // Description: 64-bit Arithmetic Logic Unit (ALU) -module alu +module integer_alu import rv64_pkg::*; ( input alu_op_t alu_op, // ALU operation select (from decoder) diff --git a/rv64cpu/rtl/core/fpu/fpu.sv b/rv64cpu/rtl/core/fpu/fpu.sv index a1962e1..9e9494d 100644 --- a/rv64cpu/rtl/core/fpu/fpu.sv +++ b/rv64cpu/rtl/core/fpu/fpu.sv @@ -4,7 +4,7 @@ // File path: rtl/core/fpu/fpu_unit.sv // Description: RV64F/RV64D floating-point execution unit. -module fpu_unit +module fpu import rv64_pkg::*; ( input fp_op_t fp_op, diff --git a/rv64cpu/rtl/core/mmu/mmu.sv b/rv64cpu/rtl/core/mmu/mmu.sv index 169bf81..60c4afa 100644 --- a/rv64cpu/rtl/core/mmu/mmu.sv +++ b/rv64cpu/rtl/core/mmu/mmu.sv @@ -17,7 +17,7 @@ // File path: rtl/core/mmu/mmu_top.sv // Description: MMU top-level integrating iTLB + dTLB + shared PTW -module mmu_top +module mmu import rv64_pkg::*; #( parameter int ITLB_ENTRIES = 16, diff --git a/rv64cpu/rtl/core/pipeline/ex_stage.sv b/rv64cpu/rtl/core/pipeline/ex_stage.sv index 287bfd7..2758ffc 100644 --- a/rv64cpu/rtl/core/pipeline/ex_stage.sv +++ b/rv64cpu/rtl/core/pipeline/ex_stage.sv @@ -88,7 +88,7 @@ module ex_stage // -------------- // Instantiate the core computing engine ALU - alu alu_inst ( + integer_alu alu_inst ( .alu_op (ex_alu_op), .operand_a (alu_operand_a), .operand_b (alu_operand_b), diff --git a/rv64cpu/rtl/core/pipeline/id_stage.sv b/rv64cpu/rtl/core/pipeline/id_stage.sv index 9003b42..1cf447a 100644 --- a/rv64cpu/rtl/core/pipeline/id_stage.sv +++ b/rv64cpu/rtl/core/pipeline/id_stage.sv @@ -108,7 +108,7 @@ module id_stage // Instruction Decoder Instantiation - decoder u_decoder ( + instruction_decoder u_decoder ( .instr (if_instr), .priv_mode (csr_priv_mode), .mstatus_tsr (csr_mstatus_tsr), @@ -164,7 +164,7 @@ module id_stage ); // Register File Instantiation - regfile u_regfile ( + gpr_file u_regfile ( .clk (clk), .rst (rst), @@ -180,7 +180,7 @@ module id_stage .rd_wdata (wb_rd_wdata) ); - fp_regfile u_fp_regfile ( + fpr_file u_fp_regfile ( .clk (clk), .rst (rst), .fs1_addr (rs1_addr), diff --git a/rv64cpu/rtl/core/privileged/trap_controller.sv b/rv64cpu/rtl/core/privileged/trap_controller.sv index 0969fdc..246b392 100644 --- a/rv64cpu/rtl/core/privileged/trap_controller.sv +++ b/rv64cpu/rtl/core/privileged/trap_controller.sv @@ -18,7 +18,7 @@ // Description: Privileged-level Trap Controller (Exception and Interrupt Handling) // Detects exceptions/interrupts, triggers context saving, and generates global pipeline flush and PC jump signals -module trap_ctrl +module trap_controller import rv64_pkg::*; import csr_pkg::*; ( diff --git a/rv64cpu/rtl/core/registers/fpr_file.sv b/rv64cpu/rtl/core/registers/fpr_file.sv index 67e83f9..7522b5f 100644 --- a/rv64cpu/rtl/core/registers/fpr_file.sv +++ b/rv64cpu/rtl/core/registers/fpr_file.sv @@ -4,7 +4,7 @@ // File path: rtl/core/fp_regfile.sv // Description: 32-entry 64-bit floating-point register file for RV64F/RV64D. -module fp_regfile +module fpr_file import rv64_pkg::*; ( input logic clk, diff --git a/rv64cpu/rtl/core/registers/gpr_file.sv b/rv64cpu/rtl/core/registers/gpr_file.sv index dbc3c04..4ddf200 100644 --- a/rv64cpu/rtl/core/registers/gpr_file.sv +++ b/rv64cpu/rtl/core/registers/gpr_file.sv @@ -17,7 +17,7 @@ // File path: rtl/core/regfile.sv // Description: 64-bit Register File -module regfile +module gpr_file import rv64_pkg::*; ( input logic clk, // Clock signal diff --git a/rv64cpu/rtl/core/rv64_core.sv b/rv64cpu/rtl/core/rv64_core.sv index 51c64f8..630fc3d 100644 --- a/rv64cpu/rtl/core/rv64_core.sv +++ b/rv64cpu/rtl/core/rv64_core.sv @@ -18,7 +18,7 @@ // Description: Richard CPU core top-level wrapper (Core Top) // Assembles a 5-stage pipeline, 4 inter-stage registers, and Hazard Unit -module richard_core +module rv64_core import rv64_pkg::*; import csr_pkg::*; ( @@ -389,7 +389,7 @@ module richard_core end end - mmu_top u_mmu_top ( + mmu u_mmu_top ( .clk (clk), .rst (rst), .satp_value (csr_satp_value), @@ -763,7 +763,7 @@ module richard_core .ex_branch_target (ex_branch_target_out) ); - fpu_unit u_fpu_unit ( + fpu u_fpu_unit ( .fp_op (ex_fp_op_in), .fp_fmt (ex_fp_fmt_in), .rm ((ex_fp_rm_in == 3'b111) ? csr_frm_value : ex_fp_rm_in), @@ -1171,7 +1171,7 @@ module richard_core .csr_illegal_access (csr_illegal_access) ); - trap_ctrl u_trap_ctrl ( + trap_controller u_trap_ctrl ( .wb_pc (wb_pc_in), .trap_illegal_instr (trap_illegal_instr), .trap_is_ecall (trap_is_ecall), -- cgit v1.2.3