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:
parent
cec5dc4e3b
commit
12851d3742
|
@ -12,8 +12,16 @@ parameter RESET_VECTOR = 32'h0,
|
||||||
|
|
||||||
// MTVEC_INIT: Initial value of trap vector base. Bits clear in MTVEC_WMASK
|
// 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
|
// 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
|
// written/set/cleared as normal.
|
||||||
// should probably have a different value from RESET_VECTOR.
|
//
|
||||||
|
// 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,
|
parameter MTVEC_INIT = 32'h00000000,
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -66,10 +74,13 @@ parameter MULDIV_UNROLL = 1,
|
||||||
parameter MUL_FAST = 0,
|
parameter MUL_FAST = 0,
|
||||||
|
|
||||||
// MTVEC_WMASK: Mask of which bits in MTVEC are modifiable. Save gates by
|
// 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
|
// making trap vector base partly fixed (legal, as it's WARL).
|
||||||
// vector table must always be aligned to its size, rounded up to a power of
|
//
|
||||||
// two, so careful with the low-order bits.
|
// - The vectoring mode can be made fixed by clearing the LSB of MTVEC_WMASK
|
||||||
parameter MTVEC_WMASK = 32'hfffff000,
|
//
|
||||||
|
// - 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)
|
// Port size parameters (do not modify)
|
||||||
|
|
|
@ -273,7 +273,8 @@ end
|
||||||
|
|
||||||
// Trap vector base
|
// Trap vector base
|
||||||
reg [XLEN-1:0] mtvec_reg;
|
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
|
always @ (posedge clk or negedge rst_n) begin
|
||||||
if (!rst_n) begin
|
if (!rst_n) begin
|
||||||
|
@ -524,7 +525,8 @@ always @ (*) begin
|
||||||
decode_match = 1'b1;
|
decode_match = 1'b1;
|
||||||
rdata = {
|
rdata = {
|
||||||
mtvec[XLEN-1:2], // BASE
|
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
|
end
|
||||||
|
|
||||||
|
@ -679,7 +681,7 @@ assign mip = {
|
||||||
3'h0, // Reserved
|
3'h0, // Reserved
|
||||||
1'b0, // Timer (FIXME)
|
1'b0, // Timer (FIXME)
|
||||||
3'h0, // Reserved
|
3'h0, // Reserved
|
||||||
1'b0, // Software interrupt
|
1'b0, // Software interrupt (FIXME)
|
||||||
3'h0 // Reserved
|
3'h0 // Reserved
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -695,9 +697,8 @@ hazard3_priority_encode #(
|
||||||
.gnt (irq_num)
|
.gnt (irq_num)
|
||||||
);
|
);
|
||||||
|
|
||||||
wire [11:0] mtvec_offs = (exception_req_any ?
|
wire [11:0] mtvec_offs = (
|
||||||
{8'h0, except} :
|
exception_req_any || !irq_vector_enable ? 12'h0 : {7'h0, irq_num}
|
||||||
12'h10 + {7'h0, irq_num}
|
|
||||||
) << 2;
|
) << 2;
|
||||||
|
|
||||||
assign trap_addr = except == EXCEPT_MRET ? mepc : mtvec | {20'h0, mtvec_offs};
|
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);
|
&& !(trap_enter_vld && trap_enter_rdy && except == EXCEPT_MRET);
|
||||||
|
|
||||||
always @ (posedge clk) begin
|
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
|
// annoying things like stopping instructions from retiring by repeatedly
|
||||||
// feeding in invalid instructions
|
// feeding in invalid instructions
|
||||||
|
|
||||||
|
|
|
@ -21,35 +21,19 @@ j \name
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Vector table
|
// Vector table (must be at least aligned to its size rounded up to power of 2)
|
||||||
// Hazard5 requires 4k alignment of mtvec
|
|
||||||
|
|
||||||
.p2align 12
|
.p2align 8
|
||||||
.vector_table:
|
.vector_table:
|
||||||
|
|
||||||
// Exceptions
|
// Single exception vector, also takes IRQs if vectoring is disabled
|
||||||
|
|
||||||
VEC handle_instr_misalign
|
VEC handle_exception
|
||||||
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
|
|
||||||
|
|
||||||
// Standard interrupts
|
// Standard interrupts, if vectoring is enabled
|
||||||
// Note: global EIRQ does not fire. Instead we have 16 separate vectors
|
// 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 .halt
|
VEC .halt
|
||||||
VEC isr_machine_softirq
|
VEC isr_machine_softirq
|
||||||
|
@ -66,7 +50,7 @@ j \name
|
||||||
VEC .halt
|
VEC .halt
|
||||||
VEC .halt
|
VEC .halt
|
||||||
|
|
||||||
// External interrupts
|
// External interrupts, if vectoring is enabled
|
||||||
|
|
||||||
VEC isr_irq0
|
VEC isr_irq0
|
||||||
VEC isr_irq1
|
VEC isr_irq1
|
||||||
|
@ -93,6 +77,8 @@ j \name
|
||||||
.reset_handler:
|
.reset_handler:
|
||||||
la sp, __stack_top
|
la sp, __stack_top
|
||||||
la t0, .vector_table
|
la t0, .vector_table
|
||||||
|
// Set mtvec LSB to enable vectoring
|
||||||
|
ori t0, t0, 1
|
||||||
csrw mtvec, t0
|
csrw mtvec, t0
|
||||||
|
|
||||||
// newlib _start expects argc, argv on the stack. Leave stack 16-byte aligned.
|
// newlib _start expects argc, argv on the stack. Leave stack 16-byte aligned.
|
||||||
|
@ -209,15 +195,7 @@ _str_\name:
|
||||||
.asciz "\name"
|
.asciz "\name"
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
weak_handler handle_instr_misalign
|
weak_handler handle_exception
|
||||||
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 isr_machine_softirq
|
weak_handler isr_machine_softirq
|
||||||
weak_handler isr_machine_timer
|
weak_handler isr_machine_timer
|
||||||
weak_handler isr_irq0
|
weak_handler isr_irq0
|
||||||
|
|
Loading…
Reference in New Issue