cvw/tests/testgen/privileged/testgen-CSR-PERMISSIONS.py

249 lines
6.2 KiB
Python
Raw Normal View History

#!/usr/bin/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()