diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d77b56932..0ff49f8d3f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,8 +7,30 @@ name: ci on: [push, pull_request] jobs: - riscv-tests: - name: riscv-tests + build-riscv-tests: + name: build-riscv-tests + runs-on: ubuntu-latest + env: + RISCV: /riscv + NUM_JOBS: 4 + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: Prepare + run: | + ci/setup.sh + tar -cf tools.tar tools + tar -cf tmp.tar tmp + - name: Archive production artifacts + uses: actions/upload-artifact@v3 + with: + name: compiled-tools + path: | + tools.tar + tmp.tar + execute-riscv-tests: + name: execute-riscv-tests runs-on: ubuntu-latest strategy: matrix: @@ -16,11 +38,19 @@ jobs: target: [cv64a6_imafdc_sv39, cv64a6_imafdc_sv39_wb] env: RISCV: /riscv + needs: + build-riscv-tests steps: - uses: actions/checkout@v2 with: submodules: recursive - - name: Prepare - run: ci/setup.sh - - name: run tests - run: make run-${{ matrix.testcase}}-verilator target=${{ matrix.target }} + - name: Download a single artifact + uses: actions/download-artifact@v3 + with: + name: compiled-tools + - name: Run Tests + run: | + tar xf tools.tar + tar xf tmp.tar + source verif/regress/install-cva6.sh + make run-${{ matrix.testcase}}-verilator target=${{ matrix.target }} diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8870271e5e..e5156a0bfa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -139,6 +139,24 @@ smoke: - source verif/regress/smoke-tests.sh - !reference [.simu_after_script] +smoke-tandem: + extends: + - .fe_smoke_test + variables: + DASHBOARD_JOB_TITLE: "Smoke test $DV_SIMULATORS with tandem" + DASHBOARD_JOB_DESCRIPTION: "Short tests to challenge most architectures with most testbenchs configurations" + DASHBOARD_SORT_INDEX: 0 + DASHBOARD_JOB_CATEGORY: "Basic" + SPIKE_TANDEM: 1 + parallel: + matrix: + - DV_SIMULATORS: + - "vcs-testharness,spike" + - "vcs-uvm,spike" + script: + - source verif/regress/smoke-tests.sh + - !reference [.simu_after_script] + gen_smoke: extends: - .fe_smoke_test diff --git a/Makefile b/Makefile index b98cacd3a0..c90baa7154 100644 --- a/Makefile +++ b/Makefile @@ -25,17 +25,18 @@ VCOM ?= vcom$(questa_version) VLIB ?= vlib$(questa_version) VMAP ?= vmap$(questa_version) # verilator version -verilator ?= $(PWD)/tmp/verilator-v5.008/verilator/bin/verilator +VERILATOR_INSTALL_DIR ?= $(PWD)/tmp/verilator-v5.008/verilator/ +verilator ?= verilator # traget option target-options ?= -# additional definess +# additional defines defines ?= # test name for torture runs (binary name) test-location ?= output/test # set to either nothing or -log torture-logs := # custom elf bin to run with sim or sim-verilator -elf-bin ?= tmp/riscv-tests/build/benchmarks/dhrystone.riscv +elf_file ?= tmp/riscv-tests/build/benchmarks/dhrystone.riscv # board name for bitstream generation. Currently supported: kc705, genesys2 BOARD ?= genesys2 # root path @@ -58,7 +59,9 @@ ifndef RISCV $(error RISCV not set - please point your RISCV variable to your RISCV installation) endif -# By default assume spike resides at $(root-dir)/tools/spike prefix. +# Spike tandem mode: default to environment setting (DISABLED if envariable SPIKE_TANDEM is not set). +spike-tandem ?= $(SPIKE_TANDEM) + SPIKE_INSTALL_DIR ?= $(root-dir)/tools/spike # setting additional xilinx board parameters for the selected board @@ -79,11 +82,10 @@ $(error Unknown board - please specify a supported FPGA board) endif # spike tandem verification -ifdef spike-tandem +ifneq ($(spike-tandem),) compile_flag += -define SPIKE_TANDEM - ifndef preload - $(error Tandem verification requires preloading) - endif + CFLAGS += -I. -I$(SPIKE_INSTALL_DIR)/include/riscv + defines += +SPIKE_TANDEM=1 endif # target takes one of the following cva6 hardware configuration: @@ -123,7 +125,7 @@ test_pkg := $(wildcard tb/test/*/*sequence_pkg.sv*) \ dpi := $(patsubst corev_apu/tb/dpi/%.cc, ${dpi-library}/%.o, $(wildcard corev_apu/tb/dpi/*.cc)) # filter spike stuff if tandem is not activated -ifndef spike-tandem +ifeq ($(spike-tandem),) dpi := $(filter-out ${dpi-library}/spike.o ${dpi-library}/sim_spike.o, $(dpi)) endif @@ -131,6 +133,7 @@ dpi_hdr := $(wildcard corev_apu/tb/dpi/*.h) dpi_hdr := $(addprefix $(root-dir), $(dpi_hdr)) CFLAGS += -I$(QUESTASIM_HOME)/include \ -I$(VCS_HOME)/include \ + -I$(VL_INC_DIR)/vltstd \ -I$(RISCV)/include \ -I$(SPIKE_INSTALL_DIR)/include \ -std=c++17 -I../corev_apu/tb/dpi -O3 @@ -141,13 +144,10 @@ else $(warning XCELIUM_HOME not set which is necessary for compiling DPIs when using XCELIUM) endif -ifdef spike-tandem - CFLAGS += -Itb/riscv-isa-sim/install/include/spike -endif - - # this list contains the standalone components src := core/include/$(target)_config_pkg.sv \ + $(if $(spike-tandem),verif/tb/core/rvfi_pkg.sv) \ + $(if $(spike-tandem),corev_apu/tb/common/spike.sv) \ corev_apu/src/ariane.sv \ $(wildcard corev_apu/bootrom/*.sv) \ $(wildcard corev_apu/clint/*.sv) \ @@ -215,6 +215,7 @@ fpga_src := $(addprefix $(root-dir), $(fpga_src)) # look for testbenches tbs := core/include/$(target)_config_pkg.sv corev_apu/tb/ariane_tb.sv corev_apu/tb/ariane_testharness.sv + tbs := $(addprefix $(root-dir), $(tbs)) # RISCV asm tests and benchmark setup (used for CI) @@ -233,7 +234,9 @@ riscv-fp-tests := $(shell xargs printf '\n%s' < $(riscv-fp-tests-list riscv-benchmarks := $(shell xargs printf '\n%s' < $(riscv-benchmarks-list) | cut -b 1-) # Search here for include files (e.g.: non-standalone components) -incdir := vendor/pulp-platform/common_cells/include/ vendor/pulp-platform/axi/include/ corev_apu/register_interface/include/ +incdir := $(CVA6_REPO_DIR)/vendor/pulp-platform/common_cells/include/ $(CVA6_REPO_DIR)/vendor/pulp-platform/axi/include/ \ + $(CVA6_REPO_DIR)/corev_apu/register_interface/include/ $(CVA6_REPO_DIR)/corev_apu/tb/common/ \ + $(CVA6_REPO_DIR)/vendor/pulp-platform/axi/include/ $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_agents/uvma_rvfi/ # Compile and sim flags compile_flag += +cover=bcfst+/dut -incr -64 -nologo -quiet -suppress 13262 -permissive -svinputport=compat +define+$(defines) @@ -263,11 +266,11 @@ endif # we want to preload the memories ifdef preload questa-cmd += +PRELOAD=$(preload) - elf-bin = none + elf_file = none endif ifdef spike-tandem - questa-cmd += -gblso tb/riscv-isa-sim/install/lib/libriscv.so + questa-cmd += -gblso $(SPIKE_INSTALL_DIR)/lib/libriscv.so endif # remote bitbang is enabled @@ -280,16 +283,19 @@ endif vcs_build: $(dpi-library)/ariane_dpi.so mkdir -p $(vcs-library) cd $(vcs-library) &&\ - vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog +define+$(defines) -assert svaext -f ../core/Flist.cva6 &&\ + vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog +define+$(defines) -assert svaext -f ../core/Flist.cva6 $(list_incdir) &&\ vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog +define+$(defines) $(filter %.sv,$(ariane_pkg)) +incdir+core/include/+$(VCS_HOME)/etc/uvm-1.2/dpi &&\ vhdlan $(if $(VERDI), -kdb,) -full64 -nc $(filter %.vhd,$(uart_src)) &&\ - vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog -assert svaext +define+$(defines) $(filter %.sv,$(src)) +incdir+../vendor/pulp-platform/common_cells/include/+../vendor/pulp-platform/axi/include/+../corev_apu/register_interface/include/ &&\ + vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog -assert svaext +define+$(defines) +incdir+$(VCS_HOME)/etc/uvm/src $(VCS_HOME)/etc/uvm/src/uvm_pkg.sv $(filter %.sv,$(src)) $(list_incdir) &&\ vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog -ntb_opts uvm-1.2 &&\ - vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog -ntb_opts uvm-1.2 $(tbs) +define+$(defines) +incdir+../vendor/pulp-platform/axi/include/ &&\ + vlogan $(if $(VERDI), -kdb,) -full64 -nc -sverilog -ntb_opts uvm-1.2 $(tbs) +define+$(defines) $(list_incdir) &&\ vcs $(if $(VERDI), -kdb -debug_access+all -lca,) -full64 -timescale=1ns/1ns -ntb_opts uvm-1.2 work.ariane_tb -error="IWNF" vcs: vcs_build - cd $(vcs-library) && ./simv $(if $(VERDI), -verdi -do $(root-dir)/util/init_testharness.do,) +permissive -sv_lib ../work-dpi/ariane_dpi +PRELOAD=$(elf-bin) +permissive-off ++$(elf-bin)| tee vcs.log + cd $(vcs-library) && \ + ./simv +permissive $(if $(VERDI), -verdi -do $(root-dir)/init_testharness.do,) \ + +elf_file=$(elf_file) ++$(elf_file) $(if $(spike-tandem),-sv_lib $(SPIKE_INSTALL_DIR)/libriscv) \ + -sv_lib ../work-dpi/ariane_dpi | tee vcs.log # Build the TB and module using QuestaSim build: $(library) $(library)/.build-srcs $(library)/.build-tb $(dpi-library)/ariane_dpi.so @@ -322,20 +328,20 @@ $(dpi-library)/%.o: corev_apu/tb/dpi/%.cc $(dpi_hdr) $(dpi-library)/ariane_dpi.so: $(dpi) mkdir -p $(dpi-library) # Compile C-code and generate .so file - $(CXX) -shared -m64 -o $(dpi-library)/ariane_dpi.so $? -L$(RISCV)/lib -L$(SPIKE_INSTALL_DIR)/lib -Wl,-rpath,$(RISCV)/lib -Wl,-rpath,$(SPIKE_INSTALL_DIR)/lib -lfesvr + $(CXX) -shared -m64 -o $(dpi-library)/ariane_dpi.so $? -L$(RISCV)/lib -L$(SPIKE_INSTALL_DIR)/lib -Wl,-rpath,$(RISCV)/lib -Wl,-rpath,$(SPIKE_INSTALL_DIR)/lib -lfesvr -lriscv # single test runs on Questa can be started by calling make , e.g. make towers.riscv # the test names are defined in ci/riscv-asm-tests.list, and in ci/riscv-benchmarks.list # if you want to run in batch mode, use make batch-mode=1 -# alternatively you can call make sim elf-bin= in order to load an arbitrary binary +# alternatively you can call make sim elf_file= in order to load an arbitrary binary generate-trace-vsim: - make sim preload=$(preload) elf-bin= batch-mode=1 + make sim preload=$(preload) elf_file= batch-mode=1 make generate-trace sim: build $(VSIM) +permissive $(questa-flags) $(questa-cmd) -lib $(library) +MAX_CYCLES=$(max_cycles) +UVM_TESTNAME=$(test_case) \ +BASEDIR=$(riscv-test-dir) $(uvm-flags) $(QUESTASIM_FLAGS) -gblso $(SPIKE_INSTALL_DIR)/lib/libfesvr.so -sv_lib $(dpi-library)/ariane_dpi \ - ${top_level}_optimized +permissive-off ++$(elf-bin) ++$(target-options) | tee sim.log + ${top_level}_optimized +permissive-off ++$(elf_file) ++$(target-options) | tee sim.log $(riscv-asm-tests): build $(VSIM) +permissive $(questa-flags) $(questa-cmd) -lib $(library) +max-cycles=$(max_cycles) +UVM_TESTNAME=$(test_case) \ @@ -463,7 +469,7 @@ xrun_sim: xrun_comp +UVM_TESTNAME=$(test_case) \ -l $(XRUN_RUN_LOG) \ +permissive-off \ - ++$(elf-bin) + ++$(elf_file) #-e "set_severity_pack_assert_off {warning}; set_pack_assert_off {numeric_std}" TODO: This will remove assertion warning at the beginning of the simulation. @@ -561,8 +567,9 @@ verilate_command := $(verilator) --no-timing verilator_config.vlt $(if $(DEBUG), --trace-structs,) \ $(if $(TRACE_COMPACT), --trace-fst $(VL_INC_DIR)/verilated_fst_c.cpp) \ $(if $(TRACE_FAST), --trace $(VL_INC_DIR)/verilated_vcd_c.cpp) \ - -LDFLAGS "-L$(RISCV)/lib -L$(SPIKE_INSTALL_DIR)/lib -Wl,-rpath,$(RISCV)/lib -Wl,-rpath,$(SPIKE_INSTALL_DIR)/lib -lfesvr$(if $(PROFILE), -g -pg,) -lpthread $(if $(TRACE_COMPACT), -lz,)" \ + -LDFLAGS "-L$(RISCV)/lib -L$(SPIKE_INSTALL_DIR)/lib -Wl,-rpath,$(RISCV)/lib -Wl,-rpath,$(SPIKE_INSTALL_DIR)/lib -lfesvr -lriscv $(if $(PROFILE), -g -pg,) -lpthread $(if $(TRACE_COMPACT), -lz,)" \ -CFLAGS "$(CFLAGS)$(if $(PROFILE), -g -pg,) -DVL_DEBUG" \ + $(if $(SPIKE_TANDEM), +define+SPIKE_TANDEM, ) \ --cc --vpi \ $(list_incdir) --top-module ariane_testharness \ --threads-dpi none \ @@ -570,7 +577,6 @@ verilate_command := $(verilator) --no-timing verilator_config.vlt --exe corev_apu/tb/ariane_tb.cpp corev_apu/tb/dpi/SimDTM.cc corev_apu/tb/dpi/SimJTAG.cc \ corev_apu/tb/dpi/remote_bitbang.cc corev_apu/tb/dpi/msim_helper.cc - # User Verilator, at some point in the future this will be auto-generated verilate: @echo "[Verilator] Building Model$(if $(PROFILE), for Profiling,)" @@ -578,7 +584,7 @@ verilate: cd $(ver-library) && $(MAKE) -j${NUM_JOBS} -f Variane_testharness.mk sim-verilator: verilate - $(ver-library)/Variane_testharness $(elf-bin) + $(ver-library)/Variane_testharness $(elf_file) $(addsuffix -verilator,$(riscv-asm-tests)): verilate $(ver-library)/Variane_testharness $(riscv-test-dir)/$(subst -verilator,,$@) diff --git a/ci/setup.sh b/ci/setup.sh index 47b1a52874..0340187188 100755 --- a/ci/setup.sh +++ b/ci/setup.sh @@ -1,6 +1,7 @@ #!/bin/bash set -e -ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +export ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +export ROOT_PROJECT=$ROOT export PATH=$RISCV/bin:/bin:$PATH export LIBRARY_PATH=$RISCV/lib @@ -15,13 +16,14 @@ sudo apt install device-tree-compiler ci/make-tmp.sh -ci/install-verilator.sh - sudo mkdir -p $RISCV && sudo chmod 777 $RISCV RISCV64_UNKNOWN_ELF_GCC=riscv64-unknown-elf-gcc-8.3.0-2020.04.0-x86_64-linux-ubuntu14.tar.gz if [ ! -f "$RISCV64_UNKNOWN_ELF_GCC" ]; then wget https://static.dev.sifive.com/dev-tools/$RISCV64_UNKNOWN_ELF_GCC fi tar -x -f $RISCV64_UNKNOWN_ELF_GCC --strip-components=1 -C $RISCV -ci/install-fesvr.sh + +sudo apt install libfl-dev help2man + +verif/regress/install-cva6.sh ci/build-riscv-tests.sh diff --git a/core/csr_regfile.sv b/core/csr_regfile.sv index 0c43864e40..e500ac834d 100644 --- a/core/csr_regfile.sv +++ b/core/csr_regfile.sv @@ -562,7 +562,7 @@ module csr_regfile end instret_d = instret; // increment the cycle count - if (ENABLE_CYCLE_COUNT && !mcountinhibit_q[0]) cycle_d = cycle_q + 1'b1; + if (!mcountinhibit_q[0]) cycle_d = cycle_q + 1'b1; else cycle_d = instret; end diff --git a/core/cva6.sv b/core/cva6.sv index c0b6d8d247..6651585a01 100644 --- a/core/cva6.sv +++ b/core/cva6.sv @@ -1348,27 +1348,15 @@ module cva6 if (IsRVFI) begin always_comb begin for (int i = 0; i < CVA6ExtendCfg.NrCommitPorts; i++) begin - logic exception, mem_exception; + logic exception; exception = commit_instr_id_commit[i].valid && ex_commit.valid; - mem_exception = exception && - (ex_commit.cause == riscv::INSTR_ADDR_MISALIGNED || - ex_commit.cause == riscv::INSTR_ACCESS_FAULT || - ex_commit.cause == riscv::ILLEGAL_INSTR || - ex_commit.cause == riscv::LD_ADDR_MISALIGNED || - ex_commit.cause == riscv::LD_ACCESS_FAULT || - ex_commit.cause == riscv::ST_ADDR_MISALIGNED || - ex_commit.cause == riscv::ST_ACCESS_FAULT || - ex_commit.cause == riscv::INSTR_PAGE_FAULT || - ex_commit.cause == riscv::LOAD_PAGE_FAULT || - ex_commit.cause == riscv::STORE_PAGE_FAULT); - // when rvfi_valid, the instruction is executed rvfi_o[i].valid = (commit_ack[i] && !ex_commit.valid) || (exception && (ex_commit.cause == riscv::ENV_CALL_MMODE || ex_commit.cause == riscv::ENV_CALL_SMODE || ex_commit.cause == riscv::ENV_CALL_UMODE)); - rvfi_o[i].insn = ex_commit.valid ? ex_commit.tval[31:0] : commit_instr_id_commit[i].ex.tval[31:0]; + rvfi_o[i].insn = ex_commit.valid ? ex_commit.tval[31:0] : commit_instr_id_commit[i].ex.tval[31:0]; // when trap, the instruction is not executed - rvfi_o[i].trap = mem_exception; + rvfi_o[i].trap = exception; rvfi_o[i].cause = ex_commit.cause; rvfi_o[i].mode = (CVA6Cfg.DebugEn && debug_mode) ? 2'b10 : priv_lvl; rvfi_o[i].ixl = riscv::XLEN == 64 ? 2 : 1; diff --git a/core/decoder.sv b/core/decoder.sv index e344c9ce74..0740906d84 100644 --- a/core/decoder.sv +++ b/core/decoder.sv @@ -183,7 +183,7 @@ module decoder end // WFI 12'b1_0000_0101: begin - if (ENABLE_WFI) instruction_o.op = ariane_pkg::WFI; + instruction_o.op = ariane_pkg::WFI; // if timeout wait is set, trap on an illegal instruction in S Mode // (after 0 cycles timeout) if (CVA6Cfg.RVS && priv_lvl_i == riscv::PRIV_LVL_S && tw_i) begin diff --git a/core/include/ariane_pkg.sv b/core/include/ariane_pkg.sv index ddeed84539..446f609a61 100644 --- a/core/include/ariane_pkg.sv +++ b/core/include/ariane_pkg.sv @@ -107,22 +107,17 @@ package ariane_pkg; // enables a commit log which matches spikes commit log format for easier trace comparison localparam bit ENABLE_SPIKE_COMMIT_LOG = 1'b1; - // ------------- Dangerouse ------------- + // ------------- Dangerous ------------- // if set to zero a flush will not invalidate the cache-lines, in a single core environment // where coherence is not necessary this can improve performance. This needs to be switched on // when more than one core is in a system localparam logic INVALIDATE_ON_FLUSH = 1'b1; + `ifdef SPIKE_TANDEM - // enable performance cycle counter, if set to zero mcycle will be incremented - // with instret (non RISC-V conformal) - localparam bit ENABLE_CYCLE_COUNT = 1'b0; - // mark WIF as nop - localparam bit ENABLE_WFI = 1'b0; - // Spike zeros tval on all exception except memory faults + // Spike still places 0 in TVAL for ENV_CALL_* exceptions. + // This may eventually go away when Spike starts to handle TVAL for *all* exceptions. localparam bit ZERO_TVAL = 1'b1; `else - localparam bit ENABLE_CYCLE_COUNT = 1'b1; - localparam bit ENABLE_WFI = 1'b1; localparam bit ZERO_TVAL = 1'b0; `endif // read mask for SSTATUS over MMSTATUS diff --git a/corev_apu/tb/ariane_tb.cpp b/corev_apu/tb/ariane_tb.cpp index d233950178..736f8974f9 100644 --- a/corev_apu/tb/ariane_tb.cpp +++ b/corev_apu/tb/ariane_tb.cpp @@ -62,6 +62,12 @@ void handle_sigterm(int sig) { dtm->stop(); } + +extern "C" void read_elf(const char* filename); +extern "C" int64_t read_symbol(const char* symbol, uint64_t* address); +extern "C" char get_section (long long* address, long long* len); +extern "C" void read_section_void(long long address, void * buffer, uint64_t size = 0); + // Called by $time in Verilog converts to double, to match what SystemC does double sc_time_stamp () { return main_time; @@ -285,11 +291,7 @@ int main(int argc, char **argv) { std::unique_ptr top(new Variane_testharness); - // Use an hitf hexwriter to read the binary data. - htif_hexwriter_t htif(0x0, 1, -1); - memif_t memif(&htif); - reg_t entry; - load_elf(htif_argv[1], &memif, &entry); + read_elf(htif_argv[1]); #if VM_TRACE Verilated::traceEverOn(true); // Verilator must compute traced signals @@ -335,15 +337,22 @@ int main(int argc, char **argv) { top->rst_ni = 1; // Preload memory. - size_t mem_size = 0xFFFFFF; #if (VERILATOR_VERSION_INTEGER >= 5000000) // Verilator v5: Use rootp pointer and .data() accessor. - memif.read(0x80000000, mem_size, (void *)top->rootp->ariane_testharness__DOT__i_sram__DOT__gen_cut__BRA__0__KET____DOT__i_tc_sram_wrapper__DOT__i_tc_sram__DOT__sram.m_storage); +#define MEM top->rootp->ariane_testharness__DOT__i_sram__DOT__gen_cut__BRA__0__KET____DOT__i_tc_sram_wrapper__DOT__i_tc_sram__DOT__sram.m_storage #else // Verilator v4 - memif.read(0x80000000, mem_size, (void *)top->ariane_testharness__DOT__i_sram__DOT__gen_cut__BRA__0__KET____DOT__i_tc_sram_wrapper__DOT__i_tc_sram__DOT__sram); +#define MEM top->ariane_testharness__DOT__i_sram__DOT__gen_cut__BRA__0__KET____DOT__i_tc_sram_wrapper__DOT__i_tc_sram__DOT__sram #endif - // memif.read(0x84000000, mem_size, (void *)top->ariane_testharness__DOT__i_sram__DOT__gen_cut__BRA__0__KET____DOT__gen_mem__DOT__gen_mem_user__DOT__i_tc_sram_wrapper_user__DOT__i_tc_sram__DOT__sram); + long long addr; + long long len; + + size_t mem_size = 0xFFFFFF; + while(get_section(&addr, &len)) + { + if (addr == 0x80000000) + read_section_void(addr, (void *) MEM , mem_size); + } while (!dtm->done() && !jtag->done() && !(top->exit_o & 0x1)) { top->clk_i = 0; diff --git a/corev_apu/tb/ariane_tb.sv b/corev_apu/tb/ariane_tb.sv index 67b7ea8580..8f3ab00222 100644 --- a/corev_apu/tb/ariane_tb.sv +++ b/corev_apu/tb/ariane_tb.sv @@ -24,7 +24,7 @@ import uvm_pkg::*; import "DPI-C" function read_elf(input string filename); import "DPI-C" function byte get_section(output longint address, output longint len); -import "DPI-C" context function void read_section(input longint address, inout byte buffer[]); +import "DPI-C" context function void read_section_sv(input longint address, inout byte buffer[]); module ariane_tb; @@ -91,26 +91,6 @@ module ariane_tb; .exit_o ); -`ifdef SPIKE_TANDEM - spike #( - .CVA6Cfg ( CVA6Cfg ), - .Size ( NUM_WORDS * 8 ) - ) i_spike ( - .clk_i, - .rst_ni, - .clint_tick_i ( rtc_i ), - .commit_instr_i ( dut.i_ariane.commit_instr_id_commit ), - .commit_ack_i ( dut.i_ariane.commit_ack ), - .exception_i ( dut.i_ariane.ex_commit ), - .waddr_i ( dut.i_ariane.waddr_commit_id ), - .wdata_i ( dut.i_ariane.wdata_commit_id ), - .priv_lvl_i ( dut.i_ariane.priv_lvl ) - ); - initial begin - $display("Running binary in tandem mode"); - end -`endif - // Clock process initial begin clk_i = 1'b0; @@ -158,7 +138,7 @@ module ariane_tb; automatic logic [7:0][7:0] mem_row; longint address, len; byte buffer[]; - void'(uvcl.get_arg_value("+PRELOAD=", binary)); + void'(uvcl.get_arg_value("+elf_file=", binary)); if (binary != "") begin `uvm_info( "Core Test", $sformatf("Preloading ELF: %s", binary), UVM_LOW) @@ -170,10 +150,9 @@ module ariane_tb; // while there are more sections to process while (get_section(address, len)) begin automatic int num_words = (len+7)/8; - `uvm_info( "Core Test", $sformatf("Loading Address: %x, Length: %x", address, len), -UVM_LOW) + `uvm_info( "Core Test", $sformatf("Loading Address: %x, Length: %x", address, len), UVM_LOW) buffer = new [num_words*8]; - void'(read_section(address, buffer)); + void'(read_section_sv(address, buffer)); // preload memories // 64-bit for (int i = 0; i < num_words; i++) begin diff --git a/corev_apu/tb/ariane_testharness.sv b/corev_apu/tb/ariane_testharness.sv index 5bfa842819..6c395b29fc 100644 --- a/corev_apu/tb/ariane_testharness.sv +++ b/corev_apu/tb/ariane_testharness.sv @@ -584,12 +584,7 @@ module ariane_testharness #( .AxiIdWidth ( ariane_axi_soc::IdWidthSlave ), .AxiUserWidth ( AXI_USER_WIDTH ), `ifndef VERILATOR - // disable UART when using Spike, as we need to rely on the mockuart - `ifdef SPIKE_TANDEM - .InclUART ( 1'b0 ), - `else .InclUART ( 1'b1 ), - `endif `else .InclUART ( 1'b0 ), `endif @@ -691,6 +686,22 @@ module ariane_testharness #( .end_of_test_o(rvfi_exit) ); +`ifdef SPIKE_TANDEM + spike #( + .CVA6Cfg ( CVA6Cfg ), + .rvfi_instr_t(rvfi_instr_t) + ) i_spike ( + .clk_i, + .rst_ni, + .clint_tick_i ( rtc_i ), + .rvfi_i ( rvfi ) + ); + initial begin + $display("Running binary in tandem mode"); + end +`endif + + `ifdef AXI_SVA // AXI 4 Assertion IP integration - You will need to get your own copy of this IP if you want // to use it diff --git a/corev_apu/tb/common/spike.sv b/corev_apu/tb/common/spike.sv index eceab9c61b..0b40f4d451 100644 --- a/corev_apu/tb/common/spike.sv +++ b/corev_apu/tb/common/spike.sv @@ -12,111 +12,91 @@ // Date: 3/11/2018 // Description: Wrapped Spike Model for Tandem Verification -import uvm_pkg::*; +import ariane_pkg::*; +import rvfi_pkg::*; -`include "uvm_macros.svh" - -import "DPI-C" function int spike_create(string filename, longint unsigned dram_base, int unsigned size); - -typedef riscv::commit_log_t riscv_commit_log_t; -import "DPI-C" function void spike_tick(output riscv_commit_log_t commit_log); - -import "DPI-C" function void clint_tick(); +import "DPI-C" function void spike_step(inout st_rvfi rvfi); module spike #( - parameter longint unsigned DramBase = 'h8000_0000, - parameter int unsigned Size = 64 * 1024 * 1024 // 64 Mega Byte + parameter config_pkg::cva6_cfg_t CVA6Cfg = cva6_config_pkg::cva6_cfg, + parameter type rvfi_instr_t = struct packed { + logic [config_pkg::NRET-1:0] valid; + logic [config_pkg::NRET*64-1:0] order; + logic [config_pkg::NRET*config_pkg::ILEN-1:0] insn; + logic [config_pkg::NRET-1:0] trap; + logic [config_pkg::NRET*riscv::XLEN-1:0] cause; + logic [config_pkg::NRET-1:0] halt; + logic [config_pkg::NRET-1:0] intr; + logic [config_pkg::NRET*2-1:0] mode; + logic [config_pkg::NRET*2-1:0] ixl; + logic [config_pkg::NRET*5-1:0] rs1_addr; + logic [config_pkg::NRET*5-1:0] rs2_addr; + logic [config_pkg::NRET*riscv::XLEN-1:0] rs1_rdata; + logic [config_pkg::NRET*riscv::XLEN-1:0] rs2_rdata; + logic [config_pkg::NRET*5-1:0] rd_addr; + logic [config_pkg::NRET*riscv::XLEN-1:0] rd_wdata; + logic [config_pkg::NRET*riscv::XLEN-1:0] pc_rdata; + logic [config_pkg::NRET*riscv::XLEN-1:0] pc_wdata; + logic [config_pkg::NRET*riscv::VLEN-1:0] mem_addr; + logic [config_pkg::NRET*riscv::PLEN-1:0] mem_paddr; + logic [config_pkg::NRET*(riscv::XLEN/8)-1:0] mem_rmask; + logic [config_pkg::NRET*(riscv::XLEN/8)-1:0] mem_wmask; + logic [config_pkg::NRET*riscv::XLEN-1:0] mem_rdata; + logic [config_pkg::NRET*riscv::XLEN-1:0] mem_wdata; + }, + parameter longint unsigned DramBase = 'h8000_0000, + parameter int unsigned Size = 64 * 1024 * 1024 // 64 Mega Byte )( - input logic clk_i, - input logic rst_ni, - input logic clint_tick_i, - input ariane_pkg::scoreboard_entry_t [CVA6Cfg.NrCommitPorts-1:0] commit_instr_i, - input logic [CVA6Cfg.NrCommitPorts-1:0] commit_ack_i, - input ariane_pkg::exception_t exception_i, - input logic [CVA6Cfg.NrCommitPorts-1:0][4:0] waddr_i, - input logic [CVA6Cfg.NrCommitPorts-1:0][63:0] wdata_i, - input riscv::priv_lvl_t priv_lvl_i + input logic clk_i, + input logic rst_ni, + input logic clint_tick_i, + input rvfi_instr_t[CVA6Cfg.NrCommitPorts-1:0] rvfi_i ); - static uvm_cmdline_processor uvcl = uvm_cmdline_processor::get_inst(); - string binary = ""; - - logic fake_clk; - - logic clint_tick_q, clint_tick_qq, clint_tick_qqq, clint_tick_qqqq; + string rtl_isa = ""; initial begin - void'(uvcl.get_arg_value("+PRELOAD=", binary)); - assert(binary != "") else $error("We need a preloaded binary for tandem verification"); - void'(spike_create(binary, DramBase, Size)); + rvfi_initialize_spike('h1); end - riscv_commit_log_t commit_log; - logic [31:0] instr; + st_rvfi t_core, t_reference_model; + logic [63:0] pc64; + logic [31:0] rtl_instr; + logic [31:0] spike_instr; + string cause; + string instr; always_ff @(posedge clk_i) begin if (rst_ni) begin - for (int i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin - if ((commit_instr_i[i].valid && commit_ack_i[i]) || (commit_instr_i[i].valid && exception_i.valid)) begin - spike_tick(commit_log); - instr = (commit_log.instr[1:0] != 2'b11) ? {16'b0, commit_log.instr[15:0]} : commit_log.instr; - // $display("\x1B[32m%h %h\x1B[0m", commit_log.pc, instr); - // $display("%p", commit_log); - // $display("\x1B[37m%h %h\x1B[0m", commit_instr_i[i].pc, commit_instr_i[i].ex.tval[31:0]); - assert (commit_log.pc === commit_instr_i[i].pc) else begin - $warning("\x1B[33m[Tandem] PCs Mismatch\x1B[0m"); - // $stop; - end - assert (commit_log.was_exception === exception_i.valid) else begin - $warning("\x1B[33m[Tandem] Exception not detected\x1B[0m"); - // $stop; - $display("Spike: %p", commit_log); - $display("Ariane: %p", commit_instr_i[i]); - end - if (!exception_i.valid) begin - assert (commit_log.priv === priv_lvl_i) else begin - $warning("\x1B[33m[Tandem] Privilege level mismatches\x1B[0m"); - // $stop; - $display("\x1B[37m %2d == %2d @ PC %h\x1B[0m", priv_lvl_i, commit_log.priv, commit_log.pc); - end - assert (instr === commit_instr_i[i].ex.tval) else begin - $warning("\x1B[33m[Tandem] Decoded instructions mismatch\x1B[0m"); - // $stop; - $display("\x1B[37m%h === %h @ PC %h\x1B[0m", commit_instr_i[i].ex.tval, instr, commit_log.pc); - end - // TODO(zarubaf): Adapt for floating point instructions - if (commit_instr_i[i].rd != 0) begin - // check the return value - // $display("\x1B[37m%h === %h\x1B[0m", commit_instr_i[i].rd, commit_log.rd); - assert (waddr_i[i] === commit_log.rd) else begin - $warning("\x1B[33m[Tandem] Destination register mismatches\x1B[0m"); - // $stop; - end - assert (wdata_i[i] === commit_log.data) else begin - $warning("\x1B[33m[Tandem] Write back data mismatches\x1B[0m"); - $display("\x1B[37m%h === %h @ PC %h\x1B[0m", wdata_i[i], commit_log.data, commit_log.pc); - end - end - end + + if (rvfi_i[i].valid || rvfi_i[i].trap) begin + spike_step(t_reference_model); + t_core.order = rvfi_i[i].order; + t_core.insn = rvfi_i[i].insn; + t_core.trap = rvfi_i[i].trap; + t_core.cause = rvfi_i[i].cause; + t_core.halt = rvfi_i[i].halt; + t_core.intr = rvfi_i[i].intr; + t_core.mode = rvfi_i[i].mode; + t_core.ixl = rvfi_i[i].ixl; + t_core.rs1_addr = rvfi_i[i].rs1_addr; + t_core.rs2_addr = rvfi_i[i].rs2_addr; + t_core.rs1_rdata = rvfi_i[i].rs1_rdata; + t_core.rs2_rdata = rvfi_i[i].rs2_rdata; + t_core.rd1_addr = rvfi_i[i].rd_addr; + t_core.rd1_wdata = rvfi_i[i].rd_wdata; + t_core.pc_rdata = rvfi_i[i].pc_rdata; + t_core.pc_wdata = rvfi_i[i].pc_wdata; + t_core.mem_addr = rvfi_i[i].mem_addr; + t_core.mem_rmask = rvfi_i[i].mem_rmask; + t_core.mem_wmask = rvfi_i[i].mem_wmask; + t_core.mem_rdata = rvfi_i[i].mem_rdata; + t_core.mem_wdata = rvfi_i[i].mem_wdata; + + rvfi_compare(t_core, t_reference_model); end end end end - - // we want to schedule the timer increment at the end of this cycle - assign #1ps fake_clk = clk_i; - - always_ff @(posedge fake_clk) begin - clint_tick_q <= clint_tick_i; - clint_tick_qq <= clint_tick_q; - clint_tick_qqq <= clint_tick_qq; - clint_tick_qqqq <= clint_tick_qqq; - end - - always_ff @(posedge clint_tick_qqqq) begin - if (rst_ni) begin - void'(clint_tick()); - end - end endmodule diff --git a/corev_apu/tb/dpi/sim_spike.cc b/corev_apu/tb/dpi/sim_spike.cc deleted file mode 100644 index f82f0905d5..0000000000 --- a/corev_apu/tb/dpi/sim_spike.cc +++ /dev/null @@ -1,135 +0,0 @@ -// See LICENSE for license details. - -#include "sim_spike.h" -#include "mmu.h" -#include "dts.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -sim_spike_t::sim_spike_t(const char* isa, size_t nprocs, - std::vector> mems, - const std::vector& args) - : mems(mems), procs(std::max(nprocs, size_t(1))), - current_step(0), current_proc(0), debug(false), log(true), - histogram_enabled(false), dtb_enabled(true), remote_bitbang(NULL) -{ - - for (auto& x : mems) - bus.add_device(x.first, x.second); - - debug_mmu = new mmu_t(this, NULL); - - for (size_t i = 0; i < procs.size(); i++) { - procs[i] = new processor_t(isa, this, i, false); - } - - clint.reset(new clint_t(procs)); - // we need to bring the clint to a reproducible default value - clint.get()->reset(); - bus.add_device(CLINT_BASE, clint.get()); - uart.reset(new uart_t()); - bus.add_device(UART_BASE, uart.get()); - make_bootrom(); - set_procs_debug(true); -} - -sim_spike_t::~sim_spike_t() -{ - for (size_t i = 0; i < procs.size(); i++) - delete procs[i]; - delete debug_mmu; -} - -commit_log_t sim_spike_t::tick(size_t n) -{ - commit_log_t commit_log; - - reg_t pc = procs[0]->get_state()->pc; - auto& reg = procs[0]->get_state()->log_reg_write; - // execute instruction - procs[0]->step(n); - int priv = procs[0]->get_state()->last_inst_priv; - int xlen = procs[0]->get_state()->last_inst_xlen; - int flen = procs[0]->get_state()->last_inst_flen; - - commit_log.priv = priv; - commit_log.pc = pc; - commit_log.is_fp = reg.addr & 1; - commit_log.rd = reg.addr >> 1; - commit_log.data = reg.data.v[0]; - commit_log.instr = procs[0]->get_state()->last_insn; - commit_log.was_exception = procs[0]->get_state()->was_exception; - - return commit_log; -} - -void sim_spike_t::clint_tick() { - clint->increment(1); -} - -void sim_spike_t::set_debug(bool value) -{ - debug = value; -} - -void sim_spike_t::set_log(bool value) -{ - log = value; -} - -void sim_spike_t::set_histogram(bool value) -{ - histogram_enabled = value; - for (size_t i = 0; i < procs.size(); i++) { - procs[i]->set_histogram(histogram_enabled); - } -} - -void sim_spike_t::set_procs_debug(bool value) -{ - for (size_t i=0; i< procs.size(); i++) - procs[i]->set_debug(value); -} - -bool sim_spike_t::mmio_load(reg_t addr, size_t len, uint8_t* bytes) -{ - if (addr + len < addr) - return false; - return bus.load(addr, len, bytes); -} - -bool sim_spike_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes) -{ - if (addr + len < addr) - return false; - return bus.store(addr, len, bytes); -} - -void sim_spike_t::make_bootrom() -{ - start_pc = 0x80000000; - - #include "bootrom.h" - - std::vector rom((char*)reset_vec, (char*)reset_vec + sizeof(reset_vec)); - - boot_rom.reset(new rom_device_t(rom)); - bus.add_device(DEFAULT_RSTVEC, boot_rom.get()); -} - -char* sim_spike_t::addr_to_mem(reg_t addr) { - auto desc = bus.find_device(addr); - if (auto mem = dynamic_cast(desc.second)) - if (addr - desc.first < mem->size()) - return mem->contents() + (addr - desc.first); - return NULL; -} \ No newline at end of file diff --git a/corev_apu/tb/dpi/sim_spike.h b/corev_apu/tb/dpi/sim_spike.h deleted file mode 100644 index 0619166a2f..0000000000 --- a/corev_apu/tb/dpi/sim_spike.h +++ /dev/null @@ -1,95 +0,0 @@ -// See LICENSE for license details. - -#ifndef _RISCV_SPIKE_H -#define _RISCV_SPIKE_H - -#include "processor.h" -#include "devices.h" -#include "debug_module.h" -#include "simif.h" -#include -#include -#include -#include -#include -#include - -class mmu_t; -class remote_bitbang_t; - -typedef struct -{ - char priv; - uint64_t pc; - char is_fp; - char rd; - uint64_t data; - uint32_t instr; - char was_exception; -} commit_log_t; - -// this class encapsulates the processors and memory in a RISC-V machine. -class sim_spike_t : public simif_t -{ -public: - sim_spike_t(const char* isa, size_t _nprocs, - std::vector> mems, - const std::vector& args); - ~sim_spike_t(); - - int init_sim(); - void producer_thread(); - void clint_tick(); - commit_log_t tick(size_t n); // step through simulation - void set_debug(bool value); - void set_log(bool value); - void set_histogram(bool value); - void set_procs_debug(bool value); - void set_dtb_enabled(bool value) { - this->dtb_enabled = value; - } - void set_remote_bitbang(remote_bitbang_t* remote_bitbang) { - this->remote_bitbang = remote_bitbang; - } - const char* get_dts() { return dts.c_str(); } - processor_t* get_core(size_t i) { return procs.at(i); } - unsigned nprocs() const { return procs.size(); } - -private: - std::vector> mems; - mmu_t* debug_mmu; // debug port into main memory - std::vector procs; - reg_t start_pc; - std::string dts; - std::unique_ptr boot_rom; - std::unique_ptr clint; - std::unique_ptr uart; - bus_t bus; - std::thread t1; - - processor_t* get_core(const std::string& i); - static const size_t INTERLEAVE = 5000; - static const size_t INSNS_PER_RTC_TICK = 100; // 10 MHz clock for 1 BIPS core - static const size_t CPU_HZ = 1000000000; // 1GHz CPU - size_t current_step; - size_t current_proc; - bool debug; - bool log; - bool histogram_enabled; // provide a histogram of PCs - bool dtb_enabled; - remote_bitbang_t* remote_bitbang; - - // memory-mapped I/O routines - char* addr_to_mem(reg_t addr); - bool mmio_load(reg_t addr, size_t len, uint8_t* bytes); - bool mmio_store(reg_t addr, size_t len, const uint8_t* bytes); - void proc_reset(unsigned id) {}; - - void make_bootrom(); - -public: - -}; - - -#endif \ No newline at end of file diff --git a/corev_apu/tb/dpi/spike.cc b/corev_apu/tb/dpi/spike.cc deleted file mode 100644 index fda0684481..0000000000 --- a/corev_apu/tb/dpi/spike.cc +++ /dev/null @@ -1,133 +0,0 @@ -#include -#include - -#include "sim_spike.h" -#include "msim_helper.h" - -#include -#include "svdpi.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -sim_spike_t* sim; -std::vector> mem; -commit_log_t commit_log_val; - -#define SHT_PROGBITS 0x1 -#define SHT_GROUP 0x11 - -void write_spike_mem (reg_t address, size_t len, uint8_t* buf) { - memcpy(mem[0].second->contents() + (address & ~(1 << 31)), buf,len); -} - -void read_elf(const char* filename) { - int fd = open(filename, O_RDONLY); - struct stat s; - assert(fd != -1); - if (fstat(fd, &s) < 0) - abort(); - size_t size = s.st_size; - - char* buf = (char*)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); - assert(buf != MAP_FAILED); - close(fd); - - assert(size >= sizeof(Elf64_Ehdr)); - const Elf64_Ehdr* eh64 = (const Elf64_Ehdr*)buf; - assert(IS_ELF32(*eh64) || IS_ELF64(*eh64)); - - std::vector zeros; - - #define LOAD_ELF(ehdr_t, phdr_t, shdr_t, sym_t) do { \ - ehdr_t* eh = (ehdr_t*)buf; \ - phdr_t* ph = (phdr_t*)(buf + eh->e_phoff); \ - assert(size >= eh->e_phoff + eh->e_phnum*sizeof(*ph)); \ - for (unsigned i = 0; i < eh->e_phnum; i++) { \ - if(ph[i].p_type == PT_LOAD && ph[i].p_memsz) { \ - if (ph[i].p_filesz) { \ - assert(size >= ph[i].p_offset + ph[i].p_filesz); \ - write_spike_mem(ph[i].p_paddr, ph[i].p_filesz, (uint8_t*)buf + ph[i].p_offset); \ - } \ - zeros.resize(ph[i].p_memsz - ph[i].p_filesz); \ - } \ - } \ - shdr_t* sh = (shdr_t*)(buf + eh->e_shoff); \ - assert(size >= eh->e_shoff + eh->e_shnum*sizeof(*sh)); \ - assert(eh->e_shstrndx < eh->e_shnum); \ - assert(size >= sh[eh->e_shstrndx].sh_offset + sh[eh->e_shstrndx].sh_size); \ - char *shstrtab = buf + sh[eh->e_shstrndx].sh_offset; \ - unsigned strtabidx = 0, symtabidx = 0; \ - for (unsigned i = 0; i < eh->e_shnum; i++) { \ - unsigned max_len = sh[eh->e_shstrndx].sh_size - sh[i].sh_name; \ - if ((sh[i].sh_type & SHT_GROUP) && strcmp(shstrtab + sh[i].sh_name, ".strtab") != 0 && strcmp(shstrtab + sh[i].sh_name, ".shstrtab") != 0) \ - assert(strnlen(shstrtab + sh[i].sh_name, max_len) < max_len); \ - if (sh[i].sh_type & SHT_PROGBITS) continue; \ - if (strcmp(shstrtab + sh[i].sh_name, ".strtab") == 0) \ - strtabidx = i; \ - if (strcmp(shstrtab + sh[i].sh_name, ".symtab") == 0) \ - symtabidx = i; \ - } \ - if (strtabidx && symtabidx) { \ - char* strtab = buf + sh[strtabidx].sh_offset; \ - sym_t* sym = (sym_t*)(buf + sh[symtabidx].sh_offset); \ - for (unsigned i = 0; i < sh[symtabidx].sh_size/sizeof(sym_t); i++) { \ - unsigned max_len = sh[strtabidx].sh_size - sym[i].st_name; \ - assert(sym[i].st_name < sh[strtabidx]. sh_size); \ - assert(strnlen(strtab + sym[i].st_name, max_len) < max_len); \ - } \ - } \ - } while(0) - - if (IS_ELF32(*eh64)) - LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym); - else - LOAD_ELF(Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Sym); - - munmap(buf, size); -} - -extern "C" void spike_create(const char* filename, uint64_t dram_base, unsigned int size) -{ - - mem = std::vector>(1, std::make_pair(reg_t(dram_base), new mem_t(size))); - // zero out memory - memset(mem[0].second->contents(), 0, size_t(size)); - - read_elf(filename); - - if (!sim) { - std::vector htif_args = sanitize_args(); - - sim = new sim_spike_t("rv64imac", 1, mem, htif_args); - } -} - -// advance Spike and get the retired instruction -extern "C" void spike_tick(commit_log_t* commit_log) -{ - commit_log_val = sim->tick(1); - commit_log->priv = commit_log_val.priv; - commit_log->pc = commit_log_val.pc; - commit_log->is_fp = commit_log_val.is_fp; - commit_log->rd = commit_log_val.rd; - commit_log->data = commit_log_val.data; - commit_log->instr = commit_log_val.instr; - commit_log->was_exception = commit_log_val.was_exception; -} - -extern "C" void clint_tick() -{ - sim->clint_tick(); -} \ No newline at end of file diff --git a/verif/core-v-verif b/verif/core-v-verif index a687a6023b..67791932df 160000 --- a/verif/core-v-verif +++ b/verif/core-v-verif @@ -1 +1 @@ -Subproject commit a687a6023b3204881a9fa2ba10d394f5f3e8f8b2 +Subproject commit 67791932df6128671344015584109d7a177d9a9a diff --git a/verif/env/uvme/uvme_cva6_cfg.sv b/verif/env/uvme/uvme_cva6_cfg.sv index a955464f0c..b757f53101 100644 --- a/verif/env/uvme/uvme_cva6_cfg.sv +++ b/verif/env/uvme/uvme_cva6_cfg.sv @@ -31,7 +31,7 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; // Integrals rand bit enabled; - rand bit scoreboarding_enabled; + rand bit scoreboard_enabled; rand bit cov_model_enabled; rand bit cov_cvxif_model_enabled; rand bit cov_isa_model_enabled; @@ -51,7 +51,7 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; `uvm_object_utils_begin(uvme_cva6_cfg_c) `uvm_field_int ( enabled , UVM_DEFAULT ) `uvm_field_enum(uvm_active_passive_enum, is_active , UVM_DEFAULT ) - `uvm_field_int ( scoreboarding_enabled , UVM_DEFAULT ) + `uvm_field_int ( scoreboard_enabled , UVM_DEFAULT ) `uvm_field_int ( cov_model_enabled , UVM_DEFAULT ) `uvm_field_int ( trn_log_enabled , UVM_DEFAULT ) `uvm_field_int ( ext_zicond_supported , UVM_DEFAULT ) @@ -73,7 +73,7 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; constraint defaults_cons { soft enabled == 1; soft is_active == UVM_ACTIVE; - soft scoreboarding_enabled == 1; + soft scoreboard_enabled == 1; soft cov_model_enabled == 1; soft trn_log_enabled == 1; soft sys_clk_period == uvme_cva6_sys_default_clk_period; // see uvme_cva6_constants.sv @@ -147,15 +147,15 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; isacov_cfg.enabled == 1; rvfi_cfg.enabled == 1; } - + isacov_cfg.seq_instr_group_x2_enabled == 1; isacov_cfg.seq_instr_group_x3_enabled == 0; isacov_cfg.seq_instr_group_x4_enabled == 0; isacov_cfg.seq_instr_x2_enabled == 1; isacov_cfg.reg_crosses_enabled == 0; isacov_cfg.reg_hazards_enabled == 1; - rvfi_cfg.nret == RVFI_NRET; - + rvfi_cfg.nret == cva6_config_pkg::CVA6ConfigNrCommitPorts; + if (is_active == UVM_ACTIVE) { clknrst_cfg.is_active == UVM_ACTIVE; isacov_cfg.is_active == UVM_PASSIVE; diff --git a/verif/env/uvme/uvme_cva6_constants.sv b/verif/env/uvme/uvme_cva6_constants.sv index aea0364e17..c77ec83746 100644 --- a/verif/env/uvme/uvme_cva6_constants.sv +++ b/verif/env/uvme/uvme_cva6_constants.sv @@ -26,6 +26,5 @@ parameter uvme_cva6_debug_default_clk_period = 10_000; // 10ns parameter XLEN = 32; parameter ILEN = 32; -parameter RVFI_NRET = 1; `endif // __UVME_CVA6_CONSTANTS_SV__ diff --git a/verif/env/uvme/uvme_cva6_env.sv b/verif/env/uvme/uvme_cva6_env.sv index 9889a2c2b0..6e93fbf028 100644 --- a/verif/env/uvme/uvme_cva6_env.sv +++ b/verif/env/uvme/uvme_cva6_env.sv @@ -38,6 +38,8 @@ class uvme_cva6_env_c extends uvm_env; uvme_cva6_vsqr_c vsequencer; uvme_cva6_cov_model_c cov_model; + uvmc_rvfi_reference_model m_reference_model; + // Agents uvma_clknrst_agent_c clknrst_agent; uvma_cvxif_agent_c cvxif_agent; @@ -50,7 +52,7 @@ class uvme_cva6_env_c extends uvm_env; virtual uvmt_axi_switch_intf axi_switch_vif; //CSR register model - cva6_csr_reg_block csr_reg_block; + cva6_csr_reg_block csr_reg_block; cva6_csr_reg_adapter csr_reg_adapter; cva6_csr_reg_predictor#(uvma_isacov_mon_trn_c) csr_reg_predictor; @@ -168,6 +170,9 @@ function void uvme_cva6_env_c::build_phase(uvm_phase phase); cntxt = uvme_cva6_cntxt_c::type_id::create("cntxt"); end + if ($test$plusargs("scoreboard_enabled")) + $value$plusargs("scoreboard_enabled=%b",cfg.scoreboard_enabled); + retrieve_vif(); assign_cfg (); assign_cntxt (); @@ -184,7 +189,7 @@ function void uvme_cva6_env_c::build_phase(uvm_phase phase); csr_reg_block = cva6_csr_reg_block::type_id::create("csr_reg_block", this); csr_reg_predictor = cva6_csr_reg_predictor#(uvma_isacov_mon_trn_c)::type_id::create("csr_reg_predictor", this); csr_reg_adapter = cva6_csr_reg_adapter::type_id::create("csr_reg_adapter",, get_full_name()); - csr_reg_block.build(); + csr_reg_block.build(); end endfunction : build_phase @@ -195,7 +200,7 @@ function void uvme_cva6_env_c::connect_phase(uvm_phase phase); super.connect_phase(phase); if (cfg.enabled) begin - if (cfg.scoreboarding_enabled) begin + if (cfg.scoreboard_enabled) begin connect_predictor (); connect_scoreboard(); end @@ -207,7 +212,7 @@ function void uvme_cva6_env_c::connect_phase(uvm_phase phase); connect_coverage_model(); end end - + if (csr_reg_block.get_parent() == null) begin csr_reg_block.default_map.set_base_addr('h0); csr_reg_predictor.map = csr_reg_block.default_map; @@ -269,9 +274,10 @@ endfunction: create_agents function void uvme_cva6_env_c::create_env_components(); - if (cfg.scoreboarding_enabled) begin + if (cfg.scoreboard_enabled) begin predictor = uvme_cva6_prd_c::type_id::create("predictor", this); sb = uvme_cva6_sb_c ::type_id::create("sb" , this); + m_reference_model = uvmc_rvfi_reference_model#(ILEN,XLEN)::type_id::create("m_reference_model", this); end if (cfg.cov_model_enabled) begin @@ -321,6 +327,10 @@ function void uvme_cva6_env_c::connect_scoreboard(); // TODO Connect predictor -> scoreboard // Ex: predictor.debug_ap.connect(sb.debug_sb.exp_export); + rvfi_agent.rvfi_core_ap.connect(sb.m_rvfi_scoreboard.m_imp_core); + rvfi_agent.rvfi_core_ap.connect(m_reference_model.m_analysis_imp); + m_reference_model.m_analysis_port.connect(sb.m_rvfi_scoreboard.m_imp_reference_model); + endfunction: connect_scoreboard @@ -361,11 +371,9 @@ function void uvme_cva6_env_c::connect_coverage_model(); if (cfg.cov_isa_model_enabled) begin isacov_agent.monitor.ap.connect(cov_model.isa_covg.mon_trn_fifo.analysis_export); end - foreach (rvfi_agent.instr_mon_ap[i]) begin - rvfi_agent.instr_mon_ap[i].connect(isacov_agent.monitor.rvfi_instr_imp); - end - + clknrst_agent.mon_ap.connect(cov_model.reset_export); + rvfi_agent.rvfi_core_ap.connect(isacov_agent.monitor.rvfi_instr_imp); endfunction: connect_coverage_model diff --git a/verif/env/uvme/uvme_cva6_pkg.sv b/verif/env/uvme/uvme_cva6_pkg.sv index 0e5a79fc27..b60f8b482d 100644 --- a/verif/env/uvme/uvme_cva6_pkg.sv +++ b/verif/env/uvme/uvme_cva6_pkg.sv @@ -37,6 +37,7 @@ */ package uvme_cva6_pkg; + import cva6_config_pkg ::*; import uvm_pkg ::*; import uvml_hrtbt_pkg ::*; import uvml_sb_pkg ::*; @@ -47,6 +48,8 @@ package uvme_cva6_pkg; import uvml_mem_pkg ::*; import uvma_core_cntrl_pkg::*; import uvma_rvfi_pkg::*; + import uvmc_rvfi_scoreboard_pkg::*; + import uvmc_rvfi_reference_model_pkg::*; import uvma_isacov_pkg::*; // Constants / Structs / Enums diff --git a/verif/env/uvme/uvme_cva6_sb.sv b/verif/env/uvme/uvme_cva6_sb.sv index cd4650f05b..22feb6e2ad 100644 --- a/verif/env/uvme/uvme_cva6_sb.sv +++ b/verif/env/uvme/uvme_cva6_sb.sv @@ -35,6 +35,8 @@ class uvme_cva6_sb_c extends uvm_scoreboard; // TODO Add sub-scoreboards // Ex: uvme_cva6_sb_simplex_c egress_sb; // uvme_cva6_sb_simplex_c ingress_sb; + uvmc_rvfi_scoreboard_c#(ILEN,XLEN) m_rvfi_scoreboard; + `uvm_component_utils_begin(uvme_cva6_sb_c) @@ -129,6 +131,7 @@ function void uvme_cva6_sb_c::create_sbs(); // TODO Implement uvme_cva6_sb_c::create_sbs() // Ex: egress_sb = uvme_cva6_sb_simplex_c::type_id::create("egress_sb" , this); // ingress_sb = uvme_cva6_sb_simplex_c::type_id::create("ingress_sb", this); + m_rvfi_scoreboard = uvmc_rvfi_scoreboard_c#(ILEN,XLEN)::type_id::create("m_rvfi_scoreboard", this); endfunction : create_sbs diff --git a/verif/regress/install-spike.sh b/verif/regress/install-spike.sh index 34cb792e99..1a5eb94aff 100755 --- a/verif/regress/install-spike.sh +++ b/verif/regress/install-spike.sh @@ -55,7 +55,9 @@ else # Build and install Spike (including extensions). mkdir -p build cd build - ../configure --prefix="$SPIKE_INSTALL_DIR" + if [[ ! -f config.log ]]; then + ../configure --prefix="$SPIKE_INSTALL_DIR" + fi make -j${NUM_JOBS} echo "Installing Spike in '$SPIKE_INSTALL_DIR'..." make install diff --git a/verif/regress/install-verilator.sh b/verif/regress/install-verilator.sh index 26ed703e4d..82e8963443 100755 --- a/verif/regress/install-verilator.sh +++ b/verif/regress/install-verilator.sh @@ -8,7 +8,7 @@ # Original Author: Jean-Roch COULON - Thales if [ -z "$NUM_JOBS" ]; then - NUM_JOBS=1 + NUM_JOBS=4 fi # Ensure the location of tools is known (usually, .../core-v-verif/tools). @@ -51,6 +51,7 @@ if [ ! -f "$VERILATOR_INSTALL_DIR/bin/verilator" ]; then echo "VERILATOR_BRANCH=$VERILATOR_BRANCH" echo "VERILATOR_HASH=$VERILATOR_HASH" echo "VERILATOR_PATCH=$VERILATOR_PATCH" + echo "NUM_JOBS=$NUM_JOBS" mkdir -p $VERILATOR_BUILD_DIR cd $VERILATOR_BUILD_DIR # Clone only if the ".git" directory does not exist. diff --git a/verif/sim/Makefile b/verif/sim/Makefile index 8af6ebf5b7..3607185461 100644 --- a/verif/sim/Makefile +++ b/verif/sim/Makefile @@ -14,6 +14,7 @@ ifndef CVA6_REPO_DIR $(warning must set CVA6_REPO_DIR to point at the root of CVA6 sources and CVA6_TB_DIR to point here -- doing it for you...) export CVA6_REPO_DIR = $(abspath $(root-dir)../..) export CVA6_TB_DIR = $(root-dir)/../tb/core +export CORE_V_VERIF = $(root-dir)/../core-v-verif endif ifndef TARGET_CFG export TARGET_CFG = $(target) @@ -27,6 +28,7 @@ export HPDCACHE_TARGET_CFG .DEFAULT_GOAL := help FLIST_TB := $(CVA6_TB_DIR)/Flist.cva6_tb + # target takes one of the following cva6 hardware configuration: # cv64a6_imafdc_sv39, cv32a6_imac_sv0, cv32a6_imac_sv32, cv32a6_imafc_sv32 target ?= cv64a6_imafdc_sv39 @@ -42,6 +44,10 @@ issrun_opts ?= isspostrun_opts ?= log ?= variant ?= + +# Spike tandem mode: default to environment setting (DISABLED if envariable SPIKE_TANDEM is not set). +export spike-tandem ?= $(SPIKE_TANDEM) + # Set Spike step count limit if the caller provided a step count value in variable 'steps'. ifneq ($(steps),) spike_stepout = --steps=$(steps) @@ -121,17 +127,19 @@ spike: # testharness specific commands, variables ############################################################################### vcs-testharness: - make -C $(path_var) vcs_build target=$(target) defines=$(subst +define+,,$(isscomp_opts)) - $(path_var)/work-vcs/simv +vcs+lic+wait $(if $(VERDI), -verdi -do $(path_var)/init_testharness.do,) +permissive -sv_lib $(path_var)/work-dpi/ariane_dpi \ + make -C $(path_var) work-dpi/ariane_dpi.so + make -C $(path_var) vcs_build target=$(target) defines=$(subst +define+,,$(isscomp_opts))$(if $(spike-tandem),SPIKE_TANDEM=1) + $(path_var)/work-vcs/simv $(if $(VERDI), -verdi -do $(path_var)/init_testharness.do,) +permissive \ +tohost_addr=$(shell $$RISCV/bin/${CV_SW_PREFIX}nm -B $(elf) | grep -w tohost | cut -d' ' -f1) \ - +PRELOAD=$(elf) +permissive-off ++$(elf) $(issrun_opts) + +elf_file=$(elf) +permissive-off ++$(elf) $(issrun_opts) $(if $(spike-tandem),-sv_lib $(SPIKE_INSTALL_DIR)/lib/libriscv) \ + -sv_lib $(SPIKE_INSTALL_DIR)/lib/libfesvr $(tool_path)/spike-dasm --isa=$(variant) < ./trace_rvfi_hart_00.dasm > $(log) grep $(isspostrun_opts) ./trace_rvfi_hart_00.dasm veri-testharness: make -C $(path_var) verilate verilator="verilator --no-timing" target=$(target) defines=$(subst +define+,,$(isscomp_opts)) - $(path_var)/work-ver/Variane_testharness $(if $(TRACE_COMPACT), -f verilator.fst) $(if $(TRACE_FAST), -v verilator.vcd) $(elf) $(issrun_opts) +PRELOAD=$(elf) \ - +tohost_addr=$(shell $$RISCV/bin/${CV_SW_PREFIX}nm -B $(elf) | grep -w tohost | cut -d' ' -f1) + $(path_var)/work-ver/Variane_testharness $(if $(TRACE_COMPACT), -f verilator.fst) $(if $(TRACE_FAST), -v verilator.vcd) $(elf) $(issrun_opts) \ + +elf_file=$(elf) +tohost_addr=$(shell $$RISCV/bin/${CV_SW_PREFIX}nm -B $(elf) | grep -w tohost | cut -d' ' -f1) $(tool_path)/spike-dasm --isa=$(variant) < ./trace_rvfi_hart_00.dasm > $(log) # If present, move default trace files to per-test directory. [ ! -f verilator.fst ] || mv verilator.fst `dirname $(log)`/`basename $(log) .log`.$(target).fst @@ -140,7 +148,7 @@ veri-testharness: questa-testharness: mkdir -p $(path_var)/tmp - make -C $(path_var) sim target=$(target) defines=$(subst +define+,,$(isscomp_opts)) batch-mode=1 elf-bin=$(elf) $(issrun_opts) + make -C $(path_var) sim target=$(target) defines=$(subst +define+,,$(isscomp_opts)) batch-mode=1 $(issrun_opts) $(tool_path)/spike-dasm --isa=$(variant) < $(path_var)/trace_rvfi_hart_00.dasm > $(log) grep $(isspostrun_opts) $(path_var)/trace_rvfi_hart_00.dasm @@ -156,31 +164,29 @@ export CVA6_UVMT_PATH = $(CVA6_REPO_DIR)/verif/tb/uvmt export CVA6_UVME_PATH = $(CVA6_REPO_DIR)/verif/env/uvme export CV_CORE_LC = cva6 export CV_CORE_UC = CVA6 -export DV_UVMT_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/$(CV_CORE_LC)/tb/uvmt -export DV_UVME_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/$(CV_CORE_LC)/env/uvme -export DV_UVML_HRTBT_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_libs/uvml_hrtbt -export DV_UVMA_CORE_CNTRL_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_agents/uvma_core_cntrl -export DV_UVMA_RVFI_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_agents/uvma_rvfi -export DV_UVMA_ISACOV_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_agents/uvma_isacov -export DV_UVMA_CLKNRST_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_agents/uvma_clknrst -export DV_UVMA_CVXIF_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_agents/uvma_cvxif -export DV_UVMA_AXI_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_agents/uvma_axi -export DV_UVMA_INTERRUPT_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_agents/uvma_interrupt -export DV_UVMA_DEBUG_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_agents/uvma_debug -export DV_UVMA_OBI_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_agents/uvma_obi -export DV_UVML_TRN_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_libs/uvml_trn -export DV_UVML_MEM_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_libs/uvml_mem -export DV_UVML_LOGS_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_libs/uvml_logs -export DV_UVML_SB_PATH = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_libs/uvml_sb -export CV_CORE_PKG = $(CVA6_REPO_DIR)/verif/core-v-verif/core-v-cores/$(CV_CORE_LC) +export DV_UVMT_PATH = $(CVA6_REPO_DIR)/verif/tb/uvmt +export DV_UVME_PATH = $(CVA6_REPO_DIR)/verif/env/uvme +export DV_UVML_HRTBT_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_hrtbt +export DV_UVMA_CORE_CNTRL_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_core_cntrl +export DV_UVMA_RVFI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_rvfi +export DV_UVMA_ISACOV_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_isacov +export DV_UVMA_CLKNRST_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_clknrst +export DV_UVMA_CVXIF_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_cvxif +export DV_UVMA_AXI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_axi +export DV_UVMA_INTERRUPT_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_interrupt +export DV_UVMA_DEBUG_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_debug +export DV_UVMA_OBI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_obi +export DV_UVMC_RVFI_SB_PATH = $(CORE_V_VERIF)/lib/uvm_components/uvmc_rvfi_scoreboard/ +export DV_UVMC_RVFI_REFERENCE_MODEL_PATH = $(CORE_V_VERIF)/lib/uvm_components/uvmc_rvfi_reference_model/ +export DV_UVML_TRN_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_trn +export DV_UVML_MEM_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_mem +export DV_UVML_LOGS_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_logs +export DV_UVML_SB_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_sb +export CV_CORE_PKG = $(CORE_V_VERIF)/core-v-cores/$(CV_CORE_LC) export DESIGN_RTL_DIR = $(CV_CORE_PKG)/rtl -DPI_DASM_PKG = $(CVA6_REPO_DIR)/verif/core-v-verif/lib/dpi_dasm -DPI_DASM_SPIKE_PKG = $(CVA6_REPO_DIR)/verif/core-v-verif/$(CV_CORE_LC)/vendor_lib/dpi_dasm_spike -export DPI_DASM_ROOT = $(DPI_DASM_PKG) -export DPI_DASM_SPIKE_ROOT = $(DPI_DASM_SPIKE_PKG) export TBSRC_HOME = $(CVA6_REPO_DIR)/verif/tb -export DV_OVPM_HOME = $(CVA6_REPO_DIR)/verif/core-v-verif/$(CV_CORE_LC)/vendor_lib/imperas +export DV_OVPM_HOME = $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/imperas export DV_OVPM_MODEL = $(DV_OVPM_HOME)/riscv_$(CV_CORE_UC)_OVPsim export DV_OVPM_DESIGN = $(DV_OVPM_HOME)/design @@ -188,12 +194,13 @@ ALL_UVM_FLAGS = -lca -sverilog +incdir+$(VCS_HOME)/etc/uvm/src \ $(VCS_HOME)/etc/uvm/src/uvm_pkg.sv +UVM_VERBOSITY=UVM_MEDIUM -ntb_opts uvm-1.2 -timescale=1ns/1ps \ -assert svaext -race=all -ignore unique_checks -full64 -q +incdir+$(VCS_HOME)/etc/uvm/src \ +incdir+$(CVA6_REPO_DIR)/verif/env/uvme +incdir+$(CVA6_REPO_DIR)/verif/tb/uvmt \ - $(if $(DEBUG), -debug_access+all $(if $(VERDI), -kdb) $(if $(TRACE_COMPACT),+vcs+fsdbon))\ - -cm_seqnoconst -diag noconst + $(if $(DEBUG), -debug_access+all $(if $(VERDI), -kdb) $(if $(TRACE_COMPACT),+vcs+fsdbon)) \ + -cm_seqnoconst -diag noconst \ + $(if $(spike-tandem), +define+SPIKE_TANDEM=1) ALL_SIMV_UVM_FLAGS = +vcs+lic+wait $(issrun_opts) \ - -sv_lib $(CVA6_REPO_DIR)/verif/core-v-verif/lib/dpi_dasm/lib/Linux64/libdpi_dasm +signature=I-ADD-01.signature_output \ - +UVM_TESTNAME=uvmt_cva6_firmware_test_c + -sv_lib $(CVA6_REPO_DIR)/tools/spike/lib/libdisasm \ + +signature=I-ADD-01.signature_output +UVM_TESTNAME=uvmt_cva6_firmware_test_c ifneq ($(DEBUG),) # If RTL DEBUG support requested ifneq ($(VERDI),) # If VERDI interactive mode requested, use GUI and do not run simulation @@ -213,15 +220,13 @@ ifneq ($(DEBUG),) # If RTL DEBUG support requested endif endif -dpi-library = $(VCS_WORK_DIR)/work-dpi -dpi_build: - mkdir -p $(dpi-library) - g++ -shared -fPIC -std=c++17 -Bsymbolic -I../corev_apu/tb/dpi -O3 -I$(SPIKE_INSTALL_DIR)/include \ - -I$(VCS_HOME)/include -I$(RISCV)/include -c $(CVA6_REPO_DIR)/corev_apu/tb/dpi/elfloader.cc \ - -o $(dpi-library)/elfloader.o - g++ -shared -m64 -o $(dpi-library)/ariane_dpi.so $(dpi-library)/elfloader.o -L$(RISCV)/lib -Wl,-rpath,$(RISCV)/lib +ifneq ($(SPIKE_TANDEM),) +ALL_SIMV_UVM_FLAGS += +scoreboard_enabled=1 +else +ALL_SIMV_UVM_FLAGS += +scoreboard_enabled=0 +endif -vcs_uvm_comp: dpi_build +vcs_uvm_comp: @echo "[VCS] Building Model" mkdir -p $(VCS_WORK_DIR) cd $(VCS_WORK_DIR) && vcs $(ALL_UVM_FLAGS) \ @@ -233,24 +238,19 @@ vcs_uvm_comp: dpi_build vcs_uvm_run: $(if $(TRACE_FAST), unset VERDI_HOME ;) \ cd $(VCS_WORK_DIR)/ && \ - $(VCS_WORK_DIR)/simv ${ALL_SIMV_UVM_FLAGS} \ + $(VCS_WORK_DIR)/simv \ + -sv_lib $(SPIKE_INSTALL_DIR)/lib/libriscv \ + -sv_lib $(SPIKE_INSTALL_DIR)/lib/libfesvr \ + ${ALL_SIMV_UVM_FLAGS} \ ++$(elf) \ - +PRELOAD=$(elf) \ - +tohost_addr=$(shell $$RISCV/bin/riscv-none-elf-nm -B $(elf) | grep -w tohost | cut -d' ' -f1) \ - -sv_lib $(dpi-library)/ariane_dpi \ - $(cov-run-opt) $(issrun_opts) && \ - mv $(VCS_WORK_DIR)/trace_rvfi_hart_00.dasm $(CVA6_REPO_DIR)/verif/sim/ && \ - { [ -z "`ls $(VCS_WORK_DIR)/*.$(SIMV_TRACE_EXTN)`" ] || \ - for i in `ls $(VCS_WORK_DIR)/*.$(SIMV_TRACE_EXTN)` ; do mv $$i $(CVA6_REPO_DIR)/verif/sim/`basename $$i` ; done || \ - true ; } + +elf_file=$(elf) \ + +tohost_addr=$(shell $$RISCV/bin/$(CV_SW_PREFIX)nm -B $(elf) | grep -w tohost | cut -d' ' -f1) \ + $(cov-run-opt) $(issrun_opts) vcs-uvm: make vcs_uvm_comp make vcs_uvm_run - $(tool_path)/spike-dasm --isa=$(variant) < ./trace_rvfi_hart_00.dasm > $(log) - grep $(isspostrun_opts) ./trace_rvfi_hart_00.dasm - [ -z "`ls *.$(SIMV_TRACE_EXTN)`" ] || \ - for i in `ls *.$(SIMV_TRACE_EXTN)` ; do mv $$i `dirname $(log)`/`basename $(log) .log`.$(target).$$i ; done || true + $(tool_path)/spike-dasm --isa=$(variant) < ./vcs_results/default/vcs.d/trace_rvfi_hart_00.dasm > $(log) generate_cov_dash: urg -hvp_proj cva6_embedded -format both -group instcov_for_score -hvp_attributes description -dir vcs_results/default/vcs.d/simv.vdb -plan cva6.hvp -mod modifier_embedded.hvp -tgl portsonly diff --git a/verif/sim/cva6_spike_log_to_trace_csv.py b/verif/sim/cva6_spike_log_to_trace_csv.py index 486c8d9750..a16b515e66 100644 --- a/verif/sim/cva6_spike_log_to_trace_csv.py +++ b/verif/sim/cva6_spike_log_to_trace_csv.py @@ -97,7 +97,7 @@ def read_spike_trace(path, full_trace): If full_trace is true, extract operands from the disassembled instructions. Since Spike has a strange trampoline that always runs at the start, we skip - instructions up to and including the one at PC 0x1010 (the end of the + instructions up to and including the one at PC 0x10010 (the end of the trampoline). At the end of a DV program, there's an ECALL instruction, which we take as a signal to stop checking, so we ditch everything that follows that instruction. @@ -121,7 +121,7 @@ def read_spike_trace(path, full_trace): # true. Otherwise, we are in state EFFECT if instr is not None, otherwise we # are in state INSTR. - end_trampoline_re = re.compile(r'core.*: 0x0*1010 ') + end_trampoline_re = re.compile(r'core.*: 0x0*10010 ') in_trampoline = True instr = None diff --git a/verif/tb/core/rvfi_pkg.sv b/verif/tb/core/rvfi_pkg.sv new file mode 100644 index 0000000000..fc1e039828 --- /dev/null +++ b/verif/tb/core/rvfi_pkg.sv @@ -0,0 +1,27 @@ +`ifndef __UVMA_RVFI_PKG_SV__ +`define __UVMA_RVFI_PKG_SV__ + +// Pre-processor macros +`ifdef VERILATOR + `define uvm_info(TOP,MSG,LVL) \ + $display(TOP + ":" + MSG); + `define uvm_fatal(TOP,MSG) \ + $display(TOP + ":" + MSG); $finish(); +`else +`include "uvm_macros.svh" +`endif + +package rvfi_pkg; + +`ifndef VERILATOR +import uvm_pkg ::*; +`endif + + +`include "uvma_rvfi_constants.sv" +`include "uvma_rvfi_tdefs.sv" +`include "uvma_rvfi_utils.sv" + +endpackage + +`endif diff --git a/verif/tb/uvmt/cva6_tb_wrapper.sv b/verif/tb/uvmt/cva6_tb_wrapper.sv index ebeba3dd60..8656815831 100644 --- a/verif/tb/uvmt/cva6_tb_wrapper.sv +++ b/verif/tb/uvmt/cva6_tb_wrapper.sv @@ -32,7 +32,7 @@ import uvm_pkg::*; import "DPI-C" function read_elf(input string filename); import "DPI-C" function byte get_section(output longint address, output longint len); -import "DPI-C" context function void read_section(input longint address, inout byte buffer[]); +import "DPI-C" context function void read_section_sv(input longint address, inout byte buffer[]); module cva6_tb_wrapper import uvmt_cva6_pkg::*; #( parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty, @@ -244,12 +244,11 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #( longint address; longint len; byte buffer[]; - void'(uvcl.get_arg_value("+PRELOAD=", binary)); + void'(uvcl.get_arg_value("+elf_file=", binary)); if (binary != "") begin void'(read_elf(binary)); - wait(clk_i); // while there are more sections to process @@ -257,7 +256,7 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #( automatic int num_words0 = (len+7)/8; `uvm_info( "Core Test", $sformatf("Loading Address: %x, Length: %x", address, len), UVM_LOW) buffer = new [num_words0*8]; - void'(read_section(address, buffer)); + void'(read_section_sv(address, buffer)); // preload memories // 64-bit for (int i = 0; i < num_words0; i++) begin diff --git a/verif/tb/uvmt/uvmt_cva6.flist b/verif/tb/uvmt/uvmt_cva6.flist index fb5b855e98..4776c4cbff 100644 --- a/verif/tb/uvmt/uvmt_cva6.flist +++ b/verif/tb/uvmt/uvmt_cva6.flist @@ -28,6 +28,8 @@ -f ${DV_UVMA_CORE_CNTRL_PATH}/uvma_core_cntrl_pkg.flist -f ${DV_UVMA_RVFI_PATH}/uvma_rvfi_pkg.flist -f ${DV_UVMA_ISACOV_PATH}/uvma_isacov_pkg.flist +-f ${DV_UVMC_RVFI_REFERENCE_MODEL_PATH}/uvmc_rvfi_reference_model_pkg.flist +-f ${DV_UVMC_RVFI_SB_PATH}/uvmc_rvfi_scoreboard_pkg.flist // Environments -f ${CVA6_UVME_PATH}/uvme_cva6_pkg.flist diff --git a/verif/tb/uvmt/uvmt_cva6_pkg.sv b/verif/tb/uvmt/uvmt_cva6_pkg.sv index 7469c8a90b..7300e9fb9d 100644 --- a/verif/tb/uvmt/uvmt_cva6_pkg.sv +++ b/verif/tb/uvmt/uvmt_cva6_pkg.sv @@ -38,6 +38,7 @@ package uvmt_cva6_pkg; import uvm_pkg::*; import uvme_cva6_pkg::*; + import uvmc_rvfi_reference_model_pkg::*; import uvml_hrtbt_pkg::*; import uvml_logs_pkg::*; diff --git a/verif/tb/uvmt/uvmt_cva6_tb.sv b/verif/tb/uvmt/uvmt_cva6_tb.sv index 0c89a510e6..986f165f77 100644 --- a/verif/tb/uvmt/uvmt_cva6_tb.sv +++ b/verif/tb/uvmt/uvmt_cva6_tb.sv @@ -30,6 +30,8 @@ module uvmt_cva6_tb; import uvmt_cva6_pkg::*; import uvme_cva6_pkg::*; + localparam RVFI_NRET = cva6_config_pkg::CVA6ConfigNrCommitPorts; + // CVA6 config localparam config_pkg::cva6_cfg_t CVA6Cfg = cva6_config_pkg::cva6_cfg; localparam bit IsRVFI = bit'(cva6_config_pkg::CVA6ConfigRvfiTrace); @@ -82,9 +84,9 @@ module uvmt_cva6_tb; uvma_rvfi_instr_if #( uvme_cva6_pkg::ILEN, uvme_cva6_pkg::XLEN - ) rvfi_instr_if [uvme_cva6_pkg::RVFI_NRET-1:0] (); + ) rvfi_instr_if [RVFI_NRET-1:0] (); - uvma_rvfi_csr_if#(uvme_cva6_pkg::XLEN) rvfi_csr_if [uvme_cva6_pkg::RVFI_NRET-1:0](); + uvma_rvfi_csr_if#(uvme_cva6_pkg::XLEN) rvfi_csr_if [RVFI_NRET-1:0](); uvmt_default_inputs_intf default_inputs_vif(); @@ -132,13 +134,14 @@ module uvmt_cva6_tb; .rvfi_o(rvfi_if.rvfi_o) ); - for (genvar i = 0; i < uvme_cva6_pkg::RVFI_NRET; i++) begin + for (genvar i = 0; i < RVFI_NRET; i++) begin assign rvfi_instr_if[i].clk = clknrst_if.clk; assign rvfi_instr_if[i].reset_n = clknrst_if.reset_n; assign rvfi_instr_if[i].rvfi_valid = rvfi_if.rvfi_o[i].valid; assign rvfi_instr_if[i].rvfi_order = rvfi_if.rvfi_o[i].order; assign rvfi_instr_if[i].rvfi_insn = rvfi_if.rvfi_o[i].insn; assign rvfi_instr_if[i].rvfi_trap = rvfi_if.rvfi_o[i].trap; + assign rvfi_instr_if[i].rvfi_cause = rvfi_if.rvfi_o[i].cause; assign rvfi_instr_if[i].rvfi_halt = rvfi_if.rvfi_o[i].halt; assign rvfi_instr_if[i].rvfi_intr = rvfi_if.rvfi_o[i].intr; assign rvfi_instr_if[i].rvfi_mode = rvfi_if.rvfi_o[i].mode; @@ -165,7 +168,7 @@ module uvmt_cva6_tb; assign default_inputs_vif.debug_req = 1'b0; - for (genvar i = 0; i < uvme_cva6_pkg::RVFI_NRET; i++) begin + for (genvar i = 0; i < RVFI_NRET; i++) begin initial begin uvm_config_db#(virtual uvma_rvfi_instr_if )::set(null,"*", $sformatf("instr_vif%0d", i), rvfi_instr_if[i]); diff --git a/verif/tests/uvmt/compliance-tests/uvmt_cva6_firmware_test.sv b/verif/tests/uvmt/compliance-tests/uvmt_cva6_firmware_test.sv index e6d73a71a1..b5c0a76e05 100644 --- a/verif/tests/uvmt/compliance-tests/uvmt_cva6_firmware_test.sv +++ b/verif/tests/uvmt/compliance-tests/uvmt_cva6_firmware_test.sv @@ -61,6 +61,11 @@ class uvmt_cva6_firmware_test_c extends uvmt_cva6_base_test_c; */ extern virtual task configure_phase(uvm_phase phase); + /** + * Override types with the UVM Factory + */ + extern virtual function void build_phase(uvm_phase phase); + /** * Enable program execution, wait for completion. */ @@ -92,6 +97,14 @@ task uvmt_cva6_firmware_test_c::reset_phase(uvm_phase phase); endtask : reset_phase +function void uvmt_cva6_firmware_test_c::build_phase(uvm_phase phase); + super.build_phase(phase); + + `uvm_info("firmware_test", "Overriding Reference Model with Spike", UVM_NONE) + set_type_override_by_type(uvmc_rvfi_reference_model::get_type(),uvmc_rvfi_spike::get_type()); + +endfunction : build_phase + task uvmt_cva6_firmware_test_c::configure_phase(uvm_phase phase);