Alias DPC to the real program counter, small savings overall

This commit is contained in:
Luke Wren 2022-10-10 00:28:42 +01:00
parent aa438fc37c
commit f771a1294d
3 changed files with 36 additions and 17 deletions

View File

@ -224,6 +224,10 @@ wire x_jump_not_except;
wire x_mmode_execution; wire x_mmode_execution;
wire x_trap_wfi; 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 #( hazard3_decode #(
`include "hazard3_config_inst.vh" `include "hazard3_config_inst.vh"
) decode_u ( ) decode_u (
@ -243,6 +247,10 @@ hazard3_decode #(
.m_mode (x_mmode_execution), .m_mode (x_mmode_execution),
.trap_wfi (x_trap_wfi), .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), .d_starved (d_starved),
.x_stall (x_stall), .x_stall (x_stall),
.f_jump_now (f_jump_now), .f_jump_now (f_jump_now),
@ -964,6 +972,10 @@ hazard3_csr #(
.dbg_data0_wdata (dbg_data0_wdata), .dbg_data0_wdata (dbg_data0_wdata),
.dbg_data0_wen (dbg_data0_wen), .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 // CSR access port
// *en_soon are early access strobes which are not a function of bus stall. // *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. // Can generate access faults (hence traps), but do not actually perform access.

View File

@ -36,6 +36,10 @@ module hazard3_csr #(
output wire [W_DATA-1:0] dbg_data0_wdata, output wire [W_DATA-1:0] dbg_data0_wdata,
output wire dbg_data0_wen, 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. // Read port is combinatorial.
// Write port is synchronous, and write effects will be observed on the next clock cycle. // 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. // 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
end end
reg [XLEN-1:0] dpc; // 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
always @ (posedge clk or negedge rst_n) begin // Mode we can write to it as though it were a CSR. Note only IALIGN'd values
if (!rst_n) begin // can be written to dpc.
dpc <= X0; assign debug_dpc_wdata = (debug_mode ? wdata_update : mepc_in) & (~X0 << 2 - EXTENSION_C);
end else if (DEBUG_SUPPORT) begin assign debug_dpc_wen = debug_mode ? wen && addr == DPC : enter_debug_mode;
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
// Debug Module's data0 register is mapped into the core's CSR space:
assign dbg_data0_wdata = wdata; assign dbg_data0_wdata = wdata;
assign dbg_data0_wen = debug_mode && wen && addr == DMDATA0; assign dbg_data0_wen = debug_mode && wen && addr == DMDATA0;
@ -1059,7 +1057,7 @@ always @ (*) begin
DPC: if (DEBUG_SUPPORT) begin DPC: if (DEBUG_SUPPORT) begin
decode_match = match_drw; decode_match = match_drw;
rdata = dpc; rdata = debug_dpc_rdata;
end end
DMDATA0: if (DEBUG_SUPPORT) begin DMDATA0: if (DEBUG_SUPPORT) begin
@ -1291,7 +1289,7 @@ wire [3:0] vector_sel = !exception_req_any && irq_vector_enable ? mcause_irq_num
assign trap_addr = assign trap_addr =
except == EXCEPT_MRET ? mepc : except == EXCEPT_MRET ? mepc :
pending_dbg_resume ? dpc : mtvec | {26'h0, vector_sel, 2'h0}; 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 // Check for exception-like or IRQ-like trap entry; any debug mode entry takes
// priority over any regular trap. // priority over any regular trap.

View File

@ -25,6 +25,10 @@ module hazard3_decode #(
input wire m_mode, input wire m_mode,
input wire trap_wfi, 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, output wire d_starved,
input wire x_stall, input wire x_stall,
input wire f_jump_now, input wire f_jump_now,
@ -131,6 +135,7 @@ end
reg [W_ADDR-1:0] pc; reg [W_ADDR-1:0] pc;
wire [W_ADDR-1:0] pc_seq_next = pc + (d_instr_is_32bit ? 32'h4 : 32'h2); wire [W_ADDR-1:0] pc_seq_next = pc + (d_instr_is_32bit ? 32'h4 : 32'h2);
assign d_pc = pc; assign d_pc = pc;
assign debug_dpc_rdata = pc;
// Frontend should mark the whole instruction, and nothing but the // Frontend should mark the whole instruction, and nothing but the
// instruction, as a predicted branch. This goes wrong when we execute 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 if (!rst_n) begin
pc <= RESET_VECTOR; pc <= RESET_VECTOR;
end else begin 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; pc <= f_jump_target;
end else if (!d_stall && !cir_lock) begin end else if (!d_stall && !cir_lock) begin
// If this instruction is a predicted-taken branch (and has not // If this instruction is a predicted-taken branch (and has not