This commit is contained in:
Matthew Otto 2024-07-05 08:22:51 -05:00
parent 4c0ab90507
commit 5d34c4e95a
14 changed files with 282 additions and 668 deletions

View File

@ -692,7 +692,7 @@ def main():
# Define tests that we can run # Define tests that we can run
if (args.tests == "nightly"): if (args.tests == "nightly"):
test_list = [["python", "regression-wally", "--nightly"]] test_list = [["python", "regression-wally", "--nightly --buildroot"]]
elif (args.tests == "test"): elif (args.tests == "test"):
test_list = [["python", "regression-wally", ""]] test_list = [["python", "regression-wally", ""]]
elif (args.tests == "test_lint"): elif (args.tests == "test_lint"):

View File

@ -170,7 +170,7 @@ derivconfigtests = [
["fh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64zfh", "arch64zfh_divsqrt", "arch64zfaf"]], ["fh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64zfh", "arch64zfh_divsqrt", "arch64zfaf"]],
["fdh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt", "arch64zfaf", "arch64zfad"]], ["fdh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt", "arch64zfaf", "arch64zfad"]],
["fdq_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64i", "arch64zfaf", "arch64zfad"]], ["fdq_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64i", "arch64zfaf", "arch64zfad"]],
["fdqh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt", "arch64i", "wally64q", "arch64zfaf", "arch64zfad"]], ["fdqh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt", "arch64i", "arch64zfaf", "arch64zfad"]], # "wally64q" when Q is supported again in riscof config file
] ]
bpredtests = [ bpredtests = [
@ -312,20 +312,19 @@ regressionDir = WALLY + '/sim'
os.chdir(regressionDir) os.chdir(regressionDir)
coveragesim = "questa" # Questa is required for code/functional coverage coveragesim = "questa" # Questa is required for code/functional coverage
#defaultsim = "vcs" # Default simulator for all other tests; change to Verilator when flow is ready #defaultsim = "questa" # Default simulator for all other tests; change to Verilator when flow is ready
defaultsim = "questa" # Default simulator for all other tests; change to Verilator when flow is ready defaultsim = "verilator" # Default simulator for all other tests
#defaultsim = "verilator" # Default simulator for all other tests
coverage = '--coverage' in sys.argv coverage = '--coverage' in sys.argv
fp = '--fp' in sys.argv fp = '--fp' in sys.argv
nightly = '--nightly' in sys.argv nightly = '--nightly' in sys.argv
testfloat = '--testfloat' in sys.argv testfloat = '--testfloat' in sys.argv
buildroot = '--buildroot' in sys.argv
if (nightly): if (nightly):
nightMode = "--nightly"; nightMode = "--nightly";
# sims = [defaultsim] # sims = [defaultsim] # uncomment to use only the default simulator
sims = ["questa", "vcs"] sims = ["questa", "verilator", "vcs"] # uncomment to exercise all simulators
# sims = ["questa", "verilator", "vcs"] # *** uncomment to exercise all simulators
else: else:
nightMode = "" nightMode = ""
sims = [defaultsim] sims = [defaultsim]
@ -346,23 +345,26 @@ configs = [
grepfile = WALLY + "/sim/verilator/logs/all_lints.log") grepfile = WALLY + "/sim/verilator/logs/all_lints.log")
] ]
# run full buildroot boot simulation (slow) if buildroot flag is set. Start it early to overlap with other tests
if (buildroot):
addTests(tests_buildrootboot, defaultsim)
if (coverage): # only run RV64GC tests on Questa in coverage mode if (coverage): # only run RV64GC tests on Questa in coverage mode
addTests(tests64gc_nofp, "questa") addTests(tests64gc_nofp, "questa")
if (fp): if (fp):
addTests(tests64gc_fp, "questa") addTests(tests64gc_fp, "questa")
else: else:
for sim in sims: for sim in sims:
if (not (buildroot and sim == defaultsim)): # skip shot buildroot sim if running long one
addTests(tests_buildrootshort, sim)
addTests(tests, sim) addTests(tests, sim)
addTests(tests64gc_nofp, sim) addTests(tests64gc_nofp, sim)
addTests(tests64gc_fp, sim) addTests(tests64gc_fp, sim)
# run derivative configurations in nightly regression # run derivative configurations in nightly regression
if (nightly): if (nightly):
# addTests(tests_buildrootboot, defaultsim)
addTests(tests_buildrootshort, defaultsim)
addTests(derivconfigtests, defaultsim) addTests(derivconfigtests, defaultsim)
else:
addTests(tests_buildrootshort, defaultsim)
# testfloat tests # testfloat tests
if (testfloat): # for testfloat alone, just run testfloat tests if (testfloat): # for testfloat alone, just run testfloat tests
@ -433,9 +435,10 @@ def main():
"""Run the tests and count the failures""" """Run the tests and count the failures"""
global configs, coverage global configs, coverage
os.chdir(regressionDir) os.chdir(regressionDir)
os.system('rm -rf questa/wkdir') dirs = ["questa/logs", "questa/wkdir", "verilator/logs", "verilator/wkdir", "vcs/logs", "vcs/wkdir"]
for d in ["questa/logs", "questa/wkdir", "verilator/logs", "verilator/wkdir", "vcs/logs", "vcs/wkdir"]: for d in dirs:
try: try:
os.system('rm -rf %s' % d)
os.mkdir(d) os.mkdir(d)
except: except:
pass pass

View File

@ -46,7 +46,7 @@ sudo mkdir -p $RISCV
# Update and Upgrade tools (see https://itsfoss.com/apt-update-vs-upgrade/) # Update and Upgrade tools (see https://itsfoss.com/apt-update-vs-upgrade/)
sudo apt update -y sudo apt update -y
sudo apt upgrade -y sudo apt upgrade -y
sudo apt install -y git gawk make texinfo bison flex build-essential python3 libz-dev libexpat-dev autoconf device-tree-compiler ninja-build libpixman-1-dev ncurses-base ncurses-bin libncurses5-dev dialog curl wget ftp libgmp-dev libglib2.0-dev python3-pip pkg-config opam z3 zlib1g-dev automake autotools-dev libmpc-dev libmpfr-dev gperf libtool patchutils bc mutt ssmtp cmake gfortran usbutils sudo apt install -y git gawk make texinfo bison flex build-essential python3 libz-dev libexpat-dev autoconf device-tree-compiler ninja-build libpixman-1-dev ncurses-base ncurses-bin libncurses5-dev dialog curl wget ftp libgmp-dev libglib2.0-dev python3-pip pkg-config opam z3 zlib1g-dev automake autotools-dev libmpc-dev libmpfr-dev gperf libtool patchutils bc mutt ssmtp gfortran cmake libboost-all-dev
# Other python libraries used through the book. # Other python libraries used through the book.
sudo -H pip3 install sphinx sphinx_rtd_theme matplotlib scipy scikit-learn adjustText lief markdown pyyaml sudo -H pip3 install sphinx sphinx_rtd_theme matplotlib scipy scikit-learn adjustText lief markdown pyyaml
sudo -H pip3 install riscv_isac # to generate new tests, such as quads with fp_dataset.py sudo -H pip3 install riscv_isac # to generate new tests, such as quads with fp_dataset.py

View File

