Internals: Some prep from branch towards multitrace (#5813 prep)

This commit is contained in:
Wilson Snyder 2025-09-27 20:54:26 -04:00
parent 8c7c6c594a
commit a7e6efb4c0
9 changed files with 106 additions and 68 deletions

View File

@ -664,7 +664,8 @@ class EmitCTrace final : EmitCFunc {
"IPTION: Verilator output: Tracing implementation internals\n");
// Includes
puts("#include \"" + v3Global.opt.traceSourceLang() + ".h\"\n");
for (const string& base : v3Global.opt.traceSourceLangs())
puts("#include \"" + base + ".h\"\n");
puts("#include \"" + EmitCUtil::symClassName() + ".h\"\n");
puts("\n");
}
@ -693,7 +694,8 @@ class EmitCTrace final : EmitCFunc {
"IPTION: Verilator output: Tracing declarations\n");
// Includes
typesFp()->puts("#include \"" + v3Global.opt.traceSourceLang() + ".h\"\n");
for (const string& base : v3Global.opt.traceSourceLangs())
typesFp()->puts("#include \"" + base + ".h\"\n");
typesFp()->puts("\n");
typesFp()->puts("\nvoid " + EmitCUtil::prefixNameProtect(m_modp) + "__"
@ -860,7 +862,7 @@ class EmitCTrace final : EmitCFunc {
int emitTraceDeclDType(AstNodeDType* nodep) {
// Return enum number or -1 for none
if (v3Global.opt.traceFormat().fst()) {
if (v3Global.opt.traceEnabledFst()) {
// Skip over refs-to-refs, but stop before final ref so can get data type name
// Alternatively back in V3Width we could push enum names from upper typedefs
if (AstEnumDType* const enump = VN_CAST(nodep->skipRefToEnump(), EnumDType)) {

View File

@ -82,7 +82,7 @@ class EmitCModel final : public EmitCFunc {
puts("\n");
puts("class " + EmitCUtil::symClassName() + ";\n");
puts("class " + EmitCUtil::prefixNameProtect(modp) + ";\n"); // For rootp pointer only
if (v3Global.opt.trace()) puts("class " + v3Global.opt.traceClassLang() + ";\n");
for (const string& base : v3Global.opt.traceClassLangs()) puts("class " + base + ";\n");
emitModCUse(modp, VUseType::INT_FWD_CLASS); // Note: This is needed for cell forwarding
puts("\n");
@ -637,9 +637,8 @@ class EmitCModel final : public EmitCFunc {
puts("\n");
puts("#include \"" + EmitCUtil::pchClassName() + ".h\"\n");
if (v3Global.opt.trace()) {
puts("#include \"" + v3Global.opt.traceSourceLang() + ".h\"\n");
}
for (const string& base : v3Global.opt.traceSourceLangs())
puts("#include \"" + base + ".h\"\n");
emitConstructorImplementation(modp);
emitDestructorImplementation();

View File

@ -416,7 +416,8 @@ void EmitCSyms::emitSymHdr() {
ofp()->putsIntTopInclude();
puts("#include \"verilated.h\"\n");
if (v3Global.needTraceDumper()) {
puts("#include \"" + v3Global.opt.traceSourceLang() + ".h\"\n");
for (const string& base : v3Global.opt.traceSourceLangs())
puts("#include \"" + base + ".h\"\n");
}
if (v3Global.opt.usesProfiler()) puts("#include \"verilated_profiler.h\"\n");
@ -747,7 +748,7 @@ void EmitCSyms::emitSymImp() {
puts("if (VL_UNLIKELY(!__Vm_dumperp)) {\n");
puts("__Vm_dumperp = new " + v3Global.opt.traceClassLang() + "();\n");
puts("__Vm_modelp->trace(__Vm_dumperp, 0, 0);\n");
puts("std::string dumpfile = _vm_contextp__->dumpfileCheck();\n");
puts("const std::string dumpfile = _vm_contextp__->dumpfileCheck();\n");
puts("__Vm_dumperp->open(dumpfile.c_str());\n");
puts("__Vm_dumping = true;\n");
puts("}\n");

View File

@ -226,7 +226,8 @@ std::vector<std::string> V3Global::verilatedCppFiles() {
if (v3Global.opt.vpi()) result.emplace_back("verilated_vpi.cpp");
if (v3Global.opt.savable()) result.emplace_back("verilated_save.cpp");
if (v3Global.opt.coverage()) result.emplace_back("verilated_cov.cpp");
if (v3Global.opt.trace()) result.emplace_back(v3Global.opt.traceSourceBase() + "_c.cpp");
for (const string& base : v3Global.opt.traceSourceBases())
result.emplace_back(base + "_c.cpp");
if (v3Global.usesProbDist()) result.emplace_back("verilated_probdist.cpp");
if (v3Global.usesTiming()) result.emplace_back("verilated_timing.cpp");
if (v3Global.useRandomizeMethods()) result.emplace_back("verilated_random.cpp");

View File

@ -477,6 +477,41 @@ void V3Options::decorations(FileLine* fl, const string& arg) { // --decorations
}
}
std::vector<std::string> V3Options::traceClassBases() const VL_MT_SAFE {
std::vector<std::string> result;
if (traceEnabledFst()) result.emplace_back("VerilatedFst");
if (traceEnabledSaif()) result.emplace_back("VerilatedSaif");
if (traceEnabledVcd()) result.emplace_back("VerilatedVcd");
return result;
}
std::vector<std::string> V3Options::traceClassLangs() const VL_MT_SAFE {
std::vector<std::string> result;
for (auto& cbase : traceClassBases()) result.emplace_back(cbase + (systemC() ? "Sc" : "C"));
return result;
}
std::vector<std::string> V3Options::traceSourceBases() const VL_MT_SAFE {
std::vector<std::string> result;
if (traceEnabledFst()) result.emplace_back("verilated_fst");
if (traceEnabledSaif()) result.emplace_back("verilated_saif");
if (traceEnabledVcd()) result.emplace_back("verilated_vcd");
return result;
}
std::vector<std::string> V3Options::traceSourceLangs() const VL_MT_SAFE {
std::vector<std::string> result = traceSourceBases();
for (std::string& str : result) str += systemC() ? "_sc"s : "_c"s;
return result;
}
std::string V3Options::traceClassBase() const VL_MT_SAFE {
// Deprecated - Needs to be fixed to support multiple trace, issue #5813
UASSERT(!traceClassBases().empty(), "Call traceClassBase only when trace() enabled");
return traceClassBases().front();
}
std::string V3Options::traceClassLang() const VL_MT_SAFE {
// Deprecated - Needs to be fixed to support multiple trace, issue #5813
UASSERT(!traceClassBases().empty(), "Call traceClassLang only when trace() enabled");
return traceClassLangs().front();
}
//######################################################################
// File searching
@ -903,6 +938,14 @@ void V3Options::notify() VL_MT_DISABLED {
m_main = false;
}
if (trace() && !traceEnabledFst() && !traceEnabledSaif() && !traceEnabledVcd()) {
m_traceEnabledVcd = true; // No format, with --trace means wanted --trace-vcd
}
if (traceEnabledFst() || traceEnabledSaif() || traceEnabledVcd()) m_trace = true;
const int ntraces = traceEnabledFst() + traceEnabledSaif() + traceEnabledVcd();
if (ntraces > 1) // Issue #5813
cmdfl->v3error("Only one of --trace-fst, --trace-saif or --trace--vcd may be used");
if (protectIds()) {
if (allPublic()) {
// We always call protect() on names, we don't check if public or not
@ -940,7 +983,7 @@ void V3Options::notify() VL_MT_DISABLED {
if (trace()) {
// With --trace-vcd, --trace-threads is ignored
if (traceFormat().vcd()) m_traceThreads = 1;
if (traceEnabledVcd()) m_traceThreads = 1;
}
UASSERT(!(useTraceParallel() && useTraceOffload()),
@ -1671,20 +1714,15 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
DECL_OPTION("-top", Set, &m_topModule);
DECL_OPTION("-top-module", Set, &m_topModule);
DECL_OPTION("-trace", OnOff, &m_trace);
DECL_OPTION("-trace-saif", CbCall, [this]() {
m_trace = true;
m_traceFormat = TraceFormat::SAIF;
});
DECL_OPTION("-trace-saif", CbCall, [this]() { m_traceEnabledSaif = true; });
DECL_OPTION("-trace-coverage", OnOff, &m_traceCoverage);
DECL_OPTION("-trace-depth", Set, &m_traceDepth);
DECL_OPTION("-trace-fst", CbCall, [this]() {
m_trace = true;
m_traceFormat = TraceFormat::FST;
m_traceEnabledFst = true;
addLdLibs("-lz");
});
DECL_OPTION("-trace-fst-thread", CbCall, [this, fl]() {
m_trace = true;
m_traceFormat = TraceFormat::FST;
m_traceEnabledFst = true;
addLdLibs("-lz");
fl->v3warn(DEPRECATED, "Option --trace-fst-thread is deprecated. "
"Use --trace-fst with --trace-threads > 0.");
@ -1701,10 +1739,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
});
DECL_OPTION("-no-trace-top", Set, &m_noTraceTop);
DECL_OPTION("-trace-underscore", OnOff, &m_traceUnderscore);
DECL_OPTION("-trace-vcd", CbCall, [this]() {
m_trace = true;
m_traceFormat = TraceFormat::VCD;
});
DECL_OPTION("-trace-vcd", CbCall, [this]() { m_traceEnabledVcd = true; });
DECL_OPTION("-U", CbPartialMatch, &V3PreShell::undef);
DECL_OPTION("-underline-zero", OnOff, &m_underlineZero); // Deprecated
@ -2127,8 +2162,6 @@ void V3Options::showVersion(bool verbose) {
V3Options::V3Options() {
m_impp = new V3OptionsImp;
m_traceFormat = TraceFormat::VCD;
m_makeDir = "obj_dir";
m_unusedRegexp = "*unused*";
m_xAssign = "fast";

View File

@ -159,35 +159,6 @@ inline std::ostream& operator<<(std::ostream& os, const VTimescale& rhs) {
// ######################################################################
class TraceFormat final {
public:
enum en : uint8_t { VCD = 0, FST, SAIF } m_e;
// cppcheck-suppress noExplicitConstructor
constexpr TraceFormat(en _e = VCD)
: m_e{_e} {}
explicit TraceFormat(int _e)
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
constexpr operator en() const { return m_e; }
bool fst() const { return m_e == FST; }
bool saif() const { return m_e == SAIF; }
bool vcd() const { return m_e == VCD; }
string classBase() const VL_MT_SAFE {
static const char* const names[] = {"VerilatedVcd", "VerilatedFst", "VerilatedSaif"};
return names[m_e];
}
string sourceName() const VL_MT_SAFE {
static const char* const names[] = {"verilated_vcd", "verilated_fst", "verilated_saif"};
return names[m_e];
}
};
constexpr bool operator==(const TraceFormat& lhs, const TraceFormat& rhs) {
return lhs.m_e == rhs.m_e;
}
constexpr bool operator==(const TraceFormat& lhs, TraceFormat::en rhs) { return lhs.m_e == rhs; }
constexpr bool operator==(TraceFormat::en lhs, const TraceFormat& rhs) { return lhs == rhs.m_e; }
// ######################################################################
// Information given by --hierarchical-block option
class V3HierarchicalBlockOption final {
public:
@ -321,6 +292,9 @@ private:
VOptionBool m_timing; // main switch: --timing
bool m_trace = false; // main switch: --trace
bool m_traceCoverage = false; // main switch: --trace-coverage
bool m_traceEnabledFst = false; // main switch: --trace-fst
bool m_traceEnabledSaif = false; // main switch: --trace-saif
bool m_traceEnabledVcd = false; // main switch: --trace-vcd
bool m_traceParams = true; // main switch: --trace-params
bool m_traceStructs = false; // main switch: --trace-structs
bool m_noTraceTop = false; // main switch: --no-trace-top
@ -366,7 +340,6 @@ private:
VTimescale m_timeOverridePrec; // main switch: --timescale-override
VTimescale m_timeOverrideUnit; // main switch: --timescale-override
int m_traceDepth = 0; // main switch: --trace-depth
TraceFormat m_traceFormat; // main switch: --trace or --trace-fst
int m_traceMaxArray = 32; // main switch: --trace-max-array
int m_traceMaxWidth = 256; // main switch: --trace-max-width
int m_traceThreads = 0; // main switch: --trace-threads
@ -565,6 +538,9 @@ public:
VOptionBool timing() const { return m_timing; }
bool trace() const { return m_trace; }
bool traceCoverage() const { return m_traceCoverage; }
bool traceEnabledFst() const { return m_traceEnabledFst; }
bool traceEnabledSaif() const { return m_traceEnabledSaif; }
bool traceEnabledVcd() const { return m_traceEnabledVcd; }
bool traceParams() const { return m_traceParams; }
bool traceStructs() const { return m_traceStructs; }
bool traceUnderscore() const { return m_traceUnderscore; }
@ -638,18 +614,14 @@ public:
VTimescale timeComputePrec(const VTimescale& flag) const;
VTimescale timeComputeUnit(const VTimescale& flag) const;
int traceDepth() const { return m_traceDepth; }
TraceFormat traceFormat() const { return m_traceFormat; }
bool traceEnabledFst() const { return trace() && traceFormat().fst(); }
bool traceEnabledSaif() const { return trace() && traceFormat().saif(); }
bool traceEnabledVcd() const { return trace() && traceFormat().vcd(); }
int traceMaxArray() const { return m_traceMaxArray; }
int traceMaxWidth() const { return m_traceMaxWidth; }
int traceThreads() const { return m_traceThreads; }
bool useTraceOffload() const { return trace() && traceFormat().fst() && traceThreads() > 1; }
bool useTraceOffload() const { return trace() && traceEnabledFst() && traceThreads() > 1; }
bool useTraceParallel() const {
return trace() && traceFormat().vcd() && (threads() > 1 || hierChild() > 1);
return trace() && traceEnabledVcd() && (threads() > 1 || hierChild() > 1);
}
bool useFstWriterThread() const { return traceThreads() && traceFormat().fst(); }
bool useFstWriterThread() const { return traceThreads() && traceEnabledFst(); }
unsigned vmTraceThreads() const {
return useTraceParallel() ? threads() : useTraceOffload() ? 1 : 0;
}
@ -762,12 +734,12 @@ public:
bool fTaskifyAll() const { return m_fTaskifyAll; }
bool fVarSplit() const { return m_fVarSplit; }
string traceClassBase() const VL_MT_SAFE { return m_traceFormat.classBase(); }
string traceClassLang() const { return m_traceFormat.classBase() + (systemC() ? "Sc" : "C"); }
string traceSourceBase() const { return m_traceFormat.sourceName(); }
string traceSourceLang() const VL_MT_SAFE {
return m_traceFormat.sourceName() + (systemC() ? "_sc" : "_c");
}
std::string traceClassBase() const VL_MT_SAFE; // Deprecated
std::string traceClassLang() const VL_MT_SAFE; // Deprecated
std::vector<std::string> traceClassBases() const VL_MT_SAFE;
std::vector<std::string> traceClassLangs() const VL_MT_SAFE;
std::vector<std::string> traceSourceBases() const VL_MT_SAFE;
std::vector<std::string> traceSourceLangs() const VL_MT_SAFE;
bool hierarchical() const { return m_hierarchical; }
int hierChild() const VL_MT_SAFE { return m_hierChild; }

View File

@ -0,0 +1,3 @@
%Error: Only one of --trace-fst, --trace-saif or --trace--vcd may be used
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -0,0 +1,18 @@
#!/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('vlt')
test.lint(verilator_flags=['--trace-fst --trace-vcd'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,9 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t;
initial $finish;
endmodule