mirror of
https://github.com/openhwgroup/cvw
synced 2025-01-22 20:44:28 +00:00
Remove studies/testgen as it is no longer compatible
This commit is contained in:
parent
f937e31ee9
commit
b36c64208c
@ -1,158 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-ADD-SUB-SLT-SLTU-XOR-OR-AND.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):
|
|
||||||
amsb = a >> (xlen-1)
|
|
||||||
alsbs = ((1 << (xlen-1)) - 1) & a
|
|
||||||
if (amsb):
|
|
||||||
asigned = a - (1<<xlen)
|
|
||||||
else:
|
|
||||||
asigned = a
|
|
||||||
#print("a: " + str(a) + " amsb: "+str(amsb)+ " alsbs: " + str(alsbs) + " asigned: "+str(asigned))
|
|
||||||
return asigned
|
|
||||||
|
|
||||||
def computeExpected(a, b, test, xlen):
|
|
||||||
asigned = twoscomp(a)
|
|
||||||
bsigned = twoscomp(b)
|
|
||||||
|
|
||||||
if (test == "ADD"):
|
|
||||||
return a + b
|
|
||||||
elif (test == "SUB"):
|
|
||||||
return a - b
|
|
||||||
elif (test == "SLT"):
|
|
||||||
return asigned < bsigned
|
|
||||||
elif (test == "SLTU"):
|
|
||||||
return a < b
|
|
||||||
elif (test == "XOR"):
|
|
||||||
return a ^ b
|
|
||||||
elif (test == "OR"):
|
|
||||||
return a | b
|
|
||||||
elif (test == "AND"):
|
|
||||||
return a & b
|
|
||||||
else:
|
|
||||||
die("bad test name ", test)
|
|
||||||
# exit(1)
|
|
||||||
|
|
||||||
def randRegs():
|
|
||||||
reg1 = randint(1,31)
|
|
||||||
reg2 = randint(1,31)
|
|
||||||
reg3 = randint(1,31)
|
|
||||||
if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2):
|
|
||||||
return randRegs()
|
|
||||||
else:
|
|
||||||
return reg1, reg2, reg3
|
|
||||||
|
|
||||||
def writeVector(a, b, storecmd, xlen):
|
|
||||||
global testnum
|
|
||||||
expected = computeExpected(a, b, test, xlen)
|
|
||||||
expected = expected % 2**xlen # drop carry if necessary
|
|
||||||
if (expected < 0): # take twos complement
|
|
||||||
expected = 2**xlen + expected
|
|
||||||
reg1, reg2, reg3 = randRegs()
|
|
||||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
|
||||||
lines = lines + "), rs2:x" + str(reg2) + "(" +formatstr.format(b)
|
|
||||||
lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
|
||||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
|
||||||
lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
|
||||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", x" + str(reg2) + "\n"
|
|
||||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
|
||||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg3) +", "+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 = ["ADD", "SUB", "SLT", "SLTU", "XOR", "OR", "AND"]
|
|
||||||
author = "David_Harris@hmc.edu & Katherine Parry"
|
|
||||||
xlens = [32, 64]
|
|
||||||
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 test in tests:
|
|
||||||
corners = [0, 1, 2, 0xFF, 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) + "i/"
|
|
||||||
basename = "WALLY-" + test
|
|
||||||
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 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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,161 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-ADD-SUB.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 computeExpected(a, b, test):
|
|
||||||
if (test == "ADDI"):
|
|
||||||
return a + b
|
|
||||||
elif (test == "XORI"):
|
|
||||||
return a ^ b
|
|
||||||
elif (test == "ORI"):
|
|
||||||
return a | b
|
|
||||||
elif (test == "ANDI"):
|
|
||||||
return a & b
|
|
||||||
elif (test == "SLTI"):
|
|
||||||
return a < b
|
|
||||||
else:
|
|
||||||
die("bad test name ", test)
|
|
||||||
# exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def evaluateTwoComplement(b, bits):
|
|
||||||
if (b & (1 << (bits -1))!= 0):
|
|
||||||
b = b - (1 << bits)
|
|
||||||
return b
|
|
||||||
|
|
||||||
|
|
||||||
def randRegs():
|
|
||||||
reg1 = randint(1,31)
|
|
||||||
reg3 = randint(1,31)
|
|
||||||
if (reg1 == 6 or reg3 == 6):
|
|
||||||
return randRegs()
|
|
||||||
else:
|
|
||||||
return reg1, reg3
|
|
||||||
|
|
||||||
def writeVector(a, b, storecmd):
|
|
||||||
global testnum
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
expected = computeExpected(evaluateTwoComplement(a,xlen), evaluateTwoComplement(b, 12), test)
|
|
||||||
expected = expected % 2**xlen # drop carry if necessary
|
|
||||||
if (expected < 0): # take twos complement
|
|
||||||
expected = 2**xlen + expected
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
reg1, reg3 = randRegs()
|
|
||||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
|
||||||
lines = lines + "), imm12:" + "(" +formatstrimm12.format(b)
|
|
||||||
lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
|
||||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
|
||||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", SEXT_IMM(" + formatstrimm12.format(b) + ")\n"
|
|
||||||
# lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
|
||||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
|
||||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " +"x" + str(reg3) +", "+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 = ["ADDI", "XORI", "ORI", "ANDI", "SLTI"]
|
|
||||||
author = "Shriya Nadgauda & Ethan Falicov"
|
|
||||||
xlens = [32, 64]
|
|
||||||
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
|
|
||||||
|
|
||||||
formatstrimm12 = "0x{:03x}" # format as 3-bit hexadecimal number
|
|
||||||
if (xlen == 32):
|
|
||||||
storecmd = "sw"
|
|
||||||
wordsize = 4
|
|
||||||
else:
|
|
||||||
storecmd = "sd"
|
|
||||||
wordsize = 8
|
|
||||||
|
|
||||||
for test in tests:
|
|
||||||
corners1 = [0, 1, 2, 0xFF, 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]
|
|
||||||
|
|
||||||
immBitSize = 12
|
|
||||||
corners2 = [0, 1, 2, 0xFF, 0x624 % 2**immBitSize, 2**(immBitSize-1)-2, 2**(immBitSize-1)-1,
|
|
||||||
2**(immBitSize-1), 2**(immBitSize-1)+1, 0xC36 % 2**immBitSize, 2**(immBitSize)-2, 2**(immBitSize)-1]
|
|
||||||
|
|
||||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
|
||||||
basename = "WALLY-" + test
|
|
||||||
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 a in corners1:
|
|
||||||
for b in corners2:
|
|
||||||
writeVector(a, b, storecmd)
|
|
||||||
for i in range(0,numrand):
|
|
||||||
a = getrandbits(xlen)
|
|
||||||
b = getrandbits(12)
|
|
||||||
writeVector(a, b, 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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,182 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-ADDIW-SLLIW-SRLIW-SRAIW.py
|
|
||||||
#
|
|
||||||
# ehedenberg@hmc.edu 4 February 2021
|
|
||||||
# heavily influenced by Prof Harris Code
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
import sys
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# functions
|
|
||||||
##################################
|
|
||||||
def logical_rshift(signed_integer, places):
|
|
||||||
unsigned_integer=signed_integer%(1<<32)
|
|
||||||
return unsigned_integer >> places
|
|
||||||
|
|
||||||
def toSigned12bit(n):
|
|
||||||
n=n & 0xfff
|
|
||||||
if (n&(1<<11)):
|
|
||||||
n=n|0xfffffffffffff000
|
|
||||||
return n
|
|
||||||
|
|
||||||
def toSigned32bit(n):
|
|
||||||
n=n & 0xffffffff
|
|
||||||
if (n&(1<<31)):
|
|
||||||
n=n|0xffffffff00000000
|
|
||||||
return n
|
|
||||||
|
|
||||||
|
|
||||||
def computeExpected(a, b, test):
|
|
||||||
if (test == "ADDIW"):
|
|
||||||
b=toSigned12bit(b)
|
|
||||||
return a + b
|
|
||||||
elif (test == "SLLIW"):
|
|
||||||
return (a << b)
|
|
||||||
elif (test == "SRLIW"):
|
|
||||||
return logical_rshift(a, b)
|
|
||||||
elif(test == "SRAIW"):
|
|
||||||
a= toSigned32bit(a)
|
|
||||||
return a >> b
|
|
||||||
else:
|
|
||||||
die("bad test name ", test)
|
|
||||||
# exit(1)
|
|
||||||
|
|
||||||
def randRegs():
|
|
||||||
reg1 = randint(1,31)
|
|
||||||
reg2 = randint(1,31)
|
|
||||||
reg3 = randint(1,31)
|
|
||||||
if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2):
|
|
||||||
return randRegs()
|
|
||||||
else:
|
|
||||||
return reg1, reg2, reg3
|
|
||||||
|
|
||||||
def writeVector(a, b, storecmd):
|
|
||||||
global testnum
|
|
||||||
expected = computeExpected(a, b, test)
|
|
||||||
expected = expected % 2**64 # drop carry if necessary
|
|
||||||
if (expected < 0): # take twos complement
|
|
||||||
expected = 2**64 + expected
|
|
||||||
#expected=expected+2^32<<32
|
|
||||||
if (expected >= (2**32)):
|
|
||||||
expected=expected%(2**32)
|
|
||||||
expected=toSigned32bit(expected)
|
|
||||||
reg1, reg2, reg3 = randRegs()
|
|
||||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
|
||||||
lines = lines + "), imm:"+formatstr.format(b)
|
|
||||||
lines = lines + ", result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
|
||||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
|
||||||
#lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
|
||||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", SEXT_IMM(" + formatstr.format(b) + ")\n"
|
|
||||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
|
||||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, x" + str(reg3) +", "+formatstr.format(expected)+")\n"
|
|
||||||
#lines = lines + str(b)+"\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 = ["ADDIW", "SLLIW", "SRLIW", "SRAIW"]
|
|
||||||
author = "Eizabeth Hedenberg"
|
|
||||||
xlens = [64]
|
|
||||||
shiftlen=5
|
|
||||||
addlen=12
|
|
||||||
numrand = 100
|
|
||||||
|
|
||||||
# setup
|
|
||||||
seed(0) # make tests reproducible
|
|
||||||
|
|
||||||
# generate files for each test
|
|
||||||
for xlen in xlens:
|
|
||||||
formatstrlen = str(int(xlen/4))
|
|
||||||
#formatstrlen6=str(int())
|
|
||||||
formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number
|
|
||||||
#formatstr6 = "0x{:0" + "2" + "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:
|
|
||||||
cornersa = [0, 1, 2, 0xFF, 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]
|
|
||||||
#test both confined to top 32 and not
|
|
||||||
cornersshift=[0, 1, 2, 2**(shiftlen)-1, 2**(shiftlen)-2, 0b00101, 0b01110]
|
|
||||||
#6 bits: 0, 1, 2, largest, largest -1, largest -2, 21, 46
|
|
||||||
cornersadd=[0, 1, 2, 2**(addlen-1), 2**(addlen-1)-1, 2**(addlen-1)-2, 2**(addlen-1)+1, 2**(addlen)-2, 2**(addlen)-1, 0b001010010101, 0b101011101111]
|
|
||||||
#12 bit, 0, 1, 2 argest positive, largest -1, largest -2, largest negative number, -2, -1, random
|
|
||||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
|
||||||
basename = "WALLY-" + test
|
|
||||||
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
|
|
||||||
if test=="ADDIW":
|
|
||||||
for a in cornersa:
|
|
||||||
for b in cornersadd:
|
|
||||||
writeVector(a, b, storecmd)
|
|
||||||
for i in range(0,numrand):
|
|
||||||
a = getrandbits(xlen)
|
|
||||||
b = getrandbits(12)
|
|
||||||
writeVector(a, b, storecmd)
|
|
||||||
else:
|
|
||||||
for a in cornersa:
|
|
||||||
for b in cornersshift:
|
|
||||||
writeVector(a, b, storecmd)
|
|
||||||
for i in range(0,numrand):
|
|
||||||
a = getrandbits(xlen)
|
|
||||||
b = getrandbits(5)
|
|
||||||
writeVector(a, b, 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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,174 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-ADDW-SUBW-SLLW-SRLW-SRAW.py
|
|
||||||
#
|
|
||||||
# trao@g.hmc.edu 11 February 2021
|
|
||||||
# Based on testgen-ADD-SUB.py by Prof. David Harris
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
import sys
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# functions
|
|
||||||
##################################
|
|
||||||
def logical_rshift(signed_integer, places):
|
|
||||||
unsigned_integer=signed_integer%(1<<32)
|
|
||||||
return unsigned_integer >> places
|
|
||||||
|
|
||||||
def toSigned12bit(n):
|
|
||||||
n=n & 0xfff
|
|
||||||
if (n&(1<<11)):
|
|
||||||
n=n|0xfffffffffffff000
|
|
||||||
return n
|
|
||||||
|
|
||||||
def toSigned32bit(n):
|
|
||||||
n=n & 0xffffffff
|
|
||||||
if (n&(1<<31)):
|
|
||||||
n=n|0xffffffff00000000
|
|
||||||
return n
|
|
||||||
|
|
||||||
|
|
||||||
def computeExpected(a, b, test):
|
|
||||||
if (test == "ADDW"):
|
|
||||||
return toSigned32bit(a + b)
|
|
||||||
elif (test == "SUBW"):
|
|
||||||
return toSigned32bit(a - b)
|
|
||||||
elif (test == "SLLW"):
|
|
||||||
b = b & 0x1F
|
|
||||||
return toSigned32bit(a << b)
|
|
||||||
elif (test == "SRLW"):
|
|
||||||
b = b & 0x1F
|
|
||||||
return toSigned32bit(logical_rshift(a, b))
|
|
||||||
elif(test == "SRAW"):
|
|
||||||
a= toSigned32bit(a)
|
|
||||||
b = b & 0x1F
|
|
||||||
return toSigned32bit(a >> b)
|
|
||||||
else:
|
|
||||||
die("bad test name ", test)
|
|
||||||
# exit(1)
|
|
||||||
|
|
||||||
def randRegs():
|
|
||||||
reg1 = randint(1,31)
|
|
||||||
reg2 = randint(1,31)
|
|
||||||
reg3 = randint(1,31)
|
|
||||||
if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2):
|
|
||||||
return randRegs()
|
|
||||||
else:
|
|
||||||
return reg1, reg2, reg3
|
|
||||||
|
|
||||||
def writeVector(a, b, storecmd):
|
|
||||||
global testnum
|
|
||||||
expected = computeExpected(a, b, test)
|
|
||||||
expected = expected % 2**xlen # drop carry if necessary
|
|
||||||
if (expected < 0): # take twos complement
|
|
||||||
expected = 2**xlen + expected
|
|
||||||
reg1, reg2, reg3 = randRegs()
|
|
||||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
|
||||||
lines = lines + "), rs2:x" + str(reg2) + "(" +formatstr.format(b)
|
|
||||||
lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
|
||||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
|
||||||
lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
|
||||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", x" + str(reg2) + "\n"
|
|
||||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
|
||||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg3) +", "+formatstr.format(expected)+")\n"
|
|
||||||
f.write(lines)
|
|
||||||
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 = ["ADDW", "SUBW", "SLLW", "SRLW", "SRAW"]
|
|
||||||
author = "Tejus Rao"
|
|
||||||
xlens = [64]
|
|
||||||
shiftlen=5
|
|
||||||
addlen=32
|
|
||||||
numrand = 100
|
|
||||||
|
|
||||||
# setup
|
|
||||||
seed(0) # make tests reproducible
|
|
||||||
|
|
||||||
# generate files for each test
|
|
||||||
for xlen in xlens:
|
|
||||||
formatstrlen = str(int(xlen/4))
|
|
||||||
#formatstrlen6=str(int())
|
|
||||||
formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number
|
|
||||||
#formatstr6 = "0x{:0" + "2" + "x}" # format as xlen-bit hexadecimal number
|
|
||||||
formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x
|
|
||||||
storecmd = "sd"
|
|
||||||
wordsize = 8
|
|
||||||
for test in tests:
|
|
||||||
cornersa = [0, 1, 2, 0xFF, 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]
|
|
||||||
#test both confined to top 32 and not
|
|
||||||
cornersshift=[0, 1, 2, 2**(shiftlen)-1, 2**(shiftlen)-2, 0b00101, 0b01110]
|
|
||||||
#6 bits: 0, 1, 2, largest, largest -1, largest -2, 21, 46
|
|
||||||
cornersadd=[0, 1, 2, 2**(addlen-1), 2**(addlen-1)-1, 2**(addlen-1)-2, 2**(addlen-1)+1, 2**(addlen)-2, 2**(addlen)-1, 0b001010010101, 0b101011101111]
|
|
||||||
#12 bit, 0, 1, 2 argest positive, largest -1, largest -2, largest negative number, -2, -1, random
|
|
||||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
|
||||||
basename = "WALLY-" + test
|
|
||||||
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
|
|
||||||
if test=="ADDW" or test == "SUBW":
|
|
||||||
for a in cornersa:
|
|
||||||
for b in cornersadd:
|
|
||||||
writeVector(a, b, storecmd)
|
|
||||||
for i in range(0,numrand):
|
|
||||||
a = getrandbits(xlen)
|
|
||||||
b = getrandbits(xlen)
|
|
||||||
writeVector(a, b, storecmd)
|
|
||||||
else:
|
|
||||||
for a in cornersa:
|
|
||||||
for b in cornersshift:
|
|
||||||
writeVector(a, b, storecmd)
|
|
||||||
for i in range(0,numrand):
|
|
||||||
a = getrandbits(xlen)
|
|
||||||
b = getrandbits(5)
|
|
||||||
writeVector(a, b, 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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,155 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-branch.py
|
|
||||||
#
|
|
||||||
# ssanghai@hmc.edu 13th Feb 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 computeExpected(a, b, test):
|
|
||||||
if (test == "BEQ"):
|
|
||||||
return 0xcccc if a==b else 0xeeee
|
|
||||||
elif (test == "BNE"):
|
|
||||||
return 0xeeee if a==b else 0xcccc
|
|
||||||
elif (test == "BGEU"):
|
|
||||||
return 0xcccc if a>=b else 0xeeee
|
|
||||||
elif (test == "BLT"):
|
|
||||||
if (1<<(xlen-1)) & a:
|
|
||||||
a = a -(2**xlen)
|
|
||||||
if (1<<(xlen-1)) & b:
|
|
||||||
b = b - (2**xlen)
|
|
||||||
return 0xcccc if a<b else 0xeeee
|
|
||||||
elif (test == "BLTU"):
|
|
||||||
return 0xcccc if a<b else 0xeeee
|
|
||||||
elif (test == "BGE"):
|
|
||||||
if (1<<(xlen-1)) & a:
|
|
||||||
a = a - (2**xlen)
|
|
||||||
if (1<<(xlen-1)) & b:
|
|
||||||
b = b - (2**xlen)
|
|
||||||
return 0xcccc if a>=b else 0xeeee
|
|
||||||
else:
|
|
||||||
die("bad test name ", test)
|
|
||||||
# exit(1)
|
|
||||||
|
|
||||||
def randRegs():
|
|
||||||
reg1 = randint(2,31)
|
|
||||||
reg2 = randint(2,31)
|
|
||||||
if (reg1 == 6 or reg2 == 6 or reg1 == reg2):
|
|
||||||
return randRegs()
|
|
||||||
else:
|
|
||||||
return reg1, reg2
|
|
||||||
|
|
||||||
label = 0
|
|
||||||
|
|
||||||
def writeVector(a, b, storecmd):
|
|
||||||
global testnum
|
|
||||||
global label
|
|
||||||
expected = computeExpected(a, b, test)
|
|
||||||
expected = expected % 2**xlen # drop carry if necessary
|
|
||||||
if (expected < 0): # take twos complement
|
|
||||||
expected = 2**xlen + expected
|
|
||||||
reg1, reg2 = randRegs()
|
|
||||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
|
||||||
lines = lines + "), rs2:x" + str(reg2) + "(" +formatstr.format(b) + "\n"
|
|
||||||
lines = lines + "li x1, MASK_XLEN(0xcccc)\n"
|
|
||||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
|
||||||
lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
|
||||||
lines = lines + test + " x" + str(reg1) + ", x" + str(reg2) + ", " + str(label) + "f\n"
|
|
||||||
lines = lines + "li x1, MASK_XLEN(0xeeee)\n"
|
|
||||||
lines = lines + str(label) + ":\n"
|
|
||||||
lines = lines + storecmd + " x1, " + str(wordsize*testnum) + "(x6)\n"
|
|
||||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, x1, "+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)
|
|
||||||
label += 1
|
|
||||||
testnum = testnum+1
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# main body
|
|
||||||
##################################
|
|
||||||
|
|
||||||
# change these to suite your tests
|
|
||||||
tests = ["BEQ", "BNE", "BLT", "BGE", "BGEU", "BLTU"]
|
|
||||||
author = "Shreya Sanghai"
|
|
||||||
xlens = [32, 64]
|
|
||||||
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 test in tests:
|
|
||||||
corners = [0, 1, 2, 0xFF, 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) + "i/"
|
|
||||||
basename = "WALLY-" + test
|
|
||||||
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 a in corners:
|
|
||||||
for b in corners:
|
|
||||||
writeVector(a, b, storecmd)
|
|
||||||
for i in range(0,numrand):
|
|
||||||
a = getrandbits(xlen)
|
|
||||||
b = getrandbits(xlen)
|
|
||||||
writeVector(a, b, 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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,218 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-ADD-SUB.py
|
|
||||||
#
|
|
||||||
# ushakya@hmc.edu & dottolia@hmc.edu 14 Feb 2021
|
|
||||||
# Modified: ushakya@hmc.edu 21 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 randRegs():
|
|
||||||
reg1 = randint(1,31)
|
|
||||||
reg2 = randint(1,31)
|
|
||||||
reg3 = randint(1,31)
|
|
||||||
if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2):
|
|
||||||
return randRegs()
|
|
||||||
else:
|
|
||||||
return reg1, reg2, reg3
|
|
||||||
|
|
||||||
def writeVector(a, b, storecmd):
|
|
||||||
global testnum
|
|
||||||
csr = "mscratch"
|
|
||||||
|
|
||||||
reg1, reg2, reg3 = randRegs()
|
|
||||||
lines = "\n# Testcase " + str(testnum) + ": " + csr + "\n"
|
|
||||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
|
||||||
lines = lines + "li x" + str(reg2) + ", MASK_XLEN(0)\n"
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
expected = a
|
|
||||||
|
|
||||||
if test == "csrrw":
|
|
||||||
if testnum == 0:
|
|
||||||
# this is a corner case (reading and writing same register)
|
|
||||||
expected = 4
|
|
||||||
lines += "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(0x8) + ")\n"
|
|
||||||
lines += "la x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(0x4) + ")\n"
|
|
||||||
lines += "csrrw x" + str(reg3) + ", mtvec, x" + str(reg1) + "\n"
|
|
||||||
lines += test + " x" + str(reg2) + ", mtvec, x" + str(reg2) + "\n"
|
|
||||||
lines += "csrrw x0, mtvec, x" + str(reg3) + "\n"
|
|
||||||
else:
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
|
||||||
|
|
||||||
elif test == "csrrs": # at some point, try writing a non-zero value first
|
|
||||||
lines += "csrrw x0, " + csr + ", x0\n" # set csr to 0
|
|
||||||
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
|
||||||
elif test == "csrrc": # at some point, try writing a non-one value first
|
|
||||||
allOnes = "0xFFFFFFFF" if xlen == 32 else "0xFFFFFFFFFFFFFFFF"
|
|
||||||
|
|
||||||
lines += "li x" + str(reg1) + ", MASK_XLEN(" + allOnes + ")\n"
|
|
||||||
lines += "csrrw x0, " + csr + ", x" + str(reg1) + "\n" # set csr to all ones
|
|
||||||
|
|
||||||
lines += "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
|
||||||
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
|
||||||
|
|
||||||
expected = a ^ 0xFFFFFFFF if xlen == 32 else a ^ 0xFFFFFFFFFFFFFFFF
|
|
||||||
elif test == "csrrwi":
|
|
||||||
a = a & 0x1F # imm is only 5 bits
|
|
||||||
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n"
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n"
|
|
||||||
|
|
||||||
expected = a
|
|
||||||
elif test == "csrrsi": # at some point, try writing a non-zero value first
|
|
||||||
a = a & 0x1F
|
|
||||||
|
|
||||||
lines += "csrrw x0, " + csr + ", x0\n" # set csr to 0
|
|
||||||
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n"
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n"
|
|
||||||
|
|
||||||
expected = a
|
|
||||||
elif test == "csrrci": # at some point, try writing a non-one value first
|
|
||||||
a = a & 0x1F
|
|
||||||
allOnes = "0xFFFFFFFF" if xlen == 32 else "0xFFFFFFFFFFFFFFFF"
|
|
||||||
|
|
||||||
lines += "li x" + str(reg1) + ", MASK_XLEN(" + allOnes + ")\n"
|
|
||||||
lines += "csrrw x0, " + csr + ", x" + str(reg1) + "\n" # set csr to all ones
|
|
||||||
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n"
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n"
|
|
||||||
|
|
||||||
expected = a ^ 0xFFFFFFFF if xlen == 32 else a ^ 0xFFFFFFFFFFFFFFFF
|
|
||||||
|
|
||||||
|
|
||||||
lines += storecmd + " x" + str(reg2) + ", " + 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 writeSpec(a, storecmd):
|
|
||||||
global testnum
|
|
||||||
csr = "mscratch"
|
|
||||||
reg1 = 3
|
|
||||||
reg2 = 3
|
|
||||||
|
|
||||||
lines = "\n# Testcase " + str(testnum) + ": " + csr + "\n"
|
|
||||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
|
||||||
expected = a
|
|
||||||
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
|
||||||
lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n"
|
|
||||||
|
|
||||||
lines += storecmd + " x" + str(reg2) + ", " + 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
|
|
||||||
tests = ["csrrw", "csrrs", "csrrc", "csrrwi", "csrrsi", "csrrci"]
|
|
||||||
author = "ushakya@hmc.edu & dottolia@hmc.edu"
|
|
||||||
xlens = [32, 64]
|
|
||||||
numrand = 60;
|
|
||||||
|
|
||||||
# setup
|
|
||||||
seed(0xC365DDEB9173AB42) # 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, 0x1E, 0x1F, 0xFF,
|
|
||||||
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) + "i/"
|
|
||||||
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
|
|
||||||
# test that reading and writing from same register work
|
|
||||||
if test == "csrrw":
|
|
||||||
a = getrandbits(xlen)
|
|
||||||
#writeSpec(a, storecmd)
|
|
||||||
for a in corners:
|
|
||||||
for b in corners:
|
|
||||||
writeVector(a, b, storecmd)
|
|
||||||
for i in range(0,numrand):
|
|
||||||
a = getrandbits(xlen)
|
|
||||||
b = getrandbits(xlen)
|
|
||||||
writeVector(a, b, storecmd)
|
|
||||||
|
|
||||||
|
|
||||||
# print footer
|
|
||||||
h = open("testgen_footer.S", "r")
|
|
||||||
for line in h:
|
|
||||||
f.write(line)
|
|
||||||
|
|
||||||
# Finish
|
|
||||||
lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -4\n"
|
|
||||||
lines = lines + "\nRV_COMPLIANCE_DATA_END\n"
|
|
||||||
f.write(lines)
|
|
||||||
f.close()
|
|
||||||
r.close()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,286 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-JAL.py
|
|
||||||
#
|
|
||||||
# Ben Bracker (bbracker@hmc.edu) 19 January 2021
|
|
||||||
# Based on testgen-ADD-SUB.py by David Harris
|
|
||||||
#
|
|
||||||
# Generate directed and random test vectors for RISC-V Design Validation.
|
|
||||||
##################################
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# libraries
|
|
||||||
##################################
|
|
||||||
from datetime import datetime
|
|
||||||
from random import randint
|
|
||||||
from random import choice
|
|
||||||
from random import seed
|
|
||||||
from random import getrandbits
|
|
||||||
from copy import deepcopy
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# helper functions
|
|
||||||
##################################
|
|
||||||
def InitTestGroup():
|
|
||||||
global TestGroup,TestGroupSizes,AllRegs,UnusedRegs,StoreAdrReg
|
|
||||||
TestGroup += 1
|
|
||||||
TestGroupSizes.append(0)
|
|
||||||
UnusedRegs = deepcopy(AllRegs)
|
|
||||||
oldStoreAdrReg = StoreAdrReg
|
|
||||||
while ((StoreAdrReg == oldStoreAdrReg) or (StoreAdrReg == 0) or (StoreAdrReg == 31)):
|
|
||||||
StoreAdrReg = choice(UnusedRegs)
|
|
||||||
UnusedRegs.remove(StoreAdrReg)
|
|
||||||
f.write("\n # ---------------------------------------------------------------------------------------------\n")
|
|
||||||
f.write(" # new register for address of test results\n")
|
|
||||||
addInst(" la x"+str(StoreAdrReg)+", test_1_res\n")
|
|
||||||
f.write(" # ---------------------------------------------------------------------------------------------\n")
|
|
||||||
|
|
||||||
def registerSelect():
|
|
||||||
# ensures that rd experiences all possible registers
|
|
||||||
# *** does not yet ensure that rs experiences all possible registers
|
|
||||||
# ensures that at least once rd = rs
|
|
||||||
global UnusedRegs
|
|
||||||
if len(UnusedRegs)==0:
|
|
||||||
InitTestGroup()
|
|
||||||
rd = choice(UnusedRegs)
|
|
||||||
UnusedRegs.remove(rd)
|
|
||||||
OtherRegs = deepcopy(UnusedRegs)
|
|
||||||
if 0 in OtherRegs:
|
|
||||||
OtherRegs.remove(0)
|
|
||||||
if len(OtherRegs) == 0:
|
|
||||||
OtherRegs = deepcopy(AllRegs)
|
|
||||||
OtherRegs.remove(0)
|
|
||||||
rs = choice(OtherRegs)
|
|
||||||
OtherRegs = deepcopy(AllRegs)
|
|
||||||
OtherRegs.remove(StoreAdrReg)
|
|
||||||
OtherRegs.remove(rd)
|
|
||||||
if 0 in OtherRegs:
|
|
||||||
OtherRegs.remove(0)
|
|
||||||
if rs in OtherRegs:
|
|
||||||
OtherRegs.remove(rs)
|
|
||||||
DataReg = choice(OtherRegs)
|
|
||||||
OtherRegs.remove(DataReg)
|
|
||||||
OtherRd = choice(OtherRegs)
|
|
||||||
return (rd,rs,DataReg,OtherRd)
|
|
||||||
|
|
||||||
def addInst(line):
|
|
||||||
global CurrAdr
|
|
||||||
f.write(line)
|
|
||||||
if ("li x" in line) and ("slli x" not in line):
|
|
||||||
CurrAdr += 8 if (xlen == 32) else 20
|
|
||||||
elif ("la x" in line):
|
|
||||||
CurrAdr += 8
|
|
||||||
else:
|
|
||||||
CurrAdr += 4
|
|
||||||
|
|
||||||
def expectValue(expectReg, expectVal, sigOffset):
|
|
||||||
global TestGroupSizes
|
|
||||||
TestGroupSizes[TestGroup-1] += 1
|
|
||||||
addInst(" "+storecmd+" x"+str(expectReg)+", "+str(wordsize*sigOffset)+"(x"+str(StoreAdrReg)+")\n")
|
|
||||||
f.write(" RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(expectReg)+", "+formatstr.format(expectVal)+")\n")
|
|
||||||
if (xlen == 32):
|
|
||||||
r.write(formatrefstr.format(expectVal)+"\n")
|
|
||||||
else:
|
|
||||||
r.write(formatrefstr.format(expectVal % 2**32)+"\n" + formatrefstr.format(expectVal >> 32)+"\n")
|
|
||||||
|
|
||||||
def addJalr(rs,rd,dist):
|
|
||||||
target = CurrAdr + 20 + dist
|
|
||||||
target31_12 = CurrAdr >> 12 # 20 bits for lui
|
|
||||||
target11_0 = target - (target31_12 << 12) # 12 remaining bits
|
|
||||||
target31_16 = target31_12 >> 4 # lui sign extends, so shift in a leading 0
|
|
||||||
target15_12 = target31_12 - (target31_16 << 4) # the nibble we just lost
|
|
||||||
if target11_0 > 0:
|
|
||||||
offset = randint(-(1<<11)-1,(1<<11)-2-target11_0)
|
|
||||||
else:
|
|
||||||
offset = randint(-(1<<11)-1-target11_0,(1<<11)-2)
|
|
||||||
addInst(" lui x"+str(rs)+", 0x"+imm20formatstr.format(target31_16)+"\n")
|
|
||||||
addInst(" addi x"+str(rs)+", x"+str(rs)+", SEXT_IMM(0x0"+imm12formatstr.format(target15_12 << 8)+")\n")
|
|
||||||
addInst(" slli x"+str(rs)+", x"+str(rs)+", SEXT_IMM(4)\n")
|
|
||||||
addInst(" addi x"+str(rs)+", x"+str(rs)+", SEXT_IMM(0x"+imm12formatstr.format(0xfff&(offset+target11_0+randint(0,1)))+")\n")
|
|
||||||
addInst(" JALR x"+str(rd)+", x"+str(rs)+", SEXT_IMM(0x"+imm12formatstr.format(0xfff&(-offset))+")\n")
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# test functions
|
|
||||||
##################################
|
|
||||||
def writeForwardsJumpVector(spacers,instr):
|
|
||||||
global TestNum
|
|
||||||
TestNum += 1
|
|
||||||
rd, rs, DataReg, OtherRd = registerSelect()
|
|
||||||
# Header
|
|
||||||
f.write("\n")
|
|
||||||
f.write(" # Testcase "+str(TestNum)+"\n")
|
|
||||||
# Test Code
|
|
||||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(expected)+"\n")
|
|
||||||
if (instr=="JAL"):
|
|
||||||
addInst(" JAL x"+str(rd)+", 1f\n")
|
|
||||||
elif (instr=="JALR"):
|
|
||||||
dist = spacers*(8 if (xlen == 32) else 20) # Compute distance from linked adr to target adr
|
|
||||||
addJalr(rs,rd,dist);
|
|
||||||
else:
|
|
||||||
exit("invalid instruction")
|
|
||||||
LinkAdr = CurrAdr if (rd!=0) else 0 # rd's expected value
|
|
||||||
for i in range(spacers):
|
|
||||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n")
|
|
||||||
f.write("1:\n")
|
|
||||||
# Store values to be verified
|
|
||||||
expectValue(rd, LinkAdr, 2*TestNum+0)
|
|
||||||
expectValue(DataReg, expected, 2*TestNum+1)
|
|
||||||
|
|
||||||
def writeBackwardsJumpVector(spacers,instr):
|
|
||||||
global TestNum
|
|
||||||
TestNum += 1
|
|
||||||
rd, rs, DataReg, OtherRd = registerSelect()
|
|
||||||
# Header
|
|
||||||
f.write("\n")
|
|
||||||
f.write(" # Testcase "+str(TestNum)+"\n")
|
|
||||||
# Test Code
|
|
||||||
addInst(" JAL x"+str(OtherRd)+", 2f\n")
|
|
||||||
f.write("1:\n")
|
|
||||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(expected)+"\n")
|
|
||||||
addInst(" JAL x"+str(OtherRd)+", 3f\n")
|
|
||||||
f.write("2:\n")
|
|
||||||
for i in range(spacers):
|
|
||||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n")
|
|
||||||
if (instr=="JAL"):
|
|
||||||
addInst(" JAL x"+str(rd)+", 1b\n")
|
|
||||||
elif (instr=="JALR"):
|
|
||||||
dist = -20 - 4 - (1+spacers)*(8 if (xlen == 32) else 20) # Compute distance from linked adr to target adr
|
|
||||||
addJalr(rs,rd,dist);
|
|
||||||
else:
|
|
||||||
exit("invalid instruction")
|
|
||||||
LinkAdr = CurrAdr if (rd!=0) else 0 # rd's expected value
|
|
||||||
f.write("3:\n")
|
|
||||||
# Store values to be verified
|
|
||||||
expectValue(rd, LinkAdr, 2*TestNum+0)
|
|
||||||
expectValue(DataReg, expected, 2*TestNum+1)
|
|
||||||
|
|
||||||
def writeChainVector(repetitions,spacers):
|
|
||||||
global TestNum
|
|
||||||
TestNum += 1
|
|
||||||
rd, rs, DataReg,OtherRd = registerSelect()
|
|
||||||
# Header
|
|
||||||
f.write("\n")
|
|
||||||
f.write(" # Testcase "+str(TestNum)+"\n")
|
|
||||||
# Test Code
|
|
||||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(expected)+"\n")
|
|
||||||
for i in range(repetitions):
|
|
||||||
addInst(" JAL x"+str(OtherRd)+", "+str(3*i+2)+"f\n")
|
|
||||||
if spacers:
|
|
||||||
for j in range(i):
|
|
||||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n")
|
|
||||||
f.write(str(3*i+1)+":\n")
|
|
||||||
addInst(" JAL x"+str(OtherRd)+", "+str(3*i+3)+"f\n")
|
|
||||||
if spacers:
|
|
||||||
for j in range(i):
|
|
||||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n")
|
|
||||||
f.write(str(3*i+2)+":\n")
|
|
||||||
addInst(" JAL x"+str(rd)+", "+str(3*i+1)+"b\n")
|
|
||||||
LinkAdr = CurrAdr if (rd!=0) else 0 # rd's expected value
|
|
||||||
if spacers:
|
|
||||||
for j in range(i):
|
|
||||||
addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n")
|
|
||||||
f.write(str(3*i+3)+":\n")
|
|
||||||
# Store values to be verified
|
|
||||||
expectValue(rd, LinkAdr, 2*TestNum+0)
|
|
||||||
expectValue(DataReg, expected, 2*TestNum+1)
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# main body
|
|
||||||
##################################
|
|
||||||
|
|
||||||
# change these to suite your tests
|
|
||||||
test = 0
|
|
||||||
tests = ["JAL","JALR"]
|
|
||||||
author = "Ben Bracker (bbracker@hmc.edu)"
|
|
||||||
xlens = [32,64]
|
|
||||||
numtests = 100
|
|
||||||
|
|
||||||
# setup
|
|
||||||
seed(0) # make tests reproducible
|
|
||||||
|
|
||||||
# generate files for each test
|
|
||||||
for test in tests:
|
|
||||||
for xlen in xlens:
|
|
||||||
print(test+" "+str(xlen))
|
|
||||||
CurrAdr = int("80000108",16)
|
|
||||||
TestNum = -1
|
|
||||||
TestGroup = 1
|
|
||||||
TestGroupSizes = [0]
|
|
||||||
AllRegs = list(range(0,32))
|
|
||||||
UnusedRegs = deepcopy(AllRegs)
|
|
||||||
StoreAdrReg = 6 # matches what's in header script
|
|
||||||
UnusedRegs.remove(6)
|
|
||||||
if (xlen==64):
|
|
||||||
expected = int("fedbca9876540000",16)
|
|
||||||
unexpected = int("ffff0000ffff0000",16)
|
|
||||||
else:
|
|
||||||
expected = int("fedbca98",16)
|
|
||||||
unexpected = int("ff00ff00",16)
|
|
||||||
|
|
||||||
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
|
|
||||||
imm20formatstr = "{:05x}"
|
|
||||||
imm12formatstr = "{:03x}"
|
|
||||||
|
|
||||||
if (xlen == 32):
|
|
||||||
storecmd = "sw"
|
|
||||||
wordsize = 4
|
|
||||||
else:
|
|
||||||
storecmd = "sd"
|
|
||||||
wordsize = 8
|
|
||||||
|
|
||||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
|
||||||
basename = "WALLY-" + test
|
|
||||||
fname = imperaspath + "src/" + basename + ".S"
|
|
||||||
refname = imperaspath + "references/" + basename + ".reference_output"
|
|
||||||
|
|
||||||
# print custom header part
|
|
||||||
f = open(fname, "w")
|
|
||||||
r = open(refname, "w")
|
|
||||||
f.write("///////////////////////////////////////////\n")
|
|
||||||
f.write("// "+fname+ "\n")
|
|
||||||
f.write("//\n")
|
|
||||||
f.write("// This file can be used to test the RISC-V JAL(R) instruction.\n")
|
|
||||||
f.write("// But be warned that altering the test environment may break this test!\n")
|
|
||||||
f.write("// In order to work, this test expects that the first instruction (la)\n")
|
|
||||||
f.write("// be allocated at 0x80000100.\n")
|
|
||||||
f.write("//\n")
|
|
||||||
f.write("// " + author + "\n")
|
|
||||||
f.write("// Created "+str(datetime.now())+"\n")
|
|
||||||
|
|
||||||
# insert generic header
|
|
||||||
h = open("testgen_header.S", "r")
|
|
||||||
for line in h:
|
|
||||||
f.write(line)
|
|
||||||
|
|
||||||
# print directed test vectors
|
|
||||||
if test == "JAL":
|
|
||||||
for i in range(0,31):
|
|
||||||
writeForwardsJumpVector(randint(0,4),"JAL")
|
|
||||||
for i in range(0,31):
|
|
||||||
writeBackwardsJumpVector(randint(0,4),"JAL")
|
|
||||||
writeForwardsJumpVector(100,"JAL")
|
|
||||||
writeBackwardsJumpVector(100,"JAL")
|
|
||||||
writeChainVector(6,True)
|
|
||||||
writeChainVector(16,False)
|
|
||||||
elif test == "JALR":
|
|
||||||
for i in range(0,31):
|
|
||||||
writeForwardsJumpVector(randint(0,4),"JALR")
|
|
||||||
for i in range(0,31):
|
|
||||||
writeBackwardsJumpVector(randint(0,4),"JALR")
|
|
||||||
# can't make these latter two too long else 12 bit immediate overflows
|
|
||||||
# (would need to lui or slli rs to achieve longer ranges)
|
|
||||||
writeForwardsJumpVector(15,"JALR")
|
|
||||||
writeBackwardsJumpVector(15,"JALR")
|
|
||||||
|
|
||||||
# print footer
|
|
||||||
h = open("testgen_footer.S", "r")
|
|
||||||
for line in h:
|
|
||||||
f.write(line)
|
|
||||||
|
|
||||||
# Finish
|
|
||||||
f.write(".fill "+str(sum(TestGroupSizes))+", "+str(wordsize)+", -1\n")
|
|
||||||
f.write("\nRV_COMPLIANCE_DATA_END\n")
|
|
||||||
f.close()
|
|
||||||
r.close()
|
|
@ -1,227 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-LOAD.py
|
|
||||||
#
|
|
||||||
# Jarred Allen <jaallen@g.hmc.edu> 02 February 2021
|
|
||||||
#
|
|
||||||
# Generate directed and random test vectors for RISC-V Design Validation.
|
|
||||||
##################################
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# libraries
|
|
||||||
##################################
|
|
||||||
from datetime import datetime
|
|
||||||
from random import randint, seed, getrandbits
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# functions
|
|
||||||
##################################
|
|
||||||
|
|
||||||
def rand_reg():
|
|
||||||
"""Produce a random register (skipping 6 and 31, since they're used for other things)"""
|
|
||||||
r = randint(1,29)
|
|
||||||
if r >= 6:
|
|
||||||
r += 1
|
|
||||||
return r
|
|
||||||
|
|
||||||
def rand_value(width):
|
|
||||||
"""Generate a random value which fits in the given width"""
|
|
||||||
return randint(0, (1 << width) - 1)
|
|
||||||
|
|
||||||
def rand_offset():
|
|
||||||
"""Generate a random offset"""
|
|
||||||
ret = rand_value(12)
|
|
||||||
# print("Random offset: %d" % ret)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def rand_source():
|
|
||||||
"""Generate a random value for the source register, such that the load address is in the test data"""
|
|
||||||
ret = randint(1 << 12, (1 << 12) + (1 << 10))
|
|
||||||
# print("Random source: %d" % ret)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def add_offset_to_source(source, offset):
|
|
||||||
"""Find the address from the given source value and offset"""
|
|
||||||
if offset & 0x800:
|
|
||||||
offset -= 0x1000
|
|
||||||
return source + offset
|
|
||||||
|
|
||||||
def insert_into_data(test_data, source, offset, value, width, xlen):
|
|
||||||
"""Insert the given value into the given location of the test data"""
|
|
||||||
address = add_offset_to_source(source, offset)
|
|
||||||
# print("Test #%d" % testcase_num)
|
|
||||||
# print(f"Source: {source}, Offset: {offset}, Value: {value}, Width: {width}, xlen: {xlen}, Addr: {address}")
|
|
||||||
if address < 0:
|
|
||||||
return False
|
|
||||||
word_offset = address % (xlen // 8)
|
|
||||||
word_address = address - word_offset
|
|
||||||
if word_address in test_data:
|
|
||||||
return False
|
|
||||||
test_data[word_address] = value * (1 << (word_offset*8)) + ((~(((1 << width)-1) << (word_offset*8))) & rand_value(xlen))
|
|
||||||
# print(f"Word: {hex(test_data[word_address])}")
|
|
||||||
return True
|
|
||||||
|
|
||||||
def align(address, width):
|
|
||||||
"""Align the address to the given width, in bits"""
|
|
||||||
return address - (address % (width // 8))
|
|
||||||
|
|
||||||
testcase_num = 0
|
|
||||||
def generate_case(xlen, instruction, load_register, source_register, source_register_value, offset, expected):
|
|
||||||
"""Produce the specified test case and return it as a pair of strings, where the first is the test case and the second is the output"""
|
|
||||||
global testcase_num
|
|
||||||
if xlen == 64:
|
|
||||||
store = "sd"
|
|
||||||
elif xlen == 32:
|
|
||||||
if instruction in ["lwu", "ld"]:
|
|
||||||
raise Exception("Instruction %s not supported in RV32I" % instruction)
|
|
||||||
store = "sw"
|
|
||||||
else:
|
|
||||||
raise Exception("Unknown xlen value: %s" % xlen)
|
|
||||||
if offset >= 0x800:
|
|
||||||
offset -= 0x1000
|
|
||||||
if widths[instruction] != xlen:
|
|
||||||
expected = expected % (1 << widths[instruction])
|
|
||||||
if 'u' not in instruction:
|
|
||||||
if expected & (1 << (widths[instruction] - 1)):
|
|
||||||
expected = (expected + ~((1 << widths[instruction]) - 1)) & ((1 << xlen) - 1)
|
|
||||||
data = f"""# Testcase {testcase_num}: source {offset}(x{source_register} == {source_register_value}), result: x{load_register} == {expected}
|
|
||||||
la x31, test_data
|
|
||||||
lui x{source_register}, {source_register_value // (1 << 12)}
|
|
||||||
addi x{source_register}, x{source_register}, {source_register_value % (1 << 12)}
|
|
||||||
add x{source_register}, x{source_register}, x31
|
|
||||||
{instruction} x{load_register}, {offset}(x{source_register})
|
|
||||||
{store} x{load_register}, {(testcase_num*xlen//8) % 0x800}(x6)
|
|
||||||
RVTEST_IO_ASSERT_GPR_EQ(x8, x{load_register}, {expected})
|
|
||||||
|
|
||||||
"""
|
|
||||||
testcase_num += 1
|
|
||||||
if testcase_num*xlen//8 % 0x800 == 0:
|
|
||||||
data += "# Adjust x6 because we're storing too many things\naddi x6, x6, 1024\naddi x6, x6, 1024\n\n"
|
|
||||||
if xlen == 32:
|
|
||||||
reference_output = "{:08x}\n".format(expected)
|
|
||||||
elif xlen == 64:
|
|
||||||
reference_output = "{:08x}\n{:08x}\n".format(expected % (1 << 32), expected >> 32)
|
|
||||||
return (data, reference_output)
|
|
||||||
|
|
||||||
def write_header(outfile):
|
|
||||||
outfile.write(f"""///////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// WALLY-LOAD
|
|
||||||
//
|
|
||||||
// Author: {author}
|
|
||||||
//
|
|
||||||
// Created {str(datetime.now())}
|
|
||||||
//
|
|
||||||
""")
|
|
||||||
outfile.write(open("testgen_header.S", "r").read())
|
|
||||||
|
|
||||||
def write_test_data(outfile, test_data, xlen):
|
|
||||||
# print("Begin writing test data:")
|
|
||||||
# print("{} entries, from address {} to {}".format(len(test_data), min(test_data.keys()), max(test_data.keys())))
|
|
||||||
# print(test_data)
|
|
||||||
outfile.write("""
|
|
||||||
.align 16
|
|
||||||
test_data:
|
|
||||||
|
|
||||||
""")
|
|
||||||
if xlen == 32:
|
|
||||||
data_word = ".word"
|
|
||||||
elif xlen == 64:
|
|
||||||
data_word = ".dword"
|
|
||||||
else:
|
|
||||||
raise Exception("Unknown xlen: %d" % xlen)
|
|
||||||
byte_width = xlen // 8
|
|
||||||
for addr in [0] + sorted(test_data.keys()):
|
|
||||||
if addr in test_data:
|
|
||||||
word = f" {data_word} {hex(test_data[addr] % (1 << xlen))} # test_data+{hex(addr)}\n"
|
|
||||||
else:
|
|
||||||
word = ""
|
|
||||||
try:
|
|
||||||
fill_len = (min(k for k in test_data.keys() if k > addr) - addr) // byte_width - 1
|
|
||||||
if word == "":
|
|
||||||
fill_len += 1
|
|
||||||
fill = f" .fill {fill_len}, {byte_width}, 0x0\n"
|
|
||||||
except:
|
|
||||||
fill = ""
|
|
||||||
case = word+fill
|
|
||||||
outfile.write(case)
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# main body
|
|
||||||
##################################
|
|
||||||
|
|
||||||
widths = {
|
|
||||||
"lb": 8,
|
|
||||||
"lbu": 8,
|
|
||||||
"lh": 16,
|
|
||||||
"lhu": 16,
|
|
||||||
"lw": 32,
|
|
||||||
"lwu": 32,
|
|
||||||
"ld": 64,
|
|
||||||
}
|
|
||||||
instructions = [i for i in widths]
|
|
||||||
author = "Jarred Allen"
|
|
||||||
xlens = [32, 64]
|
|
||||||
numrand = 100;
|
|
||||||
|
|
||||||
# setup
|
|
||||||
seed(0) # make tests reproducible
|
|
||||||
|
|
||||||
for xlen in xlens:
|
|
||||||
testcase_num = 0
|
|
||||||
fname = "../../imperas-riscv-tests/riscv-test-suite/rv{}i/src/WALLY-LOAD.S".format(xlen)
|
|
||||||
refname = "../../imperas-riscv-tests/riscv-test-suite/rv{}i/references/WALLY-LOAD.reference_output".format(xlen)
|
|
||||||
f = open(fname, "w")
|
|
||||||
r = open(refname, "w")
|
|
||||||
write_header(f)
|
|
||||||
test_data = dict()
|
|
||||||
corner_values = [0x00, 0xFFFFFFFF, 0x7F, 0x7FFF, 0x7FFFFFFF]
|
|
||||||
if xlen == 64:
|
|
||||||
corner_values += [0xFFFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFF]
|
|
||||||
corner_offsets = [0x800, 0x000, 0x7FF]
|
|
||||||
for instruction in instructions:
|
|
||||||
print("Running xlen: %d, instruction: %s" % (xlen, instruction))
|
|
||||||
if xlen == 32:
|
|
||||||
if instruction in ["lwu", "ld"]:
|
|
||||||
continue
|
|
||||||
for value in corner_values + [rand_value(widths[instruction]) for _ in range(3)]:
|
|
||||||
value = value % (1 << widths[instruction])
|
|
||||||
source_reg = rand_source()
|
|
||||||
for offset in corner_offsets + [rand_offset() for _ in range(3)]:
|
|
||||||
offset = align(offset, widths[instruction])
|
|
||||||
source_reg = align(source_reg, widths[instruction])
|
|
||||||
if insert_into_data(test_data, source_reg, offset, value, widths[instruction], xlen):
|
|
||||||
data, output = generate_case(xlen, instruction, rand_reg(), rand_reg(), source_reg, offset, value)
|
|
||||||
f.write(data)
|
|
||||||
r.write(output)
|
|
||||||
while testcase_num % 4:
|
|
||||||
source = rand_source()
|
|
||||||
offset = rand_offset()
|
|
||||||
value = rand_value(widths[instruction])
|
|
||||||
if insert_into_data(test_data, source, offset, value, widths['lb'], xlen):
|
|
||||||
data, output = generate_case(xlen, 'lb', rand_reg(), rand_reg(), source, offset, value)
|
|
||||||
f.write(data)
|
|
||||||
r.write(output)
|
|
||||||
f.write("""# ---------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
RVTEST_IO_WRITE_STR(x31, "Test End\\n")
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
RV_COMPLIANCE_HALT
|
|
||||||
|
|
||||||
RV_COMPLIANCE_CODE_END
|
|
||||||
|
|
||||||
.data
|
|
||||||
# Input data section
|
|
||||||
""")
|
|
||||||
write_test_data(f, test_data, xlen)
|
|
||||||
f.write("""# Output data section.
|
|
||||||
RV_COMPLIANCE_DATA_BEGIN
|
|
||||||
|
|
||||||
test_1_res:
|
|
||||||
""")
|
|
||||||
f.write(f".fill {testcase_num}, {xlen//8}, -1\n")
|
|
||||||
f.write("\nRV_COMPLIANCE_DATA_END\n")
|
|
||||||
f.close()
|
|
||||||
r.close()
|
|
File diff suppressed because it is too large
Load Diff
@ -1,154 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-SLL-SRL-SRA.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):
|
|
||||||
amsb = a >> (xlen-1)
|
|
||||||
alsbs = ((1 << (xlen-1)) - 1) & a
|
|
||||||
if (amsb):
|
|
||||||
asigned = a - (1<<xlen)
|
|
||||||
else:
|
|
||||||
asigned = a
|
|
||||||
#print("a: " + str(a) + " amsb: "+str(amsb)+ " alsbs: " + str(alsbs) + " asigned: "+str(asigned))
|
|
||||||
return asigned
|
|
||||||
|
|
||||||
def computeExpected(a, b, test, xlen):
|
|
||||||
asigned = twoscomp(a)
|
|
||||||
b = b % xlen
|
|
||||||
if (test == "SLL"):
|
|
||||||
return a << b
|
|
||||||
elif (test == "SRL"):
|
|
||||||
return a >> b
|
|
||||||
elif (test == "SRA"):
|
|
||||||
return asigned >> b
|
|
||||||
else:
|
|
||||||
die("bad test name ", test)
|
|
||||||
# exit(1)
|
|
||||||
|
|
||||||
def randRegs():
|
|
||||||
reg1 = randint(1,31)
|
|
||||||
reg2 = randint(1,31)
|
|
||||||
reg3 = randint(1,31)
|
|
||||||
if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2):
|
|
||||||
return randRegs()
|
|
||||||
else:
|
|
||||||
return reg1, reg2, reg3
|
|
||||||
|
|
||||||
def writeVector(a, b, storecmd, xlen):
|
|
||||||
global testnum
|
|
||||||
expected = computeExpected(a, b, test, xlen)
|
|
||||||
expected = expected % 2**xlen # drop carry if necessary
|
|
||||||
if (expected < 0): # take twos complement
|
|
||||||
expected = 2**xlen + expected
|
|
||||||
reg1, reg2, reg3 = randRegs()
|
|
||||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
|
||||||
lines = lines + "), rs2:x" + str(reg2) + "(" +formatstr.format(b)
|
|
||||||
lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
|
||||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
|
||||||
lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
|
||||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", x" + str(reg2) + "\n"
|
|
||||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
|
||||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg3) +", "+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 = ["SLL", "SRL", "SRA"]
|
|
||||||
author = "David_Harris@hmc.edu"
|
|
||||||
xlens = [32, 64]
|
|
||||||
numrand = 48
|
|
||||||
|
|
||||||
# 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 test in tests:
|
|
||||||
corners = [0, 1, 2, 0xFF, 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]
|
|
||||||
if (xlen == 32):
|
|
||||||
shamt = [0, 1, 2, 3, 4, 8, 15, 16, 29, 30, 31]
|
|
||||||
else:
|
|
||||||
shamt = [0, 1, 3, 8, 15, 16, 29, 31, 32, 47, 48, 62, 63]
|
|
||||||
|
|
||||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
|
||||||
basename = "WALLY-" + test
|
|
||||||
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 a in corners:
|
|
||||||
for b in shamt:
|
|
||||||
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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,189 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-ADD-SUB.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 computeExpected(a, b, test):
|
|
||||||
if (test == "SLLI"):
|
|
||||||
return a << b
|
|
||||||
elif (test == "SRLI"):
|
|
||||||
return srli(a,b)
|
|
||||||
elif (test == "SRAI"):
|
|
||||||
return a >> b
|
|
||||||
else:
|
|
||||||
die("bad test name ", test)
|
|
||||||
# exit(1)
|
|
||||||
|
|
||||||
def signExt(b, bits):
|
|
||||||
a_str = bin(b)[2::]
|
|
||||||
if (a_str[0] == "b"):
|
|
||||||
a_str = a_str[1:]
|
|
||||||
|
|
||||||
if (len(a_str) < 12):
|
|
||||||
zeroPadding = "0" * (bits - len(a_str))
|
|
||||||
a_str = zeroPadding + a_str
|
|
||||||
|
|
||||||
print( "{:x}, {:s} ".format(b, a_str))
|
|
||||||
padding = a_str[len(a_str)-1] * (bits - len(a_str))
|
|
||||||
return int(padding + a_str, 2)
|
|
||||||
|
|
||||||
|
|
||||||
def evaluateTwoComplement(b, bits):
|
|
||||||
if (b & (1 << (bits -1))!= 0):
|
|
||||||
b = b - (1 << bits)
|
|
||||||
return b
|
|
||||||
|
|
||||||
|
|
||||||
def srli(a,b):
|
|
||||||
if (a < 0):
|
|
||||||
a = 2**xlen + a
|
|
||||||
if (b==0):
|
|
||||||
return a
|
|
||||||
a_str = bin(a)[2:]
|
|
||||||
if a_str[0]== "b":
|
|
||||||
a_str = a_str[1:]
|
|
||||||
# print(a_str)
|
|
||||||
numZeroPad = (len(a_str)-abs(b))
|
|
||||||
out = a_str[:numZeroPad]
|
|
||||||
if (numZeroPad <= 0):
|
|
||||||
return 0
|
|
||||||
print("a: {:b}, b: {:d}, out:{:b}".format(a, b, int(out,2)))
|
|
||||||
return int(out,2)
|
|
||||||
|
|
||||||
def randRegs():
|
|
||||||
reg1 = randint(1,31)
|
|
||||||
reg3 = randint(1,31)
|
|
||||||
if (reg1 == 6 or reg3 == 6):
|
|
||||||
return randRegs()
|
|
||||||
else:
|
|
||||||
return reg1, reg3
|
|
||||||
|
|
||||||
def writeVector(a, b, storecmd):
|
|
||||||
global testnum
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
expected = computeExpected(evaluateTwoComplement(a, xlen), b, test)
|
|
||||||
# print( "original {:x}, sign Extended {:x} ".format(b, signExt(b,xlen)))
|
|
||||||
# print (str(a) + "<" + str(signExt(b,xlen)) + " : " + str(expected))
|
|
||||||
expected = expected % 2**xlen # drop carry if necessary
|
|
||||||
if (expected < 0): # take twos complement
|
|
||||||
expected = 2**xlen + expected
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
reg1, reg3 = randRegs()
|
|
||||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
|
||||||
lines = lines + "), imm5:" + "(" +formatstrimm5.format(b)
|
|
||||||
lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
|
||||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
|
||||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", " + formatstrimm5.format(b) + "\n"
|
|
||||||
# lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
|
||||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
|
||||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " +"x" + str(reg3) +", "+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 = ["SLLI", "SRLI", "SRAI"]
|
|
||||||
author = "Shriya Nadgauda & Ethan Falicov"
|
|
||||||
xlens = [32, 64]
|
|
||||||
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
|
|
||||||
|
|
||||||
formatstrimm5 = "0b{:05b}" # format as 5-bit binary number
|
|
||||||
if (xlen == 32):
|
|
||||||
storecmd = "sw"
|
|
||||||
wordsize = 4
|
|
||||||
else:
|
|
||||||
storecmd = "sd"
|
|
||||||
wordsize = 8
|
|
||||||
|
|
||||||
for test in tests:
|
|
||||||
corners1 = [0, 1, 2, 0xFF, 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]
|
|
||||||
|
|
||||||
immBitSize = 5
|
|
||||||
corners2 = [0, 1, 2, 0x07, 0x14 % 2**immBitSize, 2**(immBitSize-1)-2, 2**(immBitSize-1)-1,
|
|
||||||
2**(immBitSize-1), 2**(immBitSize-1)+1, 0x06 % 2**immBitSize, 2**(immBitSize)-2, 2**(immBitSize)-1]
|
|
||||||
|
|
||||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
|
||||||
basename = "WALLY-" + test
|
|
||||||
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 a in corners1:
|
|
||||||
for b in corners2:
|
|
||||||
writeVector(a, b, storecmd)
|
|
||||||
for i in range(0,numrand):
|
|
||||||
a = getrandbits(xlen)
|
|
||||||
b = getrandbits(5)
|
|
||||||
writeVector(a, b, 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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,173 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-ADD-SUB.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 computeExpected(a, b, test):
|
|
||||||
if (test == "SLTIU"):
|
|
||||||
return a < b
|
|
||||||
else:
|
|
||||||
die("bad test name ", test)
|
|
||||||
# exit(1)
|
|
||||||
|
|
||||||
def signExt(b, bits):
|
|
||||||
a_str = bin(b)[2::]
|
|
||||||
if (a_str[0] == "b"):
|
|
||||||
a_str = a_str[1:]
|
|
||||||
|
|
||||||
if (len(a_str) < 12):
|
|
||||||
zeroPadding = "0" * (12 - len(a_str))
|
|
||||||
a_str = zeroPadding + a_str
|
|
||||||
|
|
||||||
|
|
||||||
padding = a_str[0] * (bits - len(a_str))
|
|
||||||
print( "b {:x}, sign extended {:s} ".format(b, padding + a_str))
|
|
||||||
return int(padding + a_str, 2)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def evaluateTwoComplement(b, bits):
|
|
||||||
if (b & (1 << (bits -1))!= 0):
|
|
||||||
b = b - (1 << bits)
|
|
||||||
return b
|
|
||||||
|
|
||||||
|
|
||||||
def randRegs():
|
|
||||||
reg1 = randint(1,31)
|
|
||||||
reg3 = randint(1,31)
|
|
||||||
if (reg1 == 6 or reg3 == 6):
|
|
||||||
return randRegs()
|
|
||||||
else:
|
|
||||||
return reg1, reg3
|
|
||||||
|
|
||||||
def writeVector(a, b, storecmd):
|
|
||||||
global testnum
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
signExtImm = signExt(b,xlen)
|
|
||||||
if signExtImm < 0:
|
|
||||||
signExtImm = signExtImm + 2 ** xlen
|
|
||||||
expected = computeExpected(a, signExtImm, test)
|
|
||||||
# s
|
|
||||||
|
|
||||||
expected = expected % 2**xlen # drop carry if necessary
|
|
||||||
if (expected < 0): # take twos complement
|
|
||||||
expected = 2**xlen + expected
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
reg1, reg3 = randRegs()
|
|
||||||
lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a)
|
|
||||||
lines = lines + "), imm12:" + "(" +formatstrimm12.format(b)
|
|
||||||
lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n"
|
|
||||||
lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n"
|
|
||||||
lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", SEXT_IMM(" + formatstrimm12.format(b) + ")\n"
|
|
||||||
# lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(b) + ")\n"
|
|
||||||
lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n"
|
|
||||||
lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " +"x" + str(reg3) +", "+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 = ["SLTIU"]
|
|
||||||
author = "Shriya Nadgauda & Ethan Falicov"
|
|
||||||
xlens = [32, 64]
|
|
||||||
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
|
|
||||||
|
|
||||||
formatstrimm12 = "0x{:03x}" # format as 3-bit hexadecimal number
|
|
||||||
if (xlen == 32):
|
|
||||||
storecmd = "sw"
|
|
||||||
wordsize = 4
|
|
||||||
else:
|
|
||||||
storecmd = "sd"
|
|
||||||
wordsize = 8
|
|
||||||
|
|
||||||
for test in tests:
|
|
||||||
corners1 = [0, 1, 2, 0xFF, 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]
|
|
||||||
|
|
||||||
immBitSize = 12
|
|
||||||
corners2 = [0, 1, 2, 0xFF, 0x624 % 2**immBitSize, 2**(immBitSize-1)-2, 2**(immBitSize-1)-1,
|
|
||||||
2**(immBitSize-1), 2**(immBitSize-1)+1, 0xC36 % 2**immBitSize, 2**(immBitSize)-2, 2**(immBitSize)-1]
|
|
||||||
|
|
||||||
imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/"
|
|
||||||
basename = "WALLY-" + test
|
|
||||||
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 a in corners1:
|
|
||||||
for b in corners2:
|
|
||||||
writeVector(a, b, storecmd)
|
|
||||||
for i in range(0,numrand):
|
|
||||||
a = getrandbits(xlen)
|
|
||||||
b = getrandbits(12)
|
|
||||||
writeVector(a, b, 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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,282 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-STORE.py
|
|
||||||
#
|
|
||||||
# Jessica Torrey <jtorrey@hmc.edu> 03 February 2021
|
|
||||||
# Thomas Fleming <tfleming@hmc.edu> 03 February 2021
|
|
||||||
#
|
|
||||||
# Generate directed and random test vectors for RISC-V Design Validation.
|
|
||||||
##################################
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# libraries
|
|
||||||
##################################
|
|
||||||
from datetime import datetime
|
|
||||||
from random import randint, seed, getrandbits
|
|
||||||
from textwrap import dedent
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# global structures
|
|
||||||
##################################
|
|
||||||
size_to_store = {8: "sd", 4: "sw", 2: "sh", 1: "sb"}
|
|
||||||
size_to_load = {8: "ld", 4: "lw", 2: "lh", 1: "lb"}
|
|
||||||
store_to_size = {"sd": 8, "sw": 4, "sh": 2, "sb": 1}
|
|
||||||
testcase_num = 0
|
|
||||||
signature_len = 2000
|
|
||||||
signature = [0xff for _ in range(signature_len)]
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# functions
|
|
||||||
##################################
|
|
||||||
|
|
||||||
def rand_reg():
|
|
||||||
"""
|
|
||||||
Produce a random register from 1 to 31 (skipping 6, since r6 is used for
|
|
||||||
other things).
|
|
||||||
"""
|
|
||||||
r = randint(1,30)
|
|
||||||
if r >= 6:
|
|
||||||
r += 1
|
|
||||||
return r
|
|
||||||
|
|
||||||
def rand_regs():
|
|
||||||
"""
|
|
||||||
Generate two random, unequal register numbers (skipping x6).
|
|
||||||
"""
|
|
||||||
rs1 = rand_reg()
|
|
||||||
rs2 = rand_reg()
|
|
||||||
while rs1 == rs2:
|
|
||||||
rs2 = rand_reg()
|
|
||||||
|
|
||||||
return rs1, rs2
|
|
||||||
|
|
||||||
def generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta):
|
|
||||||
"""
|
|
||||||
Create assembly code for a given STORE test case, returned as a string.
|
|
||||||
|
|
||||||
Generates an `xlen`-bit test case for `instruction` (one of sb, sh, sw, or
|
|
||||||
sd) that loads `value` into `value_register`, then attempts to store that
|
|
||||||
value in memory at address (x6 + `base_delta`). The test case
|
|
||||||
assumes the current base address for the signature is in register x6.
|
|
||||||
|
|
||||||
The form of the STORE instruction is as follows:
|
|
||||||
|
|
||||||
`instruction` `value_register` `offset`(`addr_register`)
|
|
||||||
"""
|
|
||||||
global testcase_num
|
|
||||||
|
|
||||||
hex_value = f"{value:0{xlen // 4}x}"
|
|
||||||
|
|
||||||
data = f"""# Testcase {testcase_num}: source: x{value_register} (value 0x{hex_value}), destination: {offset}(x{addr_register}) ({base_delta} bytes into signature)
|
|
||||||
addi x{addr_register}, x6, {base_delta}
|
|
||||||
li x{value_register}, MASK_XLEN({-offset})
|
|
||||||
add x{addr_register}, x{addr_register}, x{value_register}
|
|
||||||
li x{value_register}, 0x{hex_value}
|
|
||||||
{instruction} x{value_register}, {offset}(x{addr_register})
|
|
||||||
"""
|
|
||||||
|
|
||||||
update_signature(store_to_size[instruction], value, base_delta)
|
|
||||||
|
|
||||||
testcase_num += 1
|
|
||||||
return data
|
|
||||||
|
|
||||||
def validate_memory(scratch_register, value_register, value, base_delta, length):
|
|
||||||
"""
|
|
||||||
Create assembly code to verify that `length` bytes at mem[x6 + `base_delta`]
|
|
||||||
store `value`.
|
|
||||||
|
|
||||||
Assumes x6 stores the current base address for the signature.
|
|
||||||
"""
|
|
||||||
truncated_value = value & (2**(length * 8) - 1)
|
|
||||||
hex_value = f"{truncated_value:0{length * 2}x}"
|
|
||||||
|
|
||||||
load = size_to_load[length]
|
|
||||||
data = f"""addi x{scratch_register}, x6, {base_delta}
|
|
||||||
{load} x{value_register}, 0(x{scratch_register})
|
|
||||||
RVTEST_IO_ASSERT_GPR_EQ(x{scratch_register}, x{value_register}, 0x{hex_value})
|
|
||||||
|
|
||||||
"""
|
|
||||||
return data
|
|
||||||
|
|
||||||
def update_signature(length, value, base_delta):
|
|
||||||
"""
|
|
||||||
Write the lower `length` bytes of `value` to the little-endian signature
|
|
||||||
array, starting at byte `base_delta`.
|
|
||||||
"""
|
|
||||||
truncated_value = value & (2**(length * 8) - 1)
|
|
||||||
value_bytes = truncated_value.to_bytes(length, 'little')
|
|
||||||
#print("n: {}, value: {:x}, trunc: {:x}, length: {}, bd: {:x}".format(testcase_num, value, truncated_value, length, base_delta))
|
|
||||||
for i in range(length):
|
|
||||||
signature[base_delta + i] = value_bytes[i]
|
|
||||||
|
|
||||||
def write_signature(outfile):
|
|
||||||
"""
|
|
||||||
Writes successive 32-bit words from the signature array into a given file.
|
|
||||||
"""
|
|
||||||
for i in range(0, signature_len, 4):
|
|
||||||
word = list(reversed(signature[i:i+4]))
|
|
||||||
hexword = bytearray(word).hex()
|
|
||||||
outfile.write(f"{hexword}\n")
|
|
||||||
|
|
||||||
def write_header(outfile):
|
|
||||||
"""
|
|
||||||
Write the name of the test file, authors, and creation date.
|
|
||||||
"""
|
|
||||||
outfile.write(dedent(f"""\
|
|
||||||
///////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// WALLY-STORE
|
|
||||||
//
|
|
||||||
// Author: {author}
|
|
||||||
//
|
|
||||||
// Created {str(datetime.now())}
|
|
||||||
"""))
|
|
||||||
outfile.write(open("testgen_header.S", "r").read())
|
|
||||||
|
|
||||||
def write_footer(outfile):
|
|
||||||
"""
|
|
||||||
Write necessary closing code, including a data section for the signature.
|
|
||||||
"""
|
|
||||||
outfile.write(open("testgen_footer.S", 'r').read())
|
|
||||||
data_section = dedent(f"""\
|
|
||||||
\t.fill {signature_len}, 1, -1
|
|
||||||
RV_COMPLIANCE_DATA_END
|
|
||||||
""")
|
|
||||||
outfile.write(data_section)
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# test cases
|
|
||||||
##################################
|
|
||||||
|
|
||||||
def write_basic_tests(outfile, xlen, instr_len, num, base_delta):
|
|
||||||
"""
|
|
||||||
Test basic functionality of STORE, using random registers, offsets, and
|
|
||||||
values.
|
|
||||||
|
|
||||||
Creates `num` tests for a single store instruction of length `instr_len`,
|
|
||||||
writing to memory at consecutive locations, starting `base_delta` bytes from
|
|
||||||
the start of the signature.
|
|
||||||
|
|
||||||
Returns the number of bytes from the start of the signature where testing
|
|
||||||
ended.
|
|
||||||
"""
|
|
||||||
instruction = size_to_store[instr_len]
|
|
||||||
for i in range(num):
|
|
||||||
value_register, addr_register = rand_regs()
|
|
||||||
offset = randint(-2**(12 - 1), 2**(12 - 1) - 1)
|
|
||||||
value = randint(0, 2**(instr_len * 8) - 1)
|
|
||||||
test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta)
|
|
||||||
validate = validate_memory(addr_register, value_register, value, base_delta, instr_len)
|
|
||||||
outfile.write(test)
|
|
||||||
outfile.write(validate)
|
|
||||||
base_delta += instr_len
|
|
||||||
return base_delta
|
|
||||||
|
|
||||||
def write_random_store_tests(outfile, xlen, instr_len, num, min_base_delta):
|
|
||||||
"""
|
|
||||||
Test random access of STORE, using random registers, offsets, values, and
|
|
||||||
memory locations.
|
|
||||||
|
|
||||||
Creates `num` tests for a single store instruction of length `instr_len`,
|
|
||||||
writing to memory at random locations between `min_base_delta` bytes past
|
|
||||||
the start of the signature to the end of the signature.
|
|
||||||
"""
|
|
||||||
instruction = size_to_store[instr_len]
|
|
||||||
for i in range(num):
|
|
||||||
base_delta = randint(min_base_delta, signature_len - 1)
|
|
||||||
base_delta -= (base_delta % instr_len)
|
|
||||||
value_register, addr_register = rand_regs()
|
|
||||||
offset = randint(-2**(12 - 1), 2**(12 - 1) - 1)
|
|
||||||
value = randint(0, 2**(instr_len * 8) - 1)
|
|
||||||
|
|
||||||
test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta)
|
|
||||||
validate = validate_memory(addr_register, value_register, value, base_delta, instr_len)
|
|
||||||
outfile.write(test)
|
|
||||||
outfile.write(validate)
|
|
||||||
|
|
||||||
def write_repeated_store_tests(outfile, xlen, instr_len, num, base_delta):
|
|
||||||
"""
|
|
||||||
Test repeated access of STORE, using random registers, offsets, values, and a
|
|
||||||
single memory location.
|
|
||||||
|
|
||||||
Creates `num` tests for a single store instruction of length `instr_len`,
|
|
||||||
writing to memory `base_delta` bytes past the start of the signature.
|
|
||||||
"""
|
|
||||||
instruction = size_to_store[instr_len]
|
|
||||||
for i in range(num):
|
|
||||||
value_register, addr_register = rand_regs()
|
|
||||||
offset = 0
|
|
||||||
value = (1 << ((2 * i) % xlen))
|
|
||||||
|
|
||||||
test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta)
|
|
||||||
validate = validate_memory(addr_register, value_register, value, base_delta, instr_len)
|
|
||||||
|
|
||||||
outfile.write(test)
|
|
||||||
outfile.write(validate)
|
|
||||||
|
|
||||||
def write_corner_case_tests(outfile, xlen, instr_len, base_delta):
|
|
||||||
instruction = size_to_store[instr_len]
|
|
||||||
|
|
||||||
corner_cases_32 = [0x0, 0x10000001, 0x01111111]
|
|
||||||
corner_cases_64 = [0x1000000000000001, 0x0111111111111111]
|
|
||||||
corner_cases = corner_cases_32
|
|
||||||
if xlen == 64:
|
|
||||||
corner_cases += corner_cases_64
|
|
||||||
|
|
||||||
for offset in corner_cases:
|
|
||||||
for value in corner_cases:
|
|
||||||
value_register, addr_register = rand_regs()
|
|
||||||
test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta)
|
|
||||||
validate = validate_memory(addr_register, value_register, value, base_delta, instr_len)
|
|
||||||
|
|
||||||
outfile.write(test)
|
|
||||||
outfile.write(validate)
|
|
||||||
|
|
||||||
base_delta += instr_len
|
|
||||||
|
|
||||||
return base_delta
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# main body
|
|
||||||
##################################
|
|
||||||
|
|
||||||
instructions = ["sd", "sw", "sh", "sb"]
|
|
||||||
author = "Jessica Torrey <jtorrey@hmc.edu> & Thomas Fleming <tfleming@hmc.edu>"
|
|
||||||
xlens = [32, 64]
|
|
||||||
numrand = 100
|
|
||||||
|
|
||||||
# setup
|
|
||||||
seed(0) # make tests reproducible
|
|
||||||
|
|
||||||
for xlen in xlens:
|
|
||||||
if (xlen == 32):
|
|
||||||
wordsize = 4
|
|
||||||
else:
|
|
||||||
wordsize = 8
|
|
||||||
|
|
||||||
fname = f"../../imperas-riscv-tests/riscv-test-suite/rv{xlen}i/src/WALLY-STORE.S"
|
|
||||||
refname = f"../../imperas-riscv-tests/riscv-test-suite/rv{xlen}i/references/WALLY-STORE.reference_output"
|
|
||||||
f = open(fname, "w")
|
|
||||||
r = open(refname, "w")
|
|
||||||
|
|
||||||
write_header(f)
|
|
||||||
|
|
||||||
base_delta = 0
|
|
||||||
|
|
||||||
for instruction in instructions:
|
|
||||||
if xlen == 32 and instruction == 'sd':
|
|
||||||
continue
|
|
||||||
instr_len = store_to_size[instruction]
|
|
||||||
base_delta = write_basic_tests(f, xlen, instr_len, 5, base_delta)
|
|
||||||
write_repeated_store_tests(f, xlen, instr_len, 32, base_delta)
|
|
||||||
write_random_store_tests(f, xlen, instr_len, 5, base_delta + wordsize)
|
|
||||||
|
|
||||||
write_footer(f)
|
|
||||||
|
|
||||||
write_signature(r)
|
|
||||||
f.close()
|
|
||||||
r.close()
|
|
||||||
|
|
||||||
# Reset testcase_num and signature
|
|
||||||
testcase_num = 0
|
|
||||||
signature = [0xff for _ in range(signature_len)]
|
|
@ -1,285 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
##################################
|
|
||||||
# testgen-VIRTUALMEMORY.py
|
|
||||||
#
|
|
||||||
# Jessica Torrey <jtorrey@hmc.edu> 01 March 2021
|
|
||||||
# Thomas Fleming <tfleming@hmc.edu> 01 March 2021
|
|
||||||
#
|
|
||||||
# Generate an ad-hoc test program for RISC-V Design Validation. Tests the
|
|
||||||
# functionality of the memory management unit (MMU).
|
|
||||||
##################################
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# libraries
|
|
||||||
##################################
|
|
||||||
from datetime import datetime
|
|
||||||
from random import randint, seed, getrandbits
|
|
||||||
from textwrap import dedent
|
|
||||||
from virtual_memory_util import *
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# global structures
|
|
||||||
##################################
|
|
||||||
|
|
||||||
testcase_num = 0
|
|
||||||
signature_len = 2000
|
|
||||||
signature = [0xff for _ in range(signature_len)]
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# functions
|
|
||||||
##################################
|
|
||||||
|
|
||||||
def rand_reg():
|
|
||||||
"""
|
|
||||||
Produce a random register from 1 to 31 (skipping 6, since r6 is used for
|
|
||||||
other things).
|
|
||||||
"""
|
|
||||||
r = randint(1,30)
|
|
||||||
if r >= 6:
|
|
||||||
r += 1
|
|
||||||
return r
|
|
||||||
|
|
||||||
def rand_regs():
|
|
||||||
"""
|
|
||||||
Generate two random, unequal register numbers (skipping x6).
|
|
||||||
"""
|
|
||||||
rs1 = rand_reg()
|
|
||||||
rs2 = rand_reg()
|
|
||||||
while rs1 == rs2:
|
|
||||||
rs2 = rand_reg()
|
|
||||||
|
|
||||||
return rs1, rs2
|
|
||||||
|
|
||||||
def initialize_page_directory()
|
|
||||||
|
|
||||||
def generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta):
|
|
||||||
"""
|
|
||||||
Create assembly code for a given STORE test case, returned as a string.
|
|
||||||
|
|
||||||
Generates an `xlen`-bit test case for `instruction` (one of sb, sh, sw, or
|
|
||||||
sd) that loads `value` into `value_register`, then attempts to store that
|
|
||||||
value in memory at address (x6 + `base_delta`). The test case
|
|
||||||
assumes the current base address for the signature is in register x6.
|
|
||||||
|
|
||||||
The form of the STORE instruction is as follows:
|
|
||||||
|
|
||||||
`instruction` `value_register` `offset`(`addr_register`)
|
|
||||||
"""
|
|
||||||
global testcase_num
|
|
||||||
|
|
||||||
hex_value = f"{value:0{xlen // 4}x}"
|
|
||||||
|
|
||||||
data = f"""# Testcase {testcase_num}: source: x{value_register} (value 0x{hex_value}), destination: {offset}(x{addr_register}) ({base_delta} bytes into signature)
|
|
||||||
addi x{addr_register}, x6, {base_delta}
|
|
||||||
li x{value_register}, MASK_XLEN({-offset})
|
|
||||||
add x{addr_register}, x{addr_register}, x{value_register}
|
|
||||||
li x{value_register}, 0x{hex_value}
|
|
||||||
{instruction} x{value_register}, {offset}(x{addr_register})
|
|
||||||
"""
|
|
||||||
|
|
||||||
#update_signature(store_to_size[instruction], value, base_delta)
|
|
||||||
|
|
||||||
testcase_num += 1
|
|
||||||
return data
|
|
||||||
|
|
||||||
def validate_memory(scratch_register, value_register, value, base_delta, length):
|
|
||||||
"""
|
|
||||||
Create assembly code to verify that `length` bytes at mem[x6 + `base_delta`]
|
|
||||||
store `value`.
|
|
||||||
|
|
||||||
Assumes x6 stores the current base address for the signature.
|
|
||||||
"""
|
|
||||||
truncated_value = value & (2**(length * 8) - 1)
|
|
||||||
hex_value = f"{truncated_value:0{length * 2}x}"
|
|
||||||
|
|
||||||
load = size_to_load[length]
|
|
||||||
data = f"""addi x{scratch_register}, x6, {base_delta}
|
|
||||||
{load} x{value_register}, 0(x{scratch_register})
|
|
||||||
RVTEST_IO_ASSERT_GPR_EQ(x{scratch_register}, x{value_register}, 0x{hex_value})
|
|
||||||
|
|
||||||
"""
|
|
||||||
return data
|
|
||||||
|
|
||||||
def update_signature(length, value, base_delta):
|
|
||||||
"""
|
|
||||||
Write the lower `length` bytes of `value` to the little-endian signature
|
|
||||||
array, starting at byte `base_delta`.
|
|
||||||
"""
|
|
||||||
truncated_value = value & (2**(length * 8) - 1)
|
|
||||||
value_bytes = truncated_value.to_bytes(length, 'little')
|
|
||||||
#print("n: {}, value: {:x}, trunc: {:x}, length: {}, bd: {:x}".format(testcase_num, value, truncated_value, length, base_delta))
|
|
||||||
for i in range(length):
|
|
||||||
signature[base_delta + i] = value_bytes[i]
|
|
||||||
|
|
||||||
def write_signature(outfile):
|
|
||||||
"""
|
|
||||||
Writes successive 32-bit words from the signature array into a given file.
|
|
||||||
"""
|
|
||||||
for i in range(0, signature_len, 4):
|
|
||||||
word = list(reversed(signature[i:i+4]))
|
|
||||||
hexword = bytearray(word).hex()
|
|
||||||
outfile.write(f"{hexword}\n")
|
|
||||||
|
|
||||||
def write_header(outfile):
|
|
||||||
"""
|
|
||||||
Write the name of the test file, authors, and creation date.
|
|
||||||
"""
|
|
||||||
outfile.write(dedent(f"""\
|
|
||||||
///////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// WALLY-STORE
|
|
||||||
//
|
|
||||||
// Author: {author}
|
|
||||||
//
|
|
||||||
// Created {str(datetime.now())}
|
|
||||||
"""))
|
|
||||||
outfile.write(open("testgen_header.S", "r").read())
|
|
||||||
|
|
||||||
def write_footer(outfile):
|
|
||||||
"""
|
|
||||||
Write necessary closing code, including a data section for the signature.
|
|
||||||
"""
|
|
||||||
outfile.write(open("testgen_footer.S", 'r').read())
|
|
||||||
data_section = dedent(f"""\
|
|
||||||
\t.fill {signature_len}, 1, -1
|
|
||||||
RV_COMPLIANCE_DATA_END
|
|
||||||
""")
|
|
||||||
outfile.write(data_section)
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# test cases
|
|
||||||
##################################
|
|
||||||
|
|
||||||
def write_basic_tests(outfile, xlen, instr_len, num, base_delta):
|
|
||||||
"""
|
|
||||||
Test basic functionality of STORE, using random registers, offsets, and
|
|
||||||
values.
|
|
||||||
|
|
||||||
Creates `num` tests for a single store instruction of length `instr_len`,
|
|
||||||
writing to memory at consecutive locations, starting `base_delta` bytes from
|
|
||||||
the start of the signature.
|
|
||||||
|
|
||||||
Returns the number of bytes from the start of the signature where testing
|
|
||||||
ended.
|
|
||||||
"""
|
|
||||||
instruction = size_to_store[instr_len]
|
|
||||||
for i in range(num):
|
|
||||||
value_register, addr_register = rand_regs()
|
|
||||||
offset = randint(-2**(12 - 1), 2**(12 - 1) - 1)
|
|
||||||
value = randint(0, 2**(instr_len * 8) - 1)
|
|
||||||
test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta)
|
|
||||||
validate = validate_memory(addr_register, value_register, value, base_delta, instr_len)
|
|
||||||
outfile.write(test)
|
|
||||||
outfile.write(validate)
|
|
||||||
base_delta += instr_len
|
|
||||||
return base_delta
|
|
||||||
|
|
||||||
def write_random_store_tests(outfile, xlen, instr_len, num, min_base_delta):
|
|
||||||
"""
|
|
||||||
Test random access of STORE, using random registers, offsets, values, and
|
|
||||||
memory locations.
|
|
||||||
|
|
||||||
Creates `num` tests for a single store instruction of length `instr_len`,
|
|
||||||
writing to memory at random locations between `min_base_delta` bytes past
|
|
||||||
the start of the signature to the end of the signature.
|
|
||||||
"""
|
|
||||||
instruction = size_to_store[instr_len]
|
|
||||||
for i in range(num):
|
|
||||||
base_delta = randint(min_base_delta, signature_len - 1)
|
|
||||||
base_delta -= (base_delta % instr_len)
|
|
||||||
value_register, addr_register = rand_regs()
|
|
||||||
offset = randint(-2**(12 - 1), 2**(12 - 1) - 1)
|
|
||||||
value = randint(0, 2**(instr_len * 8) - 1)
|
|
||||||
|
|
||||||
test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta)
|
|
||||||
validate = validate_memory(addr_register, value_register, value, base_delta, instr_len)
|
|
||||||
outfile.write(test)
|
|
||||||
outfile.write(validate)
|
|
||||||
|
|
||||||
def write_repeated_store_tests(outfile, xlen, instr_len, num, base_delta):
|
|
||||||
"""
|
|
||||||
Test repeated access of STORE, using random registers, offsets, values, and a
|
|
||||||
single memory location.
|
|
||||||
|
|
||||||
Creates `num` tests for a single store instruction of length `instr_len`,
|
|
||||||
writing to memory `base_delta` bytes past the start of the signature.
|
|
||||||
"""
|
|
||||||
instruction = size_to_store[instr_len]
|
|
||||||
for i in range(num):
|
|
||||||
value_register, addr_register = rand_regs()
|
|
||||||
offset = 0
|
|
||||||
value = (1 << ((2 * i) % xlen))
|
|
||||||
|
|
||||||
test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta)
|
|
||||||
validate = validate_memory(addr_register, value_register, value, base_delta, instr_len)
|
|
||||||
|
|
||||||
outfile.write(test)
|
|
||||||
outfile.write(validate)
|
|
||||||
|
|
||||||
def write_corner_case_tests(outfile, xlen, instr_len, base_delta):
|
|
||||||
instruction = size_to_store[instr_len]
|
|
||||||
|
|
||||||
corner_cases_32 = [0x0, 0x10000001, 0x01111111]
|
|
||||||
corner_cases_64 = [0x1000000000000001, 0x0111111111111111]
|
|
||||||
corner_cases = corner_cases_32
|
|
||||||
if xlen == 64:
|
|
||||||
corner_cases += corner_cases_64
|
|
||||||
|
|
||||||
for offset in corner_cases:
|
|
||||||
for value in corner_cases:
|
|
||||||
value_register, addr_register = rand_regs()
|
|
||||||
test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta)
|
|
||||||
validate = validate_memory(addr_register, value_register, value, base_delta, instr_len)
|
|
||||||
|
|
||||||
outfile.write(test)
|
|
||||||
outfile.write(validate)
|
|
||||||
|
|
||||||
base_delta += instr_len
|
|
||||||
|
|
||||||
return base_delta
|
|
||||||
|
|
||||||
##################################
|
|
||||||
# main body
|
|
||||||
##################################
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
instructions = ["sd", "sw", "sh", "sb"]
|
|
||||||
author = "Jessica Torrey <jtorrey@hmc.edu> & Thomas Fleming <tfleming@hmc.edu>"
|
|
||||||
xlens = [32, 64]
|
|
||||||
numrand = 100
|
|
||||||
|
|
||||||
# setup
|
|
||||||
seed(0) # make tests reproducible
|
|
||||||
|
|
||||||
for xlen in xlens:
|
|
||||||
if (xlen == 32):
|
|
||||||
wordsize = 4
|
|
||||||
else:
|
|
||||||
wordsize = 8
|
|
||||||
|
|
||||||
fname = f"../../imperas-riscv-tests/riscv-test-suite/rv{xlen}i/src/WALLY-VIRTUALMEMORY.S"
|
|
||||||
refname = f"../../imperas-riscv-tests/riscv-test-suite/rv{xlen}i/references/WALLY-VIRTUALMEMORY.reference_output"
|
|
||||||
f = open(fname, "w")
|
|
||||||
r = open(refname, "w")
|
|
||||||
|
|
||||||
write_header(f)
|
|
||||||
|
|
||||||
base_delta = 0
|
|
||||||
|
|
||||||
for instruction in instructions:
|
|
||||||
if xlen == 32 and instruction == 'sd':
|
|
||||||
continue
|
|
||||||
instr_len = store_to_size[instruction]
|
|
||||||
base_delta = write_basic_tests(f, xlen, instr_len, 5, base_delta)
|
|
||||||
write_repeated_store_tests(f, xlen, instr_len, 32, base_delta)
|
|
||||||
write_random_store_tests(f, xlen, instr_len, 5, base_delta + wordsize)
|
|
||||||
|
|
||||||
write_footer(f)
|
|
||||||
|
|
||||||
write_signature(r)
|
|
||||||
f.close()
|
|
||||||
r.close()
|
|
||||||
|
|
||||||
# Reset testcase_num and signature
|
|
||||||
testcase_num = 0
|
|
||||||
signature = [0xff for _ in range(signature_len)]
|
|
Loading…
Reference in New Issue
Block a user