From 54c2edb841a5572a5e6071cd3f2decbd026e6c5c Mon Sep 17 00:00:00 2001 From: Jared Bold Date: Mon, 5 Oct 2026 17:52:30 -0500 Subject: [PATCH] Change verilator_coverage to optimized executable (#8542) --- CMakeLists.txt | 4 +- Makefile.in | 4 +- bin/verilator_coverage | 63 ++++++++++++++++++--------- docs/CONTRIBUTORS | 1 + docs/guide/exe_verilator_coverage.rst | 8 ++++ docs/guide/install-cmake.rst | 5 +++ src/CMakeLists.txt | 43 +++++++++--------- src/Makefile.in | 20 +++++++-- src/Makefile_obj.in | 7 --- 9 files changed, 98 insertions(+), 57 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2933ee202..987bdb684 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ endif() option( DEBUG_AND_RELEASE_AND_COVERAGE - "Builds both the debug and release binaries, overriding CMAKE_BUILD_TYPE. Not supported under MSBuild." + "Builds debug and release binaries for Verilator and coverage, overriding CMAKE_BUILD_TYPE. Not supported under MSBuild." ) find_package(Python3 COMPONENTS Interpreter) @@ -137,6 +137,8 @@ if(DEBUG_AND_RELEASE_AND_COVERAGE) add_subdirectory(src build-Release) set(CMAKE_BUILD_TYPE Coverage) add_subdirectory(src build-Coverage) + set(CMAKE_BUILD_TYPE CoverageRelease) + add_subdirectory(src build-CoverageRelease) set(CMAKE_BUILD_TYPE ${saved_build_type}) else() add_subdirectory(src) diff --git a/Makefile.in b/Makefile.in index 386b69744..6303fc758 100644 --- a/Makefile.in +++ b/Makefile.in @@ -144,8 +144,9 @@ all_nomsg: verilator_exe $(VL_INST_MAN_FILES) .PHONY: verilator_exe .PHONY: verilator_bin$(EXEEXT) .PHONY: verilator_bin_dbg$(EXEEXT) +.PHONY: verilator_coverage_bin$(EXEEXT) .PHONY: verilator_coverage_bin_dbg$(EXEEXT) -verilator_exe verilator_bin$(EXEEXT) verilator_bin_dbg$(EXEEXT) verilator_coverage_bin_dbg$(EXEEXT): +verilator_exe verilator_bin$(EXEEXT) verilator_bin_dbg$(EXEEXT) verilator_coverage_bin$(EXEEXT) verilator_coverage_bin_dbg$(EXEEXT): @echo ------------------------------------------------------------ @echo "making verilator in src" $(MAKE) -C src $(OBJCACHE_JOBS) @@ -244,6 +245,7 @@ VL_INST_PUBLIC_SCRIPT_FILES = \ VL_INST_PUBLIC_BIN_FILES = \ verilator_bin$(EXEEXT) \ verilator_bin_dbg$(EXEEXT) \ + verilator_coverage_bin$(EXEEXT) \ verilator_coverage_bin_dbg$(EXEEXT) \ # Private executabels intended to be invoked by internals diff --git a/bin/verilator_coverage b/bin/verilator_coverage index 4854f5117..ce728a918 100755 --- a/bin/verilator_coverage +++ b/bin/verilator_coverage @@ -45,6 +45,7 @@ if (! GetOptions ( # Major operating modes "help" => \&usage, "debug:s" => \&debug, + "debugi=i" => sub { $Debug ||= 1; }, # "version!" => \&version, # Also passthru'ed # Additional parameters "<>" => sub {}, # Ignored @@ -73,30 +74,48 @@ sub debug { # Builds sub verilator_coverage_bin { - my $bin = ""; - # Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path - my $basename = ($ENV{VERILATOR_COVERAGE_BIN} - || "verilator_coverage_bin_dbg"); - if (defined($ENV{VERILATOR_ROOT})) { - my $dir = $ENV{VERILATOR_ROOT}; - if (-x "$dir/bin/$basename" - || -x "$dir/bin/$basename.exe") { # From a "make install" into VERILATOR_ROOT - $bin = "$dir/bin/$basename"; - } else { - $bin = "$dir/$basename"; # From pointing to kit directory - } + my @basenames = (); + if ($ENV{VERILATOR_COVERAGE_BIN}) { + push @basenames, $ENV{VERILATOR_COVERAGE_BIN}; } else { - if (-x "$RealBin/$basename" - || -x "$RealBin/$basename.exe") { - $bin = "$RealBin/$basename"; # From path/to/verilator with verilator_bin installed - } else { - $bin = $basename; # Find in PATH + if (!$Debug) { + push @basenames, "verilator_coverage_bin"; } - # Note we don't look under bin/$basename which would be right if running - # in the kit dir. Running that would likely break, since - # VERILATOR_ROOT wouldn't be set and Verilator won't find internal files. + # Fall back to dbg version if opt can't be found + push @basenames, "verilator_coverage_bin_dbg"; } - return $bin; + + for my $basename (@basenames) { + # Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path + if (defined($ENV{VERILATOR_ROOT})) { + my $dir = $ENV{VERILATOR_ROOT}; + if (bin_exists("$dir/bin/$basename")) { # From a "make install" into VERILATOR_ROOT + return "$dir/bin/$basename"; + } elsif (bin_exists("$dir/$basename")) { + return "$dir/$basename"; # From pointing to kit directory + } + } else { + if (bin_exists("$RealBin/$basename")) { + return "$RealBin/$basename"; # From path/to/verilator with verilator_bin installed + } + # Note we don't look under bin/$basename which would be right if running + # in the kit dir. Running that would likely break, since + # VERILATOR_ROOT wouldn't be set and Verilator won't find internal files. + } + } + if (defined($ENV{VERILATOR_ROOT})) { + warn "%Error: verilator_coverage: VERILATOR_ROOT set but could not find coverage binary.\n"; + warn "%Error: VERILATOR_ROOT=$ENV{VERILATOR_ROOT}\n"; + exit 1; + } + + # Find in path + return $basenames[0]; +} + +sub bin_exists { + my $path = shift; + return -x "$path" || -x "$path.exe"; } ####################################################################### @@ -177,6 +196,8 @@ L. --annotate-all All files should be shown. --annotate-min Minimum occurrence count for uncovered. --annotate-points Annotates info from each coverage point. + --debug Enable debugging with the debug executable. + --debugi Set debug level using the debug executable. --filter-type Keep only records of given coverage type. --help Displays this message and version and exits. --include-reset-arcs Include reset arcs in FSM arc summaries. diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index c56ab04dd..11bbce658 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -147,6 +147,7 @@ James Shi Jamey Hicks Jamie Iles Jan Van Winkel +Jared Bold Jean Berniolles Jean-Nicolas Strauss Jeffrey Song diff --git a/docs/guide/exe_verilator_coverage.rst b/docs/guide/exe_verilator_coverage.rst index 923c5ec38..6574772e1 100644 --- a/docs/guide/exe_verilator_coverage.rst +++ b/docs/guide/exe_verilator_coverage.rst @@ -131,6 +131,14 @@ verilator_coverage Arguments This option should be used together with :option:`--annotate`. +.. option:: --debug + + Runs the debug executable and enables debugging messages. + +.. option:: --debugi + + Runs the debug executable and sets the debugging level. + .. option:: --filter-type Keeps records of coverage types that matches with diff --git a/docs/guide/install-cmake.rst b/docs/guide/install-cmake.rst index f7ce15acf..7d350eed8 100644 --- a/docs/guide/install-cmake.rst +++ b/docs/guide/install-cmake.rst @@ -59,6 +59,11 @@ To build using ninja: cmake --install . --prefix $PWD/../install +For coverage tools, use ``CMAKE_BUILD_TYPE=CoverageRelease`` to build +``verilator_coverage_bin`` or ``CMAKE_BUILD_TYPE=Coverage`` to build +``verilator_coverage_bin_dbg``. + + .. _cmake usage: Usage diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 798bfbac1..baf2cf904 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -530,30 +530,32 @@ foreach(astgen_name ${ASTGENERATED_NAMES}) endforeach() # -# Set up the Coverage build type +# Set up the coverage build types (Coverage retains the debug build) addbuildtype(DEBUG COVERAGE) +addbuildtype(RELEASE COVERAGERELEASE) -# This regenerates include/verilated_cov_key.h in the source tree. -# It is a custom_target, not custom_command, because vlcovgen.d is -# a phony target (it doesn't exist as a file). -add_custom_target( - vlcovgen.d${CMAKE_BUILD_TYPE} - DEPENDS ../include/verilated_cov_key.h ${VLCOVGEN} - COMMENT "Updating include/verilated_cov_key.h" - COMMAND ${PYTHON3} ${VLCOVGEN} --srcdir ${srcdir} -) +# All configurations share this source header and must use a single writer. +if(NOT TARGET vlcovgen) + add_custom_target( + vlcovgen + DEPENDS ${srcdir}/../include/verilated_cov_key.h ${VLCOVGEN} + COMMENT "Updating include/verilated_cov_key.h" + COMMAND ${PYTHON3} ${VLCOVGEN} --srcdir ${srcdir} + ) +endif() # # Set up the verilator binary target set(verilator verilator${CMAKE_BUILD_TYPE}) +set(coverage_config $,$>) add_executable( ${verilator} - $<$>:${COMMON_SOURCES}> - $<$>:${GENERATED_FILES}> - $<$:${COVERAGE_SOURCES} + $<$:${COMMON_SOURCES}> + $<$:${GENERATED_FILES}> + $<${coverage_config}:${COVERAGE_SOURCES} config_rev.h> ) @@ -563,8 +565,9 @@ set_target_properties( OUTPUT_NAME_RELEASE verilator_bin OUTPUT_NAME_DEBUG verilator_bin_dbg OUTPUT_NAME_COVERAGE verilator_coverage_bin_dbg + OUTPUT_NAME_COVERAGERELEASE verilator_coverage_bin #UNITY_BUILD $,FALSE,${CMAKE_UNITY_BUILD}> - MSVC_RUNTIME_LIBRARY MultiThreaded$,,DebugDLL> + MSVC_RUNTIME_LIBRARY MultiThreaded$,$>,,DebugDLL> #JOB_POOL_LINK one_job # Linking takes lots of resources INTERPROCEDURAL_OPTIMIZATION_RELEASE $ ) @@ -581,19 +584,13 @@ endif() add_dependencies( ${verilator} + vlcovgen V3Lexer_yy_cpp${CMAKE_BUILD_TYPE} V3PreLex_yy_cpp${CMAKE_BUILD_TYPE} ) target_link_libraries(${verilator} PRIVATE Threads::Threads) -# verilated_cov_key.h is only regenerated in a single-configuration environment. -# This limitation can be lifted when `add_dependencies` will support generator -# expressions. See https://gitlab.kitware.com/cmake/cmake/issues/19467 -if(CMAKE_BUILD_TYPE STREQUAL Coverage) - add_dependencies(${verilator} vlcovgen.d${CMAKE_BUILD_TYPE}) -endif() - if(NOT MSVC) target_compile_features(${verilator} PRIVATE cxx_std_11) endif() @@ -602,8 +599,8 @@ target_compile_definitions( ${verilator} PRIVATE YYDEBUG # Required to get nice error messages - $<$:VL_DEBUG> - $<$:_GLIBCXX_DEBUG> + $<$,$>:VL_DEBUG> + $<$,$>:_GLIBCXX_DEBUG> ) target_include_directories( diff --git a/src/Makefile.in b/src/Makefile.in index d793fb698..5632f6ec6 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -46,22 +46,29 @@ obj_opt: mkdir -p $@ obj_dbg: mkdir -p $@ +obj_shared: + mkdir -p $@ ../bin: mkdir -p $@ .SUFFIXES: -.PHONY: ../bin/verilator_bin$(EXEEXT) ../bin/verilator_bin_dbg$(EXEEXT) ../bin/verilator_coverage_bin_dbg$(EXEEXT) +.PHONY: ../bin/verilator_bin$(EXEEXT) ../bin/verilator_bin_dbg$(EXEEXT) ../bin/verilator_coverage_bin$(EXEEXT) ../bin/verilator_coverage_bin_dbg$(EXEEXT) -opt: ../bin/verilator_bin$(EXEEXT) +opt: ../bin/verilator_bin$(EXEEXT) ../bin/verilator_coverage_bin$(EXEEXT) ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build ../bin/verilator_bin$(EXEEXT): ../bin/verilator_bin_dbg$(EXEEXT) -cp -p $< $@.tmp -mv -f $@.tmp $@ + ../bin/verilator_coverage_bin$(EXEEXT): ../bin/verilator_coverage_bin_dbg$(EXEEXT) + -cp -p $< $@.tmp + -mv -f $@.tmp $@ else ../bin/verilator_bin$(EXEEXT): obj_opt ../bin prefiles $(MAKE) -C obj_opt -j 1 TGT=../$@ -f ../Makefile_obj serial $(MAKE) -C obj_opt TGT=../$@ -f ../Makefile_obj + ../bin/verilator_coverage_bin$(EXEEXT): obj_opt ../bin prefiles + $(MAKE) -C obj_opt TGT=../$@ VL_VLCOV=1 -f ../Makefile_obj endif dbg: ../bin/verilator_bin_dbg$(EXEEXT) ../bin/verilator_coverage_bin_dbg$(EXEEXT) @@ -70,7 +77,6 @@ dbg: ../bin/verilator_bin_dbg$(EXEEXT) ../bin/verilator_coverage_bin_dbg$(EXEEXT $(BEAR_OBJ_OPT) $(MAKE) -C obj_dbg TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj ../bin/verilator_coverage_bin_dbg$(EXEEXT): obj_dbg ../bin prefiles - $(MAKE) -C obj_dbg TGT=../$@ VL_DEBUG=1 VL_VLCOV=1 -f ../Makefile_obj serial_vlcov $(MAKE) -C obj_dbg TGT=../$@ VL_DEBUG=1 VL_VLCOV=1 -f ../Makefile_obj ifneq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... don't rebuild each commit @@ -80,7 +86,13 @@ ifneq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... don't rebuil endif prefiles:: -prefiles:: config_rev.h +prefiles:: config_rev.h obj_shared/vlcovgen.d + +# Generate the shared header once, before any binary can read it. +obj_shared/vlcovgen.d: ${srcdir}/vlcovgen ${srcdir}/../include/verilated_cov_key.h | obj_shared + $(PYTHON3) ${srcdir}/vlcovgen --srcdir ${srcdir} + touch $@ + # This output goes into srcdir if locally configured, as we need to distribute it as part of the kit. config_rev.h: ${srcdir}/config_rev $(GIT_CHANGE_DEP) $(PYTHON3) ${srcdir}/config_rev ${srcdir} >$@ diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index 76eae2230..9c1c1a47d 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -156,7 +156,6 @@ HEADERS = $(wildcard V*.h v*.h) ASTGEN = $(srcdir)/astgen BISONPRE = $(srcdir)/bisonpre FLEXFIX = $(srcdir)/flexfix -VLCOVGEN = $(srcdir)/vlcovgen # BISON_DEBUG = -Wcounterexamples @@ -449,12 +448,6 @@ $(foreach obj,$(RAW_OBJS_PCH_ASTNOMT),$(eval $(call CXX_ASTNOMT_template,$(obj)) # Target rule called before parallel build to make generated files serial:: V3Ast__gen_forward_class_decls.h V3ParseBison.c -serial_vlcov:: vlcovgen.d - -vlcovgen.d: $(VLCOVGEN) $(srcdir)/../include/verilated_cov_key.h - $(PYTHON3) $(VLCOVGEN) --srcdir $(srcdir) - touch $@ - V3Ast__gen_forward_class_decls.h: $(ASTGEN) $(AST_DEFS) $(DFG_DEFS) $(PYTHON3) $(ASTGEN) $(ASTGENFLAGS) --classes