@ -14,38 +14,16 @@
import argparse import argparse
import os import os
def LaunchSim(ElfFile):
# Launch selected simulator def LaunchSim(ElfFile, flags):
cd = "cd $WALLY/sim/" +args.sim cd = "cd $WALLY/sim/" +args.sim
# ugh. can't have more than 9 arguments passed to vsim. why? I'll have to remove --lockstep when running
# functional coverage and imply it. # per-simulator launch
if (args.sim == "questa"): if (args.sim == "questa"):
if (args.lockstep): # Questa cannot accept more than 9 arguments. fcov implies lockstep
prefix = "IMPERAS_TOOLS=" + WALLY + "/sim/imperas.ic"
if(int(args.locksteplog) >= 1): EnableLog = 1
else: EnableLog = 0
if(args.locksteplog != 0): ImperasPlusArgs = " +IDV_TRACE2LOG=" + str(EnableLog) + " +IDV_TRACE2LOG_AFTER=" + str(args.locksteplog)
else: ImperasPlusArgs = ""
if(args.fcov):
CovEnableStr = "1" if int(args.covlog) > 0 else "0";
if(args.covlog >= 1): EnableLog = 1
else: EnableLog = 0
ImperasPlusArgs = " +IDV_TRACE2COV=" + str(EnableLog) + " +TRACE2LOG_AFTER=" + str(args.covlog) + " +TRACE2COV_ENABLE=" + CovEnableStr;
suffix = ""
else:
CovEnableStr = ""
suffix = "--lockstep"
else:
prefix = ""
ImperasPlusArgs = ""
suffix = ""
if (args.tb == "testbench_fp"): if (args.tb == "testbench_fp"):
args.args = " -GTEST=\"" + args.testsuite + "\" " + args.args args.args = " -GTEST=\"" + args.testsuite + "\" " + args.args
cmd = "do wally.do " + args.config + " " + args.testsuite + " " + args.tb + " " + args.args + " " + ElfFile + " " + suffix + " " + ImperasPlusArgs cmd = "do wally.do " + args.config + " " + args.testsuite + " " + args.tb + " " + args.args + " " + ElfFile + " " + flags
if (args.coverage):
cmd += " --coverage"
if (args.fcov):
cmd += " --fcov"
if (args.gui): # launch Questa with GUI; add +acc to keep variables accessible if (args.gui): # launch Questa with GUI; add +acc to keep variables accessible
if(args.tb == "testbench"): if(args.tb == "testbench"):
cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc -GDEBUG=1\"" cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc -GDEBUG=1\""
@ -58,24 +36,26 @@ def LaunchSim(ElfFile):
elif (args.sim == "verilator"): elif (args.sim == "verilator"):
# PWD=${WALLY}/sim CONFIG=rv64gc TESTSUITE=arch64i # PWD=${WALLY}/sim CONFIG=rv64gc TESTSUITE=arch64i
print(f"Running Verilator on {args.config} {args.testsuite}") print(f"Running Verilator on {args.config} {args.testsuite}")
if (args.coverage):
print("Coverage option not available for Verilator")
exit(1)
if (args.gui):
print("GUI option not available for Verilator")
exit(1)
os.system(f"/usr/bin/make -C {regressionDir}/verilator WALLYCONF={args.config} TEST={args.testsuite} TESTBENCH={args.tb} EXTRA_ARGS='{args.args}'") 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"): elif (args.sim == "vcs"):
print(f"Running VCS on " + args.config + " " + args.testsuite) print(f"Running VCS on " + args.config + " " + args.testsuite)
if (args.gui): if (args.gui):
args.args += "gui" args.args += "gui"
elif (args.coverage): if (args.args == ""):
args.args += "coverage" vcsargs = ""
cmd = cd + "; ./run_vcs " + args.config + " " + args.testsuite + " " + args.args else:
vcsargs = " --args " + args.args
if (ElfFile != ""):
ElfFile = " --elffile " + ElfFile
cmd = cd + "; ./run_vcs " + args.config + " " + args.testsuite + vcsargs + ElfFile + " " + flags
print(cmd) print(cmd)
os.system(cmd) os.system(cmd)
########################
# main wsim script
########################
# Parse arguments # Parse arguments
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("config", help="Configuration file") parser.add_argument("config", help="Configuration file")
@ -96,6 +76,7 @@ print("Config=" + args.config + " tests=" + args.testsuite + " sim=" + args.sim
ElfFile="" ElfFile=""
DirectorMode = 0 DirectorMode = 0
ElfList = [] ElfList = []
WALLY = os.environ.get('WALLY')
if(os.path.isfile(args.testsuite)): if(os.path.isfile(args.testsuite)):
ElfFile = "+ElfFile=" + args.testsuite ElfFile = "+ElfFile=" + args.testsuite
@ -111,21 +92,43 @@ elif(os.path.isdir(args.testsuite)):
print(ElfList) print(ElfList)
# Validate arguments # Validate arguments
if (args.gui): if (args.gui or args.coverage or args.fcov or args.lockstep):
if args.sim not in ["questa", "vcs"]: if args.sim not in ["questa", "vcs"]:
print("GUI option only supported for Questa and VCS") print("Option only supported for Questa and VCS")
exit(1)
if (args.coverage):
if args.sim not in ["questa", "vcs"]:
print("Coverage option only available for Questa and VCS")
exit(1) exit(1)
if (args.vcd): if (args.vcd):
args.args += " -DMAKEVCD=1" args.args += " -DMAKEVCD=1"
# if lockstep is enabled, then we need to pass the Imperas lockstep arguments
if(int(args.locksteplog) >= 1): EnableLog = 1
else: EnableLog = 0
if (args.lockstep):
prefix = "IMPERAS_TOOLS=" + WALLY + "/sim/imperas.ic"
if(args.locksteplog != 0): ImperasPlusArgs = " +IDV_TRACE2LOG=" + str(EnableLog) + " +IDV_TRACE2LOG_AFTER=" + str(args.locksteplog)
else: ImperasPlusArgs = ""
if(args.fcov):
CovEnableStr = "1" if int(args.covlog) > 0 else "0";
if(args.covlog >= 1): EnableLog = 1
else: EnableLog = 0
ImperasPlusArgs = " +IDV_TRACE2COV=" + str(EnableLog) + " +TRACE2LOG_AFTER=" + str(args.covlog) + " +TRACE2COV_ENABLE=" + CovEnableStr;
suffix = ""
else:
CovEnableStr = ""
suffix = "--lockstep"
else:
prefix = ""
ImperasPlusArgs = ""
suffix = ""
flags = suffix + " " + ImperasPlusArgs
# other flags
if (args.coverage):
flags += " --coverage"
if (args.fcov):
flags += " --fcov"
# create the output sub-directories. # create the output sub-directories.
WALLY = os.environ.get('WALLY')
regressionDir = WALLY + '/sim/' regressionDir = WALLY + '/sim/'
for d in ["logs", "wkdir", "cov"]: for d in ["logs", "wkdir", "cov"]:
try: try:
@ -135,7 +138,7 @@ for d in ["logs", "wkdir", "cov"]:
if(DirectorMode): if(DirectorMode):
for ElfFile in ElfList: for ElfFile in ElfList:
LaunchSim(ElfFile) LaunchSim(ElfFile, flags)
else: else:
LaunchSim(ElfFile) LaunchSim(ElfFile, flags)

View File

@ -811,11 +811,13 @@ deriv f_rv32gc rv32gc
D_SUPPORTED 0 D_SUPPORTED 0
ZCD_SUPPORTED 0 ZCD_SUPPORTED 0
ZFH_SUPPORTED 0 ZFH_SUPPORTED 0
ZCD_SUPPORTED 0
deriv fh_rv32gc rv32gc deriv fh_rv32gc rv32gc
D_SUPPORTED 0 D_SUPPORTED 0
ZCD_SUPPORTED 0 ZCD_SUPPORTED 0
ZFH_SUPPORTED 1 ZFH_SUPPORTED 1
ZCD_SUPPORTED 0
deriv fd_rv32gc rv32gc deriv fd_rv32gc rv32gc
ZFH_SUPPORTED 0 ZFH_SUPPORTED 0
@ -835,11 +837,13 @@ deriv f_rv64gc rv64gc
D_SUPPORTED 0 D_SUPPORTED 0
ZCD_SUPPORTED 0 ZCD_SUPPORTED 0
ZFH_SUPPORTED 0 ZFH_SUPPORTED 0
ZCD_SUPPORTED 0
deriv fh_rv64gc rv64gc deriv fh_rv64gc rv64gc
D_SUPPORTED 0 D_SUPPORTED 0
ZCD_SUPPORTED 0 ZCD_SUPPORTED 0
ZFH_SUPPORTED 1 ZFH_SUPPORTED 1
ZCD_SUPPORTED 0
deriv fd_rv64gc rv64gc deriv fd_rv64gc rv64gc
ZFH_SUPPORTED 0 ZFH_SUPPORTED 0

View File

@ -1,118 +1,84 @@
#!/bin/bash #!/usr/bin/python3
# VCS Compilation for WALLY
# Divya Kohli, Rose Thompson, David Harris 2024 # run_vcs
# Note: VCS produces warning about unsupported Linux Version, but runs successfully # David_Harris@hmc.edu 2 July 2024
# Run VCS on a given file, passing appropriate flags
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 # SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
# Color Definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Directories import argparse
CFG="${WALLY}/config" import os
SRC="${WALLY}/src" import subprocess
TB="${WALLY}/testbench"
# Set CONFIG_VARIANT from the first script argument # run a Linux command and return the result as a string in a form that VCS can use
CONFIG_VARIANT=${1} def runfindcmd(cmd):
# Set TESTSUITE from the second script argument # print("Executing: " + str(cmd) )
TESTSUITE=$2 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
WKDIR="wkdir/${1}_${2}" parser = argparse.ArgumentParser()
COV="cov/${1}_${2}" parser.add_argument("config", help="Configuration file")
LOGS="logs" parser.add_argument("testsuite", help="Test suite (or none, when running a single ELF file) ")
parser.add_argument("--elffile", "-e", help="ELF file name", default="")
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("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", 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 + " elffile=" + args.elffile + " lockstep=" + str(args.lockstep) + " args='" + args.args + "'")
if [ ${TESTSUITE} = "buildroot" ]; then cfgdir = "$WALLY/config"
shift 2 srcdir = "$WALLY/src"
PLUSARGS="$*" tbdir = "$WALLY/testbench"
fi wkdir = "$WALLY/sim/vcs/wkdir/" + args.config + "_" + args.testsuite
covdir = "$WALLY/sim/vcs/cov/" + args.config + "_" + args.testsuite
logdir = "$WALLY/sim/vcs/logs"
clean_logs() { os.system("mkdir -p " + wkdir)
echo -e "${YELLOW}Cleaning up workspace...${NC}" os.system("mkdir -p " + covdir)
rm -rf wkdir logs cov os.system("mkdir -p " + logdir)
}
clean_simprofile() {
echo -e "${YELLOW}Cleaning up simprofile_dir...${NC}"
rm -rf simprofile_dir* profileReport*
}
#clean_simprofile # Find RTL source files
#clean_logs 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"'
# Function to create a directory if it does not exist rtlsrc_files = runfindcmd(rtlsrc_cmd)
create_directory() { tbcommon_cmd = 'find ' + tbdir+'/common -name "*.sv" ! -path "' + tbdir+'/common/wallyTracer.sv"'
local dir=$1 # Local variable for directory name tbcommon_files = runfindcmd(tbcommon_cmd)
RTL_FILES = tbdir+'/testbench.sv ' + str(rtlsrc_files) + ' ' + str(tbcommon_files)
if [ ! -d "$dir" ]; then # Include directories
mkdir -p "$dir" INCLUDE_PATH="+incdir+" + cfgdir + "/" + args.config + " +incdir+" + cfgdir + "/deriv/" + args.config + " +incdir+" + cfgdir + "/shared +incdir+$WALLY/tests +incdir+" + tbdir + " +incdir+" + srcdir
if [ $? -eq 0 ]; then
echo "Directory $dir created successfully."
else
echo "Failed to create directory $dir."
exit 1
fi
else
echo "Directory $dir already exists."
fi
}
# Create or verify WKDIR, COV, and LOGS directories # lockstep mode
create_directory "$WKDIR" if (args.lockstep):
create_directory "$COV" LOCKSTEP_OPTIONS = " +define+USE_IMPERAS_DV +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"
create_directory "$LOGS" LOCKSTEP_SIMV = "-sv_lib $IMPERAS_HOME/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model"
else:
LOCKSTEP_OPTIONS = ""
LOCKSTEP_SIMV = ""
# Ensure the working directory exists # coverage mode
if [ ! -d "$WKDIR" ]; then if (args.coverage):
echo -e "${YELLOW}Directory $WKDIR does not exist. Creating it now...${NC}" COV_OPTIONS = "-cm line+cond+branch+fsm+tgl -cm_log " + wkdir + "/coverage.log -cm_dir " + wkdir + "/coverage"
mkdir -p "$WKDIR" && echo -e "${GREEN}Directory $WKDIR created successfully.${NC}" || { else:
echo -e "${RED}Failed to create directory $WKDIR.${NC}" COV_OPTIONS = ""
exit 1
}
else
echo -e "${GREEN}Directory $WKDIR already exists.${NC}"
fi
# GUI option handling # Simulation commands
GUI=""
if [ "$3" = "gui" ]; then
GUI="-gui"
else
GUI=""
fi
# Collect include directories
INCLUDE_DIRS=$(find ${SRC} -type d | xargs -I {} echo -n "{} ")
INCLUDE_PATH="+incdir+${CFG}/${CONFIG_VARIANT} +incdir+${CFG}/deriv/${CONFIG_VARIANT} +incdir+${CFG}/shared +incdir+../../tests +define+ +incdir+${TB} ${SRC}/cvw.sv +incdir+${SRC}"
# Prepare RTL files avoiding certain paths
RTL_FILES="$INCLUDE_DIRS $(find ${SRC} -name "*.sv" ! -path "${SRC}/generic/mem/rom1p1r_128x64.sv" ! -path "${SRC}/generic/mem/ram2p1r1wbe_128x64.sv" ! -path "${SRC}/generic/mem/rom1p1r_128x32.sv" ! -path "${SRC}/generic/mem/ram2p1r1wbe_2048x64.sv") ${TB}/testbench.sv $(find ${TB}/common -name "*.sv" ! -path "${TB}/common/wallyTracer.sv")"
# Simulation and Coverage Commands
OUTPUT="sim_out" 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 +vcs+vcdpluson -suppress +warn -sverilog +vc -Mupdate -line -full64 -kdb -lca -debug_access+all+reverse -ntb_opts sensitive_dyn ${INCLUDE_PATH} $RTL_FILES" 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 " + INCLUDE_PATH # Disabled Debug flags; add them back for a GUI mode -debug_access+all+reverse -kdb +vcs+vcdpluson
SIMV_CMD="./${WKDIR}/$OUTPUT +TEST=${TESTSUITE} ${PLUSARGS}" 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"
COV_FILES="${TB}/coverage/test_pmp_coverage.sv" SIMV_CMD= wkdir + "/" + OUTPUT + " +TEST=" + args.testsuite + " " + args.elffile + " " + args.args + " -no_save " + LOCKSTEP_SIMV
COV_OPTIONS="-cm line+cond+branch+fsm+tgl -cm_log ${WKDIR}/coverage.log -cm_dir ${WKDIR}/COVERAGE"
### CODE COVERAGE REPORT in IndividualCovReport in XML format
#COV_RUN="urg -dir ${WKDIR}/COVERAGE.vdb -report IndividualCovReport/${CONFIG_VARIANT}_${TESTSUITE}"
### CODE COVERAGE REPORT in IndividualCovReport in text format
COV_RUN="urg -dir ./${WKDIR}/COVERAGE.vdb -format text -report IndividualCovReport/${CONFIG_VARIANT}_${TESTSUITE}"
# Run simulation
# Clean and run simulation with VCS print("Executing: " + str(VCS) )
subprocess.run(VCS, shell=True)
if [ "$3" = "coverage" ]; then subprocess.run(SIMV_CMD, shell=True)
echo -e "${YELLOW}#### Running VCS Simulation with Coverage ####${NC}" if (args.coverage):
# Code Coverage. COV_RUN = "urg -dir " + wkdir + "/coverage.vdb -format text -report IndividualCovReport/" + args.config + "_" + args.testsuite
$VCS_CMD -Mdir=${WKDIR} $COV_OPTIONS -o ${WKDIR}/$OUTPUT -Mlib ${WKDIR} -work ${WKDIR} -l "$LOGS/${CONFIG_VARIANT}_${TESTSUITE}.log" subprocess.run(COV_RUN, shell=True)
$SIMV_CMD $COV_OPTIONS
$COV_RUN
#cp -rf urgReport $COV
else
echo -e "${YELLOW}#### Running VCS Simulation ####${NC}"
$VCS_CMD -Mdir=${WKDIR} -o ${WKDIR}/$OUTPUT -work ${WKDIR} -Mlib ${WKDIR} -l "$LOGS/${CONFIG_VARIANT}_${TESTSUITE}.log"
$SIMV_CMD
fi

View File

@ -116,7 +116,7 @@ module ebu import cvw::*; #(parameter cvw_t P) (
assign HBURST = LSUSelect ? LSUHBURSTOut : IFUSelect ? IFUHBURSTOut : '0; // If doing memory accesses, use LSUburst, else use Instruction burst. assign HBURST = LSUSelect ? LSUHBURSTOut : IFUSelect ? IFUHBURSTOut : '0; // If doing memory accesses, use LSUburst, else use Instruction burst.
assign HTRANS = LSUSelect ? LSUHTRANSOut : IFUSelect ? IFUHTRANSOut: '0; // SEQ if not first read or write, NONSEQ if first read or write, IDLE otherwise assign HTRANS = LSUSelect ? LSUHTRANSOut : IFUSelect ? IFUHTRANSOut: '0; // SEQ if not first read or write, NONSEQ if first read or write, IDLE otherwise
assign HWRITE = LSUSelect ? LSUHWRITEOut : '0; assign HWRITE = LSUSelect ? LSUHWRITEOut : '0;
assign HPROT = 4'b0011; // not used; see Section 3.7 assign HPROT = {3'b001, LSUSelect}; // treat as privileged access of either Opcode fetch or Data access
assign HMASTLOCK = 1'b0; // no locking supported assign HMASTLOCK = 1'b0; // no locking supported
// data phase muxing. This would be a mux if IFU wrote data. // data phase muxing. This would be a mux if IFU wrote data.

