Add ccache-report target to standard Makefile (#3011)
Using the standard model Makefile, when in addition to an explicit target, the target 'ccache-report' is also given, a summary of ccache hits/misses during this invocation of 'make' will be prited at the end of the build.
This commit is contained in:
parent
31bb73e3de
commit
0edf1f0c94
|
|
@ -131,6 +131,7 @@ DISTFILES1 = $(INFOS) .gitignore \
|
||||||
verilator-config.cmake.in \
|
verilator-config.cmake.in \
|
||||||
verilator-config-version.cmake.in \
|
verilator-config-version.cmake.in \
|
||||||
bin/verilator \
|
bin/verilator \
|
||||||
|
bin/verilator_ccache_report \
|
||||||
bin/verilator_coverage \
|
bin/verilator_coverage \
|
||||||
bin/verilator_difftree \
|
bin/verilator_difftree \
|
||||||
bin/verilator_gantt \
|
bin/verilator_gantt \
|
||||||
|
|
@ -194,6 +195,7 @@ DISTFILES2 = \
|
||||||
|
|
||||||
INST_PROJ_FILES = \
|
INST_PROJ_FILES = \
|
||||||
bin/verilator \
|
bin/verilator \
|
||||||
|
bin/verilator_ccache_report \
|
||||||
bin/verilator_coverage \
|
bin/verilator_coverage \
|
||||||
bin/verilator_gantt \
|
bin/verilator_gantt \
|
||||||
bin/verilator_includer \
|
bin/verilator_includer \
|
||||||
|
|
@ -282,7 +284,7 @@ verilator.pdf: Makefile
|
||||||
|
|
||||||
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
|
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
|
||||||
VL_INST_BIN_FILES = verilator verilator_bin$(EXEEXT) verilator_bin_dbg$(EXEEXT) verilator_coverage_bin_dbg$(EXEEXT) \
|
VL_INST_BIN_FILES = verilator verilator_bin$(EXEEXT) verilator_bin_dbg$(EXEEXT) verilator_coverage_bin_dbg$(EXEEXT) \
|
||||||
verilator_coverage verilator_gantt verilator_includer verilator_profcfunc
|
verilator_ccache_report verilator_coverage verilator_gantt verilator_includer verilator_profcfunc
|
||||||
# Some scripts go into both the search path and pkgdatadir,
|
# Some scripts go into both the search path and pkgdatadir,
|
||||||
# so they can be found by the user, and under $VERILATOR_ROOT.
|
# so they can be found by the user, and under $VERILATOR_ROOT.
|
||||||
|
|
||||||
|
|
@ -311,6 +313,7 @@ installbin:
|
||||||
( cd bin ; $(INSTALL_PROGRAM) verilator_coverage_bin_dbg$(EXEEXT) $(DESTDIR)$(bindir)/verilator_coverage_bin_dbg$(EXEEXT) )
|
( cd bin ; $(INSTALL_PROGRAM) verilator_coverage_bin_dbg$(EXEEXT) $(DESTDIR)$(bindir)/verilator_coverage_bin_dbg$(EXEEXT) )
|
||||||
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/bin
|
$(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/bin
|
||||||
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
|
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
|
||||||
|
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_ccache_report $(DESTDIR)$(pkgdatadir)/bin/verilator_ccache_report )
|
||||||
|
|
||||||
# Man files can either be part of the original kit, or built in current directory
|
# Man files can either be part of the original kit, or built in current directory
|
||||||
# So important we use $^ so VPATH is searched
|
# So important we use $^ so VPATH is searched
|
||||||
|
|
@ -477,6 +480,7 @@ clang-format:
|
||||||
$(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CLANGFORMAT_FILES)
|
$(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CLANGFORMAT_FILES)
|
||||||
|
|
||||||
PY_PROGRAMS = \
|
PY_PROGRAMS = \
|
||||||
|
bin/verilator_ccache_report \
|
||||||
examples/xml_py/vl_file_copy \
|
examples/xml_py/vl_file_copy \
|
||||||
examples/xml_py/vl_hier_graph \
|
examples/xml_py/vl_hier_graph \
|
||||||
docs/guide/conf.py \
|
docs/guide/conf.py \
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# pylint: disable=C0103,C0114,C0115,C0116,C0123,C0301,R0902,R0913,R0914,R0912,R0915,W0621
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import collections
|
||||||
|
import re
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
allow_abbrev=False,
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
description="""Report ccache behavior of a Verilated model build.""",
|
||||||
|
epilog=
|
||||||
|
"""Copyright 2002-2021 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""")
|
||||||
|
|
||||||
|
parser.add_argument('-o', type=argparse.FileType('w'), metavar="OUTFILE",
|
||||||
|
required=True,
|
||||||
|
help='output file')
|
||||||
|
parser.add_argument('logfile', type=argparse.FileType('r'),
|
||||||
|
help='ccache log file')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
results = {}
|
||||||
|
|
||||||
|
for line in args.logfile:
|
||||||
|
line = line.strip()
|
||||||
|
match = re.match(r'.*Object file: (.*)$', line)
|
||||||
|
if match:
|
||||||
|
obj = match.group(1)
|
||||||
|
match = re.match(r'.*Result: (.*)$', line)
|
||||||
|
if match:
|
||||||
|
results[obj] = match.group(1)
|
||||||
|
|
||||||
|
args.o.write("#" * 80 + "\n")
|
||||||
|
args.o.write("ccache report (from verilator_ccache_report) :\n")
|
||||||
|
|
||||||
|
if not results:
|
||||||
|
args.o.write("\nAll object files up to date\n")
|
||||||
|
else:
|
||||||
|
args.o.write("\nCompiled object files:\n")
|
||||||
|
width = max(len(_) for _ in results) + 1
|
||||||
|
for k in sorted(results.keys()):
|
||||||
|
args.o.write("{:{width}} : {}\n".format(k, results[k], width=width))
|
||||||
|
|
||||||
|
args.o.write("\nSummary:\n")
|
||||||
|
counts = collections.Counter(_ for _ in results.values())
|
||||||
|
total = sum(counts.values())
|
||||||
|
width = max(len(_) for _ in results.values()) + 1
|
||||||
|
for k in sorted(counts.keys()):
|
||||||
|
c = counts[k]
|
||||||
|
args.o.write("{:{width}}| {} ({:.2%})\n".format(k, c, c / total, width=width))
|
||||||
|
|
||||||
|
args.o.write("#" * 80 + "\n")
|
||||||
|
|
@ -387,7 +387,7 @@ How do I get faster build times?
|
||||||
identical source builds, even across different users. If ccache was
|
identical source builds, even across different users. If ccache was
|
||||||
installed when Verilator was built it is used, or see OBJCACHE
|
installed when Verilator was built it is used, or see OBJCACHE
|
||||||
environment variable to override this. Also see the
|
environment variable to override this. Also see the
|
||||||
:vlopt:`--output-split` option.
|
:vlopt:`--output-split` option and :ref: `Profiling ccache efficiency`
|
||||||
|
|
||||||
* To reduce the compile time of classes that use a Verilated module (e.g. a
|
* To reduce the compile time of classes that use a Verilated module (e.g. a
|
||||||
top CPP file) you may wish to add a
|
top CPP file) you may wish to add a
|
||||||
|
|
|
||||||
|
|
@ -316,6 +316,35 @@ statistics.
|
||||||
|
|
||||||
For more information see :command:`verilator_gantt`.
|
For more information see :command:`verilator_gantt`.
|
||||||
|
|
||||||
|
.. _Profiling ccache efficiency:
|
||||||
|
|
||||||
|
Profiling ccache efficiency
|
||||||
|
===========================
|
||||||
|
|
||||||
|
The Verilator generated Makefile provides support for basic profiling of
|
||||||
|
ccache behavior during the build. This can be used to track down files that
|
||||||
|
might be unnecessarily rebuilt, though as of today even small code changes
|
||||||
|
will usually require rebuilding a large number of files. Improving ccache
|
||||||
|
efficiency during the edit/compile/test loop is an active area of
|
||||||
|
development.
|
||||||
|
|
||||||
|
To get a basic report of how well ccache is doing, add the `ccache-report`
|
||||||
|
target when invoking the generated Makefile:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
make -C obj_dir -f Vout.mk Vout ccache-report
|
||||||
|
|
||||||
|
This will print a report based on all executions of ccache during this
|
||||||
|
invocation of Make. The report is also written to a file, in this example
|
||||||
|
`obj_dir/Vout__cache_report.txt`.
|
||||||
|
|
||||||
|
To use the `ccache-report` target, at least one other explicit build target
|
||||||
|
must be specified, and OBJCACHE must be set to 'ccache'.
|
||||||
|
|
||||||
|
This feature is currently experimental and might change in subsequent
|
||||||
|
releases.
|
||||||
|
|
||||||
.. _Save/Restore:
|
.. _Save/Restore:
|
||||||
|
|
||||||
Save/Restore
|
Save/Restore
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
PERL = @PERL@
|
PERL = @PERL@
|
||||||
|
PYTHON3 = @PYTHON3@
|
||||||
CXX = @CXX@
|
CXX = @CXX@
|
||||||
LINK = @CXX@
|
LINK = @CXX@
|
||||||
AR = ar
|
AR = ar
|
||||||
|
|
@ -35,6 +36,7 @@ CFG_LDLIBS_THREADS = @CFG_LDLIBS_THREADS@
|
||||||
|
|
||||||
VERILATOR_COVERAGE = $(PERL) $(VERILATOR_ROOT)/bin/verilator_coverage
|
VERILATOR_COVERAGE = $(PERL) $(VERILATOR_ROOT)/bin/verilator_coverage
|
||||||
VERILATOR_INCLUDER = $(PERL) $(VERILATOR_ROOT)/bin/verilator_includer
|
VERILATOR_INCLUDER = $(PERL) $(VERILATOR_ROOT)/bin/verilator_includer
|
||||||
|
VERILATOR_CCACHE_REPORT = $(PYTHON3) $(VERILATOR_ROOT)/bin/verilator_ccache_report
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Make checks
|
# Make checks
|
||||||
|
|
@ -254,6 +256,37 @@ endif
|
||||||
#.cpp.o:
|
#.cpp.o:
|
||||||
# $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
|
# $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
### ccache report
|
||||||
|
|
||||||
|
ifneq ($(findstring ccache-report,$(MAKECMDGOALS)),)
|
||||||
|
ifneq ($(OBJCACHE),ccache)
|
||||||
|
$(error ccache-report requires OBJCACHE to equal 'ccache')
|
||||||
|
endif
|
||||||
|
VK_OTHER_GOALS := $(strip $(subst ccache-report,,$(MAKECMDGOALS)))
|
||||||
|
ifeq ($(VK_OTHER_GOALS),)
|
||||||
|
$(error ccache-report must be used with at least one other explicit target)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Report ccache behaviour for this invocation of make
|
||||||
|
export CCACHE_LOGFILE := $(VM_PREFIX).ccache-log
|
||||||
|
VK_CCACHE_REPORT := $(VM_PREFIX)__ccache_report.txt
|
||||||
|
# Truncate logfile
|
||||||
|
$(shell echo "" > $(CCACHE_LOGFILE))
|
||||||
|
# Remove previous report
|
||||||
|
$(shell rm -f $(VK_CCACHE_REPORT))
|
||||||
|
|
||||||
|
$(VK_CCACHE_REPORT): $(VK_OBJS)
|
||||||
|
$(VERILATOR_CCACHE_REPORT) -o $@ $(CCACHE_LOGFILE)
|
||||||
|
|
||||||
|
.PHONY: ccache-report
|
||||||
|
ccache-report: $(VK_CCACHE_REPORT)
|
||||||
|
@cat $<
|
||||||
|
|
||||||
|
# ccache-report runs last
|
||||||
|
ccache-report: $(VK_OTHER_GOALS)
|
||||||
|
endif
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
### Debugging
|
### Debugging
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2304,6 +2304,10 @@ sub cfg_with_threaded {
|
||||||
return 1; # C++11 now always required
|
return 1; # C++11 now always required
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub cfg_with_ccache {
|
||||||
|
return `grep "OBJCACHE \?= ccache" "$ENV{VERILATOR_ROOT}/include/verilated.mk"` ne "";
|
||||||
|
}
|
||||||
|
|
||||||
sub tries {
|
sub tries {
|
||||||
# Number of retries when reading logfiles, generally only need many
|
# Number of retries when reading logfiles, generally only need many
|
||||||
# retries when system is busy running a lot of tests
|
# retries when system is busy running a lot of tests
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2021 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
|
||||||
|
|
||||||
|
scenarios(vlt => 1);
|
||||||
|
|
||||||
|
if (!$Self->cfg_with_ccache) {
|
||||||
|
skip("Requires configuring with ccache");
|
||||||
|
}
|
||||||
|
|
||||||
|
top_filename("t_a1_first_cc.v");
|
||||||
|
|
||||||
|
# This test requires rebuilding the object files to check the ccache log
|
||||||
|
foreach my $filename (glob ("$Self->{obj_dir}/*.o")) {
|
||||||
|
print "rm $filename\n" if $Self->{verbose};
|
||||||
|
unlink $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
compile(
|
||||||
|
verilator_flags2 => ['--trace'],
|
||||||
|
make_flags => "ccache-report"
|
||||||
|
);
|
||||||
|
|
||||||
|
my $report = "$Self->{obj_dir}/$Self->{VM_PREFIX}__ccache_report.txt";
|
||||||
|
|
||||||
|
# We do not actually want to make this test depend on whether the file was
|
||||||
|
# cached or not, so trim the report to ignore actual caching behaviour
|
||||||
|
run(cmd => ["sed", "-i", "-e", "'s/ : .*/ : IGNORED/; /^Summary/,\$d;'", $report]);
|
||||||
|
|
||||||
|
files_identical($report, "t/$Self->{name}__ccache_report_initial.out");
|
||||||
|
|
||||||
|
# Now rebuild again (should be all up to date)
|
||||||
|
run(
|
||||||
|
logfile => "$Self->{obj_dir}/rebuild.log",
|
||||||
|
cmd => ["make", "-C", $Self->{obj_dir},
|
||||||
|
"-f", "$Self->{VM_PREFIX}.mk",
|
||||||
|
$Self->{VM_PREFIX}, "ccache-report"]
|
||||||
|
);
|
||||||
|
|
||||||
|
files_identical($report, "t/$Self->{name}__ccache_report_rebuild.out");
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
################################################################################
|
||||||
|
ccache report (from verilator_ccache_report) :
|
||||||
|
|
||||||
|
Compiled object files:
|
||||||
|
Vt_ccache_report__ALL.o : IGNORED
|
||||||
|
Vt_ccache_report__main.o : IGNORED
|
||||||
|
verilated.o : IGNORED
|
||||||
|
verilated_vcd_c.o : IGNORED
|
||||||
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
################################################################################
|
||||||
|
ccache report (from verilator_ccache_report) :
|
||||||
|
|
||||||
|
All object files up to date
|
||||||
|
################################################################################
|
||||||
|
|
@ -10,23 +10,33 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||||
|
|
||||||
scenarios(dist => 1);
|
scenarios(dist => 1);
|
||||||
|
|
||||||
|
# See also t_flag_version.pl
|
||||||
|
|
||||||
|
sub check {
|
||||||
|
my $interpreter = shift;
|
||||||
|
my $prog = shift;
|
||||||
|
|
||||||
|
run(fails => 0,
|
||||||
|
cmd => [$interpreter, $prog, "--help"],
|
||||||
|
logfile => "$Self->{obj_dir}/t_help.log",
|
||||||
|
tee => 0,
|
||||||
|
verilator_run => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
file_grep("$Self->{obj_dir}/t_help.log", qr/DISTRIBUTION/i);
|
||||||
|
}
|
||||||
|
|
||||||
foreach my $prog (
|
foreach my $prog (
|
||||||
# See also t_flag_version.pl
|
|
||||||
"../bin/verilator",
|
"../bin/verilator",
|
||||||
"../bin/verilator_coverage",
|
"../bin/verilator_coverage",
|
||||||
"../bin/verilator_difftree",
|
"../bin/verilator_difftree",
|
||||||
"../bin/verilator_gantt",
|
"../bin/verilator_gantt",
|
||||||
"../bin/verilator_profcfunc",
|
"../bin/verilator_profcfunc",
|
||||||
) {
|
) {
|
||||||
run(fails => 0,
|
check("perl", $prog);
|
||||||
cmd => ["perl", $prog,
|
|
||||||
"--help"],
|
|
||||||
logfile => "$Self->{obj_dir}/t_help.log",
|
|
||||||
tee => 0,
|
|
||||||
verilator_run => 1,
|
|
||||||
);
|
|
||||||
file_grep("$Self->{obj_dir}/t_help.log", qr/DISTRIBUTION/i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check("python3", "../bin/verilator_ccache_report");
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
1;
|
1;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue