First pass at U-mode CSR support. Bizarrely causes CXXRTL tb to not write to stdout when invoked by subprocess.run from Python.

This commit is contained in:
Luke Wren 2022-05-24 16:06:28 +01:00
parent 4ba3f7ceb9
commit d62861159f
4 changed files with 260 additions and 158 deletions

View File

@ -77,12 +77,15 @@ parameter CSR_M_TRAP = 1,
// CSR_COUNTER: Include performance counters and relevant M-mode CSRs // CSR_COUNTER: Include performance counters and relevant M-mode CSRs
parameter CSR_COUNTER = 1, parameter CSR_COUNTER = 1,
// U_MODE: support for the U (user, unprivileged) execution mode. If U_MODE is // U_MODE: Support the U (user) execution mode. In U mode, the core performs
// 1, PMP support is recommended. // unprivileged bus accesses, and software's access to CSRs is restricted.
// Additionally, if the PMP is included, the core may restrict U-mode
// software's access to memory.
// Requires: CSR_M_TRAP.
parameter U_MODE = 0, parameter U_MODE = 0,
// PMP_REGIONS: Number of physical memory protection regions, or 0 for no PMP. // PMP_REGIONS: Number of physical memory protection regions, or 0 for no PMP.
// PMP is more useful if U mode is supported, but has use on M-only systems. // PMP is more useful if U mode is supported, but this is not a requirement.
parameter PMP_REGIONS = 0, parameter PMP_REGIONS = 0,
// DEBUG_SUPPORT: Support for run/halt and instruction injection from an // DEBUG_SUPPORT: Support for run/halt and instruction injection from an

View File