View File

@ -56,8 +56,8 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
logic [`NUM_REGS-1:0] frf_wb; logic [`NUM_REGS-1:0] frf_wb;
logic [4:0] frf_a4; logic [4:0] frf_a4;
logic frf_we4; logic frf_we4;
logic [P.XLEN-1:0] CSRArray [logic[11:0]]; logic [P.XLEN-1:0] CSRArray [4095:0];
logic [P.XLEN-1:0] CSRArrayOld [logic[11:0]]; logic [P.XLEN-1:0] CSRArrayOld [4095:0];
logic [`NUM_CSRS-1:0] CSR_W; logic [`NUM_CSRS-1:0] CSR_W;
logic CSRWriteM, CSRWriteW; logic CSRWriteM, CSRWriteW;
logic [11:0] CSRAdrM, CSRAdrW; logic [11:0] CSRAdrM, CSRAdrW;

View File

@ -26,7 +26,8 @@
module watchdog #(parameter XLEN, WatchDogTimerThreshold) module watchdog #(parameter XLEN, WatchDogTimerThreshold)
(input clk, (input clk,
input reset input reset,
string TEST
); );
// check for hang up. // check for hang up.
@ -46,9 +47,14 @@ module watchdog #(parameter XLEN, WatchDogTimerThreshold)
always_comb begin always_comb begin
WatchDogTimeOut = WatchDogTimerCount >= WatchDogTimerThreshold; WatchDogTimeOut = WatchDogTimerCount >= WatchDogTimerThreshold;
if(WatchDogTimeOut) begin if(WatchDogTimeOut) begin
$display("FAILURE: Watch Dog Time Out triggered. PCW stuck at %x for more than %d cycles", PCW, WatchDogTimerCount); if (TEST == "buildroot") $display("Watch Dog Time Out triggered. This is a normal termination for a full buildroot boot. Check sim/<simulator>/logs/buildroot_uart.log to check if the boot printed the login prompt.");
$stop; else $display("FAILURE: Watch Dog Time Out triggered. PCW stuck at %x for more than %d cycles", PCW, WatchDogTimerCount);
end `ifdef QUESTA
$stop; // if this is changed to $finish for Questa, wally-batch.do does not go to the next step to run coverage, and wally.do terminates without allowing GUI debug
`else
$finish;
`endif
end
end end
endmodule endmodule

View File

@ -1,378 +0,0 @@
///////////////////////////////////////////
// testbench.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Wally Testbench and helper modules
// Applies test programs from the riscv-arch-test and Imperas suites
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
// may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work distributed under the
// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
////////////////////////////////////////////////////////////////////////////////////////////////
`include "config.vh"
// This is set from the command line script
// `define USE_IMPERAS_DV
`ifdef USE_IMPERAS_DV
`include "idv/idv.svh"
`endif
import cvw::*;
module testbench;
parameter DEBUG=0;
`ifdef USE_IMPERAS_DV
import idvPkg::*;
import rvviApiPkg::*;
import idvApiPkg::*;
`endif
`include "parameter-defs.vh"
logic clk;
logic reset_ext, reset;
logic [P.XLEN-1:0] testadr, testadrNoBase;
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW;
logic [3:0] dummy;
logic [P.AHBW-1:0] HRDATAEXT;
logic HREADYEXT, HRESPEXT;
logic HSELEXTSDC;
logic [P.PA_BITS-1:0] HADDR;
logic [P.AHBW-1:0] HWDATA;
logic [P.XLEN/8-1:0] HWSTRB;
logic HWRITE;
logic [2:0] HSIZE;
logic [2:0] HBURST;
logic [3:0] HPROT;
logic [1:0] HTRANS;
logic HMASTLOCK;
logic HCLK, HRESETn;
logic [P.XLEN-1:0] PCW;
logic [31:0] NextInstrE, InstrM;
string ProgramAddrMapFile, ProgramLabelMapFile;
integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 };
logic DCacheFlushDone, DCacheFlushStart;
string testName;
string memfilename, testDir, adrstr, elffilename;
logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
logic UARTSin, UARTSout;
logic SPIIn, SPIOut;
logic [3:0] SPICS;
logic SDCIntr;
logic HREADY;
logic HSELEXT;
logic InitializingMemories;
integer ResetCount, ResetThreshold;
logic InReset;
// Imperas look here.
initial
begin
ResetCount = 0;
ResetThreshold = 2;
InReset = 1;
testadr = 0;
testadrNoBase = 0;
if ($value$plusargs("testDir=%s", testDir)) begin
memfilename = {testDir, "/ref/ref.elf.memfile"};
elffilename = {testDir, "/ref/ref.elf"};
$display($sformatf("%m @ t=%0t: loading testDir %0s", $time, testDir));
end else begin
$error("Must specify test directory using plusarg testDir");
end
if (P.BUS_SUPPORTED) $readmemh(memfilename, dut.uncoregen.uncore.ram.ram.memory.RAM);
else $error("Imperas test bench requires BUS.");
ProgramAddrMapFile = {testDir, "/ref/ref.elf.objdump.addr"};
ProgramLabelMapFile = {testDir, "/ref/ref.elf.objdump.lab"};
// declare memory labels that interest us, the updateProgramAddrLabelArray task will find the addr of each label and fill the array
// to expand, add more elements to this array and initialize them to zero (also initilaize them to zero at the start of the next test)
updateProgramAddrLabelArray(ProgramAddrMapFile, ProgramLabelMapFile, ProgramAddrLabelArray);
$display("Read memfile %s", memfilename);
end
`ifdef USE_IMPERAS_DV
rvviTrace #(.XLEN(P.XLEN), .FLEN(P.FLEN)) rvvi();
wallyTracer #(P) wallyTracer(rvvi);
trace2log idv_trace2log(rvvi);
trace2cov idv_trace2cov(rvvi);
// enabling of comparison types
trace2api #(.CMP_PC (1),
.CMP_INS (1),
.CMP_GPR (1),
.CMP_FPR (1),
.CMP_VR (0),
.CMP_CSR (1)
) idv_trace2api(rvvi);
initial begin
IDV_MAX_ERRORS = 3;
// Initialize REF (do this before initializing the DUT)
if (!rvviVersionCheck(RVVI_API_VERSION)) begin
$display($sformatf("%m @ t=%0t: Expecting RVVI API version %0d.", $time, RVVI_API_VERSION));
$fatal;
end
void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org"));
void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME, "riscv"));
void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VARIANT, "RV64GC"));
void'(rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, 56));
void'(rvviRefConfigSetInt(IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS, 6));
if (!rvviRefInit(elffilename)) begin
$display($sformatf("%m @ t=%0t: rvviRefInit failed", $time));
$fatal;
end
// Volatile CSRs
void'(rvviRefCsrSetVolatile(0, 32'hC00)); // CYCLE
void'(rvviRefCsrSetVolatile(0, 32'hB00)); // MCYCLE
void'(rvviRefCsrSetVolatile(0, 32'hC02)); // INSTRET
void'(rvviRefCsrSetVolatile(0, 32'hB02)); // MINSTRET
void'(rvviRefCsrSetVolatile(0, 32'hC01)); // TIME
// cannot predict this register due to latency between
// pending and taken
void'(rvviRefCsrSetVolatile(0, 32'h344)); // MIP
void'(rvviRefCsrSetVolatile(0, 32'h144)); // SIP
// Privileges for PMA are set in the imperas.ic
// volatile (IO) regions are defined here
// only real ROM/RAM areas are BOOTROM and UNCORE_RAM
if (P.CLINT_SUPPORTED) begin
void'(rvviRefMemorySetVolatile(P.CLINT_BASE, (P.CLINT_BASE + P.CLINT_RANGE)));
end
if (P.GPIO_SUPPORTED) begin
void'(rvviRefMemorySetVolatile(P.GPIO_BASE, (P.GPIO_BASE + P.GPIO_RANGE)));
end
if (P.UART_SUPPORTED) begin
void'(rvviRefMemorySetVolatile(P.UART_BASE, (P.UART_BASE + P.UART_RANGE)));
end
if (P.PLIC_SUPPORTED) begin
void'(rvviRefMemorySetVolatile(P.PLIC_BASE, (P.PLIC_BASE + P.PLIC_RANGE)));
end
if (P.SDC_SUPPORTED) begin
void'(rvviRefMemorySetVolatile(P.SDC_BASE, (P.SDC_BASE + P.SDC_RANGE)));
end
if (P.SPI_SUPPORTED) begin
void'(rvviRefMemorySetVolatile(P.SPI_BASE, (P.SPI_BASE + P.SPI_RANGE)));
end
if(P.XLEN==32) begin
void'(rvviRefCsrSetVolatile(0, 32'hC80)); // CYCLEH
void'(rvviRefCsrSetVolatile(0, 32'hB80)); // MCYCLEH
void'(rvviRefCsrSetVolatile(0, 32'hC82)); // INSTRETH
void'(rvviRefCsrSetVolatile(0, 32'hB82)); // MINSTRETH
end
void'(rvviRefCsrSetVolatile(0, 32'h104)); // SIE - Temporary!!!!
end
always @(dut.core.priv.priv.csr.csri.MIP_REGW[7]) void'(rvvi.net_push("MTimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[7]));
always @(dut.core.priv.priv.csr.csri.MIP_REGW[11]) void'(rvvi.net_push("MExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[11]));
always @(dut.core.priv.priv.csr.csri.MIP_REGW[9]) void'(rvvi.net_push("SExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[9]));
always @(dut.core.priv.priv.csr.csri.MIP_REGW[3]) void'(rvvi.net_push("MSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[3]));
always @(dut.core.priv.priv.csr.csri.MIP_REGW[1]) void'(rvvi.net_push("SSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[1]));
always @(dut.core.priv.priv.csr.csri.MIP_REGW[5]) void'(rvvi.net_push("STimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[5]));
final begin
void'(rvviRefShutdown());
end
`endif
flopenr #(P.XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW);
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, InstrM, InstrW);
// check assertions for a legal configuration
riscvassertions #(P) riscvassertions();
// instantiate device to be tested
assign GPIOIN = 0;
assign UARTSin = 1;
if(P.EXT_MEM_SUPPORTED) begin
ram_ahb #(.BASE(P.EXT_MEM_BASE), .RANGE(P.EXT_MEM_RANGE))
ram (.HCLK, .HRESETn, .HADDR, .HWRITE, .HTRANS, .HWDATA, .HSELRam(HSELEXT),
.HREADRam(HRDATAEXT), .HREADYRam(HREADYEXT), .HRESPRam(HRESPEXT), .HREADY,
.HWSTRB);
end else begin
assign HREADYEXT = 1;
assign HRESPEXT = 0;
assign HRDATAEXT = 0;
end
if(P.SDC_SUPPORTED) begin : sdcard
// *** fix later
/* -----\/----- EXCLUDED -----\/-----
sdModel sdcard
(.sdClk(SDCCLK),
.cmd(SDCCmd),
.dat(SDCDat));
assign SDCCmd = SDCCmdOE ? SDCCmdOut : 1'bz;
assign SDCCmdIn = SDCCmd;
assign SDCDatIn = SDCDat;
-----/\----- EXCLUDED -----/\----- */
assign SDCIntr = 0;
end else begin
assign SDCIntr = 0;
end
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
// Track names of instructions
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
dut.core.ifu.InstrRawF[31:0],
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
InstrM, InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// initialize tests
// generate clock to sequence tests
always
begin
clk = 1; # 5; clk = 0; # 5;
// if ($time % 100000 == 0) $display("Time is %0t", $time);
end
// check results
assign reset_ext = InReset;
always @(negedge clk)
begin
InitializingMemories = 0;
if(InReset == 1) begin
// once the test inidicates it's done we need to immediately hold reset for a number of cycles.
if(ResetCount < ResetThreshold) ResetCount = ResetCount + 1;
else begin // hit reset threshold so we remove reset.
InReset = 0;
ResetCount = 0;
end
end
end // always @ (negedge clk)
// track the current function or global label
if (DEBUG == 1) begin : FunctionName
FunctionName #(P) FunctionName(.reset(reset),
.clk(clk),
.ProgramAddrMapFile(ProgramAddrMapFile),
.ProgramLabelMapFile(ProgramLabelMapFile));
end
// Duplicate copy of pipeline registers that are optimized out of some configurations
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
// Termination condition
// terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed
// or sw gp,-56(t0) for new Imperas tests
// or sd gp, -56(t0)
// or on a jump to self infinite loop (6f) for RISC-V Arch tests
logic ecf; // remove this once we don't rely on old Imperas tests with Ecalls
if (P.ZICSR_SUPPORTED) assign ecf = dut.core.priv.priv.EcallFaultM;
else assign ecf = 0;
assign DCacheFlushStart = ecf &
(dut.core.ieu.dp.regf.rf[3] == 1 |
(dut.core.ieu.dp.regf.we3 &
dut.core.ieu.dp.regf.a3 == 3 &
dut.core.ieu.dp.regf.wd3 == 1)) |
((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk),
.start(DCacheFlushStart),
.done(DCacheFlushDone));
// initialize the branch predictor
if (P.BPRED_SUPPORTED == 1)
begin
genvar adrindex;
// Initializing all zeroes into the branch predictor memory.
for(adrindex = 0; adrindex < 1024; adrindex++) begin
initial begin
force dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex] = 0;
force dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem[adrindex] = 0;
#1;
release dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex];
release dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem[adrindex];
end
end
end
watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck
endmodule
/* verilator lint_on STMTDLY */
/* verilator lint_on WIDTH */
task automatic updateProgramAddrLabelArray;
input string ProgramAddrMapFile, ProgramLabelMapFile;
inout integer ProgramAddrLabelArray [string];
// Gets the memory location of begin_signature
integer ProgramLabelMapFP, ProgramAddrMapFP;
ProgramLabelMapFP = $fopen(ProgramLabelMapFile, "r");
ProgramAddrMapFP = $fopen(ProgramAddrMapFile, "r");
if (ProgramLabelMapFP & ProgramAddrMapFP) begin // check we found both files
while (!$feof(ProgramLabelMapFP)) begin
string label, adrstr;
integer returncode;
returncode = $fscanf(ProgramLabelMapFP, "%s\n", label);
returncode = $fscanf(ProgramAddrMapFP, "%s\n", adrstr);
if (ProgramAddrLabelArray.exists(label))
ProgramAddrLabelArray[label] = adrstr.atohex();
end
end
$fclose(ProgramLabelMapFP);
$fclose(ProgramAddrMapFP);
endtask

