Merge pull request #947 from davidharrishmc/main

Recreate coverage improvements
This commit is contained in:
Jordan Carlin 2024-09-05 16:34:32 -07:00 committed by GitHub
commit f365e460f8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 29 additions and 579 deletions

View File

@ -232,8 +232,8 @@ bpredtests = [
# list of tests not supported by ImperasDV yet that should be waived during lockstep testing # list of tests not supported by ImperasDV yet that should be waived during lockstep testing
lockstepwaivers = [ lockstepwaivers = [
"WALLY-q-01.S_ref.elf", # Q extension is not supported by ImperasDV "WALLY-q-01.S_ref.elf", # Q extension is not supported by ImperasDV
"WALLY-cbom-01.S_ref.elf", # cbom extension is not supported by ImperasDV because there is no cache model in ImperasDV "WALLY-cbom-01.S_ref.elf" #, # cbom extension is not supported by ImperasDV because there is no cache model in ImperasDV
"coverage_ieu.elf" # Issue 881: ImperasDV misinterprets 0x6BF05013 as a grevi rather than an illegal instruction # "coverage_ieu.elf" # Issue 881: ImperasDV misinterprets 0x6BF05013 as a grevi rather than an illegal instruction
] ]
################################## ##################################
@ -408,7 +408,8 @@ if (args.ccov): # only run RV64GC tests on Questa in code coverage mode
if (args.fp): if (args.fp):
addTests(tests64gc_fp, coveragesim) addTests(tests64gc_fp, coveragesim)
elif (args.fcov): # only run RV64GC tests on Questa in lockstep in functional coverage mode elif (args.fcov): # only run RV64GC tests on Questa in lockstep in functional coverage mode
addLockstepTestsByDir(WALLY+"/tests/functcov/rv64/I", "rv64gc", coveragesim) # addLockstepTestsByDir(WALLY+"/tests/functcov/rv64/I", "rv64gc", coveragesim)
addLockstepTestsByDir(WALLY+"/addins/cvw-arch-verif/tests/rv32/I", "rv32gc", coveragesim)
elif (args.fcovrvvi): # only run RV64GC tests on Questa in rvvi coverage mode elif (args.fcovrvvi): # only run RV64GC tests on Questa in rvvi coverage mode
addTests(tests64gc_nofp, coveragesim) addTests(tests64gc_nofp, coveragesim)
if (args.fp): if (args.fp):
@ -545,7 +546,8 @@ def main():
if args.ccov: if args.ccov:
os.system('make QuestaCodeCoverage') os.system('make QuestaCodeCoverage')
if args.fcov: if args.fcov:
os.system('make QuestaFunctCoverage') #os.system('make QuestaFunctCoverage')
os.system('make -f '+WALLY+'/addins/cvw-arch-verif/Makefile merge')
if args.fcovrvvi: if args.fcovrvvi:
os.system('make QuestaFunctCoverageRvvi') os.system('make QuestaFunctCoverageRvvi')
# Count the number of failures # Count the number of failures

View File

@ -27,8 +27,8 @@ parser.add_argument("--sim", "-s", help="Simulator", choices=["questa", "verilat
parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench") 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") parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true")
parser.add_argument("--ccov", "-c", help="Code Coverage", action="store_true") parser.add_argument("--ccov", "-c", help="Code Coverage", action="store_true")
parser.add_argument("--fcov", "-f", help="Functional Coverage, implies lockstep", action="store_true") parser.add_argument("--fcovimp", "-f2", help="Functional Coverage with Imperas licensed riscvISACOV, implies lockstep", action="store_true")
parser.add_argument("--fcov2", "-f2", help="Functional Coverage, implies lockstep", action="store_true") parser.add_argument("--fcov", "-f", help="Functional Coverage with cvw-arch-verif, implies lockstep", action="store_true")
parser.add_argument("--fcovrvvi", "-fr", help="Functional Coverage RVVI", action="store_true") parser.add_argument("--fcovrvvi", "-fr", help="Functional Coverage RVVI", action="store_true")
parser.add_argument("--args", "-a", help="Optional arguments passed to simulator via $value$plusargs", default="") 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("--params", "-p", help="Optional top-level parameter overrides of the form param=value", default="")
@ -68,7 +68,7 @@ if(args.testsuite.endswith('.elf') and args.elf == ""): # No --elf argument; che
# Validate arguments # Validate arguments
if (args.gui or args.ccov or args.fcov or args.fcov2 or args.fcovrvvi or args.lockstep): if (args.gui or args.ccov or args.fcov or args.fcovimp or args.fcovrvvi or args.lockstep):
if args.sim not in ["questa", "vcs"]: if args.sim not in ["questa", "vcs"]:
print("Option only supported for Questa and VCS") print("Option only supported for Questa and VCS")
exit(1) exit(1)
@ -85,7 +85,7 @@ if (args.tb == "testbench_fp"):
# if lockstep is enabled, then we need to pass the Imperas lockstep arguments # if lockstep is enabled, then we need to pass the Imperas lockstep arguments
if(int(args.locksteplog) >= 1): EnableLog = 1 if(int(args.locksteplog) >= 1): EnableLog = 1
else: EnableLog = 0 else: EnableLog = 0
if((args.lockstep or args.fcov or args.fcov2) and args.sim == "questa"): if((args.lockstep or args.fcov or args.fcovimp) and args.sim == "questa"):
prefix = "IMPERAS_TOOLS=" + WALLY + "/config/"+args.config+"/imperas.ic" prefix = "IMPERAS_TOOLS=" + WALLY + "/config/"+args.config+"/imperas.ic"
prefix = "MTI_VCO_MODE=64 " + prefix prefix = "MTI_VCO_MODE=64 " + prefix
else: else:
@ -94,13 +94,13 @@ else:
if (args.lockstep): if (args.lockstep):
if(args.locksteplog != 0): ImperasPlusArgs = " +IDV_TRACE2LOG=" + str(EnableLog) + " +IDV_TRACE2LOG_AFTER=" + str(args.locksteplog) if(args.locksteplog != 0): ImperasPlusArgs = " +IDV_TRACE2LOG=" + str(EnableLog) + " +IDV_TRACE2LOG_AFTER=" + str(args.locksteplog)
else: ImperasPlusArgs = "" else: ImperasPlusArgs = ""
if(args.fcov): if(args.fcovimp):
CovEnableStr = "1" if int(args.covlog) > 0 else "0" CovEnableStr = "1" if int(args.covlog) > 0 else "0"
if(args.covlog >= 1): EnableLog = 1 if(args.covlog >= 1): EnableLog = 1
else: EnableLog = 0 else: EnableLog = 0
ImperasPlusArgs = " +IDV_TRACE2COV=" + str(EnableLog) + " +TRACE2LOG_AFTER=" + str(args.covlog) + " +TRACE2COV_ENABLE=" + CovEnableStr ImperasPlusArgs = " +IDV_TRACE2COV=" + str(EnableLog) + " +TRACE2LOG_AFTER=" + str(args.covlog) + " +TRACE2COV_ENABLE=" + CovEnableStr
suffix = "" suffix = ""
if(args.fcov2): if(args.fcov):
CovEnableStr = "1" if int(args.covlog) > 0 else "0"; CovEnableStr = "1" if int(args.covlog) > 0 else "0";
if(args.covlog >= 1): EnableLog = 1 if(args.covlog >= 1): EnableLog = 1
else: EnableLog = 0 else: EnableLog = 0
@ -121,8 +121,8 @@ if (args.ccov):
flags += " --ccov" flags += " --ccov"
if (args.fcov): if (args.fcov):
flags += " --fcov" flags += " --fcov"
if (args.fcov2): if (args.fcovimp):
flags += " --fcov2" flags += " --fcovimp"
if (args.fcovrvvi): if (args.fcovrvvi):
flags += "--fcovrvvi" flags += "--fcovrvvi"

View File

@ -111,9 +111,9 @@
# Add Imperas simulator application instruction tracing # Add Imperas simulator application instruction tracing
# uncomment these to provide tracing # uncomment these to provide tracing
--verbose --trace --tracechange --traceshowicount --tracemode -tracemem ASX --monitornetschange # --traceafter 300000000 #--verbose --trace --tracechange --traceshowicount --tracemode -tracemem ASX --monitornetschange # --traceafter 300000000
--override cpu/debugflags=6 --override cpu/verbose=1 #--override cpu/debugflags=6 --override cpu/verbose=1
--override cpu/show_c_prefix=T #--override cpu/show_c_prefix=T
# Store simulator output to logfile # Store simulator output to logfile
--output imperas.log --output imperas.log

View File

@ -115,8 +115,8 @@ if {[lcheck lst "--fcovrvvi"]} {
set FCdefineRVVI_COVERAGE "+define+RVVI_COVERAGE" set FCdefineRVVI_COVERAGE "+define+RVVI_COVERAGE"
} }
# if --fcov found set flag and remove from list # if --fcovimp found set flag and remove from list
if {[lcheck lst "--fcov"]} { if {[lcheck lst "--fcovimp"]} {
set FunctCoverage 1 set FunctCoverage 1
set FCvlog "+define+INCLUDE_TRACE2COV \ set FCvlog "+define+INCLUDE_TRACE2COV \
+define+IDV_INCLUDE_TRACE2COV \ +define+IDV_INCLUDE_TRACE2COV \
@ -135,15 +135,17 @@ if {[lcheck lst "--fcov"]} {
} }
# if --fcov2 found set flag and remove from list # if --fcov found set flag and remove from list
if {[lcheck lst "--fcov2"]} { if {[lcheck lst "--fcov"]} {
set FunctCoverage 1 set FunctCoverage 1
set FCvlog "+define+INCLUDE_TRACE2COV \ set FCvlog "+define+INCLUDE_TRACE2COV \
+define+IDV_INCLUDE_TRACE2COV \ +define+IDV_INCLUDE_TRACE2COV \
+define+COVER_BASE_RV32I \ +define+COVER_BASE_RV32I \
+define+COVER_LEVEL_DV_PR_EXT \ +define+COVER_LEVEL_DV_PR_EXT \
+incdir+$env(WALLY)/addins/riscvISACOV/source \ +incdir+$env(WALLY)/addins/riscvISACOV/source \
+incdir+$env(WALLY)/addins/cvw-arch-verif/fcov/RV32" "
# +incdir+$env(WALLY)/addins/cvw-arch-verif/fcov/rv32 \
set FCvopt "+TRACE2COV_ENABLE=1 +IDV_TRACE2COV=1" set FCvopt "+TRACE2COV_ENABLE=1 +IDV_TRACE2COV=1"
# Uncomment various cover statements below to control which extensions get functional coverage # Uncomment various cover statements below to control which extensions get functional coverage
lappend FCdefineCOVER_EXTS "+define+COVER_RV32I" lappend FCdefineCOVER_EXTS "+define+COVER_RV32I"
@ -165,7 +167,6 @@ if {[lcheck lst "--lockstep"] || $FunctCoverage == 1} {
${IMPERAS_HOME}/ImpPublic/source/host/rvvi/*.sv \ ${IMPERAS_HOME}/ImpPublic/source/host/rvvi/*.sv \
${IMPERAS_HOME}/ImpProprietary/source/host/idv/*.sv" ${IMPERAS_HOME}/ImpProprietary/source/host/idv/*.sv"
set SVLib "-sv_lib ${IMPERAS_HOME}/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model" set SVLib "-sv_lib ${IMPERAS_HOME}/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model"
#set OtherFlags $::env(OTHERFLAGS) # not working 7/15/24 dh; this should be the way to pass things like --verbose (Issue 871)
} }
# Set PlusArgs passed using the --args flag # Set PlusArgs passed using the --args flag
@ -202,7 +203,7 @@ if {$DEBUG > 0} {
# suppress spurious warnngs about # suppress spurious warnngs about
# "Extra checking for conflicts with always_comb done at vopt time" # "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt # because vsim will run vopt
set INC_DIRS "+incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared +incdir+${FCRVVI}/common +incdir+${FCRVVI}" set INC_DIRS "+incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared +incdir+${FCRVVI} +incdir+${FCRVVI}/rv32 +incdir+${FCRVVI}/common +incdir+${FCRVVI}"
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" 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 -lint +nowarnRDGN -work ${WKDIR} {*}${INC_DIRS} {*}${FCvlog} {*}${FCdefineCOVER_EXTS} {*}${lockstepvlog} ${FCdefineRVVI_COVERAGE} {*}${SOURCES} -suppress 2244 -suppress 2282 -suppress 2583 -suppress 7063,2596,13286 vlog -lint +nowarnRDGN -work ${WKDIR} {*}${INC_DIRS} {*}${FCvlog} {*}${FCdefineCOVER_EXTS} {*}${lockstepvlog} ${FCdefineRVVI_COVERAGE} {*}${SOURCES} -suppress 2244 -suppress 2282 -suppress 2583 -suppress 7063,2596,13286

View File

@ -1,39 +0,0 @@
#all:
# ./covergen.py
# cd ../riscof; make wally-riscv-arch-test
# cd ../../sim; make memfiles
CEXT := c
CPPEXT := cpp
AEXT := s
SEXT := S
SRCEXT := \([$(CEXT)$(AEXT)$(SEXT)]\|$(CPPEXT)\)
#SRCS = $(wildcard *.S)
#PROGS = $(patsubst %.S,%,$(SRCS))
SRCDIR = ${WALLY}/tests/functcov/rv64/I
SRCEXT = S
SOURCES ?= $(shell find $(SRCDIR) -type f -regex ".*\.$(SRCEXT)" | sort)
OBJEXT = elf
OBJECTS := $(SOURCES:.$(SEXT)=.$(OBJEXT))
all:
./covergen.py
make build
build: $(OBJECTS)
%.elf.objdump: %.elf
# Change many things if bit width isn't 64
$(SRCDIR)/%.elf: $(SRCDIR)/%.$(SEXT)
riscv64-unknown-elf-gcc -g -o $@ -march=rv64gqc_zfa_zba_zbb_zbc_zbs_zfh_zicboz_zicbop_zicbom -mabi=lp64 -mcmodel=medany \
-nostartfiles -T${WALLY}/examples/link/link.ld $<
riscv64-unknown-elf-objdump -S -D $@ > $@.objdump
riscv64-unknown-elf-elf2hex --bit-width 64 --input $@ --output $@.memfile
extractFunctionRadix.sh $@.objdump
clean:
rm -f ${SRCDIR}/*.elf ${SRCDIR}/*.objdump ${SRCDIR}/*.addr *${SRCDIR}/.lab ${SRCDIR}/*.memfile

View File

@ -1,491 +0,0 @@
#!/usr/bin/env python3
##################################
# covergen.py
#
# David_Harris@hmc.edu 27 March 2024
#
# Generate directed tests for functional coverage
##################################
##################################
# libraries
##################################
from datetime import datetime
from random import randint
from random import seed
from random import getrandbits
import os
import re
##################################
# functions
##################################
def shiftImm(imm, xlen):
imm = imm % xlen
return str(imm)
def signedImm12(imm):
imm = imm % pow(2, 12)
if (imm & 0x800):
imm = imm - 0x1000
return str(imm)
def unsignedImm20(imm):
imm = imm % pow(2, 20)
return str(imm)
def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen):
lines = "\n# Testcase " + str(desc) + "\n"
if (rs1val < 0):
rs1val = rs1val + 2**xlen
if (rs2val < 0):
rs2val = rs2val + 2**xlen
lines = lines + "li x" + str(rd) + ", " + formatstr.format(rdval) + " # initialize rd to a random value that should get changed; helps covering rd_toggle\n"
if (test in rtype):
lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n"
lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n"
lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", x" + str(rs2) + " # perform operation\n"
elif (test in shiftitype):
lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n"
if (test in shiftiwtype):
lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + shiftImm(immval, 32) + " # perform operation\n"
else:
lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + shiftImm(immval, xlen) + " # perform operation\n"
elif (test in itype):
lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n"
lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # perform operation\n"
elif (test in loaditype):#["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"]
if (rs1 != 0):
lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n"
lines = lines + "la x" + str(rs1) + ", scratch" + " # base address \n"
lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(-immval) + " # sub immediate from rs1 to counter offset\n"
if (xlen == 32):
storeop = "sw"
else:
storeop = "sd"
lines = lines + storeop + " x" + str(rs2) + ", " + signedImm12(immval) +" (x" + str(rs1) + ") # store value to put someting in memory\n"
lines = lines + test + " x" + str(rd) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation\n"
# lines = lines + test + " x" + str(rd) + ", 0(x" + str(rs1) + ") # perform operation\n"
elif (test in stype):#["sb", "sh", "sw", "sd"]
if (rs1 != 0):
if (rs2 == rs1): # make sure registers are different so they don't conflict
rs2 = (rs1 + 1) % 32
if (rs2 == 0):
rs2 = 1
lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n"
lines = lines + "la x" + str(rs1) + ", scratch" + " # base address \n"
lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(-immval) + " # sub immediate from rs1 to counter offset\n"
lines = lines + test + " x" + str(rs2) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation \n"
elif (test in btype):#["beq", "bne", "blt", "bge", "bltu", "bgeu"]
for same in range(2):
if (same):
rs1val = rs2val
lines = lines + "# same values in both registers\n"
lines = lines + "nop\n"
lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n"
lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2\n"
lines = lines + test + " x" + str(rs1) + ", x" + str(rs2) + ", some_label_for_btype_" + str(immval) + str(same) + " # perform operation \n"
lines = lines + "addi x0, x1, 1\n"
lines = lines + "some_label_for_btype_" + str(immval)+ str(same) + ":\n"
lines = lines + "addi x0, x2, 2\n"
lines = lines + "nop\nnop\nnop\nnop\nnop\n"
elif (test in jtype):#["jal"]
lines = lines + "jal x" + str(rd) + ", 1f # perform operation\n"
lines = lines + "nop\n"
lines = lines + "1:\n"
elif (test in jalrtype):#["jalr"]
lines = lines + "la x" + str(rs1) + ", 1f\n"
lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(-immval) + " # add immediate to lower part of rs1\n"
lines = lines + "jalr x" + str(rd) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # perform operation\n"
lines = lines + "nop\n"
lines = lines + "1:\n"
elif (test in utype):#["lui", "auipc"]
lines = lines + test + " x" + str(rd) + ", " + unsignedImm20(immval) + " # perform operation\n"
else:
pass
#print("Error: %s type not implemented yet" % test)
f.write(lines)
def writeHazardVector(desc, rs1a, rs2a, rda, rs1b, rs2b, rdb, test):
# consecutive R-type instructions to trigger hazards
lines = "\n# Testcase " + str(desc) + "\n"
lines = lines + test + " x" + str(rda) + ", x" + str(rs1a) + ", x" + str(rs2a) + " # perform first operation\n"
lines = lines + test + " x" + str(rdb) + ", x" + str(rs1b) + ", x" + str(rs2b) + " # perform second operation\n"
f.write(lines)
def randomize():
rs1 = randint(1, 31)
rs2 = randint(1, 31)
# choose rd that is different than rs1 and rs2
rd = rs1
while (rd == rs1 or rd == rs2):
rd = randint(1, 31)
rd = randint(1, 31)
rs1val = randint(0, 2**xlen-1)
rs2val = randint(0, 2**xlen-1)
immval = randint(0, 2**xlen-1)
rdval = randint(0, 2**xlen-1)
return [rs1, rs2, rd, rs1val, rs2val, immval, rdval]
def make_rd(test, xlen):
for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rd (Test destination rd = x" + str(r) + ")"
writeCovVector(desc, rs1, rs2, r, rs1val, rs2val, immval, rdval, test, xlen)
def make_rs1(test, xlen):
for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rs1 (Test source rs1 = x" + str(r) + ")"
writeCovVector(desc, r, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen)
def make_rs2(test, xlen):
for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rs2 (Test source rs2 = x" + str(r) + ")"
writeCovVector(desc, rs1, r, rd, rs1val, rs2val, immval, rdval, test, xlen)
def make_rd_rs1(test, xlen):
for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rd_rs1 (Test rd = rs1 = x" + str(r) + ")"
writeCovVector(desc, r, rs2, r, rs1val, rs2val, immval, rdval, test, xlen)
def make_rd_rs2(test, xlen):
for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rd_rs2 (Test rd = rs1 = x" + str(r) + ")"
writeCovVector(desc, rs1, r, r, rs1val, rs2val, immval, rdval, test, xlen)
def make_rd_rs1_rs2(test, xlen):
for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rd_rs1_rs2 (Test rd = rs1 = rs2 = x" + str(r) + ")"
writeCovVector(desc, r, r, r, rs1val, rs2val, immval, rdval, test, xlen)
def make_rs1_rs2(test, xlen):
for r in range(32):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rs1_rs2 (Test rs1 = rs2 = x" + str(r) + ")"
writeCovVector(desc, r, r, rd, rs1val, rs2val, immval, rdval, test, xlen)
def make_rs1_maxvals(test, xlen):
for v in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rs1_maxvals (Test source rs1 value = " + hex(v) + ")"
writeCovVector(desc, rs1, rs2, rd, v, rs2val, immval, rdval, test, xlen)
def make_rs2_maxvals(test, xlen):
for v in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rs2_maxvals (Test source rs2 value = " + hex(v) + ")"
writeCovVector(desc, rs1, rs2, rd, rs1val, v, immval, rdval, test, xlen)
def make_rd_maxvals(test, xlen):
for v in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]:
# rs1 = 0, rs2 = v, others are random
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")"
writeCovVector(desc, rs1, 0, rd, v, rs2val, 0, rdval, test, xlen)
# rs1, rs2 = v, others are random
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")"
writeCovVector(desc, rs1, rs2, rd, v, v, v, rdval, test, xlen)
# rs1 = all 1s, rs2 = v, others are random
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_rd_maxvals (Test rd value = " + hex(v) + ")"
writeCovVector(desc, rs1, rs2, rd, v, -1, -1, rdval, test, xlen)
def make_rd_rs1_eqval(test, xlen):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rdm_rs1_eqval (Test rs1 = rd = " + hex(rs1val) + ")"
writeCovVector(desc, rs1, 0, rd, rdval, rs2val, immval, rdval, test, xlen)
def make_rd_rs2_eqval(test, xlen):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rd_rs2_eqval (Test rs2 = rd = " + hex(rs2val) + ")"
writeCovVector(desc, 0, rs2, rd, rs1val, rdval, immval, rdval, test, xlen)
def make_rs1_rs2_eqval(test, xlen):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cmp_rs1_rs2_eqval (Test rs1 = rs2 = " + hex(rs1val) + ")"
writeCovVector(desc, rs1, rs2, rd, rs1val, rs1val, immval, rdval, test, xlen)
def make_cp_gpr_hazard(test, xlen):
for haz in ["raw", "waw", "war"]:
for src in range(2):
[rs1a, rs2a, rda, rs1vala, rs2vala, immvala, rdvala] = randomize()
[rs1b, rs2b, rdb, rs1valb, rs2valb, immvalb, rdvalb] = randomize()
# set up hazard
if (haz == "raw"):
if (src):
rs2b = rda
else:
rs1b = rda
elif (haz == "waw"):
rdb = rda
elif (haz == "war"):
if (src):
rdb = rs2a
else:
rdb = rs1a
desc = "cmp_gpr_hazard " + haz + " test"
writeHazardVector(desc, rs1a, rs2a, rda, rs1b, rs2b, rdb, test)
def make_rs1_sign(test, xlen):
for v in [1, -1]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
rs1val = abs(rs1val % 2**(xlen-1)) * v;
desc = "cp_rs1_sign (Test source rs1 value = " + hex(rs1val) + ")"
writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen)
def make_rs2_sign(test, xlen):
for v in [1, -1]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
rs2val = abs(rs2val % 2**(xlen-1)) * v;
desc = "cp_rs2_sign (Test source rs2 value = " + hex(rs2val) + ")"
writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen)
def make_cr_rs1_rs2_sign(test, xlen):
for v1 in [1, -1]:
for v2 in [1, -1]:
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
rs1val = abs(rs1val % 2**(xlen-1)) * v1;
rs2val = abs(rs2val % 2**(xlen-1)) * v2;
desc = "cr_rs1_rs2 (Test source rs1 = " + hex(rs1val) + " rs2 = " + hex(rs2val) + ")"
writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen)
def make_imm_zero(test, xlen):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
desc = "cp_imm_zero"
writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, 0, rdval, test, xlen)
def make_j_imm_ones_zeros(test, xlen):
for align in range(2,19):
lines = "\n# Testcase cp_imm_ones_zeros " + str(align) + "\n"
lines = lines + "li x1, " + formatstr.format(randint(0, 2**xlen-1)) + "\n"
lines = lines + "jal x20, 1f # jump to aligned address to stress immediate\n"
lines = lines + ".align " + str(align) + "\n"
lines = lines + "1:\n"
f.write(lines)
def make_offset(test, xlen):
if (test in btype):
lines = "\n# Testcase cp_offset\n"
lines = lines + "j 2f # jump past backward branch target\n"
lines = lines + "1: j 3f # backward branch target: jump past backward branch\n"
lines = lines + "2: " + test + " x0, x0, 1b # backward branch\n"
lines = lines + "3: nop # done with sequence\n"
f.write(lines)
def make_mem_hazard(test, xlen):
lines = "\n# Testcase mem_hazard (no dependency)\n"
lines = lines + "la x1, scratch\n"
lines = lines + test + " x2, 0(x1)\n"
f.write(lines)
def make_cr_rs1_imm(test, xlen):
desc = "cp_cr_rs1_imm"
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
for s1 in range(2):
for s2 in range(3):
if (s1):
rs1v = -abs(rs1val)
else:
rs1v = abs(rs1val)
if (s2 == 0):
immv = 0
elif (s2 == 1):
immv = abs(immval)
else:
immv = -abs(immval)
writeCovVector(desc, rs1, rs2, rd, rs1v, rs2val, immv, rdval, test, xlen)
def make_imm_shift(test, xlen):
desc = "cp_imm_shift"
for shift in range(0, xlen):
[rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize()
writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, shift, rdval, test, xlen)
def write_tests(coverpoints, test, xlen):
for coverpoint in coverpoints:
if (coverpoint == "cp_asm_count"):
pass
elif (coverpoint == "cp_rd"):
make_rd(test, xlen)
elif (coverpoint == "cp_rs1"):
make_rs1(test, xlen)
elif (coverpoint == "cp_rs2"):
make_rs2(test, xlen)
elif (coverpoint == "cmp_rd_rs1"):
make_rd_rs1(test, xlen)
elif (coverpoint == "cmp_rd_rs2"):
make_rd_rs2(test, xlen)
elif (coverpoint == "cmp_rd_rs1_rs2"):
make_rd_rs1_rs2(test, xlen)
elif (coverpoint == "cmp_rd_rs1_eq"):
pass # duplicate of cmp_rd_rs1
elif (coverpoint == "cmp_rd_rs2_eq"):
pass # duplicate of cmp_rd_rs2
elif (coverpoint == "cmp_rs1_rs2_eq"):
make_rs1_rs2(test, xlen)
elif (coverpoint == "cp_rs1_maxvals"):
make_rs1_maxvals(test, xlen)
elif (coverpoint == "cp_rs2_maxvals"):
make_rs2_maxvals(test, xlen)
elif (coverpoint == "cp_rd_maxvals"):
make_rd_maxvals(test, xlen)
elif (coverpoint == "cmp_rd_rs1_eqval"):
make_rd_rs1_eqval(test, xlen)
elif (coverpoint == "cmp_rd_rs2_eqval"):
make_rd_rs2_eqval(test, xlen)
elif (coverpoint == "cmp_rs1_rs2_eqval"):
make_rs1_rs2_eqval(test, xlen)
elif (coverpoint == "cp_rs1_sign"):
make_rs1_sign(test, xlen)
elif (coverpoint == "cp_rs2_sign"):
make_rs2_sign(test, xlen)
elif (coverpoint == "cp_rd_sign"):
pass #TODO hope already covered by rd_maxvals
elif (coverpoint == "cr_rs1_rs2"):
make_cr_rs1_rs2_sign(test, xlen)
elif (coverpoint == "cp_gpr_hazard"):
make_cp_gpr_hazard(test, xlen)
elif (coverpoint == "cp_rs1_toggle"):
pass #TODO toggle not needed and seems to be covered by other things
elif (coverpoint == "cp_rs2_toggle"):
pass #TODO toggle not needed and seems to be covered by other things
elif (coverpoint == "cp_rd_toggle"):
pass #TODO toggle not needed and seems to be covered by other things
elif (coverpoint == "cp_imm_sign"):
make_imm_zero(test, xlen)
elif (coverpoint == "cr_rs1_imm"):
make_cr_rs1_imm(test, xlen)
elif (coverpoint == "cp_imm_ones_zeros"):
if (test in jtype):
make_j_imm_ones_zeros(test, xlen)
elif (coverpoint == "cp_mem_hazard"):
make_mem_hazard(test, xlen)
elif (coverpoint == "cp_imm_zero"):
make_imm_zero(test, xlen)
elif (coverpoint == "cp_mem_unaligned"):
pass # seems this should be part of privileged tests
elif (coverpoint == "cp_offset"):
make_offset(test, xlen)
elif (coverpoint == "cr_nord_rs1_rs2"):
pass #TODO (not if crosses are not needed)
elif (coverpoint == "cp_imm_shift"):
make_imm_shift(test, xlen)
elif (coverpoint == "cp_rd_boolean"):
pass # covered by other generators
else:
print("Warning: " + coverpoint + " not implemented yet for " + test)
def getcovergroups(coverdefdir, coverfiles):
coverpoints = {}
curinstr = ""
for coverfile in coverfiles:
coverfile = coverdefdir + "/" + coverfile + "_coverage.svh"
f = open(coverfile, "r")
for line in f:
m = re.search(r'cp_asm_count.*\"(.*)"', line)
if (m):
# if (curinstr != ""):
# print(curinstr + ": " + str(coverpoints[curinstr]))
curinstr = m.group(1)
coverpoints[curinstr] = []
m = re.search("\s*(\S+) :", line)
if (m):
coverpoints[curinstr].append(m.group(1))
f.close()
print(coverpoints)
return coverpoints
##################################
# main body
##################################
# change these to suite your tests
riscv = os.environ.get("RISCV")
coverdefdir = riscv+"/ImperasDV-OpenHW/Imperas/ImpProprietary/source/host/riscvISACOV/source/coverage";
#coverfiles = ["RV64I", "RV64M", "RV64A", "RV64C", "RV64F", "RV64D"] # add more later
coverfiles = ["RV64I"] # add more later
rtype = ["add", "sub", "sll", "slt", "sltu", "xor", "srl", "sra", "or", "and",
"addw", "subw", "sllw", "srlw", "sraw"
"mul", "mulh", "mulhsu", "mulhu", "div", "divu", "rem", "remu",
"mulw", "divw", "divuw", "remw", "remuw"]
loaditype = ["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"]
shiftitype = ["slli", "srli", "srai", "slliw", "srliw", "sraiw"]
shiftiwtype = ["slliw", "srliw", "sraiw"]
itype = ["addi", "slti", "sltiu", "xori", "ori", "andi", "addiw"]
stype = ["sb", "sh", "sw", "sd"]
btype = ["beq", "bne", "blt", "bge", "bltu", "bgeu"]
jtype = ["jal"]
jalrtype = ["jalr"]
utype = ["lui", "auipc"]
# TODO: auipc missing, check whatelse is missing in ^these^ types
coverpoints = getcovergroups(coverdefdir, coverfiles)
author = "David_Harris@hmc.edu"
xlens = [64]
numrand = 3
# setup
seed(0) # make tests reproducible
# generate files for each test
for xlen in xlens:
formatstrlen = str(int(xlen/4))
formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number
formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x
if (xlen == 32):
storecmd = "sw"
wordsize = 4
else:
storecmd = "sd"
wordsize = 8
WALLY = os.environ.get('WALLY')
pathname = WALLY+"/tests/functcov/rv" + str(xlen) + "/I/"
cmd = "mkdir -p " + pathname + " ; rm -f " + pathname + "/*" # make directory and remove old tests in dir
os.system(cmd)
for test in coverpoints.keys():
basename = "WALLY-COV-" + test
fname = pathname + "/" + basename + ".S"
# print custom header part
f = open(fname, "w")
line = "///////////////////////////////////////////\n"
f.write(line)
line="// "+fname+ "\n// " + author + "\n"
f.write(line)
line ="// Created " + str(datetime.now()) + "\n"
f.write(line)
# insert generic header
h = open("covergen_header.S", "r")
for line in h:
f.write(line)
# print directed and random test vectors
# Coverage for R-type arithmetic instructions
#if (test not in rtests):
# exit("Error: %s not implemented yet" % test)
#else:
# write_rtype_arith_vectors(test, xlen)
write_tests(coverpoints[test], test, xlen)
# print footer
line = "\n.EQU NUMTESTS," + str(1) + "\n\n"
f.write(line)
h = open("covergen_footer.S", "r")
for line in h:
f.write(line)
# Finish
f.close()

View File

@ -1,11 +0,0 @@
self_loop:
j self_loop
.data
.align 4
scratch:
.bss 8
.end

View File

@ -1,12 +0,0 @@
//
// Copyright (C) 2024 Harvey Mudd College & Oklahoma State University
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
///////////////////////////////////////////
.section .text.init
.globl rvtest_entry_point
rvtest_entry_point:

View File

@ -8,7 +8,7 @@ This folder consists of all the required files and tools to generate Q tests for
NOTE : Only some of the IBM tests are currently supporting Quad testing. NOTE : Only some of the IBM tests are currently supporting Quad testing.
Tests which are working : ibm1, ibm9,ibm21,ibm23,ibm24,ibm25,ibm26,ibm27,ibm28,ibm29 Tests which are implemented in riscv-isac/riscv_isac/fp_dataset.py : ibm1, ibm9,ibm21,ibm23,ibm24,ibm25,ibm26,ibm27,ibm28,ibm29
These ibm tests can be included in the riscv-ctg tests generation command, along with riscof. These ibm tests can be included in the riscv-ctg tests generation command, along with riscof.
The tests which are currently breaking due to overflow errors are : ibm2,ibm3,ibm4,ibm5,ibm6,ibm7,ibm8,ibm10,ibm11,ibm12,ibm13,ibm14,ibm15,ibm16,ibm17,ibm18,ibm19,ibm20,ibm22 The tests which are currently breaking due to overflow errors are : ibm2,ibm3,ibm4,ibm5,ibm6,ibm7,ibm8,ibm10,ibm11,ibm12,ibm13,ibm14,ibm15,ibm16,ibm17,ibm18,ibm19,ibm20,ibm22
@ -26,7 +26,7 @@ TO DO:
Debug why fadd.q_b1 doesn't match Sail vs. Spike Debug why fadd.q_b1 doesn't match Sail vs. Spike
Run the q test on Wally RTL Run the q test on Wally RTL
Make more tests from the working datasets Make more tests from the working datasets
Get other datasets working by using softfloat to do quad math Get other fp_dataset.py 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 Push changes back to riscv-ctg and riscv-isac and remove them from wally-riscv-arch/tsts/riscv-test-suite/rv64i_m/Q

View File

@ -393,7 +393,7 @@ def ibm_b1(flen, iflen, opcode, ops):
qinfinity + qdefaultnan + [qqnan[0], qqnan[1]] + \ qinfinity + qdefaultnan + [qqnan[0], qqnan[1]] + \
[qsnan[0], qsnan[1]] + qone [qsnan[0], qsnan[1]] + qone
else: else:
logger.error('Invalid iflen value!') logger.error('Invalid iflen value is ' + iflen)
sys.exit(1) sys.exit(1)
# the following creates a cross product for ops number of variables # the following creates a cross product for ops number of variables
@ -4073,7 +4073,7 @@ def ibm_b21(flen, iflen, opcode, ops):
qinfinity + qdefaultnan + [qqnan[0], qqnan[1]] + \ qinfinity + qdefaultnan + [qqnan[0], qqnan[1]] + \
[qsnan[0], qsnan[1]] [qsnan[0], qsnan[1]]
else: else:
logger.error('Invalid iflen value!') logger.error('Invalid iflen value 2 ' + iflen)
sys.exit(1) sys.exit(1)
# the following creates a cross product for ops number of variables # the following creates a cross product for ops number of variables