diff --git a/hdl/hazard3_config.vh b/hdl/hazard3_config.vh index fdb24eb..8fd466f 100644 --- a/hdl/hazard3_config.vh +++ b/hdl/hazard3_config.vh @@ -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) diff --git a/hdl/hazard3_csr.v b/hdl/hazard3_csr.v index 3666b88..7f9d886 100644 --- a/hdl/hazard3_csr.v +++ b/hdl/hazard3_csr.v @@ -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 diff --git a/test/sim/common/init.S b/test/sim/common/init.S index ce0b799..c93d3c6 100644 --- a/test/sim/common/init.S +++ b/test/sim/common/init.S @@ -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