mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of github.com:davidharrishmc/riscv-wally into main
This commit is contained in:
commit
22279a29ab
1
.gitignore
vendored
1
.gitignore
vendored
@ -70,3 +70,4 @@ synthDC/*.svf
|
|||||||
synthDC/runs/
|
synthDC/runs/
|
||||||
synthDC/hdl
|
synthDC/hdl
|
||||||
/pipelined/regression/power.saif
|
/pipelined/regression/power.saif
|
||||||
|
tests/fp/vectors/*.tv
|
||||||
|
12
linux/bootmem.txt
Normal file
12
linux/bootmem.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
00001000: 00000297 auipc t0, 0 # t0 = 0x00001000
|
||||||
|
00001004: 02828613 addi a2, t0,0x28 # a2 = 0x00001028
|
||||||
|
00001008: f1402573 csrr a0, mhartid # a0 = mhartid
|
||||||
|
0000100c: 0202b583 ld a1, 32(t0) # a1 = 87000000 - device tree address
|
||||||
|
00001010: 0182b283 ld t0, 24(t0) # t0 = 80000000 - start of firmware
|
||||||
|
00001014: 00028067 jr t0 # jump to firmware
|
||||||
|
00001018: 0000000080000000 # firmware start address
|
||||||
|
00001020: 0000000087000000 # flattened device tree load address
|
||||||
|
00001028: 000000004942534f # a2 points to this 8 dword data structure
|
||||||
|
00001030: 0000000000000002
|
||||||
|
00001038: 0000000080200000
|
||||||
|
00001040: 0000000000000001
|
@ -28,7 +28,7 @@ ${DIS}/vmlinux.objdump.addr: ${DIS}/vmlinux.objdump
|
|||||||
-cd ${DIS}; extractFunctionRadix.sh vmlinux.objdump
|
-cd ${DIS}; extractFunctionRadix.sh vmlinux.objdump
|
||||||
|
|
||||||
${DIS}/busybox.objdump: ${DIS}/rootfs/bin/busybox
|
${DIS}/busybox.objdump: ${DIS}/rootfs/bin/busybox
|
||||||
riscv64-unknown-elf-objdump -D ${DIS}/rootfs/bin/busybox >> ${DIS}/busybox.objdump
|
riscv64-unknown-elf-objdump -S ${DIS}/rootfs/bin/busybox >> ${DIS}/busybox.objdump
|
||||||
|
|
||||||
${DIS}/rootfs/bin/busybox:
|
${DIS}/rootfs/bin/busybox:
|
||||||
mkdir -p ${DIS}/rootfs
|
mkdir -p ${DIS}/rootfs
|
||||||
|
68
linux/testvector-generation/filterTrapsToInterrupts.py
Executable file
68
linux/testvector-generation/filterTrapsToInterrupts.py
Executable file
@ -0,0 +1,68 @@
|
|||||||
|
#! /usr/bin/python3
|
||||||
|
import sys, os
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
################
|
||||||
|
# Helper Funcs #
|
||||||
|
################
|
||||||
|
|
||||||
|
def tokenize(string):
|
||||||
|
tokens = []
|
||||||
|
token = ''
|
||||||
|
whitespace = 0
|
||||||
|
prevWhitespace = 0
|
||||||
|
for char in string:
|
||||||
|
prevWhitespace = whitespace
|
||||||
|
whitespace = char in ' \t\n'
|
||||||
|
if (whitespace):
|
||||||
|
if ((not prevWhitespace) and (token != '')):
|
||||||
|
tokens.append(token)
|
||||||
|
token = ''
|
||||||
|
else:
|
||||||
|
token = token + char
|
||||||
|
return tokens
|
||||||
|
|
||||||
|
def strip0x(num):
|
||||||
|
return num[2:]
|
||||||
|
|
||||||
|
def stripZeroes(num):
|
||||||
|
num = num.strip('0')
|
||||||
|
if num=='':
|
||||||
|
return '0'
|
||||||
|
else:
|
||||||
|
return num
|
||||||
|
|
||||||
|
#############
|
||||||
|
# Main Code #
|
||||||
|
#############
|
||||||
|
print("Begin filtering traps down to just external interrupts.")
|
||||||
|
|
||||||
|
# Parse Args
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
sys.exit('Error filterTrapsToInterrupts.py expects 1 arg: <path_to_testvector_dir>')
|
||||||
|
tvDir = sys.argv[1]+'/'
|
||||||
|
trapsFilePath = tvDir+'traps.txt'
|
||||||
|
if not os.path.exists(trapsFilePath):
|
||||||
|
sys.exit('Error input file '+trapsFilePath+'not found')
|
||||||
|
|
||||||
|
with open(tvDir+'interrupts.txt', 'w') as interruptsFile:
|
||||||
|
with open(trapsFilePath, 'r') as trapsFile:
|
||||||
|
while True:
|
||||||
|
trap = trapsFile.readline()
|
||||||
|
if trap == '':
|
||||||
|
break
|
||||||
|
trapType = trap.split(' ')[-1]
|
||||||
|
if ('interrupt' in trap) and (('external' in trapType) or ('m_timer' in trapType)): # no s_timer because that is not controlled by CLINT
|
||||||
|
interruptsFile.write(trap) # overall line
|
||||||
|
interruptsFile.write(trapsFile.readline()) # attempted instr count
|
||||||
|
interruptsFile.write(trapsFile.readline()) # hart #
|
||||||
|
interruptsFile.write(trapsFile.readline()) # asynchronous
|
||||||
|
interruptsFile.write(trapsFile.readline()) # cause
|
||||||
|
interruptsFile.write(trapsFile.readline()) # epc
|
||||||
|
interruptsFile.write(trapsFile.readline()) # tval
|
||||||
|
interruptsFile.write(trapsFile.readline()) # description
|
||||||
|
else:
|
||||||
|
for i in range(7):
|
||||||
|
trapsFile.readline()
|
||||||
|
|
||||||
|
print("Finished filtering traps down to just external interrupts.")
|
@ -53,7 +53,7 @@ then
|
|||||||
-ex "printf \"Warning - please verify that the second half of $rawUntrimmedBootmemFile is all 0s\n\"" \
|
-ex "printf \"Warning - please verify that the second half of $rawUntrimmedBootmemFile is all 0s\n\"" \
|
||||||
-ex "dump binary memory $rawUntrimmedBootmemFile 0x1000 0x2fff" \
|
-ex "dump binary memory $rawUntrimmedBootmemFile 0x1000 0x2fff" \
|
||||||
-ex "printf \"Creating $rawRamFile\n\"" \
|
-ex "printf \"Creating $rawRamFile\n\"" \
|
||||||
-ex "dump binary memory $rawRamFile 0x80000000 0xffffffff" \
|
-ex "dump binary memory $rawRamFile 0x80000000 0x87ffffff" \
|
||||||
-ex "kill" \
|
-ex "kill" \
|
||||||
-ex "q"
|
-ex "q"
|
||||||
|
|
||||||
|
@ -4,10 +4,12 @@ imageDir=$RISCV/buildroot/output/images
|
|||||||
tvDir=$RISCV/linux-testvectors
|
tvDir=$RISCV/linux-testvectors
|
||||||
recordFile="$tvDir/all.qemu"
|
recordFile="$tvDir/all.qemu"
|
||||||
traceFile="$tvDir/all.txt"
|
traceFile="$tvDir/all.txt"
|
||||||
|
trapsFile="$tvDir/traps.txt"
|
||||||
interruptsFile="$tvDir/interrupts.txt"
|
interruptsFile="$tvDir/interrupts.txt"
|
||||||
|
|
||||||
read -p "Warning: running this script will overwrite the contents of:
|
read -p "Warning: running this script will overwrite the contents of:
|
||||||
* $traceFile
|
* $traceFile
|
||||||
|
* $trapsFile
|
||||||
* $interruptsFile
|
* $interruptsFile
|
||||||
Would you like to proceed? (y/n) " -n 1 -r
|
Would you like to proceed? (y/n) " -n 1 -r
|
||||||
echo
|
echo
|
||||||
@ -28,6 +30,7 @@ then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
touch $traceFile
|
touch $traceFile
|
||||||
|
touch $trapsFile
|
||||||
touch $interruptsFile
|
touch $interruptsFile
|
||||||
|
|
||||||
# QEMU Simulation
|
# QEMU Simulation
|
||||||
@ -38,7 +41,9 @@ then
|
|||||||
-bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \
|
-bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \
|
||||||
-singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on,rr=replay,rrfile=$recordFile \
|
-singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on,rr=replay,rrfile=$recordFile \
|
||||||
-d nochain,cpu,in_asm,int \
|
-d nochain,cpu,in_asm,int \
|
||||||
2>&1 >./qemu-serial | ./parseQEMUtoGDB.py | ./parseGDBtoTrace.py $interruptsFile | ./remove_dup.awk > $traceFile)
|
2>&1 >./qemu-serial | ./parseQEMUtoGDB.py | ./parseGDBtoTrace.py $trapsFile | ./remove_dup.awk > $traceFile)
|
||||||
|
|
||||||
|
./filterTrapsToInterrupts.py $tvDir
|
||||||
|
|
||||||
echo "genTrace.sh completed!"
|
echo "genTrace.sh completed!"
|
||||||
echo "You may want to restrict write access to $tvDir now and give cad ownership of it."
|
echo "You may want to restrict write access to $tvDir now and give cad ownership of it."
|
||||||
|
@ -29,10 +29,14 @@ def printPC(l):
|
|||||||
|
|
||||||
def printCSRs():
|
def printCSRs():
|
||||||
global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs
|
global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs
|
||||||
|
global interrupt_line
|
||||||
if not inPageFault:
|
if not inPageFault:
|
||||||
for (csr,val) in CSRs.items():
|
for (csr,val) in CSRs.items():
|
||||||
print('{}{}{:#x} {}'.format(csr, ' '*(15-len(csr)), val, val))
|
print('{}{}{:#x} {}'.format(csr, ' '*(15-len(csr)), val, val))
|
||||||
print('-----')
|
print('-----') # end of current instruction
|
||||||
|
if len(interrupt_line)>0: # squish interrupts in between instructions
|
||||||
|
print(interrupt_line)
|
||||||
|
interrupt_line=""
|
||||||
|
|
||||||
def parseCSRs(l):
|
def parseCSRs(l):
|
||||||
global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs
|
global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs
|
||||||
@ -119,15 +123,9 @@ for l in fileinput.input():
|
|||||||
break
|
break
|
||||||
elif l.startswith('IN:'):
|
elif l.startswith('IN:'):
|
||||||
# New disassembled instr
|
# New disassembled instr
|
||||||
if len(interrupt_line)>0:
|
|
||||||
print(interrupt_line)
|
|
||||||
interrupt_line=""
|
|
||||||
parseState = "instr"
|
parseState = "instr"
|
||||||
elif (parseState == "instr") and l.startswith('0x'):
|
elif (parseState == "instr") and l.startswith('0x'):
|
||||||
# New instruction
|
# New instruction
|
||||||
if len(interrupt_line)>0:
|
|
||||||
print(interrupt_line)
|
|
||||||
interrupt_line=""
|
|
||||||
if "out of bounds" in l:
|
if "out of bounds" in l:
|
||||||
sys.stderr.write("Detected QEMU page fault error\n")
|
sys.stderr.write("Detected QEMU page fault error\n")
|
||||||
beginPageFault = not inPageFault
|
beginPageFault = not inPageFault
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
`define ZIFENCEI_SUPPORTED 1
|
`define ZIFENCEI_SUPPORTED 1
|
||||||
`define COUNTERS 32
|
`define COUNTERS 32
|
||||||
`define ZICOUNTERS_SUPPORTED 1
|
`define ZICOUNTERS_SUPPORTED 1
|
||||||
|
`define ZFH_SUPPORTED 0
|
||||||
|
|
||||||
// Microarchitectural Features
|
// Microarchitectural Features
|
||||||
`define UARCH_PIPELINED 1
|
`define UARCH_PIPELINED 1
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
`define ZIFENCEI_SUPPORTED 1
|
`define ZIFENCEI_SUPPORTED 1
|
||||||
`define COUNTERS 32
|
`define COUNTERS 32
|
||||||
`define ZICOUNTERS_SUPPORTED 1
|
`define ZICOUNTERS_SUPPORTED 1
|
||||||
|
`define ZFH_SUPPORTED 0
|
||||||
|
|
||||||
/// Microarchitectural Features
|
/// Microarchitectural Features
|
||||||
`define UARCH_PIPELINED 1
|
`define UARCH_PIPELINED 1
|
||||||
|
@ -41,7 +41,6 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} {
|
|||||||
run -all
|
run -all
|
||||||
run -all
|
run -all
|
||||||
exec ./slack-notifier/slack-notifier.py
|
exec ./slack-notifier/slack-notifier.py
|
||||||
quit
|
|
||||||
} else {
|
} else {
|
||||||
vlog -lint -work wkdir/work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 -suppress 7063
|
vlog -lint -work wkdir/work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 -suppress 7063
|
||||||
# start and run simulation
|
# start and run simulation
|
||||||
@ -52,11 +51,15 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} {
|
|||||||
#vopt work_$2.testbench -work work_$2 -o workopt_$2 +cover=sbectf
|
#vopt work_$2.testbench -work work_$2 -o workopt_$2 +cover=sbectf
|
||||||
#vsim -coverage -lib work_$2 workopt_$2
|
#vsim -coverage -lib work_$2 workopt_$2
|
||||||
|
|
||||||
|
# power add generates the logging necessary for saif generation.
|
||||||
|
power add -r /dut/core/*
|
||||||
run -all
|
run -all
|
||||||
quit
|
power off -r /dut/core/*
|
||||||
}
|
}
|
||||||
|
|
||||||
#coverage report -file wally-pipelined-coverage.txt
|
#coverage report -file wally-pipelined-coverage.txt
|
||||||
# These aren't doing anything helpful
|
# These aren't doing anything helpful
|
||||||
#coverage report -memory
|
#coverage report -memory
|
||||||
#profile report -calltree -file wally-pipelined-calltree.rpt -cutoff 2
|
#profile report -calltree -file wally-pipelined-calltree.rpt -cutoff 2
|
||||||
|
power report -all -bsaif power.saif
|
||||||
|
quit
|
||||||
|
@ -57,12 +57,12 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} {
|
|||||||
do wave.do
|
do wave.do
|
||||||
|
|
||||||
# power add generates the logging necessary for saif generation.
|
# power add generates the logging necessary for saif generation.
|
||||||
#power add -r /dut/core/*
|
power add -r /dut/core/*
|
||||||
#-- Run the Simulation
|
#-- Run the Simulation
|
||||||
|
|
||||||
run -all
|
run -all
|
||||||
#power off -r /dut/core/*
|
power off -r /dut/core/*
|
||||||
#power report -all -bsaif power.saif
|
power report -all -bsaif power.saif
|
||||||
noview ../testbench/testbench.sv
|
noview ../testbench/testbench.sv
|
||||||
view wave
|
view wave
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ module expadd(
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
end else begin
|
end else if (`FPSIZES == 4) begin
|
||||||
always_comb begin
|
always_comb begin
|
||||||
case (FmtE)
|
case (FmtE)
|
||||||
2'h3: Denorm = 1;
|
2'h3: Denorm = 1;
|
||||||
@ -619,7 +619,7 @@ module normalize(
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
end else begin
|
end else if (`FPSIZES == 4) begin
|
||||||
always_comb begin
|
always_comb begin
|
||||||
case (FmtM)
|
case (FmtM)
|
||||||
2'h3: SumExpTmp = SumExpTmpTmp;
|
2'h3: SumExpTmp = SumExpTmpTmp;
|
||||||
@ -664,7 +664,7 @@ module normalize(
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
end else begin
|
end else if (`FPSIZES == 4) begin
|
||||||
logic Sum0LEZ, Sum0GEFL, Sum1LEZ, Sum1GEFL, Sum2LEZ, Sum2GEFL, Sum3LEZ, Sum3GEFL;
|
logic Sum0LEZ, Sum0GEFL, Sum1LEZ, Sum1GEFL, Sum2LEZ, Sum2GEFL, Sum3LEZ, Sum3GEFL;
|
||||||
assign Sum0LEZ = SumExpTmpTmp[`NE+1] | ~|SumExpTmpTmp;
|
assign Sum0LEZ = SumExpTmpTmp[`NE+1] | ~|SumExpTmpTmp;
|
||||||
assign Sum0GEFL = $signed(SumExpTmpTmp) >= $signed(-(`NE+2)'(`NF )-(`NE+2)'(2));
|
assign Sum0GEFL = $signed(SumExpTmpTmp) >= $signed(-(`NE+2)'(`NF )-(`NE+2)'(2));
|
||||||
@ -719,7 +719,7 @@ module normalize(
|
|||||||
(|CorrSumShifted[3*`NF+2-`NF1:2*`NF+3]&((FmtM==`FMT1)|(FmtM==`FMT2))) |
|
(|CorrSumShifted[3*`NF+2-`NF1:2*`NF+3]&((FmtM==`FMT1)|(FmtM==`FMT2))) |
|
||||||
(|CorrSumShifted[3*`NF+2-`NF2:3*`NF+3-`NF1]&(FmtM==`FMT2));
|
(|CorrSumShifted[3*`NF+2-`NF2:3*`NF+3-`NF1]&(FmtM==`FMT2));
|
||||||
|
|
||||||
end else begin
|
end else if (`FPSIZES == 4) begin
|
||||||
assign NormSumSticky = (|CorrSumShifted[2*`NF+2:0]) |
|
assign NormSumSticky = (|CorrSumShifted[2*`NF+2:0]) |
|
||||||
(|CorrSumShifted[3*`NF+2-`D_NF:2*`NF+3]&((FmtM==1)|(FmtM==0)|(FmtM==2))) |
|
(|CorrSumShifted[3*`NF+2-`D_NF:2*`NF+3]&((FmtM==1)|(FmtM==0)|(FmtM==2))) |
|
||||||
(|CorrSumShifted[3*`NF+2-`S_NF:3*`NF+3-`D_NF]&((FmtM==0)|(FmtM==2))) |
|
(|CorrSumShifted[3*`NF+2-`S_NF:3*`NF+3-`D_NF]&((FmtM==0)|(FmtM==2))) |
|
||||||
@ -876,7 +876,7 @@ module fmaround(
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
end else begin
|
end else if (`FPSIZES == 4) begin
|
||||||
always_comb begin
|
always_comb begin
|
||||||
case (FmtM)
|
case (FmtM)
|
||||||
2'h3: begin
|
2'h3: begin
|
||||||
@ -995,7 +995,7 @@ module fmaround(
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
end else begin
|
end else if (`FPSIZES == 4) begin
|
||||||
always_comb begin
|
always_comb begin
|
||||||
case (FmtM)
|
case (FmtM)
|
||||||
2'h3: RoundAdd = Minus1 ? {`FLEN+1{1'b1}} : {{{`FLEN{1'b0}}}, Plus1};
|
2'h3: RoundAdd = Minus1 ? {`FLEN+1{1'b1}} : {{{`FLEN{1'b0}}}, Plus1};
|
||||||
@ -1063,7 +1063,7 @@ module fmaflags(
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
end else begin
|
end else if (`FPSIZES == 4) begin
|
||||||
always_comb begin
|
always_comb begin
|
||||||
case (FmtM)
|
case (FmtM)
|
||||||
2'h3: GtMaxExp = &FullResultExp[`NE-1:0] | FullResultExp[`NE];
|
2'h3: GtMaxExp = &FullResultExp[`NE-1:0] | FullResultExp[`NE];
|
||||||
@ -1223,7 +1223,7 @@ module resultselect(
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
end else begin
|
end else if (`FPSIZES == 4) begin
|
||||||
always_comb begin
|
always_comb begin
|
||||||
case (FmtM)
|
case (FmtM)
|
||||||
2'h3: begin
|
2'h3: begin
|
||||||
|
@ -261,7 +261,7 @@ module unpack (
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
end else begin // if all precsisons are supported - quad, double, single, and half
|
end else if (`FPSIZES == 4) begin // if all precsisons are supported - quad, double, single, and half
|
||||||
|
|
||||||
// quad | double | single | half
|
// quad | double | single | half
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
@ -1450,30 +1450,30 @@ string imperas32f[] = '{
|
|||||||
|
|
||||||
string wally64priv[] = '{
|
string wally64priv[] = '{
|
||||||
`WALLYTEST,
|
`WALLYTEST,
|
||||||
"rv64i_m/privilege/WALLY-CSR-permission-s-01", "0050a0",
|
"rv64i_m/privilege/WALLY-CSR-permission-s-01", "0060a0",
|
||||||
//"rv64i_m/privilege/WALLY-CSR-PERMISSIONS-M", "005070",
|
//"rv64i_m/privilege/WALLY-CSR-PERMISSIONS-M", "005090",
|
||||||
//"rv64i_m/privilege/WALLY-CSR-PERMISSIONS-S", "003070",
|
//"rv64i_m/privilege/WALLY-CSR-PERMISSIONS-S", "003090",
|
||||||
"rv64i_m/privilege/WALLY-CSR-permission-u-01", "0050a0",
|
"rv64i_m/privilege/WALLY-CSR-permission-u-01", "0060a0",
|
||||||
// "rv64i_m/privilege/WALLY-MARCHID", "003070",
|
// "rv64i_m/privilege/WALLY-MARCHID", "004090",
|
||||||
/* "rv64i_m/privilege/WALLY-MCAUSE", "003070",
|
/* "rv64i_m/privilege/WALLY-MCAUSE", "003090",
|
||||||
"rv64i_m/privilege/WALLY-MEDELEG", "003070",
|
"rv64i_m/privilege/WALLY-MEDELEG", "004090",
|
||||||
"rv64i_m/privilege/WALLY-MHARTID", "003070",
|
"rv64i_m/privilege/WALLY-MHARTID", "004090",
|
||||||
"rv64i_m/privilege/WALLY-MIMPID", "003070",*/
|
"rv64i_m/privilege/WALLY-MIMPID", "004090",*/
|
||||||
"rv64i_m/privilege/WALLY-minfo-01", "0040a0",
|
"rv64i_m/privilege/WALLY-minfo-01", "0050a0",
|
||||||
"rv64i_m/privilege/WALLY-misa-01", "0040a0",
|
"rv64i_m/privilege/WALLY-misa-01", "0050a0",
|
||||||
"rv64i_m/privilege/WALLY-MMU-SV39", "0040a0",
|
"rv64i_m/privilege/WALLY-MMU-SV39", "0050a0",
|
||||||
"rv64i_m/privilege/WALLY-MMU-SV48", "0040a0",
|
"rv64i_m/privilege/WALLY-MMU-SV48", "0050a0",
|
||||||
/* "rv64i_m/privilege/WALLY-MSTATUS", "002070",
|
/* "rv64i_m/privilege/WALLY-MSTATUS", "002090",
|
||||||
"rv64i_m/privilege/WALLY-MTVEC", "002070",
|
"rv64i_m/privilege/WALLY-MTVEC", "002090",
|
||||||
"rv64i_m/privilege/WALLY-MVENDORID", "003070", */
|
"rv64i_m/privilege/WALLY-MVENDORID", "004090", */
|
||||||
"rv64i_m/privilege/WALLY-PMA", "0040a0",
|
"rv64i_m/privilege/WALLY-PMA", "0050a0",
|
||||||
"rv64i_m/privilege/WALLY-PMP", "0040a0",
|
"rv64i_m/privilege/WALLY-PMP", "0050a0"
|
||||||
// "rv64i_m/privilege/WALLY-SCAUSE", "002070",
|
// "rv64i_m/privilege/WALLY-SCAUSE", "002090",
|
||||||
"rv64i_m/privilege/WALLY-scratch-01", "0040a0",
|
// "rv64i_m/privilege/WALLY-scratch-01", "0040a0",
|
||||||
"rv64i_m/privilege/WALLY-sscratch-s-01", "0040a0"
|
// "rv64i_m/privilege/WALLY-sscratch-s-01", "0040a0",
|
||||||
// "rv64i_m/privilege/WALLY-trap-01", "0040a0"
|
// "rv64i_m/privilege/WALLY-trap-01", "0050a0"
|
||||||
// "rv64i_m/privilege/WALLY-STVEC", "002070",
|
// "rv64i_m/privilege/WALLY-STVEC", "002090",
|
||||||
// "rv64i_m/privilege/WALLY-UCAUSE", "002070",
|
// "rv64i_m/privilege/WALLY-UCAUSE", "002090",
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
# Makefile
|
|
||||||
|
|
||||||
CC = gcc
|
|
||||||
CFLAGS = -O3
|
|
||||||
LIBS = -lm
|
|
||||||
LFLAGS = -L.
|
|
||||||
IFLAGS = -I../../../addins/SoftFloat-3e/source/include/
|
|
||||||
LIBS = ../../../addins/SoftFloat-3e/build/Linux-x86_64-GCC/softfloat.a
|
|
||||||
SRCS = $(wildcard *.c)
|
|
||||||
|
|
||||||
PROGS = $(patsubst %.c,%,$(SRCS))
|
|
||||||
|
|
||||||
all: $(PROGS)
|
|
||||||
|
|
||||||
%: %.c
|
|
||||||
$(CC) $(CFLAGS) $(IFLAGS) $(LFLAGS) -o $@ $< $(LIBS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(PROGS)
|
|
Binary file not shown.
@ -1,52 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "softfloat.h"
|
|
||||||
#include "softfloat_types.h"
|
|
||||||
|
|
||||||
int float_rounding_mode = 0;
|
|
||||||
|
|
||||||
union dp {
|
|
||||||
unsigned short x[4];
|
|
||||||
double y;
|
|
||||||
} X;
|
|
||||||
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
uint8_t rounding_mode;
|
|
||||||
uint8_t exceptions;
|
|
||||||
|
|
||||||
uint64_t n, d, result;
|
|
||||||
float64_t d_n, d_d, d_result;
|
|
||||||
|
|
||||||
n = 0x3feffffffefffff6;
|
|
||||||
d = 0xffeffffffffffffe;
|
|
||||||
//n = 0x00000000400001ff;
|
|
||||||
//d = 0x3ffffdfffffffbfe;
|
|
||||||
|
|
||||||
d_n.v = n;
|
|
||||||
d_d.v = d;
|
|
||||||
|
|
||||||
softfloat_roundingMode = rounding_mode;
|
|
||||||
softfloat_exceptionFlags = 0;
|
|
||||||
softfloat_detectTininess = softfloat_tininess_beforeRounding;
|
|
||||||
|
|
||||||
d_result = f64_div(d_n, d_d);
|
|
||||||
|
|
||||||
//result = d_result.v;
|
|
||||||
//exceptions = softfloat_exceptionFlags & 0x1f;
|
|
||||||
|
|
||||||
X.x[3] = (d_result.v & 0xffff000000000000) >> 48;
|
|
||||||
X.x[2] = (d_result.v & 0x0000ffff00000000) >> 32;
|
|
||||||
X.x[1] = (d_result.v & 0x00000000ffff0000) >> 16;
|
|
||||||
X.x[0] = (d_result.v & 0x000000000000ffff);
|
|
||||||
|
|
||||||
printf("Number = %.4x\n", X.x[3]);
|
|
||||||
printf("Number = %.4x\n", X.x[2]);
|
|
||||||
printf("Number = %.4x\n", X.x[1]);
|
|
||||||
printf("Number = %.4x\n", X.x[0]);
|
|
||||||
printf("Number = %1.25lg\n", X.y);
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
Binary file not shown.
@ -1,47 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "softfloat.h"
|
|
||||||
#include "softfloat_types.h"
|
|
||||||
|
|
||||||
int float_rounding_mode = 0;
|
|
||||||
|
|
||||||
union sp {
|
|
||||||
unsigned short x[2];
|
|
||||||
float y;
|
|
||||||
} X;
|
|
||||||
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
uint8_t rounding_mode;
|
|
||||||
uint8_t exceptions;
|
|
||||||
|
|
||||||
uint32_t multiplier, multiplicand, addend, result;
|
|
||||||
float32_t f_multiplier, f_multiplicand, f_addend, f_result;
|
|
||||||
|
|
||||||
multiplier = 0xbf800000;
|
|
||||||
multiplicand = 0xbf800000;
|
|
||||||
addend = 0xffaaaaaa;
|
|
||||||
|
|
||||||
f_multiplier.v = multiplier;
|
|
||||||
f_multiplicand.v = multiplicand;
|
|
||||||
f_addend.v = addend;
|
|
||||||
|
|
||||||
softfloat_roundingMode = rounding_mode;
|
|
||||||
softfloat_exceptionFlags = 0;
|
|
||||||
softfloat_detectTininess = softfloat_tininess_beforeRounding;
|
|
||||||
|
|
||||||
f_result = f32_mulAdd(f_multiplier, f_multiplicand, f_addend);
|
|
||||||
|
|
||||||
result = f_result.v;
|
|
||||||
exceptions = softfloat_exceptionFlags & 0x1f;
|
|
||||||
|
|
||||||
printf("%x\n", f_result.v);
|
|
||||||
|
|
||||||
// Print out SP number
|
|
||||||
X.x[1] = (f_result.v & 0xffff0000) >> 16;
|
|
||||||
X.x[0] = (f_result.v & 0x0000ffff);
|
|
||||||
printf("Number = %f\n", X.y);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,23 +1,11 @@
|
|||||||
beef00b4 # Test 12.3.2.1: read 64 bits success in CLINT
|
beef00b4 # Test 12.3.2.1: read 64 bits success in CLINT
|
||||||
0000dead # all of these read successes are also confirming successful writes
|
0000dead # all of these read successes are also confirming successful writes
|
||||||
00000007 # write 32 bits with access fault in CLINT
|
beef00b5 # read 32 bits success in CLINT (bottom 32 bits sign extended)
|
||||||
00000000
|
ffffffff
|
||||||
00000005 # read 32 bits with access fault in CLINT
|
000000b6 # read 16 bits success in CLINT (bottom 16 bits sign extended)
|
||||||
00000000
|
|
||||||
00000bad
|
|
||||||
00000000
|
|
||||||
00000007 # write 16 bits with access fault in CLINT
|
|
||||||
00000000
|
|
||||||
00000005 # read 16 bits with access fault in CLINT
|
|
||||||
00000000
|
|
||||||
00000bad
|
|
||||||
00000000
|
|
||||||
00000007 # write 8 bits with access fault in CLINT
|
|
||||||
00000000
|
|
||||||
00000005 # read 8 bits with access fault in CLINT
|
|
||||||
00000000
|
|
||||||
00000bad
|
|
||||||
00000000
|
00000000
|
||||||
|
ffffffb7 # read 8 bits success in CLINT (bottom 8 bits sign extended)
|
||||||
|
ffffffff
|
||||||
00000001 # execute test with access fault in CLINT
|
00000001 # execute test with access fault in CLINT
|
||||||
00000000
|
00000000
|
||||||
00000bad
|
00000bad
|
||||||
|
@ -85,12 +85,12 @@ test_cases:
|
|||||||
# Use timecmp register as readable and writable section of the CLINT
|
# Use timecmp register as readable and writable section of the CLINT
|
||||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B4, write64_test # 64-bit write: success
|
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B4, write64_test # 64-bit write: success
|
||||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B4, read64_test # 64-bit read: success
|
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B4, read64_test # 64-bit read: success
|
||||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B5, write32_test # 32-bit write: failure *** due to non-native length access
|
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B5, write32_test # 32-bit write: success
|
||||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B5, read32_test # 32-bit read: failure
|
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B5, read32_test # 32-bit read: success
|
||||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B6, write16_test # 16-bit write: failure
|
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B6, write16_test # 16-bit write: success
|
||||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B6, read16_test # 16-bit read: failure
|
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B6, read16_test # 16-bit read: success
|
||||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B7, write08_test # 08-bit write: failure
|
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B7, write08_test # 08-bit write: success
|
||||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B7, read08_test # 08-bit read: failure
|
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B7, read08_test # 08-bit read: success
|
||||||
|
|
||||||
.8byte CLINT_BASE, 0xbad, executable_test# execute: instruction access fault
|
.8byte CLINT_BASE, 0xbad, executable_test# execute: instruction access fault
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ RVTEST_CODE_BEGIN
|
|||||||
//
|
//
|
||||||
// Initialize x6 as a virtual pointer to the test results
|
// Initialize x6 as a virtual pointer to the test results
|
||||||
// Initialize x16 as a physical pointer to the test results
|
// Initialize x16 as a physical pointer to the test results
|
||||||
// Set up stack pointer (sp = x2)
|
// Set up stack pointer, mscratch, sscratch
|
||||||
//
|
//
|
||||||
// ---------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -50,8 +50,12 @@ RVTEST_CODE_BEGIN
|
|||||||
la x16, test_1_res // x16 reserved for the physical address equivalent of x6 to be used in trap handlers
|
la x16, test_1_res // x16 reserved for the physical address equivalent of x6 to be used in trap handlers
|
||||||
// any time either is used, both must be updated.
|
// any time either is used, both must be updated.
|
||||||
|
|
||||||
// address for stack
|
// address for normal user stack, mscratch stack, and sscratch stack
|
||||||
la sp, top_of_stack
|
la sp, mscratch_top
|
||||||
|
csrw mscratch, sp
|
||||||
|
la sp, sscratch_top
|
||||||
|
csrw sscratch, sp
|
||||||
|
la sp, stack_top
|
||||||
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
@ -72,7 +76,7 @@ cause_instr_addr_misaligned:
|
|||||||
|
|
||||||
cause_instr_access:
|
cause_instr_access:
|
||||||
la x28, 0x0 // address zero is an address with no memory
|
la x28, 0x0 // address zero is an address with no memory
|
||||||
sd x1, -8(sp) // push the return adress ontot the stack
|
sd x1, -8(sp) // push the return adress onto the stack
|
||||||
addi sp, sp, -8
|
addi sp, sp, -8
|
||||||
jalr x28 // cause instruction access trap
|
jalr x28 // cause instruction access trap
|
||||||
ld x1, 0(sp) // pop return adress back from the stack
|
ld x1, 0(sp) // pop return adress back from the stack
|
||||||
@ -83,7 +87,7 @@ cause_illegal_instr:
|
|||||||
.word 0x00000000 // a 32 bit zros is an illegal instruction
|
.word 0x00000000 // a 32 bit zros is an illegal instruction
|
||||||
ret
|
ret
|
||||||
|
|
||||||
cause_breakpnt: // ****
|
cause_breakpnt:
|
||||||
ebreak
|
ebreak
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@ -128,7 +132,9 @@ cause_time_interrupt:
|
|||||||
sw x31,4(x29) // store into most significant word of MTIMECMP
|
sw x31,4(x29) // store into most significant word of MTIMECMP
|
||||||
nowrap:
|
nowrap:
|
||||||
sw x28, 0(x29) // store into least significant word of MTIMECMP
|
sw x28, 0(x29) // store into least significant word of MTIMECMP
|
||||||
loop: j loop // wait until interrupt occurs
|
loop:
|
||||||
|
wfi
|
||||||
|
j loop // wait until interrupt occurs
|
||||||
ret
|
ret
|
||||||
|
|
||||||
cause_soft_interrupt:
|
cause_soft_interrupt:
|
||||||
@ -150,7 +156,7 @@ end_trap_triggers:
|
|||||||
|
|
||||||
.macro TRAP_HANDLER MODE, VECTORED=1, DEBUG=0
|
.macro TRAP_HANDLER MODE, VECTORED=1, DEBUG=0
|
||||||
// MODE decides which mode this trap handler will be taken in (M or S mode)
|
// MODE decides which mode this trap handler will be taken in (M or S mode)
|
||||||
// Vectored decides whether interrumpts are handled with the vector table at trap_handler_MODE (1)
|
// Vectored decides whether interrupts are handled with the vector table at trap_handler_MODE (1)
|
||||||
// vs Using the non-vector approach the rest of the trap handler takes (0)
|
// vs Using the non-vector approach the rest of the trap handler takes (0)
|
||||||
// DEBUG decides whether we will print mtval a string with status.mpie, status.mie, and status.mpp to the signature (1)
|
// DEBUG decides whether we will print mtval a string with status.mpie, status.mie, and status.mpp to the signature (1)
|
||||||
// vs not saving that info to the signature (0)
|
// vs not saving that info to the signature (0)
|
||||||
@ -216,23 +222,28 @@ trap_handler_\MODE\():
|
|||||||
// *** ASSUMES that a cause value of 0 for an interrupt is unimplemented
|
// *** ASSUMES that a cause value of 0 for an interrupt is unimplemented
|
||||||
// otherwise, a vectored interrupt handler should jump to trap_handler_\MODE\() + 4 * Interrupt cause code
|
// otherwise, a vectored interrupt handler should jump to trap_handler_\MODE\() + 4 * Interrupt cause code
|
||||||
// No matter the value of VECTORED, exceptions (not interrupts) are handled in an unvecotred way
|
// No matter the value of VECTORED, exceptions (not interrupts) are handled in an unvecotred way
|
||||||
j soft_interrupt_\MODE\() // 1: instruction access fault // the zero spot is taken up by the instruction to skip this table.
|
j s_soft_vector_\MODE\() // 1: instruction access fault // the zero spot is taken up by the instruction to skip this table.
|
||||||
j segfault_\MODE\() // 2: reserved
|
j segfault_\MODE\() // 2: reserved
|
||||||
j soft_interrupt_\MODE\() // 3: breakpoint
|
j m_soft_vector_\MODE\() // 3: breakpoint
|
||||||
j segfault_\MODE\() // 4: reserved
|
j segfault_\MODE\() // 4: reserved
|
||||||
j time_interrupt_\MODE\() // 5: load access fault
|
j s_time_vector_\MODE\() // 5: load access fault
|
||||||
j segfault_\MODE\() // 6: reserved
|
j segfault_\MODE\() // 6: reserved
|
||||||
j time_interrupt_\MODE\() // 7: store access fault
|
j m_time_vector_\MODE\() // 7: store access fault
|
||||||
j segfault_\MODE\() // 8: reserved
|
j segfault_\MODE\() // 8: reserved
|
||||||
j ext_interrupt_\MODE\() // 9: ecall from S-mode
|
j s_ext_vector_\MODE\() // 9: ecall from S-mode
|
||||||
j segfault_\MODE\() // 10: reserved
|
j segfault_\MODE\() // 10: reserved
|
||||||
j ext_interrupt_\MODE\() // 11: ecall from M-mode
|
j m_ext_vector_\MODE\() // 11: ecall from M-mode
|
||||||
// 12 through >=16 are reserved or designated for platform use
|
// 12 through >=16 are reserved or designated for platform use
|
||||||
|
|
||||||
trap_unvectored_\MODE\():
|
trap_unvectored_\MODE\():
|
||||||
|
csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
|
||||||
|
// *** NOTE: this means that nested traps will be screwed up but they shouldn't happen in any of these tests
|
||||||
|
|
||||||
|
trap_stack_saved_\MODE\(): // jump here after handling vectored interupt since we already switch sp and scratch there
|
||||||
// save registers on stack before using
|
// save registers on stack before using
|
||||||
sd x1, -8(sp)
|
sd x1, -8(sp)
|
||||||
sd x5, -16(sp)
|
sd x5, -16(sp)
|
||||||
|
sd x7, -24(sp)
|
||||||
|
|
||||||
// Record trap
|
// Record trap
|
||||||
csrr x1, \MODE\()cause // record the mcause
|
csrr x1, \MODE\()cause // record the mcause
|
||||||
@ -262,49 +273,35 @@ trap_unvectored_\MODE\():
|
|||||||
// Respond to trap based on cause
|
// Respond to trap based on cause
|
||||||
// All interrupts should return after being logged
|
// All interrupts should return after being logged
|
||||||
csrr x1, \MODE\()cause
|
csrr x1, \MODE\()cause
|
||||||
|
slli x1, x1, 3 // multiply cause by 8 to get offset in vector Table
|
||||||
li x5, 0x8000000000000000 // if msb is set, it is an interrupt
|
li x5, 0x8000000000000000 // if msb is set, it is an interrupt
|
||||||
and x5, x5, x1
|
and x5, x5, x1
|
||||||
bnez x5, trapreturn_\MODE\() // return from interrupt
|
bnez x5, interrupt_handler_\MODE\() // return from interrupt
|
||||||
// Other trap handling is specified in the vector Table
|
// Other trap handling is specified in the vector Table
|
||||||
slli x1, x1, 3 // multiply cause by 8 to get offset in vector Table
|
|
||||||
la x5, exception_vector_table_\MODE\()
|
la x5, exception_vector_table_\MODE\()
|
||||||
add x5, x5, x1 // compute address of vector in Table
|
add x5, x5, x1 // compute address of vector in Table
|
||||||
ld x5, 0(x5) // fectch address of handler from vector Table
|
ld x5, 0(x5) // fectch address of handler from vector Table
|
||||||
jr x5 // and jump to the handler
|
jr x5 // and jump to the handler
|
||||||
|
|
||||||
|
interrupt_handler_\MODE\():
|
||||||
|
la x5, interrupt_vector_table_\MODE\() // NOTE THIS IS NOT THE SAME AS VECTORED INTERRUPTS!!!
|
||||||
|
add x5, x5, x1 // compute address of vector in Table
|
||||||
|
ld x5, 0(x5) // fectch address of handler from vector Table
|
||||||
|
jr x5 // and jump to the handler
|
||||||
|
|
||||||
segfault_\MODE\():
|
segfault_\MODE\():
|
||||||
ld x5, -16(sp) // restore registers from stack before faulting
|
sd x7, -24(sp) // restore registers from stack before faulting
|
||||||
|
ld x5, -16(sp)
|
||||||
ld x1, -8(sp)
|
ld x1, -8(sp)
|
||||||
j terminate_test // halt program.
|
j terminate_test // halt program.
|
||||||
|
|
||||||
trapreturn_\MODE\():
|
trapreturn_\MODE\():
|
||||||
// look at the instruction to figure out whether to add 2 or 4 bytes to PC, or go to address specified in a1
|
csrr x1, \MODE\()epc
|
||||||
csrr x1, \MODE\()epc // get the mepc
|
addi x1, x1, 4 // return to the address AFTER the trapping instruction
|
||||||
addi x1, x1, 4 // *** should be 2 for compressed instructions, see note.
|
|
||||||
|
|
||||||
|
|
||||||
// ****** KMG: the following is no longer as easy to determine. mepc gets the virtual address of the trapped instruction,
|
|
||||||
// ******** but in the handler, we work in M mode with physical addresses
|
|
||||||
// This means the address in mepc is suddenly pointing somewhere else.
|
|
||||||
// to get this to work, We could either retranslate the vaddr back into a paddr (probably on the scale of difficult to intractible)
|
|
||||||
// or we could come up with some other ingenious way to stay in M mode and see if the instruction was compressed.
|
|
||||||
|
|
||||||
// lw x5, 0(x1) // read the faulting instruction
|
|
||||||
// li x1, 3 // check bottom 2 bits of instruction to see if compressed
|
|
||||||
// and x5, x5, x1 // mask the other bits
|
|
||||||
// beq x5, x1, trapreturn_uncompressed_\MODE\() // if 11, the instruction is return_uncompressed
|
|
||||||
|
|
||||||
// trapreturn_compressed_\MODE\():
|
|
||||||
// csrr x1, mepc // get the mepc again
|
|
||||||
// addi x1, x1, 2 // add 2 to find the next instruction
|
|
||||||
// j trapreturn_specified_\MODE\() // and return
|
|
||||||
|
|
||||||
// trapreturn_uncompressed_\MODE\():
|
|
||||||
// csrr x1, mepc // get the mepc again
|
|
||||||
// addi x1, x1, 4 // add 4 to find the next instruction
|
|
||||||
|
|
||||||
trapreturn_specified_\MODE\():
|
trapreturn_specified_\MODE\():
|
||||||
// reset the necessary pointers and registers (x1, x5, x6, and the return address going to mepc)
|
// reset the necessary pointers and registers (x1, x5, x6, and the return address going to mepc)
|
||||||
|
// note that we don't need to change x7 since it was a temporary register with no important address in it.
|
||||||
// so that when we return to a new virtual address, they're all in the right spot as well.
|
// so that when we return to a new virtual address, they're all in the right spot as well.
|
||||||
|
|
||||||
beqz a1, trapreturn_finished_\MODE\() // either update values, of go to default return address.
|
beqz a1, trapreturn_finished_\MODE\() // either update values, of go to default return address.
|
||||||
@ -318,13 +315,13 @@ trapreturn_specified_\MODE\():
|
|||||||
sll x5, x5, a2
|
sll x5, x5, a2
|
||||||
addi x5, x5, -1 // x5 = mask bits for offset into current pagetype
|
addi x5, x5, -1 // x5 = mask bits for offset into current pagetype
|
||||||
|
|
||||||
// reset the top of the stack, x1
|
// reset the top of the stack, which will be put into ra
|
||||||
ld x7, -8(sp)
|
ld x7, -8(sp)
|
||||||
and x7, x5, x7 // x7 = offset for x1
|
and x7, x5, x7 // x7 = offset for x1
|
||||||
add x7, x7, a1 // x7 = new address for x1
|
add x7, x7, a1 // x7 = new address for x1
|
||||||
sd x7, -8(sp)
|
sd x7, -8(sp)
|
||||||
|
|
||||||
// reset the second spot in the stack, x5
|
// reset the second spot in the stack, which will be put into x5
|
||||||
ld x7, -16(sp)
|
ld x7, -16(sp)
|
||||||
and x7, x5, x7 // x7 = offset for x5
|
and x7, x5, x7 // x7 = offset for x5
|
||||||
add x7, x7, a1 // x7 = new address for x5
|
add x7, x7, a1 // x7 = new address for x5
|
||||||
@ -334,7 +331,7 @@ trapreturn_specified_\MODE\():
|
|||||||
and x7, x5, x6 // x7 = offset for x6
|
and x7, x5, x6 // x7 = offset for x6
|
||||||
add x6, x7, a1 // x6 = new address for the result pointer
|
add x6, x7, a1 // x6 = new address for the result pointer
|
||||||
|
|
||||||
// set return address, stored temporarily in x1, to the next instruction, but in the new virtual page.
|
// reset x1, which temporarily holds the return address that will be written to mepc.
|
||||||
and x1, x5, x1 // x1 = offset for the return address
|
and x1, x5, x1 // x1 = offset for the return address
|
||||||
add x1, x1, a1 // x1 = new return address.
|
add x1, x1, a1 // x1 = new return address.
|
||||||
|
|
||||||
@ -342,10 +339,10 @@ trapreturn_specified_\MODE\():
|
|||||||
li a2, 0 // reset trapreturn inputs to the trap handler
|
li a2, 0 // reset trapreturn inputs to the trap handler
|
||||||
|
|
||||||
trapreturn_finished_\MODE\():
|
trapreturn_finished_\MODE\():
|
||||||
csrw \MODE\()epc, x1 // update the epc with address of next instruction
|
csrw \MODE\()epc, x1 // update the epc with address of next instruction
|
||||||
ld x5, -16(sp) // restore registers from stack before returning
|
ld x7, -24(sp) // restore registers from stack before returning
|
||||||
|
ld x5, -16(sp)
|
||||||
ld x1, -8(sp)
|
ld x1, -8(sp)
|
||||||
// *** this should be handled by indirectly clearing this bit csrw \MODE\()ip, 0x0 // clear interrupt pending register to indicate interrupt has been handled
|
|
||||||
\MODE\()ret // return from trap
|
\MODE\()ret // return from trap
|
||||||
|
|
||||||
ecallhandler_\MODE\():
|
ecallhandler_\MODE\():
|
||||||
@ -380,18 +377,17 @@ ecallhandler_changetousermode_\MODE\():
|
|||||||
j trapreturn_\MODE\()
|
j trapreturn_\MODE\()
|
||||||
|
|
||||||
instrpagefault_\MODE\():
|
instrpagefault_\MODE\():
|
||||||
ld x1, -8(sp) // load return address int x1 (the address AFTER the jal to the faulting address)
|
ld x1, -8(sp) // load return address from stack into ra (the address AFTER the jal to the faulting address)
|
||||||
j trapreturn_finished_\MODE\() // puts x1 into mepc, restores stack and returns to program (outside of faulting page)
|
j trapreturn_finished_\MODE\() // puts x1 into mepc, restores stack and returns to program (outside of faulting page)
|
||||||
|
|
||||||
instrfault_\MODE\():
|
instrfault_\MODE\():
|
||||||
ld x1, -8(sp) // load return address int x1 (the address AFTER the jal to the faulting address)
|
ld x1, -8(sp) // load return address from stack into ra (the address AFTER the jal to the faulting address)
|
||||||
j trapreturn_finished_\MODE\() // return to the code after recording the mcause
|
j trapreturn_finished_\MODE\() // return to the code at ra value from before trap
|
||||||
|
|
||||||
illegalinstr_\MODE\():
|
illegalinstr_\MODE\():
|
||||||
j trapreturn_\MODE\() // return to the code after recording the mcause
|
j trapreturn_\MODE\() // return to the code after recording the mcause
|
||||||
|
|
||||||
accessfault_\MODE\():
|
accessfault_\MODE\():
|
||||||
// *** What do I have to do here?
|
|
||||||
j trapreturn_\MODE\()
|
j trapreturn_\MODE\()
|
||||||
|
|
||||||
addr_misaligned_\MODE\():
|
addr_misaligned_\MODE\():
|
||||||
@ -400,36 +396,67 @@ addr_misaligned_\MODE\():
|
|||||||
breakpt_\MODE\():
|
breakpt_\MODE\():
|
||||||
j trapreturn_\MODE\()
|
j trapreturn_\MODE\()
|
||||||
|
|
||||||
soft_interrupt_\MODE\():
|
s_soft_vector_\MODE\():
|
||||||
li x5, 0x7EC // write 0x7EC (looks like VEC) to the output before the mcause and extras to indicate that this trap was handled with a vector table.
|
csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
|
||||||
sd x5, 0(x16)
|
sd x5, -8(sp) // put x5 on the scratch stack before messing with it
|
||||||
|
li x5, 0x7EC01 // write 0x7ec01 (for "VEC"tored and 01 for the interrupt code)
|
||||||
|
j vectored_int_end_\MODE\()
|
||||||
|
|
||||||
|
m_soft_vector_\MODE\():
|
||||||
|
csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
|
||||||
|
sd x5, -8(sp) // put x5 on the scratch stack before messing with it
|
||||||
|
li x5, 0x7EC03 // write 0x7ec03 (for "VEC"tored and 03 for the interrupt code)
|
||||||
|
j vectored_int_end_\MODE\()
|
||||||
|
|
||||||
|
s_time_vector_\MODE\():
|
||||||
|
csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
|
||||||
|
sd x5, -8(sp) // put x5 on the scratch stack before messing with it
|
||||||
|
li x5, 0x7EC05 // write 0x7ec05 (for "VEC"tored and 05 for the interrupt code)
|
||||||
|
j vectored_int_end_\MODE\()
|
||||||
|
|
||||||
|
m_time_vector_\MODE\():
|
||||||
|
csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
|
||||||
|
sd x5, -8(sp) // put x5 on the scratch stack before messing with it
|
||||||
|
li x5, 0x7EC07 // write 0x7ec07 (for "VEC"tored and 07 for the interrupt code)
|
||||||
|
j vectored_int_end_\MODE\()
|
||||||
|
|
||||||
|
s_ext_vector_\MODE\():
|
||||||
|
csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
|
||||||
|
sd x5, -8(sp) // put x5 on the scratch stack before messing with it
|
||||||
|
li x5, 0x7EC09 // write 0x7ec09 (for "VEC"tored and 08 for the interrupt code)
|
||||||
|
j vectored_int_end_\MODE\()
|
||||||
|
|
||||||
|
m_ext_vector_\MODE\():
|
||||||
|
csrrw sp, \MODE\()scratch, sp // swap sp and scratch so we can use the scratch stack in the trap hanler without messing up sp's value or the stack itself.
|
||||||
|
sd x5, -8(sp) // put x5 on the scratch stack before messing with it
|
||||||
|
li x5, 0x7EC0B // write 0x7ec0B (for "VEC"tored and 0B for the interrupt code)
|
||||||
|
j vectored_int_end_\MODE\()
|
||||||
|
|
||||||
|
vectored_int_end_\MODE\():
|
||||||
|
sd x5, 0(x16) // store to signature to show vectored interrupts succeeded.
|
||||||
addi x6, x6, 8
|
addi x6, x6, 8
|
||||||
addi x16, x16, 8
|
addi x16, x16, 8
|
||||||
|
ld x5, -8(sp) // restore x5 before continuing to handle trap in case its needed.
|
||||||
|
j trap_stack_saved_\MODE\()
|
||||||
|
|
||||||
|
soft_interrupt_\MODE\():
|
||||||
la x28, 0x02000000 // Reset by clearing MSIP interrupt from CLINT
|
la x28, 0x02000000 // Reset by clearing MSIP interrupt from CLINT
|
||||||
sw x0, 0(x28)
|
sw x0, 0(x28)
|
||||||
j trap_unvectored_\MODE\()
|
j trapreturn_\MODE\()
|
||||||
|
|
||||||
time_interrupt_\MODE\():
|
time_interrupt_\MODE\():
|
||||||
li x5, 0x7EC
|
|
||||||
sd x5, 0(x16)
|
|
||||||
addi x6, x6, 8
|
|
||||||
addi x16, x16, 8
|
|
||||||
|
|
||||||
la x29, 0x02004000 // MTIMECMP register in CLINT
|
la x29, 0x02004000 // MTIMECMP register in CLINT
|
||||||
li x30, 0xFFFFFFFF
|
li x30, 0xFFFFFFFF
|
||||||
sd x30, 0(x29) // reset interrupt by setting mtimecmp to 0xFFFFFFFF
|
sd x30, 0(x29) // reset interrupt by setting mtimecmp to 0xFFFFFFFF
|
||||||
|
|
||||||
j trap_unvectored_\MODE\()
|
ld x1, -8(sp) // load return address from stack into ra (the address AFTER the jal to the faulting address)
|
||||||
|
j trapreturn_finished_\MODE\() // return to the code at ra value from before trap
|
||||||
|
|
||||||
ext_interrupt_\MODE\():
|
ext_interrupt_\MODE\():
|
||||||
li x5, 0x7EC
|
|
||||||
sd x5, 0(x16)
|
|
||||||
addi x6, x6, 8
|
|
||||||
addi x16, x16, 8
|
|
||||||
li x28, 0x10060000 // reset interrupt by clearing all the GPIO bits
|
li x28, 0x10060000 // reset interrupt by clearing all the GPIO bits
|
||||||
sw x0, 8(x28) // disable the first pin as an output
|
sw x0, 8(x28) // disable the first pin as an output
|
||||||
sw x0, 40(x28) // write a 0 to the first output pin (reset interrupt)
|
sw x0, 40(x28) // write a 0 to the first output pin (reset interrupt)
|
||||||
j trap_unvectored_\MODE\()
|
j trapreturn_\MODE\()
|
||||||
|
|
||||||
// Table of trap behavior
|
// Table of trap behavior
|
||||||
// lists what to do on each exception (not interrupts)
|
// lists what to do on each exception (not interrupts)
|
||||||
@ -455,6 +482,21 @@ exception_vector_table_\MODE\():
|
|||||||
.8byte segfault_\MODE\() // 14: reserved
|
.8byte segfault_\MODE\() // 14: reserved
|
||||||
.8byte trapreturn_\MODE\() // 15: store page fault
|
.8byte trapreturn_\MODE\() // 15: store page fault
|
||||||
|
|
||||||
|
.align 3 // aligns this data table to an 8 byte boundary
|
||||||
|
interrupt_vector_table_\MODE\():
|
||||||
|
.8byte segfault_\MODE\() // 0: reserved
|
||||||
|
.8byte s_soft_vector_\MODE\() // 1: instruction access fault // the zero spot is taken up by the instruction to skip this table.
|
||||||
|
.8byte segfault_\MODE\() // 2: reserved
|
||||||
|
.8byte m_soft_vector_\MODE\() // 3: breakpoint
|
||||||
|
.8byte segfault_\MODE\() // 4: reserved
|
||||||
|
.8byte s_time_vector_\MODE\() // 5: load access fault
|
||||||
|
.8byte segfault_\MODE\() // 6: reserved
|
||||||
|
.8byte m_time_vector_\MODE\() // 7: store access fault
|
||||||
|
.8byte segfault_\MODE\() // 8: reserved
|
||||||
|
.8byte s_ext_vector_\MODE\() // 9: ecall from S-mode
|
||||||
|
.8byte segfault_\MODE\() // 10: reserved
|
||||||
|
.8byte m_ext_vector_\MODE\() // 11: ecall from M-mode
|
||||||
|
|
||||||
.align 3
|
.align 3
|
||||||
trap_return_pagetype_table_\MODE\():
|
trap_return_pagetype_table_\MODE\():
|
||||||
.8byte 0xC // 0: kilopage has 12 offset bits
|
.8byte 0xC // 0: kilopage has 12 offset bits
|
||||||
@ -1051,9 +1093,20 @@ rvtest_data:
|
|||||||
RVTEST_DATA_END
|
RVTEST_DATA_END
|
||||||
|
|
||||||
.align 3 // align stack to 8 byte boundary
|
.align 3 // align stack to 8 byte boundary
|
||||||
bottom_of_stack:
|
stack_bottom:
|
||||||
.fill 1024, 4, 0xdeadbeef
|
.fill 1024, 4, 0xdeadbeef
|
||||||
top_of_stack:
|
stack_top:
|
||||||
|
|
||||||
|
.align 3
|
||||||
|
mscratch_bottom:
|
||||||
|
.fill 512, 4, 0xdeadbeef
|
||||||
|
mscratch_top:
|
||||||
|
|
||||||
|
.align 3
|
||||||
|
sscratch_bottom:
|
||||||
|
.fill 512, 4, 0xdeadbeef
|
||||||
|
sscratch_top:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RVMODEL_DATA_BEGIN
|
RVMODEL_DATA_BEGIN
|
||||||
|
Loading…
Reference in New Issue
Block a user