From f7797d60925a96c4f719a20bd41316a61bf73c7e Mon Sep 17 00:00:00 2001 From: David Harris Date: Wed, 3 Jul 2024 14:54:46 -0700 Subject: [PATCH] First version of iterelf running; removed directory support from wsim --- .gitignore | 2 +- bin/iterelf | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++ bin/wsim | 95 +++++++++++++++++++------------------------------ 3 files changed, 138 insertions(+), 59 deletions(-) create mode 100755 bin/iterelf diff --git a/.gitignore b/.gitignore index 9a5f1668c..dd152a1d9 100644 --- a/.gitignore +++ b/.gitignore @@ -93,7 +93,7 @@ synthDC/wallyplots/ synthDC/runArchive synthDC/hdl sim/power.saif -tests/fp/vectors/*.tv +tests/fp/vectors synthDC/Summary.csv tests/custom/work tests/custom/*/*/*.list diff --git a/bin/iterelf b/bin/iterelf new file mode 100755 index 000000000..2f6441e59 --- /dev/null +++ b/bin/iterelf @@ -0,0 +1,100 @@ +#!/usr/bin/python3 + +# iterelf +# David_Harris@hmc.edu and Rose Thompson 7/3/2024 +# Run wsim on all the ELF files in a directory in parallel in lockstep + + +import argparse +import os +import multiprocessing +from multiprocessing import Pool, TimeoutError +TIMEOUT_DUR = 60 # 1` minute + +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' + +def search_log_for_mismatches(logfile): + """Search through the given log file for text, returning True if it is found or False if it is not""" + grepwarn = "grep -H Warning: " + logfile + os.system(grepwarn) + greperr = "grep -H Error: " + logfile + os.system(greperr) + grepcmd = "grep -a -e 'Mismatches : 0' '%s' > /dev/null" % logfile +# print(" search_log_for_text invoking %s" % grepcmd) + return os.system(grepcmd) == 0 + +def run_test_case(elf): + """Run the given test case, and return 0 if the test suceeds and 1 if it fails""" + WALLY = os.environ.get('WALLY') + fields = elf.rsplit('/', 3) + if (fields[2] == "ref"): + shortelf = fields[1] + "_" + fields[3] + else: + shorelf = fields[2] + "_" + fields[3] +# shortelf = fields[1] + "_" + fields[2] + logfile = WALLY + "/sim/" + args.sim + "/logs/" + shortelf + ".log" + cmd = "wsim " + args.config + " " + shortelf + " --elf " + elf + " --sim " + args.sim + " --lockstep > " + logfile # add coveerage flags if necessary +# print("cmd = " + cmd) + os.system(cmd) + if search_log_for_mismatches(logfile): + print(f"{bcolors.OKGREEN}%s: Success{bcolors.ENDC}" % (cmd)) + return 0 + else: + print(f"{bcolors.FAIL}%s: Failures detected in output{bcolors.ENDC}" % (cmd)) + print(" Check %s" % logfile) + return 1 + +################################## +# Main body +################################## + +# Parse arguments +parser = argparse.ArgumentParser() +parser.add_argument("dir", help="Configuration file") +parser.add_argument("--config", help="Configuration", default="rv64gc") +parser.add_argument("--sim", "-s", help="Simulator", choices=["questa", "vcs"], default="questa") +parser.add_argument("--coverage", "-c", help="Code & Functional Coverage", action="store_true") +parser.add_argument("--fcov", "-f", help="Code & Functional Coverage", action="store_true") +parser.add_argument("--exclude", help="Exclude files with this sufix", default="my.elf") +args = parser.parse_args() + +# find all ELF files in directory + +ElfList = [] +if (os.path.isdir(args.dir)): + DirectorMode = 1 + for dirpath, dirnames, filenames in os.walk(os.path.abspath(args.dir)): + for file in filenames: + if (file.endswith("elf") and not file.endswith(args.exclude)): + ElfList.append(os.path.join(dirpath, file)) +else: + print(args.dir + " is not a directory") + exit(1) +#print(ElfList) + +# spawn parallel wsim jobs for each ELF file + +ImperasDVLicenseCount = 8 +with Pool(processes=min(len(ElfList),multiprocessing.cpu_count(), ImperasDVLicenseCount)) as pool: + num_fail = 0 + results = {} + for elf in ElfList: + results[elf] = pool.apply_async(run_test_case,(elf,)) + for (elf,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}" % (elf, TIMEOUT_DUR)) +print("Completed %d tests with %d failures" % (len(ElfList), num_fail)) + +# *** generate memfiles \ No newline at end of file diff --git a/bin/wsim b/bin/wsim index 6a3963319..c10e5073e 100755 --- a/bin/wsim +++ b/bin/wsim @@ -14,44 +14,6 @@ import argparse import os - -def LaunchSim(ElfFile, flags): - cd = "cd $WALLY/sim/" +args.sim - - # per-simulator launch - if (args.sim == "questa"): - # Questa cannot accept more than 9 arguments. fcov implies lockstep - if (args.tb == "testbench_fp"): - args.args = " -GTEST=\"" + args.testsuite + "\" " + args.args - cmd = "do wally.do " + args.config + " " + args.testsuite + " " + args.tb + " " + args.args + " " + ElfFile + " " + flags - if (args.gui): # launch Questa with GUI; add +acc to keep variables accessible - if(args.tb == "testbench"): - cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc -GDEBUG=1\"" - elif(args.tb == "testbench_fp"): - cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc\"" - else: # launch Questa in batch mode - cmd = cd + "; " + prefix + " vsim -c -do \"" + cmd + "\"" - print("Running Questa with command: " + cmd) - os.system(cmd) - elif (args.sim == "verilator"): - # PWD=${WALLY}/sim CONFIG=rv64gc TESTSUITE=arch64i - print(f"Running Verilator on {args.config} {args.testsuite}") - os.system(f"/usr/bin/make -C {regressionDir}/verilator WALLYCONF={args.config} TEST={args.testsuite} TESTBENCH={args.tb} EXTRA_ARGS='{args.args}'") - elif (args.sim == "vcs"): - print(f"Running VCS on " + args.config + " " + args.testsuite) - if (args.gui): - args.args += "gui" - if (args.args == ""): - vcsargs = "" - else: - vcsargs = " --args " + args.args - if (ElfFile != ""): - ElfFile = " --elffile " + ElfFile - cmd = cd + "; ./run_vcs " + args.config + " " + args.testsuite + vcsargs + ElfFile + " " + flags - print(cmd) - os.system(cmd) - - ######################## # main wsim script ######################## @@ -60,6 +22,7 @@ def LaunchSim(ElfFile, flags): parser = argparse.ArgumentParser() parser.add_argument("config", help="Configuration file") parser.add_argument("testsuite", help="Test suite or ELF file") +parser.add_argument("--elf", "-e", help="ELF File name", default="") parser.add_argument("--sim", "-s", help="Simulator", choices=["questa", "verilator", "vcs"], default="questa") parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench") parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true") @@ -70,26 +33,14 @@ parser.add_argument("--vcd", "-v", help="Generate testbench.vcd", action="store_ parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true") parser.add_argument("--locksteplog", "-b", help="Retired instruction number to be begin logging.", default=0) parser.add_argument("--covlog", "-d", help="Log coverage after n instructions.", default=0) -parser.add_argument("--elfext", "-e", help="When searching for elf files only includes ones which end in this extension", default=".elf") args = parser.parse_args() print("Config=" + args.config + " tests=" + args.testsuite + " sim=" + args.sim + " gui=" + str(args.gui) + " args='" + args.args + "'") ElfFile="" DirectorMode = 0 -ElfList = [] WALLY = os.environ.get('WALLY') -if(os.path.isfile(args.testsuite)): - ElfFile = "+ElfFile=" + args.testsuite - args.testsuite = "none" - ElfList.append("+ElfFile=" + args.testsuite) -elif(os.path.isdir(args.testsuite)): - DirectorMode = 1 - for dirpath, dirnames, filenames in os.walk(args.testsuite): - for file in filenames: - if file.endswith(args.elfext): - ElfList.append("+ElfFile=" + os.path.join(dirpath, file)) - args.testsuite = "none" -print(ElfList) +if(os.path.isfile(args.elf)): + ElfFile = "+ElfFile=" + args.elf # Validate arguments if (args.gui or args.coverage or args.fcov or args.lockstep): @@ -135,10 +86,38 @@ for d in ["logs", "wkdir", "cov"]: os.mkdir(regressionDir+args.sim+"/"+d) except: pass - -if(DirectorMode): - for ElfFile in ElfList: - LaunchSim(ElfFile, flags) -else: - LaunchSim(ElfFile, flags) +cd = "cd $WALLY/sim/" +args.sim + +# per-simulator launch +if (args.sim == "questa"): + # Questa cannot accept more than 9 arguments. fcov implies lockstep + if (args.tb == "testbench_fp"): + args.args = " -GTEST=\"" + args.testsuite + "\" " + args.args + cmd = "do wally.do " + args.config + " " + args.testsuite + " " + args.tb + " " + args.args + " " + ElfFile + " " + flags + if (args.gui): # launch Questa with GUI; add +acc to keep variables accessible + if(args.tb == "testbench"): + cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc -GDEBUG=1\"" + elif(args.tb == "testbench_fp"): + cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc\"" + else: # launch Questa in batch mode + cmd = cd + "; " + prefix + " vsim -c -do \"" + cmd + "\"" + print("Running Questa with command: " + cmd) + os.system(cmd) +elif (args.sim == "verilator"): + # PWD=${WALLY}/sim CONFIG=rv64gc TESTSUITE=arch64i + print(f"Running Verilator on {args.config} {args.testsuite}") + os.system(f"/usr/bin/make -C {regressionDir}/verilator WALLYCONF={args.config} TEST={args.testsuite} TESTBENCH={args.tb} EXTRA_ARGS='{args.args}'") +elif (args.sim == "vcs"): + print(f"Running VCS on " + args.config + " " + args.testsuite) + if (args.gui): + args.args += "gui" + if (args.args == ""): + vcsargs = "" + else: + vcsargs = " --args " + args.args + if (ElfFile != ""): + ElfFile = " --elffile " + ElfFile + cmd = cd + "; ./run_vcs " + args.config + " " + args.testsuite + vcsargs + ElfFile + " " + flags + print(cmd) + os.system(cmd)