verilator/bin/verilator_ccache_report

98 lines
3.2 KiB
Python
Executable File

#!/usr/bin/env python3
# pylint: disable=C0103,C0114,C0115,C0116,C0123,C0209,C0301,R0902,R0913,R0914,R0912,R0915,W0621
######################################################################
import argparse
import collections
import pathlib
import re
from datetime import datetime
parser = argparse.ArgumentParser(
allow_abbrev=False,
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""Report ccache behavior of a Verilated model build.
For documentation see
https://verilator.org/guide/latest/exe_verilator_ccache_report.html""",
epilog=
"""Copyright 2002-2023 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('logdir', type=pathlib.Path, help='log directory')
args = parser.parse_args()
results = {}
elapsed = {}
def toDateTime(s):
return datetime.strptime(s, "%Y-%m-%dT%H:%M:%S.%f")
for logfile in args.logdir.iterdir():
with logfile.open() as fh:
start = None
obj = None
for line in fh:
line = line.strip()
match = re.match(r'\[(\S+)\s.*Object file: (.*)$', line)
if match:
start = toDateTime(match.group(1))
obj = match.group(2)
match = re.match(r'\[(\S+)\s.*Result: (.*)$', line)
if match:
assert obj is not None
elapsed[obj] = toDateTime(match.group(1)) - start
results[obj] = match.group(2)
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")
wnames = max(len(_) for _ in results) + 1
wresults = max(len(_) for _ in results.values()) + 1
for k in sorted(results.keys()):
args.o.write("{:{wnames}} : {:{wresults}} : {}s\n".format(
k,
results[k],
elapsed[k].total_seconds(),
wnames=wnames,
wresults=wresults))
args.o.write("\nSummary:\n")
counts = collections.Counter(_ for _ in results.values())
total = sum(counts.values())
for k in sorted(counts.keys()):
c = counts[k]
args.o.write("{:{width}}| {} ({:.2%})\n".format(k,
c,
c / total,
width=wresults))
args.o.write("\nLongest:\n")
longest = sorted(list(elapsed.items()),
key=lambda kv: -kv[1].total_seconds())
for i, (k, v) in enumerate(longest):
args.o.write("{:{width}}| {}s\n".format(k,
v.total_seconds(),
width=wnames))
if i > 4:
break
args.o.write("#" * 80 + "\n")