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_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.

View File

@ -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.

View File

@ -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