This commit is contained in:
mmasserfrye 2022-05-12 07:24:04 +00:00
commit cf900cf44d
8 changed files with 173 additions and 9 deletions

View File

@ -9,7 +9,7 @@ use warnings;
import os; import os;
if ($#ARGV != 0) { if ($#ARGV != 0) {
die("Usage: $0 workpath [e.g. $0 $WALLY/addins/riscv-arch-test/work") die("Usage: $0 workpath [e.g. $0 \$WALLY/addins/riscv-arch-test/work")
} }
my $mypath = $ARGV[0]; my $mypath = $ARGV[0];
my @dirs = glob($mypath.'/*/*'); my @dirs = glob($mypath.'/*/*');

View File

@ -0,0 +1,19 @@
TARGET = trap
$(TARGET).objdump: $(TARGET)
riscv64-unknown-elf-objdump -D $(TARGET) > $(TARGET).objdump
$(TARGET): $(TARGET).S Makefile
riscv64-unknown-elf-gcc -g -o $(TARGET) -march=rv64gc -mabi=lp64 -mcmodel=medany \
-nostartfiles -T../../link/link.ld $(TARGET).S
sim:
spike +signature=$(TARGET).signature.output +signature-granularity=8 $(TARGET)
diff --ignore-case $(TARGET).signature.output $(TARGET).reference_output || exit
echo "Signature matches! Success!"
clean:
rm -f $(TARGET) $(TARGET).objdump $(TARGET).signature.output

BIN
examples/asm/trap/trap Executable file

Binary file not shown.

131
examples/asm/trap/trap.S Normal file
View File

@ -0,0 +1,131 @@
// trap.S
// David_Harris@hmc.edu 11 May 2022
//
// Demonstrates setting up traps and invoking a trap handler.
// The trap handler accepts timer interrupts and ecalls.
// Saves cause and mtval into the signature
// Ecall takes one argument in a0
// 0: change privilege mode to user
// 1: change privilege mode to supervisor
// 3: change privilege mode to machine
// 4: exit program with write tohost
.EQU MTIME, 0x200bff8
.EQU MTIMECMP, 0x2004000
.global rvtest_entry_point
rvtest_entry_point:
la sp, topofstack # Initialize stack pointer (not used)
la s6, begin_signature # s6 points to signature
# Set up timer
jal set_timecmp
# 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, 0x080
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
main:
# Change to user mode
li a0, 0 # a0 = 0: argument to enter user mode
ecall # System call to enter user mode
# Wait for timer interrupts
li t0, 0x1000 # loop counter start value
loop:
addi t0, t0, -1 # decrement counter
bne t0, zero, loop # and repeat until zero
done:
li a0, 4 # argument to finish program
ecall # system call to finish program
j self_loop # wait forever (not taken)
set_timecmp: # Set timer compare to 800 ticks later
la t0, MTIME
la t1, MTIMECMP
ld t0, 0(t0) # Read current timer
addi t0, t0, 0x60 # Increment timer
sd t0, 0(t1) # Set MTIMECMP = MTIME + 0x800
ret
.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
sd t0, 0(s6) # Save MCAUSE and MTVAL in the signature
sd t1, 8(s6)
addi s6, s6, 16
bgez t0, exception # if msb is clear, it is an exception
interrupt: # must be a timer interrupt
jal set_timecmp # Increment compare for next timer interrupt
j trap_return # clean up and return
exception:
csrr t1, mepc # add 4 to MEPC to determine return Address
addi t1, t1, 4
csrw mepc, t1
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
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:

View File

@ -0,0 +1,6 @@
000000000000000b
0000000000000000
8000000000000007
0000000000000000
0000000000000008
0000000000000000

View File

