mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			153 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| ///////////////////////////////////////////
 | |
| // WALLY-init-lib.h
 | |
| //
 | |
| // Written: David_Harris@hmc.edu 21 March 2023
 | |
| //
 | |
| // Purpose: Initialize stack, handle interrupts, terminate test case
 | |
| //
 | |
| // A component of the CORE-V-WALLY configurable RISC-V project.
 | |
| // https://github.com/openhwgroup/cvw
 | |
| // 
 | |
| // Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
 | |
| //
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
 | |
| //
 | |
| // Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file 
 | |
| // except in compliance with the License, or, at your option, the Apache License version 2.0. You 
 | |
| // may obtain a copy of the License at
 | |
| //
 | |
| // https://solderpad.org/licenses/SHL-2.1/
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, any work distributed under the 
 | |
| // License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
 | |
| // either express or implied. See the License for the specific language governing permissions 
 | |
| // and limitations under the License.
 | |
| ////////////////////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| // load code to initalize stack, handle interrupts, terminate
 | |
| // The PMP tests are sensitive to the exact addresses in this code, so unfortunately
 | |
| // modifying anything breaks those tests.
 | |
| 
 | |
| .section .text.init
 | |
| .global rvtest_entry_point
 | |
| 
 | |
| rvtest_entry_point:
 | |
|     la sp, topofstack       # Initialize stack pointer (not used)
 | |
| 
 | |
|     # Set up interrupts
 | |
|     la t0, trap_handler
 | |
|     csrw mtvec, t0      # Initialize MTVEC to trap_handler
 | |
|     csrw mideleg, zero  # Don't delegate interrupts
 | |
|     csrw medeleg, zero  # Don't delegate exceptions
 | |
| #    li t0, -1           # set mtimecmp to biggest number so it doesnt interrupt again
 | |
| #    li t1, 0x02004000   # MTIMECMP in CLINT
 | |
| #    sd t0, 0(t1)      
 | |
|     li t0, 0x80         
 | |
| #    li t0, 0x00         
 | |
|     csrw mie, t0        # Enable machine timer interrupt
 | |
|     la t0, topoftrapstack 
 | |
|     csrw mscratch, t0   # MSCRATCH holds trap stack pointer
 | |
|     csrsi mstatus, 0x8  # Turn on mstatus.MIE global interrupt enable
 | |
|     # set up PMP so user and supervisor mode can access full address space
 | |
|     csrw pmpcfg0, 0xF   # configure PMP0 to TOR RWX
 | |
|     li t0, 0xFFFFFFFF   
 | |
|     csrw pmpaddr0, t0   # configure PMP0 top of range to 0xFFFFFFFF to allow all 32-bit addresses
 | |
|     j main              # Call main function in user test program
 | |
| 
 | |
| done:
 | |
|     li a0, 4            # argument to finish program    
 | |
|     ecall               # system call to finish program
 | |
|     j self_loop         # wait forever (not taken)
 | |
| 
 | |
| .align 4                # trap handlers must be aligned to multiple of 4
 | |
| trap_handler:
 | |
|     # Load trap handler stack pointer tp
 | |
|     csrrw tp, mscratch, tp  # swap MSCRATCH and tp
 | |
|     sd t0, 0(tp)        # Save t0 and t1 on the stack
 | |
|     sd t1, -8(tp)
 | |
|     csrr t0, mcause     # Check the cause
 | |
|     csrr t1, mtval      # And the trap value
 | |
|     bgez t0, exception  # if msb is clear, it is an exception
 | |
| 
 | |
| interrupt:              # must be a timer interrupt 
 | |
|     li t0, -1           # set mtimecmp to biggest number so it doesnt interrupt again
 | |
|     li t1, 0x02004000   # MTIMECMP in CLIN
 | |
|     sd t0, 0(t1)      
 | |
|     csrw stimecmp, t0   # sets stimecmp to big number so it doesnt interrupt 
 | |
|     li t0, 32
 | |
|     csrc sip, t0        # clears stimer interrupt
 | |
|     j trap_return       # clean up and return
 | |
| 
 | |
| exception:
 | |
|     csrr t0, mcause
 | |
|     li t1, 8            # is it an ecall trap?
 | |
|     andi t0, t0, 0xFC # if CAUSE = 8, 9, or 11
 | |
|     bne t0, t1, trap_return # ignore other exceptions
 | |
| 
 | |
| ecall:
 | |
|     li t0, 4
 | |
|     beq a0, t0, write_tohost    # call 4: terminate program
 | |
|     bltu a0, t0, changeprivilege    # calls 0-3: change privilege level
 | |
|     j trap_return       # ignore other ecalls
 | |
| 
 | |
| changeprivilege:
 | |
|     li t0, 0x00001800   # mask off mstatus.MPP in bits 11-12
 | |
|     csrc mstatus, t0
 | |
|     andi a0, a0, 0x003  # only keep bottom two bits of argument
 | |
|     slli a0, a0, 11     # move into mstatus.MPP position
 | |
|     csrs mstatus, a0    # set mstatus.MPP with desired privilege
 | |
| 
 | |
| trap_return:            # return from trap handler
 | |
|     csrr t0, mepc  # get address of instruction that caused exception
 | |
|     li t1, 0x20000  
 | |
|     csrs mstatus, t1    # set mprv bit to fetch instruction with permission of code that trapped
 | |
|     lh t0, 0(t0)   # get instruction that caused exception
 | |
|     csrc mstatus, t1    # clear mprv bit to restore normal operation
 | |
|     li t1, 3
 | |
|     and t0, t0, t1  # mask off upper bits
 | |
|     beq t0, t1, instr32  # if lower 2 bits are 11, instruction is uncompresssed
 | |
|     li t0, 2        # increment PC by 2 for compressed instruction
 | |
|     j updateepc
 | |
| instr32:
 | |
|     li t0, 4
 | |
| updateepc:
 | |
|     csrr t1, mepc   # add 2 or 4 (from t0) to MEPC to determine return Address
 | |
|     add t1, t1, t0
 | |
|     csrw mepc, t1
 | |
| 
 | |
|     ld t1, -8(tp)       # restore t1 and t0
 | |
|     ld t0, 0(tp)
 | |
|     csrrw tp, mscratch, tp  # restore tp
 | |
|     mret                # return from trap
 | |
| 
 | |
| write_tohost:
 | |
|     la t1, tohost
 | |
|     li t0, 1            # 1 for success, 3 for failure
 | |
|     sd t0, 0(t1)        # send success code
 | |
| 
 | |
| self_loop:
 | |
|     j self_loop         # wait
 | |
|     
 | |
| .section .tohost 
 | |
| tohost:                 # write to HTIF
 | |
|     .dword 0
 | |
| fromhost:
 | |
|     .dword 0
 | |
| 
 | |
| .EQU XLEN,64
 | |
| begin_signature:
 | |
|     .fill 6*(XLEN/32),4,0xdeadbeef    # 
 | |
| end_signature:
 | |
| 
 | |
| # Initialize stack with room for 512 bytes
 | |
| .bss
 | |
|     .space 512
 | |
| topofstack:
 | |
| # And another stack for the trap handler
 | |
| .bss   
 | |
|     .space 512
 | |
| topoftrapstack:
 | |
| 
 | |
| .align 4
 | |
| .section .text.main
 |