From cf0476e565c74082f011a6c428095e60a743b822 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Wed, 1 Apr 2026 00:58:22 +0800 Subject: feat: Complete CSR/privileged/exception interrupt path and fill in strict acceptance tests - Refactor trap/CSR data path in the Core, unified with trap_ctrl interface to drive CSR update and return process - Improve critical paths for exception/interrupt handling: ecall, illegal, load fault, external interrupt, mret/sret return - Adjust pipeline stage registers with flush/stall coordination, fix residual control signal issues in trap scenarios - Enhance decode and related pipeline module behavior consistency, fill in missing control signal propagation across registers - Expand core integration testing, add trap/interrupt scenarios and CLI dispatch that can be executed per case - Extend CSR unit test coverage: read/write semantics, privilege switching, delegation and nested returns, illegal access protection, etc. - Register new core scenario cases in CTest to form a regression-capable P2 strict acceptance suite Verification: - Build passed - Full CTest passed (22/22) --- rv64cpu/rtl/core/hazard_unit.sv | 92 +++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 27 deletions(-) (limited to 'rv64cpu/rtl/core/hazard_unit.sv') diff --git a/rv64cpu/rtl/core/hazard_unit.sv b/rv64cpu/rtl/core/hazard_unit.sv index 2798116..aef550c 100644 --- a/rv64cpu/rtl/core/hazard_unit.sv +++ b/rv64cpu/rtl/core/hazard_unit.sv @@ -37,6 +37,7 @@ module hazard_unit input logic ex_reg_write_en, input logic ex_is_load, input logic ex_branch_taken, + input logic [XLEN-1:0] ex_branch_target, // ----------------------- // Inputs from MEM Stage (EX/MEM register outputs) @@ -45,6 +46,13 @@ module hazard_unit input logic mem_reg_write_en, input logic mem_stall_req, // D-Cache miss or memory busy + // ----------------------- + // Trap Controller Inputs + // ----------------------- + input logic trap_flush_req, + input logic trap_pc_sel, + input logic [XLEN-1:0] trap_target_pc, + // ----------------------- // Inputs from WB Stage (MEM/WB register outputs) // ----------------------- @@ -66,7 +74,14 @@ module hazard_unit output logic id_ex_stall_en, output logic ex_mem_stall_en, output logic if_id_flush_en, - output logic id_ex_flush_en + output logic id_ex_flush_en, + + // ----------------------- + // Outputs: IF-stage PC redirect controls + // ----------------------- + output logic pc_redirect_sel, + output logic [XLEN-1:0] pc_redirect_target, + output logic pc_redirect_is_trap ); // ----------------------- @@ -111,41 +126,64 @@ module hazard_unit assign load_use_stall = ex_is_load && (ex_rd_addr != 5'b0) && ((ex_rd_addr == id_rs1_addr) || (ex_rd_addr == id_rs2_addr)); + // ----------------------- + // PC Redirect Selection (Trap has top priority) + // ----------------------- + always_comb begin + pc_redirect_sel = 1'b0; + pc_redirect_target = '0; + pc_redirect_is_trap = 1'b0; + + if (trap_pc_sel) begin + pc_redirect_sel = 1'b1; + pc_redirect_target = trap_target_pc; + pc_redirect_is_trap = 1'b1; + end else if (ex_branch_taken) begin + pc_redirect_sel = 1'b1; + pc_redirect_target = ex_branch_target; + end + end + // ----------------------- // Stall and Flush Signal Generation // ----------------------- always_comb begin // Defaults: no stalls, no flushes - if_stall_en = 1'b0; - if_id_stall_en = 1'b0; - id_ex_stall_en = 1'b0; + if_stall_en = 1'b0; + if_id_stall_en = 1'b0; + id_ex_stall_en = 1'b0; ex_mem_stall_en = 1'b0; - if_id_flush_en = 1'b0; - id_ex_flush_en = 1'b0; - - // (1) Memory stall (D-Cache miss): freeze the entire pipeline - if (mem_stall_req) begin - if_stall_en = 1'b1; - if_id_stall_en = 1'b1; - id_ex_stall_en = 1'b1; - ex_mem_stall_en = 1'b1; - end + if_id_flush_en = 1'b0; + id_ex_flush_en = 1'b0; - // (2) Load-Use stall: freeze IF and IF/ID, insert bubble into ID/EX - if (load_use_stall && !mem_stall_req) begin - if_stall_en = 1'b1; - if_id_stall_en = 1'b1; - id_ex_flush_en = 1'b1; - end - - // (3) Branch/jump misprediction: flush IF/ID and ID/EX - // Branch flush overrides load-use stall (the stalled instruction is invalid anyway) - if (ex_branch_taken) begin + if (trap_flush_req) begin if_id_flush_en = 1'b1; id_ex_flush_en = 1'b1; - // Cancel load-use stall if branch is also taken - if_stall_en = 1'b0; - if_id_stall_en = 1'b0; + end else begin + // (1) Memory stall (D-Cache miss): freeze the entire pipeline + if (mem_stall_req) begin + if_stall_en = 1'b1; + if_id_stall_en = 1'b1; + id_ex_stall_en = 1'b1; + ex_mem_stall_en = 1'b1; + end + + // (2) Load-Use stall: freeze IF and IF/ID, insert bubble into ID/EX + if (load_use_stall && !mem_stall_req) begin + if_stall_en = 1'b1; + if_id_stall_en = 1'b1; + id_ex_flush_en = 1'b1; + end + + // (3) Branch/jump misprediction: flush IF/ID and ID/EX + // Branch flush overrides load-use stall (the stalled instruction is invalid anyway) + if (ex_branch_taken) begin + if_id_flush_en = 1'b1; + id_ex_flush_en = 1'b1; + // Cancel load-use stall if branch is also taken + if_stall_en = 1'b0; + if_id_stall_en = 1'b0; + end end end -- cgit v1.2.3