diff --git a/src/V3Error.cpp b/src/V3Error.cpp index 10d76ef09..572d97bd2 100644 --- a/src/V3Error.cpp +++ b/src/V3Error.cpp @@ -266,7 +266,7 @@ void V3ErrorGuarded::v3errorEndGuts(const std::ostringstream& sstr, const string } if (debug()) { execErrorExitCb(); - V3Stats::statsFinalAll(v3Global.rootp()); + V3Stats::statsStageAll(v3Global.rootp(), "Final"); V3Stats::statsReport(); } vlAbortOrExit(); diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp index a1ad5edb2..fd445e469 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -193,5 +193,3 @@ public: void V3Stats::statsStageAll(AstNetlist* nodep, const std::string& stage, bool fastOnly) { StatsVisitor{nodep, stage, fastOnly}; } - -void V3Stats::statsFinalAll(AstNetlist* nodep) { statsStageAll(nodep, "Final"); } diff --git a/src/V3Stats.h b/src/V3Stats.h index d035aeeeb..84d023296 100644 --- a/src/V3Stats.h +++ b/src/V3Stats.h @@ -147,9 +147,8 @@ public: } /// Called each stage static void statsStage(const string& name); - /// Called by the top level to collect statistics + /// Called by the top level, and error path, to collect statistics static void statsStageAll(AstNetlist* nodep, const string& stage, bool fastOnly = false); - static void statsFinalAll(AstNetlist* nodep); /// Called by the top level to dump the statistics static void statsReport(); /// Called by debug dumps diff --git a/src/Verilator.cpp b/src/Verilator.cpp index 53ed00a79..dca85ae99 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -127,7 +127,6 @@ V3Global v3Global; static void reportStatsIfEnabled() { if (v3Global.opt.stats()) { FileLine::stats(); - V3Stats::statsFinalAll(v3Global.rootp()); V3Stats::statsReport(); } } @@ -207,10 +206,7 @@ static void process() { V3Hierarchical::createGraph(v3Global.rootp()); // If a plan is created, further analysis is not necessary. // The actual Verilation will be done based on this plan. - if (v3Global.hierGraphp()) { - reportStatsIfEnabled(); - return; - } + if (v3Global.hierGraphp()) return; } // Calculate and check widths, edit tree to TRUNC/EXTRACT any width mismatches @@ -817,12 +813,6 @@ static bool verilate(const string& argString) { // Final writing shouldn't throw warnings, but... V3Error::abortIfWarnings(); - // Free memory so compiler has more for --build - // No need to do this if skipped (above) as didn't alloc much - UINFO(1, "Releasing netlist memory"); - v3Global.rootp()->deleteContents(); - V3Os::releaseMemory(); - if (v3Global.opt.stats()) V3Stats::statsStage("released"); return true; } @@ -846,10 +836,18 @@ static string buildMakeCmd(const string& makefile, const string& target) { return cmd.str(); } +static void releaseNetlistMemory() { + UINFO(1, "Releasing netlist memory"); + v3Global.rootp()->deleteContents(); + V3Os::releaseMemory(); + if (v3Global.opt.stats()) V3Stats::statsStage("released"); +} + static void execBuildJob() { UASSERT(v3Global.opt.build(), "--build is not specified."); UASSERT(v3Global.opt.gmake(), "--build requires GNU Make."); UASSERT(!v3Global.opt.makeJson(), "--build cannot use json build."); + releaseNetlistMemory(); const VlOs::DeltaWallTime buildWallTime{true}; UINFO(1, "Start Build"); @@ -866,6 +864,7 @@ static void execBuildJob() { static void execHierVerilation() { UASSERT(v3Global.hierGraphp(), "must be called only when plan exists"); + releaseNetlistMemory(); const string makefile = v3Global.opt.prefix() + "_hier.mk "; const string target = v3Global.opt.build() ? " hier_build" : " hier_verilation"; const string cmdStr = buildMakeCmd(makefile, target); diff --git a/test_regress/t/t_benchmark_mux4k.py b/test_regress/t/t_benchmark_mux4k.py index 61180d55a..54667898d 100755 --- a/test_regress/t/t_benchmark_mux4k.py +++ b/test_regress/t/t_benchmark_mux4k.py @@ -15,4 +15,7 @@ test.compile(v_flags2=["--stats", test.wno_unopthreads_for_few_cores]) test.execute() +# Check netlist was NOT released on shutdown +test.file_grep_not(test.stats, r"Stage, Elapsed time \(sec\), \d+_released") + test.passes() diff --git a/test_regress/t/t_flag_build.py b/test_regress/t/t_flag_build.py index 59ded9803..d047dde66 100755 --- a/test_regress/t/t_flag_build.py +++ b/test_regress/t/t_flag_build.py @@ -14,9 +14,13 @@ test.top_filename = "t/t_flag_make_cmake.v" test.compile( # Don't call cmake nor gmake from driver.py verilator_flags2=[ - '--exe --cc --build -j 2', '../' + test.main_filename, '-MAKEFLAGS -p --trace-vcd' + '--exe --cc --build -j 2', '../' + test.main_filename, '-MAKEFLAGS -p --trace-vcd', + '--stats' ]) test.execute() +# Check netlist was released before forking the build +test.file_grep(test.stats, r"Stage, Elapsed time \(sec\), \d+_released") + test.passes() diff --git a/test_regress/t/t_hier_block.py b/test_regress/t/t_hier_block.py index 294b5139a..fa1790af0 100755 --- a/test_regress/t/t_hier_block.py +++ b/test_regress/t/t_hier_block.py @@ -41,5 +41,7 @@ test.file_grep(test.obj_dir + "/Vsub1/sub1.sv", r'^module\s+(\S+)\s+', "sub1") test.file_grep(test.obj_dir + "/Vsub2/sub2.sv", r'^module\s+(\S+)\s+', "sub2") test.file_grep(test.stats, r'HierBlock,\s+Hierarchical blocks\s+(\d+)', 14) test.file_grep(test.run_log_filename, r'MACRO:(\S+) is defined', "cplusplus") +# Check netlist was released before forking the sub verilation +test.file_grep(test.stats, r"Stage, Elapsed time \(sec\), \d+_released") test.passes()