Merge branch 'main' of https://github.com/openhwgroup/cvw into breker

This commit is contained in:
Jordan Carlin 2024-12-19 12:27:38 -08:00
commit e52b7d835a
No known key found for this signature in database
6 changed files with 188 additions and 147 deletions

View file

@ -227,26 +227,28 @@ This utility will take up approximately 100 GB on your hard drive. You can also
wsim runs one of multiple simulators, Questa, VCS, or Verilator using a specific configuration and either a suite of tests or a specific elf file.
The general syntax is
`wsim <config> <suite or elf file or directory> [--options]`
`wsim <config> <suite or elf file> [--options]`
Parameters and options:
```
-h, --help show this help message and exit
--elf ELF, -e ELF ELF File name; use if name does not end in .elf
--sim {questa,verilator,vcs}, -s {questa,verilator,vcs} Simulator
--tb {testbench,testbench_fp}, -t {testbench,testbench_fp} Testbench
--gui, -g Simulate with GUI
--coverage, -c Code & Functional Coverage
--fcov, -f Code & Functional Coverage
--ccov, -c Code Coverage
--fcov, -f Functional Coverage with cvw-arch-verif, implies lockstep
--args ARGS, -a ARGS Optional arguments passed to simulator via $value$plusargs
--params PARAMS, -p PARAMS Optional top-level parameter overrides of the form param=value
--define DEFINE, -d DEFINE Optional define macros passed to simulator
--vcd, -v Generate testbench.vcd
--lockstep, -l Run ImperasDV lock, step, and compare.
--locksteplog LOCKSTEPLOG, -b LOCKSTEPLOG Retired instruction number to be begin logging.
--covlog COVLOG, -d COVLOG Log coverage after n instructions.
--elfext ELFEXT, -e ELFEXT When searching for elf files only includes ones which end in this extension
--lockstepverbose, -lv Run ImperasDV lock, step, and compare with tracing enabled
--rvvi, -r Simulate rvvi hardware interface and ethernet.
```
Run basic test with questa
Run basic test with Questa
```bash
wsim rv64gc arch64i
@ -258,26 +260,26 @@ Run Questa with gui
wsim rv64gc wally64priv --gui
```
Run lockstep against ImperasDV with a single elf file in the gui. Lockstep requires single elf.
Run basic test with Verilator
```bash
wsim rv64gc ../../tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/ref/ref.elf --lockstep --gui
wsim rv32i arch32i --sim verilator
```
Run lockstep against ImperasDV with a single elf file. Compute coverage.
Run lockstep against ImperasDV with a single elf file in the gui. Lockstep requires single elf.
```bash
wsim rv64gc ../../tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/ref/ref.elf --lockstep --coverage
wsim rv64gc $WALLY/tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/ref/ref.elf --lockstep --gui
```
Run lockstep against ImperasDV with directory file.
Run lockstep against ImperasDV with a single elf file. Collect functional coverage.
```bash
wsim rv64gc ../../tests/riscof/work/riscv-arch-test/rv64i_m/I/src/ --lockstep
wsim rv64gc $WALLY/addins/cvw-arch-verif/tests/rv64/Zicsr/WALLY-COV-ALL.elf --fcov
```
Run lockstep against ImperasDV with directory file and specify specific extension.
Run Linux boot simulation in lock step between Wally and ImperasDV
```bash
wsim rv64gc ../../tests/riscof/work/riscv-arch-test/rv64i_m/I/src/ --lockstep --elfext ref.elf
wsim buildroot buildroot --args +INSTR_LIMIT=600000000 --lockstep
```

@ -1 +1 @@
Subproject commit 95f849e42ef81562376fdc8fc4b91824fe7b5a36
Subproject commit efd70ce71a352eb8c4ca3d3b63d06a7b076078cb

View file

