Bring mtvec vectoring modes in line with spec: all exceptions go to mtvec, IRQs are optionally vectored away from it if mtvec LSB is set

This commit is contained in:
Luke Wren 2021-05-30 19:52:46 +01:00
parent cec5dc4e3b
commit 12851d3742
3 changed files with 35 additions and 45 deletions

View File

@ -12,8 +12,16 @@ parameter RESET_VECTOR = 32'h0,
// MTVEC_INIT: Initial value of trap vector base. Bits clear in MTVEC_WMASK
// will never change from this initial value. Bits set in MTVEC_WMASK can be
// written/set/cleared as normal. Note that, if CSR_M_TRAP is set, MTVEC_INIT
// should probably have a different value from RESET_VECTOR.
// written/set/cleared as normal.
//
// Note that, if CSR_M_TRAP is set, MTVEC_INIT should probably have a
// different value from RESET_VECTOR.
//
// Note that mtvec bits 1:0 do not affect the trap base (as per RISC-V spec).
// Bit 1 is don't care, bit 0 selects the vectoring mode: unvectored if == 0
// (all traps go to mtvec), vectored if == 1 (exceptions go to mtvec, IRQs to
// mtvec + mcause * 4). This means MTVEC_INIT also sets the initial vectoring
// mode.
parameter MTVEC_INIT = 32'h00000000,
// ----------------------------------------------------------------------------
@ -66,10 +74,13 @@ parameter MULDIV_UNROLL = 1,
parameter MUL_FAST = 0,
// MTVEC_WMASK: Mask of which bits in MTVEC are modifiable. Save gates by
// making trap vector base partly fixed (legal, as it's WARL). Note the entire
// vector table must always be aligned to its size, rounded up to a power of
// two, so careful with the low-order bits.
parameter MTVEC_WMASK = 32'hfffff000,
// making trap vector base partly fixed (legal, as it's WARL).
//
// - The vectoring mode can be made fixed by clearing the LSB of MTVEC_WMASK
//
// - Note the entire vector table must always be aligned to its size, rounded
// up to a power of two, so careful with the low-order bits.
parameter MTVEC_WMASK = 32'hffffffff,
// ----------------------------------------------------------------------------
// Port size parameters (do not modify)

View File

@ -273,7 +273,8 @@ end
// Trap vector base
reg [XLEN-1:0] mtvec_reg;
wire [XLEN-1:0] mtvec = (mtvec_reg & MTVEC_WMASK) | (MTVEC_INIT & ~MTVEC_WMASK);
wire [XLEN-1:0] mtvec = ((mtvec_reg & MTVEC_WMASK) | (MTVEC_INIT & ~MTVEC_WMASK)) & ({XLEN{1'b1}} << 2);
wire irq_vector_enable = mtvec_reg[0];
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
@ -524,7 +525,8 @@ always @ (*) begin
decode_match = 1'b1;
rdata = {
mtvec[XLEN-1:2], // BASE
2'h1 // MODE = Vectored (Direct is useless, and we don't have CLIC)
1'b0, // Reserved mode bit gets WARL'd to 0
irq_vector_enable // MODE is vectored (2'h1) or direct (2'h0)
};
end
@ -679,7 +681,7 @@ assign mip = {
3'h0, // Reserved
1'b0, // Timer (FIXME)
3'h0, // Reserved
1'b0, // Software interrupt
1'b0, // Software interrupt (FIXME)
3'h0 // Reserved
};
@ -695,9 +697,8 @@ hazard3_priority_encode #(
.gnt (irq_num)
);
wire [11:0] mtvec_offs = (exception_req_any ?
{8'h0, except} :
12'h10 + {7'h0, irq_num}
wire [11:0] mtvec_offs = (
exception_req_any || !irq_vector_enable ? 12'h0 : {7'h0, irq_num}
) << 2;
assign trap_addr = except == EXCEPT_MRET ? mepc : mtvec | {20'h0, mtvec_offs};
@ -722,7 +723,7 @@ always @ (posedge clk or negedge rst_n)
&& !(trap_enter_vld && trap_enter_rdy && except == EXCEPT_MRET);
always @ (posedge clk) begin
// Assume there are no nested exceptions, to stop risc-formal from doing
// Assume there are no nested exceptions, to stop riscv-formal from doing
// annoying things like stopping instructions from retiring by repeatedly
// feeding in invalid instructions

View File

@ -21,35 +21,19 @@ j \name
.endm
// ----------------------------------------------------------------------------
// Vector table
// Hazard5 requires 4k alignment of mtvec
// Vector table (must be at least aligned to its size rounded up to power of 2)
.p2align 12
.p2align 8
.vector_table:
// Exceptions
// Single exception vector, also takes IRQs if vectoring is disabled
VEC handle_instr_misalign
VEC handle_instr_fault
VEC handle_instr_illegal
VEC handle_breakpoint
VEC handle_load_misalign
VEC handle_load_fault
VEC handle_store_misalign
VEC handle_store_fault
VEC .halt
VEC .halt
VEC .halt
VEC handle_ecall
VEC .halt
VEC .halt
VEC .halt
VEC .halt
VEC handle_exception
// Standard interrupts
// Standard interrupts, if vectoring is enabled
// Note: global EIRQ does not fire. Instead we have 16 separate vectors
VEC .halt
// handle_exception ^^^ takes the slot where U-mode softirq would be
VEC .halt
VEC .halt
VEC isr_machine_softirq
@ -66,7 +50,7 @@ j \name
VEC .halt
VEC .halt
// External interrupts
// External interrupts, if vectoring is enabled
VEC isr_irq0
VEC isr_irq1
@ -93,6 +77,8 @@ j \name
.reset_handler:
la sp, __stack_top
la t0, .vector_table
// Set mtvec LSB to enable vectoring
ori t0, t0, 1
csrw mtvec, t0
// newlib _start expects argc, argv on the stack. Leave stack 16-byte aligned.
@ -209,15 +195,7 @@ _str_\name:
.asciz "\name"
.endm
weak_handler handle_instr_misalign
weak_handler handle_instr_fault
weak_handler handle_instr_illegal
weak_handler handle_breakpoint
weak_handler handle_load_misalign
weak_handler handle_load_fault
weak_handler handle_store_misalign
weak_handler handle_store_fault
weak_handler handle_ecall
weak_handler handle_exception
weak_handler isr_machine_softirq
weak_handler isr_machine_timer
weak_handler isr_irq0