diff --git a/tests/testgen/PIPELINE.py b/tests/testgen/PIPELINE.py deleted file mode 100755 index 35d040763..000000000 --- a/tests/testgen/PIPELINE.py +++ /dev/null @@ -1,166 +0,0 @@ -#!/usr/bin/env python3 -################################## -# PIPELINE.py -# -# David_Harris@hmc.edu 27 October 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def twoscomp(a): - amsb = a >> (xlen-1) - alsbs = ((1 << (xlen-1)) - 1) & a - if (amsb): - asigned = a - (1<> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -instrs = ["ADD"] # "SUB", "XOR", "OR", "AND", "SLT", "SLTU", ] -author = "David_Harris@hmc.edu" -xlens = [32, 64] -numrand = 1000 - -# setup -seed(0) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - pathname = "../wally-riscv-arch-test/riscv-test-suite/rv" + str(xlen) + "i_m/I/" - fname = pathname + "src/PIPELINE.S" - testnum = 0 - - # print custom header part - f = open(fname, "w") -# r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("testgen_header.S", "r") - for line in h: - f.write(line) - - maxreg = 5 - for i in range(numrand): - instr = instrs[randint(0,len(instrs)-1)] - reg1 = randint(0,maxreg) - reg2 = randint(1,maxreg) - reg3 = randint(1,maxreg) - line = instr + " x" +str(reg3) + ", x" + str(reg1) + ", x" + str(reg2) + "\n" - f.write(line) - - for i in range(1,maxreg+1): - line = storecmd + " x" + str(i) + ", " + str(wordsize*(i-1)) + "(x8)\n" - f.write(line) - - # print directed and random test vectors - # for a in corners: - # for b in corners: - # writeVector(a, b, storecmd, xlen) - # for i in range(0,numrand): - # a = getrandbits(xlen) - # b = getrandbits(xlen) - # writeVector(a, b, storecmd, xlen) - - - # print footer - h = open("testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish -# lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" -# lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() -# r.close() - - - - diff --git a/tests/testgen/imperas/testgen_footer.S b/tests/testgen/imperas/testgen_footer.S deleted file mode 100644 index f7cc0b18b..000000000 --- a/tests/testgen/imperas/testgen_footer.S +++ /dev/null @@ -1,18 +0,0 @@ - # --------------------------------------------------------------------------------------------- - - RVTEST_IO_WRITE_STR(x31, "Test End\n") - - # --------------------------------------------------------------------------------------------- - - RV_COMPLIANCE_HALT - -RV_COMPLIANCE_CODE_END - -# Input data section. - .data - - -# Output data section. -RV_COMPLIANCE_DATA_BEGIN - -test_1_res: diff --git a/tests/testgen/imperas/testgen_header.S b/tests/testgen/imperas/testgen_header.S deleted file mode 100644 index 118042a5c..000000000 --- a/tests/testgen/imperas/testgen_header.S +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University -// Adapted from Imperas RISCV-TEST_SUITE -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, -// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -/////////////////////////////////////////// - -#include "riscv_test_macros.h" -#include "compliance_test.h" -#include "compliance_io.h" - -RV_COMPLIANCE_RV64M - -RV_COMPLIANCE_CODE_BEGIN - - - RVTEST_IO_INIT - RVTEST_IO_ASSERT_GPR_EQ(x31, x0, 0x00000000) - RVTEST_IO_WRITE_STR(x31, "Test Begin\n") - - # --------------------------------------------------------------------------------------------- - - #RVTEST_IO_WRITE_STR(x31, "# Test group 1\n") - - - # address for test results - la x6, test_1_res - \ No newline at end of file diff --git a/tests/testgen/privileged/README.md b/tests/testgen/privileged/README.md deleted file mode 100644 index 9b3faff6f..000000000 --- a/tests/testgen/privileged/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Privileged Test Generators - -Create a test generator in this folder with the name testgen-NAME.py. Then, to generate and compile these tests, use: - -```bash -sh run.sh NAME -``` - -For example, for `testgen-CAUSE.py`, we would run `sh run.sh CAUSE`. - -This bash file is super basic, so only allows for a single argument after the name. -Provide -sim as the second argument to simulate the compiled tests using wally. - -```bash -sh run.sh NAME -sim -``` - -To compile tests without running them in OVPsim, provide -c as the second argument - -```bash -sh run.sh NAME -c -``` - -The test generator also has a really nice feature that grabs the location of begin_signature after compiling the tests. For example, running `sh run.sh EPC` will output something like this at the end: - -```verilog -rv64p = '{ - 'rv64p/WALLY-MEPC', '5000', - 'rv64p/WALLY-SEPC', '4000' -}; - -rv32p = '{ - 'rv32p/WALLY-MEPC', '5000', - 'rv32p/WALLY-SEPC', '4000' -}; -``` \ No newline at end of file diff --git a/tests/testgen/privileged/run.sh b/tests/testgen/privileged/run.sh deleted file mode 100755 index 8509e77e6..000000000 --- a/tests/testgen/privileged/run.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash - -# -# Written 1 Mar 2021 by Domenico Ottolia (dottolia@hmc.edu) -# -# See README.md in this directory for more info -# - -clear -printf "\n\n#####\nStarting tests for $1\n#####\n\n" - -if [[ "$2" != "-simonly" ]] -then - cd $WALLY/testgen/privileged - $RISCV/riscv-python/bin/python3 "testgen-$1.py" - printf "\n\n#####\nRan testgen-$1.py Making...\n#####\n\n\n" - - if [[ "$2" == "-c" ]] - then - printf "\n\n###\nWARNING\nThis seems to not be outputting begin_signature at the moment... Probably won't work in modelsim...\n###\n\n\n" - cd $WALLY/imperas-riscv-tests/riscv-test-suite/rv64p/src - riscv64-unknown-elf-gcc -nostdlib -nostartfiles -march=rv64g "WALLY-$1".S -I../../../riscv-test-env -I../../../riscv-test-env/p -I../../../riscv-target/riscvOVPsimPlus -T../../../riscv-test-env/p/link.ld -o "../../../work/rv64p/WALLY-$1.elf" - cd $WALLY/imperas-riscv-tests/work/rv64p - riscv64-unknown-elf-objdump -d "WALLY-$1".elf > "WALLY-$1".elf.objdump - - elif [[ "$2" != "-nosim" ]] - then - cd $WALLY/imperas-riscv-tests - make privileged - - exe2memfile.pl work/*/*.elf - extractFunctionRadix.sh work/rv64p/*.elf.objdump - fi -fi - -if [[ "$2" == "-simonly" ]] -then - printf "\n\n###\nWARNING\nThis seems to not be outputting begin_signature at the moment... Probably won't work in modelsim...\n###\n\n\n" - cd $WALLY/imperas-riscv-tests/riscv-test-suite/rv64p/src - riscv64-unknown-elf-gcc -nostdlib -nostartfiles -march=rv64g "WALLY-$1".S -I../../../riscv-test-env -I../../../riscv-test-env/p -I../../../riscv-target/riscvOVPsimPlus -T../../../riscv-test-env/p/link.ld -o "../../../work/rv64p/WALLY-$1.elf" - cd $WALLY/imperas-riscv-tests/work/rv64p - riscv64-unknown-elf-objdump -d "WALLY-$1".elf > "WALLY-$1".elf.objdump - - # riscv64-unknown-elf-gcc -nostdlib -nostartfiles -march=rv64g "WALLY-CAUSE".S -I../../../riscv-test-env -I../../../riscv-test-env/p -I../../../riscv-target/riscvOVPsimPlus -T../../../riscv-test-env/p/link.ld -o "../../../work/rv64p/WALLY-CAUSE.elf" - # riscv64-unknown-elf-objdump -d "WALLY-CAUSE.elf" > "WALLY-CAUSE.elf.objdump" -fi - -if [[ "$2" == "-sim" || "$2" == "-simonly" ]] -then - printf "\n\n\n#####\nSimulating!\n#####\n\n" - cd $WALLY/sim - vsim -do wally-privileged.do -c -fi - -cd $WALLY/pipelined -printf "\n\n\n#####\nDone!\n#####\n\n" - -cd $WALLY/imperas-riscv-tests/work -for isa in "rv64p" "rv32p"; do - printf "$isa = '{" - COMMA="" - for file in "$isa"/*.elf.objdump; do - if [[ "$file" == *"$1"* ]]; then - RES=$(grep "^\s*0*8000.000 " $file) - RES=$(echo "$RES" | sed -r 's/^0*80+([0-9]+).+?$/\1/g') - file=$(echo "$file" | sed -r 's/^(.+?)\.elf\.objdump/\1/g') - printf "$COMMA\n '$file', '${RES}'" - COMMA="," - fi - done - printf "\n};\n\n" -done - -cd $WALLY/pipelined \ No newline at end of file diff --git a/tests/testgen/privileged/testgen-CAUSE.py b/tests/testgen/privileged/testgen-CAUSE.py deleted file mode 100755 index 12e4ef886..000000000 --- a/tests/testgen/privileged/testgen-CAUSE.py +++ /dev/null @@ -1,573 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-CAUSE.py (new) -# -# dottolia@hmc.edu 1 Mar 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -# -# -################################## -# DOCUMENTATION: -# -# The most up-to-date comments explaining what everything -# does and the layout of the privileged tests -# can be found in testgen-TVAL.py. This and -# other files do not have as many comments -# -################################### - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -#For instruction-fetch access or page-fault exceptions on systems with variable-length instructions, mtval will contain the virtual address of the portion of the instruction that caused the fault while mepc will point to the beginning of the instruction. - -def randRegs(): - reg1 = randint(1,20) - reg2 = randint(1,20) - reg3 = randint(1,20) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return str(reg1), str(reg2), str(reg3) - -def writeVectors(storecmd, returningInstruction): - global testnum - - if testMode == "m": - if fromMode == "m": - expectedCode = 7 if fromMode == "m" else 5 - clintAddr = "0x2004000" - - writeTest(storecmd, f, r, f""" - li x1, 0x8 - csrrs x0, {fromMode}status, x1 - - la x18, {clintAddr} - {loadcmd} x11, 0(x18) - li x1, 0x3fffffffffffffff - {storecmd} x1, 0(x18) - - li x1, 0x80 - csrrs x0, {fromMode}ie, x1 - - {storecmd} x0, 0(x18) - """, True, expectedCode, f""" - li x1, 0x80 - csrrc x0, {fromMode}ie, x1 - - li x1, 0x8 - csrrc x0, {fromMode}status, x1 - - la x18, {clintAddr} - li x1, -1 - {storecmd} x1, 0(x18) - """) - - # Page 6 of unpriviledged spec - # For both CSRRS and CSRRC, if rs1=x0, then the instruction will not write to the CSR at all, and so shall not cause any of the side effects - - # User Software Interrupt: True, 0 - # Supervisor Software Interrupt: True, 1 - # Machine Software Interrupt: True, 2 - - # When running run.sh CAUSE -c, everything works, but begin_signature doesn't appear - # 0x2000000 in wally - # writeTest(storecmd, f, r, f""" - # la x10, 0x2000000 #clint - - # li x1, 42 - # sw x1, 0(x10) - # """, True, 2, "m", f""" - # lw x0, 0(x10) - # """) - - # User Timer Interrupt: True, 4 - # Supervior timer interrupt: True, 5 - # Machine timer interrupt: True, 7 - - # if fromMode == "m": - # clintAddr = "0x2004000" - - # writeTest(storecmd, f, r, f""" - # # li x1, 0x8 - # # csrrs x0, mstatus, x1 - - # # li x1, 0x80 - # # csrrs x0, mie, x1 - - # # la x18, {clintAddr} - # # lw x11, 0(x18) - # # lw x12, 4(x18) - # # li x1, 1 - # # {storecmd} x1, 0(x18) - # nop - # sub x1, x2, x3 - # sub x2, x3, x4 - # sub x3, x4, x5 - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # """, True, 7, f""" - # # la x18, {clintAddr} - # # {storecmd} x11, 0(x18) - # """) - - #writeTest(storecmd, f, r, f""" - # li x2, 0x0 -# - # li x4, 0x80 - # csrrs x0, mie, x4 - - # la x2, 0x2004000 - - # li x3, 0x0 - # lw x5, 0(x2) - # sd x3, 0(x2) - # wfi - # """, True, 7, "m", f""" - # t - # """) - - # writeTest(storecmd, f, r, f""" - # csrr x18, mstatus - # # csrsi mstatus, 0b11111 - # csrr x19, mie - # li x17, 0b1111111111111 - # # csrs mie, x17 - - # la x10, 0x2004000 #clint timer - # li x1, 0 - - # lw x11, 0(x10) - # lw x12, 4(x10) - - # {storecmd} x0, 0(x10) - # {storecmd} x0, 4(x10) - # """, True, 7, "m", f""" - # {storecmd} x11, 0(x10) - # {storecmd} x12, 4(x10) - - # csrw mstatus, x18 - # csrw mie, x19 - # """) - - # User external input: True, 8 - # Supervisor external input: True, 9 - # Machine externa input: True, 11 - - # Instruction address misaligned: False, 0 - # looks like this is giving us an infinite loop for wally - # BUG: jumping to a misaligned instruction address doesn't cause an exception: we actually jump... - # Either that, or somehow at the end we always end up at 0x80004002 - # This is fine in OVPsim - # writeTest(storecmd, f, r, f""" - # li x1, 11 - # jr x1 # Something about this instruction is funky on wally, but fine with ovpsim - # """, False, 0) - - # Instruction access fault: False, 1 - - # Illegal Instruction - writeTest(storecmd, f, r, f""" - .fill 1, 4, 0 - """, False, 2) - - # Breakpoint - if returningInstruction != "ebreak": - writeTest(storecmd, f, r, f""" - ebreak - """, False, 3) - - # Load Address Misaligned - writeTest(storecmd, f, r, f""" - lw x0, 11(x0) - """, False, 4) - - # Load Access fault: False, 5 - - # Store/AMO address misaligned - writeTest(storecmd, f, r, f""" - sw x0, 11(x0) - """, False, 6) - - # Environment call from u-mode: only for when only M and U mode enabled? - # writeTest(storecmd, f, r, f""" - # ecall - # """, False, 8, "u") - if returningInstruction != "ecall": - if fromMode == "u": - writeTest(storecmd, f, r, f""" - ecall - """, False, 8) - - # Environment call from s-mode - if fromMode == "s": - writeTest(storecmd, f, r, f""" - ecall - """, False, 9) - - # Environment call from m-mode - if fromMode == "m": - writeTest(storecmd, f, r, f""" - ecall - """, False, 11) - - # Instruction page fault: 12 - # Load page fault: 13 - # Store/AMO page fault: 15 - - - - -def writeTest(storecmd, f, r, test, interrupt, code, resetHander = ""): - global testnum, storeAddressOffset - - expected = code - if(interrupt): - expected+=(1 << (xlen - 1)) - - # The code we actually change for our test - lines = f""" - csrr x25, {testMode}cause - """ - - # Boilerplate - # - # x28 is the address that our trap handler will jump to before returning. - # This is where we can do our actual tests. After we're done computing and storing - # what we want, we jump to x27, which continues with the trap handling code (look at the _j_x_trap_... labels) - # - lines = f""" - la x28, _jtest{testnum} - j _jdo{testnum} - - _jtest{testnum}: - {lines} - {resetHander} - jr x27 - - _jdo{testnum}: - li x25, 0xDEADBEA7 - li gp, 0 - {test} - """ - - # We expect x25 to be 0 always. This is because of the code we wrote at the begining - # of this function - - # Store the expected value of x25 to memory and in the .reference_output file - lines += f""" - {storecmd} x25, {testnum * wordsize}(x6) - """ - - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -author = "dottolia@hmc.edu" -xlens = [32, 64] -testCount = 8; - -# setup -# Change this seed to a different constant value for every test -seed(0xC363DAEB9193AB45) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - loadcmd = "lw" - wordsize = 4 - else: - storecmd = "sd" - loadcmd = "ld" - wordsize = 8 - - # testMode can be m, s, and u. User mode traps are deprecated, so this should likely just be ["m", "s"] - for testMode in ["m", "s"]: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + testMode.upper() + "CAUSE" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - storeAddressOffset = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line.replace("RV_COMPLIANCE_RV64M", "RV_COMPLIANCE_RV" + str(xlen) + "M")) - # f.write(f""" - # #include "riscv_test_macros.h" - # #include "compliance_test.h" - # #include "compliance_io.h" - - # 0000000080000000 <_start>: - # 80000000: 0480006f j 80000048 - # """) - - # We need to leave at least one bit in medeleg unset so that we have a way to get - # back to machine mode when the tests are complete (otherwise we'll only ever be able - # to get up to supervisor mode). - # - # So, we define a returning instruction which will be used to cause the exception that - # brings us into machine mode. The bit for this returning instruction is NOT set in - # medeleg. However, this also means that we can't test that instruction. So, we have - # two different returning instructions. - # - # Current code is written to only support ebreak and ecall. - # - # For testgen-TVAL, we don't need to test ebreak, so we can use that as the sole - # returning instruction. For others, like testgen-CAUSE, we'll need to put - # both ebreak and ecall here. - for returningInstruction in ["ebreak"]: - - # All registers used: - # x30: set to 1 if we should return to & stay in machine mode after trap, 0 otherwise - # ... - # x28: address trap handler should jump to for the test - # x27: address the test should return to after the test - # ... - # x25: value to write to memory - # ... - # x20: intermediate value in trap handler. Don't overwrite this! - # x19: mtvec old value - # x18: medeleg old value - # x17: sedeleg old value (currently unused — user mode traps deprecated) - # x16: mideleg old value - # ... - # x10 - x14 can be freely written - # ... - # x7: copy of x6. Increment this instead of using an offset on x6. - # this allows us to create more than 2048/wordlen tests. - # This is the address we write results to - # x6: Starting address we should write expected results to - # ... - # x1 - x5 can be freely written - - - - # Set up x7 and store old value of mtvec - lines = f""" - add x7, x6, x0 - csrr x19, mtvec - - slli a0,a0,0x1f - slli a0,a0,0x1e - slli a0,a0,0x1d - slli a0,a0,0x1c - slli a0,a0,0x1b - slli a0,a0,0x1a - slli a0,a0,0x19 - """ - - # Not used — user mode traps are deprecated - if testMode == "u": - lines += f""" - csrr x17, sedeleg - li x9, {"0b1100000000" if testMode == "u" else "0b0000000000"} - csrs sedeleg, x9 - """ - - # Code that will jump to the test (x28 is set in writeTest above) - testJumpCode = f""" - auipc x27, 0 - addi x27, x27, 12 - jr x28 - """ - - # Code for handling traps in different modes - # Some comments are inside of the below strings (prefixed with a #, as you might expected) - lines += f""" - # Reset x30 to 0 so we can run the tests. We'll set this to 1 when tests are completed so we stay in machine mode - li x30, 0 - - # Set up - la x1, _j_m_trap_{returningInstruction} - csrw mtvec, x1 - la x1, _j_s_trap_{returningInstruction} - csrw stvec, x1 - la x1, _j_u_trap_{returningInstruction} - # csrw utvec, x1 # user mode traps are not supported - - # Start the tests! - j _j_t_begin_{returningInstruction} - - # Machine mode traps - _j_m_trap_{returningInstruction}: - {testJumpCode if testMode == "m" else "li x25, 0xBAD00003"} - - csrrs x20, mepc, x0 - addi x20, x20, 4 - csrrw x0, mepc, x20 - bnez x30, _j_all_end_{returningInstruction} - mret - - # Supervisor mode traps - _j_s_trap_{returningInstruction}: - {testJumpCode if testMode == "s" else "li x25, 0xBAD00001"} - - csrrs x20, sepc, x0 - addi x20, x20, 4 - csrrw x0, sepc, x20 - bnez x30, _j_goto_machine_mode_{returningInstruction} - sret - - # Unused: user mode traps are no longer supported - _j_u_trap_{returningInstruction}: - {testJumpCode if testMode == "u" else "li x25, 0xBAD00000"} - - csrrs x20, uepc, x0 - addi x20, x20, 4 - csrrw x0, uepc, x20 - bnez x30, _j_goto_supervisor_mode_{returningInstruction} - uret - - # Currently unused. Just jumps to _j_goto_machine_mode. If you actually - # want to implement this, you'll likely need to reset sedeleg here - # and then cause an exception with {returningInstruction} (based on my intuition. Try that first, but I could be missing something / just wrong) - _j_goto_supervisor_mode_{returningInstruction}: - j _j_goto_machine_mode_{returningInstruction} - - _j_goto_machine_mode_{returningInstruction}: - li x30, 1 # This will cause us to branch to _j_all_end_{returningInstruction} in the machine trap handler, which we'll get into by invoking... - {returningInstruction} # ... this instruction! - - # Run the actual tests! - _j_t_begin_{returningInstruction}: - """ - - fromModeOptions = ["m", "s", "u"] if testMode == "m" else (["s", "u"] if testMode == "s" else ["u"]) - - # We don't want to delegate our returning instruction. Otherwise, we'll have no way of getting - # back to machine mode at the end! (and we need to be in machine mode to complete the tests) - medelegMask = "0b1111111111110111" if returningInstruction == "ebreak" else "0b1111000011111111" - - # Set medeleg and mideleg - lines += f""" - csrr x18, medeleg - li x9, {medelegMask if testMode == "s" or testMode == "u" else "0"} - csrw medeleg, x9 - - csrr x16, mideleg - li x9, {"0xffffffff" if testMode == "s" or testMode == "u" else "0"} - csrw mideleg, x9 - """ - - f.write(lines) - - for fromMode in fromModeOptions: - lines = "" - - # Code to bring us down to supervisor mode - if fromMode == "s" or fromMode == "u": - lines += f""" - li x1, 0b110000000000 - csrrc x31, mstatus, x1 - li x1, 0b0100000000000 - csrrs x31, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrw mepc, x1 - mret - - # We're now in supervisor mode... - """ - - # Code to bring us down to user mode - if fromMode == "u": - lines += f""" - - li x1, 0b110000000000 - csrrc x31, sstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the sret instruction - csrw sepc, x1 - sret - - # We're now in user mode... - """ - - f.write(lines) - for i in range(0,testCount): - writeVectors(storecmd, returningInstruction) - - - # Very end of test. Bring us back up to machine mode - # We set x30 to 1, which will cause us to branch to _j_all_end in the - # machine mode trap handler, before executing the mret instruction. This will - # make us stay in machine mode. - # - # If we're currently in user mode, this will first bump us up to the supervisor mode - # trap handler, which will call returningInstruction again before it's sret instruction, - # bumping us up to machine mode - # - # Get into the trap handler by running returningInstruction (either an ecall or ebreak) - f.write(f""" - li x30, 1 - li gp, 0 - {returningInstruction} - _j_all_end_{returningInstruction}: - - # Reset trap handling csrs to old values - csrw mtvec, x19 - csrw medeleg, x18 - csrw mideleg, x16 - """) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() diff --git a/tests/testgen/privileged/testgen-CSR-PERMISSIONS.py b/tests/testgen/privileged/testgen-CSR-PERMISSIONS.py deleted file mode 100755 index fadff0a36..000000000 --- a/tests/testgen/privileged/testgen-CSR-PERMISSIONS.py +++ /dev/null @@ -1,248 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-CSR-PERMISSIONS.py -# -# dottolia@hmc.edu 1 May 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -# Verify that an illegal instruction is raised when trying to write to csrs of a higher privilege -# -################################## -# DOCUMENTATION: -# -# Most of the comments explaining what everything -# does and the layout of the privileged tests -# can be found in this file -# -################################### - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -testCount = 2 - -def writeVectors(storecmd, testMode): - global testnum - - csrs = ["status", "edeleg", "ideleg", "ie", "tvec", "counteren", "scratch", "epc", "cause", "tval", "ip"] - if testMode == "s": - csrs.append("atp") - #csrs = ["status"] - for csrStart in csrs: - for i in range(0, testCount): - a = 1 - - csr = testMode + csrStart - - # only check for CSR changes if testing machine-mode registers - csrWillChange = testMode == "s" or csrStart == "status" or csrStart == "epc" or csrStart == "cause" or csrStart == "tval" - newCSRValue = "" if testMode == "s" else "csrr x24, " + csr - - f.write(f""" - li x13, 1 - """) - - fromModeOptions = ["s", "u"] if testMode == "m" else ["u"] - for fromMode in fromModeOptions: - label = f"""{fromMode}_{csr}_{testnum}""" - endlabel = f"""_j_end_{label}""" - # This is all from testgen-TVAL.py, within the for loop on returningInstruction - # - # x25: mepc value - # x24: new csr value - # x23: original csr value - lines = f""" - li x30, 0 - la x1, _m_trap_from_{label} - csrw mtvec, x1 - - csrr x23, {csr} - - j _j_test_{label} - - _m_trap_from_{label}: - bnez x30, {endlabel} - - csrr x25, mcause - {newCSRValue} - - csrrs x20, mepc, x0 - addi x20, x20, 4 - csrrw x0, mepc, x20 - - mret - - _j_test_{label}: - """ - - lines += f""" - li x1, 0b110000000000 - csrrc x0, mstatus, x1 - li x1, 0b0100000000000 - csrrs x0, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrw mepc, x1 - mret - - # We're now in supervisor mode... - """ - - # Code to bring us down to user mode - if fromMode == "u": - lines += f""" - - li x1, 0b110000000000 - csrrc x0, sstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the sret instruction - csrw sepc, x1 - sret - - # We're now in user mode... - """ - - f.write(lines) - - - writeTest(storecmd, f, r, f"""csrrw x1, {csr}, x0""", csrWillChange) - writeTest(storecmd, f, r, f"""csrrw x0, {csr}, x13""", csrWillChange) - writeTest(storecmd, f, r, f"""csrrwi x0, {csr}, {a}""", csrWillChange) - if a != 0: - writeTest(storecmd, f, r, f"""csrrs x0, {csr}, x13""", csrWillChange) - writeTest(storecmd, f, r, f"""csrrc x0, {csr}, x13""", csrWillChange) - writeTest(storecmd, f, r, f"""csrrsi x0, {csr}, {a}""", csrWillChange) - writeTest(storecmd, f, r, f"""csrrci x0, {csr}, {a}""", csrWillChange) - - f.write(f""" - li x30, 1 - ebreak - {endlabel}: - """) - - - - -def writeTest(storecmd, f, r, test, csrWillChange): - global testnum - - test = f""" - _jdo{testnum}: - li x25, 0xDEADBEA7 - - {test} - - {storecmd} x25, 0(x7) - addi x7, x7, {wordsize} - """ - - # We expect x25 to always be an illegal instruction - expected = 2 - - f.write(test) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - - if not csrWillChange: - # We expect x24 should be equal to x23 - expected = 0 - - f.write(f""" - sub x25, x24, x23 - {storecmd} x25, 0(x7) - addi x7, x7, {wordsize} - """) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -author = "dottolia@hmc.edu" -xlens = [32, 64] - -# setup -# Change this seed to a different constant value for every test -seed(0xC363DAEB9193AB45) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - - for testMode in ["m", "s"]: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-CSR-PERMISSIONS-" + testMode.upper() - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - storeAddressOffset = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - f.write(f""" - add x7, x6, x0 - csrr x19, mtvec - """) - - writeVectors(storecmd, testMode) - - f.write(f""" - csrw mtvec, x19 - """) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - - diff --git a/tests/testgen/privileged/testgen-DELEG.py b/tests/testgen/privileged/testgen-DELEG.py deleted file mode 100755 index 4d7a99716..000000000 --- a/tests/testgen/privileged/testgen-DELEG.py +++ /dev/null @@ -1,371 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-CAUSE.py -# -# dottolia@hmc.edu 27 Apr 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -# -# -################################## -# DOCUMENTATION: -# Most of the comments explaining what everything -# does can be found in testgen-TVAL.py -################################### - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -#For instruction-fetch access or page-fault exceptions on systems with variable-length instructions, mtval will contain the virtual address of the portion of the instruction that caused the fault while mepc will point to the beginning of the instruction. - -def randRegs(): - reg1 = randint(1,20) - reg2 = randint(1,20) - reg3 = randint(1,20) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return str(reg1), str(reg2), str(reg3) - -def writeVectors(storecmd): - global testnum - - # User Software Interrupt: True, 0 - # Supervisor Software Interrupt: True, 1 - # Machine Software Interrupt: True, 2 - - writeTest(storecmd, f, r, "timer-interrupt", True, -1) # code determined inside of writeTest - - # User external input: True, 8 - # Supervisor external input: True, 9 - # Machine externa input: True, 11 - - # Instruction address misaligned: False, 0 - - # Instruction access fault: False, 1 - - # Illegal Instruction - writeTest(storecmd, f, r, f""" - .fill 1, 4, 0 - """, False, 2) - - # Breakpoint - writeTest(storecmd, f, r, "ebreak", False, 3) - - # Load Address Misaligned - writeTest(storecmd, f, r, f""" - lw x0, 11(x0) - """, False, 4) - - # # Load Access fault: False, 5 - # TODO: THIS NEEDS TO BE IMPLEMENTED - - # # Store/AMO address misaligned - writeTest(storecmd, f, r, f""" - sw x0, 11(x0) - """, False, 6) - - # Breakpoint: codes 8, 9, 11 - writeTest(storecmd, f, r, "ecall", False, -1) # code determined inside of writeTest - - # Instruction page fault: 12 - # TODO: THIS NEEDS TO BE IMPLEMENTED - - # Load page fault: 13 - # TODO: THIS NEEDS TO BE IMPLEMENTED - - # Store/AMO page fault: 15 - # TODO: THIS NEEDS TO BE IMPLEMENTED - - - #writeTest(storecmd, f, r, "ecall", False, 11, "m") - -def writeTest(storecmd, f, r, test, interrupt, code, resetHander = ""): - global testnum - global testMode - global isInterrupts - - beforeTest = "" - - if interrupt != isInterrupts: - return - - isTimerInterruptTest = test == "timer-interrupt" - delegateType = "i" if interrupt else "e" - for mode in (["m", "s", "u"] if testMode == "m" else ["s", "u"]): - if isTimerInterruptTest: - clintAddr = "0x2004000" - - if mode == "m": - code = 7 - test = f""" - la x18, {clintAddr} - {storecmd} x0, 0(x18) - """ - - elif mode == "s": - code = 5 - test = "" - else: - code = 4 - test = "" - - ieMask = 1 << code - statusMask = 0b1010 - - beforeTest = f""" - li x1, {statusMask} - csrrs x0, mstatus, x1 - - li x1, 0b0010 - csrrs x0, sstatus, x1 - - la x18, {clintAddr} - lw x11, 0(x18) - li x1, 0x7fffffffffffffff - {storecmd} x1, 0(x18) - - li x1, {ieMask} - csrrs x0, mie, x1 - - li x1, {ieMask} - csrrs x0, sie, x1 - """ - - resetHander = f""" - #li x1, 0x80 - #csrrc x0, sie, x1 - - li x1, {ieMask} - csrrc x0, mie, x1 - - li x1, {ieMask} - csrrc x0, sie, x1 - - li x1, {statusMask} - csrrc x0, mstatus, x1 - - li x1, 0b0010 - csrrc x0, sstatus, x1 - - la x18, {clintAddr} - {storecmd} x11, 0(x18) - """ - - if mode == "s": - beforeTest += f""" - li x1, {ieMask} - csrrs x0, sip, x1 - """ - - resetHander += f""" - li x1, {ieMask} - csrrc x0, sip, x1 - """ - - elif test == "ecall": - if mode == "m": - code = 11 - elif mode == "s": - code = 9 - else: - code = 8 - - mask = 1 << code - for delegated in [True, False]: - labelSuffix = testnum - - f.write(f""" - _start_{labelSuffix}: - - la x1, _j_m_trap_{labelSuffix} - csrw mtvec, x1 - la x1, _j_s_trap_{labelSuffix} - csrw stvec, x1 - - j _j_test_{labelSuffix} - - _j_m_trap_{labelSuffix}: - {resetHander} - li x25, 3 - - csrr x1, mepc - addi x1, x1, 4 - csrrw x0, mepc, x1 - bnez x30, _j_finished_{labelSuffix} - mret - - _j_s_trap_{labelSuffix}: - {resetHander} - li x25, 1 - - csrr x1, sepc - addi x1, x1, 4 - csrrw x0, sepc, x1 - bnez x30, _j_goto_machine_mode_{labelSuffix} - sret - - _j_goto_machine_mode_{labelSuffix}: - li x30, 1 - {"ebreak" if test is not "ebreak" else "ecall"} - - _j_test_{labelSuffix}: - """) - - original = f""" - li x1, {mask if delegated else 0} - csrw m{delegateType}deleg, x1 - """ - - if mode != "m": - lines = f""" - {original} - - {beforeTest} - - li x1, 0b110000000000 - csrrc x31, {testMode}status, x1 - li x1, 0b{"01" if mode == "s" else "00"}00000000000 - csrrs x31, {testMode}status, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the ret instruction - csrrw x27, {testMode}epc, x1 - {testMode}ret - - # From {testMode}, we're now in {mode} mode... - {test} - """ - - writeTestInner(storecmd, f, r, lines, 1 if delegated else 3) - - f.write(f""" - j _j_goto_machine_mode_{labelSuffix} - """) - - else: - lines = f""" - {original} - {beforeTest} - {test} - """ - writeTestInner(storecmd, f, r, lines, 3) - - f.write(f""" - _j_finished_{labelSuffix}: - li x30, 0 - """) - - -def writeTestInner(storecmd, f, r, lines, expected): - global testnum - - lines = f""" - li x25, 0xDEADBEA7 - {lines} - """ - - lines += storecmd + " x25, " + str(testnum * wordsize) + "(x6)\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -author = "dottolia@hmc.edu" -xlens = [32, 64] -numrand = 1; - -# setup -seed(0xD0C0_D0C0_D0C0_D0C0) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - - for testMode in ["m"]: - for isInterrupts in [True, False]: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + testMode.upper() + ("I" if isInterrupts else "E") + "DELEG" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - # All registers used: - # x19: mtvec old value - # x18: medeleg old value - # x17: mideleg old value - - f.write(f""" - add x7, x6, x0 - csrr x19, mtvec - csrr x18, medeleg - csrr x17, medeleg - """) - - testnum = 0 - for i in range(0, 2): - writeVectors(storecmd) - - f.write(f""" - csrw mtvec, x19 - csrw medeleg, x18 - csrw mideleg, x17 - """) - - # if we're in supervisor mode, this leaves the ebreak instruction untested (we need a way to) - # get back to machine mode. - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - diff --git a/tests/testgen/privileged/testgen-EPC.py b/tests/testgen/privileged/testgen-EPC.py deleted file mode 100755 index c9b5ad0e0..000000000 --- a/tests/testgen/privileged/testgen-EPC.py +++ /dev/null @@ -1,263 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-CAUSE.py -# -# dottolia@hmc.edu 1 Mar 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -#For instruction-fetch access or page-fault exceptions on systems with variable-length instructions, mtval will contain the virtual address of the portion of the instruction that caused the fault while mepc will point to the beginning of the instruction. - -def randRegs(): - reg1 = randint(1,20) - reg2 = randint(1,20) - reg3 = randint(1,20) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return str(reg1), str(reg2), str(reg3) - -def writeVectors(storecmd): - global testnum - - # Load address misaligned - writeTest(storecmd, f, r, f""" - ecall - """, False, 9) - - -def writeTest(storecmd, f, r, test, interrupt, code, resetHander = ""): - global testnum - global testMode - - nops = "" - for i in range(0, randint(1, 16)): - nops+="nop\n" - - lines = f""" - {nops} - li x25, 0xDEADBEA7 - auipc x26, 0 - addi x26, x26, 8 - {test} - - _jend{testnum}: - - {storecmd} x25, 0(x7) - addi x7, x7, {wordsize} - """ - - f.write(lines) - - expected = 0 - - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 -################################## -# main body -################################## - -# change these to suite your tests -author = "dottolia@hmc.edu" -xlens = [32, 64] -numrand = 64; - -# setup -seed(0x9365DDEB9173AB42) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - - corners = [ - 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1 - ] - - for testMode in ["m", "s"]: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + testMode.upper() + "EPC" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - # All registers used: - # x30: set to 1 if we should return to & stay in machine mode after trap, 0 otherwise - # ... - # x26: expected epc value - # x25: value to write to memory - # ... - # x19: mtvec old value - # x18: medeleg old value - # x17: sedeleg old value - - - lines = f""" - add x7, x6, x0 - csrr x19, mtvec - - csrr x18, medeleg - li x9, {"0b1100000000" if testMode == "s" or testMode == "u" else "0b0000000000"} - csrs medeleg, x9 - - """ - - if testMode == "u": - lines += f""" - csrr x17, sedeleg - li x9, {"0b1100000000" if testMode == "u" else "0b0000000000"} - csrs sedeleg, x9 - """ - - lines += f""" - - li x30, 0 - - la x1, _j_m_trap - csrw mtvec, x1 - la x1, _j_s_trap - csrw stvec, x1 - la x1, _j_u_trap - csrw utvec, x1 - j _j_t_begin - - _j_m_trap: - csrrs x1, mepc, x0 - {"sub x25, x26, x1" if testMode == "m" else "li x25, 0xBAD00003"} - - addi x1, x1, 4 - csrrw x0, mepc, x1 - bnez x30, _j_all_end - mret - - _j_s_trap: - csrrs x1, sepc, x0 - {"sub x25, x26, x1" if testMode == "s" else "li x25, 0xBAD00001"} - - addi x1, x1, 4 - csrrw x0, sepc, x1 - bnez x30, _j_goto_machine_mode - sret - - _j_u_trap: - csrrs x1, uepc, x0 - {"sub x25, x26, x1" if testMode == "u" else "li x25, 0xBAD00000"} - - addi x1, x1, 4 - csrrw x0, uepc, x1 - bnez x30, _j_goto_supervisor_mode - uret - - _j_goto_supervisor_mode: - csrw sedeleg, x17 - j _j_goto_machine_mode - - _j_goto_machine_mode: - csrw medeleg, x18 - li x30, 1 - ecall - - _j_t_begin: - """ - - fromModeOptions = ["m", "s", "u"] if testMode == "m" else (["s", "u"] if testMode == "s" else ["u"]) - - f.write(lines) - - for fromMode in fromModeOptions: - lines = "" - - if fromMode == "s" or fromMode == "u": - lines += f""" - li x1, 0b110000000000 - csrrc x31, mstatus, x1 - li x1, 0b0100000000000 - csrrs x31, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrw mepc, x1 - mret - - # We're now in supervisor mode... - """ - - if fromMode == "u": - lines += f""" - - li x1, 0b110000000000 - csrrc x31, sstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the sret instruction - csrw sepc, x1 - sret - - # We're now in user mode... - """ - - # print directed and random test vectors - f.write(lines) - for i in range(0,numrand): - writeVectors(storecmd) - - - f.write(f""" - li x30, 1 - ecall - _j_all_end: - - csrw mtvec, x19 - """) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() diff --git a/tests/testgen/privileged/testgen-IE.py b/tests/testgen/privileged/testgen-IE.py deleted file mode 100755 index 032d719d2..000000000 --- a/tests/testgen/privileged/testgen-IE.py +++ /dev/null @@ -1,406 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-IE.py -# -# ushakya@hmc.edu 31 March 2021 -# Modified: 4 April 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def writeTrapHandlers(storecmd, mode): - global testnum - [reg1, reg2, reg3] = [30, 29, 28] - [reg4, reg5] = [27, 26] - if mode == "M": - lines = "\n# Trap Handler: Machine Timer Interupt\n" - lines += "_timerM_trap_handler:\n" - lines += "li x" + str(reg1) + ", MASK_XLEN(0xFFFF)\n" - lines += "la x" + str(reg2) + ", 0x2004000\n" - lines += str(storecmd) + " x" + str(reg1) + ", 0(x" + str(reg2) + ")\n" - lines += "csrrc x" + str(reg3) + ", mepc, x0\n" - lines += "addi x"+ str(reg3) + ", x" + str(reg3) + ", MASK_XLEN(0x4)\n" - lines += "csrrw x0, mepc, x" + str(reg3) + "\n" - # clear machine timer interupt enable bit in mie - lines += "li x" + str(reg4) + ", MASK_XLEN(" + str(0x80) + ")\n" - lines += "csrrc x0, mie, x" + str(reg4) + "\n" - lines += "mret\n" - elif mode == "S": - lines = "\n# Trap Handler: Supervisor Timer Interupt\n" - lines += "_timerS_trap_handler:\n" - lines += "li x" + str(reg4) + ", MASK_XLEN(0x20)\n" - lines += "csrrc x0, mip, x" + str(reg4) + "\n" - lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - lines += "mret\n" - - #lines += "\n# Trap Handler: User Timer Interupt\n" - #lines += "_timerU_trap_handler:\n" - #lines += "li x" + str(reg4) + ", MASK_XLEN(0x10)\n" - #lines += "csrrc x0, mip, x" + str(reg4) + "\n" - #lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - #lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - #lines += "mret\n" - - #lines += "\n# Trap Handler: Machine Software Interupt\n" - #lines += "_softwareM_trap_handler:\n" - #lines += "li x" + str(reg1) + ", MASK_XLEN(0x0)\n" # clear MSIP bit in CLINT - #lines += "la x" + str(reg2) + ", 0x2000000\n" - #lines += str(storecmd) + " x" + str(reg1) + ", 0(x" + str(reg2) + ")\n" - ##lines += "csrrs x" + str(reg3) + ", mepc, x0\n" - #lines += "addi x"+ str(reg3) + ", x" + str(reg3) + ", MASK_XLEN(0x4)\n" - #lines += "csrrw x0, mepc, x" + str(reg3) + "\n" - #lines += "mret\n" - - """lines += "\n# Trap Handler: Supervisor Software Interupt\n" - lines += "_softwareS_trap_handler:\n" - lines += "li x" + str(reg4) + ", MASK_XLEN(0x2)\n" - lines += "csrrc x0, mip, x" + str(reg4) + "\n" - lines += "csrrs x" + str(reg5) + ", mepc, x0\n" - lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - lines += "csrrw x0, mepc, x" + str(reg5) + "\n" - lines += "mret\n" -""" - #lines += "\n# Trap Handler: User Software Interupt\n" - #lines += "_softwareU_trap_handler:\n" - #lines += "li x" + str(reg4) + ", MASK_XLEN(0x1)\n" - #lines += "csrrc x0, mip, x" + str(reg4) + "\n" - #lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - #lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - #lines += "mret\n" - - #lines += "\n# Trap Handler: Machine External Interupt\n" - #lines += "_externalM_trap_handler:\n" - #lines += "li x" + str(reg1) + ", MASK_XLEN(0x0)\n" # clear MSIP bit in CLINT - #lines += "la x" + str(reg2) + ", 0x2000000\n" - #lines += str(storecmd) + " x" + str(reg1) + ", 0(x" + str(reg2) + ")\n" - #lines += "csrrw x" + str(reg3) + ", mepc, x0\n" - #lines += "addi x"+ str(reg3) + ", x" + str(reg3) + ", MASK_XLEN(0x4)\n" - #lines += "mret\n" - - #lines += "\n# Trap Handler: Supervisor External Interupt\n" - #lines += "_externalS_trap_handler:\n" - #lines += "li x" + str(reg4) + ", MASK_XLEN(0x200)\n" - #lines += "csrrc x0, mip, x" + str(reg4) + "\n" - #lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - #lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - #lines += "mret\n" - - #lines += "\n# Trap Handler: User External Interupt\n" - #lines += "_externalU_trap_handler:\n" - #lines += "li x" + str(reg4) + ", MASK_XLEN(0x100)\n" - #lines += "csrrc x0, mip, x" + str(reg4) + "\n" - #lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - #lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - #lines += "mret\n" - - f.write(lines) - -def getInteruptEnableValues(): - if test == "timerM": - mstatusE = 0x8 - mieE = 0x80 - elif test == "timerS": - mstatusE = 0x2 - mieE = 0x20 - elif test == "timerU": - mstatusE = 0x1 - mieE = 0x10 - elif test == "softwareM": - mstatusE = 0x8 - mieE = 0x8 - elif test == "softwareS": - mstatusE = 0x2 - mieE = 0x2 - elif test == "softwareU": - mstatusE = 0x1 - mieE = 0x1 - elif test == "externalM": - mstatusE = 0x8 - mieE = 0x800 - elif test == "externalS": - mstatusE = 0x2 - mieE = 0x200 - elif test == "externalU": - mstatusE = 0x1 - mieE = 0x100 - return [mstatusE, mieE] - -def getMcause(): - b = 1 << (xlen-1) - if test == "timerM": - b = b + 0x7 - elif test == "timerS": - b = b + 0x5 - elif test == "timerU": - b = b + 0x4 - elif test == "softwareM": - b = b + 0x3 - elif test == "softwareS": - b = b + 0x1 - elif test == "softwareU": - b = b - elif test == "externalM": - b = b + 0xB - elif test == "externalS": - b = b + 0x9 - elif test == "externalU": - b = b + 0x8 - return b - -def writeVectors(a, xlen, storecmd): - global testnum - - # Registers used: - # x13 ---> read mcause value - # x12 ---> save old value of mtvec - # x8 ---> holds mieE - # x5 ---> holds value of trap handler - # x3 ---> holds mstatusE - # remaining registers (not used by mode management) are free to be used by tests - - [reg2, reg3] = [2, 3] - [reg5, reg8] = [5, 8] - [reg10, reg11, reg12] = [10, 11, 12] - [reg13, reg14, reg15] = [13, 14, 15] - - lines = f"\n# Testcase {testnum}: {test} Interupt\n" - - # mcause code - expected = getMcause() - - [mstatusE, mieE] = getInteruptEnableValues() - # ensure interupt enable bit in mie is low - lines += "li x" + str(reg8) + ", MASK_XLEN(" + formatstr.format(mieE) + ")\n" - lines += "csrrc x0, mie, x" + str(reg8) + "\n" - - # set interupt enable bit in mstatus - lines += "li x" + str(reg3) + ", MASK_XLEN(" + formatstr.format(mstatusE) + ")\n" - lines += "csrrs x0, mstatus, x" + str(reg3) + "\n" - - # Save and set trap handler address for interrupt - lines += "la x" + str(reg5) + ", _" + test + "_trap_handler\n" - - # save orignal mtvec address - lines += "csrrw x" + str(reg12) + ", mtvec, x" + str(reg5) + "\n" - - # cause timer interupt - if test == "timerM": - - # load MTIMECMP register address - lines += "la x" + str(reg2) + ", 0x2004000\n" - - # to be stored in MTIMECMP - lines += "li x" + str(reg10) + ", MASK_XLEN(0)\n" - - # save old value of mtimecmp and then set mtimecmp to zero - if xlens == 64: - lines += "lw x" + str(reg11) + ", 0(x" + str(reg2) + ")\n" - lines += str(storecmd) + " x" + str(reg10) + ", 0(x" + str(reg2) + ")\n" - - elif xlen == 32: - lines += "lw x" + str(reg11) + ", 0(x" + str(reg2) + ")\n" - lines += str(storecmd) + " x" + str(reg10) + ", 0(x" + str(reg2) + ")\n" - lines += str(storecmd) + " x" + str(reg10) + ", 4(x" + str(reg2) + ")\n" - - elif test == "timerS": - lines += "li x" + str(reg3) + ", MASK_XLEN(0x20)\n" - lines += "csrrs x0, mip, x" + str(reg3) + "\n" - - # cause software interupt - if test == "softwareM": - lines += "la x" + str(reg8) + ", 0x2000000\n" # Write to the MSIP bit in CLINT - lines += "li x" + str(reg11) + ", MASK_XLEN(0x1)\n" - lines += str(storecmd) + " x" + str(reg11) + ", 0(x" + str(reg8) + ")\n" - elif test == "softwareS": - lines += "li x" + str(reg3) + ", MASK_XLEN(0x2)\n" - lines += "csrrs x0, mip, x" + str(reg3) + "\n" - - - # set timer interupt enable bit in mie - lines += "csrrs x0, mie, x" + str(reg8) + "\n" - - # wait for interupt to be taken - lines += "nop\nnop\n" - - lines += "csrrs " + " x" + str(reg13) + ", mcause, x0\n" - - # reset mtvec - lines += "csrrw x0, mtvec, x" + str(reg12) + "\n" - - lines += storecmd + " x" + str(reg13) + ", " + str(wordsize*testnum) + "(x6)\n" - lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, x" + str(reg13) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -tests = ["timerM"] #, "timerM", "timerS", "softwareM", "softwareS"] -author = "ushakya@hmc.edu" -xlens = [64] #, 32] -modes = ["M"]#, "S"] -numrand = 100; - -# setup -seed(0) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - for mode in modes: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + mode + "IE" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - line = "\n" - # Registers used for dropping down to supervisor mode: - # x30 ---> set to 1 if we should return to & stay in machine mode after trap, 0 otherwise - # x20 ---> hold address of _j_all_end_{returningInstruction} - # x19 ---> save old value of mtvec - # x18 ---> save old value of medeleg - # x16 ---> save old value of mideleg - # x9 ---> bit mask for mideleg and medeleg - # x1 ---> used to go down to supervisor mode - - # We need to leave at least one bit in medeleg unset so that we have a way to get - # back to machine mode when the tests are complete (otherwise we'll only ever be able - # to get up to supervisor mode). - # - # So, we define a returning instruction which will be used to cause the exception that - # brings us into machine mode. The bit for this returning instruction is NOT set in - # medeleg. However, this also means that we can't test that instruction. So, we have - # two different returning instructions. - # - # Current code is written to only support ebreak and ecall. - # - # For testgen-IE, we don't need to test ebreak, so we can use that as the sole - # returning instruction. - returningInstruction = "ebreak" - if mode == "S": - # need to move down to supervisor mode (based on code in testgen-TVAL) - lines += f""" - # Reset x30 to 0 so we can run the tests. We'll set this to 1 when tests are completed so we stay in machine mode - li x30, 0 - """ - - # We don't want to delegate our returning instruction. Otherwise, we'll have no way of getting - # back to machine mode at the end! (and we need to be in machine mode to complete the tests) - medelegMask = "0b1111111111110111" if returningInstruction == "ebreak" else "0b1111000011111111" - - # Set medeleg and mideleg - lines += f""" - csrr x18, medeleg - li x9, {medelegMask if testMode == "s" or testMode == "u" else "0"} - csrw medeleg, x9 - - csrr x16, mideleg - li x9, {"0xffffffff" if testMode == "s" or testMode == "u" else "0"} - csrw mideleg, x9 - """ - - # bring down to supervisor mode - lines += f""" - li x1, 0b110000000000 - csrrc x31, mstatus, x1 - li x1, 0b0100000000000 - csrrs x31, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrw mepc, x1 - mret - - # We're now in supervisor mode... - """ - - for test in tests: - # print directed and random test vectors - for i in range(0,numrand): - a = getrandbits(xlen) - writeVectors(a, xlen, storecmd) - - if mode == "S": - # Bring us back up to machine mode! - # Creates a new trap handler that just jumps to _j_all_end_{returningInstruction} - # - # Get into the trap handler by running returningInstruction (in this case its ebreak) - f.write(f""" - li x30, 1 #may not need this - csrr x19, mtvec # save old value of mtvec - la x20 _j_all_end_{returningInstruction} - csrw mtvec, x20 - {returningInstruction} - - _returnMachineMode_handler: - j _j_all_end_{returningInstruction} - mret - - _j_all_end_{returningInstruction}: - - # Reset trap handling csrs to old values - csrw mtvec, x19 - csrw medeleg, x18 - csrw mideleg, x16 - """) - - f.write(lines) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - - writeTrapHandlers(storecmd, mode) - - f.close() - r.close() diff --git a/tests/testgen/privileged/testgen-IP.py b/tests/testgen/privileged/testgen-IP.py deleted file mode 100755 index 2741362ed..000000000 --- a/tests/testgen/privileged/testgen-IP.py +++ /dev/null @@ -1,196 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-IE.py -# -# ushakya@hmc.edu 31 March 2021 -# Modified: 4 April 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def getInteruptEnableValues(): - if test == "timerM": - mstatusE = 0x8 - mieE = 0x80 - elif test == "timerS": - mstatusE = 0x2 - mieE = 0x20 - elif test == "timerU": - mstatusE = 0x1 - mieE = 0x10 - elif test == "softwareM": - mstatusE = 0x8 - mieE = 0x8 - elif test == "softwareS": - mstatusE = 0x2 - mieE = 0x2 - elif test == "softwareU": - mstatusE = 0x1 - mieE = 0x1 - elif test == "externalM": - mstatusE = 0x8 - mieE = 0x800 - elif test == "externalS": - mstatusE = 0x2 - mieE = 0x200 - elif test == "externalU": - mstatusE = 0x1 - mieE = 0x100 - return [mstatusE, mieE] - -def getMcause(): - b = 1 << (xlen-1) - if test == "timerM": - b = b + 0x7 - elif test == "timerS": - b = b + 0x5 - elif test == "timerU": - b = b + 0x4 - elif test == "softwareM": - b = b + 0x3 - elif test == "softwareS": - b = b + 0x1 - elif test == "softwareU": - b = b - elif test == "externalM": - b = b + 0xB - elif test == "externalS": - b = b + 0x9 - elif test == "externalU": - b = b + 0x8 - return b - -# MIP is implicitly tested in the MIE tests -# these tests are to test that when mtimecmp < mtime -# MTIP bit is high in MIP -def writeVectors(a, xlen, storecmd): - global testnum - - [reg2, reg3] = [2, 3] - [reg5, reg8] = [5, 8] - [reg10, reg11, reg12] = [10, 11, 12] - [reg13, reg14, reg15] = [13, 14, 15] - - lines = f"\n# Testcase {testnum}: {test} Interupt\n" - - # mcause code - expected = 0x80 - - [mstatusE, mieE] = getInteruptEnableValues() - # ensure interupt enable bit in mie is low - lines += "li x" + str(reg8) + ", MASK_XLEN(" + formatstr.format(mieE) + ")\n" - lines += "csrrc x0, mie, x" + str(reg8) + "\n" - - # set interupt enable bit in mstatus - lines += "li x" + str(reg3) + ", MASK_XLEN(" + formatstr.format(mstatusE) + ")\n" - lines += "csrrs x0, mstatus, x" + str(reg3) + "\n" - - # cause timer interupt - if test == "timerM": - - # load MTIMECMP register address - lines += "la x" + str(reg2) + ", 0x2004000\n" - - # to be stored in MTIMECMP - lines += "li x" + str(reg10) + ", MASK_XLEN(0)\n" - - # save old value of mtimecmp and then set mtimecmp to zero - if xlens == 64: - lines += "lw x" + str(reg11) + ", 0(x" + str(reg2) + ")\n" - lines += str(storecmd) + " x" + str(reg10) + ", 0(x" + str(reg2) + ")\n" - - elif xlen == 32: - lines += "lw x" + str(reg11) + ", 0(x" + str(reg2) + ")\n" - lines += str(storecmd) + " x" + str(reg10) + ", 0(x" + str(reg2) + ")\n" - lines += str(storecmd) + " x" + str(reg10) + ", 4(x" + str(reg2) + ")\n" - - lines += "csrrs " + " x" + str(reg13) + ", mip, x0\n" - - lines += storecmd + " x" + str(reg13) + ", " + str(wordsize*testnum) + "(x6)\n" - lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, x" + str(reg13) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -tests = ["timerM"] #, "softwareM"] -author = "ushakya@hmc.edu" -xlens = [64, 32] -numrand = 100; - -# setup -seed(0) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-IP" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - for test in tests: - # print directed and random test vectors - for i in range(0,numrand): - a = getrandbits(xlen) - writeVectors(a, xlen, storecmd) - - f.write(lines) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - - f.close() - r.close() diff --git a/tests/testgen/privileged/testgen-READONLY.py b/tests/testgen/privileged/testgen-READONLY.py deleted file mode 100755 index 71eedbde5..000000000 --- a/tests/testgen/privileged/testgen-READONLY.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-CAUSE.py -# -# dottolia@hmc.edu 1 Mar 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -#For instruction-fetch access or page-fault exceptions on systems with variable-length instructions, mtval will contain the virtual address of the portion of the instruction that caused the fault while mepc will point to the beginning of the instruction. - -def randRegs(): - reg1 = randint(1,20) - reg2 = randint(1,20) - reg3 = randint(1,20) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return str(reg1), str(reg2), str(reg3) - -def writeVectors(a, storecmd): - writeSingleVector(a, storecmd, f"""csrrw x0, {test}, x13""") - writeSingleVector(a, storecmd, f"""csrrwi x0, {test}, {a % 32}""") - if a != 0: - writeSingleVector(a, storecmd, f"""csrrs x0, {test}, x13""") - writeSingleVector(a, storecmd, f"""csrrc x0, {test}, x13""") - writeSingleVector(a, storecmd, f"""csrrsi x0, {test}, {(a % 31) + 1}""") - writeSingleVector(a, storecmd, f"""csrrci x0, {test}, {(a % 31) + 1}""") - - -def writeSingleVector(a, storecmd, writeInstruction): - global testnum - - # Illegal Instruction - writeTest(storecmd, f, r, f""" - li x13, MASK_XLEN({a}) - csrrw x11, {test}, x0 - {writeInstruction} - csrrwi x12, {test}, 0 - sub x15, x11, x12 - """, False, 2) - - expected = 0 - lines = "" - lines += storecmd + " x15, " + str(wordsize*testnum) + "(x6)\n" - #lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - - - -def writeTest(storecmd, f, r, test, interrupt, code, mode = "m", resetHander = ""): - global testnum - - expected = code - if(interrupt): - expected+=(1 << (wordsize - 1)) - - - trapEnd = "" - before = "" - if mode != "m": - before = f""" - li x1, 0b110000000000 - csrrc x28, mstatus, x1 - li x1, 0b{"01" if mode == "s" else "00"}0000000000 - csrrs x28, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrrw x27, mepc, x1 - mret - - # We're now in {mode} mode... - """ - - trapEnd = f"""j _jend{testnum}""" - - - # Setup - # TODO: Adding 8 to x30 won't work for 32 bit? - # x31: Old mtvec value - # x30: trap handler address - # x29: Old mtvec value for user/supervisor mode - # x28: Old mstatus value - # x27: Old mepc value - # x26: 0 if we should execute mret normally. 1 otherwise. This allows us to stay in machine - # x25: mcause - # mode for the next tests - lines = f""" - # Testcase {testnum} - csrrs x31, mtvec, x0 - - auipc x30, 0 - addi x30, x30, 12 - j _jtest{testnum} - - # Machine trap vector - {resetHander} - csrrs x25, mcause, x0 - csrrs x1, mepc, x0 - addi x1, x1, 4 - csrrw x0, mepc, x1 - {trapEnd} - mret - - # Actual test - _jtest{testnum}: - csrrw x0, mtvec, x30 - - # Start test code - li x25, 0x7BAD - {before} - {test} - - # Finished test. Reset to old mtvec - _jend{testnum}: - - csrrw x0, mtvec, x31 - """ - - #expected = 42 - - lines += storecmd + " x25, " + str(wordsize*testnum) + "(x6)\n" - #lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - - # lines += storecmd + " x0" + ", " + str(wordsize*testnum) + "(x6)\n" - # #lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\n" - # f.write(lines) - # if (xlen == 32): - # line = formatrefstr.format(expected)+"\n" - # else: - # line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - # r.write(line) - # testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -# csrrw, csrrs, csrrc, csrrwi, csrrsi, csrrci -author = "dottolia@hmc.edu" -xlens = [32, 64] -numrand = 4; -tests = ["marchid", "mhartid", "mimpid", "mvendorid"] - -# setup -seed(0xD365DDEB9173AB42) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - - for test in tests: - corners = [ - 0, 1, 2, 31, 32, - 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1 - ] - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + test.upper() - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - # print directed and random test vectors - for i in corners: - writeVectors(i, storecmd) - for i in range(0,numrand): - writeVectors(getrandbits(xlen), storecmd) - - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - - diff --git a/tests/testgen/privileged/testgen-RET.py b/tests/testgen/privileged/testgen-RET.py deleted file mode 100755 index 94d5f7262..000000000 --- a/tests/testgen/privileged/testgen-RET.py +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-CAUSE.py -# -# dottolia@hmc.edu 16 Mar 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from enum import Enum -from random import getrandbits - -################################## -# functions -################################## - -# def computeExpected(a, b, test): -# if (test == "ADD"): -# return a + b -# elif (test == "SUB"): -# return a - b -# else: -# die("bad test name ", test) -# # exit(1) - -def randRegs(): - reg1 = randint(1,30) - reg2 = randint(1,30) - reg3 = randint(1,30) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return reg1, reg2, reg3 - -def writeVectors(storecmd): - global testnum - reg1, reg2, reg3 = randRegs() - - # t5 gets written with mtvec? - - # lines = f""" - - # li x{reg1}, 0 - # csrwi mtvec, 80002000 - # .data 00000000 - # j _done{testnum} - - # _trap{testnum}: - # csrrs x{reg1}, mcause, x0 - # ecall - - # _done{testnum}: - # add x0, x0, x0 - # """ - - #lines = - - - # https://ftp.gnu.org/old-gnu/Manuals/gas-2.9.1/html_chapter/as_7.html - - lines = f""" - li x1, 100 - li x2, 200 - add x3, x1, x2 - add x6, x3, x3 - - """ - f.write(lines) - - expected = 600 - - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - -################################## -# main body -################################## - -author = "Domenico Ottolia (dottolia@hmc.edu)" -xlens = [32, 64] -numrand = 60; - -# setup -seed(0xC395D19B9173AD42) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - - imperaspath = f"""../../../imperas-riscv-tests/riscv-test-suite/rv{xlen}p/""" - basename = "WALLY-RET" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - # h = open("../testgen_header.S", "r") - # for line in h: - # f.write(line) - - # print directed and random test vectors - - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - writeVectors(storecmd) - - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - - - # print footer - # h = open("../testgen_footer.S", "r") - # for line in h: - # f.write(line) - - # Finish - # lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - # lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - # f.write(lines) - f.close() - r.close() - diff --git a/tests/testgen/privileged/testgen-TVAL.py b/tests/testgen/privileged/testgen-TVAL.py deleted file mode 100755 index b5402d0e7..000000000 --- a/tests/testgen/privileged/testgen-TVAL.py +++ /dev/null @@ -1,374 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-TVAL.py -# -# dottolia@hmc.edu 1 Mar 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -# -################################## -# DOCUMENTATION: -# -# Most of the comments explaining what everything -# does and the layout of the privileged tests -# can be found in this file -# -################################### - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def writeVectors(storecmd): - global testnum - - # Illegal Instruction - writeTest(storecmd, f, r, f""" - .fill 1, 4, 0 - """, f""" - li x23, 0 - """) - - val = (randint(0, 200) * 2) + 1 - - # Load Address Misaligned - writeTest(storecmd, f, r, f""" - lw x0, {val}(x0) - """, f""" - li x23, {val} - """) - - val = (randint(0, 200) * 2) + 1 - - # Store Address Misaligned - writeTest(storecmd, f, r, f""" - sw x0, {val}(x0) - """, f""" - li x23, {val} - """) - - - - -def writeTest(storecmd, f, r, test, expected, mode = "m", resetHander = ""): - global testnum, storeAddressOffset - - # The code we actually change for our test - lines = f""" - {expected} - csrr x25, {testMode}tval - sub x25, x25, x23 - """ - - # Boilerplate - # - # x28 is the address that our trap handler will jump to before returning. - # This is where we can do our actual tests. After we're done computing and storing - # what we want, we jump to x27, which continues with the trap handling code (look at the _j_x_trap_... labels) - # - lines = f""" - la x28, _jtest{testnum} - j _jdo{testnum} - - _jtest{testnum}: - {lines} - jr x27 - - _jdo{testnum}: - li x25, 0xDEADBEA7 - {test} - """ - - # We expect x25 to be 0 always. This is because of the code we wrote at the begining - # of this function - expected = 0 - - # Store the expected value of x25 to memory and in the .reference_output file - lines += f""" - {storecmd} x25, 0(x7) - addi x7, x7, {wordsize} - """ - - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -author = "dottolia@hmc.edu" -xlens = [32, 64] -testCount = 32; - -# setup -# Change this seed to a different constant value for every test -seed(0xC363DAEB9193AB45) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - - # testMode can be m, s, and u. User mode traps are deprecated, so this should likely just be ["m", "s"] - for testMode in ["m", "s"]: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + testMode.upper() + "TVAL" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - storeAddressOffset = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - # We need to leave at least one bit in medeleg unset so that we have a way to get - # back to machine mode when the tests are complete (otherwise we'll only ever be able - # to get up to supervisor mode). - # - # So, we define a returning instruction which will be used to cause the exception that - # brings us into machine mode. The bit for this returning instruction is NOT set in - # medeleg. However, this also means that we can't test that instruction. So, we have - # two different returning instructions. - # - # Current code is written to only support ebreak and ecall. - # - # For testgen-TVAL, we don't need to test ebreak, so we can use that as the sole - # returning instruction. For others, like testgen-CAUSE, we'll need to put - # both ebreak and ecall here. - for returningInstruction in ["ebreak"]: - - # All registers used: - # x30: set to 1 if we should return to & stay in machine mode after trap, 0 otherwise - # ... - # x28: address trap handler should jump to for the test - # x27: address the test should return to after the test - # ... - # x25: value to write to memory - # ... - # x20: intermediate value in trap handler. Don't overwrite this! - # x19: mtvec old value - # x18: medeleg old value - # x17: sedeleg old value (currently unused — user mode traps deprecated) - # x16: mideleg old value - # ... - # x10 - x14 can be freely written - # ... - # x7: copy of x6. Increment this instead of using an offset on x6. - # this allows us to create more than 2048/wordlen tests. - # This is the address we write results to - # x6: Starting address we should write expected results to - # ... - # x4 & x5 can be freely written - # x3 — DO NOT WRITE ANY NON-ZERO VALUE TO THIS — test exits on ecall if x3 = 1 (x3 is gp) - # x1 & x2 can be freely written - - - - # Set up x7 and store old value of mtvec - lines = f""" - add x7, x6, x0 - csrr x19, mtvec - """ - - # Not used — user mode traps are deprecated - if testMode == "u": - lines += f""" - csrr x17, sedeleg - li x9, {"0b1100000000" if testMode == "u" else "0b0000000000"} - csrs sedeleg, x9 - """ - - # Code that will jump to the test (x28 is set in writeTest above) - testJumpCode = f""" - auipc x27, 0 - addi x27, x27, 12 - jr x28 - """ - - # Code for handling traps in different modes - # Some comments are inside of the below strings (prefixed with a #, as you might expected) - lines += f""" - # Reset x30 to 0 so we can run the tests. We'll set this to 1 when tests are completed so we stay in machine mode - li x30, 0 - - # Set up - la x1, _j_m_trap_{returningInstruction} - csrw mtvec, x1 - la x1, _j_s_trap_{returningInstruction} - csrw stvec, x1 - la x1, _j_u_trap_{returningInstruction} - # csrw utvec, x1 # user mode traps are not supported - - # Start the tests! - j _j_t_begin_{returningInstruction} - - # Machine mode traps - _j_m_trap_{returningInstruction}: - {testJumpCode if testMode == "m" else "li x25, 0xBAD00003"} - - csrrs x20, mepc, x0 - addi x20, x20, 4 - csrrw x0, mepc, x20 - bnez x30, _j_all_end_{returningInstruction} - mret - - # Supervisor mode traps - _j_s_trap_{returningInstruction}: - {testJumpCode if testMode == "s" else "li x25, 0xBAD00001"} - - csrrs x20, sepc, x0 - addi x20, x20, 4 - csrrw x0, sepc, x20 - bnez x30, _j_goto_machine_mode_{returningInstruction} - sret - - # Unused: user mode traps are no longer supported - _j_u_trap_{returningInstruction}: - {testJumpCode if testMode == "u" else "li x25, 0xBAD00000"} - - csrrs x20, uepc, x0 - addi x20, x20, 4 - csrrw x0, uepc, x20 - bnez x30, _j_goto_supervisor_mode_{returningInstruction} - uret - - # Currently unused. Just jumps to _j_goto_machine_mode. If you actually - # want to implement this, you'll likely need to reset sedeleg here - # and then cause an exception with {returningInstruction} (based on my intuition. Try that first, but I could be missing something / just wrong) - _j_goto_supervisor_mode_{returningInstruction}: - j _j_goto_machine_mode_{returningInstruction} - - _j_goto_machine_mode_{returningInstruction}: - li x30, 1 # This will cause us to branch to _j_all_end_{returningInstruction} in the machine trap handler, which we'll get into by invoking... - {returningInstruction} # ... this instruction! - - # Run the actual tests! - _j_t_begin_{returningInstruction}: - """ - - fromModeOptions = ["m", "s", "u"] if testMode == "m" else (["s", "u"] if testMode == "s" else ["u"]) - - # We don't want to delegate our returning instruction. Otherwise, we'll have no way of getting - # back to machine mode at the end! (and we need to be in machine mode to complete the tests) - medelegMask = "0b1111111111110111" if returningInstruction == "ebreak" else "0b1111000011111111" - - # Set medeleg and mideleg - lines += f""" - csrr x18, medeleg - li x9, {medelegMask if testMode == "s" or testMode == "u" else "0"} - csrw medeleg, x9 - - csrr x16, mideleg - li x9, {"0xffffffff" if testMode == "s" or testMode == "u" else "0"} - csrw mideleg, x9 - """ - - f.write(lines) - - for fromMode in fromModeOptions: - lines = "" - - # Code to bring us down to supervisor mode - if fromMode == "s" or fromMode == "u": - lines += f""" - li x1, 0b110000000000 - csrrc x31, mstatus, x1 - li x1, 0b0100000000000 - csrrs x31, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrw mepc, x1 - mret - - # We're now in supervisor mode... - """ - - # Code to bring us down to user mode - if fromMode == "u": - lines += f""" - - li x1, 0b110000000000 - csrrc x31, sstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the sret instruction - csrw sepc, x1 - sret - - # We're now in user mode... - """ - - f.write(lines) - for i in range(0,testCount): - writeVectors(storecmd) - - - # Very end of test. Bring us back up to machine mode - # We set x30 to 1, which will cause us to branch to _j_all_end in the - # machine mode trap handler, before executing the mret instruction. This will - # make us stay in machine mode. - # - # If we're currently in user mode, this will first bump us up to the supervisor mode - # trap handler, which will call returningInstruction again before it's sret instruction, - # bumping us up to machine mode - # - # Get into the trap handler by running returningInstruction (either an ecall or ebreak) - f.write(f""" - li x30, 1 - {returningInstruction} - _j_all_end_{returningInstruction}: - - # Reset trap handling csrs to old values - csrw mtvec, x19 - csrw medeleg, x18 - csrw mideleg, x16 - """) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - - diff --git a/tests/testgen/privileged/testgen-TVEC.py b/tests/testgen/privileged/testgen-TVEC.py deleted file mode 100755 index ce484c8b4..000000000 --- a/tests/testgen/privileged/testgen-TVEC.py +++ /dev/null @@ -1,473 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-TVEC.py (new) -# -# dottolia@hmc.edu 1 Mar 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -# -# -################################## -# DOCUMENTATION: -# -# The most up-to-date comments explaining what everything -# does and the layout of the privileged tests -# can be found in testgen-TVAL.py. This and -# other files do not have as many comments -# -################################### - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# setup -################################## - -areVectoredTrapsSupported = True - -################################## -# functions -################################## - -#For instruction-fetch access or page-fault exceptions on systems with variable-length instructions, mtval will contain the virtual address of the portion of the instruction that caused the fault while mepc will point to the beginning of the instruction. - -def randRegs(): - reg1 = randint(1,20) - reg2 = randint(1,20) - reg3 = randint(1,20) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return str(reg1), str(reg2), str(reg3) - -def writeVectors(storecmd, returningInstruction): - global testnum - - - # Illegal Instruction - # writeTest(storecmd, f, r, f""" - # .fill 1, 4, 0 - # """, False, 0) - - # # Breakpoint - # if returningInstruction != "ebreak": - # writeTest(storecmd, f, r, f""" - # ebreak - # """, False, 0) - - # # Load Address Misaligned - # writeTest(storecmd, f, r, f""" - # lw x0, 11(x0) - # """, False, 0) - - # # Load Access fault: False, 5 - - # # Store/AMO address misaligned - # writeTest(storecmd, f, r, f""" - # sw x0, 11(x0) - # """, False, 0) - - # # Environment call from u-mode: only for when only M and U mode enabled? - # # writeTest(storecmd, f, r, f""" - # # ecall - # # """, False, 8, "u") - if returningInstruction != "ecall": - writeTest(storecmd, f, r, f""" - ecall - """, False, 0) - - - if fromMode == "m" and testMode == "m": - expectedCode = 7 if fromMode == "m" else 5 - clintAddr = "0x2004000" - - writeTest(storecmd, f, r, f""" - li x1, 0x8 - csrrs x0, {fromMode}status, x1 - - la x18, {clintAddr} - # lw x11, 0(x18) - # li x1, 0x3fffffffffffffff - # {storecmd} x1, 0(x18) - - li x1, 0x80 - csrrs x0, {fromMode}ie, x1 - - {storecmd} x0, 0(x18) - """, True, expectedCode, f""" - li x1, 0x80 - csrrc x0, {fromMode}ie, x1 - - li x1, 0x8 - csrrc x0, {fromMode}status, x1 - - la x18, {clintAddr} - {storecmd} x0, 0(x18) - """) - - # Instruction page fault: 12 - # Load page fault: 13 - # Store/AMO page fault: 15 - - - - -def writeTest(storecmd, f, r, test, interrupt, code, resetHander = ""): - global testnum, storeAddressOffset, xlen - - expected = code - - # Boilerplate - # - # x28 is the address that our trap handler will jump to before returning. - # This is where we can do our actual tests. After we're done computing and storing - # what we want, we jump to x27, which continues with the trap handling code (look at the _j_x_trap_... labels) - # - lines = f""" - la x28, _jtest{testnum} - j _jdo{testnum} - - _jtest{testnum}: - nop - {resetHander} - jr x27 - - _jdo{testnum}: - li x25, 0xDEADBEA7 - {test} - """ - - - if not areVectoredTrapsSupported or not vectoredInterrupts: - expected = 0 - - writeGeneralTest(storecmd, f, r, lines, expected) - -def writeGeneralTest(storecmd, f, r, test, expected): - global testnum, storeAddressOffset, xlen - - lines = f""" - {test} - {storecmd} x25, {testnum * wordsize}(x6) - """ - - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - - testnum = testnum+1 - -################################## -# main body -################################## - -author = "dottolia@hmc.edu" -xlens = [32, 64] -testCount = 4; - -# setup -# Change this seed to a different constant value for every test -seed(0xC363DAEB9193AB45) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - - # testMode can be m, s, and u. User mode traps are deprecated, so this should likely just be ["m", "s"] - for testMode in ["m", "s"]: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + testMode.upper() + "TVEC" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - storeAddressOffset = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - # Ensure MODE of *tvec (last 2 bits) is either 00 or 01 - f.write(f""" - csrr x19, {testMode}tvec - """) - - for i in range(0, 16): - i = i; - trySet = i | 0b10; - expected = trySet & 0xFFFF_FFFFD; - writeGeneralTest(storecmd, f, r, f""" - li x1, {trySet} - csrw {testMode}tvec, x1 - csrr x25, {testMode}tvec - """, expected) - - f.write(f""" - csrw {testMode}tvec, x19 - """) - - # We need to leave at least one bit in medeleg unset so that we have a way to get - # back to machine mode when the tests are complete (otherwise we'll only ever be able - # to get up to supervisor mode). - # - # So, we define a returning instruction which will be used to cause the exception that - # brings us into machine mode. The bit for this returning instruction is NOT set in - # medeleg. However, this also means that we can't test that instruction. So, we have - # two different returning instructions. - # - # Current code is written to only support ebreak and ecall. - # - # For testgen-TVAL, we don't need to test ebreak, so we can use that as the sole - # returning instruction. For others, like testgen-CAUSE, we'll need to put - # both ebreak and ecall here. - - - for returningInstruction in ["ebreak"]: - for vectoredInterrupts in [True, False]: - - # All registers used: - # x30: set to 1 if we should return to & stay in machine mode after trap, 0 otherwise - # ... - # x28: address trap handler should jump to for the test - # x27: address the test should return to after the test - # ... - # x25: value to write to memory - # ... - # x20: intermediate value in trap handler. Don't overwrite this! - # x19: mtvec old value - # x18: medeleg old value - # x17: sedeleg old value (currently unused — user mode traps deprecated) - # x16: mideleg old value - # ... - # x10 - x14 can be freely written - # ... - # x7: copy of x6. Increment this instead of using an offset on x6. - # this allows us to create more than 2048/wordlen tests. - # This is the address we write results to - # x6: Starting address we should write expected results to - # ... - # x1 - x5 can be freely written - - - - # Set up x7 and store old value of mtvec - lines = f""" - # add x7, x6, x0 - csrr x19, mtvec - """ - - # Not used — user mode traps are deprecated - if testMode == "u": - lines += f""" - csrr x17, sedeleg - li x9, {"0b1100000000" if testMode == "u" else "0b0000000000"} - csrs sedeleg, x9 - """ - - # Code that will jump to the test (x28 is set in writeTest above) - testJumpCode = f""" - auipc x27, 0 - addi x27, x27, 12 - jr x28 - """ - - beforeCode = {"m": "", "s": ""} - for pm in ["m", "s"]: - for i in range(0, 16): - beforeCode[pm] = beforeCode[pm] + f""" - nop - nop - li x25, {i} - j _j_{pm}_trap_end_{returningInstruction}_{vectoredInterrupts} - """ - - # Code for handling traps in different modes - # Some comments are inside of the below strings (prefixed with a #, as you might expected) - enableVectored = "addi x1, x1, 1" if vectoredInterrupts else "" - - lines += f""" - # Reset x30 to 0 so we can run the tests. We'll set this to 1 when tests are completed so we stay in machine mode - li x30, 0 - - # Set up - la x1, _j_m_trap_{returningInstruction}_{vectoredInterrupts} - {enableVectored} # enable/don't enable vectored interrupts - csrw mtvec, x1 - la x1, _j_s_trap_{returningInstruction}_{vectoredInterrupts} - {enableVectored} # enable/don't enable vectored interrupts - csrw stvec, x1 - la x1, _j_u_trap_{returningInstruction}_{vectoredInterrupts} - {enableVectored} # enable/don't enable vectored interrupts - # csrw utvec, x1 # user mode traps are not supported - - # Start the tests! - j _j_t_begin_{returningInstruction}_{vectoredInterrupts} - - # Machine mode traps - _j_m_trap_{returningInstruction}_{vectoredInterrupts}: - {beforeCode['m']} - - _j_m_trap_end_{returningInstruction}_{vectoredInterrupts}: - {testJumpCode} - - csrrs x20, mepc, x0 - addi x20, x20, 4 - csrrw x0, mepc, x20 - bnez x30, _j_all_end_{returningInstruction}_{vectoredInterrupts} - mret - - # Supervisor mode traps - _j_s_trap_{returningInstruction}_{vectoredInterrupts}: - {beforeCode['s']} - - _j_s_trap_end_{returningInstruction}_{vectoredInterrupts}: - {testJumpCode} - - csrrs x20, sepc, x0 - addi x20, x20, 4 - csrrw x0, sepc, x20 - bnez x30, _j_goto_machine_mode_{returningInstruction}_{vectoredInterrupts} - sret - - # Unused: user mode traps are no longer supported - _j_u_trap_{returningInstruction}_{vectoredInterrupts}: - {testJumpCode if testMode == "u" else "li x25, 0xBAD00000"} - - csrrs x20, uepc, x0 - addi x20, x20, 4 - csrrw x0, uepc, x20 - bnez x30, _j_goto_supervisor_mode_{returningInstruction}_{vectoredInterrupts} - uret - - # Currently unused. Just jumps to _j_goto_machine_mode. If you actually - # want to implement this, you'll likely need to reset sedeleg here - # and then cause an exception with {returningInstruction} (based on my intuition. Try that first, but I could be missing something / just wrong) - _j_goto_supervisor_mode_{returningInstruction}_{vectoredInterrupts}: - j _j_goto_machine_mode_{returningInstruction}_{vectoredInterrupts} - - _j_goto_machine_mode_{returningInstruction}_{vectoredInterrupts}: - li x30, 1 # This will cause us to branch to _j_all_end_{returningInstruction}_{vectoredInterrupts} in the machine trap handler, which we'll get into by invoking... - {returningInstruction} # ... this instruction! - - # Run the actual tests! - _j_t_begin_{returningInstruction}_{vectoredInterrupts}: - """ - - fromModeOptions = ["m", "s", "u"] if testMode == "m" else (["s", "u"] if testMode == "s" else ["u"]) - - # We don't want to delegate our returning instruction. Otherwise, we'll have no way of getting - # back to machine mode at the end! (and we need to be in machine mode to complete the tests) - medelegMask = "0b1111111111110111" if returningInstruction == "ebreak" else "0b1111000011111111" - - # Set medeleg and mideleg - lines += f""" - csrr x18, medeleg - li x9, {medelegMask if testMode == "s" or testMode == "u" else "0"} - csrw medeleg, x9 - - csrr x16, mideleg - li x9, {"0xffffffff" if testMode == "s" or testMode == "u" else "0"} - csrw mideleg, x9 - """ - - f.write(lines) - - for fromMode in fromModeOptions: - lines = "" - - # Code to bring us down to supervisor mode - if fromMode == "s" or fromMode == "u": - lines += f""" - li x1, 0b110000000000 - csrrc x31, mstatus, x1 - li x1, 0b0100000000000 - csrrs x31, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrw mepc, x1 - mret - - # We're now in supervisor mode... - """ - - # Code to bring us down to user mode - if fromMode == "u": - lines += f""" - - li x1, 0b110000000000 - csrrc x31, sstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the sret instruction - csrw sepc, x1 - sret - - # We're now in user mode... - """ - - f.write(lines) - for i in range(0,testCount): - writeVectors(storecmd, returningInstruction) - - - # Very end of test. Bring us back up to machine mode - # We set x30 to 1, which will cause us to branch to _j_all_end in the - # machine mode trap handler, before executing the mret instruction. This will - # make us stay in machine mode. - # - # If we're currently in user mode, this will first bump us up to the supervisor mode - # trap handler, which will call returningInstruction again before it's sret instruction, - # bumping us up to machine mode - # - # Get into the trap handler by running returningInstruction (either an ecall or ebreak) - f.write(f""" - li x30, 1 - li gp, 0 - {returningInstruction} - _j_all_end_{returningInstruction}_{vectoredInterrupts}: - - # Reset trap handling csrs to old values - csrw mtvec, x19 - csrw medeleg, x18 - csrw mideleg, x16 - """) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() diff --git a/tests/testgen/testgen.py b/tests/testgen/testgen.py deleted file mode 100755 index 46bd2cb75..000000000 --- a/tests/testgen/testgen.py +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen.py -# -# David_Harris@hmc.edu 19 January 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def twoscomp(a, xlen): - amsb = a >> (xlen-1) - alsbs = ((1 << (xlen-1)) - 1) & a - if (amsb): - asigned = a - (1<