@ -38,6 +38,7 @@ module csrm #(parameter
MARCHID = 12'hF12, MARCHID = 12'hF12,
MIMPID = 12'hF13, MIMPID = 12'hF13,
MHARTID = 12'hF14, MHARTID = 12'hF14,
MCONFIGPTR = 12'hF15,
MSTATUS = 12'h300, MSTATUS = 12'h300,
MISA_ADR = 12'h301, MISA_ADR = 12'h301,
MEDELEG = 12'h302, MEDELEG = 12'h302,
@ -186,6 +187,7 @@ module csrm #(parameter
MARCHID: CSRMReadValM = 0; MARCHID: CSRMReadValM = 0;
MIMPID: CSRMReadValM = `XLEN'h100; // pipelined implementation MIMPID: CSRMReadValM = `XLEN'h100; // pipelined implementation
MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0 MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0
MCONFIGPTR: CSRReadValM = 0; // hardwired to 0
MSTATUS: CSRMReadValM = MSTATUS_REGW; MSTATUS: CSRMReadValM = MSTATUS_REGW;
MSTATUSH: CSRMReadValM = MSTATUSH_REGW; MSTATUSH: CSRMReadValM = MSTATUSH_REGW;
MTVEC: CSRMReadValM = MTVEC_REGW; MTVEC: CSRMReadValM = MTVEC_REGW;

View File

@ -36,6 +36,9 @@ rv32i_sc_tests = \
WALLY-misa-01 \ WALLY-misa-01 \
WALLY-amo \ WALLY-amo \
WALLY-lrsc \ WALLY-lrsc \
WALLY-status-mie-01 \
WALLY-trap-sret-01 \
target_tests_nosim = \ target_tests_nosim = \
WALLY-pma \ WALLY-pma \
@ -43,15 +46,15 @@ target_tests_nosim = \
WALLY-stvec-01 \ WALLY-stvec-01 \
WALLY-mie-01 \ WALLY-mie-01 \
WALLY-sie-01 \ WALLY-sie-01 \
WALLY-status-mie-01 \
WALLY-status-sie-01 \
WALLY-trap-sret-01 \
WALLY-trap-01 \ WALLY-trap-01 \
WALLY-trap-s-01 \ WALLY-trap-s-01 \
WALLY-trap-u-01 \ WALLY-trap-u-01 \
WALLY-status-tw-01 \
WALLY-wfi-01 \ WALLY-wfi-01 \
WALLY-status-fp-enabled-01 \ WALLY-status-fp-enabled-01 \
WALLY-status-sie-01 \
WALLY-status-tw-01 \
# unclear why wfi, status-fp-enabled, status-sie, and status-tw fail
rv32i_tests = $(addsuffix .elf, $(rv32i_sc_tests)) rv32i_tests = $(addsuffix .elf, $(rv32i_sc_tests))

View File

@ -38,6 +38,10 @@ rv64i_sc_tests = \
WALLY-amo \ WALLY-amo \
WALLY-lrsc \ WALLY-lrsc \
WALLY-trap-sret-01 \ WALLY-trap-sret-01 \
WALLY-status-mie-01 \
WALLY-status-sie-01 \
WALLY-status-tw-01 \
# Don't simulate these because they rely on SoC features that Spike does not offer. # Don't simulate these because they rely on SoC features that Spike does not offer.
target_tests_nosim = \ target_tests_nosim = \
@ -47,14 +51,13 @@ target_tests_nosim = \
WALLY-stvec-01 \ WALLY-stvec-01 \
WALLY-mie-01 \ WALLY-mie-01 \
WALLY-sie-01 \ WALLY-sie-01 \
WALLY-status-mie-01 \
WALLY-status-sie-01 \
WALLY-trap-01 \ WALLY-trap-01 \
WALLY-trap-s-01 \ WALLY-trap-s-01 \
WALLY-trap-u-01 \ WALLY-trap-u-01 \
WALLY-status-tw-01 \
WALLY-wfi-01 \
WALLY-status-fp-enabled-01 \ WALLY-status-fp-enabled-01 \
WALLY-wfi-01 \
# unclear why status-fp-enabled and wfi aren't simulating ok
rv64i_tests = $(addsuffix .elf, $(rv64i_sc_tests)) rv64i_tests = $(addsuffix .elf, $(rv64i_sc_tests))