forked from Github_Repos/cvw
137 lines
4.5 KiB
C
137 lines
4.5 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.
|
|
//
|
|
// 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
|
|
|
|
.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, 0x80
|
|
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
|
|
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
|
|
lh t0, 0(t0) # get instruction that caused exception
|
|
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
|