View File

@ -125,10 +125,9 @@ module testbench;
TEST = "none"; TEST = "none";
if (!$value$plusargs("ElfFile=%s", ElfFile)) if (!$value$plusargs("ElfFile=%s", ElfFile))
ElfFile = "none"; ElfFile = "none";
else begin
end
if (!$value$plusargs("INSTR_LIMIT=%d", INSTR_LIMIT)) if (!$value$plusargs("INSTR_LIMIT=%d", INSTR_LIMIT))
INSTR_LIMIT = 0; INSTR_LIMIT = 0;
//$display("TEST = %s ElfFile = %s", TEST, ElfFile);
// pick tests based on modes supported // pick tests based on modes supported
//tests = '{}; //tests = '{};
@ -638,7 +637,7 @@ module testbench;
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// watch for problems such as lockup, reading unitialized memory, bad configs // watch for problems such as lockup, reading unitialized memory, bad configs
watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset, .TEST); // check if PCW is stuck
ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM, ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM,
dut.core.ifu.PCM, InstrM, dut.core.lsu.IEUAdrM, InstrMName); dut.core.ifu.PCM, InstrM, dut.core.lsu.IEUAdrM, InstrMName);
riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration

View File

@ -66,6 +66,7 @@ module testbench_fp;
logic [P.FMTBITS-1:0] ModFmt; // format - 10 = half, 00 = single, 01 = double, 11 = quad logic [P.FMTBITS-1:0] ModFmt; // format - 10 = half, 00 = single, 01 = double, 11 = quad
logic [P.FLEN-1:0] FpRes, FpCmpRes; // Results from each unit logic [P.FLEN-1:0] FpRes, FpCmpRes; // Results from each unit
logic [P.XLEN-1:0] IntRes, CmpRes; // Results from each unit logic [P.XLEN-1:0] IntRes, CmpRes; // Results from each unit
logic [P.Q_LEN-1:0] FpResExtended; // FpRes extended to same length as Ans/Res
logic [4:0] FmaFlg, CvtFlg, DivFlg; // Outputed flags logic [4:0] FmaFlg, CvtFlg, DivFlg; // Outputed flags
logic [4:0] CmpFlg; // Outputed flags logic [4:0] CmpFlg; // Outputed flags
logic AnsNaN, ResNaN, NaNGood; logic AnsNaN, ResNaN, NaNGood;
@ -820,13 +821,14 @@ module testbench_fp;
end end
always_comb begin always_comb begin
FpResExtended = {{(P.Q_LEN-P.FLEN){1'b1}}, FpRes};
// select the result to check // select the result to check
case (UnitVal) case (UnitVal)
`FMAUNIT: Res = FpRes; `FMAUNIT: Res = FpResExtended;
`DIVUNIT: Res = FpRes; `DIVUNIT: Res = FpResExtended;
`CMPUNIT: Res = {{(FLEN > XLEN ? FLEN-XLEN : XLEN-FLEN){1'b0}}, CmpRes}; `CMPUNIT: Res = {{(Q_LEN-XLEN){1'b0}}, CmpRes};
`CVTINTUNIT: if (WriteIntVal) Res = {{(FLEN > XLEN ? FLEN-XLEN : XLEN-FLEN){1'b0}}, IntRes}; else Res = FpRes; `CVTINTUNIT: if (WriteIntVal) Res = {{(Q_LEN-XLEN){1'b0}}, IntRes}; else Res = FpResExtended;
`CVTFPUNIT: Res = FpRes; `CVTFPUNIT: Res = FpResExtended;
endcase endcase
// select the flag to check // select the flag to check
@ -965,7 +967,7 @@ module testbench_fp;
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
// check if result is correct // check if result is correct
assign ResMatch = ((Res === Ans) | NaNGood | (NaNGood === 1'bx)); assign ResMatch = ((Res[P.FLEN-1:0] === Ans[P.FLEN-1:0]) | NaNGood | (NaNGood === 1'bx));
assign FlagMatch = ((ResFlg === AnsFlg) | (AnsFlg === 5'bx)); assign FlagMatch = ((ResFlg === AnsFlg) | (AnsFlg === 5'bx));
assign divsqrtop = (OpCtrlVal == `SQRT_OPCTRL) | (OpCtrlVal == `DIV_OPCTRL); assign divsqrtop = (OpCtrlVal == `SQRT_OPCTRL) | (OpCtrlVal == `DIV_OPCTRL);
assign FMAop = (OpCtrlVal == `FMAUNIT); assign FMAop = (OpCtrlVal == `FMAUNIT);
@ -987,7 +989,7 @@ module testbench_fp;
// increment the test // increment the test
TestNum += 1; TestNum += 1;
// clear the vectors // clear the vectors
for(int i=0; i<MAXVECTORS; i++) TestVectors[i] = {P.FLEN*4+8{1'bx}}; for(int i=0; i<MAXVECTORS; i++) TestVectors[i] = {P.Q_LEN*4+8{1'bx}};
// read next files // read next files
$readmemh({`PATH, Tests[TestNum]}, TestVectors); $readmemh({`PATH, Tests[TestNum]}, TestVectors);
// set the vector index back to 0 // set the vector index back to 0
@ -1052,6 +1054,7 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
// Format of vectors Inputs(1/2/3)_AnsFlg // Format of vectors Inputs(1/2/3)_AnsFlg
always @(VectorNum) begin always @(VectorNum) begin
AnsFlg = TestVector[4:0]; AnsFlg = TestVector[4:0];
//$display("Entering readvectors with VectorNum=%d, TestVector=%x, Unit=%d, Fmt=%d, OpCtrl=%d", VectorNum, TestVector, Unit, Fmt, OpCtrl);
case (Unit) case (Unit)
`FMAUNIT: `FMAUNIT:
case (Fmt) case (Fmt)
@ -1070,48 +1073,49 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
end end
2'b01: if (P.D_SUPPORTED) begin // double 2'b01: if (P.D_SUPPORTED) begin // double
if (OpCtrl === `FMA_OPCTRL) begin if (OpCtrl === `FMA_OPCTRL) begin
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+4*(P.D_LEN)-1:8+3*(P.D_LEN)]}; X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+4*(P.D_LEN)-1:8+3*(P.D_LEN)]};
Y = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]}; Y = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]};
Z = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+P.D_LEN]}; Z = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+P.D_LEN]};
$display("Read %x %x %x", X, Y, Z);
end end
else begin else begin
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]}; X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]};
if (OpCtrl === `MUL_OPCTRL) Y = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+(P.D_LEN)]}; if (OpCtrl === `MUL_OPCTRL) Y = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+(P.D_LEN)]};
else Y = {{P.FLEN-P.D_LEN{1'b1}}, 2'b0, {P.D_NE-1{1'b1}}, (P.D_NF)'(0)}; else Y = {{P.Q_LEN-P.D_LEN{1'b1}}, 2'b0, {P.D_NE-1{1'b1}}, (P.D_NF)'(0)};
if (OpCtrl === `MUL_OPCTRL) Z = {{P.FLEN-P.D_LEN{1'b1}}, {P.D_LEN{1'b0}}}; if (OpCtrl === `MUL_OPCTRL) Z = {{P.Q_LEN-P.D_LEN{1'b1}}, {P.D_LEN{1'b0}}};
else Z = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+(P.D_LEN)]}; else Z = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+(P.D_LEN)]};
end end
Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; Ans = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]};
end end
2'b00: if (P.F_SUPPORTED) begin // single 2'b00: if (P.F_SUPPORTED) begin // single
if (OpCtrl === `FMA_OPCTRL) begin if (OpCtrl === `FMA_OPCTRL) begin
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+4*(P.S_LEN)-1:8+3*(P.S_LEN)]}; X = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+4*(P.S_LEN)-1:8+3*(P.S_LEN)]};
Y = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+3*(P.S_LEN)-1:8+2*(P.S_LEN)]}; Y = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+3*(P.S_LEN)-1:8+2*(P.S_LEN)]};
Z = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+P.S_LEN]}; Z = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+P.S_LEN]};
end end
else begin else begin
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+3*(P.S_LEN)-1:8+2*(P.S_LEN)]}; X = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+3*(P.S_LEN)-1:8+2*(P.S_LEN)]};
if (OpCtrl === `MUL_OPCTRL) Y = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+(P.S_LEN)]}; if (OpCtrl === `MUL_OPCTRL) Y = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+(P.S_LEN)]};
else Y = {{P.FLEN-P.S_LEN{1'b1}}, 2'b0, {P.S_NE-1{1'b1}}, (P.S_NF)'(0)}; else Y = {{P.Q_LEN-P.S_LEN{1'b1}}, 2'b0, {P.S_NE-1{1'b1}}, (P.S_NF)'(0)};
if (OpCtrl === `MUL_OPCTRL) Z = {{P.FLEN-P.S_LEN{1'b1}}, {P.S_LEN{1'b0}}}; if (OpCtrl === `MUL_OPCTRL) Z = {{P.Q_LEN-P.S_LEN{1'b1}}, {P.S_LEN{1'b0}}};
else Z = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+(P.S_LEN)]}; else Z = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+(P.S_LEN)]};
end end
Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; Ans = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]};
end end
2'b10: begin // half 2'b10: begin // half
if (OpCtrl === `FMA_OPCTRL) begin if (OpCtrl === `FMA_OPCTRL) begin
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+4*(P.H_LEN)-1:8+3*(P.H_LEN)]}; X = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+4*(P.H_LEN)-1:8+3*(P.H_LEN)]};
Y = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+3*(P.H_LEN)-1:8+2*(P.H_LEN)]}; Y = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+3*(P.H_LEN)-1:8+2*(P.H_LEN)]};
Z = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+P.H_LEN]}; Z = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+P.H_LEN]};
end end
else begin else begin
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+3*(P.H_LEN)-1:8+2*(P.H_LEN)]}; X = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+3*(P.H_LEN)-1:8+2*(P.H_LEN)]};
if (OpCtrl === `MUL_OPCTRL) Y = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+(P.H_LEN)]}; if (OpCtrl === `MUL_OPCTRL) Y = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+(P.H_LEN)]};
else Y = {{P.FLEN-P.H_LEN{1'b1}}, 2'b0, {P.H_NE-1{1'b1}}, (P.H_NF)'(0)}; else Y = {{P.Q_LEN-P.H_LEN{1'b1}}, 2'b0, {P.H_NE-1{1'b1}}, (P.H_NF)'(0)};
if (OpCtrl === `MUL_OPCTRL) Z = {{P.FLEN-P.H_LEN{1'b1}}, {P.H_LEN{1'b0}}}; if (OpCtrl === `MUL_OPCTRL) Z = {{P.Q_LEN-P.H_LEN{1'b1}}, {P.H_LEN{1'b0}}};
else Z = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+(P.H_LEN)]}; else Z = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+(P.H_LEN)]};
end end
Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; Ans = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]};
end end
endcase endcase
`DIVUNIT: `DIVUNIT:
@ -1122,16 +1126,16 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
Ans = TestVector[8+(P.Q_LEN-1):8]; Ans = TestVector[8+(P.Q_LEN-1):8];
end end
2'b01: if (P.D_SUPPORTED) begin // double 2'b01: if (P.D_SUPPORTED) begin // double
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+(P.D_LEN)]}; X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+(P.D_LEN)]};
Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; Ans = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]};
end end
2'b00: if (P.F_SUPPORTED) begin // single 2'b00: if (P.F_SUPPORTED) begin // single
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+1*(P.S_LEN)]}; X = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+1*(P.S_LEN)]};
Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; Ans = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]};
end end
2'b10: begin // half 2'b10: begin // half
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+(P.H_LEN)]}; X = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+(P.H_LEN)]};
Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; Ans = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]};
end end
endcase endcase
else else
@ -1142,19 +1146,19 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
Ans = TestVector[8+(P.Q_LEN-1):8]; Ans = TestVector[8+(P.Q_LEN-1):8];
end end
2'b01: if (P.D_SUPPORTED) begin // double 2'b01: if (P.D_SUPPORTED) begin // double
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]}; X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+3*(P.D_LEN)-1:8+2*(P.D_LEN)]};
Y = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+(P.D_LEN)]}; Y = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+2*(P.D_LEN)-1:8+(P.D_LEN)]};
Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; Ans = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]};
end end
2'b00: if (P.F_SUPPORTED) begin // single 2'b00: if (P.F_SUPPORTED) begin // single
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+3*(P.S_LEN)-1:8+2*(P.S_LEN)]}; X = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+3*(P.S_LEN)-1:8+2*(P.S_LEN)]};
Y = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+1*(P.S_LEN)]}; Y = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+2*(P.S_LEN)-1:8+1*(P.S_LEN)]};
Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; Ans = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]};
end end
2'b10: begin // half 2'b10: begin // half
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+3*(P.H_LEN)-1:8+2*(P.H_LEN)]}; X = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+3*(P.H_LEN)-1:8+2*(P.H_LEN)]};
Y = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+(P.H_LEN)]}; Y = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+2*(P.H_LEN)-1:8+(P.H_LEN)]};
Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; Ans = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]};
end end
endcase endcase
`CMPUNIT: `CMPUNIT:
@ -1162,22 +1166,22 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
2'b11: begin // quad 2'b11: begin // quad
X = TestVector[12+2*(P.Q_LEN)-1:12+(P.Q_LEN)]; X = TestVector[12+2*(P.Q_LEN)-1:12+(P.Q_LEN)];
Y = TestVector[12+(P.Q_LEN)-1:12]; Y = TestVector[12+(P.Q_LEN)-1:12];
Ans = {{P.FLEN-1{1'b0}}, TestVector[8]}; Ans = {{P.Q_LEN-1{1'b0}}, TestVector[8]};
end end
2'b01: if (P.D_SUPPORTED) begin // double 2'b01: if (P.D_SUPPORTED) begin // double
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[12+2*(P.D_LEN)-1:12+(P.D_LEN)]}; X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[12+2*(P.D_LEN)-1:12+(P.D_LEN)]};
Y = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[12+(P.D_LEN)-1:12]}; Y = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[12+(P.D_LEN)-1:12]};
Ans = {{P.FLEN-1{1'b0}}, TestVector[8]}; Ans = {{P.Q_LEN-1{1'b0}}, TestVector[8]};
end end
2'b00: if (P.F_SUPPORTED) begin // single 2'b00: if (P.F_SUPPORTED) begin // single
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[12+2*(P.S_LEN)-1:12+(P.S_LEN)]}; X = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[12+2*(P.S_LEN)-1:12+(P.S_LEN)]};
Y = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[12+(P.S_LEN)-1:12]}; Y = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[12+(P.S_LEN)-1:12]};
Ans = {{P.FLEN-1{1'b0}}, TestVector[8]}; Ans = {{P.Q_LEN-1{1'b0}}, TestVector[8]};
end end
2'b10: begin // half 2'b10: begin // half
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[12+2*(P.H_LEN)-1:12+(P.H_LEN)]}; X = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[12+2*(P.H_LEN)-1:12+(P.H_LEN)]};
Y = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[12+(P.H_LEN)-1:12]}; Y = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[12+(P.H_LEN)-1:12]};
Ans = {{P.FLEN-1{1'b0}}, TestVector[8]}; Ans = {{P.Q_LEN-1{1'b0}}, TestVector[8]};
end end
endcase endcase
`CVTFPUNIT: `CVTFPUNIT:
@ -1190,75 +1194,75 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
end end
2'b01: if (P.D_SUPPORTED) begin // double 2'b01: if (P.D_SUPPORTED) begin // double
X = {TestVector[8+P.Q_LEN+P.D_LEN-1:8+(P.D_LEN)]}; X = {TestVector[8+P.Q_LEN+P.D_LEN-1:8+(P.D_LEN)]};
Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; Ans = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]};
end end
2'b00: begin // single 2'b00: begin // single
X = {TestVector[8+P.Q_LEN+P.S_LEN-1:8+(P.S_LEN)]}; X = {TestVector[8+P.Q_LEN+P.S_LEN-1:8+(P.S_LEN)]};
Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; Ans = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]};
end end
2'b10: begin // half 2'b10: begin // half
X = {TestVector[8+P.Q_LEN+P.H_LEN-1:8+(P.H_LEN)]}; X = {TestVector[8+P.Q_LEN+P.H_LEN-1:8+(P.H_LEN)]};
Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; Ans = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]};
end end
endcase endcase
end end
2'b01: if (P.D_SUPPORTED) begin // double 2'b01: if (P.D_SUPPORTED) begin // double
case (OpCtrl[1:0]) case (OpCtrl[1:0])
2'b11: begin // quad 2'b11: begin // quad
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+P.D_LEN+P.Q_LEN-1:8+(P.Q_LEN)]}; X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+P.D_LEN+P.Q_LEN-1:8+(P.Q_LEN)]};
Ans = TestVector[8+(P.Q_LEN-1):8]; Ans = TestVector[8+(P.Q_LEN-1):8];
end end
2'b01: begin // double 2'b01: begin // double
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+P.D_LEN+P.D_LEN-1:8+(P.D_LEN)]}; X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+P.D_LEN+P.D_LEN-1:8+(P.D_LEN)]};
Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; Ans = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]};
end end
2'b00: begin // single 2'b00: begin // single
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+P.D_LEN+P.S_LEN-1:8+(P.S_LEN)]}; X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+P.D_LEN+P.S_LEN-1:8+(P.S_LEN)]};
Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; Ans = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]};
end end
2'b10: begin // half 2'b10: begin // half
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+P.D_LEN+P.H_LEN-1:8+(P.H_LEN)]}; X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+P.D_LEN+P.H_LEN-1:8+(P.H_LEN)]};
Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; Ans = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]};
end end
endcase endcase
end end
2'b00: if (P.F_SUPPORTED) begin // single 2'b00: if (P.F_SUPPORTED) begin // single
case (OpCtrl[1:0]) case (OpCtrl[1:0])
2'b11: begin // quad 2'b11: begin // quad
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+P.S_LEN+P.Q_LEN-1:8+(P.Q_LEN)]}; X = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+P.S_LEN+P.Q_LEN-1:8+(P.Q_LEN)]};
Ans = TestVector[8+(P.Q_LEN-1):8]; Ans = TestVector[8+(P.Q_LEN-1):8];
end end
2'b01: if (P.D_SUPPORTED) begin // double 2'b01: if (P.D_SUPPORTED) begin // double
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+P.S_LEN+P.D_LEN-1:8+(P.D_LEN)]}; X = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+P.S_LEN+P.D_LEN-1:8+(P.D_LEN)]};
Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; Ans = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]};
end end
2'b00: begin // single 2'b00: begin // single
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+P.S_LEN+P.S_LEN-1:8+(P.S_LEN)]}; X = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+P.S_LEN+P.S_LEN-1:8+(P.S_LEN)]};
Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; Ans = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]};
end end
2'b10: begin // half 2'b10: begin // half
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+P.S_LEN+P.H_LEN-1:8+(P.H_LEN)]}; X = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+P.S_LEN+P.H_LEN-1:8+(P.H_LEN)]};
Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; Ans = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]};
end end
endcase endcase
end end
2'b10: begin // half 2'b10: begin // half
case (OpCtrl[1:0]) case (OpCtrl[1:0])
2'b11: begin // quad 2'b11: begin // quad
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+P.H_LEN+P.Q_LEN-1:8+(P.Q_LEN)]}; X = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+P.H_LEN+P.Q_LEN-1:8+(P.Q_LEN)]};
Ans = TestVector[8+(P.Q_LEN-1):8]; Ans = TestVector[8+(P.Q_LEN-1):8];
end end
2'b01: if (P.D_SUPPORTED) begin // double 2'b01: if (P.D_SUPPORTED) begin // double
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+P.H_LEN+P.D_LEN-1:8+(P.D_LEN)]}; X = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+P.H_LEN+P.D_LEN-1:8+(P.D_LEN)]};
Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; Ans = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]};
end end
2'b00: if (P.F_SUPPORTED) begin // single 2'b00: if (P.F_SUPPORTED) begin // single
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+P.H_LEN+P.S_LEN-1:8+(P.S_LEN)]}; X = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+P.H_LEN+P.S_LEN-1:8+(P.S_LEN)]};
Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; Ans = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]};
end end
2'b10: begin // half 2'b10: begin // half
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+P.H_LEN+P.H_LEN-1:8+(P.H_LEN)]}; X = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+P.H_LEN+P.H_LEN-1:8+(P.H_LEN)]};
Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; Ans = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]};
end end
endcase endcase
end end
@ -1269,25 +1273,25 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
// {is the integer a long, is the opperation to an integer} // {is the integer a long, is the opperation to an integer}
casez ({OpCtrl[2:1]}) casez ({OpCtrl[2:1]})
2'b11: begin // long -> quad 2'b11: begin // long -> quad
X = {P.FLEN{1'bx}}; X = {P.Q_LEN{1'bx}};
SrcA = TestVector[8+P.Q_LEN+P.XLEN-1:8+(P.Q_LEN)]; SrcA = TestVector[8+P.Q_LEN+P.XLEN-1:8+(P.Q_LEN)];
Ans = TestVector[8+(P.Q_LEN-1):8]; Ans = TestVector[8+(P.Q_LEN-1):8];
end end
2'b10: begin // int -> quad 2'b10: begin // int -> quad
// correctly sign extend the integer depending on if it's a signed/unsigned test // correctly sign extend the integer depending on if it's a signed/unsigned test
X = {P.FLEN{1'bx}}; X = {P.Q_LEN{1'bx}};
SrcA = {{P.XLEN-32{TestVector[8+P.Q_LEN+32-1]}}, TestVector[8+P.Q_LEN+32-1:8+(P.Q_LEN)]}; SrcA = {{P.XLEN-32{TestVector[8+P.Q_LEN+32-1]}}, TestVector[8+P.Q_LEN+32-1:8+(P.Q_LEN)]};
Ans = TestVector[8+(P.Q_LEN-1):8]; Ans = TestVector[8+(P.Q_LEN-1):8];
end end
2'b01: begin // quad -> long 2'b01: begin // quad -> long
X = {TestVector[8+P.XLEN+P.Q_LEN-1:8+(P.XLEN)]}; X = {TestVector[8+P.XLEN+P.Q_LEN-1:8+(P.XLEN)]};
SrcA = {P.XLEN{1'bx}}; SrcA = {P.XLEN{1'bx}};
Ans = {{(P.FLEN > 64 ? P.FLEN-64 : 0){1'b0}}, TestVector[8+(P.XLEN-1):8]}; Ans = {{(P.Q_LEN-64){1'b0}}, TestVector[8+(64-1):8]};
end end
2'b00: begin // quad -> int 2'b00: begin // quad -> int
X = {TestVector[8+32+P.Q_LEN-1:8+(32)]}; X = {TestVector[8+32+P.Q_LEN-1:8+(32)]};
SrcA = {P.XLEN{1'bx}}; SrcA = {P.XLEN{1'bx}};
Ans = {{P.FLEN-32{TestVector[8+32-1]}},TestVector[8+(32-1):8]}; Ans = {{(P.Q_LEN-32){TestVector[8+32-1]}},TestVector[8+(32-1):8]};
end end
endcase endcase
end end
@ -1295,25 +1299,25 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
// {Int->Fp?, is the integer a long} // {Int->Fp?, is the integer a long}
casez ({OpCtrl[2:1]}) casez ({OpCtrl[2:1]})
2'b11: begin // long -> double 2'b11: begin // long -> double
X = {P.FLEN{1'bx}}; X = {P.Q_LEN{1'bx}};
SrcA = TestVector[8+P.D_LEN+P.XLEN-1:8+(P.D_LEN)]; SrcA = TestVector[8+P.D_LEN+P.XLEN-1:8+(P.D_LEN)];
Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; Ans = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]};
end end
2'b10: begin // int -> double 2'b10: begin // int -> double
// correctly sign extend the integer depending on if it's a signed/unsigned test // correctly sign extend the integer depending on if it's a signed/unsigned test
X = {P.FLEN{1'bx}}; X = {P.Q_LEN{1'bx}};
SrcA = {{P.XLEN-32{TestVector[8+P.D_LEN+32-1]}}, TestVector[8+P.D_LEN+32-1:8+(P.D_LEN)]}; SrcA = {{P.XLEN-32{TestVector[8+P.D_LEN+32-1]}}, TestVector[8+P.D_LEN+32-1:8+(P.D_LEN)]};
Ans = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]}; Ans = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+(P.D_LEN-1):8]};
end end
2'b01: begin // double -> long 2'b01: begin // double -> long
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+P.XLEN+P.D_LEN-1:8+(P.XLEN)]}; X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+P.XLEN+P.D_LEN-1:8+(P.XLEN)]};
SrcA = {P.XLEN{1'bx}}; SrcA = {P.XLEN{1'bx}};
Ans = {{(P.FLEN-64){1'b0}}, TestVector[8+(P.XLEN-1):8]}; Ans = {{(P.Q_LEN-64){1'b0}}, TestVector[8+(64-1):8]};
end end
2'b00: begin // double -> int 2'b00: begin // double -> int
X = {{P.FLEN-P.D_LEN{1'b1}}, TestVector[8+32+P.D_LEN-1:8+(32)]}; X = {{P.Q_LEN-P.D_LEN{1'b1}}, TestVector[8+32+P.D_LEN-1:8+(32)]};
SrcA = {P.XLEN{1'bx}}; SrcA = {P.XLEN{1'bx}};
Ans = {{P.FLEN-32{TestVector[8+32-1]}},TestVector[8+(32-1):8]}; Ans = {{P.Q_LEN-32{TestVector[8+32-1]}},TestVector[8+(32-1):8]};
end end
endcase endcase
end end
@ -1321,25 +1325,25 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
// {is the integer a long, is the opperation to an integer} // {is the integer a long, is the opperation to an integer}
casez ({OpCtrl[2:1]}) casez ({OpCtrl[2:1]})
2'b11: begin // long -> single 2'b11: begin // long -> single
X = {P.FLEN{1'bx}}; X = {P.Q_LEN{1'bx}};
SrcA = TestVector[8+P.S_LEN+P.XLEN-1:8+(P.S_LEN)]; SrcA = TestVector[8+P.S_LEN+P.XLEN-1:8+(P.S_LEN)];
Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; Ans = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]};
end end
2'b10: begin // int -> single 2'b10: begin // int -> single
// correctly sign extend the integer depending on if it's a signed/unsigned test // correctly sign extend the integer depending on if it's a signed/unsigned test
X = {P.FLEN{1'bx}}; X = {P.Q_LEN{1'bx}};
SrcA = {{P.XLEN-32{TestVector[8+P.S_LEN+32-1]}}, TestVector[8+P.S_LEN+32-1:8+(P.S_LEN)]}; SrcA = {{P.XLEN-32{TestVector[8+P.S_LEN+32-1]}}, TestVector[8+P.S_LEN+32-1:8+(P.S_LEN)]};
Ans = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]}; Ans = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+(P.S_LEN-1):8]};
end end
2'b01: begin // single -> long 2'b01: begin // single -> long
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+P.XLEN+P.S_LEN-1:8+(P.XLEN)]}; X = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+P.XLEN+P.S_LEN-1:8+(P.XLEN)]};
SrcA = {P.XLEN{1'bx}}; SrcA = {P.XLEN{1'bx}};
Ans = {{(P.FLEN > 64 ? P.FLEN-64 : 0){1'b0}}, TestVector[8+(P.XLEN-1):8]}; Ans = {{(P.Q_LEN-64){1'b0}}, TestVector[8+(64-1):8]};
end end
2'b00: begin // single -> int 2'b00: begin // single -> int
X = {{P.FLEN-P.S_LEN{1'b1}}, TestVector[8+32+P.S_LEN-1:8+(32)]}; X = {{P.Q_LEN-P.S_LEN{1'b1}}, TestVector[8+32+P.S_LEN-1:8+(32)]};
SrcA = {P.XLEN{1'bx}}; SrcA = {P.XLEN{1'bx}};
Ans = {{P.FLEN-32{TestVector[8+32-1]}},TestVector[8+(32-1):8]}; Ans = {{(P.Q_LEN-32){TestVector[8+32-1]}},TestVector[8+(32-1):8]};
end end
endcase endcase
end end
@ -1347,25 +1351,25 @@ module readvectors import cvw::*; #(parameter cvw_t P) (
// {is the integer a long, is the opperation to an integer} // {is the integer a long, is the opperation to an integer}
casez ({OpCtrl[2:1]}) casez ({OpCtrl[2:1]})
2'b11: begin // long -> half 2'b11: begin // long -> half
X = {P.FLEN{1'bx}}; X = {P.Q_LEN{1'bx}};
SrcA = TestVector[8+P.H_LEN+P.XLEN-1:8+(P.H_LEN)]; SrcA = TestVector[8+P.H_LEN+P.XLEN-1:8+(P.H_LEN)];
Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; Ans = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]};
end end
2'b10: begin // int -> half 2'b10: begin // int -> half
// correctly sign extend the integer depending on if it's a signed/unsigned test // correctly sign extend the integer depending on if it's a signed/unsigned test
X = {P.FLEN{1'bx}}; X = {P.Q_LEN{1'bx}};
SrcA = {{P.XLEN-32{TestVector[8+P.H_LEN+32-1]}}, TestVector[8+P.H_LEN+32-1:8+(P.H_LEN)]}; SrcA = {{P.XLEN-32{TestVector[8+P.H_LEN+32-1]}}, TestVector[8+P.H_LEN+32-1:8+(P.H_LEN)]};
Ans = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]}; Ans = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+(P.H_LEN-1):8]};
end end
2'b01: begin // half -> long 2'b01: begin // half -> long
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+P.XLEN+P.H_LEN-1:8+(P.XLEN)]}; X = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+P.XLEN+P.H_LEN-1:8+(P.XLEN)]};
SrcA = {P.XLEN{1'bx}}; SrcA = {P.XLEN{1'bx}};
Ans = {{(P.FLEN > 64 ? P.FLEN-64 : 0){1'b0}}, TestVector[8+(P.XLEN-1):8]}; Ans = {{(P.Q_LEN-64){1'b0}}, TestVector[8+(64-1):8]};
end end
2'b00: begin // half -> int 2'b00: begin // half -> int
X = {{P.FLEN-P.H_LEN{1'b1}}, TestVector[8+32+P.H_LEN-1:8+(32)]}; X = {{P.Q_LEN-P.H_LEN{1'b1}}, TestVector[8+32+P.H_LEN-1:8+(32)]};
SrcA = {P.XLEN{1'bx}}; SrcA = {P.XLEN{1'bx}};
Ans = {{P.FLEN-32{TestVector[8+32-1]}}, TestVector[8+(32-1):8]}; Ans = {{(P.Q_LEN-32){TestVector[8+32-1]}}, TestVector[8+(32-1):8]};
end end
endcase endcase
end end

