797 lines
26 KiB
Makefile
797 lines
26 KiB
Makefile
#*****************************************************************************
|
|
# DESCRIPTION: Verilator top level: Makefile pre-configure version
|
|
#
|
|
# This file is part of Verilator.
|
|
#
|
|
# Code available from: https://verilator.org
|
|
#
|
|
#*****************************************************************************
|
|
#
|
|
# Copyright 2003-2025 by Wilson Snyder. This program is free software; you
|
|
# can redistribute it and/or modify it under the terms of either the GNU
|
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
|
# Version 2.0.
|
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
#
|
|
#****************************************************************************/
|
|
#
|
|
# make all to compile and build Verilator.
|
|
# make install to install it.
|
|
# make TAGS to update tags tables.
|
|
#
|
|
# make clean or make mostlyclean
|
|
# Delete all files from the current directory that are normally
|
|
# created by building the program. Don't delete the files that
|
|
# record the configuration. Also preserve files that could be made
|
|
# by building, but normally aren't because the distribution comes
|
|
# with them.
|
|
#
|
|
# make distclean
|
|
# Delete all files from the current directory that are created by
|
|
# configuring or building the program. If you have unpacked the
|
|
# source and built the program without creating any other files,
|
|
# `make distclean' should leave only the files that were in the
|
|
# distribution.
|
|
#
|
|
# make maintainer-clean
|
|
# Delete everything from the current directory that can be
|
|
# reconstructed with this Makefile. This typically includes
|
|
# everything deleted by distclean, plus more: C source files
|
|
# produced by Bison, tags tables, info files, and so on.
|
|
|
|
#### Start of system configuration section. ####
|
|
|
|
srcdir = @srcdir@
|
|
VPATH = @srcdir@
|
|
HOST = @HOST@
|
|
EXEEXT = @EXEEXT@
|
|
|
|
DOXYGEN = doxygen
|
|
INSTALL = @INSTALL@
|
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
|
INSTALL_DATA = @INSTALL_DATA@
|
|
MAKEINFO = makeinfo
|
|
POD2TEXT = pod2text
|
|
PYTHON3 = @PYTHON3@
|
|
MKINSTALLDIRS = $(SHELL) $(srcdir)/src/mkinstalldirs
|
|
|
|
# Version (for docs/guide/conf.py)
|
|
PACKAGE_VERSION_NUMBER = @PACKAGE_VERSION_NUMBER@
|
|
|
|
# Destination prefix for RPMs
|
|
DESTDIR =
|
|
|
|
#### Don't edit: You're much better using configure switches to set these
|
|
prefix = @prefix@
|
|
exec_prefix = @exec_prefix@
|
|
|
|
# Directory in which to install scripts.
|
|
bindir = @bindir@
|
|
|
|
# Directory in which to install manpages.
|
|
mandir = @mandir@
|
|
|
|
# Directory in which to install library files.
|
|
datadir = @datadir@
|
|
|
|
# Directory in which to install documentation info files.
|
|
infodir = @infodir@
|
|
|
|
# Directory in which to install package-specific files
|
|
# Generally ${prefix}/share/verilator
|
|
pkgdatadir = @pkgdatadir@
|
|
|
|
# Directory in which to install pkgconfig file
|
|
# Generally ${prefix}/share/pkgconfig
|
|
pkgconfigdir = @pkgconfigdir@
|
|
|
|
# Directory in which to install data across multiple architectures
|
|
datarootdir = @datarootdir@
|
|
|
|
# Compile options
|
|
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
|
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
|
CFG_WITH_DEV_GCOV = @CFG_WITH_DEV_GCOV@
|
|
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
|
CFG_WITH_SOLVER = @CFG_WITH_SOLVER@
|
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
|
|
|
#### End of system configuration section. ####
|
|
######################################################################
|
|
# Main build targets
|
|
|
|
.SUFFIXES:
|
|
|
|
SHELL = /bin/sh
|
|
|
|
SUBDIRS = docs src test_regress \
|
|
examples/cmake_hello_c \
|
|
examples/cmake_hello_sc \
|
|
examples/cmake_tracing_c \
|
|
examples/cmake_tracing_sc \
|
|
examples/cmake_protect_lib \
|
|
examples/make_hello_binary \
|
|
examples/make_hello_c \
|
|
examples/make_hello_sc \
|
|
examples/make_tracing_c \
|
|
examples/make_tracing_sc \
|
|
examples/make_protect_lib \
|
|
examples/json_py \
|
|
|
|
INFOS = verilator.html verilator.pdf
|
|
|
|
INFOS_OLD = README README.html README.pdf
|
|
|
|
EXAMPLES_FIRST = \
|
|
examples/make_hello_c \
|
|
examples/make_hello_sc \
|
|
|
|
EXAMPLES = $(EXAMPLES_FIRST) $(filter-out $(EXAMPLES_FIRST), $(sort $(wildcard examples/*)))
|
|
|
|
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
|
|
# No verilator_ccache_report.1, verilator_difftree.1 as those are not bin/ installed
|
|
VL_INST_MAN_FILES = \
|
|
verilator.1 \
|
|
verilator_coverage.1 \
|
|
verilator_gantt.1 \
|
|
verilator_profcfunc.1 \
|
|
|
|
default: all
|
|
all: all_nomsg msg_test
|
|
all_nomsg: verilator_exe $(VL_INST_MAN_FILES)
|
|
|
|
.PHONY: verilator_exe
|
|
.PHONY: verilator_bin$(EXEEXT)
|
|
.PHONY: verilator_bin_dbg$(EXEEXT)
|
|
.PHONY: verilator_coverage_bin_dbg$(EXEEXT)
|
|
verilator_exe verilator_bin$(EXEEXT) verilator_bin_dbg$(EXEEXT) verilator_coverage_bin_dbg$(EXEEXT):
|
|
@echo ------------------------------------------------------------
|
|
@echo "making verilator in src"
|
|
$(MAKE) -C src $(OBJCACHE_JOBS)
|
|
|
|
######################################################################
|
|
# Tests
|
|
|
|
.PHONY: msg_test
|
|
msg_test: all_nomsg
|
|
@echo "Build complete!"
|
|
@echo
|
|
@echo "Now type 'make test' to test."
|
|
@echo
|
|
|
|
.PHONY: test
|
|
ifeq ($(CFG_WITH_LONGTESTS),yes) # Local... Else don't burden users
|
|
test: smoke-test test_regress
|
|
# examples is part of test_regress's test_regress/t/t_a2_examples.py
|
|
# (because that allows it to run in parallel with other test_regress's)
|
|
else
|
|
test: smoke-test examples
|
|
endif
|
|
@echo "Tests passed!"
|
|
@echo
|
|
@echo "Now type 'make install' to install."
|
|
@echo "Or type 'make' inside an examples subdirectory."
|
|
@echo
|
|
|
|
smoke-test: all_nomsg
|
|
test_regress/t/t_a1_first_cc.py
|
|
test_regress/t/t_a2_first_sc.py
|
|
|
|
test_regress: all_nomsg
|
|
$(MAKE) -C test_regress
|
|
|
|
.PHONY: test-snap test-diff
|
|
test-snap test-diff:
|
|
$(MAKE) -C test_regress $@
|
|
|
|
examples: all_nomsg
|
|
for p in $(EXAMPLES) ; do \
|
|
$(MAKE) -C $$p VERILATOR_ROOT=`pwd` || exit 10; \
|
|
done
|
|
|
|
######################################################################
|
|
# Docs
|
|
|
|
.PHONY: docs
|
|
docs: info $(VL_INST_MAN_FILES)
|
|
|
|
info: $(INFOS)
|
|
|
|
verilator.1: ${srcdir}/bin/verilator
|
|
pod2man $< $@
|
|
verilator_coverage.1: ${srcdir}/bin/verilator_coverage
|
|
pod2man $< $@
|
|
%.1: ${srcdir}/bin/%
|
|
help2man --no-info --no-discard-stderr --version-string=- \
|
|
-n "$(shell $< --help | head -n 3 | tail -n 1)" $< -o $@
|
|
|
|
.PHONY: verilator.html
|
|
verilator.html:
|
|
$(MAKE) -C docs html
|
|
|
|
# PDF needs DIST variables; but having configure.ac as dependency isn't detected
|
|
.PHONY: verilator.pdf
|
|
verilator.pdf: Makefile
|
|
$(MAKE) -C docs verilator.pdf
|
|
|
|
TAGFILES = ${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \
|
|
${srcdir}/*.in ${srcdir}/*.pod
|
|
|
|
TAGS: $(TAGFILES)
|
|
etags $(TAGFILES)
|
|
|
|
.PHONY: doxygen
|
|
|
|
doxygen:
|
|
$(MAKE) -C docs doxygen
|
|
|
|
.PHONY: spelling
|
|
spelling:
|
|
$(MAKE) -C docs spelling
|
|
|
|
######################################################################
|
|
# Install
|
|
|
|
# Public executables intended to be invoked directly by the user
|
|
# Don't put wildcards in these variables, it might cause an uninstall of other stuff
|
|
VL_INST_PUBLIC_SCRIPT_FILES = \
|
|
verilator \
|
|
verilator_coverage \
|
|
verilator_gantt \
|
|
verilator_profcfunc \
|
|
|
|
VL_INST_PUBLIC_BIN_FILES = \
|
|
verilator_bin$(EXEEXT) \
|
|
verilator_bin_dbg$(EXEEXT) \
|
|
verilator_coverage_bin_dbg$(EXEEXT) \
|
|
|
|
# Private executabels intended to be invoked by internals
|
|
# Don't put wildcards in these variables, it might cause an uninstall of other stuff
|
|
VL_INST_PRIVATE_SCRIPT_FILES = \
|
|
verilator_ccache_report \
|
|
verilator_includer \
|
|
|
|
VL_INST_INC_BLDDIR_FILES = \
|
|
include/verilated_config.h \
|
|
include/verilated.mk \
|
|
|
|
# Files under srcdir, instead of build time
|
|
VL_INST_INC_SRCDIR_FILES = \
|
|
include/*.[chv]* \
|
|
include/*.vlt \
|
|
include/*.sv \
|
|
include/gtkwave/*.[chv]* \
|
|
include/vltstd/*.[chv]* \
|
|
|
|
VL_INST_DATA_SRCDIR_FILES = \
|
|
examples/*/*.[chv]* \
|
|
examples/*/CMakeLists.txt \
|
|
examples/*/Makefile* \
|
|
examples/*/vl_* \
|
|
|
|
mkbindirs:
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/bin
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(bindir)
|
|
|
|
installbin: | mkbindirs
|
|
cd $(srcdir)/bin; \
|
|
for p in $(VL_INST_PUBLIC_SCRIPT_FILES) ; do \
|
|
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
|
|
done
|
|
perl -p -i -e 'use File::Spec;' \
|
|
-e' $$path = File::Spec->abs2rel("$(realpath $(DESTDIR)$(pkgdatadir))", "$(realpath $(DESTDIR)$(bindir))");' \
|
|
-e 's/my \$$verilator_pkgdatadir_relpath = .*/my \$$verilator_pkgdatadir_relpath = "$$path";/g' \
|
|
-- "$(DESTDIR)/$(bindir)/verilator"
|
|
cd bin; \
|
|
for p in $(VL_INST_PUBLIC_BIN_FILES) ; do \
|
|
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
|
|
done
|
|
cd $(srcdir)/bin; \
|
|
for p in $(VL_INST_PRIVATE_SCRIPT_FILES) ; do \
|
|
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkgdatadir)/bin/$$p; \
|
|
done
|
|
|
|
installredirect: installbin | mkbindirs
|
|
cp ${srcdir}/bin/redirect ${srcdir}/bin/redirect.tmp
|
|
perl -p -i -e 'use File::Spec;' \
|
|
-e' $$path = File::Spec->abs2rel("$(realpath $(DESTDIR)$(bindir))", "$(realpath $(DESTDIR)$(pkgdatadir)/bin)");' \
|
|
-e 's/RELPATH.*/"$$path";/g' -- "${srcdir}/bin/redirect.tmp"
|
|
cd $(srcdir)/bin; \
|
|
for p in $(VL_INST_PUBLIC_SCRIPT_FILES) $(VL_INST_PUBLIC_BIN_FILES) ; do \
|
|
$(INSTALL_PROGRAM) redirect.tmp $(DESTDIR)$(pkgdatadir)/bin/$$p; \
|
|
done
|
|
rm ${srcdir}/bin/redirect.tmp
|
|
|
|
# Man files can either be part of the original kit, or built in current directory
|
|
# So important we use $^ so VPATH is searched
|
|
installman: $(VL_INST_MAN_FILES)
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man1
|
|
for p in $^ ; do \
|
|
$(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
|
|
done
|
|
|
|
installdata:
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/include/gtkwave
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/include/vltstd
|
|
for p in $(VL_INST_INC_BLDDIR_FILES) ; do \
|
|
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
|
|
done
|
|
cd $(srcdir) \
|
|
; for p in $(VL_INST_INC_SRCDIR_FILES) ; do \
|
|
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
|
|
done
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/make_hello_binary
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/make_hello_c
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/make_hello_sc
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/make_tracing_c
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/make_tracing_sc
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/make_protect_lib
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_hello_c
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_hello_sc
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_tracing_c
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_tracing_sc
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/cmake_protect_lib
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/examples/json_py
|
|
cd $(srcdir) \
|
|
; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \
|
|
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
|
|
done
|
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgconfigdir)
|
|
$(INSTALL_DATA) verilator.pc $(DESTDIR)$(pkgconfigdir)
|
|
$(INSTALL_DATA) verilator-config.cmake $(DESTDIR)$(pkgdatadir)
|
|
$(INSTALL_DATA) verilator-config-version.cmake $(DESTDIR)$(pkgdatadir)
|
|
|
|
# We don't trust rm -rf, so rmdir instead as it will fail if user put in other files
|
|
uninstall:
|
|
-cd $(DESTDIR)$(bindir) && rm -f $(VL_INST_PUBLIC_SCRIPT_FILES)
|
|
-cd $(DESTDIR)$(bindir) && rm -f $(VL_INST_PUBLIC_BIN_FILES)
|
|
-cd $(DESTDIR)$(pkgdatadir)/bin && rm -f $(VL_INST_PUBLIC_SCRIPT_FILES)
|
|
-cd $(DESTDIR)$(pkgdatadir)/bin && rm -f $(VL_INST_PUBLIC_BIN_FILES)
|
|
-cd $(DESTDIR)$(pkgdatadir)/bin && rm -f $(VL_INST_PRIVATE_SCRIPT_FILES)
|
|
-cd $(DESTDIR)$(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
|
|
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_BLDDIR_FILES)
|
|
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_SRCDIR_FILES)
|
|
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_DATA_SRCDIR_FILES)
|
|
-rm $(DESTDIR)$(pkgconfigdir)/verilator.pc
|
|
-rm $(DESTDIR)$(pkgdatadir)/verilator-config.cmake
|
|
-rm $(DESTDIR)$(pkgdatadir)/verilator-config-version.cmake
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/bin
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/include/gtkwave
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/include/vltstd
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/include
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/make_hello_binary
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/make_hello_c
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/make_hello_sc
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/make_tracing_c
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/make_tracing_sc
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/make_protect_lib
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_hello_c
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_hello_sc
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_tracing_c
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_tracing_sc
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/cmake_protect_lib
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples/json_py
|
|
-rmdir $(DESTDIR)$(pkgdatadir)/examples
|
|
-rmdir $(DESTDIR)$(pkgdatadir)
|
|
-rmdir $(DESTDIR)$(pkgconfigdir)
|
|
|
|
install: all_nomsg install-all
|
|
install-all: installbin installredirect installman installdata install-msg
|
|
|
|
install-here: installman info
|
|
|
|
install-msg:
|
|
@echo
|
|
@echo "Installed binaries to $(DESTDIR)$(bindir)/verilator"
|
|
@echo "Installed man to $(DESTDIR)$(mandir)/man1"
|
|
@echo "Installed examples to $(DESTDIR)$(pkgdatadir)/examples"
|
|
@echo
|
|
@echo "For documentation see 'man verilator' or 'verilator --help'"
|
|
@echo "For forums and to report bugs see https://verilator.org"
|
|
@echo
|
|
|
|
######################################################################
|
|
# Format/Lint
|
|
|
|
CPPCHECK_VERILATOR_CPP = $(wildcard $(srcdir)/src/V3*.cpp $(srcdir)/src/Verilator*.cpp)
|
|
CPPCHECK_RUNTIME_CPP = $(wildcard $(srcdir)/include/*.cpp)
|
|
CPPCHECK_VLC_CPP = $(wildcard $(srcdir)/src/Vlc*.cpp)
|
|
CPPCHECK_EXAMPLES_CPP = $(wildcard $(srcdir)/examples/*/*.cpp)
|
|
CHECK_CPP = $(CPPCHECK_VERILATOR_CPP) $(CPPCHECK_RUNTIME_CPP) $(CPPCHECK_VLC_CPP) $(CPPCHECK_EXAMPLES_CPP)
|
|
CHECK_H = $(wildcard \
|
|
$(srcdir)/include/*.h \
|
|
$(srcdir)/src/*.h )
|
|
CHECK_YL = $(wildcard \
|
|
$(srcdir)/src/*.y \
|
|
$(srcdir)/src/*.l )
|
|
CPPCHECK = cppcheck
|
|
CPPCHECK_JOBS = $(shell nproc)
|
|
CPPCHECK_CACHE = $(srcdir)/src/obj_dbg/cppcheck-cache
|
|
CPPCHECK_FLAGS = --enable=all
|
|
CPPCHECK_FLAGS += --inline-suppr
|
|
CPPCHECK_FLAGS += --suppressions-list=$(srcdir)/src/cppcheck-suppressions.txt
|
|
CPPCHECK_FLAGS += --cppcheck-build-dir=$(CPPCHECK_CACHE)
|
|
CPPCHECK_FLAGS += -DVL_DEBUG=1 -DVL_CPPCHECK=1 -DINFILTER_PIPE=1 -D__GNUC__=1
|
|
CPPCHECK_FLAGS += -j$(CPPCHECK_JOBS)
|
|
CPPCHECK_INC = -I$(srcdir)/include
|
|
CPPCHECK_INC += -I$(srcdir)/include/gtkwave
|
|
CPPCHECK_INC += -I$(srcdir)/include/vltstd
|
|
CPPCHECK_INC += -I$(srcdir)/src/obj_dbg
|
|
CPPCHECK_INC += -I$(srcdir)/src
|
|
|
|
$(CPPCHECK_CACHE): $(CHECK_CPP) $(CHECK_H) $(CHECK_YL)
|
|
/bin/rm -rf $@
|
|
/bin/mkdir -p $@
|
|
|
|
cppcheck-verilator: | $(CPPCHECK_CACHE)
|
|
$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK_VERILATOR_CPP)
|
|
cppcheck-runtime: | $(CPPCHECK_CACHE)
|
|
$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK_RUNTIME_CPP)
|
|
cppcheck-vlc: | $(CPPCHECK_CACHE)
|
|
$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK_VLC_CPP)
|
|
cppcheck-examples: | $(CPPCHECK_CACHE)
|
|
$(CPPCHECK) $(CPPCHECK_FLAGS) $(CPPCHECK_INC) $(CPPCHECK_EXAMPLES_CPP)
|
|
|
|
cppcheck:
|
|
$(MAKE) cppcheck-vlc
|
|
$(MAKE) cppcheck-examples
|
|
$(MAKE) cppcheck-runtime
|
|
$(MAKE) cppcheck-verilator
|
|
|
|
CLANGTIDY = clang-tidy
|
|
CLANGTIDY_FLAGS = -config='' \
|
|
-header-filter='.*' \
|
|
-checks='-fuchsia-*,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-init-variables,-cppcoreguidelines-avoid-goto,-modernize-avoid-c-arrays,-readability-magic-numbers,-readability-simplify-boolean-expr,-cppcoreguidelines-macro-usage' \
|
|
|
|
CLANGTIDY_DEP = $(subst .cpp,.cpp.tidy,$(CHECK_CPP))
|
|
CLANGTIDY_DEFS = -DVL_DEBUG=1 -DVL_CPPCHECK=1
|
|
|
|
clang-tidy: $(CLANGTIDY_DEP)
|
|
%.cpp.tidy: %.cpp
|
|
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- $(CLANGTIDY_DEFS) $(CPPCHECK_INC) | 2>&1 tee $@
|
|
%.h.tidy: %.h
|
|
$(CLANGTIDY) $(CLANGTIDY_FLAGS) $< -- $(CLANGTIDY_DEFS) $(CPPCHECK_INC) -x c++-header | 2>&1 tee $@
|
|
|
|
analyzer-src:
|
|
-rm -rf src/obj_dbg
|
|
scan-build $(MAKE) -k verilator_coverage_bin_dbg$(EXEEXT) verilator_bin_dbg$(EXEEXT)
|
|
|
|
analyzer-include:
|
|
-rm -rf examples/*/obj*
|
|
scan-build $(MAKE) -k examples
|
|
|
|
format:
|
|
$(MAKE) -j 5 format-c format-cmake format-exec format-py
|
|
|
|
CLANGFORMAT = clang-format-18
|
|
CLANGFORMAT_FLAGS = -i
|
|
CLANGFORMAT_FILES = $(CHECK_CPP) $(CHECK_H) $(CHECK_YL) test_regress/t/*.c* test_regress/t/*.h
|
|
|
|
format-c clang-format:
|
|
$(CLANGFORMAT) --version
|
|
@$(CLANGFORMAT) --version | fgrep 'version 18' > /dev/null \
|
|
|| echo "*** You are not using clang-format-18, indents may differ from master's ***"
|
|
$(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CLANGFORMAT_FILES)
|
|
|
|
YAMLFIX = YAMLFIX_WHITELINES=1 YAMLFIX_LINE_LENGTH=200 YAMLFIX_preserve_quotes=true yamlfix
|
|
|
|
yamlfix:
|
|
$(YAMLFIX) .
|
|
|
|
# CMake files
|
|
CMAKE_FILES = \
|
|
CMakeLists.txt \
|
|
examples/*/CMakeLists.txt \
|
|
src/CMakeLists.txt \
|
|
test_regress/CMakeLists.txt \
|
|
*.cmake.in \
|
|
|
|
# Makefiles
|
|
MAKE_FILES = \
|
|
Makefile*.in \
|
|
docs/Makefile* \
|
|
include/verilated.mk.in \
|
|
examples/*/Makefile* \
|
|
src/Makefile*.in \
|
|
test_regress/Makefile* \
|
|
|
|
# Python programs, subject to format and lint
|
|
PY_PROGRAMS = \
|
|
bin/verilator_ccache_report \
|
|
bin/verilator_difftree \
|
|
bin/verilator_gantt \
|
|
bin/verilator_includer \
|
|
bin/verilator_profcfunc \
|
|
examples/json_py/vl_file_copy \
|
|
examples/json_py/vl_hier_graph \
|
|
docs/guide/conf.py \
|
|
docs/bin/vl_sphinx_extract \
|
|
docs/bin/vl_sphinx_fix \
|
|
src/astgen \
|
|
src/bisonpre \
|
|
src/config_rev \
|
|
src/flexfix \
|
|
src/vlcovgen \
|
|
src/.gdbinit.py \
|
|
test_regress/*.py \
|
|
test_regress/t/*.pf \
|
|
nodist/clang_check_attributes \
|
|
nodist/dot_importer \
|
|
nodist/fuzzer/actual_fail \
|
|
nodist/fuzzer/generate_dictionary \
|
|
nodist/install_test \
|
|
nodist/log_changes \
|
|
|
|
# Python files, subject to format but not lint
|
|
PY_FILES = \
|
|
$(PY_PROGRAMS) \
|
|
test_regress/t/*.py \
|
|
|
|
# Python files, test_regress tests
|
|
PY_TEST_FILES = test_regress/t/*.py
|
|
|
|
YAPF = yapf3
|
|
YAPF_FLAGS = -i --parallel
|
|
|
|
format-py yapf:
|
|
$(YAPF) --version
|
|
$(YAPF) $(YAPF_FLAGS) $(PY_FILES)
|
|
|
|
GERSEMI = gersemi
|
|
GERSEMI_FLAGS = -i --no-warn-about-unknown-commands
|
|
|
|
format-cmake:
|
|
$(GERSEMI) $(GERSEMI_FLAGS) $(CMAKE_FILES)
|
|
|
|
MBAKE = mbake
|
|
MBAKE_FLAGS = format --config ./.bake.toml
|
|
|
|
format-make:
|
|
$(MBAKE) $(MBAKE_FLAGS) $(MAKE_FILES)
|
|
|
|
format-yaml: yamlfix
|
|
|
|
PYLINT = pylint
|
|
PYLINT_FLAGS = --recursive=n --score=n --disable=R0801
|
|
PYLINT_TEST_FLAGS = $(PYLINT_FLAGS) --disable=C0103,C0114,C0116,C0209,C0411,C0413,C0301,R0801,R0912,R0915,R0916,R1702,W0511,W0621
|
|
|
|
RUFF = ruff
|
|
RUFF_FLAGS = check --ignore=E402,E501,E701
|
|
|
|
# "make -k" so can see all tool result errors
|
|
lint-py:
|
|
$(MAKE) -k lint-py-pylint lint-py-pylint-tests lint-py-ruff
|
|
|
|
lint-py-pylint:
|
|
$(PYLINT) $(PYLINT_FLAGS) $(PY_PROGRAMS)
|
|
|
|
lint-py-pylint-tests:
|
|
$(PYLINT) $(PYLINT_TEST_FLAGS) $(PY_TEST_FILES) | $(PYTHON3) nodist/lint_py_test_filter
|
|
|
|
lint-py-ruff:
|
|
$(RUFF) $(RUFF_FLAGS) $(PY_PROGRAMS)
|
|
|
|
format-exec:
|
|
-chmod a+x test_regress/t/*.py
|
|
|
|
######################################################################
|
|
# Configure
|
|
|
|
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in
|
|
|
|
# autoheader might not change config_package.h.in, so touch it
|
|
${srcdir}/config_package.h: ${srcdir}/config_package.h.in configure
|
|
cd ${srcdir} && autoheader
|
|
touch $@
|
|
Makefile: Makefile.in config.status $(IN_WILD)
|
|
./config.status
|
|
src/Makefile: src/Makefile.in Makefile
|
|
config.status: configure
|
|
./config.status --recheck
|
|
|
|
configure: configure.ac
|
|
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
|
autoconf --warnings=all
|
|
else
|
|
autoconf
|
|
endif
|
|
|
|
######################################################################
|
|
# Coverage collection and reporting
|
|
|
|
COVERAGE_DIR := obj_coverage
|
|
|
|
ifeq ($(CFG_WITH_DEV_GCOV),yes)
|
|
|
|
# Figure out base and head refs for coverage report
|
|
COVERAGE_REF_BASE := $(if $(COVERAGE_BASE),$(shell git rev-parse --short $(COVERAGE_BASE)))
|
|
COVERAGE_REF_HEAD := $(shell git rev-parse --short HEAD)
|
|
override undefine COVERAGE_BASE # Use the above variabels instead
|
|
|
|
# 'fastcov' setup
|
|
FASTCOV := nodist/fastcov.py
|
|
FASTCOV_OPT := -j $(shell nproc)
|
|
FASTCOV_OPT += --lcov
|
|
FASTCOV_OPT += --process-gcno
|
|
FASTCOV_OPT += --branch-coverage
|
|
FASTCOV_OPT += --dump-statistic
|
|
# Files matching the following glob patterns will be excluded from coverage
|
|
FASTCOV_OPT += --exclude-glob
|
|
FASTCOV_OPT += '/usr/*'
|
|
FASTCOV_OPT += '*examples/*'
|
|
FASTCOV_OPT += '*include/gtkwave/*'
|
|
FASTCOV_OPT += '*src/obj_dbg/*'
|
|
FASTCOV_OPT += '*src/obj_opt/*.yy.cpp'
|
|
FASTCOV_OPT += '*src/obj_opt/V3Ast*'
|
|
FASTCOV_OPT += '*src/obj_opt/V3Dfg*'
|
|
FASTCOV_OPT += '*src/obj_opt/V3ParseBison.c'
|
|
FASTCOV_OPT += '*test_regress/*'
|
|
# Lines *containing* these substrings will be excluded from *all* coverage
|
|
FASTCOV_OPT += --custom-exclusion-marker
|
|
FASTCOV_OPT += ASTGEN_MEMBERS
|
|
FASTCOV_OPT += ERROR_RSVD_WORD
|
|
FASTCOV_OPT += LCOV_EXCL_LINE
|
|
FASTCOV_OPT += V3ERROR_NA
|
|
FASTCOV_OPT += VL_DEFINE_DEBUG_FUNCTIONS
|
|
FASTCOV_OPT += VL_FATAL
|
|
FASTCOV_OPT += VL_RTTI_IMPL
|
|
FASTCOV_OPT += VL_UNREACHABLE
|
|
FASTCOV_OPT += v3fatalSrc
|
|
# Lines *starting* with these substrings will be ecluded from *branch* coverage
|
|
FASTCOV_OPT += --exclude-br-lines-starting-with
|
|
FASTCOV_OPT += BROKEN_BASE_RTN
|
|
FASTCOV_OPT += BROKEN_RTN
|
|
FASTCOV_OPT += NUM_ASSERT
|
|
FASTCOV_OPT += SELF_CHECK
|
|
FASTCOV_OPT += UASSERT
|
|
FASTCOV_OPT += UINFO
|
|
FASTCOV_OPT += assert
|
|
FASTCOV_OPT += 'if (VL_UNCOVERABLE'
|
|
FASTCOV_OPT += '} else if (VL_UNCOVERABLE'
|
|
|
|
# 'genhtml' setup
|
|
GENHTML := genhtml
|
|
GENHTML_OPT := -j $(shell nproc)
|
|
GENHTML_OPT += --branch-coverage
|
|
GENHTML_OPT += --demangle-cpp
|
|
GENHTML_OPT += --missed
|
|
GENHTML_OPT += --rc branch_coverage=1
|
|
GENHTML_OPT += --rc genhtml_hi_limit=100
|
|
GENHTML_OPT += --ignore-errors negative
|
|
ifeq ($(COVERAGE_REF_BASE),)
|
|
GENHTML_OPT += --header-title "Code coverage for Verilator $(shell git describe --dirty)"
|
|
else
|
|
GENHTML_OPT += --header-title "Patch coverage for Verilator $(COVERAGE_REF_BASE)..$(COVERAGE_REF_HEAD)$(if $(shell git status --porcelain),-dirty)"
|
|
endif
|
|
GENHTML_OPT += --flat
|
|
GENHTML_OPT += --precision 2
|
|
GENHTML_OPT += --legend
|
|
GENHTML_OPT += --show-proportion
|
|
GENHTML_OPT += --filter brace,blank,range
|
|
|
|
# There are loads (~20k combined), but using this seems fine on modern hardware
|
|
GCNO_FILES = $(shell find . -name '*.gcno')
|
|
GCDA_FILES = $(shell find . -name '*.gcda')
|
|
|
|
# Combine all .gcda coverage date files into lcov .info file
|
|
$(COVERAGE_DIR)/verilator.info: $(GCNO_FILES) $(GCDA_FILES)
|
|
@echo "####################################################################"
|
|
@echo "# fastcov: combining all .gcda files into lcov .info"
|
|
@echo "####################################################################"
|
|
@mkdir -p $(COVERAGE_DIR)
|
|
/usr/bin/time -f "That took %E" \
|
|
$(FASTCOV) $(FASTCOV_OPT) --output $@
|
|
|
|
# Filter combined .info file for patch coverage
|
|
$(COVERAGE_DIR)/verilator-patch.info: $(COVERAGE_DIR)/verilator.info
|
|
@echo "####################################################################"
|
|
@echo "# fastcov: Filtering for patch coverage"
|
|
@echo "####################################################################"
|
|
rm -f $(COVERAGE_DIR)/empty-patch
|
|
git diff $(COVERAGE_REF_BASE) -- include src > $(COVERAGE_DIR)/filter.patch
|
|
[ -s $(COVERAGE_DIR)/filter.patch ]] || touch $(COVERAGE_DIR)/empty-patch
|
|
$(FASTCOV) -C $^ --lcov -o $@ --diff-filter $(COVERAGE_DIR)/filter.patch
|
|
|
|
# Build coverage report
|
|
$(COVERAGE_DIR)/report/index.html: $(COVERAGE_DIR)/verilator$(if $(COVERAGE_REF_BASE),-patch).info
|
|
@echo "####################################################################"
|
|
@echo "# genhtml: Generating coverage report"
|
|
@echo "####################################################################"
|
|
@rm -rf $(COVERAGE_DIR)/report
|
|
[ -f $(COVERAGE_DIR)/empty-patch ]] || /usr/bin/time -f "That took %E" \
|
|
$(GENHTML) $(GENHTML_OPT) --output-directory $(COVERAGE_DIR)/report $^ || true
|
|
@# Uncommitted changes not tracked, force rebuild on next run if patch coverage
|
|
@$(if $(COVERAGE_REF_BASE),mv $(COVERAGE_DIR)/verilator-patch.info $(COVERAGE_DIR)/verilator-patch-last.info)
|
|
|
|
# Convenience targets
|
|
.PHONY: coverage-combine
|
|
coverage-combine: $(COVERAGE_DIR)/verilator.info
|
|
|
|
# Via recursive make, so the message is always printed
|
|
.PHONY: coverage-report
|
|
coverage-report:
|
|
@$(MAKE) --no-print-directory $(COVERAGE_DIR)/report/index.html || true
|
|
@if [ -f $(COVERAGE_DIR)/report/index.html ]; then \
|
|
echo "####################################################################"; \
|
|
echo "# Coverage report is at: $(COVERAGE_DIR)/report/index.html"; \
|
|
echo "# Use 'make coverage-view' to open it in your default browser"; \
|
|
echo "####################################################################"; \
|
|
elif [ -f $(COVERAGE_DIR)/empty-patch ]; then \
|
|
echo "####################################################################"; \
|
|
echo "# Patch is empty"; \
|
|
echo "####################################################################"; \
|
|
else \
|
|
echo "####################################################################"; \
|
|
echo "# Failed to create coverage report. Maybe no data, or error?"; \
|
|
echo "####################################################################"; \
|
|
false; \
|
|
fi
|
|
|
|
# Open covarage report in default web browser
|
|
.PHONY: coverage-view
|
|
coverage-view: coverage-report
|
|
@test -f $(COVERAGE_DIR)/report/index.html && open $(COVERAGE_DIR)/report/index.html || true
|
|
|
|
# Deletes all coverage data files (.gcda)
|
|
.PHONY: coverage-zero
|
|
coverage-zero: # 'rm $(GCDA_FILES)' might fail with too many args
|
|
$(FASTCOV) --zerocounters
|
|
|
|
endif
|
|
|
|
######################################################################
|
|
# Clean
|
|
|
|
maintainer-clean::
|
|
@echo "This command is intended for maintainers to use;"
|
|
@echo "rebuilding the deleted files requires autoconf."
|
|
rm -f configure
|
|
|
|
clean mostlyclean distclean maintainer-clean maintainer-copy::
|
|
for dir in $(SUBDIRS); do \
|
|
echo making $@ in $$dir ; \
|
|
$(MAKE) -C $$dir $@ ; \
|
|
done
|
|
|
|
clean mostlyclean distclean maintainer-clean::
|
|
rm -f $(SCRIPTS) *.tmp
|
|
rm -f *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.kys *.log
|
|
rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs *.idx
|
|
rm -f *.ev *.evs *.ov *.ovs *.cv *.cvs *.ma *.mas
|
|
rm -f *.tex
|
|
rm -rf examples/*/obj_dir* examples/*/logs
|
|
rm -rf test_*/obj_dir
|
|
rm -rf src/*.tidy include/*.tidy examples/*/*.tidy
|
|
rm -rf .ruff_cache
|
|
rm -rf nodist/fuzzer/dictionary
|
|
rm -rf $(COVERAGE_DIR)
|
|
rm -rf verilator.txt
|
|
|
|
distclean maintainer-clean::
|
|
rm -f *.info* *.1 $(INFOS) $(INFOS_OLD) $(VL_INST_MAN_FILES)
|
|
rm -f Makefile config.status config.cache config.log TAGS
|
|
rm -f verilator_bin* verilator_coverage_bin*
|
|
rm -f bin/verilator_bin* bin/verilator_coverage_bin*
|
|
rm -f include/verilated.mk include/verilated_config.h
|
|
|
|
######################################################################
|
|
# Distributions
|
|
|
|
DISTTITLE := Verilator $(word 1,$(PACKAGE_VERSION))
|
|
DISTNAME := verilator-$(word 1,$(PACKAGE_VERSION))
|
|
DISTDATEPRE := $(word 2,$(PACKAGE_VERSION))
|
|
DISTDATE := $(subst /,-,$(DISTDATEPRE))
|
|
DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME)))
|
|
|
|
tag:
|
|
svnorcvs tag $(DISTTAGNAME)
|
|
|
|
maintainer-diff:
|
|
svnorcvs diff $(DISTTAGNAME)
|
|
|
|
preexist:
|
|
svnorcvs nexists $(DISTTAGNAME)
|
|
|
|
maintainer-dist: preexist tag
|
|
svnorcvs release $(DISTTAGNAME)
|