@ -118,7 +118,6 @@ begin
end end
endfunction endfunction
wire enter_debug_mode; wire enter_debug_mode;
wire exit_debug_mode; wire exit_debug_mode;
@ -130,30 +129,57 @@ always @ (posedge clk or negedge rst_n) begin
end end
end end
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Trap-handling CSRs // Trap-handling CSRs
wire debug_suppresses_trap_update = DEBUG_SUPPORT && (debug_mode || enter_debug_mode); wire debug_suppresses_trap_update = DEBUG_SUPPORT && (debug_mode || enter_debug_mode);
// Two-level interrupt enable stack, shuffled on entry/exit: // Two-level interrupt enable stack, shuffled on entry/exit:
reg m_mode;
reg mstatus_mpie; reg mstatus_mpie;
reg mstatus_mie; reg mstatus_mie;
reg mstatus_mpp; // only MSB is implemented
reg mstatus_mprv;
wire wen_m_mode = wen && (m_mode || debug_mode);
always @ (posedge clk or negedge rst_n) begin always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
m_mode <= 1'b1;
mstatus_mpie <= 1'b0; mstatus_mpie <= 1'b0;
mstatus_mie <= 1'b0; mstatus_mie <= 1'b0;
mstatus_mpp <= 1'b1;
mstatus_mprv <= 1'b0;
end else if (CSR_M_TRAP) begin end else if (CSR_M_TRAP) begin
if (trap_enter_vld && trap_enter_rdy && !debug_suppresses_trap_update) begin if (trap_enter_vld && trap_enter_rdy && !debug_suppresses_trap_update) begin
if (except == EXCEPT_MRET) begin if (except == EXCEPT_MRET) begin
mstatus_mpie <= 1'b1; mstatus_mpie <= 1'b1;
mstatus_mie <= mstatus_mpie; mstatus_mie <= mstatus_mpie;
if (U_MODE) begin
m_mode <= mstatus_mpp;
end
end else begin end else begin
mstatus_mpie <= mstatus_mie; mstatus_mpie <= mstatus_mie;
mstatus_mie <= 1'b0; mstatus_mie <= 1'b0;
if (U_MODE) begin
m_mode <= 1'b1;
mstatus_mpp <= m_mode;
end
end end
end else if (wen && addr == MSTATUS) begin end else if (wen_m_mode && addr == MSTATUS) begin
{mstatus_mpie, mstatus_mie} <= {wdata_update[7], wdata_update[3]}; mstatus_mpie <= wdata_update[7];
mstatus_mie <= wdata_update[3];
mstatus_mprv <= wdata_update[17];
// Note only the MSB of MPP is implemented. It reads back as 11 or 00.
mstatus_mpp <= wdata_update[12];
end else if (wen && debug_mode && addr == DCSR && U_MODE && DEBUG_SUPPORT) begin
// Debugger can change/observe core state directly through
// dcsr.prv (this doesn't affect debugger operation, as all
// operations have an effective level of M-mode whilst the core
// is halted for debug.)
m_mode <= wdata_update[1];
end end
end end
end end
@ -164,7 +190,7 @@ always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
mscratch <= X0; mscratch <= X0;
end else if (CSR_M_TRAP) begin end else if (CSR_M_TRAP) begin
if (wen && addr == MSCRATCH) if (wen_m_mode && addr == MSCRATCH)
mscratch <= wdata_update; mscratch <= wdata_update;
end end
end end
@ -178,7 +204,7 @@ always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
mtvec_reg <= MTVEC_INIT; mtvec_reg <= MTVEC_INIT;
end else if (CSR_M_TRAP) begin end else if (CSR_M_TRAP) begin
if (wen && addr == MTVEC) if (wen_m_mode && addr == MTVEC)
mtvec_reg <= update_nonconst(mtvec_reg, MTVEC_WMASK); mtvec_reg <= update_nonconst(mtvec_reg, MTVEC_WMASK);
end end
end end
@ -194,7 +220,7 @@ always @ (posedge clk or negedge rst_n) begin
end else if (CSR_M_TRAP) begin end else if (CSR_M_TRAP) begin
if (trap_enter_vld && trap_enter_rdy && except != EXCEPT_MRET && !debug_suppresses_trap_update) begin if (trap_enter_vld && trap_enter_rdy && except != EXCEPT_MRET && !debug_suppresses_trap_update) begin
mepc <= mepc_in & MEPC_MASK; mepc <= mepc_in & MEPC_MASK;
end else if (wen && addr == MEPC) begin end else if (wen_m_mode && addr == MEPC) begin
mepc <= wdata_update & MEPC_MASK; mepc <= wdata_update & MEPC_MASK;
end end
end end
@ -208,7 +234,7 @@ always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
mie <= X0; mie <= X0;
end else if (CSR_M_TRAP) begin end else if (CSR_M_TRAP) begin
if (wen && addr == MIE) if (wen_m_mode && addr == MIE)
mie <= update_nonconst(mie, MIE_WMASK); mie <= update_nonconst(mie, MIE_WMASK);
end end
end end
@ -236,7 +262,7 @@ always @ (posedge clk or negedge rst_n) begin
if (trap_enter_vld && trap_enter_rdy && except != EXCEPT_MRET && !debug_suppresses_trap_update) begin if (trap_enter_vld && trap_enter_rdy && except != EXCEPT_MRET && !debug_suppresses_trap_update) begin
mcause_irq <= mcause_irq_next; mcause_irq <= mcause_irq_next;
mcause_code <= mcause_code_next; mcause_code <= mcause_code_next;
end else if (wen && addr == MCAUSE) begin end else if (wen_m_mode && addr == MCAUSE) begin
{mcause_irq, mcause_code} <= {wdata_update[31], wdata_update[5:0]}; {mcause_irq, mcause_code} <= {wdata_update[31], wdata_update[5:0]};
end end
end end
@ -266,13 +292,13 @@ always @ (posedge clk or negedge rst_n) begin
meie1 <= X0; meie1 <= X0;
meie2 <= X0; meie2 <= X0;
meie3 <= X0; meie3 <= X0;
end else if (wen && addr == MEIE0) begin end else if (wen_m_mode && addr == MEIE0) begin
meie0 <= update_nonconst(meie0, MEIE0_WMASK); meie0 <= update_nonconst(meie0, MEIE0_WMASK);
end else if (wen && addr == MEIE1) begin end else if (wen_m_mode && addr == MEIE1) begin
meie1 <= update_nonconst(meie1, MEIE1_WMASK); meie1 <= update_nonconst(meie1, MEIE1_WMASK);
end else if (wen && addr == MEIE2) begin end else if (wen_m_mode && addr == MEIE2) begin
meie2 <= update_nonconst(meie2, MEIE2_WMASK); meie2 <= update_nonconst(meie2, MEIE2_WMASK);
end else if (wen && addr == MEIE3) begin end else if (wen_m_mode && addr == MEIE3) begin
meie3 <= update_nonconst(meie3, MEIE3_WMASK); meie3 <= update_nonconst(meie3, MEIE3_WMASK);
end end
end end
@ -313,7 +339,7 @@ always @ (posedge clk or negedge rst_n) begin
if (!(mcountinhibit_ir || debug_mode) && instr_ret) if (!(mcountinhibit_ir || debug_mode) && instr_ret)
{minstreth, minstret} <= (({minstreth, minstret} + 1'b1) & ~({2*XLEN{1'b1}} << W_COUNTER)) {minstreth, minstret} <= (({minstreth, minstret} + 1'b1) & ~({2*XLEN{1'b1}} << W_COUNTER))
| ({minstreth, minstret} & ({2*XLEN{1'b1}} << W_COUNTER)); | ({minstreth, minstret} & ({2*XLEN{1'b1}} << W_COUNTER));
if (wen) begin if (wen_m_mode) begin
if (addr == MCYCLEH) if (addr == MCYCLEH)
mcycleh <= wdata_update; mcycleh <= wdata_update;
if (addr == MCYCLE) if (addr == MCYCLE)
@ -329,6 +355,27 @@ always @ (posedge clk or negedge rst_n) begin
end end
end end
// Note we still implement tm, even though the time/timeh CSRs are
// unimplemented. The tm bit provides a standard way to configure whether
// M-mode software permits the trapped access to reach the timer registers.
// (This is in fact required by the RVM-CSI platform spec.)
reg mcounteren_cy;
reg mcounteren_tm;
reg mcounteren_ir;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
mcounteren_cy <= 1'b0;
mcounteren_tm <= 1'b0;
mcounteren_ir <= 1'b0;
end else if (CSR_COUNTER && U_MODE && wen_m_mode && addr == MCOUNTEREN) begin
// Note this register only exists when U mode is implemented.
mcounteren_cy <= wdata_update[0];
mcounteren_tm <= wdata_update[1];
mcounteren_ir <= wdata_update[2];
end
end
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Debug-mode CSRs // Debug-mode CSRs
@ -387,6 +434,14 @@ assign dbg_data0_wen = debug_mode && wen && addr == DMDATA0;
reg decode_match; reg decode_match;
// Address match conditions -- certain CSRs are inaccessible if their
// conditions are not met:
wire match_drw = DEBUG_SUPPORT && debug_mode;
wire match_mrw = m_mode || debug_mode;
wire match_mro = (m_mode || debug_mode) && !wen_soon;
wire match_urw = U_MODE && 1'b1;
wire match_uro = U_MODE && !wen_soon;
always @ (*) begin always @ (*) begin
decode_match = 1'b0; decode_match = 1'b0;
rdata = {XLEN{1'b0}}; rdata = {XLEN{1'b0}};
@ -397,7 +452,7 @@ always @ (*) begin
MISA: if (CSR_M_MANDATORY) begin MISA: if (CSR_M_MANDATORY) begin
// WARL, so it is legal to be tied constant // WARL, so it is legal to be tied constant
decode_match = 1'b1; decode_match = match_mrw;
rdata = { rdata = {
2'h1, // MXL: 32-bit 2'h1, // MXL: 32-bit
{XLEN-28{1'b0}}, // WLRL {XLEN-28{1'b0}}, // WLRL
@ -415,47 +470,47 @@ always @ (*) begin
}; };
end end
MVENDORID: if (CSR_M_MANDATORY) begin MVENDORID: if (CSR_M_MANDATORY) begin
decode_match = !wen_soon; // MRO decode_match = match_mro;
rdata = MVENDORID_VAL; rdata = MVENDORID_VAL;
end end
MARCHID: if (CSR_M_MANDATORY) begin MARCHID: if (CSR_M_MANDATORY) begin
decode_match = !wen_soon; // MRO decode_match = match_mro;
// Hazard3's open source architecture ID // Hazard3's open source architecture ID
rdata = 32'd27; rdata = 32'd27;
end end
MIMPID: if (CSR_M_MANDATORY) begin MIMPID: if (CSR_M_MANDATORY) begin
decode_match = !wen_soon; // MRO decode_match = match_mro;
rdata = MIMPID_VAL; rdata = MIMPID_VAL;
end end
MHARTID: if (CSR_M_MANDATORY) begin MHARTID: if (CSR_M_MANDATORY) begin
decode_match = !wen_soon; // MRO decode_match = match_mro;
rdata = MHARTID_VAL; rdata = MHARTID_VAL;
end end
MCONFIGPTR: if (CSR_M_MANDATORY) begin MCONFIGPTR: if (CSR_M_MANDATORY) begin
decode_match = !wen_soon; // MRO decode_match = match_mro;
rdata = MCONFIGPTR_VAL; rdata = MCONFIGPTR_VAL;
end end
MSTATUS: if (CSR_M_MANDATORY || CSR_M_TRAP) begin MSTATUS: if (CSR_M_MANDATORY || CSR_M_TRAP) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = { rdata = {
1'b0, // Never any dirty state besides GPRs 1'b0, // Never any dirty state besides GPRs
8'd0, // (WPRI) 8'd0, // (WPRI)
1'b0, // TSR (Trap SRET), tied 0 if no S mode. 1'b0, // TSR (Trap SRET), tied 0 if no S mode.
1'b0, // TW (Timeout Wait), tied 0 if only M mode. 1'b0, // TW (Timeout Wait), tied 0 if only M mode.
1'b0, // TVM (trap virtual memory), tied 0 if no S mode. 1'b0, // TVM (trap virtual memory), tied 0 if no S mode.
1'b0, // MXR (Make eXecutable Readable), tied 0 if not S mode. 1'b0, // MXR (Make eXecutable Readable), tied 0 if not S mode.
1'b0, // SUM, tied 0, we have no S or U mode 1'b0, // SUM, tied 0, we have no S or U mode
1'b0, // MPRV (modify privilege), tied 0 if no U mode mstatus_mprv, // MPRV (modify privilege)
4'd0, // XS, FS always "off" (no extension state to clear!) 4'd0, // XS, FS always "off" (no extension state to clear!)
2'b11, // MPP (M-mode previous privilege), we are always M-mode {2{m_mode}}, // MPP (M-mode previous privilege), only M and U supported
2'd0, // (WPRI) 2'd0, // (WPRI)
1'b0, // SPP, tied 0 if S mode not supported 1'b0, // SPP, tied 0 if S mode not supported
mstatus_mpie, mstatus_mpie, // Previous interrupt enable
3'd0, // No S, U 3'd0, // No S, U
mstatus_mie, mstatus_mie, // Interrupt enable
3'd0 // No S, U 3'd0 // No S, U
}; };
end end
@ -464,7 +519,7 @@ always @ (*) begin
// unimplemented in this case, but now it must be decoded even if // unimplemented in this case, but now it must be decoded even if
// hardwired to 0. // hardwired to 0.
MSTATUSH: if (CSR_M_MANDATORY || CSR_M_TRAP) begin MSTATUSH: if (CSR_M_MANDATORY || CSR_M_TRAP) begin
decode_match = 1'b1; decode_match = match_mrw;
end end
// MEDELEG, MIDELEG should not exist for M-only implementations. Will raise // MEDELEG, MIDELEG should not exist for M-only implementations. Will raise
@ -476,17 +531,17 @@ always @ (*) begin
// This is a 32 bit synthesised register with set/clear/write/read, don't // This is a 32 bit synthesised register with set/clear/write/read, don't
// turn it on unless we really have to // turn it on unless we really have to
MSCRATCH: if (CSR_M_TRAP && CSR_M_MANDATORY) begin MSCRATCH: if (CSR_M_TRAP && CSR_M_MANDATORY) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = mscratch; rdata = mscratch;
end end
MEPC: if (CSR_M_TRAP) begin MEPC: if (CSR_M_TRAP) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = mepc; rdata = mepc;
end end
MCAUSE: if (CSR_M_TRAP) begin MCAUSE: if (CSR_M_TRAP) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = { rdata = {
mcause_irq, // Sign bit is 1 for IRQ, 0 for exception mcause_irq, // Sign bit is 1 for IRQ, 0 for exception
{26{1'b0}}, // Padding {26{1'b0}}, // Padding
@ -495,23 +550,23 @@ always @ (*) begin
end end
MTVAL: if (CSR_M_TRAP) begin MTVAL: if (CSR_M_TRAP) begin
decode_match = 1'b1; decode_match = match_mrw;
// Hardwired to 0 // Hardwired to 0
end end
MIE: if (CSR_M_TRAP) begin MIE: if (CSR_M_TRAP) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = mie; rdata = mie;
end end
MIP: if (CSR_M_TRAP) begin MIP: if (CSR_M_TRAP) begin
// Writes are permitted, but ignored. // Writes are permitted, but ignored.
decode_match = 1'b1; decode_match = match_mrw;
rdata = mip; rdata = mip;
end end
MTVEC: if (CSR_M_TRAP) begin MTVEC: if (CSR_M_TRAP) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = { rdata = {
mtvec[XLEN-1:2], // BASE mtvec[XLEN-1:2], // BASE
1'b0, // Reserved mode bit gets WARL'd to 0 1'b0, // Reserved mode bit gets WARL'd to 0
@ -523,98 +578,98 @@ always @ (*) begin
// Counter CSRs // Counter CSRs
// Get the tied WARLs out the way first // Get the tied WARLs out the way first
MHPMCOUNTER3: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER3: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER4: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER4: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER5: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER5: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER6: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER6: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER7: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER7: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER8: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER8: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER9: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER9: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER10: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER10: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER11: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER11: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER12: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER12: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER13: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER13: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER14: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER14: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER15: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER15: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER16: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER16: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER17: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER17: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER18: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER18: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER19: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER19: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER20: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER20: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER21: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER21: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER22: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER22: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER23: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER23: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER24: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER24: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER25: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER25: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER26: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER26: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER27: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER27: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER28: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER28: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER29: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER29: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER30: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER30: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER31: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER31: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER3H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER3H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER4H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER4H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER5H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER5H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER6H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER6H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER7H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER7H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER8H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER8H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER9H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER9H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER10H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER10H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER11H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER11H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER12H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER12H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER13H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER13H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER14H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER14H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER15H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER15H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER16H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER16H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER17H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER17H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER18H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER18H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER19H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER19H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER20H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER20H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER21H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER21H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER22H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER22H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER23H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER23H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER24H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER24H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER25H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER25H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER26H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER26H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER27H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER27H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER28H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER28H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER29H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER29H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER30H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER30H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMCOUNTER31H: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMCOUNTER31H: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT3: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT3: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT4: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT4: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT5: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT5: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT6: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT6: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT7: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT7: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT8: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT8: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT9: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT9: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT10: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT10: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT11: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT11: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT12: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT12: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT13: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT13: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT14: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT14: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT15: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT15: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT16: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT16: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT17: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT17: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT18: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT18: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT19: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT19: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT20: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT20: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT21: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT21: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT22: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT22: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT23: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT23: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT24: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT24: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT25: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT25: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT26: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT26: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT27: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT27: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT28: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT28: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT29: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT29: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT30: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT30: if (CSR_COUNTER) begin decode_match = match_mrw; end
MHPMEVENT31: if (CSR_COUNTER) begin decode_match = 1'b1; end MHPMEVENT31: if (CSR_COUNTER) begin decode_match = match_mrw; end
MCOUNTINHIBIT: if (CSR_COUNTER) begin MCOUNTINHIBIT: if (CSR_COUNTER) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = { rdata = {
29'd0, 29'd0,
mcountinhibit_ir, mcountinhibit_ir,
@ -624,23 +679,56 @@ always @ (*) begin
end end
MCYCLE: if (CSR_COUNTER) begin MCYCLE: if (CSR_COUNTER) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = mcycle; rdata = mcycle;
end end
MINSTRET: if (CSR_COUNTER) begin MINSTRET: if (CSR_COUNTER) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = minstret; rdata = minstret;
end end
MCYCLEH: if (CSR_COUNTER) begin MCYCLEH: if (CSR_COUNTER) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = mcycleh; rdata = mcycleh;
end end
MINSTRETH: if (CSR_COUNTER) begin MINSTRETH: if (CSR_COUNTER) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = minstreth; rdata = minstreth;
end end
MCOUNTEREN: if (CSR_COUNTER && U_MODE) begin
decode_match = match_mrw;
rdata = {
29'd0,
mcounteren_ir,
mcounteren_tm,
mcounteren_cy
};
end
// ------------------------------------------------------------------------
// U-mode CSRs
// The read-only counters are always visible to M mode, and are visible to
// U mode if the corresponding mcounteren bit is set.
CYCLE: if (CSR_COUNTER) begin
decode_match = mcounteren_cy ? match_uro : match_mro;
rdata = mcycle;
end
CYCLEH: if (CSR_COUNTER && U_MODE) begin
decode_match = mcounteren_cy ? match_uro : match_mro;
rdata = mcycleh;
end
INSTRET: if (CSR_COUNTER) begin
decode_match = mcounteren_ir ? match_uro : match_mro;
rdata = minstret;
end
INSTRETH: if (CSR_COUNTER) begin
decode_match = mcounteren_ir ? match_uro : match_mro;
rdata = minstreth;
end
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Trigger Module CSRs // Trigger Module CSRs
@ -649,14 +737,14 @@ always @ (*) begin
// - tselect must raise an exception when written to // - tselect must raise an exception when written to
// Otherwise it returns an error instead of 0 count when enumerating triggers // Otherwise it returns an error instead of 0 count when enumerating triggers
TSELECT: if (DEBUG_SUPPORT) begin TSELECT: if (DEBUG_SUPPORT) begin
decode_match = !wen_soon; decode_match = match_mro;
end end
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Debug CSRs // Debug CSRs
DCSR: if (DEBUG_SUPPORT && debug_mode) begin DCSR: if (DEBUG_SUPPORT) begin
decode_match = 1'b1; decode_match = match_drw;
rdata = { rdata = {
4'h4, // xdebugver = 4, for 0.13.2 debug spec 4'h4, // xdebugver = 4, for 0.13.2 debug spec
12'd0, // reserved 12'd0, // reserved
@ -667,20 +755,20 @@ always @ (*) begin
1'b1, // stoptime = 0, no core-local timer increment in debug mode 1'b1, // stoptime = 0, no core-local timer increment in debug mode
dcsr_cause, dcsr_cause,
1'b0, // reserved 1'b0, // reserved
1'b0, // mprven = 0, we don't have MPRV support 1'b0, // mprven = 0, debugger always acts as M-mode
1'b0, // nmip = 0, we have no NMI 1'b0, // nmip = 0, we have no NMI
dcsr_step, dcsr_step,
2'h3 // prv = 3, we only have M mode {2{m_mode}} // priv = M or U, report the core state directly
}; };
end end
DPC: if (DEBUG_SUPPORT && debug_mode) begin DPC: if (DEBUG_SUPPORT) begin
decode_match = 1'b1; decode_match = match_drw;
rdata = dpc; rdata = dpc;
end end
DMDATA0: if (DEBUG_SUPPORT && debug_mode) begin DMDATA0: if (DEBUG_SUPPORT) begin
decode_match = 1'b1; decode_match = match_drw;
rdata = dbg_data0_rdata; rdata = dbg_data0_rdata;
end end
@ -688,47 +776,47 @@ always @ (*) begin
// Custom CSRs // Custom CSRs
MEIE0: if (CSR_M_TRAP && N_IRQ_REG0 > 0) begin MEIE0: if (CSR_M_TRAP && N_IRQ_REG0 > 0) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = meie0; rdata = meie0;
end end
MEIE1: if (CSR_M_TRAP && N_IRQ_REG1 > 0) begin MEIE1: if (CSR_M_TRAP && N_IRQ_REG1 > 0) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = meie1; rdata = meie1;
end end
MEIE2: if (CSR_M_TRAP && N_IRQ_REG2 > 0) begin MEIE2: if (CSR_M_TRAP && N_IRQ_REG2 > 0) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = meie2; rdata = meie2;
end end
MEIE3: if (CSR_M_TRAP && N_IRQ_REG3 > 0) begin MEIE3: if (CSR_M_TRAP && N_IRQ_REG3 > 0) begin
decode_match = 1'b1; decode_match = match_mrw;
rdata = meie3; rdata = meie3;
end end
MEIP0: if (CSR_M_TRAP && N_IRQ_REG0 > 0) begin MEIP0: if (CSR_M_TRAP && N_IRQ_REG0 > 0) begin
decode_match = !wen_soon; decode_match = match_mro;
rdata = meip0; rdata = meip0;
end end
MEIP1: if (CSR_M_TRAP && N_IRQ_REG1 > 0) begin MEIP1: if (CSR_M_TRAP && N_IRQ_REG1 > 0) begin
decode_match = !wen_soon; decode_match = match_mro;
rdata = meip1; rdata = meip1;
end end
MEIP2: if (CSR_M_TRAP && N_IRQ_REG2 > 0) begin MEIP2: if (CSR_M_TRAP && N_IRQ_REG2 > 0) begin
decode_match = !wen_soon; decode_match = match_mro;
rdata = meip2; rdata = meip2;
end end
MEIP3: if (CSR_M_TRAP && N_IRQ_REG3 > 0) begin MEIP3: if (CSR_M_TRAP && N_IRQ_REG3 > 0) begin
decode_match = !wen_soon; decode_match = match_mro;
rdata = meip3; rdata = meip3;
end end
MLEI: if (CSR_M_TRAP) begin MLEI: if (CSR_M_TRAP) begin
decode_match = !wen_soon; decode_match = match_mro;
rdata = {{XLEN-9{1'b0}}, mlei, 2'b00}; rdata = {{XLEN-9{1'b0}}, mlei, 2'b00};
end end

View File

@ -161,6 +161,17 @@ localparam MEIP2 = 12'hfe2; // External interrupt pending register 2
localparam MEIP3 = 12'hfe3; // External interrupt pending register 3 localparam MEIP3 = 12'hfe3; // External interrupt pending register 3
localparam MLEI = 12'hfe4; // Lowest external interrupt number localparam MLEI = 12'hfe4; // Lowest external interrupt number
// ----------------------------------------------------------------------------
// U-mode CSRs
// Read-only aliases of M-mode counter CSRs:
localparam CYCLE = 12'hc00;
localparam TIME = 12'hc01;
localparam INSTRET = 12'hc02;
localparam CYCLEH = 12'hc80;
localparam TIMEH = 12'hc81;
localparam INSTRETH = 12'hc82;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Trigger Module // Trigger Module

View File

@ -218,7 +218,7 @@ always @ (*) begin: check_i_match
i_partial_match = 1'b0; i_partial_match = 1'b0;
i_l = 1'b0; i_l = 1'b0;
i_x = 1'b0; i_x = 1'b0;
for (i = PMP_REGIONS - 1; i >= 0; i = i - 1) begin for (i = PMP_REGIONS - 1; i >= 0; i = i -q 1) begin
match_hw0 = |pmpcfg_a[i] && (i_addr & match_mask[i]) == match_addr[i]; match_hw0 = |pmpcfg_a[i] && (i_addr & match_mask[i]) == match_addr[i];
match_hw1 = |pmpcfg_a[i] && (i_addr_hw1 & match_mask[i]) == match_addr[i]; match_hw1 = |pmpcfg_a[i] && (i_addr_hw1 & match_mask[i]) == match_addr[i];
if (match_hw0 || match_hw1) begin if (match_hw0 || match_hw1) begin