Spike Tandem Implementation using VCS simulator (#1561)

This commit is contained in:
MarioOpenHWGroup 2023-11-09 19:29:24 +01:00 committed by GitHub
parent 3c45510934
commit 220f534b6d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 354 additions and 638 deletions

View file

@ -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 }}

View file

@ -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

View file

@ -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 <testname>, 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 <testname> batch-mode=1
# alternatively you can call make sim elf-bin=<path/to/elf-bin> in order to load an arbitrary binary
# alternatively you can call make sim elf_file=<path/to/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,,$@)

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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 @@ done_processing:
std::unique_ptr<Variane_testharness> 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 @@ done_processing:
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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,135 +0,0 @@
// See LICENSE for license details.
#include "sim_spike.h"
#include "mmu.h"
#include "dts.h"
#include <map>
#include <iostream>
#include <sstream>
#include <climits>
#include <cstdlib>
#include <cassert>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <inttypes.h>
sim_spike_t::sim_spike_t(const char* isa, size_t nprocs,
std::vector<std::pair<reg_t, mem_t*>> mems,
const std::vector<std::string>& 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<char> 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<mem_t*>(desc.second))
if (addr - desc.first < mem->size())
return mem->contents() + (addr - desc.first);
return NULL;
}

View file

@ -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 <fesvr/htif.h>
#include <fesvr/context.h>
#include <vector>
#include <string>
#include <memory>
#include <thread>
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<std::pair<reg_t, mem_t*>> mems,
const std::vector<std::string>& 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<std::pair<reg_t, mem_t*>> mems;
mmu_t* debug_mmu; // debug port into main memory
std::vector<processor_t*> procs;
reg_t start_pc;
std::string dts;
std::unique_ptr<rom_device_t> boot_rom;
std::unique_ptr<clint_t> clint;
std::unique_ptr<uart_t> 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

View file

@ -1,133 +0,0 @@
#include <fesvr/elf.h>
#include <fesvr/memif.h>
#include "sim_spike.h"
#include "msim_helper.h"
#include <vpi_user.h>
#include "svdpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <memory>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>
#include <map>
#include <iostream>
sim_spike_t* sim;
std::vector<std::pair<reg_t, mem_t*>> 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<uint8_t> 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<std::pair<reg_t, mem_t*>>(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<std::string> 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();
}

@ -1 +1 @@
Subproject commit a687a6023b3204881a9fa2ba10d394f5f3e8f8b2
Subproject commit 67791932df6128671344015584109d7a177d9a9a

View file

@ -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;

View file

@ -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__

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

27
verif/tb/core/rvfi_pkg.sv Normal file
View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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::*;

View file

@ -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]);

View file

@ -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);