diff --git a/.gitignore b/.gitignore index 1aa2b562d..6aacdec2e 100644 --- a/.gitignore +++ b/.gitignore @@ -31,8 +31,7 @@ tests/fp/vectors/sed* tests/fp/combined_IF_vectors/IF_vectors/*.tv tests/custom/*/*/ tests/custom/*/*/*.memfile -tests/riscvdv -tests/functcov +sim/tests/riscvdv # Linux linux/buildroot @@ -110,9 +109,6 @@ sim/questa/fcovrvvi_logs sim/questa/fcovrvvi_ucdb sim/questa/fcov_logs sim/questa/fcov_ucdb -sim/questa/functcov_logs -sim/questa/functcov_ucdbs -sim/questa/functcov sim/questa/riscv.ucdb transcript vsim.wlf diff --git a/Makefile b/Makefile index b44d6221b..323b18b1d 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,8 @@ # Top-level Makefile for CORE-V-Wally # SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +MAKEFLAGS += --output-sync --no-print-directory + SIM = ${WALLY}/sim .PHONY: all riscof testfloat combined_IF_vectors zsbl benchmarks coremark embench coverage clean diff --git a/README.md b/README.md index 251cac42b..f5dfe0f47 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ Add the following lines to your `.bashrc` or `.bash_profile` to run the setup sc Build the tests and run a regression simulation to prove everything is installed. Building tests will take a while. - $ make + $ make --jobs $ regression-wally # Toolchain Installation and Configuration (Sys Admin) diff --git a/addins/riscv-arch-test b/addins/riscv-arch-test index 7152865ac..ce04b4930 160000 --- a/addins/riscv-arch-test +++ b/addins/riscv-arch-test @@ -1 +1 @@ -Subproject commit 7152865aca51062c87ff2cbb014e199a24bdc874 +Subproject commit ce04b4930545ae4c81e2f3b6f6935e2aac08679e diff --git a/benchmarks/coremark/Makefile b/benchmarks/coremark/Makefile index 63afc34bf..a999e70f3 100644 --- a/benchmarks/coremark/Makefile +++ b/benchmarks/coremark/Makefile @@ -37,14 +37,14 @@ $(work_dir)/coremark.bare.riscv.elf.memfile: $(work_dir)/coremark.bare.riscv extractFunctionRadix.sh $<.elf.objdump $(work_dir)/coremark.bare.riscv: $(sources) Makefile - make -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=$(RISCV) XCFLAGS="$(PORT_CFLAGS)" + $(MAKE) -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=$(RISCV) XCFLAGS="$(PORT_CFLAGS)" mkdir -p $(work_dir) mv $(cmbase)/coremark.bare.riscv $(work_dir) .PHONY: clean clean: - make -C $(cmbase) clean + $(MAKE) -C $(cmbase) clean rm -f $(work_dir)/* diff --git a/bin/regression-wally b/bin/regression-wally index c6c8ab523..1e8d49b50 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -547,7 +547,6 @@ def main(): if args.ccov: os.system('make QuestaCodeCoverage') if args.fcov: - #os.system('make QuestaFunctCoverage') os.system('make -f '+WALLY+'/addins/cvw-arch-verif/Makefile merge') if args.fcovrvvi: os.system('make QuestaFunctCoverageRvvi') diff --git a/fpga/zsbl/Makefile b/fpga/zsbl/Makefile index 9d962d430..8ba2b84d2 100644 --- a/fpga/zsbl/Makefile +++ b/fpga/zsbl/Makefile @@ -64,7 +64,7 @@ LIBS+=${LIBRARY_DIRS:%=-L%} ${LIBRARY_FILES:%=-l%} INC+=${LIBRARY_DIRS:%=-I%} ${LIBRARY_DIRS}: - make -C $@ -j 1 + $(MAKE) -C $@ -j 1 .PHONY: $(LIBRARY_DIRS) $(TARGET) endif diff --git a/sim/Makefile b/sim/Makefile index e88238fb2..5f225584e 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -3,12 +3,33 @@ # SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 SIM = ${WALLY}/sim +TESTS = ${WALLY}/tests -all: riscoftests memfiles coveragetests deriv +.PHONY: all riscoftests wallyriscoftests coveragetests deriv clean wally-riscv-arch-test benchmarks -wally-riscv-arch-test: wallyriscoftests memfiles +all: riscoftests coveragetests deriv -QuestaCodeCoverage: questa/ucdb/rv64gc_arch64i.ucdb +wally-riscv-arch-test: wallyriscoftests + +riscoftests: +# Builds riscv-arch-test 64 and 32-bit versions and builds wally-riscv-arch-test 64 and 32-bit versions + $(MAKE) -C ${TESTS}/riscof + +wallyriscoftests: +# Builds wally-riscv-arch-test 64 and 32-bit versions + $(MAKE) -C ${TESTS}/riscof wally-riscv-arch-test + +coveragetests: + $(MAKE) -C ${TESTS}/coverage + +deriv: + derivgen.pl + + + +.PHONY: QuestaCodeCoverage QuestaFunctCoverageRvvi collect_functcov combine_functcov remove_functcov_artifacts riscvdv riscvdv_functcov + +QuestaCodeCoverage: questa/ucdb/rv64gc_arch64i.ucdb vcover merge -out questa/ucdb/cov.ucdb questa/ucdb/rv64gc_arch64i.ucdb questa/ucdb/rv64gc*.ucdb -logfile questa/cov/log # vcover merge -out questa/ucdb/cov.ucdb questa/ucdb/rv64gc_arch64i.ucdb questa/ucdb/rv64gc*.ucdb questa/ucdb/buildroot_buildroot.ucdb riscv.ucdb -logfile questa/cov/log vcover report -details questa/ucdb/cov.ucdb > questa/cov/rv64gc_coverage_details.rpt @@ -30,14 +51,6 @@ 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_I_WALLY-COV-add.elf.ucdb - vcover merge -out ${SIM}/questa/fcov_ucdb/fcov.ucdb ${SIM}/questa/fcov_ucdb/rv64gc_I_WALLY-COV-add.elf.ucdb ${SIM}/questa/fcov_ucdb/rv64gc_I_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 - QuestaFunctCoverageRvvi: ${WALLY}/addins/cvw-arch-verif/work/rv64gc_arch64i.ucdb vcover merge -out ${SIM}/questa/fcovrvvi_ucdb/fcovrvvi.ucdb ${WALLY}/addins/cvw-arch-verif/work/rv64gc_arch64i.ucdb ${WALLY}/addins/cvw-arch-verif/work/rv64gc_*.ucdb -logfile ${SIM}/questa/fcovrvvi/log vcover report -details -html ${SIM}/questa/fcovrvvi_ucdb/fcovrvvi.ucdb @@ -46,59 +59,42 @@ QuestaFunctCoverageRvvi: ${WALLY}/addins/cvw-arch-verif/work/rv64gc_arch64i.ucdb vcover report ${SIM}/questa/fcovrvvi_ucdb/fcovrvvi.ucdb -details -cvg | egrep "Coverpoint|Covergroup|Cross|TYPE" > ${SIM}/questa/fcovrvvi/fcovrvvi.summary.log grep "TOTAL COVERGROUP COVERAGE" ${SIM}/questa/fcovrvvi/fcovrvvi.log -imperasdv_cov: - touch ${SIM}/seed0.txt - echo "0" > ${SIM}/seed0.txt -# ${RISCV}/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --verbose --seed 0 --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m -# ${RISCV}/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --elf ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/dut/my.elf --seed ${SIM}/seed0.txt --coverdb ${SIM}/cov/rv64gc_arch64i.ucdb --verbose -# ${RISCV}/ImperasDV-OpenHW/scripts/cvw/run-elf-cov.bash --elf ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/dut/my.elf --seed ${SIM}/seed0.txt --coverdb ${SIM}/questa/riscv.ucdb --verbose - run-elf-cov.bash --elf ${WALLY}/tests/riscvdv/asm_test/riscv_arithmetic_basic_test_0.elf --seed ${SIM}/questa/seed0.txt --coverdb ${SIM}/questa/riscv.ucdb --verbose - vcover report -details -html ${SIM}/questa/riscv.ucdb - -funcovreg: - #iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m --cover - #iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/I --cover - #iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege --cover - #iter-elf.bash --search ${WALLY}/tests/riscof/work/wally-riscv-arch-test/rv64i_m/Q --cover - rm -f ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/*/src/*/dut/my.elf - iter-elf.bash --search ${WALLY}/tests/riscof/work/riscv-arch-test/rv64i_m/I --cover - vcover report -details -html ${SIM}/questa/riscv.ucdb - - -riscvdv: - python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps gen,gcc_compile >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1 -# python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps gcc_compile >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1 -# python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps iss_sim >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1 -# run-elf.bash --seed ${SIM}/questa/seed0.txt --verbose --elf ${WALLY}/tests/riscvdv/asm_test/${test_name}_0.o >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1 +collect_functcov: remove_functcov_artifacts riscvdv_functcov combine_functcov riscvdv_functcov: mkdir -p ${SIM}/questa/fcov_logs mkdir -p ${SIM}/questa/fcov_ucdbs - cd ${SIM}/questa/fcov_logs && rm -rf * - cd ${SIM}/questa/fcov_ucdbs && rm -rf * - make riscvdv test_name=riscv_arithmetic_basic_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_amo_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_ebreak_debug_mode_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_ebreak_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_floating_point_arithmetic_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_floating_point_mmu_stress_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_floating_point_rand_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_full_interrupt_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_hint_instr_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_illegal_instr_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_invalid_csr_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_jump_stress_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_loop_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_machine_mode_rand_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_mmu_stress_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_no_fence_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_non_compressed_instr_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_pmp_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_privileged_mode_rand_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_rand_instr_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_rand_jump_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_sfence_exception_test >> ${SIM}/questa/fcov.log 2>&1 - make riscvdv test_name=riscv_unaligned_load_store_test >> ${SIM}/questa/fcov.log 2>&1 + rm -rf ${SIM}/questa/fcov_logs/* + rm -rf ${SIM}/questa/fcov_ucdbs/* + $(MAKE) riscvdv test_name=riscv_arithmetic_basic_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_amo_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_ebreak_debug_mode_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_ebreak_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_floating_point_arithmetic_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_floating_point_mmu_stress_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_floating_point_rand_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_full_interrupt_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_hint_instr_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_illegal_instr_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_invalid_csr_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_jump_stress_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_loop_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_machine_mode_rand_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_mmu_stress_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_no_fence_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_non_compressed_instr_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_pmp_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_privileged_mode_rand_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_rand_instr_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_rand_jump_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_sfence_exception_test >> ${SIM}/questa/fcov.log 2>&1 + $(MAKE) riscvdv test_name=riscv_unaligned_load_store_test >> ${SIM}/questa/fcov.log 2>&1 + +riscvdv: + python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps gen,gcc_compile >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1 +# python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps gcc_compile >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1 +# python3 ${WALLY}/addins/riscv-dv/run.py --test ${test_name} --target rv64gc --output tests/riscvdv --iterations 1 -si questa --iss spike --verbose --cov --seed 0 --steps iss_sim >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1 +# run-elf.bash --seed ${SIM}/questa/seed0.txt --verbose --elf ${WALLY}/tests/riscvdv/asm_test/${test_name}_0.o >> ${SIM}/questa/fcov_logs/${test_name}.log 2>&1 combine_functcov: mkdir -p ${SIM}/questa/fcov @@ -121,37 +117,14 @@ combine_functcov: grep "Total Coverage By Instance" ${SIM}/questa/fcov/fcov.log remove_functcov_artifacts: - rm ${SIM}/questa/riscv.ucdb ${SIM}/questa/fcov.log ${SIM}/questa/covhtmlreport/ ${SIM}/questa/fcov_logs/ ${SIM}/questa/fcov_ucdbs/ ${SIM}/questa/fcov/ -rf - -collect_functcov: remove_functcov_artifacts riscvdv_functcov combine_functcov - -allclean: clean all - -clean: - make clean -C ../tests/riscof -# make clean -C ../../tests/wally-riscv-arch-test -# make allclean -C ../../tests/imperas-riscv-tests - -riscoftests: -# Builds riscv-arch-test 64 and 32-bit versions and builds wally-riscv-arch-test 64 and 32-bit versions - make -C ../tests/riscof/ - -wallyriscoftests: -# Builds riscv-arch-test 64 and 32-bit versions and builds wally-riscv-arch-test 64 and 32-bit versions - make -C ../tests/riscof/ wally-riscv-arch-test - -memfiles: - make -f makefile-memfile wally-sim-files --jobs - -coveragetests: - make -C ../tests/coverage/ --jobs - -deriv: - derivgen.pl + rm -rf ${SIM}/questa/riscv.ucdb ${SIM}/questa/fcov.log ${SIM}/questa/covhtmlreport/ ${SIM}/questa/fcov_logs/ ${SIM}/questa/fcov_ucdbs/ ${SIM}/questa/fcov/ benchmarks: - $(MAKE) -C ../benchmarks/embench build - $(MAKE) -C ../benchmarks/embench size - $(MAKE) -C ../benchmarks/embench modelsim_build_memfile - $(MAKE) -C ../benchmarks/coremark + $(MAKE) -C ${WALLY}benchmarks/embench build + $(MAKE) -C ${WALLY}/benchmarks/embench size + $(MAKE) -C ${WALLY}/benchmarks/embench modelsim_build_memfile + $(MAKE) -C ${WALLY}/benchmarks/coremark +clean: + $(MAKE) clean -C ${TESTS}/riscof +# $(MAKE) clean -C ${TESTS}/wally-riscv-arch-test diff --git a/sim/makefile-memfile b/sim/makefile-memfile deleted file mode 100644 index 6c2da42fa..000000000 --- a/sim/makefile-memfile +++ /dev/null @@ -1,41 +0,0 @@ -ROOT := .. -SUFFIX := work -ARCHDIR := $(ROOT)/tests/riscof -WALLYDIR:= $(ROOT)/tests/wally-riscv-arch-test -# IMPERASDIR := $(ROOT)/tests/imperas-riscv-tests -# ALLDIRS := $(ARCHDIR)/$(SUFFIX) $(WALLYDIR)/$(SUFFIX) $(IMPERASDIR)/$(SUFFIX) -IMPERASDIR := $(ROOT)/tests/imperas-riscv-tests -#ALLDIRS := $(ARCHDIR)/$(SUFFIX) $(WALLYDIR)/$(SUFFIX) -ALLDIRS := $(ARCHDIR)/$(SUFFIX) - -ELFFILES ?= $(shell find $(ALLDIRS) -type f -regex ".*\.elf") -OBJDUMPFILES ?= $(shell find $(ALLDIRS) -type f -regex ".*\.elf.objdump") -MEMFILES ?= $(ELFFILES:.elf=.elf.memfile) -ADDRFILES ?= $(OBJDUMPFILES:.objdump=.objdump.addr) - -print: - echo "files in $(ALLDIRS) are $(ELFFILES)." - echo "memfiles are $(MEMFILES)" - -.PHONY: all wally-sim-files -all: wally-sim-files - -wally-sim-files: $(MEMFILES) $(ADDRFILES) - echo "$@" - -# notes to self on how this works. -# The find command locates all of the *.elf files in directory DIR1. A list of .memfiles and -# .addr files are generated from the .elf. These are used as targets. -# % is a wildcard in a make target which is then referenced as % in the depenecies and $* -# in the recipe. -# because elf2hex requires a bit width we use findstring to figure out if the compiled directory -# is XLEN=64 or 32. This is hacky and will likely break in the future. -# the .addr is a separate target so make can split into more jobs and more parallism. -%.elf.memfile: %.elf - riscv64-unknown-elf-elf2hex --bit-width $(if $(findstring rv64,$*),64,32) --input $< --output $@ - -%.elf.objdump.addr: %.elf.objdump - extractFunctionRadix.sh $< - -.PHONY: clean -clean: diff --git a/testbench/testbench.sv b/testbench/testbench.sv index f91bdcc67..46c08fc86 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -2,26 +2,26 @@ // testbench.sv // // Written: David_Harris@hmc.edu 9 January 2021 -// Modified: +// Modified: // // Purpose: Wally Testbench and helper modules -// Applies test programs from the riscv-arch-test and Imperas suites -// +// Applies test programs from the riscv-arch-test and other custom tests +// // 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 +// 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 +// 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. //////////////////////////////////////////////////////////////////////////////////////////////// @@ -50,7 +50,7 @@ module testbench; parameter I_CACHE_ADDR_LOGGER=0; parameter D_CACHE_ADDR_LOGGER=0; parameter RVVI_SYNTH_SUPPORTED=0; - + `ifdef USE_IMPERAS_DV import idvPkg::*; import rvviApiPkg::*; @@ -64,7 +64,7 @@ module testbench; `elsif VCS import "DPI-C" function string getenv(input string env_name); string RISCV_DIR = getenv("RISCV"); - string WALLY_DIR = getenv("WALLY"); + string WALLY_DIR = getenv("WALLY"); `else string RISCV_DIR = "$RISCV"; string WALLY_DIR = "$WALLY"; @@ -82,7 +82,7 @@ module testbench; // DUT signals logic [P.AHBW-1:0] HRDATAEXT; - logic HREADYEXT, HRESPEXT; + logic HREADYEXT, HRESPEXT; logic [P.PA_BITS-1:0] HADDR; logic [P.AHBW-1:0] HWDATA; logic [P.XLEN/8-1:0] HWSTRB; @@ -102,12 +102,12 @@ module testbench; logic SDCCmd; logic SDCIn; logic [3:0] SDCCS; - logic SDCCLK; + logic SDCCLK; logic HREADY; logic HSELEXT; - + string ProgramAddrMapFile, ProgramLabelMapFile; integer ProgramAddrLabelArray [string]; @@ -118,7 +118,7 @@ module testbench; string tests[]; logic DCacheFlushDone, DCacheFlushStart; - logic riscofTest; + logic riscofTest; logic Validate; logic SelectTest; logic TestComplete; @@ -134,36 +134,29 @@ module testbench; if (!$value$plusargs("INSTR_LIMIT=%d", INSTR_LIMIT)) INSTR_LIMIT = 0; //$display("TEST = %s ElfFile = %s", TEST, ElfFile); - + // pick tests based on modes supported //tests = '{}; if (P.XLEN == 64) begin // RV64 case (TEST) "arch64i": tests = arch64i; "arch64priv": tests = arch64priv; - "arch64c": if (P.C_SUPPORTED) + "arch64c": if (P.ZCA_SUPPORTED) if (P.ZICSR_SUPPORTED) tests = {arch64c, arch64cpriv}; else tests = {arch64c}; "arch64m": if (P.M_SUPPORTED) tests = arch64m; "arch64a_amo": if (P.ZAAMO_SUPPORTED) tests = arch64a_amo; "arch64f": if (P.F_SUPPORTED) tests = arch64f; - "arch64d": if (P.D_SUPPORTED) tests = arch64d; + "arch64d": if (P.D_SUPPORTED) tests = arch64d; "arch64f_fma": if (P.F_SUPPORTED) tests = arch64f_fma; - "arch64d_fma": if (P.D_SUPPORTED) tests = arch64d_fma; + "arch64d_fma": if (P.D_SUPPORTED) tests = arch64d_fma; "arch64f_divsqrt": if (P.F_SUPPORTED) tests = arch64f_divsqrt; - "arch64d_divsqrt": if (P.D_SUPPORTED) tests = arch64d_divsqrt; + "arch64d_divsqrt": if (P.D_SUPPORTED) tests = arch64d_divsqrt; "arch64zifencei": if (P.ZIFENCEI_SUPPORTED) tests = arch64zifencei; "arch64zicond": if (P.ZICOND_SUPPORTED) tests = arch64zicond; - "imperas64i": tests = imperas64i; - "imperas64f": if (P.F_SUPPORTED) tests = imperas64f; - "imperas64d": if (P.D_SUPPORTED) tests = imperas64d; - "imperas64m": if (P.M_SUPPORTED) tests = imperas64m; "wally64q": if (P.Q_SUPPORTED) tests = wally64q; "wally64a_lrsc": if (P.ZALRSC_SUPPORTED) tests = wally64a_lrsc; - "imperas64c": if (P.C_SUPPORTED) tests = imperas64c; - else tests = imperas64iNOc; "custom": tests = custom; - "wally64i": tests = wally64i; "wally64priv": tests = wally64priv; "wally64periph": tests = wally64periph; "coremark": tests = coremark; @@ -177,7 +170,7 @@ module testbench; "arch64zicboz": if (P.ZICBOZ_SUPPORTED) tests = arch64zicboz; "arch64zcb": if (P.ZCB_SUPPORTED) tests = arch64zcb; "arch64zfh": if (P.ZFH_SUPPORTED) tests = arch64zfh; - "arch64zfh_fma": if (P.ZFH_SUPPORTED) tests = arch64zfh_fma; + "arch64zfh_fma": if (P.ZFH_SUPPORTED) tests = arch64zfh_fma; "arch64zfh_divsqrt": if (P.ZFH_SUPPORTED) tests = arch64zfh_divsqrt; "arch64zfaf": if (P.ZFA_SUPPORTED) tests = arch64zfaf; "arch64zfad": if (P.ZFA_SUPPORTED & P.D_SUPPORTED) tests = arch64zfad; @@ -188,32 +181,26 @@ module testbench; "arch64zknd": if (P.ZKND_SUPPORTED) tests = arch64zknd; "arch64zkne": if (P.ZKNE_SUPPORTED) tests = arch64zkne; "arch64zknh": if (P.ZKNH_SUPPORTED) tests = arch64zknh; - endcase + endcase end else begin // RV32 case (TEST) - "arch32e": tests = arch32e; + "arch32e": tests = arch32e; "arch32i": tests = arch32i; "arch32priv": tests = arch32priv; - "arch32c": if (P.C_SUPPORTED) + "arch32c": if (P.C_SUPPORTED) if (P.ZICSR_SUPPORTED) tests = {arch32c, arch32cpriv}; else tests = {arch32c}; "arch32m": if (P.M_SUPPORTED) tests = arch32m; - "arch32a_amo": if (P.ZAAMO_SUPPORTED) tests = arch32a_amo; + "arch32a_amo": if (P.ZAAMO_SUPPORTED) tests = arch32a_amo; "arch32f": if (P.F_SUPPORTED) tests = arch32f; "arch32d": if (P.D_SUPPORTED) tests = arch32d; "arch32f_fma": if (P.F_SUPPORTED) tests = arch32f_fma; "arch32d_fma": if (P.D_SUPPORTED) tests = arch32d_fma; "arch32f_divsqrt": if (P.F_SUPPORTED) tests = arch32f_divsqrt; - "arch32d_divsqrt": if (P.D_SUPPORTED) tests = arch32d_divsqrt; + "arch32d_divsqrt": if (P.D_SUPPORTED) tests = arch32d_divsqrt; "arch32zifencei": if (P.ZIFENCEI_SUPPORTED) tests = arch32zifencei; "arch32zicond": if (P.ZICOND_SUPPORTED) tests = arch32zicond; - "imperas32i": tests = imperas32i; - "imperas32f": if (P.F_SUPPORTED) tests = imperas32f; - "imperas32m": if (P.M_SUPPORTED) tests = imperas32m; - "wally32a_lrsc": if (P.ZALRSC_SUPPORTED) tests = wally32a_lrsc; - "imperas32c": if (P.C_SUPPORTED) tests = imperas32c; - else tests = imperas32iNOc; - "wally32i": tests = wally32i; + "wally32a_lrsc": if (P.ZALRSC_SUPPORTED) tests = wally32a_lrsc; "wally32priv": tests = wally32priv; "wally32periph": tests = wally32periph; "ahb32" : tests = ahb32; @@ -226,7 +213,7 @@ module testbench; "arch32zicboz": if (P.ZICBOZ_SUPPORTED) tests = arch32zicboz; "arch32zcb": if (P.ZCB_SUPPORTED) tests = arch32zcb; "arch32zfh": if (P.ZFH_SUPPORTED) tests = arch32zfh; - "arch32zfh_fma": if (P.ZFH_SUPPORTED) tests = arch32zfh_fma; + "arch32zfh_fma": if (P.ZFH_SUPPORTED) tests = arch32zfh_fma; "arch32zfh_divsqrt": if (P.ZFH_SUPPORTED) tests = arch32zfh_divsqrt; "arch32zfaf": if (P.ZFA_SUPPORTED) tests = arch32zfaf; "arch32zfad": if (P.ZFA_SUPPORTED & P.D_SUPPORTED) tests = arch32zfad; @@ -292,13 +279,13 @@ module testbench; always_ff @(posedge clk) if (TestBenchReset) CurrState <= STATE_TESTBENCH_RESET; - else CurrState <= NextState; + else CurrState <= NextState; // fsm next state logic always_comb begin - // riscof tests have a different signature, tests[0] == "1" refers to RiscvArchTests - // and tests[0] == "2" refers to WallyRiscvArchTests - riscofTest = tests[0] == "1" | tests[0] == "2"; + // riscof tests have a different signature, tests[0] == "0" refers to RiscvArchTests + // and tests[0] == "1" refers to WallyRiscvArchTests + riscofTest = tests[0] == "0" | tests[0] == "1"; pathname = tvpaths[tests[0].atoi()]; case(CurrState) @@ -321,11 +308,11 @@ module testbench; default: NextState = STATE_TESTBENCH_RESET; endcase end // always_comb - // fsm output control logic - assign reset_ext = CurrState == STATE_TESTBENCH_RESET | CurrState == STATE_INIT_TEST | - CurrState == STATE_RESET_MEMORIES | CurrState == STATE_RESET_MEMORIES2 | + // fsm output control logic + assign reset_ext = CurrState == STATE_TESTBENCH_RESET | CurrState == STATE_INIT_TEST | + CurrState == STATE_RESET_MEMORIES | CurrState == STATE_RESET_MEMORIES2 | CurrState == STATE_LOAD_MEMORIES | CurrState ==STATE_RESET_TEST; - // this initialization is very expensive, only do it for coremark. + // this initialization is very expensive, only do it for coremark. assign ResetMem = (CurrState == STATE_RESET_MEMORIES | CurrState == STATE_RESET_MEMORIES2) & TEST == "coremark"; assign LoadMem = CurrState == STATE_LOAD_MEMORIES; assign ResetCntRst = CurrState == STATE_INIT_TEST; @@ -356,7 +343,7 @@ module testbench; assign EcallFaultM = dut.core.priv.priv.EcallFaultM; else assign EcallFaultM = 0; - + always @(posedge clk) begin //////////////////////////////////////////////////////////////////////////////// // Verify the test ran correctly by checking the memory against a known signature. @@ -368,12 +355,12 @@ module testbench; $stop; end if(SelectTest) begin - if (riscofTest) begin + if (riscofTest) begin memfilename = {pathname, tests[test], "/ref/ref.elf.memfile"}; elffilename = {pathname, tests[test], "ref/ref.elf"}; ProgramAddrMapFile = {pathname, tests[test], "/ref/ref.elf.objdump.addr"}; ProgramLabelMapFile = {pathname, tests[test], "/ref/ref.elf.objdump.lab"}; - end else if(TEST == "buildroot") begin + end else if(TEST == "buildroot") begin memfilename = {RISCV_DIR, "/linux-testvectors/ram.bin"}; elffilename = "buildroot"; bootmemfilename = {RISCV_DIR, "/linux-testvectors/bootmem.bin"}; @@ -397,8 +384,8 @@ module testbench; ProgramAddrMapFile = {pathname, tests[test], ".elf.objdump.addr"}; ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"}; end - // 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 + // 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, memfilename, WALLY_DIR, ProgramAddrLabelArray); end @@ -408,9 +395,9 @@ module testbench; $fclose(uartoutfile); if (TEST == "embench") begin // Writes contents of begin_signature to .sim.output file - // this contains instret and cycles for start and end of test run, used by embench - // python speed script to calculate embench speed score. - // also, begin_signature contains the results of the self checking mechanism, + // this contains instret and cycles for start and end of test run, used by embench + // python speed script to calculate embench speed score. + // also, begin_signature contains the results of the self checking mechanism, // which will be read by the python script for error checking $display("Embench Benchmark: %s is done.", tests[test]); if (riscofTest) outputfile = {pathname, tests[test], "/ref/ref.sim.output"}; @@ -433,17 +420,17 @@ module testbench; `else $finish; `endif - end else begin + end else begin // for tests with no self checking mechanism, read .signature.output file and compare to check for errors // clear signature to prevent contamination from previous tests if (!begin_signature_addr) $display("begin_signature addr not found in %s", ProgramLabelMapFile); - else if (TEST != "embench") begin + else if (TEST != "embench") begin CheckSignature(pathname, tests[test], riscofTest, begin_signature_addr, errors); if(errors > 0) totalerrors = totalerrors + 1; end end - test = test + 1; + test = test + 1; if (test == tests.size()) begin if (totalerrors == 0) $display("SUCCESS! All tests ran without failures."); else $display("FAIL: %d test programs had errors", totalerrors); @@ -473,7 +460,7 @@ module testbench; if (LoadMem) begin string romfilename, sdcfilename; romfilename = {"../tests/custom/fpga-test-sdc/bin/fpga-test-sdc.memfile"}; - sdcfilename = {"../testbench/sdc/ramdisk2.hex"}; + sdcfilename = {"../testbench/sdc/ramdisk2.hex"}; //$readmemh(romfilename, dut.uncoregen.uncore.bootrom.bootrom.memory.ROM); //$readmemh(sdcfilename, sdcard.sdcard.FLASHmem); // shorten sdc timers for simulation @@ -548,7 +535,7 @@ module testbench; end end end - end + end if (P.DTIM_SUPPORTED) begin always @(posedge clk) begin if (LoadMem) begin @@ -569,9 +556,9 @@ module testbench; integer adrindex; if (P.UNCORE_RAM_SUPPORTED) - always @(posedge clk) + always @(posedge clk) if (ResetMem) // program memory is sometimes reset (e.g. for CoreMark, which needs zeroed memory) - for (adrindex=0; adrindex<(P.UNCORE_RAM_RANGE>>1+(P.XLEN/32)); adrindex = adrindex+1) + for (adrindex=0; adrindex<(P.UNCORE_RAM_RANGE>>1+(P.XLEN/32)); adrindex = adrindex+1) dut.uncoregen.uncore.ram.ram.memory.ram.RAM[adrindex] = '0; //////////////////////////////////////////////////////////////////////////////// @@ -584,10 +571,10 @@ module testbench; assign SPIIn = 1'b0; if(P.EXT_MEM_SUPPORTED) begin - ram_ahb #(.P(P), .BASE(P.EXT_MEM_BASE), .RANGE(P.EXT_MEM_RANGE)) - ram (.HCLK, .HRESETn, .HADDR, .HWRITE, .HTRANS, .HWDATA, .HSELRam(HSELEXT), + ram_ahb #(.P(P), .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 + end else begin assign HREADYEXT = 1'b1; assign {HRESPEXT, HRDATAEXT} = '0; end @@ -597,7 +584,7 @@ module testbench; /* -----\/----- EXCLUDED -----\/----- sdModel sdcard (.sdClk(SDCCLK), - .cmd(SDCCmd), + .cmd(SDCCmd), .dat(SDCDat)); assign SDCCmd = SDCCmdOE ? SDCCmdOut : 1'bz; @@ -607,14 +594,14 @@ module testbench; -----/\----- EXCLUDED -----/\----- */ end else begin assign SDCIn = 1'b1; - + end - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .ExternalStall(RVVIStall), + wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .ExternalStall(RVVIStall), .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); + .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SPICLK, .SDCIn, .SDCCmd, .SDCCS, .SDCCLK); // generate clock to sequence tests always begin @@ -629,17 +616,17 @@ module testbench; logic [3:0] mii_txd; logic mii_tx_en, mii_tx_er; - rvvitbwrapper #(P, MAX_CSRS, RVVI_INIT_TIME_OUT, RVVI_PACKET_DELAY) + rvvitbwrapper #(P, MAX_CSRS, RVVI_INIT_TIME_OUT, RVVI_PACKET_DELAY) rvvitbwrapper(.clk, .reset, .RVVIStall, .mii_tx_clk(clk), .mii_txd, .mii_tx_en, .mii_tx_er, .mii_rx_clk(clk), .mii_rxd('0), .mii_rx_dv('0), .mii_rx_er('0)); end else begin assign RVVIStall = '0; end - + /* // Print key info each cycle for debugging - always @(posedge clk) begin + always @(posedge clk) begin #2; $display("PCM: %x InstrM: %x (%5s) WriteDataM: %x IEUResultM: %x", dut.core.PCM, dut.core.InstrM, InstrMName, dut.core.WriteDataM, dut.core.ieu.dp.IEUResultM); @@ -667,7 +654,7 @@ module testbench; // watch for problems such as lockup, reading unitialized memory, bad configs 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); riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration loggers #(P, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER) @@ -692,7 +679,7 @@ module testbench; end // Termination condition - // Terminate on + // Terminate on // 1. jump to self loop (0x0000006f) // 2. a store word writes to the address "tohost" // 3. or PC is stuck at 0 @@ -706,13 +693,13 @@ module testbench; // (FunctionName.PCM == 0 & dut.core.ifu.InstrM == 0 & dut.core.InstrValidM & PrevPCZero)); // if (FunctionName.PCM == 0 & dut.core.ifu.InstrM == 0 & dut.core.InstrValidM & PrevPCZero) // $error("Program fetched illegal instruction 0x00000000 from address 0x00000000 twice in a row. Usually due to fault with no fault handler."); - end + end DCacheFlushFSM #(P) DCacheFlushFSM(.clk, .start(DCacheFlushStart), .done(DCacheFlushDone)); if(P.ZICSR_SUPPORTED) begin logic [P.XLEN-1:0] Minstret; - assign Minstret = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + assign Minstret = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; always @(negedge clk) begin if (INSTR_LIMIT > 0) begin if((Minstret != 0) & (Minstret % 'd100000 == 0)) $display("Reached %d instructions", Minstret); @@ -758,14 +745,14 @@ end $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, "RV64GCK")); void'(rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, XLEN==64 ? 56 : 34)); void'(rvviRefConfigSetInt(IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS, 6)); - if(elffilename == "buildroot") filename = ""; + if(elffilename == "buildroot") filename = ""; else filename = elffilename; // use the ImperasDV rvviRefInit to load the reference model with an elf file @@ -778,8 +765,8 @@ end if (!rvviRefInit("")) begin // still have to call with nothing $display($sformatf("%m @ t=%0t: rvviRefInit failed", $time)); $fatal; - end - + end + memfilenameImperasDV = {RISCV_DIR, "/linux-testvectors/ram.bin"}; bootmemfilenameImperasDV = {RISCV_DIR, "/linux-testvectors/bootmem.bin"}; @@ -797,7 +784,7 @@ end //$display("boot %08X x32[0]=%08X x32[1]=%08X", index, x32[0], x32[1]); end $fclose(memFile); - + $display("RVVI Loading ram.bin"); memFile = $fopen(memfilenameImperasDV, "rb"); index = 'h80000000 - 8; @@ -812,9 +799,9 @@ end //$display("ram %08X x32[0]=%08X x32[1]=%08X", index, x32[0], x32[1]); end $fclose(memFile); - + $display("RVVI Loading Complete"); - + void'(rvviRefPcSet(0, P.RESET_VECTOR)); // set BOOTROM address end @@ -829,22 +816,22 @@ end void'(rvviRefCsrSetVolatile(0, 32'hB80)); // MCYCLEH void'(rvviRefCsrSetVolatile(0, 32'hC82)); // INSTRETH void'(rvviRefCsrSetVolatile(0, 32'hB82)); // MINSTRETH - void'(rvviRefCsrSetVolatile(0, 32'hC81)); // TIMEH + void'(rvviRefCsrSetVolatile(0, 32'hC81)); // TIMEH end // User HPMCOUNTER3 - HPMCOUNTER31 for (iter='hC03; iter<='hC1F; iter++) begin void'(rvviRefCsrSetVolatile(0, iter)); // HPMCOUNTERx - if (P.XLEN == 32) + if (P.XLEN == 32) void'(rvviRefCsrSetVolatile(0, iter+128)); // HPMCOUNTERxH - end - + end + // Machine MHPMCOUNTER3 - MHPMCOUNTER31 for (iter='hB03; iter<='hB1F; iter++) begin void'(rvviRefCsrSetVolatile(0, iter)); // MHPMCOUNTERx - if (P.XLEN == 32) + if (P.XLEN == 32) void'(rvviRefCsrSetVolatile(0, iter+128)); // MHPMCOUNTERxH - end - + end + // cannot predict this register due to latency between // pending and taken void'(rvviRefCsrSetVolatile(0, 32'h344)); // MIP @@ -880,7 +867,7 @@ end 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])); @@ -902,7 +889,7 @@ end task automatic CheckSignature; // This task must be declared inside this module as it needs access to parameter P. There is // no way to pass P to the task unless we convert it to a module. - + input string pathname; input string TestName; input logic riscofTest; @@ -920,8 +907,8 @@ end string signame; logic [P.XLEN-1:0] testadr, testadrNoBase; - //$display("Invoking CheckSignature %s %s %0t", pathname, TestName, $time); - + //$display("Invoking CheckSignature %s %s %0t", pathname, TestName, $time); + // read .signature.output file and compare to check for errors if (riscofTest) signame = {pathname, TestName, "/ref/Reference-sail_c_simulator.signature"}; else signame = {pathname, TestName, ".signature.output"}; @@ -951,8 +938,8 @@ end end // Check valid number of lines were read - if (siglines == 0) begin - errors = 1; + if (siglines == 0) begin + errors = 1; $display("Error: empty test file %s", signame); end else if (P.XLEN == 64 & (siglines % 2)) begin errors = 1; @@ -970,9 +957,9 @@ end testadr = ($unsigned(begin_signature_addr))/(P.XLEN/8); testadrNoBase = (begin_signature_addr - P.UNCORE_RAM_BASE)/(P.XLEN/8); for (i=0; i config32.ini - sed 's,{0},$(current_dir),g;s,{1},64gc,g;s,{2},$(nproc),g' config.ini > config64.ini - sed 's,{0},$(current_dir),g;s,{1},32e,g;s,{2},$(nproc),g' config.ini > config32e.ini +# Generate config.ini files +config%.ini: config.ini + sed 's,{0},$(current_dir),g;s,{1},$(patsubst %64,%64gc,$(patsubst %32,%32gc,$*)),g;s,{2},$(nproc),g' config.ini > $@ -arch32e: - riscof run --work-dir=$(work_dir) --config=config32e.ini --suite=$(arch_dir)/riscv-test-suite/ --env=$(arch_dir)/riscv-test-suite/env --no-browser - rsync -a $(work_dir)/rv32e_m/ $(arch_workdir)/rv32e_m/ || echo "error suppressed" +# Generate riscv-arch-test targets +arch%: config$$*.ini | $(work_dir) $(arch_workdir) + riscof run --work-dir=$(work_dir)/$@ --config=$< --suite=$(arch_dir)/riscv-test-suite/ --env=$(arch_dir)/riscv-test-suite/env --no-browser + $(MAKE) -f makefile-memfile WORKDIR=$(work_dir)/$@ BITWIDTH=$(patsubst %32e,%32,$*) + rsync -a $(work_dir)/$@/rv*/* $(arch_workdir)/rv$(patsubst %64,%64i,$(patsubst %32,%32i,$*))_m || echo "error suppressed" -arch32: - riscof run --work-dir=$(work_dir) --config=config32.ini --suite=$(arch_dir)/riscv-test-suite/ --env=$(arch_dir)/riscv-test-suite/env --no-browser - rsync -a $(work_dir)/rv32i_m/ $(arch_workdir)/rv32i_m/ || echo "error suppressed" +# Generate wally-riscv-arch-test targets +wally%: config$$*.ini | $(work_dir) $(wally_workdir) + riscof run --work-dir=$(work_dir)/$@ --config=$< --suite=$(wally_dir)/riscv-test-suite/ --env=$(wally_dir)/riscv-test-suite/env --no-browser --no-dut-run + $(MAKE) -f makefile-memfile WORKDIR=$(work_dir)/$@ + rsync -a $(work_dir)/$@/rv*/* $(wally_workdir)/rv$(patsubst %64,%64i,$(patsubst %32,%32i,$*))_m || echo "error suppressed" - -arch64: - riscof run --work-dir=$(work_dir) --config=config64.ini --suite=$(arch_dir)/riscv-test-suite/ --env=$(arch_dir)/riscv-test-suite/env --no-browser - rsync -a $(work_dir)/rv64i_m/ $(arch_workdir)/rv64i_m/ || echo "error suppressed" -# Also copy F and D tests to RV64 - rsync -a $(work_dir)/rv32i_m/ $(arch_workdir)/rv64i_m/ || echo "error suppressed" - -wally32: - riscof run --work-dir=$(work_dir) --config=config32.ini --suite=$(wally_dir)/riscv-test-suite/ --env=$(wally_dir)/riscv-test-suite/env --no-browser --no-dut-run - rsync -a $(work_dir)/rv32i_m/ $(wally_workdir)/rv32i_m/ || echo "error suppressed" - -wally64: - riscof run --work-dir=$(work_dir) --config=config64.ini --suite=$(wally_dir)/riscv-test-suite/ --env=$(wally_dir)/riscv-test-suite/env --no-browser --no-dut-run - rsync -a $(work_dir)/rv64i_m/ $(wally_workdir)/rv64i_m/ || echo "error suppressed" -# Also copy F and D tests to RV64 - rsync -a $(work_dir)/rv32i_m/ $(wally_workdir)/rv64i_m/ || echo "error suppressed" - -quad64: - riscof run --work-dir=$(work_dir) --config=config64.ini --suite=$(wally_dir)/riscv-test-suite/rv64i_m/Q/riscv-ctg/tests/ --env=$(wally_dir)/riscv-test-suite/env - -#wally32e: -# riscof run --work-dir=$(work_dir) --config=config32e.ini --suite=$(wally_dir)/riscv-test-suite/ --env=$(wally_dir)/riscv-test-suite/env --no-browser --no-dut-run -# rsync -a $(work_dir)/rv32i_m/ $(wally_workdir)/rv32i_m/ || echo "error suppressed" -# rsync -a $(work_dir)/rv32e_unratified/ $(wally_workdir)/rv32e_unratified/ || echo "error suppressed" - - -memfile: - find $(work) -type f -name "*.elf" | grep "rv64i_m" | while read f; do riscv64-unknown-elf-elf2hex --bit-width 64 --input "$$f" --output "$$f.memfile"; done - find $(work) -type f -name "*.elf" | grep "rv32i_m" | while read f; do riscv64-unknown-elf-elf2hex --bit-width 32 --input "$$f" --output "$$f.memfile"; done - find $(work) -type f -name "*.elf.objdump" | while read f; do extractFunctionRadix.sh $$f; done +quad64: config64.ini $(wally_dir)/riscv-test-suite/rv64i_m/Q/riscv-ctg/tests | $(work_dir) + riscof run --work-dir=$(work_dir)/$@ --config=$< --suite=$(wally_dir)/riscv-test-suite/rv64i_m/Q/riscv-ctg/tests/ --env=$(wally_dir)/riscv-test-suite/env + $(MAKE) -f makefile-memfile WORKDIR=$(work_dir)/$@ clean: - rm -f config64.ini - rm -f config32.ini - rm -f config32e.ini + rm -f config??*.ini rm -rf $(work_dir) rm -rf $(wally_workdir) rm -rf $(arch_workdir) rm -rf $(submodule_wor_dir) + +$(work_dir) $(arch_workdir) $(wally_workdir): + mkdir -p $@ diff --git a/tests/riscof/makefile-memfile b/tests/riscof/makefile-memfile new file mode 100644 index 000000000..6ccdca37c --- /dev/null +++ b/tests/riscof/makefile-memfile @@ -0,0 +1,24 @@ +WORKDIR ?= $(WALLY)/tests/riscof/work/ + +ELFFILES ?= $(shell find $(WORKDIR) -type f -regex ".*\.elf") +OBJDUMPFILES ?= $(shell find $(WORKDIR) -type f -regex ".*\.elf.objdump") +MEMFILES ?= $(ELFFILES:.elf=.elf.memfile) +ADDRFILES ?= $(OBJDUMPFILES:.objdump=.objdump.addr) + +.PHONY: wally-sim-files +wally-sim-files: $(MEMFILES) $(ADDRFILES) + +# notes to self on how this works. +# The find command locates all of the *.elf files in directory DIR1. A list of .memfiles and +# .addr files are generated from the .elf. These are used as targets. +# % is a wildcard in a make target which is then referenced as % in the depenecies and $* +# in the recipe. +# because elf2hex requires a bit width we use findstring to figure out if the compiled directory +# is XLEN=64 or 32. This is hacky and will likely break in the future. +# the .addr is a separate target so make can split into more jobs and more parallism. +%.elf.memfile: BITWIDTH ?= $(if $(findstring rv64,$*),64,32) +%.elf.memfile: %.elf + riscv64-unknown-elf-elf2hex --bit-width $(BITWIDTH) --input $< --output $@ + +%.elf.objdump.addr: %.elf.objdump + extractFunctionRadix.sh $< diff --git a/tests/testgen/PIPELINE.py b/tests/testgen/PIPELINE.py deleted file mode 100755 index 35d040763..000000000 --- a/tests/testgen/PIPELINE.py +++ /dev/null @@ -1,166 +0,0 @@ -#!/usr/bin/env python3 -################################## -# PIPELINE.py -# -# David_Harris@hmc.edu 27 October 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def twoscomp(a): - amsb = a >> (xlen-1) - alsbs = ((1 << (xlen-1)) - 1) & a - if (amsb): - asigned = a - (1<> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -instrs = ["ADD"] # "SUB", "XOR", "OR", "AND", "SLT", "SLTU", ] -author = "David_Harris@hmc.edu" -xlens = [32, 64] -numrand = 1000 - -# 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 - pathname = "../wally-riscv-arch-test/riscv-test-suite/rv" + str(xlen) + "i_m/I/" - fname = pathname + "src/PIPELINE.S" - testnum = 0 - - # print custom header part - f = open(fname, "w") -# r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("testgen_header.S", "r") - for line in h: - f.write(line) - - maxreg = 5 - for i in range(numrand): - instr = instrs[randint(0,len(instrs)-1)] - reg1 = randint(0,maxreg) - reg2 = randint(1,maxreg) - reg3 = randint(1,maxreg) - line = instr + " x" +str(reg3) + ", x" + str(reg1) + ", x" + str(reg2) + "\n" - f.write(line) - - for i in range(1,maxreg+1): - line = storecmd + " x" + str(i) + ", " + str(wordsize*(i-1)) + "(x8)\n" - f.write(line) - - # print directed and random test vectors - # for a in corners: - # for b in corners: - # writeVector(a, b, storecmd, xlen) - # for i in range(0,numrand): - # a = getrandbits(xlen) - # b = getrandbits(xlen) - # writeVector(a, b, storecmd, xlen) - - - # print footer - h = open("testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish -# lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" -# lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() -# r.close() - - - - diff --git a/tests/testgen/imperas/testgen_footer.S b/tests/testgen/imperas/testgen_footer.S deleted file mode 100644 index f7cc0b18b..000000000 --- a/tests/testgen/imperas/testgen_footer.S +++ /dev/null @@ -1,18 +0,0 @@ - # --------------------------------------------------------------------------------------------- - - RVTEST_IO_WRITE_STR(x31, "Test End\n") - - # --------------------------------------------------------------------------------------------- - - RV_COMPLIANCE_HALT - -RV_COMPLIANCE_CODE_END - -# Input data section. - .data - - -# Output data section. -RV_COMPLIANCE_DATA_BEGIN - -test_1_res: diff --git a/tests/testgen/imperas/testgen_header.S b/tests/testgen/imperas/testgen_header.S deleted file mode 100644 index 118042a5c..000000000 --- a/tests/testgen/imperas/testgen_header.S +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University -// Adapted from Imperas RISCV-TEST_SUITE -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, -// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -/////////////////////////////////////////// - -#include "riscv_test_macros.h" -#include "compliance_test.h" -#include "compliance_io.h" - -RV_COMPLIANCE_RV64M - -RV_COMPLIANCE_CODE_BEGIN - - - RVTEST_IO_INIT - RVTEST_IO_ASSERT_GPR_EQ(x31, x0, 0x00000000) - RVTEST_IO_WRITE_STR(x31, "Test Begin\n") - - # --------------------------------------------------------------------------------------------- - - #RVTEST_IO_WRITE_STR(x31, "# Test group 1\n") - - - # address for test results - la x6, test_1_res - \ No newline at end of file diff --git a/tests/testgen/privileged/README.md b/tests/testgen/privileged/README.md deleted file mode 100644 index 9b3faff6f..000000000 --- a/tests/testgen/privileged/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Privileged Test Generators - -Create a test generator in this folder with the name testgen-NAME.py. Then, to generate and compile these tests, use: - -```bash -sh run.sh NAME -``` - -For example, for `testgen-CAUSE.py`, we would run `sh run.sh CAUSE`. - -This bash file is super basic, so only allows for a single argument after the name. -Provide -sim as the second argument to simulate the compiled tests using wally. - -```bash -sh run.sh NAME -sim -``` - -To compile tests without running them in OVPsim, provide -c as the second argument - -```bash -sh run.sh NAME -c -``` - -The test generator also has a really nice feature that grabs the location of begin_signature after compiling the tests. For example, running `sh run.sh EPC` will output something like this at the end: - -```verilog -rv64p = '{ - 'rv64p/WALLY-MEPC', '5000', - 'rv64p/WALLY-SEPC', '4000' -}; - -rv32p = '{ - 'rv32p/WALLY-MEPC', '5000', - 'rv32p/WALLY-SEPC', '4000' -}; -``` \ No newline at end of file diff --git a/tests/testgen/privileged/run.sh b/tests/testgen/privileged/run.sh deleted file mode 100755 index 8509e77e6..000000000 --- a/tests/testgen/privileged/run.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash - -# -# Written 1 Mar 2021 by Domenico Ottolia (dottolia@hmc.edu) -# -# See README.md in this directory for more info -# - -clear -printf "\n\n#####\nStarting tests for $1\n#####\n\n" - -if [[ "$2" != "-simonly" ]] -then - cd $WALLY/testgen/privileged - $RISCV/riscv-python/bin/python3 "testgen-$1.py" - printf "\n\n#####\nRan testgen-$1.py Making...\n#####\n\n\n" - - if [[ "$2" == "-c" ]] - then - printf "\n\n###\nWARNING\nThis seems to not be outputting begin_signature at the moment... Probably won't work in modelsim...\n###\n\n\n" - cd $WALLY/imperas-riscv-tests/riscv-test-suite/rv64p/src - riscv64-unknown-elf-gcc -nostdlib -nostartfiles -march=rv64g "WALLY-$1".S -I../../../riscv-test-env -I../../../riscv-test-env/p -I../../../riscv-target/riscvOVPsimPlus -T../../../riscv-test-env/p/link.ld -o "../../../work/rv64p/WALLY-$1.elf" - cd $WALLY/imperas-riscv-tests/work/rv64p - riscv64-unknown-elf-objdump -d "WALLY-$1".elf > "WALLY-$1".elf.objdump - - elif [[ "$2" != "-nosim" ]] - then - cd $WALLY/imperas-riscv-tests - make privileged - - exe2memfile.pl work/*/*.elf - extractFunctionRadix.sh work/rv64p/*.elf.objdump - fi -fi - -if [[ "$2" == "-simonly" ]] -then - printf "\n\n###\nWARNING\nThis seems to not be outputting begin_signature at the moment... Probably won't work in modelsim...\n###\n\n\n" - cd $WALLY/imperas-riscv-tests/riscv-test-suite/rv64p/src - riscv64-unknown-elf-gcc -nostdlib -nostartfiles -march=rv64g "WALLY-$1".S -I../../../riscv-test-env -I../../../riscv-test-env/p -I../../../riscv-target/riscvOVPsimPlus -T../../../riscv-test-env/p/link.ld -o "../../../work/rv64p/WALLY-$1.elf" - cd $WALLY/imperas-riscv-tests/work/rv64p - riscv64-unknown-elf-objdump -d "WALLY-$1".elf > "WALLY-$1".elf.objdump - - # riscv64-unknown-elf-gcc -nostdlib -nostartfiles -march=rv64g "WALLY-CAUSE".S -I../../../riscv-test-env -I../../../riscv-test-env/p -I../../../riscv-target/riscvOVPsimPlus -T../../../riscv-test-env/p/link.ld -o "../../../work/rv64p/WALLY-CAUSE.elf" - # riscv64-unknown-elf-objdump -d "WALLY-CAUSE.elf" > "WALLY-CAUSE.elf.objdump" -fi - -if [[ "$2" == "-sim" || "$2" == "-simonly" ]] -then - printf "\n\n\n#####\nSimulating!\n#####\n\n" - cd $WALLY/sim - vsim -do wally-privileged.do -c -fi - -cd $WALLY/pipelined -printf "\n\n\n#####\nDone!\n#####\n\n" - -cd $WALLY/imperas-riscv-tests/work -for isa in "rv64p" "rv32p"; do - printf "$isa = '{" - COMMA="" - for file in "$isa"/*.elf.objdump; do - if [[ "$file" == *"$1"* ]]; then - RES=$(grep "^\s*0*8000.000 " $file) - RES=$(echo "$RES" | sed -r 's/^0*80+([0-9]+).+?$/\1/g') - file=$(echo "$file" | sed -r 's/^(.+?)\.elf\.objdump/\1/g') - printf "$COMMA\n '$file', '${RES}'" - COMMA="," - fi - done - printf "\n};\n\n" -done - -cd $WALLY/pipelined \ No newline at end of file diff --git a/tests/testgen/privileged/testgen-CAUSE.py b/tests/testgen/privileged/testgen-CAUSE.py deleted file mode 100755 index 12e4ef886..000000000 --- a/tests/testgen/privileged/testgen-CAUSE.py +++ /dev/null @@ -1,573 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-CAUSE.py (new) -# -# dottolia@hmc.edu 1 Mar 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -# -# -################################## -# DOCUMENTATION: -# -# The most up-to-date comments explaining what everything -# does and the layout of the privileged tests -# can be found in testgen-TVAL.py. This and -# other files do not have as many comments -# -################################### - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -#For instruction-fetch access or page-fault exceptions on systems with variable-length instructions, mtval will contain the virtual address of the portion of the instruction that caused the fault while mepc will point to the beginning of the instruction. - -def randRegs(): - reg1 = randint(1,20) - reg2 = randint(1,20) - reg3 = randint(1,20) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return str(reg1), str(reg2), str(reg3) - -def writeVectors(storecmd, returningInstruction): - global testnum - - if testMode == "m": - if fromMode == "m": - expectedCode = 7 if fromMode == "m" else 5 - clintAddr = "0x2004000" - - writeTest(storecmd, f, r, f""" - li x1, 0x8 - csrrs x0, {fromMode}status, x1 - - la x18, {clintAddr} - {loadcmd} x11, 0(x18) - li x1, 0x3fffffffffffffff - {storecmd} x1, 0(x18) - - li x1, 0x80 - csrrs x0, {fromMode}ie, x1 - - {storecmd} x0, 0(x18) - """, True, expectedCode, f""" - li x1, 0x80 - csrrc x0, {fromMode}ie, x1 - - li x1, 0x8 - csrrc x0, {fromMode}status, x1 - - la x18, {clintAddr} - li x1, -1 - {storecmd} x1, 0(x18) - """) - - # Page 6 of unpriviledged spec - # For both CSRRS and CSRRC, if rs1=x0, then the instruction will not write to the CSR at all, and so shall not cause any of the side effects - - # User Software Interrupt: True, 0 - # Supervisor Software Interrupt: True, 1 - # Machine Software Interrupt: True, 2 - - # When running run.sh CAUSE -c, everything works, but begin_signature doesn't appear - # 0x2000000 in wally - # writeTest(storecmd, f, r, f""" - # la x10, 0x2000000 #clint - - # li x1, 42 - # sw x1, 0(x10) - # """, True, 2, "m", f""" - # lw x0, 0(x10) - # """) - - # User Timer Interrupt: True, 4 - # Supervior timer interrupt: True, 5 - # Machine timer interrupt: True, 7 - - # if fromMode == "m": - # clintAddr = "0x2004000" - - # writeTest(storecmd, f, r, f""" - # # li x1, 0x8 - # # csrrs x0, mstatus, x1 - - # # li x1, 0x80 - # # csrrs x0, mie, x1 - - # # la x18, {clintAddr} - # # lw x11, 0(x18) - # # lw x12, 4(x18) - # # li x1, 1 - # # {storecmd} x1, 0(x18) - # nop - # sub x1, x2, x3 - # sub x2, x3, x4 - # sub x3, x4, x5 - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # nop - # """, True, 7, f""" - # # la x18, {clintAddr} - # # {storecmd} x11, 0(x18) - # """) - - #writeTest(storecmd, f, r, f""" - # li x2, 0x0 -# - # li x4, 0x80 - # csrrs x0, mie, x4 - - # la x2, 0x2004000 - - # li x3, 0x0 - # lw x5, 0(x2) - # sd x3, 0(x2) - # wfi - # """, True, 7, "m", f""" - # t - # """) - - # writeTest(storecmd, f, r, f""" - # csrr x18, mstatus - # # csrsi mstatus, 0b11111 - # csrr x19, mie - # li x17, 0b1111111111111 - # # csrs mie, x17 - - # la x10, 0x2004000 #clint timer - # li x1, 0 - - # lw x11, 0(x10) - # lw x12, 4(x10) - - # {storecmd} x0, 0(x10) - # {storecmd} x0, 4(x10) - # """, True, 7, "m", f""" - # {storecmd} x11, 0(x10) - # {storecmd} x12, 4(x10) - - # csrw mstatus, x18 - # csrw mie, x19 - # """) - - # User external input: True, 8 - # Supervisor external input: True, 9 - # Machine externa input: True, 11 - - # Instruction address misaligned: False, 0 - # looks like this is giving us an infinite loop for wally - # BUG: jumping to a misaligned instruction address doesn't cause an exception: we actually jump... - # Either that, or somehow at the end we always end up at 0x80004002 - # This is fine in OVPsim - # writeTest(storecmd, f, r, f""" - # li x1, 11 - # jr x1 # Something about this instruction is funky on wally, but fine with ovpsim - # """, False, 0) - - # Instruction access fault: False, 1 - - # Illegal Instruction - writeTest(storecmd, f, r, f""" - .fill 1, 4, 0 - """, False, 2) - - # Breakpoint - if returningInstruction != "ebreak": - writeTest(storecmd, f, r, f""" - ebreak - """, False, 3) - - # Load Address Misaligned - writeTest(storecmd, f, r, f""" - lw x0, 11(x0) - """, False, 4) - - # Load Access fault: False, 5 - - # Store/AMO address misaligned - writeTest(storecmd, f, r, f""" - sw x0, 11(x0) - """, False, 6) - - # Environment call from u-mode: only for when only M and U mode enabled? - # writeTest(storecmd, f, r, f""" - # ecall - # """, False, 8, "u") - if returningInstruction != "ecall": - if fromMode == "u": - writeTest(storecmd, f, r, f""" - ecall - """, False, 8) - - # Environment call from s-mode - if fromMode == "s": - writeTest(storecmd, f, r, f""" - ecall - """, False, 9) - - # Environment call from m-mode - if fromMode == "m": - writeTest(storecmd, f, r, f""" - ecall - """, False, 11) - - # Instruction page fault: 12 - # Load page fault: 13 - # Store/AMO page fault: 15 - - - - -def writeTest(storecmd, f, r, test, interrupt, code, resetHander = ""): - global testnum, storeAddressOffset - - expected = code - if(interrupt): - expected+=(1 << (xlen - 1)) - - # The code we actually change for our test - lines = f""" - csrr x25, {testMode}cause - """ - - # Boilerplate - # - # x28 is the address that our trap handler will jump to before returning. - # This is where we can do our actual tests. After we're done computing and storing - # what we want, we jump to x27, which continues with the trap handling code (look at the _j_x_trap_... labels) - # - lines = f""" - la x28, _jtest{testnum} - j _jdo{testnum} - - _jtest{testnum}: - {lines} - {resetHander} - jr x27 - - _jdo{testnum}: - li x25, 0xDEADBEA7 - li gp, 0 - {test} - """ - - # We expect x25 to be 0 always. This is because of the code we wrote at the begining - # of this function - - # Store the expected value of x25 to memory and in the .reference_output file - lines += f""" - {storecmd} x25, {testnum * wordsize}(x6) - """ - - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -author = "dottolia@hmc.edu" -xlens = [32, 64] -testCount = 8; - -# setup -# Change this seed to a different constant value for every test -seed(0xC363DAEB9193AB45) # 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" - loadcmd = "lw" - wordsize = 4 - else: - storecmd = "sd" - loadcmd = "ld" - wordsize = 8 - - # testMode can be m, s, and u. User mode traps are deprecated, so this should likely just be ["m", "s"] - for testMode in ["m", "s"]: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + testMode.upper() + "CAUSE" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - storeAddressOffset = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line.replace("RV_COMPLIANCE_RV64M", "RV_COMPLIANCE_RV" + str(xlen) + "M")) - # f.write(f""" - # #include "riscv_test_macros.h" - # #include "compliance_test.h" - # #include "compliance_io.h" - - # 0000000080000000 <_start>: - # 80000000: 0480006f j 80000048 - # """) - - # We need to leave at least one bit in medeleg unset so that we have a way to get - # back to machine mode when the tests are complete (otherwise we'll only ever be able - # to get up to supervisor mode). - # - # So, we define a returning instruction which will be used to cause the exception that - # brings us into machine mode. The bit for this returning instruction is NOT set in - # medeleg. However, this also means that we can't test that instruction. So, we have - # two different returning instructions. - # - # Current code is written to only support ebreak and ecall. - # - # For testgen-TVAL, we don't need to test ebreak, so we can use that as the sole - # returning instruction. For others, like testgen-CAUSE, we'll need to put - # both ebreak and ecall here. - for returningInstruction in ["ebreak"]: - - # All registers used: - # x30: set to 1 if we should return to & stay in machine mode after trap, 0 otherwise - # ... - # x28: address trap handler should jump to for the test - # x27: address the test should return to after the test - # ... - # x25: value to write to memory - # ... - # x20: intermediate value in trap handler. Don't overwrite this! - # x19: mtvec old value - # x18: medeleg old value - # x17: sedeleg old value (currently unused — user mode traps deprecated) - # x16: mideleg old value - # ... - # x10 - x14 can be freely written - # ... - # x7: copy of x6. Increment this instead of using an offset on x6. - # this allows us to create more than 2048/wordlen tests. - # This is the address we write results to - # x6: Starting address we should write expected results to - # ... - # x1 - x5 can be freely written - - - - # Set up x7 and store old value of mtvec - lines = f""" - add x7, x6, x0 - csrr x19, mtvec - - slli a0,a0,0x1f - slli a0,a0,0x1e - slli a0,a0,0x1d - slli a0,a0,0x1c - slli a0,a0,0x1b - slli a0,a0,0x1a - slli a0,a0,0x19 - """ - - # Not used — user mode traps are deprecated - if testMode == "u": - lines += f""" - csrr x17, sedeleg - li x9, {"0b1100000000" if testMode == "u" else "0b0000000000"} - csrs sedeleg, x9 - """ - - # Code that will jump to the test (x28 is set in writeTest above) - testJumpCode = f""" - auipc x27, 0 - addi x27, x27, 12 - jr x28 - """ - - # Code for handling traps in different modes - # Some comments are inside of the below strings (prefixed with a #, as you might expected) - lines += f""" - # Reset x30 to 0 so we can run the tests. We'll set this to 1 when tests are completed so we stay in machine mode - li x30, 0 - - # Set up - la x1, _j_m_trap_{returningInstruction} - csrw mtvec, x1 - la x1, _j_s_trap_{returningInstruction} - csrw stvec, x1 - la x1, _j_u_trap_{returningInstruction} - # csrw utvec, x1 # user mode traps are not supported - - # Start the tests! - j _j_t_begin_{returningInstruction} - - # Machine mode traps - _j_m_trap_{returningInstruction}: - {testJumpCode if testMode == "m" else "li x25, 0xBAD00003"} - - csrrs x20, mepc, x0 - addi x20, x20, 4 - csrrw x0, mepc, x20 - bnez x30, _j_all_end_{returningInstruction} - mret - - # Supervisor mode traps - _j_s_trap_{returningInstruction}: - {testJumpCode if testMode == "s" else "li x25, 0xBAD00001"} - - csrrs x20, sepc, x0 - addi x20, x20, 4 - csrrw x0, sepc, x20 - bnez x30, _j_goto_machine_mode_{returningInstruction} - sret - - # Unused: user mode traps are no longer supported - _j_u_trap_{returningInstruction}: - {testJumpCode if testMode == "u" else "li x25, 0xBAD00000"} - - csrrs x20, uepc, x0 - addi x20, x20, 4 - csrrw x0, uepc, x20 - bnez x30, _j_goto_supervisor_mode_{returningInstruction} - uret - - # Currently unused. Just jumps to _j_goto_machine_mode. If you actually - # want to implement this, you'll likely need to reset sedeleg here - # and then cause an exception with {returningInstruction} (based on my intuition. Try that first, but I could be missing something / just wrong) - _j_goto_supervisor_mode_{returningInstruction}: - j _j_goto_machine_mode_{returningInstruction} - - _j_goto_machine_mode_{returningInstruction}: - li x30, 1 # This will cause us to branch to _j_all_end_{returningInstruction} in the machine trap handler, which we'll get into by invoking... - {returningInstruction} # ... this instruction! - - # Run the actual tests! - _j_t_begin_{returningInstruction}: - """ - - fromModeOptions = ["m", "s", "u"] if testMode == "m" else (["s", "u"] if testMode == "s" else ["u"]) - - # We don't want to delegate our returning instruction. Otherwise, we'll have no way of getting - # back to machine mode at the end! (and we need to be in machine mode to complete the tests) - medelegMask = "0b1111111111110111" if returningInstruction == "ebreak" else "0b1111000011111111" - - # Set medeleg and mideleg - lines += f""" - csrr x18, medeleg - li x9, {medelegMask if testMode == "s" or testMode == "u" else "0"} - csrw medeleg, x9 - - csrr x16, mideleg - li x9, {"0xffffffff" if testMode == "s" or testMode == "u" else "0"} - csrw mideleg, x9 - """ - - f.write(lines) - - for fromMode in fromModeOptions: - lines = "" - - # Code to bring us down to supervisor mode - if fromMode == "s" or fromMode == "u": - lines += f""" - li x1, 0b110000000000 - csrrc x31, mstatus, x1 - li x1, 0b0100000000000 - csrrs x31, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrw mepc, x1 - mret - - # We're now in supervisor mode... - """ - - # Code to bring us down to user mode - if fromMode == "u": - lines += f""" - - li x1, 0b110000000000 - csrrc x31, sstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the sret instruction - csrw sepc, x1 - sret - - # We're now in user mode... - """ - - f.write(lines) - for i in range(0,testCount): - writeVectors(storecmd, returningInstruction) - - - # Very end of test. Bring us back up to machine mode - # We set x30 to 1, which will cause us to branch to _j_all_end in the - # machine mode trap handler, before executing the mret instruction. This will - # make us stay in machine mode. - # - # If we're currently in user mode, this will first bump us up to the supervisor mode - # trap handler, which will call returningInstruction again before it's sret instruction, - # bumping us up to machine mode - # - # Get into the trap handler by running returningInstruction (either an ecall or ebreak) - f.write(f""" - li x30, 1 - li gp, 0 - {returningInstruction} - _j_all_end_{returningInstruction}: - - # Reset trap handling csrs to old values - csrw mtvec, x19 - csrw medeleg, x18 - csrw mideleg, x16 - """) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() diff --git a/tests/testgen/privileged/testgen-CSR-PERMISSIONS.py b/tests/testgen/privileged/testgen-CSR-PERMISSIONS.py deleted file mode 100755 index fadff0a36..000000000 --- a/tests/testgen/privileged/testgen-CSR-PERMISSIONS.py +++ /dev/null @@ -1,248 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-CSR-PERMISSIONS.py -# -# dottolia@hmc.edu 1 May 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -# Verify that an illegal instruction is raised when trying to write to csrs of a higher privilege -# -################################## -# DOCUMENTATION: -# -# Most of the comments explaining what everything -# does and the layout of the privileged tests -# can be found in this file -# -################################### - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -testCount = 2 - -def writeVectors(storecmd, testMode): - global testnum - - csrs = ["status", "edeleg", "ideleg", "ie", "tvec", "counteren", "scratch", "epc", "cause", "tval", "ip"] - if testMode == "s": - csrs.append("atp") - #csrs = ["status"] - for csrStart in csrs: - for i in range(0, testCount): - a = 1 - - csr = testMode + csrStart - - # only check for CSR changes if testing machine-mode registers - csrWillChange = testMode == "s" or csrStart == "status" or csrStart == "epc" or csrStart == "cause" or csrStart == "tval" - newCSRValue = "" if testMode == "s" else "csrr x24, " + csr - - f.write(f""" - li x13, 1 - """) - - fromModeOptions = ["s", "u"] if testMode == "m" else ["u"] - for fromMode in fromModeOptions: - label = f"""{fromMode}_{csr}_{testnum}""" - endlabel = f"""_j_end_{label}""" - # This is all from testgen-TVAL.py, within the for loop on returningInstruction - # - # x25: mepc value - # x24: new csr value - # x23: original csr value - lines = f""" - li x30, 0 - la x1, _m_trap_from_{label} - csrw mtvec, x1 - - csrr x23, {csr} - - j _j_test_{label} - - _m_trap_from_{label}: - bnez x30, {endlabel} - - csrr x25, mcause - {newCSRValue} - - csrrs x20, mepc, x0 - addi x20, x20, 4 - csrrw x0, mepc, x20 - - mret - - _j_test_{label}: - """ - - lines += f""" - li x1, 0b110000000000 - csrrc x0, mstatus, x1 - li x1, 0b0100000000000 - csrrs x0, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrw mepc, x1 - mret - - # We're now in supervisor mode... - """ - - # Code to bring us down to user mode - if fromMode == "u": - lines += f""" - - li x1, 0b110000000000 - csrrc x0, sstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the sret instruction - csrw sepc, x1 - sret - - # We're now in user mode... - """ - - f.write(lines) - - - writeTest(storecmd, f, r, f"""csrrw x1, {csr}, x0""", csrWillChange) - writeTest(storecmd, f, r, f"""csrrw x0, {csr}, x13""", csrWillChange) - writeTest(storecmd, f, r, f"""csrrwi x0, {csr}, {a}""", csrWillChange) - if a != 0: - writeTest(storecmd, f, r, f"""csrrs x0, {csr}, x13""", csrWillChange) - writeTest(storecmd, f, r, f"""csrrc x0, {csr}, x13""", csrWillChange) - writeTest(storecmd, f, r, f"""csrrsi x0, {csr}, {a}""", csrWillChange) - writeTest(storecmd, f, r, f"""csrrci x0, {csr}, {a}""", csrWillChange) - - f.write(f""" - li x30, 1 - ebreak - {endlabel}: - """) - - - - -def writeTest(storecmd, f, r, test, csrWillChange): - global testnum - - test = f""" - _jdo{testnum}: - li x25, 0xDEADBEA7 - - {test} - - {storecmd} x25, 0(x7) - addi x7, x7, {wordsize} - """ - - # We expect x25 to always be an illegal instruction - expected = 2 - - f.write(test) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - - if not csrWillChange: - # We expect x24 should be equal to x23 - expected = 0 - - f.write(f""" - sub x25, x24, x23 - {storecmd} x25, 0(x7) - addi x7, x7, {wordsize} - """) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -author = "dottolia@hmc.edu" -xlens = [32, 64] - -# setup -# Change this seed to a different constant value for every test -seed(0xC363DAEB9193AB45) # 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 - - for testMode in ["m", "s"]: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-CSR-PERMISSIONS-" + testMode.upper() - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - storeAddressOffset = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - f.write(f""" - add x7, x6, x0 - csrr x19, mtvec - """) - - writeVectors(storecmd, testMode) - - f.write(f""" - csrw mtvec, x19 - """) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - - diff --git a/tests/testgen/privileged/testgen-DELEG.py b/tests/testgen/privileged/testgen-DELEG.py deleted file mode 100755 index 4d7a99716..000000000 --- a/tests/testgen/privileged/testgen-DELEG.py +++ /dev/null @@ -1,371 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-CAUSE.py -# -# dottolia@hmc.edu 27 Apr 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -# -# -################################## -# DOCUMENTATION: -# Most of the comments explaining what everything -# does can be found in testgen-TVAL.py -################################### - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -#For instruction-fetch access or page-fault exceptions on systems with variable-length instructions, mtval will contain the virtual address of the portion of the instruction that caused the fault while mepc will point to the beginning of the instruction. - -def randRegs(): - reg1 = randint(1,20) - reg2 = randint(1,20) - reg3 = randint(1,20) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return str(reg1), str(reg2), str(reg3) - -def writeVectors(storecmd): - global testnum - - # User Software Interrupt: True, 0 - # Supervisor Software Interrupt: True, 1 - # Machine Software Interrupt: True, 2 - - writeTest(storecmd, f, r, "timer-interrupt", True, -1) # code determined inside of writeTest - - # User external input: True, 8 - # Supervisor external input: True, 9 - # Machine externa input: True, 11 - - # Instruction address misaligned: False, 0 - - # Instruction access fault: False, 1 - - # Illegal Instruction - writeTest(storecmd, f, r, f""" - .fill 1, 4, 0 - """, False, 2) - - # Breakpoint - writeTest(storecmd, f, r, "ebreak", False, 3) - - # Load Address Misaligned - writeTest(storecmd, f, r, f""" - lw x0, 11(x0) - """, False, 4) - - # # Load Access fault: False, 5 - # TODO: THIS NEEDS TO BE IMPLEMENTED - - # # Store/AMO address misaligned - writeTest(storecmd, f, r, f""" - sw x0, 11(x0) - """, False, 6) - - # Breakpoint: codes 8, 9, 11 - writeTest(storecmd, f, r, "ecall", False, -1) # code determined inside of writeTest - - # Instruction page fault: 12 - # TODO: THIS NEEDS TO BE IMPLEMENTED - - # Load page fault: 13 - # TODO: THIS NEEDS TO BE IMPLEMENTED - - # Store/AMO page fault: 15 - # TODO: THIS NEEDS TO BE IMPLEMENTED - - - #writeTest(storecmd, f, r, "ecall", False, 11, "m") - -def writeTest(storecmd, f, r, test, interrupt, code, resetHander = ""): - global testnum - global testMode - global isInterrupts - - beforeTest = "" - - if interrupt != isInterrupts: - return - - isTimerInterruptTest = test == "timer-interrupt" - delegateType = "i" if interrupt else "e" - for mode in (["m", "s", "u"] if testMode == "m" else ["s", "u"]): - if isTimerInterruptTest: - clintAddr = "0x2004000" - - if mode == "m": - code = 7 - test = f""" - la x18, {clintAddr} - {storecmd} x0, 0(x18) - """ - - elif mode == "s": - code = 5 - test = "" - else: - code = 4 - test = "" - - ieMask = 1 << code - statusMask = 0b1010 - - beforeTest = f""" - li x1, {statusMask} - csrrs x0, mstatus, x1 - - li x1, 0b0010 - csrrs x0, sstatus, x1 - - la x18, {clintAddr} - lw x11, 0(x18) - li x1, 0x7fffffffffffffff - {storecmd} x1, 0(x18) - - li x1, {ieMask} - csrrs x0, mie, x1 - - li x1, {ieMask} - csrrs x0, sie, x1 - """ - - resetHander = f""" - #li x1, 0x80 - #csrrc x0, sie, x1 - - li x1, {ieMask} - csrrc x0, mie, x1 - - li x1, {ieMask} - csrrc x0, sie, x1 - - li x1, {statusMask} - csrrc x0, mstatus, x1 - - li x1, 0b0010 - csrrc x0, sstatus, x1 - - la x18, {clintAddr} - {storecmd} x11, 0(x18) - """ - - if mode == "s": - beforeTest += f""" - li x1, {ieMask} - csrrs x0, sip, x1 - """ - - resetHander += f""" - li x1, {ieMask} - csrrc x0, sip, x1 - """ - - elif test == "ecall": - if mode == "m": - code = 11 - elif mode == "s": - code = 9 - else: - code = 8 - - mask = 1 << code - for delegated in [True, False]: - labelSuffix = testnum - - f.write(f""" - _start_{labelSuffix}: - - la x1, _j_m_trap_{labelSuffix} - csrw mtvec, x1 - la x1, _j_s_trap_{labelSuffix} - csrw stvec, x1 - - j _j_test_{labelSuffix} - - _j_m_trap_{labelSuffix}: - {resetHander} - li x25, 3 - - csrr x1, mepc - addi x1, x1, 4 - csrrw x0, mepc, x1 - bnez x30, _j_finished_{labelSuffix} - mret - - _j_s_trap_{labelSuffix}: - {resetHander} - li x25, 1 - - csrr x1, sepc - addi x1, x1, 4 - csrrw x0, sepc, x1 - bnez x30, _j_goto_machine_mode_{labelSuffix} - sret - - _j_goto_machine_mode_{labelSuffix}: - li x30, 1 - {"ebreak" if test is not "ebreak" else "ecall"} - - _j_test_{labelSuffix}: - """) - - original = f""" - li x1, {mask if delegated else 0} - csrw m{delegateType}deleg, x1 - """ - - if mode != "m": - lines = f""" - {original} - - {beforeTest} - - li x1, 0b110000000000 - csrrc x31, {testMode}status, x1 - li x1, 0b{"01" if mode == "s" else "00"}00000000000 - csrrs x31, {testMode}status, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the ret instruction - csrrw x27, {testMode}epc, x1 - {testMode}ret - - # From {testMode}, we're now in {mode} mode... - {test} - """ - - writeTestInner(storecmd, f, r, lines, 1 if delegated else 3) - - f.write(f""" - j _j_goto_machine_mode_{labelSuffix} - """) - - else: - lines = f""" - {original} - {beforeTest} - {test} - """ - writeTestInner(storecmd, f, r, lines, 3) - - f.write(f""" - _j_finished_{labelSuffix}: - li x30, 0 - """) - - -def writeTestInner(storecmd, f, r, lines, expected): - global testnum - - lines = f""" - li x25, 0xDEADBEA7 - {lines} - """ - - lines += storecmd + " x25, " + str(testnum * wordsize) + "(x6)\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -author = "dottolia@hmc.edu" -xlens = [32, 64] -numrand = 1; - -# setup -seed(0xD0C0_D0C0_D0C0_D0C0) # 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 - - for testMode in ["m"]: - for isInterrupts in [True, False]: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + testMode.upper() + ("I" if isInterrupts else "E") + "DELEG" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - # All registers used: - # x19: mtvec old value - # x18: medeleg old value - # x17: mideleg old value - - f.write(f""" - add x7, x6, x0 - csrr x19, mtvec - csrr x18, medeleg - csrr x17, medeleg - """) - - testnum = 0 - for i in range(0, 2): - writeVectors(storecmd) - - f.write(f""" - csrw mtvec, x19 - csrw medeleg, x18 - csrw mideleg, x17 - """) - - # if we're in supervisor mode, this leaves the ebreak instruction untested (we need a way to) - # get back to machine mode. - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - diff --git a/tests/testgen/privileged/testgen-EPC.py b/tests/testgen/privileged/testgen-EPC.py deleted file mode 100755 index c9b5ad0e0..000000000 --- a/tests/testgen/privileged/testgen-EPC.py +++ /dev/null @@ -1,263 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-CAUSE.py -# -# dottolia@hmc.edu 1 Mar 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -#For instruction-fetch access or page-fault exceptions on systems with variable-length instructions, mtval will contain the virtual address of the portion of the instruction that caused the fault while mepc will point to the beginning of the instruction. - -def randRegs(): - reg1 = randint(1,20) - reg2 = randint(1,20) - reg3 = randint(1,20) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return str(reg1), str(reg2), str(reg3) - -def writeVectors(storecmd): - global testnum - - # Load address misaligned - writeTest(storecmd, f, r, f""" - ecall - """, False, 9) - - -def writeTest(storecmd, f, r, test, interrupt, code, resetHander = ""): - global testnum - global testMode - - nops = "" - for i in range(0, randint(1, 16)): - nops+="nop\n" - - lines = f""" - {nops} - li x25, 0xDEADBEA7 - auipc x26, 0 - addi x26, x26, 8 - {test} - - _jend{testnum}: - - {storecmd} x25, 0(x7) - addi x7, x7, {wordsize} - """ - - f.write(lines) - - expected = 0 - - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 -################################## -# main body -################################## - -# change these to suite your tests -author = "dottolia@hmc.edu" -xlens = [32, 64] -numrand = 64; - -# setup -seed(0x9365DDEB9173AB42) # 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 - - corners = [ - 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1 - ] - - for testMode in ["m", "s"]: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + testMode.upper() + "EPC" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - # All registers used: - # x30: set to 1 if we should return to & stay in machine mode after trap, 0 otherwise - # ... - # x26: expected epc value - # x25: value to write to memory - # ... - # x19: mtvec old value - # x18: medeleg old value - # x17: sedeleg old value - - - lines = f""" - add x7, x6, x0 - csrr x19, mtvec - - csrr x18, medeleg - li x9, {"0b1100000000" if testMode == "s" or testMode == "u" else "0b0000000000"} - csrs medeleg, x9 - - """ - - if testMode == "u": - lines += f""" - csrr x17, sedeleg - li x9, {"0b1100000000" if testMode == "u" else "0b0000000000"} - csrs sedeleg, x9 - """ - - lines += f""" - - li x30, 0 - - la x1, _j_m_trap - csrw mtvec, x1 - la x1, _j_s_trap - csrw stvec, x1 - la x1, _j_u_trap - csrw utvec, x1 - j _j_t_begin - - _j_m_trap: - csrrs x1, mepc, x0 - {"sub x25, x26, x1" if testMode == "m" else "li x25, 0xBAD00003"} - - addi x1, x1, 4 - csrrw x0, mepc, x1 - bnez x30, _j_all_end - mret - - _j_s_trap: - csrrs x1, sepc, x0 - {"sub x25, x26, x1" if testMode == "s" else "li x25, 0xBAD00001"} - - addi x1, x1, 4 - csrrw x0, sepc, x1 - bnez x30, _j_goto_machine_mode - sret - - _j_u_trap: - csrrs x1, uepc, x0 - {"sub x25, x26, x1" if testMode == "u" else "li x25, 0xBAD00000"} - - addi x1, x1, 4 - csrrw x0, uepc, x1 - bnez x30, _j_goto_supervisor_mode - uret - - _j_goto_supervisor_mode: - csrw sedeleg, x17 - j _j_goto_machine_mode - - _j_goto_machine_mode: - csrw medeleg, x18 - li x30, 1 - ecall - - _j_t_begin: - """ - - fromModeOptions = ["m", "s", "u"] if testMode == "m" else (["s", "u"] if testMode == "s" else ["u"]) - - f.write(lines) - - for fromMode in fromModeOptions: - lines = "" - - if fromMode == "s" or fromMode == "u": - lines += f""" - li x1, 0b110000000000 - csrrc x31, mstatus, x1 - li x1, 0b0100000000000 - csrrs x31, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrw mepc, x1 - mret - - # We're now in supervisor mode... - """ - - if fromMode == "u": - lines += f""" - - li x1, 0b110000000000 - csrrc x31, sstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the sret instruction - csrw sepc, x1 - sret - - # We're now in user mode... - """ - - # print directed and random test vectors - f.write(lines) - for i in range(0,numrand): - writeVectors(storecmd) - - - f.write(f""" - li x30, 1 - ecall - _j_all_end: - - csrw mtvec, x19 - """) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() diff --git a/tests/testgen/privileged/testgen-IE.py b/tests/testgen/privileged/testgen-IE.py deleted file mode 100755 index 032d719d2..000000000 --- a/tests/testgen/privileged/testgen-IE.py +++ /dev/null @@ -1,406 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-IE.py -# -# ushakya@hmc.edu 31 March 2021 -# Modified: 4 April 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def writeTrapHandlers(storecmd, mode): - global testnum - [reg1, reg2, reg3] = [30, 29, 28] - [reg4, reg5] = [27, 26] - if mode == "M": - lines = "\n# Trap Handler: Machine Timer Interupt\n" - lines += "_timerM_trap_handler:\n" - lines += "li x" + str(reg1) + ", MASK_XLEN(0xFFFF)\n" - lines += "la x" + str(reg2) + ", 0x2004000\n" - lines += str(storecmd) + " x" + str(reg1) + ", 0(x" + str(reg2) + ")\n" - lines += "csrrc x" + str(reg3) + ", mepc, x0\n" - lines += "addi x"+ str(reg3) + ", x" + str(reg3) + ", MASK_XLEN(0x4)\n" - lines += "csrrw x0, mepc, x" + str(reg3) + "\n" - # clear machine timer interupt enable bit in mie - lines += "li x" + str(reg4) + ", MASK_XLEN(" + str(0x80) + ")\n" - lines += "csrrc x0, mie, x" + str(reg4) + "\n" - lines += "mret\n" - elif mode == "S": - lines = "\n# Trap Handler: Supervisor Timer Interupt\n" - lines += "_timerS_trap_handler:\n" - lines += "li x" + str(reg4) + ", MASK_XLEN(0x20)\n" - lines += "csrrc x0, mip, x" + str(reg4) + "\n" - lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - lines += "mret\n" - - #lines += "\n# Trap Handler: User Timer Interupt\n" - #lines += "_timerU_trap_handler:\n" - #lines += "li x" + str(reg4) + ", MASK_XLEN(0x10)\n" - #lines += "csrrc x0, mip, x" + str(reg4) + "\n" - #lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - #lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - #lines += "mret\n" - - #lines += "\n# Trap Handler: Machine Software Interupt\n" - #lines += "_softwareM_trap_handler:\n" - #lines += "li x" + str(reg1) + ", MASK_XLEN(0x0)\n" # clear MSIP bit in CLINT - #lines += "la x" + str(reg2) + ", 0x2000000\n" - #lines += str(storecmd) + " x" + str(reg1) + ", 0(x" + str(reg2) + ")\n" - ##lines += "csrrs x" + str(reg3) + ", mepc, x0\n" - #lines += "addi x"+ str(reg3) + ", x" + str(reg3) + ", MASK_XLEN(0x4)\n" - #lines += "csrrw x0, mepc, x" + str(reg3) + "\n" - #lines += "mret\n" - - """lines += "\n# Trap Handler: Supervisor Software Interupt\n" - lines += "_softwareS_trap_handler:\n" - lines += "li x" + str(reg4) + ", MASK_XLEN(0x2)\n" - lines += "csrrc x0, mip, x" + str(reg4) + "\n" - lines += "csrrs x" + str(reg5) + ", mepc, x0\n" - lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - lines += "csrrw x0, mepc, x" + str(reg5) + "\n" - lines += "mret\n" -""" - #lines += "\n# Trap Handler: User Software Interupt\n" - #lines += "_softwareU_trap_handler:\n" - #lines += "li x" + str(reg4) + ", MASK_XLEN(0x1)\n" - #lines += "csrrc x0, mip, x" + str(reg4) + "\n" - #lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - #lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - #lines += "mret\n" - - #lines += "\n# Trap Handler: Machine External Interupt\n" - #lines += "_externalM_trap_handler:\n" - #lines += "li x" + str(reg1) + ", MASK_XLEN(0x0)\n" # clear MSIP bit in CLINT - #lines += "la x" + str(reg2) + ", 0x2000000\n" - #lines += str(storecmd) + " x" + str(reg1) + ", 0(x" + str(reg2) + ")\n" - #lines += "csrrw x" + str(reg3) + ", mepc, x0\n" - #lines += "addi x"+ str(reg3) + ", x" + str(reg3) + ", MASK_XLEN(0x4)\n" - #lines += "mret\n" - - #lines += "\n# Trap Handler: Supervisor External Interupt\n" - #lines += "_externalS_trap_handler:\n" - #lines += "li x" + str(reg4) + ", MASK_XLEN(0x200)\n" - #lines += "csrrc x0, mip, x" + str(reg4) + "\n" - #lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - #lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - #lines += "mret\n" - - #lines += "\n# Trap Handler: User External Interupt\n" - #lines += "_externalU_trap_handler:\n" - #lines += "li x" + str(reg4) + ", MASK_XLEN(0x100)\n" - #lines += "csrrc x0, mip, x" + str(reg4) + "\n" - #lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - #lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - #lines += "mret\n" - - f.write(lines) - -def getInteruptEnableValues(): - if test == "timerM": - mstatusE = 0x8 - mieE = 0x80 - elif test == "timerS": - mstatusE = 0x2 - mieE = 0x20 - elif test == "timerU": - mstatusE = 0x1 - mieE = 0x10 - elif test == "softwareM": - mstatusE = 0x8 - mieE = 0x8 - elif test == "softwareS": - mstatusE = 0x2 - mieE = 0x2 - elif test == "softwareU": - mstatusE = 0x1 - mieE = 0x1 - elif test == "externalM": - mstatusE = 0x8 - mieE = 0x800 - elif test == "externalS": - mstatusE = 0x2 - mieE = 0x200 - elif test == "externalU": - mstatusE = 0x1 - mieE = 0x100 - return [mstatusE, mieE] - -def getMcause(): - b = 1 << (xlen-1) - if test == "timerM": - b = b + 0x7 - elif test == "timerS": - b = b + 0x5 - elif test == "timerU": - b = b + 0x4 - elif test == "softwareM": - b = b + 0x3 - elif test == "softwareS": - b = b + 0x1 - elif test == "softwareU": - b = b - elif test == "externalM": - b = b + 0xB - elif test == "externalS": - b = b + 0x9 - elif test == "externalU": - b = b + 0x8 - return b - -def writeVectors(a, xlen, storecmd): - global testnum - - # Registers used: - # x13 ---> read mcause value - # x12 ---> save old value of mtvec - # x8 ---> holds mieE - # x5 ---> holds value of trap handler - # x3 ---> holds mstatusE - # remaining registers (not used by mode management) are free to be used by tests - - [reg2, reg3] = [2, 3] - [reg5, reg8] = [5, 8] - [reg10, reg11, reg12] = [10, 11, 12] - [reg13, reg14, reg15] = [13, 14, 15] - - lines = f"\n# Testcase {testnum}: {test} Interupt\n" - - # mcause code - expected = getMcause() - - [mstatusE, mieE] = getInteruptEnableValues() - # ensure interupt enable bit in mie is low - lines += "li x" + str(reg8) + ", MASK_XLEN(" + formatstr.format(mieE) + ")\n" - lines += "csrrc x0, mie, x" + str(reg8) + "\n" - - # set interupt enable bit in mstatus - lines += "li x" + str(reg3) + ", MASK_XLEN(" + formatstr.format(mstatusE) + ")\n" - lines += "csrrs x0, mstatus, x" + str(reg3) + "\n" - - # Save and set trap handler address for interrupt - lines += "la x" + str(reg5) + ", _" + test + "_trap_handler\n" - - # save orignal mtvec address - lines += "csrrw x" + str(reg12) + ", mtvec, x" + str(reg5) + "\n" - - # cause timer interupt - if test == "timerM": - - # load MTIMECMP register address - lines += "la x" + str(reg2) + ", 0x2004000\n" - - # to be stored in MTIMECMP - lines += "li x" + str(reg10) + ", MASK_XLEN(0)\n" - - # save old value of mtimecmp and then set mtimecmp to zero - if xlens == 64: - lines += "lw x" + str(reg11) + ", 0(x" + str(reg2) + ")\n" - lines += str(storecmd) + " x" + str(reg10) + ", 0(x" + str(reg2) + ")\n" - - elif xlen == 32: - lines += "lw x" + str(reg11) + ", 0(x" + str(reg2) + ")\n" - lines += str(storecmd) + " x" + str(reg10) + ", 0(x" + str(reg2) + ")\n" - lines += str(storecmd) + " x" + str(reg10) + ", 4(x" + str(reg2) + ")\n" - - elif test == "timerS": - lines += "li x" + str(reg3) + ", MASK_XLEN(0x20)\n" - lines += "csrrs x0, mip, x" + str(reg3) + "\n" - - # cause software interupt - if test == "softwareM": - lines += "la x" + str(reg8) + ", 0x2000000\n" # Write to the MSIP bit in CLINT - lines += "li x" + str(reg11) + ", MASK_XLEN(0x1)\n" - lines += str(storecmd) + " x" + str(reg11) + ", 0(x" + str(reg8) + ")\n" - elif test == "softwareS": - lines += "li x" + str(reg3) + ", MASK_XLEN(0x2)\n" - lines += "csrrs x0, mip, x" + str(reg3) + "\n" - - - # set timer interupt enable bit in mie - lines += "csrrs x0, mie, x" + str(reg8) + "\n" - - # wait for interupt to be taken - lines += "nop\nnop\n" - - lines += "csrrs " + " x" + str(reg13) + ", mcause, x0\n" - - # reset mtvec - lines += "csrrw x0, mtvec, x" + str(reg12) + "\n" - - lines += storecmd + " x" + str(reg13) + ", " + str(wordsize*testnum) + "(x6)\n" - lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, x" + str(reg13) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -tests = ["timerM"] #, "timerM", "timerS", "softwareM", "softwareS"] -author = "ushakya@hmc.edu" -xlens = [64] #, 32] -modes = ["M"]#, "S"] -numrand = 100; - -# 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 - for mode in modes: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + mode + "IE" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - line = "\n" - # Registers used for dropping down to supervisor mode: - # x30 ---> set to 1 if we should return to & stay in machine mode after trap, 0 otherwise - # x20 ---> hold address of _j_all_end_{returningInstruction} - # x19 ---> save old value of mtvec - # x18 ---> save old value of medeleg - # x16 ---> save old value of mideleg - # x9 ---> bit mask for mideleg and medeleg - # x1 ---> used to go down to supervisor mode - - # We need to leave at least one bit in medeleg unset so that we have a way to get - # back to machine mode when the tests are complete (otherwise we'll only ever be able - # to get up to supervisor mode). - # - # So, we define a returning instruction which will be used to cause the exception that - # brings us into machine mode. The bit for this returning instruction is NOT set in - # medeleg. However, this also means that we can't test that instruction. So, we have - # two different returning instructions. - # - # Current code is written to only support ebreak and ecall. - # - # For testgen-IE, we don't need to test ebreak, so we can use that as the sole - # returning instruction. - returningInstruction = "ebreak" - if mode == "S": - # need to move down to supervisor mode (based on code in testgen-TVAL) - lines += f""" - # Reset x30 to 0 so we can run the tests. We'll set this to 1 when tests are completed so we stay in machine mode - li x30, 0 - """ - - # We don't want to delegate our returning instruction. Otherwise, we'll have no way of getting - # back to machine mode at the end! (and we need to be in machine mode to complete the tests) - medelegMask = "0b1111111111110111" if returningInstruction == "ebreak" else "0b1111000011111111" - - # Set medeleg and mideleg - lines += f""" - csrr x18, medeleg - li x9, {medelegMask if testMode == "s" or testMode == "u" else "0"} - csrw medeleg, x9 - - csrr x16, mideleg - li x9, {"0xffffffff" if testMode == "s" or testMode == "u" else "0"} - csrw mideleg, x9 - """ - - # bring down to supervisor mode - lines += f""" - li x1, 0b110000000000 - csrrc x31, mstatus, x1 - li x1, 0b0100000000000 - csrrs x31, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrw mepc, x1 - mret - - # We're now in supervisor mode... - """ - - for test in tests: - # print directed and random test vectors - for i in range(0,numrand): - a = getrandbits(xlen) - writeVectors(a, xlen, storecmd) - - if mode == "S": - # Bring us back up to machine mode! - # Creates a new trap handler that just jumps to _j_all_end_{returningInstruction} - # - # Get into the trap handler by running returningInstruction (in this case its ebreak) - f.write(f""" - li x30, 1 #may not need this - csrr x19, mtvec # save old value of mtvec - la x20 _j_all_end_{returningInstruction} - csrw mtvec, x20 - {returningInstruction} - - _returnMachineMode_handler: - j _j_all_end_{returningInstruction} - mret - - _j_all_end_{returningInstruction}: - - # Reset trap handling csrs to old values - csrw mtvec, x19 - csrw medeleg, x18 - csrw mideleg, x16 - """) - - f.write(lines) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - - writeTrapHandlers(storecmd, mode) - - f.close() - r.close() diff --git a/tests/testgen/privileged/testgen-IP.py b/tests/testgen/privileged/testgen-IP.py deleted file mode 100755 index 2741362ed..000000000 --- a/tests/testgen/privileged/testgen-IP.py +++ /dev/null @@ -1,196 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-IE.py -# -# ushakya@hmc.edu 31 March 2021 -# Modified: 4 April 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def getInteruptEnableValues(): - if test == "timerM": - mstatusE = 0x8 - mieE = 0x80 - elif test == "timerS": - mstatusE = 0x2 - mieE = 0x20 - elif test == "timerU": - mstatusE = 0x1 - mieE = 0x10 - elif test == "softwareM": - mstatusE = 0x8 - mieE = 0x8 - elif test == "softwareS": - mstatusE = 0x2 - mieE = 0x2 - elif test == "softwareU": - mstatusE = 0x1 - mieE = 0x1 - elif test == "externalM": - mstatusE = 0x8 - mieE = 0x800 - elif test == "externalS": - mstatusE = 0x2 - mieE = 0x200 - elif test == "externalU": - mstatusE = 0x1 - mieE = 0x100 - return [mstatusE, mieE] - -def getMcause(): - b = 1 << (xlen-1) - if test == "timerM": - b = b + 0x7 - elif test == "timerS": - b = b + 0x5 - elif test == "timerU": - b = b + 0x4 - elif test == "softwareM": - b = b + 0x3 - elif test == "softwareS": - b = b + 0x1 - elif test == "softwareU": - b = b - elif test == "externalM": - b = b + 0xB - elif test == "externalS": - b = b + 0x9 - elif test == "externalU": - b = b + 0x8 - return b - -# MIP is implicitly tested in the MIE tests -# these tests are to test that when mtimecmp < mtime -# MTIP bit is high in MIP -def writeVectors(a, xlen, storecmd): - global testnum - - [reg2, reg3] = [2, 3] - [reg5, reg8] = [5, 8] - [reg10, reg11, reg12] = [10, 11, 12] - [reg13, reg14, reg15] = [13, 14, 15] - - lines = f"\n# Testcase {testnum}: {test} Interupt\n" - - # mcause code - expected = 0x80 - - [mstatusE, mieE] = getInteruptEnableValues() - # ensure interupt enable bit in mie is low - lines += "li x" + str(reg8) + ", MASK_XLEN(" + formatstr.format(mieE) + ")\n" - lines += "csrrc x0, mie, x" + str(reg8) + "\n" - - # set interupt enable bit in mstatus - lines += "li x" + str(reg3) + ", MASK_XLEN(" + formatstr.format(mstatusE) + ")\n" - lines += "csrrs x0, mstatus, x" + str(reg3) + "\n" - - # cause timer interupt - if test == "timerM": - - # load MTIMECMP register address - lines += "la x" + str(reg2) + ", 0x2004000\n" - - # to be stored in MTIMECMP - lines += "li x" + str(reg10) + ", MASK_XLEN(0)\n" - - # save old value of mtimecmp and then set mtimecmp to zero - if xlens == 64: - lines += "lw x" + str(reg11) + ", 0(x" + str(reg2) + ")\n" - lines += str(storecmd) + " x" + str(reg10) + ", 0(x" + str(reg2) + ")\n" - - elif xlen == 32: - lines += "lw x" + str(reg11) + ", 0(x" + str(reg2) + ")\n" - lines += str(storecmd) + " x" + str(reg10) + ", 0(x" + str(reg2) + ")\n" - lines += str(storecmd) + " x" + str(reg10) + ", 4(x" + str(reg2) + ")\n" - - lines += "csrrs " + " x" + str(reg13) + ", mip, x0\n" - - lines += storecmd + " x" + str(reg13) + ", " + str(wordsize*testnum) + "(x6)\n" - lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, x" + str(reg13) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -tests = ["timerM"] #, "softwareM"] -author = "ushakya@hmc.edu" -xlens = [64, 32] -numrand = 100; - -# 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 - - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-IP" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - for test in tests: - # print directed and random test vectors - for i in range(0,numrand): - a = getrandbits(xlen) - writeVectors(a, xlen, storecmd) - - f.write(lines) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - - f.close() - r.close() diff --git a/tests/testgen/privileged/testgen-READONLY.py b/tests/testgen/privileged/testgen-READONLY.py deleted file mode 100755 index 71eedbde5..000000000 --- a/tests/testgen/privileged/testgen-READONLY.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-CAUSE.py -# -# dottolia@hmc.edu 1 Mar 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -#For instruction-fetch access or page-fault exceptions on systems with variable-length instructions, mtval will contain the virtual address of the portion of the instruction that caused the fault while mepc will point to the beginning of the instruction. - -def randRegs(): - reg1 = randint(1,20) - reg2 = randint(1,20) - reg3 = randint(1,20) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return str(reg1), str(reg2), str(reg3) - -def writeVectors(a, storecmd): - writeSingleVector(a, storecmd, f"""csrrw x0, {test}, x13""") - writeSingleVector(a, storecmd, f"""csrrwi x0, {test}, {a % 32}""") - if a != 0: - writeSingleVector(a, storecmd, f"""csrrs x0, {test}, x13""") - writeSingleVector(a, storecmd, f"""csrrc x0, {test}, x13""") - writeSingleVector(a, storecmd, f"""csrrsi x0, {test}, {(a % 31) + 1}""") - writeSingleVector(a, storecmd, f"""csrrci x0, {test}, {(a % 31) + 1}""") - - -def writeSingleVector(a, storecmd, writeInstruction): - global testnum - - # Illegal Instruction - writeTest(storecmd, f, r, f""" - li x13, MASK_XLEN({a}) - csrrw x11, {test}, x0 - {writeInstruction} - csrrwi x12, {test}, 0 - sub x15, x11, x12 - """, False, 2) - - expected = 0 - lines = "" - lines += storecmd + " x15, " + str(wordsize*testnum) + "(x6)\n" - #lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - - - -def writeTest(storecmd, f, r, test, interrupt, code, mode = "m", resetHander = ""): - global testnum - - expected = code - if(interrupt): - expected+=(1 << (wordsize - 1)) - - - trapEnd = "" - before = "" - if mode != "m": - before = f""" - li x1, 0b110000000000 - csrrc x28, mstatus, x1 - li x1, 0b{"01" if mode == "s" else "00"}0000000000 - csrrs x28, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrrw x27, mepc, x1 - mret - - # We're now in {mode} mode... - """ - - trapEnd = f"""j _jend{testnum}""" - - - # Setup - # TODO: Adding 8 to x30 won't work for 32 bit? - # x31: Old mtvec value - # x30: trap handler address - # x29: Old mtvec value for user/supervisor mode - # x28: Old mstatus value - # x27: Old mepc value - # x26: 0 if we should execute mret normally. 1 otherwise. This allows us to stay in machine - # x25: mcause - # mode for the next tests - lines = f""" - # Testcase {testnum} - csrrs x31, mtvec, x0 - - auipc x30, 0 - addi x30, x30, 12 - j _jtest{testnum} - - # Machine trap vector - {resetHander} - csrrs x25, mcause, x0 - csrrs x1, mepc, x0 - addi x1, x1, 4 - csrrw x0, mepc, x1 - {trapEnd} - mret - - # Actual test - _jtest{testnum}: - csrrw x0, mtvec, x30 - - # Start test code - li x25, 0x7BAD - {before} - {test} - - # Finished test. Reset to old mtvec - _jend{testnum}: - - csrrw x0, mtvec, x31 - """ - - #expected = 42 - - lines += storecmd + " x25, " + str(wordsize*testnum) + "(x6)\n" - #lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - - # lines += storecmd + " x0" + ", " + str(wordsize*testnum) + "(x6)\n" - # #lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\n" - # f.write(lines) - # if (xlen == 32): - # line = formatrefstr.format(expected)+"\n" - # else: - # line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - # r.write(line) - # testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -# csrrw, csrrs, csrrc, csrrwi, csrrsi, csrrci -author = "dottolia@hmc.edu" -xlens = [32, 64] -numrand = 4; -tests = ["marchid", "mhartid", "mimpid", "mvendorid"] - -# setup -seed(0xD365DDEB9173AB42) # 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 - - for test in tests: - corners = [ - 0, 1, 2, 31, 32, - 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1 - ] - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + test.upper() - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - # print directed and random test vectors - for i in corners: - writeVectors(i, storecmd) - for i in range(0,numrand): - writeVectors(getrandbits(xlen), storecmd) - - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - - diff --git a/tests/testgen/privileged/testgen-RET.py b/tests/testgen/privileged/testgen-RET.py deleted file mode 100755 index 94d5f7262..000000000 --- a/tests/testgen/privileged/testgen-RET.py +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-CAUSE.py -# -# dottolia@hmc.edu 16 Mar 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from enum import Enum -from random import getrandbits - -################################## -# functions -################################## - -# def computeExpected(a, b, test): -# if (test == "ADD"): -# return a + b -# elif (test == "SUB"): -# return a - b -# else: -# die("bad test name ", test) -# # exit(1) - -def randRegs(): - reg1 = randint(1,30) - reg2 = randint(1,30) - reg3 = randint(1,30) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return reg1, reg2, reg3 - -def writeVectors(storecmd): - global testnum - reg1, reg2, reg3 = randRegs() - - # t5 gets written with mtvec? - - # lines = f""" - - # li x{reg1}, 0 - # csrwi mtvec, 80002000 - # .data 00000000 - # j _done{testnum} - - # _trap{testnum}: - # csrrs x{reg1}, mcause, x0 - # ecall - - # _done{testnum}: - # add x0, x0, x0 - # """ - - #lines = - - - # https://ftp.gnu.org/old-gnu/Manuals/gas-2.9.1/html_chapter/as_7.html - - lines = f""" - li x1, 100 - li x2, 200 - add x3, x1, x2 - add x6, x3, x3 - - """ - f.write(lines) - - expected = 600 - - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - -################################## -# main body -################################## - -author = "Domenico Ottolia (dottolia@hmc.edu)" -xlens = [32, 64] -numrand = 60; - -# setup -seed(0xC395D19B9173AD42) # 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 - - imperaspath = f"""../../../imperas-riscv-tests/riscv-test-suite/rv{xlen}p/""" - basename = "WALLY-RET" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - # h = open("../testgen_header.S", "r") - # for line in h: - # f.write(line) - - # print directed and random test vectors - - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - writeVectors(storecmd) - - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - - - # print footer - # h = open("../testgen_footer.S", "r") - # for line in h: - # f.write(line) - - # Finish - # lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - # lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - # f.write(lines) - f.close() - r.close() - diff --git a/tests/testgen/privileged/testgen-TVAL.py b/tests/testgen/privileged/testgen-TVAL.py deleted file mode 100755 index b5402d0e7..000000000 --- a/tests/testgen/privileged/testgen-TVAL.py +++ /dev/null @@ -1,374 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-TVAL.py -# -# dottolia@hmc.edu 1 Mar 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -# -################################## -# DOCUMENTATION: -# -# Most of the comments explaining what everything -# does and the layout of the privileged tests -# can be found in this file -# -################################### - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def writeVectors(storecmd): - global testnum - - # Illegal Instruction - writeTest(storecmd, f, r, f""" - .fill 1, 4, 0 - """, f""" - li x23, 0 - """) - - val = (randint(0, 200) * 2) + 1 - - # Load Address Misaligned - writeTest(storecmd, f, r, f""" - lw x0, {val}(x0) - """, f""" - li x23, {val} - """) - - val = (randint(0, 200) * 2) + 1 - - # Store Address Misaligned - writeTest(storecmd, f, r, f""" - sw x0, {val}(x0) - """, f""" - li x23, {val} - """) - - - - -def writeTest(storecmd, f, r, test, expected, mode = "m", resetHander = ""): - global testnum, storeAddressOffset - - # The code we actually change for our test - lines = f""" - {expected} - csrr x25, {testMode}tval - sub x25, x25, x23 - """ - - # Boilerplate - # - # x28 is the address that our trap handler will jump to before returning. - # This is where we can do our actual tests. After we're done computing and storing - # what we want, we jump to x27, which continues with the trap handling code (look at the _j_x_trap_... labels) - # - lines = f""" - la x28, _jtest{testnum} - j _jdo{testnum} - - _jtest{testnum}: - {lines} - jr x27 - - _jdo{testnum}: - li x25, 0xDEADBEA7 - {test} - """ - - # We expect x25 to be 0 always. This is because of the code we wrote at the begining - # of this function - expected = 0 - - # Store the expected value of x25 to memory and in the .reference_output file - lines += f""" - {storecmd} x25, 0(x7) - addi x7, x7, {wordsize} - """ - - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -author = "dottolia@hmc.edu" -xlens = [32, 64] -testCount = 32; - -# setup -# Change this seed to a different constant value for every test -seed(0xC363DAEB9193AB45) # 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 - - # testMode can be m, s, and u. User mode traps are deprecated, so this should likely just be ["m", "s"] - for testMode in ["m", "s"]: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + testMode.upper() + "TVAL" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - storeAddressOffset = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - # We need to leave at least one bit in medeleg unset so that we have a way to get - # back to machine mode when the tests are complete (otherwise we'll only ever be able - # to get up to supervisor mode). - # - # So, we define a returning instruction which will be used to cause the exception that - # brings us into machine mode. The bit for this returning instruction is NOT set in - # medeleg. However, this also means that we can't test that instruction. So, we have - # two different returning instructions. - # - # Current code is written to only support ebreak and ecall. - # - # For testgen-TVAL, we don't need to test ebreak, so we can use that as the sole - # returning instruction. For others, like testgen-CAUSE, we'll need to put - # both ebreak and ecall here. - for returningInstruction in ["ebreak"]: - - # All registers used: - # x30: set to 1 if we should return to & stay in machine mode after trap, 0 otherwise - # ... - # x28: address trap handler should jump to for the test - # x27: address the test should return to after the test - # ... - # x25: value to write to memory - # ... - # x20: intermediate value in trap handler. Don't overwrite this! - # x19: mtvec old value - # x18: medeleg old value - # x17: sedeleg old value (currently unused — user mode traps deprecated) - # x16: mideleg old value - # ... - # x10 - x14 can be freely written - # ... - # x7: copy of x6. Increment this instead of using an offset on x6. - # this allows us to create more than 2048/wordlen tests. - # This is the address we write results to - # x6: Starting address we should write expected results to - # ... - # x4 & x5 can be freely written - # x3 — DO NOT WRITE ANY NON-ZERO VALUE TO THIS — test exits on ecall if x3 = 1 (x3 is gp) - # x1 & x2 can be freely written - - - - # Set up x7 and store old value of mtvec - lines = f""" - add x7, x6, x0 - csrr x19, mtvec - """ - - # Not used — user mode traps are deprecated - if testMode == "u": - lines += f""" - csrr x17, sedeleg - li x9, {"0b1100000000" if testMode == "u" else "0b0000000000"} - csrs sedeleg, x9 - """ - - # Code that will jump to the test (x28 is set in writeTest above) - testJumpCode = f""" - auipc x27, 0 - addi x27, x27, 12 - jr x28 - """ - - # Code for handling traps in different modes - # Some comments are inside of the below strings (prefixed with a #, as you might expected) - lines += f""" - # Reset x30 to 0 so we can run the tests. We'll set this to 1 when tests are completed so we stay in machine mode - li x30, 0 - - # Set up - la x1, _j_m_trap_{returningInstruction} - csrw mtvec, x1 - la x1, _j_s_trap_{returningInstruction} - csrw stvec, x1 - la x1, _j_u_trap_{returningInstruction} - # csrw utvec, x1 # user mode traps are not supported - - # Start the tests! - j _j_t_begin_{returningInstruction} - - # Machine mode traps - _j_m_trap_{returningInstruction}: - {testJumpCode if testMode == "m" else "li x25, 0xBAD00003"} - - csrrs x20, mepc, x0 - addi x20, x20, 4 - csrrw x0, mepc, x20 - bnez x30, _j_all_end_{returningInstruction} - mret - - # Supervisor mode traps - _j_s_trap_{returningInstruction}: - {testJumpCode if testMode == "s" else "li x25, 0xBAD00001"} - - csrrs x20, sepc, x0 - addi x20, x20, 4 - csrrw x0, sepc, x20 - bnez x30, _j_goto_machine_mode_{returningInstruction} - sret - - # Unused: user mode traps are no longer supported - _j_u_trap_{returningInstruction}: - {testJumpCode if testMode == "u" else "li x25, 0xBAD00000"} - - csrrs x20, uepc, x0 - addi x20, x20, 4 - csrrw x0, uepc, x20 - bnez x30, _j_goto_supervisor_mode_{returningInstruction} - uret - - # Currently unused. Just jumps to _j_goto_machine_mode. If you actually - # want to implement this, you'll likely need to reset sedeleg here - # and then cause an exception with {returningInstruction} (based on my intuition. Try that first, but I could be missing something / just wrong) - _j_goto_supervisor_mode_{returningInstruction}: - j _j_goto_machine_mode_{returningInstruction} - - _j_goto_machine_mode_{returningInstruction}: - li x30, 1 # This will cause us to branch to _j_all_end_{returningInstruction} in the machine trap handler, which we'll get into by invoking... - {returningInstruction} # ... this instruction! - - # Run the actual tests! - _j_t_begin_{returningInstruction}: - """ - - fromModeOptions = ["m", "s", "u"] if testMode == "m" else (["s", "u"] if testMode == "s" else ["u"]) - - # We don't want to delegate our returning instruction. Otherwise, we'll have no way of getting - # back to machine mode at the end! (and we need to be in machine mode to complete the tests) - medelegMask = "0b1111111111110111" if returningInstruction == "ebreak" else "0b1111000011111111" - - # Set medeleg and mideleg - lines += f""" - csrr x18, medeleg - li x9, {medelegMask if testMode == "s" or testMode == "u" else "0"} - csrw medeleg, x9 - - csrr x16, mideleg - li x9, {"0xffffffff" if testMode == "s" or testMode == "u" else "0"} - csrw mideleg, x9 - """ - - f.write(lines) - - for fromMode in fromModeOptions: - lines = "" - - # Code to bring us down to supervisor mode - if fromMode == "s" or fromMode == "u": - lines += f""" - li x1, 0b110000000000 - csrrc x31, mstatus, x1 - li x1, 0b0100000000000 - csrrs x31, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrw mepc, x1 - mret - - # We're now in supervisor mode... - """ - - # Code to bring us down to user mode - if fromMode == "u": - lines += f""" - - li x1, 0b110000000000 - csrrc x31, sstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the sret instruction - csrw sepc, x1 - sret - - # We're now in user mode... - """ - - f.write(lines) - for i in range(0,testCount): - writeVectors(storecmd) - - - # Very end of test. Bring us back up to machine mode - # We set x30 to 1, which will cause us to branch to _j_all_end in the - # machine mode trap handler, before executing the mret instruction. This will - # make us stay in machine mode. - # - # If we're currently in user mode, this will first bump us up to the supervisor mode - # trap handler, which will call returningInstruction again before it's sret instruction, - # bumping us up to machine mode - # - # Get into the trap handler by running returningInstruction (either an ecall or ebreak) - f.write(f""" - li x30, 1 - {returningInstruction} - _j_all_end_{returningInstruction}: - - # Reset trap handling csrs to old values - csrw mtvec, x19 - csrw medeleg, x18 - csrw mideleg, x16 - """) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - - diff --git a/tests/testgen/privileged/testgen-TVEC.py b/tests/testgen/privileged/testgen-TVEC.py deleted file mode 100755 index ce484c8b4..000000000 --- a/tests/testgen/privileged/testgen-TVEC.py +++ /dev/null @@ -1,473 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-TVEC.py (new) -# -# dottolia@hmc.edu 1 Mar 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -# -# -################################## -# DOCUMENTATION: -# -# The most up-to-date comments explaining what everything -# does and the layout of the privileged tests -# can be found in testgen-TVAL.py. This and -# other files do not have as many comments -# -################################### - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# setup -################################## - -areVectoredTrapsSupported = True - -################################## -# functions -################################## - -#For instruction-fetch access or page-fault exceptions on systems with variable-length instructions, mtval will contain the virtual address of the portion of the instruction that caused the fault while mepc will point to the beginning of the instruction. - -def randRegs(): - reg1 = randint(1,20) - reg2 = randint(1,20) - reg3 = randint(1,20) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return str(reg1), str(reg2), str(reg3) - -def writeVectors(storecmd, returningInstruction): - global testnum - - - # Illegal Instruction - # writeTest(storecmd, f, r, f""" - # .fill 1, 4, 0 - # """, False, 0) - - # # Breakpoint - # if returningInstruction != "ebreak": - # writeTest(storecmd, f, r, f""" - # ebreak - # """, False, 0) - - # # Load Address Misaligned - # writeTest(storecmd, f, r, f""" - # lw x0, 11(x0) - # """, False, 0) - - # # Load Access fault: False, 5 - - # # Store/AMO address misaligned - # writeTest(storecmd, f, r, f""" - # sw x0, 11(x0) - # """, False, 0) - - # # Environment call from u-mode: only for when only M and U mode enabled? - # # writeTest(storecmd, f, r, f""" - # # ecall - # # """, False, 8, "u") - if returningInstruction != "ecall": - writeTest(storecmd, f, r, f""" - ecall - """, False, 0) - - - if fromMode == "m" and testMode == "m": - expectedCode = 7 if fromMode == "m" else 5 - clintAddr = "0x2004000" - - writeTest(storecmd, f, r, f""" - li x1, 0x8 - csrrs x0, {fromMode}status, x1 - - la x18, {clintAddr} - # lw x11, 0(x18) - # li x1, 0x3fffffffffffffff - # {storecmd} x1, 0(x18) - - li x1, 0x80 - csrrs x0, {fromMode}ie, x1 - - {storecmd} x0, 0(x18) - """, True, expectedCode, f""" - li x1, 0x80 - csrrc x0, {fromMode}ie, x1 - - li x1, 0x8 - csrrc x0, {fromMode}status, x1 - - la x18, {clintAddr} - {storecmd} x0, 0(x18) - """) - - # Instruction page fault: 12 - # Load page fault: 13 - # Store/AMO page fault: 15 - - - - -def writeTest(storecmd, f, r, test, interrupt, code, resetHander = ""): - global testnum, storeAddressOffset, xlen - - expected = code - - # Boilerplate - # - # x28 is the address that our trap handler will jump to before returning. - # This is where we can do our actual tests. After we're done computing and storing - # what we want, we jump to x27, which continues with the trap handling code (look at the _j_x_trap_... labels) - # - lines = f""" - la x28, _jtest{testnum} - j _jdo{testnum} - - _jtest{testnum}: - nop - {resetHander} - jr x27 - - _jdo{testnum}: - li x25, 0xDEADBEA7 - {test} - """ - - - if not areVectoredTrapsSupported or not vectoredInterrupts: - expected = 0 - - writeGeneralTest(storecmd, f, r, lines, expected) - -def writeGeneralTest(storecmd, f, r, test, expected): - global testnum, storeAddressOffset, xlen - - lines = f""" - {test} - {storecmd} x25, {testnum * wordsize}(x6) - """ - - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - - testnum = testnum+1 - -################################## -# main body -################################## - -author = "dottolia@hmc.edu" -xlens = [32, 64] -testCount = 4; - -# setup -# Change this seed to a different constant value for every test -seed(0xC363DAEB9193AB45) # 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 - - # testMode can be m, s, and u. User mode traps are deprecated, so this should likely just be ["m", "s"] - for testMode in ["m", "s"]: - imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + testMode.upper() + "TVEC" - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - storeAddressOffset = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("../testgen_header.S", "r") - for line in h: - f.write(line) - - # Ensure MODE of *tvec (last 2 bits) is either 00 or 01 - f.write(f""" - csrr x19, {testMode}tvec - """) - - for i in range(0, 16): - i = i; - trySet = i | 0b10; - expected = trySet & 0xFFFF_FFFFD; - writeGeneralTest(storecmd, f, r, f""" - li x1, {trySet} - csrw {testMode}tvec, x1 - csrr x25, {testMode}tvec - """, expected) - - f.write(f""" - csrw {testMode}tvec, x19 - """) - - # We need to leave at least one bit in medeleg unset so that we have a way to get - # back to machine mode when the tests are complete (otherwise we'll only ever be able - # to get up to supervisor mode). - # - # So, we define a returning instruction which will be used to cause the exception that - # brings us into machine mode. The bit for this returning instruction is NOT set in - # medeleg. However, this also means that we can't test that instruction. So, we have - # two different returning instructions. - # - # Current code is written to only support ebreak and ecall. - # - # For testgen-TVAL, we don't need to test ebreak, so we can use that as the sole - # returning instruction. For others, like testgen-CAUSE, we'll need to put - # both ebreak and ecall here. - - - for returningInstruction in ["ebreak"]: - for vectoredInterrupts in [True, False]: - - # All registers used: - # x30: set to 1 if we should return to & stay in machine mode after trap, 0 otherwise - # ... - # x28: address trap handler should jump to for the test - # x27: address the test should return to after the test - # ... - # x25: value to write to memory - # ... - # x20: intermediate value in trap handler. Don't overwrite this! - # x19: mtvec old value - # x18: medeleg old value - # x17: sedeleg old value (currently unused — user mode traps deprecated) - # x16: mideleg old value - # ... - # x10 - x14 can be freely written - # ... - # x7: copy of x6. Increment this instead of using an offset on x6. - # this allows us to create more than 2048/wordlen tests. - # This is the address we write results to - # x6: Starting address we should write expected results to - # ... - # x1 - x5 can be freely written - - - - # Set up x7 and store old value of mtvec - lines = f""" - # add x7, x6, x0 - csrr x19, mtvec - """ - - # Not used — user mode traps are deprecated - if testMode == "u": - lines += f""" - csrr x17, sedeleg - li x9, {"0b1100000000" if testMode == "u" else "0b0000000000"} - csrs sedeleg, x9 - """ - - # Code that will jump to the test (x28 is set in writeTest above) - testJumpCode = f""" - auipc x27, 0 - addi x27, x27, 12 - jr x28 - """ - - beforeCode = {"m": "", "s": ""} - for pm in ["m", "s"]: - for i in range(0, 16): - beforeCode[pm] = beforeCode[pm] + f""" - nop - nop - li x25, {i} - j _j_{pm}_trap_end_{returningInstruction}_{vectoredInterrupts} - """ - - # Code for handling traps in different modes - # Some comments are inside of the below strings (prefixed with a #, as you might expected) - enableVectored = "addi x1, x1, 1" if vectoredInterrupts else "" - - lines += f""" - # Reset x30 to 0 so we can run the tests. We'll set this to 1 when tests are completed so we stay in machine mode - li x30, 0 - - # Set up - la x1, _j_m_trap_{returningInstruction}_{vectoredInterrupts} - {enableVectored} # enable/don't enable vectored interrupts - csrw mtvec, x1 - la x1, _j_s_trap_{returningInstruction}_{vectoredInterrupts} - {enableVectored} # enable/don't enable vectored interrupts - csrw stvec, x1 - la x1, _j_u_trap_{returningInstruction}_{vectoredInterrupts} - {enableVectored} # enable/don't enable vectored interrupts - # csrw utvec, x1 # user mode traps are not supported - - # Start the tests! - j _j_t_begin_{returningInstruction}_{vectoredInterrupts} - - # Machine mode traps - _j_m_trap_{returningInstruction}_{vectoredInterrupts}: - {beforeCode['m']} - - _j_m_trap_end_{returningInstruction}_{vectoredInterrupts}: - {testJumpCode} - - csrrs x20, mepc, x0 - addi x20, x20, 4 - csrrw x0, mepc, x20 - bnez x30, _j_all_end_{returningInstruction}_{vectoredInterrupts} - mret - - # Supervisor mode traps - _j_s_trap_{returningInstruction}_{vectoredInterrupts}: - {beforeCode['s']} - - _j_s_trap_end_{returningInstruction}_{vectoredInterrupts}: - {testJumpCode} - - csrrs x20, sepc, x0 - addi x20, x20, 4 - csrrw x0, sepc, x20 - bnez x30, _j_goto_machine_mode_{returningInstruction}_{vectoredInterrupts} - sret - - # Unused: user mode traps are no longer supported - _j_u_trap_{returningInstruction}_{vectoredInterrupts}: - {testJumpCode if testMode == "u" else "li x25, 0xBAD00000"} - - csrrs x20, uepc, x0 - addi x20, x20, 4 - csrrw x0, uepc, x20 - bnez x30, _j_goto_supervisor_mode_{returningInstruction}_{vectoredInterrupts} - uret - - # Currently unused. Just jumps to _j_goto_machine_mode. If you actually - # want to implement this, you'll likely need to reset sedeleg here - # and then cause an exception with {returningInstruction} (based on my intuition. Try that first, but I could be missing something / just wrong) - _j_goto_supervisor_mode_{returningInstruction}_{vectoredInterrupts}: - j _j_goto_machine_mode_{returningInstruction}_{vectoredInterrupts} - - _j_goto_machine_mode_{returningInstruction}_{vectoredInterrupts}: - li x30, 1 # This will cause us to branch to _j_all_end_{returningInstruction}_{vectoredInterrupts} in the machine trap handler, which we'll get into by invoking... - {returningInstruction} # ... this instruction! - - # Run the actual tests! - _j_t_begin_{returningInstruction}_{vectoredInterrupts}: - """ - - fromModeOptions = ["m", "s", "u"] if testMode == "m" else (["s", "u"] if testMode == "s" else ["u"]) - - # We don't want to delegate our returning instruction. Otherwise, we'll have no way of getting - # back to machine mode at the end! (and we need to be in machine mode to complete the tests) - medelegMask = "0b1111111111110111" if returningInstruction == "ebreak" else "0b1111000011111111" - - # Set medeleg and mideleg - lines += f""" - csrr x18, medeleg - li x9, {medelegMask if testMode == "s" or testMode == "u" else "0"} - csrw medeleg, x9 - - csrr x16, mideleg - li x9, {"0xffffffff" if testMode == "s" or testMode == "u" else "0"} - csrw mideleg, x9 - """ - - f.write(lines) - - for fromMode in fromModeOptions: - lines = "" - - # Code to bring us down to supervisor mode - if fromMode == "s" or fromMode == "u": - lines += f""" - li x1, 0b110000000000 - csrrc x31, mstatus, x1 - li x1, 0b0100000000000 - csrrs x31, mstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the mret instruction - csrw mepc, x1 - mret - - # We're now in supervisor mode... - """ - - # Code to bring us down to user mode - if fromMode == "u": - lines += f""" - - li x1, 0b110000000000 - csrrc x31, sstatus, x1 - - auipc x1, 0 - addi x1, x1, 16 # x1 is now right after the sret instruction - csrw sepc, x1 - sret - - # We're now in user mode... - """ - - f.write(lines) - for i in range(0,testCount): - writeVectors(storecmd, returningInstruction) - - - # Very end of test. Bring us back up to machine mode - # We set x30 to 1, which will cause us to branch to _j_all_end in the - # machine mode trap handler, before executing the mret instruction. This will - # make us stay in machine mode. - # - # If we're currently in user mode, this will first bump us up to the supervisor mode - # trap handler, which will call returningInstruction again before it's sret instruction, - # bumping us up to machine mode - # - # Get into the trap handler by running returningInstruction (either an ecall or ebreak) - f.write(f""" - li x30, 1 - li gp, 0 - {returningInstruction} - _j_all_end_{returningInstruction}_{vectoredInterrupts}: - - # Reset trap handling csrs to old values - csrw mtvec, x19 - csrw medeleg, x18 - csrw mideleg, x16 - """) - - # print footer - h = open("../testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() diff --git a/tests/testgen/testgen.py b/tests/testgen/testgen.py deleted file mode 100755 index 46bd2cb75..000000000 --- a/tests/testgen/testgen.py +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen.py -# -# David_Harris@hmc.edu 19 January 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def twoscomp(a, xlen): - amsb = a >> (xlen-1) - alsbs = ((1 << (xlen-1)) - 1) & a - if (amsb): - asigned = a - (1<