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