From f771a1294d509f5521f4a0843223a325f5377830 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Mon, 10 Oct 2022 00:28:42 +0100 Subject: [PATCH] Alias DPC to the real program counter, small savings overall --- hdl/hazard3_core.v | 12 ++++++++++++ hdl/hazard3_csr.v | 30 ++++++++++++++---------------- hdl/hazard3_decode.v | 11 ++++++++++- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/hdl/hazard3_core.v b/hdl/hazard3_core.v index 7ea5078..8601244 100644 --- a/hdl/hazard3_core.v +++ b/hdl/hazard3_core.v @@ -224,6 +224,10 @@ wire x_jump_not_except; wire x_mmode_execution; wire x_trap_wfi; +wire [W_ADDR-1:0] debug_dpc_wdata; +wire debug_dpc_wen; +wire [W_ADDR-1:0] debug_dpc_rdata; + hazard3_decode #( `include "hazard3_config_inst.vh" ) decode_u ( @@ -243,6 +247,10 @@ hazard3_decode #( .m_mode (x_mmode_execution), .trap_wfi (x_trap_wfi), + .debug_dpc_wdata (debug_dpc_wdata), + .debug_dpc_wen (debug_dpc_wen), + .debug_dpc_rdata (debug_dpc_rdata), + .d_starved (d_starved), .x_stall (x_stall), .f_jump_now (f_jump_now), @@ -964,6 +972,10 @@ hazard3_csr #( .dbg_data0_wdata (dbg_data0_wdata), .dbg_data0_wen (dbg_data0_wen), + .debug_dpc_wdata (debug_dpc_wdata), + .debug_dpc_wen (debug_dpc_wen), + .debug_dpc_rdata (debug_dpc_rdata), + // CSR access port // *en_soon are early access strobes which are not a function of bus stall. // Can generate access faults (hence traps), but do not actually perform access. diff --git a/hdl/hazard3_csr.v b/hdl/hazard3_csr.v index 4ccd250..3154aa5 100644 --- a/hdl/hazard3_csr.v +++ b/hdl/hazard3_csr.v @@ -36,6 +36,10 @@ module hazard3_csr #( output wire [W_DATA-1:0] dbg_data0_wdata, output wire dbg_data0_wen, + output wire [W_ADDR-1:0] debug_dpc_wdata, + output wire debug_dpc_wen, + input wire [W_ADDR-1:0] debug_dpc_rdata, + // Read port is combinatorial. // Write port is synchronous, and write effects will be observed on the next clock cycle. // The *_soon strobes are versions which the core does not gate with its stall signal. @@ -510,20 +514,14 @@ always @ (posedge clk or negedge rst_n) begin end end -reg [XLEN-1:0] dpc; - -always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - dpc <= X0; - end else if (DEBUG_SUPPORT) begin - if (enter_debug_mode) - dpc <= mepc_in; - else if (debug_mode && wen && addr == DPC) - // 1 or 2 LSBs are hardwired to 0, depending on IALIGN. - dpc <= wdata_update & (~X0 << 2 - EXTENSION_C); - end -end +// DPC is mapped to the real PC in the decode module. We set it to the +// exception return address when entering Debug Mode, and whilst in Debug +// Mode we can write to it as though it were a CSR. Note only IALIGN'd values +// can be written to dpc. +assign debug_dpc_wdata = (debug_mode ? wdata_update : mepc_in) & (~X0 << 2 - EXTENSION_C); +assign debug_dpc_wen = debug_mode ? wen && addr == DPC : enter_debug_mode; +// Debug Module's data0 register is mapped into the core's CSR space: assign dbg_data0_wdata = wdata; assign dbg_data0_wen = debug_mode && wen && addr == DMDATA0; @@ -1059,7 +1057,7 @@ always @ (*) begin DPC: if (DEBUG_SUPPORT) begin decode_match = match_drw; - rdata = dpc; + rdata = debug_dpc_rdata; end DMDATA0: if (DEBUG_SUPPORT) begin @@ -1290,8 +1288,8 @@ wire [3:0] mcause_irq_num = irq_active ? standard_irq_num : 4'd0; wire [3:0] vector_sel = !exception_req_any && irq_vector_enable ? mcause_irq_num : 4'd0; assign trap_addr = - except == EXCEPT_MRET ? mepc : - pending_dbg_resume ? dpc : mtvec | {26'h0, vector_sel, 2'h0}; + except == EXCEPT_MRET ? mepc : + pending_dbg_resume ? debug_dpc_rdata : mtvec | {26'h0, vector_sel, 2'h0}; // Check for exception-like or IRQ-like trap entry; any debug mode entry takes // priority over any regular trap. diff --git a/hdl/hazard3_decode.v b/hdl/hazard3_decode.v index 5b4cec5..65e7653 100644 --- a/hdl/hazard3_decode.v +++ b/hdl/hazard3_decode.v @@ -25,6 +25,10 @@ module hazard3_decode #( input wire m_mode, input wire trap_wfi, + input wire [W_ADDR-1:0] debug_dpc_wdata, + input wire debug_dpc_wen, + output wire [W_ADDR-1:0] debug_dpc_rdata, + output wire d_starved, input wire x_stall, input wire f_jump_now, @@ -131,6 +135,7 @@ end reg [W_ADDR-1:0] pc; wire [W_ADDR-1:0] pc_seq_next = pc + (d_instr_is_32bit ? 32'h4 : 32'h2); assign d_pc = pc; +assign debug_dpc_rdata = pc; // Frontend should mark the whole instruction, and nothing but the // instruction, as a predicted branch. This goes wrong when we execute the @@ -146,7 +151,11 @@ always @ (posedge clk or negedge rst_n) begin if (!rst_n) begin pc <= RESET_VECTOR; end else begin - if ((f_jump_now && !assert_cir_lock) || (cir_lock_prev && deassert_cir_lock)) begin + if (debug_dpc_wen) begin + pc <= debug_dpc_wdata; + end else if (debug_mode) begin + pc <= pc; + end else if ((f_jump_now && !assert_cir_lock) || (cir_lock_prev && deassert_cir_lock)) begin pc <= f_jump_target; end else if (!d_stall && !cir_lock) begin // If this instruction is a predicted-taken branch (and has not