Initialize profile file once
Signed-off-by: Bartłomiej Chmiel <bchmiel@antmicro.com>
This commit is contained in:
parent
98b8d43a4a
commit
d55fbb7914
|
@ -225,7 +225,10 @@ public:
|
|||
// METHODS
|
||||
VlPgoProfiler() = default;
|
||||
~VlPgoProfiler() = default;
|
||||
void write(const char* modelp, const std::string& filename, bool firstHierCall) VL_MT_SAFE;
|
||||
VL_UNMOVABLE(VlPgoProfiler);
|
||||
VL_UNCOPYABLE(VlPgoProfiler);
|
||||
void configure(const std::string& filename) VL_MT_SAFE;
|
||||
void write(const char* modelp, const std::string& filename) VL_MT_SAFE;
|
||||
void addCounter(size_t counter, const std::string& name) {
|
||||
VL_DEBUG_IF(assert(counter < N_Entries););
|
||||
m_records.emplace_back(Record{name, counter});
|
||||
|
@ -239,8 +242,7 @@ public:
|
|||
};
|
||||
|
||||
template <std::size_t N_Entries>
|
||||
void VlPgoProfiler<N_Entries>::write(const char* modelp, const std::string& filename,
|
||||
bool firstHierCall) VL_MT_SAFE {
|
||||
void VlPgoProfiler<N_Entries>::configure(const std::string& filename) VL_MT_SAFE {
|
||||
static VerilatedMutex s_mutex;
|
||||
const VerilatedLockGuard lock{s_mutex};
|
||||
|
||||
|
@ -250,22 +252,33 @@ void VlPgoProfiler<N_Entries>::write(const char* modelp, const std::string& file
|
|||
// each will collect is own data correctly. However when each is
|
||||
// destroyed we need to get all the data, not keep overwriting and only
|
||||
// get the last model's data.
|
||||
static bool s_firstCall = firstHierCall;
|
||||
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+prof+vlt+file writing to '%s'\n", filename.c_str()););
|
||||
|
||||
FILE* const fp = std::fopen(filename.c_str(), s_firstCall ? "w" : "a");
|
||||
FILE* const fp = std::fopen(filename.c_str(), "w");
|
||||
if (VL_UNLIKELY(!fp)) {
|
||||
VL_FATAL_MT(filename.c_str(), 0, "", "+prof+vlt+file file not writable");
|
||||
}
|
||||
if (s_firstCall) {
|
||||
// TODO Perhaps merge with verilated_coverage output format, so can
|
||||
// have a common merging and reporting tool, etc.
|
||||
fprintf(fp, "// Verilated model profile-guided optimization data dump file\n");
|
||||
fprintf(fp, "`verilator_config\n");
|
||||
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+prof+vlt+file initializing '%s'\n", filename.c_str()););
|
||||
|
||||
// TODO Perhaps merge with verilated_coverage output format, so can
|
||||
// have a common merging and reporting tool, etc.
|
||||
fprintf(fp, "// Verilated model profile-guided optimization data dump file\n");
|
||||
fprintf(fp, "`verilator_config\n");
|
||||
|
||||
std::fclose(fp);
|
||||
}
|
||||
|
||||
template <std::size_t N_Entries>
|
||||
void VlPgoProfiler<N_Entries>::write(const char* modelp, const std::string& filename) VL_MT_SAFE {
|
||||
static VerilatedMutex s_mutex;
|
||||
const VerilatedLockGuard lock{s_mutex};
|
||||
|
||||
FILE* const fp = std::fopen(filename.c_str(), "a");
|
||||
if (VL_UNLIKELY(!fp)) {
|
||||
VL_FATAL_MT(filename.c_str(), 0, "", "+prof+vlt+file file not writable");
|
||||
}
|
||||
|
||||
s_firstCall = false;
|
||||
VL_DEBUG_IF(VL_DBG_MSGF("+prof+vlt+file writing to '%s'\n", filename.c_str()););
|
||||
|
||||
for (const Record& rec : m_records) {
|
||||
fprintf(fp, "profile_data -model \"%s\" -mtask \"%s\" -cost 64'd%" PRIu64 "\n", modelp,
|
||||
|
|
|
@ -731,11 +731,8 @@ void EmitCSyms::emitSymImp() {
|
|||
puts("#endif // VM_TRACE\n");
|
||||
}
|
||||
if (v3Global.opt.profPgo()) {
|
||||
// Do not overwrite data during the last hierarchical stage.
|
||||
const string firstHierCall
|
||||
= (v3Global.opt.hierBlocks().empty() || v3Global.opt.hierChild()) ? "true" : "false";
|
||||
puts("_vm_pgoProfiler.write(\"" + topClassName()
|
||||
+ "\", _vm_contextp__->profVltFilename(), " + firstHierCall + ");\n");
|
||||
+ "\", _vm_contextp__->profVltFilename());\n");
|
||||
}
|
||||
puts("}\n");
|
||||
|
||||
|
@ -837,6 +834,9 @@ void EmitCSyms::emitSymImp() {
|
|||
|
||||
if (v3Global.opt.profPgo()) {
|
||||
puts("// Configure profiling for PGO\n");
|
||||
if (!v3Global.opt.hierChild()) {
|
||||
puts("_vm_pgoProfiler.configure(_vm_contextp__->profVltFilename());\n");
|
||||
}
|
||||
if (v3Global.opt.mtasks()) {
|
||||
v3Global.rootp()->topModulep()->foreach([&](const AstExecGraph* execGraphp) {
|
||||
for (const V3GraphVertex& vtx : execGraphp->depGraphp()->vertices()) {
|
||||
|
|
|
@ -18,6 +18,7 @@ module t (/*AUTOARG*/
|
|||
|
||||
generate
|
||||
for (genvar i = 0; i < `CORES; ++i) Core core(clk);
|
||||
for (genvar i = 0; i < `CORES; ++i) CoreHier hierCore(clk);
|
||||
endgenerate
|
||||
endmodule
|
||||
|
||||
|
@ -42,6 +43,14 @@ module Core(input clk);
|
|||
|
||||
Check check(.clk(clk), .crc(crc), .result(result), .rdata(rdata), .rdata2(rdata2));
|
||||
endmodule
|
||||
module CoreHier(input clk);
|
||||
// Dummy logic to have two different hier blocks at the same level.
|
||||
integer cyc = 0;
|
||||
always @(posedge clk) begin
|
||||
cyc += 1;
|
||||
if (cyc == 1) $display("%d", clk);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module Check(
|
||||
input clk,
|
||||
|
|
|
@ -11,11 +11,12 @@ import vltest_bootstrap
|
|||
|
||||
test.scenarios('vltmt')
|
||||
test.top_filename = "t/t_hier_block_perf.v"
|
||||
cycles = 100000
|
||||
cycles = 100
|
||||
test.sim_time = cycles * 10 + 1000
|
||||
|
||||
threads = 2
|
||||
flags = ["--hierarchical", "-Wno-UNOPTFLAT", "-DSIM_CYCLES=" + str(cycles)]
|
||||
config_file = test.t_dir + "/" + test.name + ".vlt"
|
||||
flags = [config_file, "--hierarchical", "-Wno-UNOPTFLAT", "-DSIM_CYCLES=" + str(cycles)]
|
||||
|
||||
test.compile(benchmarksim=1, v_flags2=["--prof-pgo"] + flags, threads=threads)
|
||||
|
||||
|
@ -24,15 +25,21 @@ test.execute(all_run_flags=[
|
|||
" +verilator+prof+exec+file+/dev/null",
|
||||
" +verilator+prof+vlt+file+" + test.obj_dir + "/profile.vlt"]) # yapf:disable
|
||||
|
||||
test.file_grep(test.obj_dir + "/profile.vlt", r'profile_data -model "VTest"')
|
||||
test.file_grep(test.obj_dir + "/profile.vlt", r'profile_data -model "VCheck"')
|
||||
test.file_grep(test.obj_dir + "/profile.vlt", r'profile_data -model "VCoreHier"')
|
||||
test.file_grep(test.obj_dir + "/profile.vlt", r'profile_data -model "V' + test.name + '"')
|
||||
|
||||
# Check for cost rollovers
|
||||
test.file_grep_not(test.obj_dir + "/profile.vlt", r'.*cost 64\'d\d{18}.*')
|
||||
|
||||
# Differentiate benchmarksim results
|
||||
test.name = test.name + "_optimized"
|
||||
test.compile(
|
||||
benchmarksim=1,
|
||||
# Intentionally no --prof-pgo here to make sure profile data can be read in
|
||||
# without it (that is: --prof-pgo has no effect on profile_data hash names)
|
||||
v_flags2=flags,
|
||||
v_flags2=[test.obj_dir + "/profile.vlt", "-Wno-PROFOUTOFDATE"] + flags,
|
||||
threads=threads)
|
||||
|
||||
test.execute()
|
||||
|
|
|
@ -8,3 +8,5 @@
|
|||
hier_workers -module "Test" -workers 2
|
||||
hier_block -module "Check"
|
||||
hier_workers -module "Check" -workers 2
|
||||
hier_block -module "CoreHier"
|
||||
hier_workers -module "CoreHier" -workers 2
|
|
@ -1,45 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2025 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
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vltmt')
|
||||
test.top_filename = "t/t_hier_block_perf.v"
|
||||
cycles = 100000
|
||||
test.sim_time = cycles * 10 + 1000
|
||||
|
||||
threads = 2
|
||||
config_file = test.t_dir + "/" + test.name + ".vlt"
|
||||
flags = [config_file, "--hierarchical", "-Wno-UNOPTFLAT", "-DSIM_CYCLES=" + str(cycles)]
|
||||
|
||||
test.compile(benchmarksim=1, v_flags2=["--prof-pgo"] + flags, threads=threads)
|
||||
|
||||
test.execute(all_run_flags=[
|
||||
"+verilator+prof+exec+start+0",
|
||||
" +verilator+prof+exec+file+/dev/null",
|
||||
" +verilator+prof+vlt+file+" + test.obj_dir + "/profile.vlt"]) # yapf:disable
|
||||
|
||||
test.file_grep(test.obj_dir + "/profile.vlt", r'profile_data -model "VTest"')
|
||||
test.file_grep(test.obj_dir + "/profile.vlt", r'profile_data -model "V' + test.name + '"')
|
||||
|
||||
# Check for cost rollovers
|
||||
test.file_grep_not(test.obj_dir + "/profile.vlt", r'.*cost 64\'d\d{18}.*')
|
||||
|
||||
# Differentiate benchmarksim results
|
||||
test.name = test.name + "_optimized"
|
||||
test.compile(
|
||||
benchmarksim=1,
|
||||
# Intentionally no --prof-pgo here to make sure profile data can be read in
|
||||
# without it (that is: --prof-pgo has no effect on profile_data hash names)
|
||||
v_flags2=flags,
|
||||
threads=threads)
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
Loading…
Reference in New Issue