@ -13,27 +13,35 @@
`define CLINT_BASE 64'h02000000
// Unprivileged extensions
`include "RV32I_coverage.svh"
`include "RV32M_coverage.svh"
`include "RV32F_coverage.svh"
`include "RV32D_coverage.svh"
`include "RV32Zba_coverage.svh"
`include "RV32Zbb_coverage.svh"
`include "RV32Zbc_coverage.svh"
`include "RV32Zbs_coverage.svh"
`include "RV32ZfaF_coverage.svh"
`include "RV32ZfaD_coverage.svh"
`include "RV32ZfaZfh_coverage.svh"
`include "RV32ZfhD_coverage.svh"
`include "RV32Zfh_coverage.svh"
`include "RV32Zicond_coverage.svh"
`include "RV32Zca_coverage.svh"
`include "RV32Zcb_coverage.svh"
`include "RV32ZcbM_coverage.svh"
`include "RV32ZcbZbb_coverage.svh"
`include "RV32Zcf_coverage.svh"
`include "RV32Zcd_coverage.svh"
`include "RV32Zicsr_coverage.svh"
`include "I_coverage.svh"
`include "M_coverage.svh"
`include "F_coverage.svh"
`include "D_coverage.svh"
`include "Zba_coverage.svh"
`include "Zbb_coverage.svh"
`include "Zbc_coverage.svh"
`include "Zbs_coverage.svh"
`include "ZfaF_coverage.svh"
`include "ZfaD_coverage.svh"
`include "ZfaZfh_coverage.svh"
`include "Zfh_coverage.svh"
`include "ZfhD_coverage.svh"
`include "Zicond_coverage.svh"
`include "Zca_coverage.svh"
`include "Zcb_coverage.svh"
`include "ZcbM_coverage.svh"
`include "ZcbZbb_coverage.svh"
`include "Zcf_coverage.svh"
`include "Zcd_coverage.svh"
`include "Zicsr_coverage.svh"
`include "Zbkb_coverage.svh"
`include "Zbkc_coverage.svh"
`include "Zbkx_coverage.svh"
`include "Zknd_coverage.svh"
`include "Zkne_coverage.svh"
`include "Zknh_coverage.svh"
`include "Zaamo_coverage.svh"
`include "Zalrsc_coverage.svh"
// Privileged extensions
`include "ZicsrM_coverage.svh"

View file

@ -13,27 +13,35 @@
`define CLINT_BASE 64'h02000000
// Unprivileged extensions
`include "RV64I_coverage.svh"
`include "RV64M_coverage.svh"
`include "RV64F_coverage.svh"
`include "RV64D_coverage.svh"
`include "RV64Zba_coverage.svh"
`include "RV64Zbb_coverage.svh"
`include "RV64Zbc_coverage.svh"
`include "RV64Zbs_coverage.svh"
`include "RV64ZfaF_coverage.svh"
`include "RV64ZfaD_coverage.svh"
`include "RV64ZfaZfh_coverage.svh"
`include "RV64ZfhD_coverage.svh"
`include "RV64Zfh_coverage.svh"
`include "RV64Zicond_coverage.svh"
`include "RV64Zca_coverage.svh"
`include "RV64Zcb_coverage.svh"
`include "RV64ZcbM_coverage.svh"
`include "RV64ZcbZbb_coverage.svh"
`include "RV64ZcbZba_coverage.svh"
`include "RV64Zcd_coverage.svh"
`include "RV64Zicsr_coverage.svh"
`include "I_coverage.svh"
`include "M_coverage.svh"
`include "F_coverage.svh"
`include "D_coverage.svh"
`include "Zba_coverage.svh"
`include "Zbb_coverage.svh"
`include "Zbc_coverage.svh"
`include "Zbs_coverage.svh"
`include "ZfaF_coverage.svh"
`include "ZfaD_coverage.svh"
`include "ZfaZfh_coverage.svh"
`include "ZfhD_coverage.svh"
`include "Zfh_coverage.svh"
`include "Zicond_coverage.svh"
`include "Zca_coverage.svh"
`include "Zcb_coverage.svh"
`include "ZcbM_coverage.svh"
`include "ZcbZbb_coverage.svh"
`include "ZcbZba_coverage.svh"
`include "Zcd_coverage.svh"
`include "Zicsr_coverage.svh"
`include "Zbkb_coverage.svh"
`include "Zbkc_coverage.svh"
`include "Zbkx_coverage.svh"
`include "Zknd_coverage.svh"
`include "Zkne_coverage.svh"
`include "Zknh_coverage.svh"
`include "Zaamo_coverage.svh"
`include "Zalrsc_coverage.svh"
// Privileged extensions
`include "RV64VM_coverage.svh"