View File

@ -1,12 +1,14 @@
hart_ids: [0] hart_ids: [0]
hart0: hart0:
# ISA: RV64IMAFDQCSUZicboz_Zicsr_Zicond_Zifencei_Zfa_Zfh_Zca_Zcb_Zba_Zbb_Zbc_Zbkb_Zbkc_Zbkx_Zbs_Zknd_Zkne_Zknh # ISA: RV64IMAFDQCSUZicboz_Zicsr_Zicond_Zifencei_Zfa_Zfh_Zca_Zcb_Zba_Zbb_Zbc_Zbkb_Zbkc_Zbkx_Zbs_Zknd_Zkne_Zknh
ISA: RV64IMAFDQCSUZicsr_Zicond_Zifencei_Zfa_Zfh_Zca_Zcb_Zba_Zbb_Zbc_Zbkb_Zbkc_Zbkx_Zbs_Zknd_Zkne_Zknh ISA: RV64IMAFDCSUZicsr_Zicond_Zifencei_Zfa_Zfh_Zca_Zcb_Zba_Zbb_Zbc_Zbkb_Zbkc_Zbkx_Zbs_Zknd_Zkne_Zknh
# ISA: RV64IMAFDQCSUZicsr_Zicond_Zifencei_Zfa_Zfh_Zca_Zcb_Zba_Zbb_Zbc_Zbkb_Zbkc_Zbkx_Zbs_Zknd_Zkne_Zknh
physical_addr_sz: 56 physical_addr_sz: 56
User_Spec_Version: '2.3' User_Spec_Version: '2.3'
supported_xlen: [64] supported_xlen: [64]
misa: misa:
reset-val: 0x800000000015112D reset-val: 0x800000000014112D
# reset-val: 0x800000000015112D
rv32: rv32:
accessible: false accessible: false
rv64: rv64:

View File

@ -22,7 +22,12 @@ riscv-ctg-> This folder consists of the CTG tool which is responsible for genera
riscof -> The riscof directory in Wally was changed to include some Quad precision template files for compilation. Along with modification of scripts and yaml files to support FLEN=128 riscof -> The riscof directory in Wally was changed to include some Quad precision template files for compilation. Along with modification of scripts and yaml files to support FLEN=128
TO DO:
Debug why fadd.q_b1 doesn't match Sail vs. Spike
Run the q test on Wally RTL
Make more tests from the working datasets
Get other datasets working by using softfloat to do quad math
Push changes back to riscv-ctg and riscv-isac and remove them from wally-riscv-arch/tsts/riscv-test-suite/rv64i_m/Q
Start by installing riscv-ctg via the following commands : Start by installing riscv-ctg via the following commands :