diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Makefile | 33 | ||||
| -rw-r--r-- | nix/flake.nix | 1 | ||||
| -rwxr-xr-x | sim/sim.py | 18 | ||||
| -rw-r--r-- | tb/top/conspiracion.cpp | 28 |
5 files changed, 59 insertions, 22 deletions
@@ -34,6 +34,7 @@ __pycache__ hps_sdram_p0_summary.csv vcd/ +cov/ obj/ .qsys_edit/ platform/ @@ -6,16 +6,24 @@ TB_DIR := tb SIM_DIR := sim TB_SIM_DIR := $(TB_DIR)/sim SIM_OBJ_DIR := $(OBJ_DIR)/$(TOP)/sim -VERILATOR := verilator +VERILATOR ?= verilator +GENHTML ?= genhtml CROSS_CC := $(CROSS_COMPILE)gcc CROSS_OBJCOPY := $(CROSS_COMPILE)objcopy CROSS_CFLAGS := -O3 -Wall -Wextra -Werror CROSS_LDFLAGS := +VFLAGS ?= \ + --x-assign unique --x-initial unique \ + --threads $(shell nproc) \ + $(if $(DISABLE_COV),,--coverage) + RTL_FILES = $(shell find $(RTL_DIR)/ ! -path '$(RTL_DIR)/top/*' -type f -name '*.sv') RTL_FILES += $(shell find $(TB_DIR)/ ! -path '$(TB_DIR)/top/*' -type f -name '*.sv') TB_FILES = $(shell find $(TB_DIR)/ ! -path '$(TB_DIR)/top/*' -type f -name '*.cpp') +SIMS := $(patsubst $(TB_SIM_DIR)/%.py,%,$(wildcard $(TB_SIM_DIR)/*.py)) + all: sim clean: @@ -29,14 +37,29 @@ trace/%: exe/% $(VCD_DIR)/% $(VCD_DIR)/%: mkdir -p $@ -sim: $(patsubst $(TB_SIM_DIR)/%.py,sim/%,$(wildcard $(TB_SIM_DIR)/*.py)) +sim: $(addprefix sim/,$(SIMS)) sim/%: $(SIM_DIR)/sim.py $(TB_SIM_DIR)/%.py exe/$(TOP) $(SIM_OBJ_DIR)/%.bin - @$< $(TB_SIM_DIR)/$*.py $(OBJ_DIR)/$(TOP)/V$(TOP) $(SIM_OBJ_DIR)/$*.bin + @$< $(TB_SIM_DIR)/$*.py $(OBJ_DIR)/$(TOP)/V$(TOP) \ + $(SIM_OBJ_DIR)/$*.bin \ + $(if $(DISABLE_COV),,$(SIM_OBJ_DIR)/$*.cov) vmlaunch: $(SIM_DIR)/sim.py $(SIM_DIR)/gdbstub.py exe/$(TOP) @$< $(SIM_DIR)/gdbstub.py $(OBJ_DIR)/$(TOP)/V$(TOP) u-boot/build/taller/u-boot-dtb.bin +ifndef DISABLE_COV +cov: $(OBJ_DIR)/$(TOP)/cov.info + @rm -rf $@ + $(GENHTML) $< --output-dir=$@ + +cov/%: $(SIM_OBJ_DIR)/%.cov + +$(SIM_OBJ_DIR)/%.cov: sim/% + +$(OBJ_DIR)/$(TOP)/cov.info: $(patsubst %,$(SIM_OBJ_DIR)/%.cov,$(SIMS)) + $(VERILATOR)_coverage -write-info $@ $(SIM_OBJ_DIR)/*.cov +endif + $(SIM_OBJ_DIR)/%.bin: $(SIM_OBJ_DIR)/% $(CROSS_OBJCOPY) -O binary --only-section=._img $< $@ @@ -60,7 +83,7 @@ exe: exe/$(TOP) exe/%: $(OBJ_DIR)/%/V%.mk $(MAKE) -C $(OBJ_DIR)/$* -f V$*.mk -.PRECIOUS: $(SIM_OBJ_DIR)/% $(SIM_OBJ_DIR)/%.o $(SIM_OBJ_DIR)/%.bin +.PRECIOUS: $(SIM_OBJ_DIR)/% $(SIM_OBJ_DIR)/%.o $(SIM_OBJ_DIR)/%.bin $(SIM_OBJ_DIR)/%.cov .SECONDEXPANSION: $(OBJ_DIR)/%.mk: \ @@ -74,4 +97,4 @@ $(OBJ_DIR)/%.mk: \ $(VERILATOR) \ -O3 --cc --exe --trace -y $(RTL_DIR) --Mdir $(dir $@) \ --top $(word 1,$(subst /, ,$*)) $(patsubst tb/%,../tb/%,$^) \ - --x-assign unique --x-initial unique --threads $(shell nproc) + $(VFLAGS) diff --git a/nix/flake.nix b/nix/flake.nix index 5de1f31..d7c7125 100644 --- a/nix/flake.nix +++ b/nix/flake.nix @@ -114,6 +114,7 @@ gdb gnumake gtkwave + lcov pkg-config (python3.withPackages (py: [ py.numpy py.pillow py.matplotlib ])) (quartus-prime-lite.override { supportedDevices = [ "Cyclone V" ]; }) @@ -1,8 +1,19 @@ #!/usr/bin/env python3 -import importlib.util, io, os, pathlib, random, selectors, signal, socket, subprocess, sys +import argparse, importlib.util, io, os, pathlib, random, selectors, signal, socket, subprocess, sys + +parser = argparse.ArgumentParser() +parser.add_argument('module_path') +parser.add_argument('verilated') +parser.add_argument('image') +parser.add_argument('coverage_out', nargs='?') +args = parser.parse_args() + +module_path = args.module_path +verilated = args.verilated +image = args.image +coverage_out = args.coverage_out -module_path, verilated, image = sys.argv[1:] test_name = pathlib.Path(module_path).stem module = None @@ -390,6 +401,9 @@ exec_args.extend(['--control-fd', str(target_fd)]) init_regs = None exec_args.append(image) +if coverage_out: + exec_args.append(coverage_out) + exec_args.append(f'+verilator+seed+{seed}') if not os.getenv('SIM_PULLX', 0): exec_args.append('+verilator+rand+reset+2') diff --git a/tb/top/conspiracion.cpp b/tb/top/conspiracion.cpp index 4f0fb3d..49c05bf 100644 --- a/tb/top/conspiracion.cpp +++ b/tb/top/conspiracion.cpp @@ -261,6 +261,11 @@ int main(int argc, char **argv) parser, "image", "Executable image to run", args::Options::Required ); + args::Positional<std::string> coverage_out + ( + parser, "coverage-out", "Coverage output file" + ); + try { parser.ParseCLI(argc, argv); @@ -757,32 +762,25 @@ int main(int argc, char **argv) core.fetch->explicit_branch__VforceEn = 0; } - if(!no_tty) - { + if (!no_tty) ttyJ0.release(); - } - if(enable_trace) - { + if (enable_trace) trace.close(); - } - if(dump_regs) - { + if (dump_regs) do_reg_dump(); - } const auto &dumps = *dump_mem; - if(!dumps.empty()) - { + if (!dumps.empty()) do_mem_dump(dumps.data(), dumps.size()); - } top.final(); - if(ctrl != stdout) - { + if (ctrl != stdout) std::fclose(ctrl); - } + + if (coverage_out) + Verilated::threadContextp()->coveragep()->write(coverage_out->c_str()); return failed ? EXIT_FAILURE : EXIT_SUCCESS; } |
