mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-03 10:15:19 +00:00
Merge pull request #983 from jordancarlin/remove-old-scripts
Remove more old scripts/files
This commit is contained in:
commit
3852b08fce
@ -1,42 +0,0 @@
|
||||
94e1819300002197
|
||||
4281420141014081
|
||||
4481440143814301
|
||||
4681460145814501
|
||||
4881480147814701
|
||||
4a814a0149814901
|
||||
4c814c014b814b01
|
||||
4e814e014d814d01
|
||||
0110011b4f814f01
|
||||
059b45011161016e
|
||||
0004063705fe0010
|
||||
05a000ef8006061b
|
||||
0ff003930000100f
|
||||
4e952e3110060e37
|
||||
c602829b0053f2b7
|
||||
2023fe02dfe312fd
|
||||
829b0053f2b7007e
|
||||
fe02dfe312fdc602
|
||||
4de31efd000e2023
|
||||
059bf1402573fdd0
|
||||
0000061705e20870
|
||||
0010029b01260613
|
||||
11010002806702fe
|
||||
84b2842ae426e822
|
||||
892ee04aec064505
|
||||
06e000ef07e000ef
|
||||
979334fd02905563
|
||||
07930177d4930204
|
||||
4089093394be2004
|
||||
04138522008905b3
|
||||
19e3014000ef2004
|
||||
64a2644260e2fe94
|
||||
6749808261056902
|
||||
dfed8b8510472783
|
||||
2423479110a73823
|
||||
10472783674910f7
|
||||
20058693ffed8b89
|
||||
05a1118737836749
|
||||
fed59be3fef5bc23
|
||||
1047278367498082
|
||||
67c98082dfed8b85
|
||||
0000808210a7a023
|
@ -1,11 +0,0 @@
|
||||
module BUFGCE (input logic I, input logic CE, output logic O);
|
||||
|
||||
logic CE_Q;
|
||||
always_latch begin
|
||||
if(~I) begin
|
||||
CE_Q <= CE;
|
||||
end
|
||||
end
|
||||
assign O = CE_Q & I;
|
||||
|
||||
endmodule
|
@ -1,32 +0,0 @@
|
||||
module BUFGCE_DIV #(parameter string DivideAmt = "1")
|
||||
(input logic I, input logic CLR, input logic CE, output logic O);
|
||||
|
||||
integer PulseCount = 0;
|
||||
logic Q;
|
||||
|
||||
always_ff @(posedge I, posedge CLR) begin
|
||||
if(CLR) PulseCount <= 0;
|
||||
else begin
|
||||
if(PulseCount < (DivideAmt.atoi()/2 - 1))
|
||||
PulseCount <= PulseCount + 1;
|
||||
else
|
||||
PulseCount <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
assign zero = PulseCount == 0;
|
||||
|
||||
|
||||
flopenr #(1) ToggleFlipFLop
|
||||
(.d(~Q),
|
||||
.q(Q),
|
||||
.clk(I),
|
||||
.reset(CLR), // reset when told by outside
|
||||
.en(zero)); // only update when counter overflows
|
||||
|
||||
if (DivideAmt != "1")
|
||||
assign O = Q;
|
||||
else
|
||||
assign O = I;
|
||||
|
||||
endmodule
|
@ -1,4 +0,0 @@
|
||||
module BUFGMUX(input logic I1, input logic I0, input logic S, output logic O);
|
||||
|
||||
assign O = S ? I1 : I0;
|
||||
endmodule
|
@ -1,56 +0,0 @@
|
||||
Procedure for Runnning SoftFloat/TestFloat with Wally
|
||||
|
||||
1.) First, compile SoftFloat and TestFloat by going to the addins
|
||||
directory and finding the specific build directory (e.g.,
|
||||
Linux_x86_64-GCC. Currently, we are using v3e of
|
||||
SoftFloat/TestFloat. I am not sure of the order, but I always compile
|
||||
SoftFloat first as I believe TestFloat uses the static library
|
||||
SoftFloat creates.
|
||||
|
||||
2.) Once compiled both, go to the tests/fp directory and run the
|
||||
create_vectors.sh Linux script. In the past, we have automated this,
|
||||
but I believe this has fallen into more of a manual state lately.
|
||||
|
||||
3.) Then, run remove_spaces.sh which will remove spaces from the
|
||||
output and put underscores between vectors (this helps differentiate
|
||||
the vectors that are generated). Again, this can be combined with
|
||||
Step 2.
|
||||
|
||||
4.) TestFloat is run from wally/cvw/sim and sim-testfloat-batch with
|
||||
its respective test. The format is ./sim-testfloat-add add. All of
|
||||
the tests are listed below. This can be augmented or added to for
|
||||
other FP tests given by the great SoftFloat/TestFloat output.
|
||||
|
||||
cvtint - test integer conversion unit (fcvtint)
|
||||
cvtfp - test floating-point conversion unit (fcvtfp)
|
||||
cmp - test comparison unit's LT, LE, EQ opperations (fcmp)
|
||||
add - test addition
|
||||
fma - test fma
|
||||
mul - test mult with fma
|
||||
sub - test subtraction
|
||||
div - test division
|
||||
sqrt - test square root
|
||||
all - test everything
|
||||
|
||||
4a.) Each test will test all its vectors - if you want to test a
|
||||
subset of the vectors (e.g., only binary16), you should modify the
|
||||
testfloat.do in the sim directory. Change the TEST_SIZE="all" to the
|
||||
specific test you want to run. For example, if you want to run only
|
||||
binary16, you should set this variable to TEST_SIZE="HP".
|
||||
|
||||
4b.) If you want to turn off the generation of wlf files while running
|
||||
sim-testfloat-batch, you can modify testfloat.do in the sim
|
||||
directory. Inside this DO file, modify the WAV file to 0 --> i.e.,
|
||||
set "quietly set WAV 0;"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
194
sim/bpred-sim.py
194
sim/bpred-sim.py
@ -1,194 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
##################################
|
||||
#
|
||||
# regression-wally
|
||||
# David_Harris@Hmc.edu 25 January 2021
|
||||
# Modified by Jarred Allen <jaallen@g.hmc.edu>
|
||||
#
|
||||
# Run a regression with multiple configurations in parallel and exit with
|
||||
# non-zero status code if an error happened, as well as printing human-readable
|
||||
# output.
|
||||
#
|
||||
##################################
|
||||
import sys,os,shutil
|
||||
import argparse
|
||||
|
||||
class bcolors:
|
||||
HEADER = '\033[95m'
|
||||
OKBLUE = '\033[94m'
|
||||
OKCYAN = '\033[96m'
|
||||
OKGREEN = '\033[92m'
|
||||
WARNING = '\033[93m'
|
||||
FAIL = '\033[91m'
|
||||
ENDC = '\033[0m'
|
||||
BOLD = '\033[1m'
|
||||
UNDERLINE = '\033[4m'
|
||||
|
||||
from collections import namedtuple
|
||||
regressionDir = os.path.dirname(os.path.abspath(__file__))
|
||||
os.chdir(regressionDir)
|
||||
|
||||
TestCase = namedtuple("TestCase", ['name', 'variant', 'cmd', 'grepstr'])
|
||||
# name: the name of this test configuration (used in printing human-readable
|
||||
# output and picking logfile names)
|
||||
# cmd: the command to run to test (should include the logfile as '{}', and
|
||||
# the command needs to write to that file)
|
||||
# grepstr: the string to grep through the log file for. The test succeeds iff
|
||||
# grep finds that string in the logfile (is used by grep, so it may
|
||||
# be any pattern grep accepts, see `man 1 grep` for more info).
|
||||
|
||||
# edit this list to add more test cases
|
||||
configs = [
|
||||
TestCase(
|
||||
name="lints",
|
||||
variant="all",
|
||||
cmd="./lint-wally | tee {}",
|
||||
grepstr="All lints run with no errors or warnings"
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
import os
|
||||
from multiprocessing import Pool, TimeoutError
|
||||
|
||||
def search_log_for_text(text, logfile):
|
||||
"""Search through the given log file for text, returning True if it is found or False if it is not"""
|
||||
grepcmd = "grep -e '%s' '%s' > /dev/null" % (text, logfile)
|
||||
return os.system(grepcmd) == 0
|
||||
|
||||
def run_test_case(config):
|
||||
"""Run the given test case, and return 0 if the test suceeds and 1 if it fails"""
|
||||
logname = "logs/"+config.variant+"_"+config.name+".log"
|
||||
cmd = config.cmd.format(logname)
|
||||
print(cmd)
|
||||
os.chdir(regressionDir)
|
||||
os.system(cmd)
|
||||
if search_log_for_text(config.grepstr, logname):
|
||||
print(f"{bcolors.OKGREEN}%s_%s: Success{bcolors.ENDC}" % (config.variant, config.name))
|
||||
return 0
|
||||
else:
|
||||
print(f"{bcolors.FAIL}%s_%s: Failures detected in output{bcolors.ENDC}" % (config.variant, config.name))
|
||||
print(" Check %s" % logname)
|
||||
return 1
|
||||
|
||||
def main():
|
||||
"""Run the tests and count the failures"""
|
||||
TIMEOUT_DUR = 10800 # 3 hours
|
||||
|
||||
global configs
|
||||
try:
|
||||
os.chdir(regressionDir)
|
||||
os.mkdir("logs")
|
||||
#print(os.getcwd())
|
||||
#print(regressionDir)
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
shutil.rmtree("wkdir")
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
os.mkdir("wkdir")
|
||||
|
||||
parser = argparse.ArgumentParser(description='Runs embench with sweeps of branch predictor sizes and types.')
|
||||
mode = parser.add_mutually_exclusive_group()
|
||||
mode.add_argument('-r', '--ras', action='store_const', help='Sweep size of return address stack (RAS).', default=False, const=True)
|
||||
mode.add_argument('-d', '--direction', action='store_const', help='Sweep size of direction prediction (2-bit, Gshare, local, etc).', default=False, const=True)
|
||||
mode.add_argument('-t', '--target', action='store_const', help='Sweep size of branch target buffer (BTB).', default=False, const=True)
|
||||
mode.add_argument('-c', '--iclass', action='store_const', help='Sweep size of classification (BTB) Same as -t.', default=False, const=True)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if(args.direction):
|
||||
# for direction predictor size sweep
|
||||
bpdSize = [6, 8, 10, 12, 14, 16]
|
||||
#bpdType = ['twobit', 'gshare', 'global', 'gshare_basic', 'global_basic', 'local_basic']
|
||||
bpdType = ['twobit', 'gshare']
|
||||
for CurrBPType in bpdType:
|
||||
for CurrBPSize in bpdSize:
|
||||
name = CurrBPType+str(CurrBPSize)
|
||||
configOptions = "+define+INSTR_CLASS_PRED=0 +define+BPRED_OVERRIDE +define+BPRED_TYPE=" + str(bpdType.index(CurrBPType)) + "+define+BPRED_SIZE=" + str(CurrBPSize)
|
||||
tc = TestCase(
|
||||
name=name,
|
||||
variant="rv32gc",
|
||||
cmd="vsim > {} -c <<!\ndo wally-batch.do rv32gc configOptions " + name + " embench " + configOptions,
|
||||
grepstr="")
|
||||
configs.append(tc)
|
||||
|
||||
if(args.target):
|
||||
# BTB and class size sweep
|
||||
bpdSize = [6, 8, 10, 12, 14, 16]
|
||||
for CurrBPSize in bpdSize:
|
||||
name = 'BTB'+str(CurrBPSize)
|
||||
configOptions = "+define+INSTR_CLASS_PRED=0 +define+BPRED_OVERRIDE +define+BPRED_TYPE=\`BP_GSHARE" + "+define+BPRED_SIZE=16" + "+define+RAS_SIZE=16+define+BTB_SIZE=" + str(CurrBPSize) + "+define+BTB_OVERRIDE"
|
||||
tc = TestCase(
|
||||
name=name,
|
||||
variant="rv32gc",
|
||||
cmd="vsim > {} -c <<!\ndo wally-batch.do rv32gc configOptions " + name + " embench " + configOptions,
|
||||
grepstr="")
|
||||
configs.append(tc)
|
||||
|
||||
if(args.iclass):
|
||||
# BTB and class size sweep
|
||||
bpdSize = [6, 8, 10, 12, 14, 16]
|
||||
for CurrBPSize in bpdSize:
|
||||
name = 'class'+str(CurrBPSize)
|
||||
configOptions = "+define+INSTR_CLASS_PRED=1 +define+BPRED_OVERRIDE +define+BPRED_TYPE=\`BP_GSHARE" + "+define+BPRED_SIZE=16" + "+define+RAS_SIZE=16+define+BTB_SIZE=" + str(CurrBPSize) + "+define+BTB_OVERRIDE"
|
||||
tc = TestCase(
|
||||
name=name,
|
||||
variant="rv32gc",
|
||||
cmd="vsim > {} -c <<!\ndo wally-batch.do rv32gc configOptions " + name + " embench " + configOptions,
|
||||
grepstr="")
|
||||
configs.append(tc)
|
||||
|
||||
# ras size sweep
|
||||
if(args.ras):
|
||||
bpdSize = [2, 3, 4, 6, 10, 16]
|
||||
for CurrBPSize in bpdSize:
|
||||
name = 'RAS'+str(CurrBPSize)
|
||||
configOptions = "+define+INSTR_CLASS_PRED=0 +define+BPRED_OVERRIDE +define+BPRED_TYPE=\`BP_GSHARE" + "+define+BPRED_SIZE=16" + "+define+BTB_SIZE=16" + "+define+RAS_SIZE=" + str(CurrBPSize) + "+define+BTB_OVERRIDE+define+RAS_OVERRIDE"
|
||||
tc = TestCase(
|
||||
name=name,
|
||||
variant="rv32gc",
|
||||
cmd="vsim > {} -c <<!\ndo wally-batch.do rv32gc configOptions " + name + " embench " + configOptions,
|
||||
grepstr="")
|
||||
configs.append(tc)
|
||||
|
||||
# bpdSize = [6, 8, 10, 12, 14, 16]
|
||||
# LHRSize = [4, 8, 10]
|
||||
# bpdType = ['local_repair']
|
||||
# for CurrBPType in bpdType:
|
||||
# for CurrBPSize in bpdSize:
|
||||
# for CurrLHRSize in LHRSize:
|
||||
# name = str(CurrLHRSize)+CurrBPType+str(CurrBPSize)
|
||||
# configOptions = "+define+INSTR_CLASS_PRED=0 +define+BPRED_TYPE=\"BP_" + CurrBPType.upper() + "\" +define+BPRED_SIZE=" + str(CurrBPSize) + " +define+BPRED_NUM_LHR=" + str(CurrLHRSize) + " "
|
||||
# tc = TestCase(
|
||||
# name=name,
|
||||
# variant="rv32gc",
|
||||
# cmd="vsim > {} -c <<!\ndo wally-batch.do rv32gc configOptions " + name + " embench " + configOptions,
|
||||
# grepstr="")
|
||||
# configs.append(tc)
|
||||
|
||||
# Scale the number of concurrent processes to the number of test cases, but
|
||||
# max out at a limited number of concurrent processes to not overwhelm the system
|
||||
with Pool(processes=min(len(configs),40)) as pool:
|
||||
num_fail = 0
|
||||
results = {}
|
||||
for config in configs:
|
||||
results[config] = pool.apply_async(run_test_case,(config,))
|
||||
for (config,result) in results.items():
|
||||
try:
|
||||
num_fail+=result.get(timeout=TIMEOUT_DUR)
|
||||
except TimeoutError:
|
||||
num_fail+=1
|
||||
print(f"{bcolors.FAIL}%s_%s: Timeout - runtime exceeded %d seconds{bcolors.ENDC}" % (config.variant, config.name, TIMEOUT_DUR))
|
||||
|
||||
# Count the number of failures
|
||||
if num_fail:
|
||||
print(f"{bcolors.FAIL}Regression failed with %s failed configurations{bcolors.ENDC}" % num_fail)
|
||||
else:
|
||||
print(f"{bcolors.OKGREEN}SUCCESS! All tests ran without failures{bcolors.ENDC}")
|
||||
return num_fail
|
||||
|
||||
if __name__ == '__main__':
|
||||
exit(main())
|
@ -1,42 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys, os, subprocess
|
||||
|
||||
def main():
|
||||
RISCV = os.environ.get("RISCV")
|
||||
maxGoodCount = 400e6 # num instrs that execute sucessfully starting from 0
|
||||
currInstrCount = maxGoodCount
|
||||
linuxTestvectors = RISCV+"/linux-testvectors"
|
||||
if not os.path.exists(linuxTestvectors):
|
||||
sys.stderr.write("Error: Linux testvectors not found at "+linuxTestvectors+"\n")
|
||||
exit(1)
|
||||
checkpointList = [int(fileName.strip('checkpoint')) for fileName in os.listdir(linuxTestvectors) if 'checkpoint' in fileName]
|
||||
checkpointList.sort()
|
||||
|
||||
logDir = "./logs/buildrootBugFinderLogs/"
|
||||
os.system("mkdir -p "+logDir)
|
||||
summaryLogFilePath = logDir+"summary.log"
|
||||
summaryLogFile = open(summaryLogFilePath,'w')
|
||||
summaryLogFile.close()
|
||||
while True:
|
||||
checkpointList = [checkpoint for checkpoint in checkpointList if checkpoint > currInstrCount]
|
||||
if len(checkpointList)==0:
|
||||
break
|
||||
checkpoint = checkpointList[0]
|
||||
logFile = logDir+"checkpoint"+str(checkpoint)+".log"
|
||||
runCommand="{\nvsim -c <<!\ndo wally-batch.do buildroot buildroot "+RISCV+" 0 "+str(checkpoint+1)+" "+str(checkpoint)+"\n!\n} | tee "+logFile
|
||||
print(runCommand)
|
||||
os.system(runCommand)
|
||||
try:
|
||||
logOutput = subprocess.check_output(["grep","-e","Reached",logFile])
|
||||
currInstrCount = int(str(logOutput).strip('b').strip('\'').strip('\\n').split(' ')[-2])
|
||||
except subprocess.CalledProcessError:
|
||||
currInstrCount = checkpoint
|
||||
summaryStr="Checkpoint "+str(checkpoint)+" reached "+str(currInstrCount)+" instrs\n"
|
||||
summaryLogFile = open(summaryLogFilePath,'a')
|
||||
summaryLogFile.write(summaryStr)
|
||||
summaryLogFile.close()
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
exit(main())
|
3
sim/xcelium/README.md
Normal file
3
sim/xcelium/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
## Xcelium Simulation with CVW
|
||||
|
||||
NOTE: Xcelium is not regularly tested and may not work correctly. It is also not integrated with the `wsim` command used for CVW, so the config and testsuite must be manually modified in `wally.xrun` and it does not support all of the other options provided by `wsim `.
|
@ -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)]
|
@ -1,27 +1,58 @@
|
||||
james.stine@okstate.edu 14 Jan 2022
|
||||
jcarlin@hmc.edu Sept 2024
|
||||
|
||||
These are the testvectors (TV) to test the floating-point unit using
|
||||
Berkeley TestFloat written originally by John Hauser. TestFloat
|
||||
requires both TestFloat and SoftFloat.
|
||||
## TestFloat for CVW
|
||||
|
||||
The locations of these tools at time of this README is found here:
|
||||
TestFloat-3e: http://www.jhauser.us/arithmetic/TestFloat.html
|
||||
SoftFloat-3e: http://www.jhauser.us/arithmetic/SoftFloat.html
|
||||
The CVW floating point unit is tested using testvectors from the Berkeley TestFloat suite, written originally by John Hauser.
|
||||
|
||||
These tools have been compiled on a x86_64 environment by going into
|
||||
their respective build/Linux-x86_64-GCC directories and running make.
|
||||
TestFloat and SoftFloat can be found as submodules in the addins directory, and are linked here:
|
||||
- TestFloat: https://github.com/ucb-bar/berkeley-testfloat-3
|
||||
- SoftFloat: https://github.com/ucb-bar/berkeley-softfloat-3
|
||||
|
||||
The makefile in the vectors subdirectory of this directory will generate TV
|
||||
for each rounding mode and operation. It also puts an underscore between each
|
||||
vector instead of a space to allow SystemVerilog readmemh to read correctly.
|
||||
### Compiling SoftFloat/TestFloat and Generating Testvectors
|
||||
|
||||
The makefile at the top level of this directory will compile SoftFloat and
|
||||
TestFloat and then generate all of the TVs. It also generates TVs for the
|
||||
combined integer floating-point divider.
|
||||
The entire testvector generation process can be performed by running make in this directory.
|
||||
|
||||
Although not needed, a case.sh script is included to change the case
|
||||
of the hex output. This is for those that do not like to see
|
||||
hexadecimal capitalized :P.
|
||||
```bash
|
||||
make --jobs
|
||||
```
|
||||
|
||||
This compiles SoftFloat for an x86_64 environment in its build/Linux-x86_64-GCC directory using the `SPECIALIZE_TYPE=RISCV` flag to get RISC-V behavior. TestFloat is then compiled in its build/Linux-x86_64-GCC directory using this SoftFloat library.
|
||||
|
||||
The Makefile in the vectors subdirectory of this directory is then called to generate testvectors for each rounding mode and operation. It also puts an underscore between each vector instead of a space to allow SystemVerilog `$readmemh` to read correctly.
|
||||
|
||||
Testvectors for the combined integer floating-point divider are also generated.
|
||||
|
||||
Although not needed, a `case.sh` script is included to change the case of the hex output. This is for those that do not like to see hexadecimal capitalized :P.
|
||||
|
||||
### Running TestFloat Vectors on Wally
|
||||
|
||||
TestFloat is run using the standard Wally simulation commands.
|
||||
|
||||
To run all TestFloat tests on many different derived configurations of Wally, use
|
||||
```bash
|
||||
regression-wally --testfloat
|
||||
```
|
||||
|
||||
To run a single test, use
|
||||
```bash
|
||||
wsim <config> <test> --tb testbench_fp
|
||||
```
|
||||
The choices for `<test>` are as follows:
|
||||
|
||||
>cvtint - test integer conversion unit (fcvtint)
|
||||
cvtfp - test floating-point conversion unit (fcvtfp)
|
||||
cmp - test comparison unit's LT, LE, EQ opperations (fcmp)
|
||||
add - test addition
|
||||
fma - test fma
|
||||
mul - test mult with fma
|
||||
sub - test subtraction
|
||||
div - test division
|
||||
sqrt - test square root
|
||||
|
||||
Any config that includes floating point support can be used. Each test will test all its vectors for all precisions supported by the given config.
|
||||
|
||||
### Testvector Count
|
||||
|
||||
46464 185856 836352 f16_add_rd.tv
|
||||
46464 185856 836352 f16_add_rne.tv
|
||||
|
Loading…
Reference in New Issue
Block a user