diff --git a/bin/regression-wally b/bin/regression-wally index 8d67e387b..5a374b2d9 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -282,6 +282,22 @@ def addTests(tests, sim): grepfile = grepfile) configs.append(tc) +def addLockstepTestsByDir(dir, config, sim): + sim_logdir = WALLY+ "/sim/" + sim + "/logs/" + cmdPrefix="wsim --sim " + sim + " " + coverStr + " " + config + for file in os.listdir(dir): + if file.endswith(".elf"): + fullfile = os.path.join(dir, file) + sim_log = sim_logdir + config + "_" + file + grepstring = "" + tc = TestCase( + name=file, + variant=config, + cmd=cmdPrefix + " " + fullfile + " > " + sim_log, + grepstr="Mismatches : 0", + grepfile = sim_log) + configs.append(tc) + def search_log_for_text(text, grepfile): """Search through the given log file for text, returning True if it is found or False if it is not""" grepwarn = "grep -H Warning: " + grepfile @@ -332,14 +348,15 @@ args = parser.parse_args() if (args.nightly): nightMode = "--nightly"; -# sims = [defaultsim] # uncomment to use only the default simulator - sims = ["questa", "verilator", "vcs"] # uncomment to exercise all simulators + sims = ["questa", "verilator", "vcs"] # exercise all simulators; can omit a sim if no license is available else: nightMode = "" sims = [defaultsim] if (args.ccov): # only run RV64GC tests in coverage mode coverStr = '--ccov' +elif (args.fcov): # only run RV64GC tests in lockstep in coverage mode + coverStr = '--fcov' else: coverStr = '' @@ -362,10 +379,20 @@ if (args.buildroot): addTests(tests_buildrootbootlockstep, "questa") # lockstep with Questa and ImperasDV runs overnight if (args.ccov): # only run RV64GC tests on Questa in code coverage mode - addTests(tests64gc_nofp, "questa") + addTests(tests64gc_nofp, coveragesim) if (args.fp): - addTests(tests64gc_fp, "questa") -else: + addTests(tests64gc_fp, coveragesim) +elif (args.fcov): # only run RV64GC tests on Questa in lockstep in functional coverage mode + addLockstepTestsByDir(WALLY+"/tests/functcov/rv64/I", "rv64gc", coveragesim) + #sim_log = WALLY + "/sim/questa/logs/fcov.log" + #tc = TestCase( + # name="lockstep_functcov", + # variant="rv64gc", + # cmd="iterelf " + WALLY + "/tests/functcov/rv64/I > " + sim_log, + # grepstr="SUCCESS! All tests ran without failures", + # grepfile = sim_log) + #configs.append(tc) +else: for sim in sims: if (not (args.buildroot and sim == defaultsim)): # skip short buildroot sim if running long one addTests(tests_buildrootshort, sim) @@ -375,7 +402,6 @@ else: # run derivative configurations and lockstep tests in nightly regression if (args.nightly): - addTests(derivconfigtests, defaultsim) sim_log = WALLY + "/sim/questa/logs/lockstep_coverage.log" tc = TestCase( name="lockstep_coverage", @@ -393,6 +419,7 @@ if (args.nightly): grepstr="SUCCESS! All tests ran without failures", grepfile = sim_log) configs.append(tc) + addTests(derivconfigtests, defaultsim) # testfloat tests if (args.testfloat): # for testfloat alone, just run testfloat tests @@ -474,16 +501,24 @@ def main(): if args.ccov: TIMEOUT_DUR = 20*60 # seconds os.system('rm -f questa/cov/*.ucdb') - elif args.nightly in sys.argv: + elif args.fcov: + TIMEOUT_DUR = 1*60 + os.system('rm -f questa/fcov_ucdb/* questa/fcov_logs/* questa/fcov/*') + elif args.nightly: TIMEOUT_DUR = 60*1440 # 1 day - elif args.testfloat in sys.argv: + elif args.testfloat: TIMEOUT_DUR = 30*60 # seconds else: TIMEOUT_DUR = 10*60 # seconds # Scale the number of concurrent processes to the number of test cases, but # max out at a limited number of concurrent processes to not overwhelm the system - with Pool(processes=min(len(configs),multiprocessing.cpu_count())) as pool: + # right now fcov, ccov, nightly all use Imperas + if (args.ccov or args.fcov or args.nightly): + ImperasDVLicenseCount = 8 # limit number of concurrent processes to avoid overloading ImperasDV licenses + else: + ImperasDVLicenseCount = 10000 # effectively no license limit for non-lockstep tests + with Pool(processes=min(len(configs),multiprocessing.cpu_count(), ImperasDVLicenseCount)) as pool: num_fail = 0 results = {} for config in configs: @@ -498,6 +533,8 @@ def main(): # Coverage report if args.ccov: os.system('make QuestaCodeCoverage') + if args.fcov: + os.system('make QuestaFunctCoverage') # Count the number of failures if num_fail: print(f"{bcolors.FAIL}Regression failed with %s failed configurations{bcolors.ENDC}" % num_fail) diff --git a/sim/Makefile b/sim/Makefile index 5635431ff..1197dfc2e 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -30,6 +30,13 @@ QuestaCodeCoverage: questa/ucdb/rv64gc_arch64i.ucdb # vcover report -recursive questa/ucdb/cov.ucdb > questa/cov/rv64gc_recursive.rpt vcover report -details -threshH 100 -html questa/ucdb/cov.ucdb +QuestaFunctCoverage: ${SIM}/questa/fcov_ucdb/rv64gc_WALLY-COV-add.elf.ucdb + vcover merge -out ${SIM}/questa/fcov_ucdb/fcov.ucdb ${SIM}/questa/fcov_ucdb/rv64gc_WALLY-COV-add.elf.ucdb ${SIM}/questa/fcov_ucdb/rv64gc_WALLY*.ucdb -logfile ${SIM}/questa/fcov_logs/log + vcover report -details -html ${SIM}/questa/fcov_ucdb/fcov.ucdb + vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -details -cvg > ${SIM}/questa/fcov/fcov.log + vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -testdetails -cvg > ${SIM}/questa/fcov/fcov.testdetails.log + vcover report ${SIM}/questa/fcov_ucdb/fcov.ucdb -details -cvg | egrep "Coverpoint|Covergroup|Cross|TYPE" > ${SIM}/questa/fcov/fcov.summary.log + grep "TOTAL COVERGROUP COVERAGE" ${SIM}/questa/fcov/fcov.log imperasdv_cov: touch ${SIM}/seed0.txt @@ -91,6 +98,7 @@ combine_functcov: cd ${SIM}/questa/fcov && rm -rf * cd ${SIM}/questa/fcov_ucdb && rm -rf * wsim rv64gc ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf --fcov > ${SIM}/questa/fcov_logs/add.log 2>&1 + wsim rv64gc ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf --fcov > ${SIM}/questa/fcov_logs/and.log 2>&1 #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/add.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-add.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1 #run-elf-cov.bash --seed ${SIM}/questa/seed0.txt --verbose --coverdb ${SIM}/questa/fcov/and.ucdb --elf ${WALLY}/tests/functcov/rv64/I/WALLY-COV-and.elf >> ${SIM}/questa/fcov_logs/add.log 2>&1 diff --git a/sim/questa/run-imperas-linux.sh b/sim/questa/run-imperas-linux.sh deleted file mode 100755 index aebf6b9d0..000000000 --- a/sim/questa/run-imperas-linux.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -#export RISCV=/scratch/moore/RISCV - -export IMPERAS_TOOLS=$(pwd)/imperas.ic -export OTHERFLAGS="+TRACE2LOG_ENABLE=1 +TRACE2LOG_AFTER=100" -#export OTHERFLAGS="+TRACE2LOG_ENABLE=1 +TRACE2LOG_AFTER=10500000" -#export OTHERFLAGS="" - -vsim -do "do wally.do buildroot buildroot testbench --lockstep +acc -GDEBUG=1" diff --git a/sim/questa/sim-imperas b/sim/questa/sim-imperas deleted file mode 100755 index 556cdebf6..000000000 --- a/sim/questa/sim-imperas +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -########################################### -## imperas-one-time.sh -## -## Written: Ross Thompson (ross1728@gmail.com) and Lee Moore (moore@imperas.com) -## Created: 31 January 2023 -## Modified: 31 January 2023 -## -## Purpose: Run wally with imperas -## -## A component of the CORE-V-WALLY configurable RISC-V project. -## https://github.com/openhwgroup/cvw -## -## Copyright (C) 2021-23 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. -################################################################################################ -IMPERAS_TOOLS=$(pwd)/imperas.ic \ -OTHERFLAGS="+TRACE2LOG_ENABLE=1 VERBOSE=1" \ -TESTDIR=${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege/src/Lee.S/ \ -vsim -do "do wally-imperas.do rv64gc" diff --git a/sim/questa/wally-imperas-cov.do b/sim/questa/wally-imperas-cov.do deleted file mode 100644 index 1b83950d0..000000000 --- a/sim/questa/wally-imperas-cov.do +++ /dev/null @@ -1,79 +0,0 @@ -# wally.do -# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -# -# Modification by Oklahoma State University & Harvey Mudd College -# Use with Testbench -# James Stine, 2008; David Harris 2021 -# Go Cowboys!!!!!! -# -# Takes 1:10 to run RV64IC tests using gui - -onbreak {resume} - -# create library -if [file exists work] { - vdel -all -} -vlib work - -# compile source files -# suppress spurious warnngs about -# "Extra checking for conflicts with always_comb done at vopt time" -# because vsim will run vopt - -# start and run simulation -# remove +acc flag for faster sim during regressions if there is no need to access internal signals - # *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings. -vlog +incdir+$env(WALLY)/config/$1 \ - +incdir+$env(WALLY)/config/deriv/$1 \ - +incdir+$env(WALLY)/config/shared \ - +define+USE_IMPERAS_DV \ - +define+IDV_INCLUDE_TRACE2COV \ - +define+INCLUDE_TRACE2COV +define+COVER_BASE_RV64I +define+COVER_LEVEL_DV_PR_EXT \ - +define+COVER_RV64I \ - +define+COVER_RV64M \ - +define+COVER_RV64A \ - +define+COVER_RV64F \ - +define+COVER_RV64D \ - +define+COVER_RV64ZICSR \ - +define+COVER_RV64C \ - +incdir+$env(IMPERAS_HOME)/ImpPublic/include/host \ - +incdir+$env(IMPERAS_HOME)/ImpProprietary/include/host \ - $env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvviApiPkg.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvApiPkg.sv \ - $env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvviTrace.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvPkg.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2bin.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2api.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2log.sv \ - \ - +incdir+$env(IMPERAS_HOME)/ImpProprietary/source/host/riscvISACOV/source \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2cov.sv \ - \ - $env(WALLY)/src/cvw.sv \ - $env(WALLY)/testbench/testbench.sv \ - $env(WALLY)/testbench/common/*.sv \ - $env(WALLY)/src/*/*.sv \ - $env(WALLY)/src/*/*/*.sv \ - -suppress 2583 \ - -suppress 7063 \ - +acc -vopt +acc work.testbench -G DEBUG=1 -o workopt -eval vsim workopt +nowarn3829 -fatal 7 \ - -sv_lib $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model \ - +ElfFile=$env(TESTDIR)/ref/ref.elf $env(OTHERFLAGS) +TRACE2COV_ENABLE=1 - -coverage save -onexit $env(WALLY)/sim/questa/riscv.ucdb - - -view wave -#-- display input and output signals as hexidecimal values -# add log -recursive /* -# do wave.do - -run -all - -noview $env(WALLY)/testbench/testbench-imperas.sv -view wave - -#quit -f diff --git a/sim/questa/wally-imperas-no-idv.do b/sim/questa/wally-imperas-no-idv.do deleted file mode 100644 index 47d8bf07b..000000000 --- a/sim/questa/wally-imperas-no-idv.do +++ /dev/null @@ -1,48 +0,0 @@ -# wally.do -# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -# -# Modification by Oklahoma State University & Harvey Mudd College -# Use with Testbench -# James Stine, 2008; David Harris 2021 -# Go Cowboys!!!!!! -# -# Takes 1:10 to run RV64IC tests using gui - -onbreak {resume} - -# create library -if [file exists work] { - vdel -all -} -vlib work - -# compile source files -# suppress spurious warnngs about -# "Extra checking for conflicts with always_comb done at vopt time" -# because vsim will run vopt - -# start and run simulation -# remove +acc flag for faster sim during regressions if there is no need to access internal signals - # *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings. -vlog +incdir+../config/$1 \ - +incdir+../config/shared \ - ../../external/ImperasDV-HMC/Imperas/ImpPublic/source/host/rvvi/rvviTrace.sv \ - ../src/cvw.sv \ - ../testbench/testbench_imperas.sv \ - ../testbench/common/*.sv \ - ../src/*/*.sv \ - ../src/*/*/*.sv \ - -suppress 2583 \ - -suppress 7063 -vopt +acc work.testbench -G DEBUG=1 -o workopt -eval vsim workopt +nowarn3829 -fatal 7 \ - +testDir=$env(TESTDIR) $env(OTHERFLAGS) -view wave -#-- display input and output signals as hexidecimal values -add log -recursive /* -do wave.do - -run -all - -noview ../testbench/testbench_imperas.sv -view wave diff --git a/sim/questa/wally-imperas.do b/sim/questa/wally-imperas.do deleted file mode 100644 index 118e44d10..000000000 --- a/sim/questa/wally-imperas.do +++ /dev/null @@ -1,64 +0,0 @@ -# wally.do -# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -# -# Modification by Oklahoma State University & Harvey Mudd College -# Use with Testbench -# James Stine, 2008; David Harris 2021 -# Go Cowboys!!!!!! -# -# Takes 1:10 to run RV64IC tests using gui - -onbreak {resume} - -# create library -if [file exists work] { - vdel -all -} -vlib work - -# compile source files -# suppress spurious warnngs about -# "Extra checking for conflicts with always_comb done at vopt time" -# because vsim will run vopt - -# start and run simulation -# remove +acc flag for faster sim during regressions if there is no need to access internal signals - # *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings. - -vlog +incdir+../config/$1 \ - +incdir+../config/shared \ - +define+USE_IMPERAS_DV \ - +incdir+$env(IMPERAS_HOME)/ImpPublic/include/host \ - +incdir+$env(IMPERAS_HOME)/ImpProprietary/include/host \ - $env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvviApiPkg.sv \ - $env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvviTrace.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvApiPkg.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvPkg.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/idvApiPkg.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2api.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2log.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2cov.sv \ - $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2bin.sv \ - ../src/cvw.sv \ - ../testbench/testbench-imperas.sv \ - ../testbench/common/*.sv \ - ../src/*/*.sv \ - ../src/*/*/*.sv \ - -suppress 2583 \ - -suppress 7063 - -vopt +acc work.testbench -G DEBUG=1 -o workopt -eval vsim workopt +nowarn3829 -fatal 7 \ - -sv_lib $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model \ - +testDir=$env(TESTDIR) $env(OTHERFLAGS) -view wave -#-- display input and output signals as hexidecimal values -add log -recursive /* -do wave.do - -run -all - -noview ../testbench/testbench_imperas.sv -view wave - -#quit -f diff --git a/sim/questa/wally.do b/sim/questa/wally.do index e5c85b92e..c7cba4925 100644 --- a/sim/questa/wally.do +++ b/sim/questa/wally.do @@ -122,13 +122,14 @@ if {$FunctCoverageIndex >= 0} { set FCdefineINCLUDE_TRACE2COV "+define+INCLUDE_TRACE2COV" set FCdefineCOVER_BASE_RV64I "+define+COVER_BASE_RV64I" set FCdefineCOVER_LEVEL_DV_PR_EXT "+define+COVER_LEVEL_DV_PR_EXT" + # Uncomment various cover statements below to control which extensions get functional coverage set FCdefineCOVER_RV64I "+define+COVER_RV64I" - set FCdefineCOVER_RV64M "+define+COVER_RV64M" - set FCdefineCOVER_RV64A "+define+COVER_RV64A" - set FCdefineCOVER_RV64F "+define+COVER_RV64F" - set FCdefineCOVER_RV64D "+define+COVER_RV64D" - set FCdefineCOVER_RV64ZICSR "+define+COVER_RV64ZICSR" - set FCdefineCOVER_RV64C "+define+COVER_RV64C" + #set FCdefineCOVER_RV64M "+define+COVER_RV64M" + #set FCdefineCOVER_RV64A "+define+COVER_RV64A" + #set FCdefineCOVER_RV64F "+define+COVER_RV64F" + #set FCdefineCOVER_RV64D "+define+COVER_RV64D" + #set FCdefineCOVER_RV64ZICSR "+define+COVER_RV64ZICSR" + #set FCdefineCOVER_RV64C "+define+COVER_RV64C" set FCdefineIDV_INCLUDE_TRACE2COV "+define+IDV_INCLUDE_TRACE2COV" set FCTRACE2COV "+TRACE2COV_ENABLE=1" set FCdefineIDV_TRACE2COV "+IDV_TRACE2COV=1" diff --git a/src/privileged/csrm.sv b/src/privileged/csrm.sv index a964de2ea..f86b3f6d6 100644 --- a/src/privileged/csrm.sv +++ b/src/privileged/csrm.sv @@ -57,6 +57,7 @@ module csrm import cvw::*; #(parameter cvw_t P) ( logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW; logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW; logic [P.XLEN-1:0] MENVCFGH_REGW; + logic [P.XLEN-1:0] TVECWriteValM; logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM; logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM; logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM; @@ -152,7 +153,8 @@ module csrm import cvw::*; #(parameter cvw_t P) ( assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID | CSRAdrM == MCONFIGPTR); // CSRs - flopenr #(P.XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW); + assign TVECWriteValM = CSRWriteValM[0] ? {CSRWriteValM[P.XLEN-1:6], 6'b000001} : {CSRWriteValM[P.XLEN-1:2], 2'b00}; + flopenr #(P.XLEN) MTVECreg(clk, reset, WriteMTVECM, TVECWriteValM, MTVEC_REGW); if (P.S_SUPPORTED) begin:deleg // DELEG registers should exist flopenr #(16) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM[15:0] & MEDELEG_MASK, MEDELEG_REGW); flopenr #(12) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM[11:0] & MIDELEG_MASK, MIDELEG_REGW); diff --git a/src/privileged/csrs.sv b/src/privileged/csrs.sv index ebd468ad6..4797f800b 100644 --- a/src/privileged/csrs.sv +++ b/src/privileged/csrs.sv @@ -78,6 +78,7 @@ module csrs import cvw::*; #(parameter cvw_t P) ( logic [P.XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW; logic [P.XLEN-1:0] SENVCFG_WriteValM; + logic [P.XLEN-1:0] TVECWriteValM; logic [63:0] STIMECMP_REGW; @@ -100,7 +101,8 @@ module csrs import cvw::*; #(parameter cvw_t P) ( assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & STCE & (P.XLEN == 32); // CSRs - flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[P.XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); + assign TVECWriteValM = CSRWriteValM[0] ? {CSRWriteValM[P.XLEN-1:6], 6'b000001} : {CSRWriteValM[P.XLEN-1:2], 2'b00}; // could share this with MTVEC, but reduces to 4-bit AND to mask bits [5:2] + flopenr #(P.XLEN) STVECreg(clk, reset, WriteSTVECM, TVECWriteValM, STVEC_REGW); flopenr #(P.XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW); flopenr #(P.XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW); flopenr #(P.XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, {NextCauseM[4], {(P.XLEN-5){1'b0}}, NextCauseM[3:0]}, SCAUSE_REGW); diff --git a/tests/testgen/covergen.py b/tests/testgen/covergen.py index 1e06e7b9c..06cf1bb83 100755 --- a/tests/testgen/covergen.py +++ b/tests/testgen/covergen.py @@ -31,54 +31,73 @@ def signedImm12(imm): imm = imm - 0x1000 return str(imm) -def signedImm20(imm): +def unsignedImm20(imm): imm = imm % pow(2, 20) - if (imm & 0x80000): - imm = imm - 0x100000 return str(imm) -def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen): +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\n" + 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 to a random value \n" - lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2 to a random value\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(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 to a random value \n" + lines = lines + "li x" + str(rs1) + ", " + formatstr.format(rs1val) + " # initialize rs1\n" 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 to a random value \n" + 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"] - lines = lines + "auipc x" + str(rs1) + ", 0x20" + " # add upper immediate value to pc \n" - lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(immval) + " # add immediate to lower part of rs1 \n" - lines = lines + test + " x" + str(rd) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation \n" - elif (test in stypes):#["sb", "sh", "sw", "sd"] + pass + #lines = lines + "auipc x" + str(rs1) + ", 0x20" + " # add upper immediate value to pc \n" + #lines = lines + "addi x" + str(rs1) + ", x" + str(rs1) + ", " + signedImm12(-immval) + " # add immediate to lower part of rs1\n" + #lines = lines + test + " x" + str(rd) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation\n" + elif (test in stype):#["sb", "sh", "sw", "sd"] #lines = lines + test + " x" + str(rs2) + ", " + signedImm12(immval) + "(x" + str(rs1) + ") # perform operation \n" #lines = lines + test + " x" + str(rs2) + ", " "0(x" + str(rs1) + ") # perform operation \n" - print("Error: %s type not implemented yet" % test) - elif (test in btypes):#["beq", "bne", "blt", "bge", "bltu", "bgeu"] + #print("Error: %s type not implemented yet" % test) + pass + elif (test in btype):#["beq", "bne", "blt", "bge", "bltu", "bgeu"] if (randint(1,100) > 50): 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 to a random value that should get changed\n" - lines = lines + "li x" + str(rs2) + ", " + formatstr.format(rs2val) + " # initialize rs2 to a random value that should get changed\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_sb_types_" + str(immval) + "+4" + " # perform operation \n" lines = lines + "addi x0, x1, 1\n" lines = lines + "some_label_for_sb_types_" + str(immval) + ":\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) @@ -93,159 +112,191 @@ def randomize(): rdval = randint(0, 2**xlen-1) return [rs1, rs2, rd, rs1val, rs2val, immval, rdval] -def make_rd(test, storecmd, xlen): +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, storecmd, xlen) + writeCovVector(desc, rs1, rs2, r, rs1val, rs2val, immval, rdval, test, xlen) -def make_rs1(test, storecmd, 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, storecmd, xlen) + writeCovVector(desc, r, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen) -def make_rs2(test, storecmd, 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, storecmd, xlen) + writeCovVector(desc, rs1, r, rd, rs1val, rs2val, immval, rdval, test, xlen) -def make_rd_rs1(test, storecmd, 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, storecmd, xlen) + writeCovVector(desc, r, rs2, r, rs1val, rs2val, immval, rdval, test, xlen) -def make_rd_rs2(test, storecmd, 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, storecmd, xlen) + writeCovVector(desc, rs1, r, r, rs1val, rs2val, immval, rdval, test, xlen) -def make_rd_rs1_rs2(test, storecmd, 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, storecmd, xlen) + writeCovVector(desc, r, r, r, rs1val, rs2val, immval, rdval, test, xlen) -def make_rs1_rs2(test, storecmd, xlen): +def make_rs1_rs2(test, xlen): for r in range(32): [rs1, rs2, rd, rs1val, rs2val, immval, rdval] = randomize() desc = "cmp_rd_rs1_rs2 (Test rs1 = rs2 = x" + str(r) + ")" - writeCovVector(desc, r, r, rd, rs1val, rs2val, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, r, r, rd, rs1val, rs2val, immval, rdval, test, xlen) -def make_rs1_maxvals(test, storecmd, 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, storecmd, xlen) + writeCovVector(desc, rs1, rs2, rd, v, rs2val, immval, rdval, test, xlen) -def make_rs2_maxvals(test, storecmd, 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, storecmd, xlen) + writeCovVector(desc, rs1, rs2, rd, rs1val, v, immval, rdval, test, xlen) -def make_rd_maxvals(test, storecmd, 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, immval, rdval, test, storecmd, xlen) + writeCovVector(desc, rs1, 0, rd, v, rs2val, immval, 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, immval, 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, -1, v, immval, rdval, test, xlen) -def make_rd_rs1_eqval(test, storecmd, 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, storecmd, xlen) + writeCovVector(desc, rs1, 0, rd, rdval, rs2val, immval, rdval, test, xlen) -def make_rd_rs2_eqval(test, storecmd, 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, storecmd, xlen) + writeCovVector(desc, 0, rs2, rd, rs1val, rdval, immval, rdval, test, xlen) -def make_rs1_rs2_eqval(test, storecmd, 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, storecmd, xlen) + writeCovVector(desc, rs1, rs2, rd, rs1val, rs1val, immval, rdval, test, xlen) -#def make_cp_gpr_hazard(test, storecmd, xlen): -# pass # *** to be implemented *** +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, storecmd, xlen): +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, storecmd, xlen) + writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen) -def make_rs2_sign(test, storecmd, 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, storecmd, xlen) + writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen) -def make_cr_rs1_rs2_sign(test, storecmd, 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, storecmd, xlen) + writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, immval, rdval, test, xlen) -def write_tests(coverpoints, test, storecmd, 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 write_tests(coverpoints, test, xlen): for coverpoint in coverpoints: if (coverpoint == "cp_asm_count"): pass elif (coverpoint == "cp_rd"): - make_rd(test, storecmd, xlen) + make_rd(test, xlen) elif (coverpoint == "cp_rs1"): - make_rs1(test, storecmd, xlen) + make_rs1(test, xlen) elif (coverpoint == "cp_rs2"): - make_rs2(test, storecmd, xlen) + make_rs2(test, xlen) elif (coverpoint == "cmp_rd_rs1"): - make_rd_rs1(test, storecmd, xlen) + make_rd_rs1(test, xlen) elif (coverpoint == "cmp_rd_rs2"): - make_rd_rs2(test, storecmd, xlen) + make_rd_rs2(test, xlen) elif (coverpoint == "cmp_rd_rs1_rs2"): - make_rd_rs1_rs2(test, storecmd, xlen) + 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, storecmd, xlen) + make_rs1_rs2(test, xlen) elif (coverpoint == "cp_rs1_maxvals"): - make_rs1_maxvals(test, storecmd, xlen) + make_rs1_maxvals(test, xlen) elif (coverpoint == "cp_rs2_maxvals"): - make_rs2_maxvals(test, storecmd, xlen) + make_rs2_maxvals(test, xlen) elif (coverpoint == "cp_rd_maxvals"): - make_rd_maxvals(test, storecmd, xlen) + make_rd_maxvals(test, xlen) elif (coverpoint == "cmp_rd_rs1_eqval"): - make_rd_rs1_eqval(test, storecmd, xlen) + make_rd_rs1_eqval(test, xlen) elif (coverpoint == "cmp_rd_rs2_eqval"): - make_rd_rs2_eqval(test, storecmd, xlen) + make_rd_rs2_eqval(test, xlen) elif (coverpoint == "cmp_rs1_rs2_eqval"): - make_rs1_rs2_eqval(test, storecmd, xlen) + make_rs1_rs2_eqval(test, xlen) elif (coverpoint == "cp_rs1_sign"): - make_rs1_sign(test, storecmd, xlen) + make_rs1_sign(test, xlen) elif (coverpoint == "cp_rs2_sign"): - make_rs2_sign(test, storecmd, xlen) + 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, storecmd, xlen) + 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_gpr_hazard"): - pass #TODO not yet implemented elif (coverpoint == "cp_imm_sign"): - pass #TODO + make_imm_zero(test, xlen) elif (coverpoint == "cr_rs1_imm"): pass #TODO (not if crosses are not needed) elif (coverpoint == "cp_imm_ones_zeros"): @@ -253,7 +304,7 @@ def write_tests(coverpoints, test, storecmd, xlen): elif (coverpoint == "cp_mem_hazard"): pass #TODO elif (coverpoint == "cp_imm_zero"): - pass #TODO + make_imm_zero(test, xlen) elif (coverpoint == "cp_mem_unaligned"): pass #TODO elif (coverpoint == "cp_offset"): @@ -303,8 +354,11 @@ rtype = ["add", "sub", "sll", "slt", "sltu", "xor", "srl", "sra", "or", "and", loaditype = ["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"] shiftitype = ["slli", "srli", "srai"] itype = ["addi", "slti", "sltiu", "xori", "ori", "andi"] -stypes = ["sb", "sh", "sw", "sd"] -btypes = ["beq", "bne", "blt", "bge", "bltu", "bgeu"] +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) @@ -327,12 +381,11 @@ for xlen in xlens: 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(): -# pathname = "../wally-riscv-arch-test/riscv-test-suite/rv" + str(xlen) + "i_m/I/" - WALLY = os.environ.get('WALLY') - pathname = WALLY+"/tests/functcov/rv" + str(xlen) + "/I/" - cmd = "mkdir -p " + pathname - os.system(cmd) basename = "WALLY-COV-" + test fname = pathname + "/" + basename + ".S" @@ -340,9 +393,9 @@ for xlen in xlens: f = open(fname, "w") line = "///////////////////////////////////////////\n" f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) + line="// "+fname+ "\n// " + author + "\n" + f.write(line) + line ="// Created " + str(datetime.now()) + "\n" f.write(line) # insert generic header @@ -355,8 +408,8 @@ for xlen in xlens: #if (test not in rtests): # exit("Error: %s not implemented yet" % test) #else: - # write_rtype_arith_vectors(test, storecmd, xlen) - write_tests(coverpoints[test], test, storecmd, xlen) + # write_rtype_arith_vectors(test, xlen) + write_tests(coverpoints[test], test, xlen) # print footer line = "\n.EQU NUMTESTS," + str(1) + "\n\n" @@ -366,9 +419,6 @@ for xlen in xlens: f.write(line) # Finish -# lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" -# lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) f.close()