View file

@ -3,12 +3,12 @@
#
# Modification by Oklahoma State University & Harvey Mudd College
# Use with Testbench
# James Stine, 2008; David Harris 2021
# James Stine, 2008; David Harris 2021; Jordan Carlin 2024
# Go Cowboys!!!!!!
#
# Takes 1:10 to run RV64IC tests using gui
# Usage: do wally.do <config> <testcases> <testbench> [--ccov] [--fcov] [--gui] [--args "any number of +value"] [--params "any number of VAR=VAL parameter overrides"]
# Usage: do wally.do <config> <testcases> <testbench> [--ccov] [--fcov] [--gui] [--args "any number of +value"] [--params "any number of VAR=VAL parameter overrides"] [--define "any number of +define+VAR=VAL"]
# Example: do wally.do rv64gc arch64i testbench
# Use this wally.do file to run this example.
@ -77,20 +77,23 @@ set accFlag ""
# Need to be able to pass arguments to vopt. Unforunately argv does not work because
# it takes on different values if vsim and the do file are called from the command line or
# if the do file is called from questa sim directly. This chunk of code uses the $4 through $n
# variables and compacts into a single list for passing to vopt.
set from 4
set step 1
# if the do file is called from questa sim directly. This chunk of code uses the $n variables
# and compacts them into a single list for passing to vopt. Shift is used to move the arguments
# through the list.
set lst {}
echo "number of args = $argc"
for {set i 0} true {incr i} {
set x [expr {$i*$step + $from}]
if {$x > $argc} break
set arg [expr "$$x"]
lappend lst $arg
# Shift off the first three arguments (config, testcases, testbench)
shift
shift
shift
# Copy the remaining arguments into a list
while {$argc > 0} {
lappend lst [expr "\$1"]
shift
}
echo "number of args = $argc"
echo "lst = $lst"
# if +acc found set flag and remove from list
@ -109,10 +112,10 @@ if {[lcheck lst "--ccov"]} {
# if --fcov found set flag and remove from list
if {[lcheck lst "--fcov"]} {
set FunctCoverage 1
set FCvlog "+incdir+$env(WALLY)/addins/cvw-arch-verif/riscvISACOV/source \
+incdir+${FCRVVI}/rv32 +incdir+${FCRVVI}/rv64 \
set FCvlog "+incdir+${FCRVVI}/unpriv \
+incdir+${FCRVVI}/priv +incdir+${FCRVVI}/rv64_priv +incdir+${FCRVVI}/rv32_priv \
+incdir+${FCRVVI}/common +incdir+${FCRVVI}"
+incdir+${FCRVVI}/common +incdir+${FCRVVI} \
+incdir+$env(WALLY)/addins/cvw-arch-verif/riscvISACOV/source"
}
# if --lockstep or --fcov found set flag and remove from list
@ -180,7 +183,7 @@ if {$DEBUG > 0} {
# because vsim will run vopt
set INC_DIRS "+incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared"
set SOURCES "${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv"
vlog -permissive -lint -work ${WKDIR} {*}${INC_DIRS} {*}${DefineArgs} {*}${FCvlog} {*}${lockstepvlog} {*}${brekervlog} {*}${SOURCES} -suppress 2282,2583,7053,7063,2596,13286
vlog -permissive -lint -work ${WKDIR} {*}${INC_DIRS} {*}${FCvlog} {*}${DefineArgs} {*}${lockstepvlog} {*}${brekervlog} {*}${SOURCES} -suppress 2282,2583,7053,7063,2596,13286
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals

View file

@ -2,98 +2,118 @@
# run_vcs
# David_Harris@hmc.edu 2 July 2024
# Modified Jordan Carlin jcarlin@hmc.edu Dec 9 2024
# Run VCS on a given file, passing appropriate flags
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
import argparse
import os
import subprocess
import sys
# Global variables
WALLY = os.environ.get('WALLY')
simdir = f"{WALLY}/sim/vcs"
cfgdir = f"{WALLY}/config"
srcdir = f"{WALLY}/src"
tbdir = f"{WALLY}/testbench"
logdir = f"{simdir}/logs"
# run a Linux command and return the result as a string in a form that VCS can use
def runfindcmd(cmd):
# print("Executing: " + str(cmd) )
res = subprocess.check_output(cmd, shell=True)
def runFindCommand(cmd):
res = subprocess.check_output(cmd, shell=True, )
res = str(res)
res = res.replace("\\n", " ") # replace newline with space
res = res.replace("\'", "") # strip off quotation marks
res = res[1:] # strip off leading b from byte string
return res
parser = argparse.ArgumentParser()
parser.add_argument("config", help="Configuration file")
parser.add_argument("testsuite", help="Test suite (or none, when running a single ELF file) ")
parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench")
parser.add_argument("--ccov", "-c", help="Code Coverage", action="store_true")
parser.add_argument("--fcov", "-f", help="Functional Coverage", action="store_true")
parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="")
parser.add_argument("--params", "-p", help="Optional top-level parameter overrides of the form param=value", default="")
parser.add_argument("--define", "-d", help="Optional define macros passed to simulator", default="")
parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true")
# GUI not yet implemented
#parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true")
args = parser.parse_args()
print("run_vcs Config=" + args.config + " tests=" + args.testsuite + " lockstep=" + str(args.lockstep) + " args='" + args.args + "' params='" + args.params + "'" + " define='" + args.define + "'")
def parseArgs():
parser = argparse.ArgumentParser()
parser.add_argument("config", help="Configuration file")
parser.add_argument("testsuite", help="Test suite (or none, when running a single ELF file) ")
parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench")
parser.add_argument("--ccov", "-c", help="Code Coverage", action="store_true")
parser.add_argument("--fcov", "-f", help="Functional Coverage", action="store_true")
parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="")
parser.add_argument("--params", "-p", help="Optional top-level parameter overrides of the form param=value", default="")
parser.add_argument("--define", "-d", help="Optional define macros passed to simulator", default="")
parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true")
#parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true") # GUI not yet implemented
return parser.parse_args()
cfgdir = "$WALLY/config"
srcdir = "$WALLY/src"
tbdir = "$WALLY/testbench"
wkdir = "$WALLY/sim/vcs/wkdir/" + args.config + "_" + args.testsuite
covdir = "$WALLY/sim/vcs/cov/" + args.config + "_" + args.testsuite
logdir = "$WALLY/sim/vcs/logs"
def createDirs(args):
wkdir = f"{simdir}/wkdir/{args.config}_{args.testsuite}"
covdir = f"{simdir}/cov/{args.config}_{args.testsuite}"
os.makedirs(wkdir, exist_ok=True)
os.makedirs(covdir, exist_ok=True)
os.makedirs(logdir, exist_ok=True)
return wkdir, covdir
os.system("mkdir -p " + wkdir)
os.system("mkdir -p " + covdir)
os.system("mkdir -p " + logdir)
def generateFileList():
rtlsrc_cmd = f'find {srcdir} -name "*.sv" ! -path "{srcdir}/generic/mem/rom1p1r_128x64.sv" ! -path "{srcdir}/generic/mem/ram2p1r1wbe_128x64.sv" ! -path "{srcdir}/generic/mem/rom1p1r_128x32.sv" ! -path "{srcdir}/generic/mem/ram2p1r1wbe_2048x64.sv"'
rtlsrc_files = runFindCommand(rtlsrc_cmd)
tbcommon_cmd = f'find {tbdir}/common -name "*.sv"'
tbcommon_files = runFindCommand(tbcommon_cmd)
tb_file = f'{tbdir}/{args.tb}.sv'
return f"{tb_file} {rtlsrc_files} {tbcommon_files}"
# Find RTL source files
rtlsrc_cmd = "find " + srcdir + ' -name "*.sv" ! -path "' + srcdir + '/generic/mem/rom1p1r_128x64.sv" ! -path "' + srcdir + '/generic/mem/ram2p1r1wbe_128x64.sv" ! -path "' + srcdir + '/generic/mem/rom1p1r_128x32.sv" ! -path "' + srcdir + '/generic/mem/ram2p1r1wbe_2048x64.sv"'
rtlsrc_files = runfindcmd(rtlsrc_cmd)
tbcommon_cmd = 'find ' + tbdir+'/common -name "*.sv" ! -path "' + tbdir+'/common/wallyTracer.sv"'
tbcommon_files = runfindcmd(tbcommon_cmd)
tb_file = tbdir + "/" + args.tb + ".sv"
RTL_FILES = tb_file + ' ' + str(rtlsrc_files) + ' ' + str(tbcommon_files)
def processArgs(wkdir, args):
compileOptions = []
simvOptions = []
if args.lockstep:
compileOptions.extend(["+incdir+$IMPERAS_HOME/ImpPublic/include/host",
"+incdir+$IMPERAS_HOME/ImpProprietary/include/host",
"$IMPERAS_HOME/ImpPublic/source/host/rvvi/*.sv",
"$IMPERAS_HOME/ImpProprietary/source/host/idv/*.sv"])
simvOptions.append("-sv_lib $IMPERAS_HOME/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model")
if args.ccov:
compileOptions.extend(["-cm line+cond+branch+fsm+tgl", f"-cm_log {wkdir}/coverage.log", f"-cm_dir {wkdir}/coverage"])
if args.params:
compileOptions.append(setupParamOverrides(wkdir, args))
if args.define:
compileOptions.append(args.define)
# if args.gui:
# compileOptions.append("-debug_access+all+reverse -kdb +vcs+vcdpluson")
compileOptions = " ".join(compileOptions)
simvOptions = " ".join(simvOptions)
return compileOptions, simvOptions
# Include directories
INCLUDE_PATH="+incdir+" + cfgdir + "/" + args.config + " +incdir+" + cfgdir + "/deriv/" + args.config + " +incdir+" + cfgdir + "/shared +incdir+$WALLY/tests +incdir+" + tbdir + " +incdir+" + srcdir
def setupParamOverrides(wkdir, args):
paramOverrideFile = os.path.join(wkdir, "param_overrides.txt")
with open(paramOverrideFile, "w") as f:
for param in args.params.split():
[param, value] = param.split("=")
if fr"\'" in value: # for bit values
value = value.replace(fr"\'", "'")
else: # for strings
value = f'"{value}"'
f.write(f"assign {value} {args.tb}/{param}\n")
return f" -parameters {wkdir}/param_overrides.txt "
# lockstep mode
if (args.lockstep):
LOCKSTEP_OPTIONS = " +incdir+$IMPERAS_HOME/ImpPublic/include/host +incdir+$IMPERAS_HOME/ImpProprietary/include/host $IMPERAS_HOME/ImpPublic/source/host/rvvi/*.sv $IMPERAS_HOME/ImpProprietary/source/host/idv/*.sv " + tbdir + "/common/wallyTracer.sv"
LOCKSTEP_SIMV = "-sv_lib $IMPERAS_HOME/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model"
else:
LOCKSTEP_OPTIONS = ""
LOCKSTEP_SIMV = ""
def setupCommands(wkdir, rtlFiles, compileOptions, simvOptions, args):
includePath=f"+incdir+{cfgdir}/{args.config} +incdir+{cfgdir}/deriv/{args.config} +incdir+{cfgdir}/shared +incdir+$WALLY/tests +incdir+{tbdir} +incdir+{srcdir}"
vcsStandardFlags = "+lint=all,noGCWM,noUI,noSVA-UA,noIDTS,noNS,noULCO,noCAWM-L,noWMIA-L,noSV-PIU,noSTASKW_CO,noSTASKW_CO1,noSTASKW_RMCOF -suppress +warn -sverilog +vc -Mupdate -line -full64 -lca -ntb_opts sensitive_dyn"
vcsCMD = f"vcs {vcsStandardFlags} -top {args.tb} {compileOptions} -Mdir={wkdir} {includePath} {srcdir}/cvw.sv {rtlFiles} -o {wkdir}/sim_out -work {wkdir} -Mlib={wkdir} -l {logdir}/{args.config}_{args.testsuite}.log"
simvCMD = f"{wkdir}/sim_out +TEST={args.testsuite} {args.args} -no_save {simvOptions}"
return vcsCMD, simvCMD
# coverage mode
if (args.ccov):
COV_OPTIONS = "-cm line+cond+branch+fsm+tgl -cm_log " + wkdir + "/coverage.log -cm_dir " + wkdir + "/coverage"
else:
COV_OPTIONS = ""
def runVCS(wkdir, vcsCMD, simvCMD):
print(f"Executing: {vcsCMD}")
subprocess.run(vcsCMD, shell=True)
subprocess.run(simvCMD, shell=True)
if (args.ccov):
COV_RUN = f"urg -dir {wkdir}/coverage.vdb -format text -report IndividualCovReport/{args.config}_{args.testsuite}"
subprocess.run(COV_RUN, shell=True)
# Write parameter overrides to a file
f = open(os.path.expandvars(wkdir) + "/param_overrides.txt", "w")
for param in args.params.split():
[param, value] = param.split("=")
if "\\'" in value: # for bit values
value = value.replace("\\'", "'")
else: # for strings
value = "\"" + value + "\""
# print("param=" + param + " value=" + value)
f.write("assign " + value + " " + args.tb + "/" + param + "\n")
f.close()
PARAM_OVERRIDES=" -parameters " + wkdir + "/param_overrides.txt "
def main(args):
print(f"run_vcs Config={args.config} tests={args.testsuite} lockstep={args.lockstep} args='{args.args}' params='{args.params}' define='{args.define}'")
wkdir, covdir = createDirs(args)
rtlFiles = generateFileList()
compileOptions, simvOptions = processArgs(wkdir, args)
vcsCMD, simvCMD = setupCommands(wkdir, rtlFiles, compileOptions, simvOptions, args)
runVCS(wkdir, vcsCMD, simvCMD)
# Simulation commands
OUTPUT="sim_out"
VCS_CMD="vcs +lint=all,noGCWM,noUI,noSVA-UA,noIDTS,noNS,noULCO,noCAWM-L,noWMIA-L,noSV-PIU,noSTASKW_CO,noSTASKW_CO1,noSTASKW_RMCOF -suppress +warn -sverilog +vc -Mupdate -line -full64 -lca -ntb_opts sensitive_dyn " + "-top " + args.tb + " " + args.define + " " + PARAM_OVERRIDES + INCLUDE_PATH # Disabled Debug flags; add them back for a GUI mode -debug_access+all+reverse -kdb +vcs+vcdpluson
VCS = VCS_CMD + " -Mdir=" + wkdir + " " + srcdir + "/cvw.sv " + LOCKSTEP_OPTIONS + " " + COV_OPTIONS + " " + RTL_FILES + " -o " + wkdir + "/" + OUTPUT + " -work " + wkdir + " -Mlib=" + wkdir + " -l " + logdir + "/" + args.config + "_" + args.testsuite + ".log"
SIMV_CMD= wkdir + "/" + OUTPUT + " +TEST=" + args.testsuite + " " + args.args + " -no_save " + LOCKSTEP_SIMV
# Run simulation
print("Executing: " + str(VCS) )
subprocess.run(VCS, shell=True)
subprocess.run(SIMV_CMD, shell=True)
if (args.ccov):
COV_RUN = "urg -dir " + wkdir + "/coverage.vdb -format text -report IndividualCovReport/" + args.config + "_" + args.testsuite
subprocess.run(COV_RUN, shell=True)
if __name__ == "__main__":
args = parseArgs()
sys.exit(main(args))