diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index d5279167d..47f45e24b 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -113,6 +113,7 @@ class EmitCSyms final : EmitCBaseVisitorConst { int m_funcNum = 0; // CFunc split function number V3OutCFile* m_ofpBase = nullptr; // Base (not split) C file std::unordered_map m_usesVfinal; // Split method uses __Vfinal + VDouble0 m_statVarScopeBytes; // Statistic tracking // METHODS void emitSymHdr(); @@ -367,6 +368,10 @@ class EmitCSyms final : EmitCBaseVisitorConst { iterateChildrenConst(nodep); if (nodep->isSigUserRdPublic() && !m_cfuncp) m_modVars.emplace_back(m_modp, nodep); } + void visit(AstVarScope* nodep) override { + iterateChildrenConst(nodep); + m_statVarScopeBytes += nodep->varp()->dtypep()->widthTotalBytes(); + } void visit(AstCoverDecl* nodep) override { // Assign numbers to all bins, so we know how big of an array to use if (!nodep->dataDeclNullp()) { // else duplicate we don't need code for @@ -832,8 +837,10 @@ void EmitCSyms::emitSymImp() { puts(" // Check resources\n"); uint64_t stackSize = V3StackCount::count(v3Global.rootp()); if (v3Global.opt.debugStackCheck()) stackSize += 1024 * 1024 * 1024; - V3Stats::addStat("Stack size prediction (bytes)", stackSize); + V3Stats::addStat("Size prediction, Stack (bytes)", stackSize); puts(" Verilated::stackCheck(" + cvtToStr(stackSize) + ");\n"); + V3Stats::addStat("Size prediction, Heap, from Var Scopes (bytes)", m_statVarScopeBytes); + V3Stats::addStat(V3Stats::STAT_MODEL_SIZE, stackSize + m_statVarScopeBytes); } if (v3Global.opt.profPgo()) { diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 1f9cb57f8..3d9e23ec1 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -23,6 +23,7 @@ #include "V3LinkParse.h" #include "V3Config.h" +#include "V3Stats.h" #include #include @@ -62,6 +63,7 @@ class LinkParseVisitor final : public VNVisitor { int m_beginDepth = 0; // How many begin blocks above current node within current AstNodeModule VLifetime m_lifetime = VLifetime::STATIC; // Propagating lifetime bool m_insideLoop = false; // True if the node is inside a loop + VDouble0 m_statModules; // Number of modules seen // METHODS void cleanFileline(AstNode* nodep) { @@ -620,6 +622,7 @@ class LinkParseVisitor final : public VNVisitor { } void visit(AstNodeModule* nodep) override { V3Config::applyModule(nodep); + ++m_statModules; VL_RESTORER(m_modp); VL_RESTORER(m_anonUdpId); @@ -915,7 +918,9 @@ public: : m_stdPackagep{rootp->stdPackagep()} { iterate(rootp); } - ~LinkParseVisitor() override = default; + ~LinkParseVisitor() override { + V3Stats::addStatSum(V3Stats::STAT_SOURCE_MODULES, m_statModules); + } }; //###################################################################### diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index 8583e0f54..d467f81e5 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -331,6 +331,7 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i } } + V3Stats::addStatSum(V3Stats::STAT_SOURCE_CHARS, m_ppBytes); if (debug() && modfilename != V3Options::getStdPackagePath()) dumpInputsFile(); // Parse it diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index bc15eb068..775669491 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -152,6 +152,7 @@ class V3ParseImp final { std::deque m_numberps; // Created numbers for later cleanup std::deque m_lexLintState; // Current lint state for save/restore std::deque m_ppBuffers; // Preprocessor->lex buffer of characters to process + size_t m_ppBytes = 0; // Preprocessor->lex bytes transferred AstNode* m_tagNodep = nullptr; // Points to the node to set to m_tag or nullptr to not set. VTimescale m_timeLastUnit; // Last `timescale's unit @@ -202,6 +203,7 @@ public: void ppPushText(const string& text) { m_ppBuffers.push_back(text); + m_ppBytes += text.length(); if (lexFileline()->contentp()) lexFileline()->contentp()->pushText(text); } size_t ppInputToLex(char* buf, size_t max_size) VL_MT_DISABLED; diff --git a/src/V3Stats.h b/src/V3Stats.h index 1347dcfd3..7c3a8ea1c 100644 --- a/src/V3Stats.h +++ b/src/V3Stats.h @@ -104,6 +104,11 @@ public: class V3Stats final { public: + // Symbolic names for some statistics that are later read by summaryReport() + static constexpr const char* STAT_MODEL_SIZE = "Size prediction, Model total (bytes)"; + static constexpr const char* STAT_SOURCE_CHARS = "Input, Verilog bytes read"; + static constexpr const char* STAT_SOURCE_MODULES = "Input, Verilog modules read"; + static void addStat(const V3Statistic&); static void addStat(const string& stage, const string& name, double value, unsigned precision = 0) {