2012-04-13 03:08:20 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2006-08-26 13:35:28 +02:00
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Collect and print statistics
|
|
|
|
|
//
|
2019-11-08 04:33:59 +01:00
|
|
|
// Code available from: https://verilator.org
|
2006-08-26 13:35:28 +02:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2023-01-01 16:18:39 +01:00
|
|
|
// Copyright 2005-2023 by Wilson Snyder. This program is free software; you
|
2020-03-21 16:24:24 +01:00
|
|
|
// can redistribute it and/or modify it under the terms of either the GNU
|
2009-05-04 23:07:57 +02:00
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
|
// Version 2.0.
|
2020-03-21 16:24:24 +01:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
2006-08-26 13:35:28 +02:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
2019-10-05 02:17:11 +02:00
|
|
|
|
2023-10-18 12:37:46 +02:00
|
|
|
#include "V3PchAstMT.h"
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
#include "V3File.h"
|
2022-08-05 11:56:57 +02:00
|
|
|
#include "V3Global.h"
|
2017-09-18 04:52:57 +02:00
|
|
|
#include "V3Os.h"
|
2022-08-05 11:56:57 +02:00
|
|
|
#include "V3Stats.h"
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2018-10-14 19:43:24 +02:00
|
|
|
#include <iomanip>
|
2020-08-15 16:03:34 +02:00
|
|
|
#include <unordered_map>
|
2018-10-14 19:43:24 +02:00
|
|
|
|
2022-09-18 21:53:42 +02:00
|
|
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
//######################################################################
|
|
|
|
|
// Stats dumping
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class StatsReport final {
|
2006-08-26 13:35:28 +02:00
|
|
|
// TYPES
|
2021-03-13 00:10:45 +01:00
|
|
|
using StatColl = std::vector<V3Statistic>;
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// STATE
|
2019-05-19 22:13:13 +02:00
|
|
|
std::ofstream& os; ///< Output stream
|
|
|
|
|
static StatColl s_allStats; ///< All statistics
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
void sumit() {
|
2023-05-07 23:58:14 +02:00
|
|
|
os << '\n';
|
2019-05-19 22:13:13 +02:00
|
|
|
// If sumit is set on a statistic, combine with others of same name
|
2021-03-12 23:26:53 +01:00
|
|
|
std::multimap<std::string, V3Statistic*> byName;
|
2019-05-19 22:13:13 +02:00
|
|
|
// * is always first
|
2020-11-11 04:10:38 +01:00
|
|
|
for (auto& itr : s_allStats) {
|
|
|
|
|
V3Statistic* repp = &itr;
|
2020-12-19 00:24:47 +01:00
|
|
|
byName.emplace(repp->name(), repp);
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process duplicates
|
2020-08-15 16:12:55 +02:00
|
|
|
V3Statistic* lastp = nullptr;
|
2020-11-11 04:10:38 +01:00
|
|
|
for (const auto& itr : byName) {
|
|
|
|
|
V3Statistic* repp = itr.second;
|
2020-04-14 04:51:35 +02:00
|
|
|
if (lastp && lastp->sumit() && lastp->printit() && lastp->name() == repp->name()
|
|
|
|
|
&& lastp->stage() == repp->stage()) {
|
2019-05-19 22:13:13 +02:00
|
|
|
repp->combineWith(lastp);
|
|
|
|
|
}
|
|
|
|
|
lastp = repp;
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stars() {
|
2019-05-19 22:13:13 +02:00
|
|
|
// Find all stages
|
|
|
|
|
size_t maxWidth = 0;
|
2021-03-12 23:26:53 +01:00
|
|
|
std::multimap<std::string, const V3Statistic*> byName;
|
2019-05-19 22:13:13 +02:00
|
|
|
// * is always first
|
2020-11-11 04:10:38 +01:00
|
|
|
for (const auto& itr : s_allStats) {
|
|
|
|
|
const V3Statistic* repp = &itr;
|
2019-05-19 22:13:13 +02:00
|
|
|
if (repp->stage() == "*" && repp->printit()) {
|
|
|
|
|
if (maxWidth < repp->name().length()) maxWidth = repp->name().length();
|
2020-12-19 00:24:47 +01:00
|
|
|
byName.emplace(repp->name(), repp);
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Print organized by stage
|
2020-11-19 03:03:23 +01:00
|
|
|
os << "Global Statistics:\n\n";
|
2020-11-11 04:10:38 +01:00
|
|
|
for (const auto& itr : byName) {
|
|
|
|
|
const V3Statistic* repp = itr.second;
|
2019-05-19 22:13:13 +02:00
|
|
|
if (repp->perf()) continue;
|
2020-04-14 04:51:35 +02:00
|
|
|
os << " " << std::left << std::setw(maxWidth) << repp->name();
|
2019-05-19 22:13:13 +02:00
|
|
|
repp->dump(os);
|
2020-11-19 03:03:23 +01:00
|
|
|
os << '\n';
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
2020-11-19 03:03:23 +01:00
|
|
|
os << '\n';
|
2019-05-19 22:13:13 +02:00
|
|
|
|
|
|
|
|
// Print organized by stage
|
2020-11-19 03:03:23 +01:00
|
|
|
os << "Performance Statistics:\n\n";
|
2020-11-11 04:10:38 +01:00
|
|
|
for (const auto& itr : byName) {
|
|
|
|
|
const V3Statistic* repp = itr.second;
|
2019-05-19 22:13:13 +02:00
|
|
|
if (!repp->perf()) continue;
|
2020-04-14 04:51:35 +02:00
|
|
|
os << " " << std::left << std::setw(maxWidth) << repp->name();
|
2019-05-19 22:13:13 +02:00
|
|
|
repp->dump(os);
|
2020-11-19 03:03:23 +01:00
|
|
|
os << '\n';
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
2020-11-19 03:03:23 +01:00
|
|
|
os << '\n';
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stages() {
|
2020-04-14 04:51:35 +02:00
|
|
|
os << "Stage Statistics:\n";
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2019-05-19 22:13:13 +02:00
|
|
|
// Find all stages
|
|
|
|
|
int stage = 0;
|
|
|
|
|
size_t maxWidth = 0;
|
2021-03-12 23:26:53 +01:00
|
|
|
std::vector<std::string> stages;
|
2020-08-15 16:03:34 +02:00
|
|
|
std::unordered_map<string, int> stageInt;
|
2021-03-12 23:26:53 +01:00
|
|
|
std::multimap<std::string, const V3Statistic*> byName;
|
2019-05-19 22:13:13 +02:00
|
|
|
// * is always first
|
2021-03-12 23:26:53 +01:00
|
|
|
for (auto it = s_allStats.begin(); it != s_allStats.end(); ++it) {
|
2019-05-19 22:13:13 +02:00
|
|
|
const V3Statistic* repp = &(*it);
|
|
|
|
|
if (repp->stage() != "*" && repp->printit()) {
|
|
|
|
|
if (maxWidth < repp->name().length()) maxWidth = repp->name().length();
|
2022-11-27 11:52:40 +01:00
|
|
|
const auto itFoundPair = stageInt.emplace(repp->stage(), stage);
|
|
|
|
|
if (itFoundPair.second) {
|
|
|
|
|
++stage;
|
2019-05-19 22:13:13 +02:00
|
|
|
stages.push_back(repp->stage());
|
|
|
|
|
}
|
2020-12-19 00:24:47 +01:00
|
|
|
byName.emplace(repp->name(), repp);
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Header
|
2020-04-14 04:51:35 +02:00
|
|
|
os << " Stat " << std::left << std::setw(maxWidth - 5 - 2) << "";
|
2020-08-16 18:54:32 +02:00
|
|
|
for (const string& i : stages) os << " " << std::left << std::setw(9) << i;
|
2020-11-19 03:03:23 +01:00
|
|
|
os << '\n';
|
2020-04-14 04:51:35 +02:00
|
|
|
os << " -------- " << std::left << std::setw(maxWidth - 5 - 2) << "";
|
2020-08-16 18:54:32 +02:00
|
|
|
for (auto it = stages.begin(); it != stages.end(); ++it) {
|
2020-04-14 04:51:35 +02:00
|
|
|
os << " " << std::left << std::setw(9) << "-------";
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
2020-04-14 04:51:35 +02:00
|
|
|
// os<<endl;
|
2019-05-19 22:13:13 +02:00
|
|
|
|
|
|
|
|
// Print organized by stage
|
|
|
|
|
string lastName = "__NONE__";
|
|
|
|
|
string lastCommaName = "__NONE__";
|
|
|
|
|
unsigned col = 0;
|
2021-03-12 23:26:53 +01:00
|
|
|
for (auto it = byName.cbegin(); it != byName.cend(); ++it) {
|
2019-05-19 22:13:13 +02:00
|
|
|
const V3Statistic* repp = it->second;
|
|
|
|
|
if (lastName != repp->name()) {
|
|
|
|
|
lastName = repp->name();
|
|
|
|
|
{
|
|
|
|
|
string commaName = lastName;
|
|
|
|
|
string::size_type pos;
|
2020-04-14 04:51:35 +02:00
|
|
|
if ((pos = commaName.find(',')) != string::npos) commaName.erase(pos);
|
2019-05-19 22:13:13 +02:00
|
|
|
if (lastCommaName != commaName) {
|
|
|
|
|
lastCommaName = commaName;
|
2020-11-19 03:03:23 +01:00
|
|
|
os << '\n';
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-11-19 03:03:23 +01:00
|
|
|
os << '\n';
|
2019-05-19 22:13:13 +02:00
|
|
|
col = 0;
|
2020-04-14 04:51:35 +02:00
|
|
|
os << " " << std::left << std::setw(maxWidth) << repp->name();
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
2020-04-14 04:51:35 +02:00
|
|
|
while (col < stages.size() && stages.at(col) != repp->stage()) {
|
|
|
|
|
os << std::setw(11) << "";
|
2019-05-19 22:13:13 +02:00
|
|
|
col++;
|
|
|
|
|
}
|
|
|
|
|
repp->dump(os);
|
|
|
|
|
col++;
|
|
|
|
|
}
|
2020-11-19 03:03:23 +01:00
|
|
|
os << '\n';
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// METHODS
|
2020-04-14 04:51:35 +02:00
|
|
|
static void addStat(const V3Statistic& stat) { s_allStats.push_back(stat); }
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// CONSTRUCTORS
|
2018-02-02 03:24:41 +01:00
|
|
|
explicit StatsReport(std::ofstream* aofp)
|
2020-08-22 13:43:56 +02:00
|
|
|
: os(*aofp) { // Need () or GCC 4.8 false warning
|
2023-05-07 23:58:14 +02:00
|
|
|
os << "Verilator Statistics Report\n\n";
|
|
|
|
|
V3Stats::infoHeader(os, "");
|
2019-05-19 22:13:13 +02:00
|
|
|
sumit();
|
|
|
|
|
stars();
|
|
|
|
|
stages();
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2020-11-17 01:56:16 +01:00
|
|
|
~StatsReport() = default;
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-04-14 04:51:35 +02:00
|
|
|
StatsReport::StatColl StatsReport::s_allStats;
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// V3Statstic class
|
|
|
|
|
|
2018-08-23 11:09:12 +02:00
|
|
|
void V3Statistic::dump(std::ofstream& os) const {
|
2023-11-12 15:19:53 +01:00
|
|
|
os << " " << std::right << std::fixed << std::setprecision(precision()) << std::setw(9)
|
|
|
|
|
<< value();
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// Top Stats class
|
|
|
|
|
|
2020-04-14 04:51:35 +02:00
|
|
|
void V3Stats::addStat(const V3Statistic& stat) { StatsReport::addStat(stat); }
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2017-09-18 04:52:57 +02:00
|
|
|
void V3Stats::statsStage(const string& name) {
|
|
|
|
|
static double lastWallTime = -1;
|
|
|
|
|
static int fileNumber = 0;
|
|
|
|
|
|
2021-03-06 16:33:43 +01:00
|
|
|
const string digitName = V3Global::digitsFilename(++fileNumber) + "_" + name;
|
2017-09-18 04:52:57 +02:00
|
|
|
|
2021-06-21 00:32:57 +02:00
|
|
|
const double wallTime = V3Os::timeUsecs() / 1.0e6;
|
2020-04-14 04:51:35 +02:00
|
|
|
if (lastWallTime < 0) lastWallTime = wallTime;
|
2021-06-21 00:32:57 +02:00
|
|
|
const double wallTimeDelta = wallTime - lastWallTime;
|
2017-09-18 04:52:57 +02:00
|
|
|
lastWallTime = wallTime;
|
2020-04-14 04:51:35 +02:00
|
|
|
V3Stats::addStatPerf("Stage, Elapsed time (sec), " + digitName, wallTimeDelta);
|
2022-12-29 17:48:19 +01:00
|
|
|
V3Stats::addStatPerf("Stage, Elapsed time (sec), TOTAL", wallTimeDelta);
|
2017-09-18 04:52:57 +02:00
|
|
|
|
2021-06-21 00:32:57 +02:00
|
|
|
const double memory = V3Os::memUsageBytes() / 1024.0 / 1024.0;
|
2020-04-14 04:51:35 +02:00
|
|
|
V3Stats::addStatPerf("Stage, Memory (MB), " + digitName, memory);
|
2017-09-18 04:52:57 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-07 23:58:14 +02:00
|
|
|
void V3Stats::infoHeader(std::ofstream& os, const string& prefix) {
|
|
|
|
|
os << prefix << "Information:\n";
|
|
|
|
|
os << prefix << " " << V3Options::version() << '\n';
|
|
|
|
|
os << prefix << " Arguments: " << v3Global.opt.allArgsString() << '\n';
|
|
|
|
|
os << prefix << " Build jobs: " << v3Global.opt.buildJobs() << '\n';
|
|
|
|
|
os << prefix << " Verilate jobs: " << v3Global.opt.verilateJobs() << '\n';
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
void V3Stats::statsReport() {
|
2020-04-14 04:51:35 +02:00
|
|
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// Open stats file
|
2021-06-21 00:32:57 +02:00
|
|
|
const string filename
|
|
|
|
|
= v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix() + "__stats.txt";
|
2021-07-12 00:42:01 +02:00
|
|
|
std::ofstream* ofp{V3File::new_ofstream(filename)};
|
2020-04-14 04:51:35 +02:00
|
|
|
if (ofp->fail()) v3fatal("Can't write " << filename);
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2022-11-19 16:48:46 +01:00
|
|
|
{ StatsReport{ofp}; } // Destruct before cleanup
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// Cleanup
|
2020-01-17 02:17:11 +01:00
|
|
|
ofp->close();
|
|
|
|
|
VL_DO_DANGLING(delete ofp, ofp);
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|