Fix scope tree in traces in hierarchical mode (#7042)

This commit is contained in:
Geza Lore 2026-02-13 01:54:03 +00:00 committed by GitHub
parent b84466ec10
commit 3dd2b762e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 39586 additions and 46566 deletions

View File

@ -2571,3 +2571,9 @@ The grammar of control commands is as follows:
scope which the rule is to match, where 0 means all levels below, 1 the
exact level as the provided scope, and 2 means an additional level of
children below the provided scope, etc.
.. option:: verilator_lib -module "<modulename>"
Internal use only. Marks the specified module as being a stub for a library
created by :option:`--lib-creat` (including when created with
:option:`--hierarchical`). Required for special internal processing.

View File

@ -134,7 +134,8 @@ void VerilatedFst::declDTypeEnum(int dtypenum, const char* name, uint32_t elemen
const char** itemValuesp) {
const fstEnumHandle enumNum
= fstWriterCreateEnumTable(m_fst, name, elements, minValbits, itemNamesp, itemValuesp);
m_local2fstdtype[dtypenum] = enumNum;
const bool newEntry = m_local2fstdtype[initUserp()].emplace(dtypenum, enumNum).second;
assert(newEntry);
}
// TODO: should return std::optional<fstScopeType>, but I can't have C++17
@ -205,7 +206,9 @@ void VerilatedFst::declare(uint32_t code, const char* name, int dtypenum,
if (bussed) name_ss << " [" << msb << ":" << lsb << "]";
const std::string name_str = name_ss.str();
if (dtypenum > 0) fstWriterEmitEnumTableRef(m_fst, m_local2fstdtype[dtypenum]);
if (dtypenum > 0) {
fstWriterEmitEnumTableRef(m_fst, m_local2fstdtype.at(initUserp()).at(dtypenum));
}
fstVarDir varDir = FST_VD_IMPLICIT;
switch (direction) {

View File

@ -53,7 +53,7 @@ private:
fstWriterContext* m_fst = nullptr;
std::map<uint32_t, vlFstHandle> m_code2symbol;
std::map<int, vlFstEnumHandle> m_local2fstdtype;
std::map<void*, std::map<int, vlFstEnumHandle>> m_local2fstdtype;
vlFstHandle* m_symbolp = nullptr; // same as m_code2symbol, but as an array
char* m_strbufp = nullptr; // String buffer long enough to hold maxBits() chars
uint64_t m_timeui = 0; // Time to emit, 0 = not needed

View File

@ -233,22 +233,41 @@ private:
};
const uint32_t m_fidx; // The index of the tracing function
void* const m_userp; // The user pointer to pass to the callback (the symbol table)
CallbackRecord(initCb_t cb, void* userp)
const bool m_isLibInstance; // Whether the callback is for a --lib-create instance
const std::string m_name; // The name of the instance callback is for
const uint32_t m_nTraceCodes; // The number of trace codes used by callback
CallbackRecord(initCb_t cb, void* userp, bool isLibInstance, const std::string& name,
uint32_t nTraceCodes)
: m_initCb{cb}
, m_fidx{0}
, m_userp{userp} {}
, m_userp{userp}
, m_isLibInstance{isLibInstance}
, m_name{name}
, m_nTraceCodes{nTraceCodes} {}
CallbackRecord(dumpCb_t cb, uint32_t fidx, void* userp)
: m_dumpCb{cb}
, m_fidx{fidx}
, m_userp{userp} {}
, m_userp{userp}
, m_isLibInstance{false} // Don't care
, m_name{} // Don't care
, m_nTraceCodes{0} // Don't care
{}
CallbackRecord(dumpOffloadCb_t cb, uint32_t fidx, void* userp)
: m_dumpOffloadCb{cb}
, m_fidx{fidx}
, m_userp{userp} {}
, m_userp{userp}
, m_isLibInstance{false} // Don't care
, m_name{} // Don't care
, m_nTraceCodes{0} // Don't care
{}
CallbackRecord(cleanupCb_t cb, void* userp)
: m_cleanupCb{cb}
, m_fidx{0}
, m_userp{userp} {}
, m_userp{userp}
, m_isLibInstance{false} // Don't care
, m_name{} // Don't care
, m_nTraceCodes{0} // Don't care
{}
};
bool m_offload = false; // Use the offload thread
@ -292,6 +311,7 @@ private:
uint32_t m_nextCode = 0; // Next code number to assign
uint32_t m_numSignals = 0; // Number of distinct signals
uint32_t m_maxBits = 0; // Number of bits in the widest signal
void* m_initUserp = nullptr; // The callback userp of the instance currently being initialized
// TODO: Should keep this as a Trie, that is how it's accessed all the time.
std::vector<std::pair<int, std::string>> m_dumpvars; // dumpvar() entries
double m_timeRes = 1e-9; // Time resolution (ns/ms etc)
@ -359,6 +379,7 @@ protected:
uint32_t nextCode() const { return m_nextCode; }
uint32_t numSignals() const { return m_numSignals; }
uint32_t maxBits() const { return m_maxBits; }
void* initUserp() const { return m_initUserp; }
void constDump(bool value) { m_constDump = value; }
void fullDump(bool value) { m_fullDump = value; }
@ -429,7 +450,8 @@ public:
// Non-hot path internal interface to Verilator generated code
void addModel(VerilatedModel*) VL_MT_SAFE_EXCLUDES(m_mutex);
void addInitCb(initCb_t cb, void* userp) VL_MT_SAFE;
void addInitCb(initCb_t cb, void* userp, const std::string& name, bool isLibInstance,
uint32_t nTraceCodes) VL_MT_SAFE;
void addConstCb(dumpCb_t cb, uint32_t fidx, void* userp) VL_MT_SAFE;
void addConstCb(dumpOffloadCb_t cb, uint32_t fidx, void* userp) VL_MT_SAFE;
void addFullCb(dumpCb_t cb, uint32_t fidx, void* userp) VL_MT_SAFE;
@ -437,6 +459,7 @@ public:
void addChgCb(dumpCb_t cb, uint32_t fidx, void* userp) VL_MT_SAFE;
void addChgCb(dumpOffloadCb_t cb, uint32_t fidx, void* userp) VL_MT_SAFE;
void addCleanupCb(cleanupCb_t cb, void* userp) VL_MT_SAFE;
void initLib(const std::string& name) VL_MT_UNSAFE;
};
//=============================================================================

View File

@ -312,10 +312,17 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::traceInit() VL_MT_UNSAFE {
m_maxBits = 0;
m_sigs_enabledVec.clear();
// Call all initialize callbacks, which will:
// Call all initialize callbacks for root (non-library) instances, which will:
// - Call decl* for each signal (these eventually call ::declCode)
// - Call the initialize callbacks of library instances underneath
// - Store the base code
for (const CallbackRecord& cbr : m_initCbs) cbr.m_initCb(cbr.m_userp, self(), nextCode());
for (const CallbackRecord& cbr : m_initCbs) {
if (cbr.m_isLibInstance) continue; // Will be called from parent callback
const uint32_t baseCode = nextCode();
m_nextCode += cbr.m_nTraceCodes;
m_initUserp = cbr.m_userp;
cbr.m_initCb(cbr.m_userp, self(), baseCode);
}
if (expectedCodes && nextCode() != expectedCodes) {
VL_FATAL_MT(__FILE__, __LINE__, "",
@ -393,8 +400,6 @@ bool VerilatedTrace<VL_SUB_T, VL_BUF_T>::declCode(uint32_t code, const std::stri
break;
}
int codesNeeded = VL_WORDS_I(bits);
m_nextCode = std::max(m_nextCode, code + codesNeeded);
++m_numSignals;
m_maxBits = std::max(m_maxBits, bits);
return enabled;
@ -680,8 +685,10 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addCallbackRecord(std::vector<CallbackR
}
template <>
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addInitCb(initCb_t cb, void* userp) VL_MT_SAFE {
addCallbackRecord(m_initCbs, CallbackRecord{cb, userp});
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addInitCb(initCb_t cb, void* userp,
const std::string& name, bool isLibInstance,
uint32_t nTraceCodes) VL_MT_SAFE {
addCallbackRecord(m_initCbs, CallbackRecord{cb, userp, isLibInstance, name, nTraceCodes});
}
template <>
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addConstCb(dumpCb_t cb, uint32_t fidx,
@ -718,6 +725,20 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addCleanupCb(cleanupCb_t cb, void* user
addCallbackRecord(m_cleanupCbs, CallbackRecord{cb, userp});
}
template <>
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::initLib(const std::string& name) VL_MT_SAFE {
// Note it's possible the instance doesn't exist if the lib was compiled without tracing
void* const prevInitUserp = m_initUserp;
for (const CallbackRecord& cbr : m_initCbs) {
if (cbr.m_name != name) continue;
const uint32_t baseCode = nextCode();
m_nextCode += cbr.m_nTraceCodes;
m_initUserp = cbr.m_userp;
cbr.m_initCb(cbr.m_userp, self(), baseCode);
m_initUserp = prevInitUserp;
}
}
//=========================================================================
// Primitives converting binary values to strings...

View File

@ -1471,6 +1471,7 @@ public:
UNROLL_FULL,
FULL_CASE,
PARALLEL_CASE,
VERILATOR_LIB,
_ENUM_SIZE
};
enum en m_e;
@ -1489,6 +1490,7 @@ public:
"UNROLL_FULL", //
"FULL_CASE", //
"PARALLEL_CASE", //
"VERILATOR_LIB", //
"_ENUM_SIZE" //
};
return names[m_e];

View File

@ -285,6 +285,7 @@ class AstNodeModule VL_NOT_FINAL : public AstNode {
bool m_internal : 1; // Internally created
bool m_recursive : 1; // Recursive module
bool m_recursiveClone : 1; // If recursive, what module it clones, otherwise nullptr
bool m_verilatorLib : 1; // Module is a stub for a Verilator produced --lib-create
protected:
AstNodeModule(VNType t, FileLine* fl, const string& name, const string& libname)
: AstNode{t, fl}
@ -301,7 +302,8 @@ protected:
, m_hierParams{false}
, m_internal{false}
, m_recursive{false}
, m_recursiveClone{false} {}
, m_recursiveClone{false}
, m_verilatorLib{false} {}
public:
ASTGEN_MEMBERS_AstNodeModule;
@ -343,6 +345,8 @@ public:
void recursive(bool flag) { m_recursive = flag; }
void recursiveClone(bool flag) { m_recursiveClone = flag; }
bool recursiveClone() const { return m_recursiveClone; }
void verilatorLib(bool flag) { m_verilatorLib = flag; }
bool verilatorLib() const { return m_verilatorLib; }
VLifetime lifetime() const { return m_lifetime; }
void lifetime(const VLifetime& flag) { m_lifetime = flag; }
VTimescale timeunit() const { return m_timeunit; }
@ -1251,6 +1255,7 @@ class AstNetlist final : public AstNode {
VTimescale m_timeunit; // Global time unit
VTimescale m_timeprecision; // Global time precision
bool m_timescaleSpecified = false; // Input HDL specified timescale
uint32_t m_nTraceCodes = 0; // Number of trace codes used by design
public:
AstNetlist();
ASTGEN_MEMBERS_AstNetlist;
@ -1292,6 +1297,8 @@ public:
void timeprecisionMerge(FileLine*, const VTimescale& value);
void timescaleSpecified(bool specified) { m_timescaleSpecified = specified; }
bool timescaleSpecified() const { return m_timescaleSpecified; }
uint32_t nTraceCodes() const { return m_nTraceCodes; }
void nTraceCodes(uint32_t value) { m_nTraceCodes = value; }
AstVarScope* stlFirstIterationp();
void clearStlFirstIterationp() { m_stlFirstIterationp = nullptr; }
};

View File

@ -2567,6 +2567,7 @@ void AstNodeModule::dump(std::ostream& str) const {
} else if (recursive()) {
str << " [RECURSIVE]";
}
if (verilatorLib()) str << " [VERILATOR-LIB]";
str << " [" << timeunit() << "]";
if (libname() != "work") str << " libname=" << libname();
}
@ -2579,6 +2580,7 @@ void AstNodeModule::dumpJson(std::ostream& str) const {
dumpJsonBoolFuncIf(str, dead);
dumpJsonBoolFuncIf(str, recursiveClone);
dumpJsonBoolFuncIf(str, recursive);
dumpJsonBoolFuncIf(str, verilatorLib);
dumpJsonStr(str, "timeunit", timeunit().ascii());
if (libname() != "work") dumpJsonStr(str, "libname=", libname());
dumpJsonGen(str);

View File

@ -292,9 +292,12 @@ class DeadVisitor final : public VNVisitor {
void visit(AstVar* nodep) override {
iterateChildren(nodep);
checkAll(nodep);
if (nodep->isSigPublic() && m_modp && VN_IS(m_modp, Package)) m_modp->user1Inc();
if (m_selloopvarsp) nodep->user1Inc();
if (mightElimVar(nodep)) m_varsp.push_back(nodep);
if (mightElimVar(nodep)) {
m_varsp.push_back(nodep);
} else {
if (m_modp && VN_IS(m_modp, Package)) m_modp->user1Inc();
}
}
void visit(AstNodeAssign* nodep) override {
// See if simple assignments to variables may be eliminated because

View File

@ -549,10 +549,14 @@ class EmitCModel final : public EmitCFunc {
"0.\");\n");
puts("}\n");
puts("vlSymsp->__Vm_baseCode = code;\n");
puts("tracep->pushPrefix(vlSymsp->name(), VerilatedTracePrefixType::SCOPE_MODULE);\n");
if (v3Global.opt.libCreate().empty()) {
puts("tracep->pushPrefix(vlSymsp->name(), VerilatedTracePrefixType::SCOPE_MODULE);\n");
}
puts(topModNameProtected + "__" + protect("trace_decl_types") + "(tracep);\n");
puts(topModNameProtected + "__" + protect("trace_init_top") + "(vlSelf, tracep);\n");
puts("tracep->popPrefix();\n");
if (v3Global.opt.libCreate().empty()) { //
puts("tracep->popPrefix();\n");
}
puts("}\n");
// Forward declaration
@ -583,8 +587,13 @@ class EmitCModel final : public EmitCFunc {
+ " and --trace-vcd with VerilatedVcd object\");\n");
puts(/**/ "}\n");
puts(/**/ "stfp->spTrace()->addModel(this);\n");
puts(/**/ "stfp->spTrace()->addInitCb(&" + protect("trace_init")
+ ", &(vlSymsp->TOP));\n");
puts(/**/ "stfp->spTrace()->addInitCb("s //
+ "&" + protect("trace_init") //
+ ", &(vlSymsp->TOP)" //
+ ", name()" //
+ ", " + (v3Global.opt.libCreate().empty() ? "false" : "true") //
+ ", " + std::to_string(v3Global.rootp()->nTraceCodes()) //
+ ");\n");
puts(/**/ topModNameProtected + "__" + protect("trace_register")
+ "(&(vlSymsp->TOP), stfp->spTrace());\n");
puts("}\n");

View File

@ -122,6 +122,12 @@ class InlineMarkVisitor final : public VNVisitor {
if (m_modp->modPublic() && (m_modp->isTop() || !v3Global.opt.flatten())) {
cantInline("modPublic", false);
}
// If the instance is a --lib-create library stub instance, and need tracing,
// then don't inline as we need to know its a lib stub for sepecial handling
// in V3TraceDecl. See #7001.
if (m_modp->verilatorLib() && v3Global.opt.trace()) {
cantInline("verilatorLib with --trace", false);
}
iterateChildren(nodep);
}

View File

@ -307,6 +307,11 @@ class LinkResolveVisitor final : public VNVisitor {
m_modp->modPublic(true); // Need to get to the task...
nodep->unlinkFrBack();
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else if (nodep->pragType() == VPragmaType::VERILATOR_LIB) {
UASSERT_OBJ(m_modp, nodep, "VERILATOR_LIB not under a module");
m_modp->verilatorLib(true);
nodep->unlinkFrBack();
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else {
iterateChildren(nodep);
}

View File

@ -102,6 +102,8 @@ class ProtectVisitor final : public VNVisitor {
txtp->add("\n`ifdef VERILATOR\n");
txtp->add("`verilator_config\n");
txtp->add("verilator_lib -module \"" + m_libName + "\"\n");
txtp->add("profile_data -hier-dpi \"" + m_libName + "_protectlib_combo_update\" -cost 64'd"
+ std::to_string(v3Global.currentHierBlockCost()) + "\n");
txtp->add("profile_data -hier-dpi \"" + m_libName + "_protectlib_seq_update\" -cost 64'd"

View File

@ -847,6 +847,9 @@ class TraceVisitor final : public VNVisitor {
// Create the trace functions and insert them into the tree
createTraceFunctions();
// Save number of trace codes used
nodep->nTraceCodes(m_code);
}
void visit(AstNodeModule* nodep) override {
if (nodep->isTop()) m_topModp = nodep;

View File

@ -94,8 +94,6 @@ public:
// TraceDecl state, as a visitor of each AstNode
class TraceDeclVisitor final : public VNVisitor {
// NODE STATE
// STATE
AstTopScope* const m_topScopep; // The singleton AstTopScope
const AstScope* m_currScopep = nullptr; // Current scope being visited
@ -130,7 +128,7 @@ class TraceDeclVisitor final : public VNVisitor {
std::string m_path; // Path to enclosing module in original hierarchy
std::string m_name; // Name of signal/subscope
void init(const std::string& name, AstNode* nodep) {
void init(const std::string& name, AstNode* nodep, bool inTopScope) {
// Compute path in hierarchy and item name
const std::string& vcdName = AstNode::vcdName(name);
AstVar* const varp = VN_CAST(nodep, Var);
@ -149,16 +147,33 @@ class TraceDeclVisitor final : public VNVisitor {
m_path = vcdName.substr(0, pathLen);
m_name = vcdName.substr(pathLen);
}
// When creating a --lib-create library, drop the name of the top module (l2 name).
// This will be replaced by the instance name in the model that uses the library.
// This would be a bit murky when there are other top level entities ($unit,
// packages, which have an instance in all libs - a problem on its own). If
// --top-module was explicitly specified, then we will drop the prefix only for the
// actual top level module, and wrap the rest in '$libroot'. This way at least we get a
// usable dump of everything, with library instances showing in a right place, without
// pollution from other top level entities.
if (inTopScope && !v3Global.opt.libCreate().empty()) {
const size_t start = m_path.find(' ');
// Must have a prefix in the top scope with lib, as top wrapper signals not traced
UASSERT_OBJ(start != std::string::npos, nodep, "No prefix with --lib-create");
const std::string prefix = m_path.substr(0, start);
m_path = m_path.substr(start + 1);
if (v3Global.opt.topModule() != prefix) m_path = "$libroot " + m_path;
}
}
public:
explicit TraceEntry(AstVarScope* vscp)
explicit TraceEntry(const AstScope* scopep, AstVarScope* vscp)
: m_vscp{vscp} {
init(vscp->varp()->name(), vscp->varp());
init(vscp->varp()->name(), vscp->varp(), scopep->isTop());
}
explicit TraceEntry(AstCell* cellp)
explicit TraceEntry(const AstScope* scopep, AstCell* cellp)
: m_cellp{cellp} {
init(cellp->name(), cellp);
init(cellp->name(), cellp, scopep->isTop());
}
int operatorCompare(const TraceEntry& b) const {
if (const int cmp = path().compare(b.path())) return cmp < 0;
@ -296,6 +311,21 @@ class TraceDeclVisitor final : public VNVisitor {
VL_DO_DANGLING(placeholderp->deleteTree(), placeholderp);
}
void fixupLibStub(const std::string& path, AstNodeStmt* placeholderp) {
FileLine* const flp = placeholderp->fileline();
// Call the initialization function for the library instance
AstCStmt* const initp = new AstCStmt{flp};
initp->add("tracep->initLib(vlSymsp->name() + ");
initp->add(new AstConst{flp, AstConst::String{}, "." + AstNode::prettyName(path)});
initp->add(");\n");
placeholderp->addNextHere(initp);
// Delete the placeholder
VL_DO_DANGLING(placeholderp->unlinkFrBack()->deleteTree(), placeholderp);
return;
}
void fixupPlaceholders() {
// Fix up cell initialization placehodlers
UINFO(9, "fixupPlaceholders()");
@ -304,7 +334,11 @@ class TraceDeclVisitor final : public VNVisitor {
const AstCell* const cellp = std::get<1>(item);
AstNodeStmt* const placeholderp = std::get<2>(item);
const std::string path = parentp->name() + "__DOT__" + cellp->name();
fixupPlaceholder(path, placeholderp);
if (cellp->modp()->verilatorLib()) {
fixupLibStub(path, placeholderp);
} else {
fixupPlaceholder(path, placeholderp);
}
}
// Fix up interface reference initialization placeholders
@ -364,6 +398,9 @@ class TraceDeclVisitor final : public VNVisitor {
UASSERT_OBJ(!m_traValuep, nodep, "Should not nest");
UASSERT_OBJ(m_traName.empty(), nodep, "Should not nest");
// If this is a stub for a --lib-create library, skip.
if (nodep->modp()->verilatorLib()) return;
VL_RESTORER(m_currScopep);
m_currScopep = nodep;
@ -372,7 +409,7 @@ class TraceDeclVisitor final : public VNVisitor {
// Gather cells under this scope
for (AstNode* stmtp = nodep->modp()->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (AstCell* const cellp = VN_CAST(stmtp, Cell)) m_entries.emplace_back(cellp);
if (AstCell* const cellp = VN_CAST(stmtp, Cell)) m_entries.emplace_back(nodep, cellp);
}
if (!m_entries.empty()) {
@ -483,8 +520,16 @@ class TraceDeclVisitor final : public VNVisitor {
if (nodep->varp()->isClassMember()) return;
if (nodep->varp()->isFuncLocal()) return;
// When creating a --lib-create library ...
if (!v3Global.opt.libCreate().empty()) {
// Ignore the wrapper created primary IO ports
if (nodep->varp()->isPrimaryIO()) return;
// Ignore parameters in packages. These will be traced at the top level.
if (nodep->varp()->isParam() && VN_IS(nodep->scopep()->modp(), Package)) return;
}
// Add to traced signal list
m_entries.emplace_back(nodep);
m_entries.emplace_back(m_currScopep, nodep);
}
// VISITORS - Data types when tracing

View File

@ -161,6 +161,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"timing_on" { FL; return yVLT_TIMING_ON; }
"tracing_off" { FL; return yVLT_TRACING_OFF; }
"tracing_on" { FL; return yVLT_TRACING_ON; }
"verilator_lib" { FL; return yVLT_VERILATOR_LIB; }
-?"-block" { FL; return yVLT_D_BLOCK; }
-?"-contents" { FL; return yVLT_D_CONTENTS; }

View File

@ -271,6 +271,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yVLT_TIMING_ON "timing_on"
%token<fl> yVLT_TRACING_OFF "tracing_off"
%token<fl> yVLT_TRACING_ON "tracing_on"
%token<fl> yVLT_VERILATOR_LIB "verilator_lib"
%token<fl> yVLT_D_BLOCK "--block"
%token<fl> yVLT_D_CONTENTS "--contents"
@ -8199,6 +8200,8 @@ vltItem:
{ V3Control::addProfileData($<fl>1, *$2, $3->toUQuad()); }
| yVLT_PROFILE_DATA vltDModel vltDMtask vltDCost
{ V3Control::addProfileData($<fl>1, *$2, *$3, $4->toUQuad()); }
| yVLT_VERILATOR_LIB vltDModule
{ V3Control::addModulePragma(*$2, VPragmaType::VERILATOR_LIB); }
;
vltOffFront<errcodeen>:

View File

@ -2492,7 +2492,7 @@ class VlTest:
print("%Warning: HARNESS_UPDATE_GOLDEN set: cp " + fn1 + " " + fn2, file=sys.stderr)
shutil.copy(fn1, fn2)
def vcd_identical(self, fn1: str, fn2: str) -> None:
def vcd_identical(self, fn1: str, fn2: str, ignore_attr: bool = False) -> None:
"""Test if two VCD files have logically-identical contents"""
# vcddiff to check transitions, if installed
cmd = "vcddiff --help"
@ -2511,6 +2511,9 @@ class VlTest:
# Also provides backup if vcddiff not installed
h1 = self._vcd_read(fn1)
h2 = self._vcd_read(fn2)
if ignore_attr:
h1 = {k: v for k, v in h1.items() if "$attr" not in v}
h2 = {k: v for k, v in h2.items() if "$attr" not in v}
a = json.dumps(h1, sort_keys=True, indent=1)
b = json.dumps(h2, sort_keys=True, indent=1)
if a != b:
@ -2530,11 +2533,17 @@ class VlTest:
out = VtOs.run_capture(cmd, check=False)
print(out)
def fst_identical(self, fn1: str, fn2: str) -> None:
def fst_identical(self, fn1: str, fn2: str, ignore_attr: bool = False) -> None:
"""Test if two FST files have logically-identical contents"""
tmp = fn1 + ".vcd"
self.fst2vcd(fn1, tmp)
self.vcd_identical(tmp, fn2)
if fn1.endswith(".fst"):
tmp = fn1 + ".vcd"
self.fst2vcd(fn1, tmp)
fn1 = tmp
if fn2.endswith(".fst"):
tmp = fn2 + ".vcd"
self.fst2vcd(fn2, tmp)
fn2 = tmp
self.vcd_identical(fn1, fn2, ignore_attr)
def saif_identical(self, fn1: str, fn2: str) -> None:
"""Test if two SAIF files have logically-identical contents"""

View File

@ -14,6 +14,17 @@
`timescale 1ns/1ps
`endif
package stateless_pkg;
localparam int ONE = 1;
endpackage
`ifdef STATEFUL_PKG
// This is in the $unit package, and will have a copy in every library, which
// is functionally incorrect, but testing it here to make sure it's at least
// traced properly.
logic global_flag = 1'b0;
`endif
interface byte_ifs(input clk);
logic [7:0] data;
modport sender(input clk, output data);
@ -27,6 +38,13 @@ typedef enum logic [1:0] {
enum_val_3 = 2'd3
} enum_t;
typedef enum logic [1:0] {
alt_enum_0 = 2'd0,
alt_enum_1 = 2'd1,
alt_enum_2 = 2'd2,
alt_enum_3 = 2'd3
} alt_enum_t;
`ifdef AS_PROT_LIB
module secret (
clk
@ -87,6 +105,9 @@ module t #(
end
end
count <= count + 1;
`ifdef STATEFUL_PKG
global_flag <= ~global_flag;
`endif
end
`ifdef CPP_MACRO
@ -126,21 +147,33 @@ module sub0(
input wire clk,
input wire [7:0] in,
output wire [7:0] out); `HIER_BLOCK
`ifdef NO_INLINE
/* verilator no_inline_module */
`endif
logic [7:0] ff;
always_ff @(posedge clk) ff <= in;
assign out = ff;
`ifdef STATEFUL_PKG
always_ff @(posedge clk) if (ff[0]) global_flag <= ff[1];
`endif
endmodule
module sub1(
input wire clk,
input wire [11:4] in, // Uses higher LSB to cover bug3539
output wire [7:0] out); `HIER_BLOCK
`ifdef NO_INLINE
/* verilator no_inline_module */
`endif
logic [7:0] ff;
enum_t enum_v;
always_ff @(posedge clk) ff <= in + 1;
always_ff @(posedge clk) ff <= in + 8'(stateless_pkg::ONE);
always_ff @(posedge clk) enum_v <= enum_v.next();
assign out = ff;
endmodule
@ -150,6 +183,7 @@ module sub2(
output wire [7:0] out); `HIER_BLOCK
logic [7:0] ff;
alt_enum_t alt_enum_v;
// dpi_import_func returns (dpi_eport_func(v) -1)
import "DPI-C" context function int dpi_import_func(int v);
@ -160,6 +194,7 @@ module sub2(
endfunction
always_ff @(posedge clk) ff <= 8'(dpi_import_func({24'b0, in})) + 8'd2;
always_ff @(posedge clk) alt_enum_v <= alt_enum_v.next();
byte_ifs in_ifs(.clk(clk));
byte_ifs out_ifs(.clk(clk));
@ -202,6 +237,9 @@ module sub3 #(
input wire clk,
input wire [7:0] in,
output wire [7:0] out); `HIER_BLOCK
`ifdef NO_INLINE
/* verilator no_inline_module */
`endif
initial $display("P0:%d UNUSED:%d %s %d", P0, UNUSED, STR, ENUM);
@ -233,6 +271,9 @@ module sub4 #(
input wire clk,
input wire [7:0] in,
output wire[7:0] out); `HIER_BLOCK
`ifdef NO_INLINE
/* verilator no_inline_module */
`endif
initial begin
if (P1 == 2) begin
@ -296,6 +337,9 @@ module sub4 #(
endmodule
module sub5 (input wire clk, input wire [127:0] in[2][3], output logic [7:0] out[2][3]); `HIER_BLOCK
`ifdef NO_INLINE
/* verilator no_inline_module */
`endif
int count = 0;
always @(posedge clk) begin
@ -349,6 +393,9 @@ module sub5 (input wire clk, input wire [127:0] in[2][3], output logic [7:0] out
endmodule
module sub6 #(parameter P0 = 1, parameter P1 = 2) (output wire [7:0] out[2]); `HIER_BLOCK
`ifdef NO_INLINE
/* verilator no_inline_module */
`endif
assign out[0] = 8'(P0);
assign out[1] = 8'(P1);
endmodule

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,31 +4,56 @@
# 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-FileCopyrightText: 2024 Wilson Snyder
# SPDX-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.priority(30)
noinline = "noinl" in test.name
if not noinline:
test.priority(30)
test.scenarios('vlt_all')
test.top_filename = "t/t_hier_block.v"
# CI environment offers 2 VCPUs, 2 thread setting causes the following warning.
# %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads.
# So use 6 threads here though it's not optimal in performance, but ok.
verilator_common_flags = [
't/t_hier_block.cpp',
'--Wno-TIMESCALEMOD',
'--trace-fst',
'--trace-underscore', # Should not trace handle
"--trace-max-width",
"0",
"--trace-max-array",
"0",
"--trace-structs",
]
test.compile(
v_flags2=['t/t_hier_block.cpp'],
verilator_flags2=[
'--hierarchical',
'--Wno-TIMESCALEMOD',
'--trace-fst',
'--no-trace-underscore', # To avoid handle mismatches
],
threads=(6 if test.vltmt else 1))
verilator_hier_flags = verilator_common_flags + ['--hierarchical']
if noinline:
verilator_hier_flags.extend(["+define+NO_INLINE"])
test.execute()
# Compile hierarchically
test.vm_prefix = "Vhier"
test.main_filename = test.obj_dir + "/Vhier__main.cpp"
test.compile(verilator_flags2=verilator_hier_flags)
test.fst_identical(test.trace_filename, test.golden_filename)
# Compile non hierarchically
test.vm_prefix = "Vnonh"
test.main_filename = test.obj_dir + "/Vnonh__main.cpp"
test.compile(verilator_flags2=verilator_common_flags)
trace_hier = test.trace_filename.replace("simx", "hier")
trace_nonh = test.trace_filename.replace("simx", "nonh")
# Run the hierarchical model
test.execute(executable=test.obj_dir + "/Vhier")
test.run(cmd=["mv", test.trace_filename, trace_hier])
# Run the non hierarchical model
test.execute(executable=test.obj_dir + "/Vnonh")
test.run(cmd=["mv", test.trace_filename, trace_nonh])
# The two models must match - ignore enum type attributes which can differ
test.fst_identical(trace_hier, trace_nonh, ignore_attr=True)
# The hierarchical must match the reference
test.fst_identical(trace_hier, test.golden_filename.replace("_noinl", ""))
test.passes()

View File

@ -0,0 +1,17 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
import runpy
test.priority(30)
test.scenarios('vlt_all')
runpy.run_path("t/t_hier_block_trace_fst.py", globals())

File diff suppressed because it is too large Load Diff

View File

@ -4,32 +4,57 @@
# 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-FileCopyrightText: 2025 Wilson Snyder
# SPDX-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.priority(30)
noinline = "noinl" in test.name
if not noinline:
test.priority(30)
test.scenarios('vlt_all')
test.top_filename = "t/t_hier_block.v"
test.golden_filename = "t/t_hier_block_trace_saif.out"
# CI environment offers 2 VCPUs, 2 thread setting causes the following warning.
# %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads.
# So use 6 threads here though it's not optimal in performance, but ok.
verilator_common_flags = [
't/t_hier_block.cpp',
'--Wno-TIMESCALEMOD',
'--trace-saif',
'--trace-underscore', # Should not trace handle
"--trace-max-width",
"0",
"--trace-max-array",
"0",
"--trace-structs",
]
test.compile(
v_flags2=['t/t_hier_block.cpp'],
verilator_flags2=[
'--hierarchical',
'--Wno-TIMESCALEMOD',
'--trace-saif',
'--no-trace-underscore', # To avoid handle mismatches
],
threads=(6 if test.vltmt else 1))
verilator_hier_flags = verilator_common_flags + ['--hierarchical']
if noinline:
verilator_hier_flags.extend(["+define+NO_INLINE"])
test.execute()
# Compile hierarchically
test.vm_prefix = "Vhier"
test.main_filename = test.obj_dir + "/Vhier__main.cpp"
test.compile(verilator_flags2=verilator_hier_flags)
test.saif_identical(test.trace_filename, test.golden_filename)
# Compile non hierarchically
test.vm_prefix = "Vnonh"
test.main_filename = test.obj_dir + "/Vnonh__main.cpp"
test.compile(verilator_flags2=verilator_common_flags)
trace_hier = test.trace_filename.replace("simx", "hier")
trace_nonh = test.trace_filename.replace("simx", "nonh")
# Run the hierarchical model
test.execute(executable=test.obj_dir + "/Vhier")
test.run(cmd=["mv", test.trace_filename, trace_hier])
# Run the non hierarchical model
test.execute(executable=test.obj_dir + "/Vnonh")
test.run(cmd=["mv", test.trace_filename, trace_nonh])
# The two models must match
test.saif_identical(trace_hier, trace_nonh)
# The hierarchical must match the reference
test.saif_identical(trace_hier, test.golden_filename.replace("_noinl", ""))
test.passes()

View File

@ -0,0 +1,17 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
import runpy
test.priority(30)
test.scenarios('vlt_all')
runpy.run_path("t/t_hier_block_trace_saif.py", globals())

File diff suppressed because it is too large Load Diff

View File

@ -4,31 +4,70 @@
# 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-FileCopyrightText: 2024 Wilson Snyder
# SPDX-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.priority(30)
import re
noinline = "noinl" in test.name
if not noinline:
test.priority(30)
test.scenarios('vlt_all')
test.top_filename = "t/t_hier_block.v"
# CI environment offers 2 VCPUs, 2 thread setting causes the following warning.
# %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads.
# So use 6 threads here though it's not optimal in performance, but ok.
verilator_common_flags = [
't/t_hier_block.cpp',
'--Wno-TIMESCALEMOD',
'--trace-vcd',
'--trace-underscore', # Should not trace handle
"--trace-max-width",
"0",
"--trace-max-array",
"0",
"--trace-structs",
]
test.compile(
v_flags2=['t/t_hier_block.cpp'],
verilator_flags2=[
'--hierarchical',
'--Wno-TIMESCALEMOD',
'--trace-vcd',
'--no-trace-underscore', # To avoid handle mismatches
],
threads=(6 if test.vltmt else 1))
verilator_hier_flags = verilator_common_flags + ['--hierarchical']
if noinline:
verilator_hier_flags.extend(["+define+NO_INLINE"])
test.execute()
# Compile hierarchically
test.vm_prefix = "Vhier"
test.main_filename = test.obj_dir + "/Vhier__main.cpp"
test.compile(verilator_flags2=verilator_hier_flags)
test.vcd_identical(test.trace_filename, test.golden_filename)
# Compile non hierarchically
test.vm_prefix = "Vnonh"
test.main_filename = test.obj_dir + "/Vnonh__main.cpp"
test.compile(verilator_flags2=verilator_common_flags)
trace_hier = test.trace_filename.replace("simx", "hier")
trace_nonh = test.trace_filename.replace("simx", "nonh")
# Run the hierarchical model
test.execute(executable=test.obj_dir + "/Vhier")
test.run(cmd=["mv", test.trace_filename, trace_hier])
# Run the non hierarchical model
test.execute(executable=test.obj_dir + "/Vnonh")
test.run(cmd=["mv", test.trace_filename, trace_nonh])
# Scope structure must match exactly
with open(trace_nonh, 'r', encoding='utf8') as fnonh, open(trace_hier, 'r',
encoding='utf8') as fhier:
for la, lb in zip(fnonh, fhier):
la = re.sub(r'^(\s*\$var\s+\S+\s+\S+\s+)\S+(.*)$', r'\1CODE\2', la)
lb = re.sub(r'^(\s*\$var\s+\S+\s+\S+\s+)\S+(.*)$', r'\1CODE\2', lb)
if la != lb:
test.error_keep_going("VCD header mismatch: '{}' !~ '{}'".format(
la.strip(), lb.strip()))
if "enddefinitions" in la:
break
# The two models must match
test.vcd_identical(trace_hier, trace_nonh)
# The hierarchical must match the reference
test.vcd_identical(trace_hier, test.golden_filename.replace("_noinl", ""))
test.passes()

View File

@ -0,0 +1,17 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
import runpy
test.priority(30)
test.scenarios('vlt_all')
runpy.run_path("t/t_hier_block_trace_vcd.py", globals())

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.priority(30)
test.scenarios('vlt_all')
test.top_filename = "t/t_hier_block.v"
test.compile(verilator_flags2=[
't/t_hier_block.cpp', '--Wno-TIMESCALEMOD', '--trace-vcd', '--trace-underscore',
"--trace-max-width", "0", "--trace-max-array", "0", "--trace-structs", "--hierarchical",
"+define+STATEFUL_PKG"
])
test.execute()
test.vcd_identical(test.trace_filename, test.golden_filename)
test.passes()

View File

@ -1,268 +1,124 @@
$version Generated by VerilatedVcd $end
$timescale 1ps $end
$scope module top $end
$var wire 1 # clk $end
$var wire 1 $ reset_l $end
$var wire 1 " clk $end
$var wire 1 # reset_l $end
$scope module t $end
$var wire 1 # clk $end
$var wire 1 $ reset_l $end
$var wire 1 " clk $end
$var wire 1 # reset_l $end
$scope module u0_sub_top $end
$var wire 1 # clk $end
$var wire 1 $ reset_l $end
$var wire 1 $ clk $end
$var wire 1 % reset_l $end
$scope module u0 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u1 $end
$var wire 1 ( clk $end
$var wire 1 ) reset_l $end
$upscope $end
$scope module u2 $end
$var wire 1 * clk $end
$var wire 1 + reset_l $end
$upscope $end
$scope module u3 $end
$var wire 1 , clk $end
$var wire 1 - reset_l $end
$upscope $end
$scope module u4 $end
$var wire 1 . clk $end
$var wire 1 / reset_l $end
$upscope $end
$scope module u5 $end
$var wire 1 0 clk $end
$var wire 1 1 reset_l $end
$upscope $end
$scope module u6 $end
$var wire 1 2 clk $end
$var wire 1 3 reset_l $end
$upscope $end
$scope module u7 $end
$var wire 1 4 clk $end
$var wire 1 5 reset_l $end
$upscope $end
$upscope $end
$scope module u1_sub_top $end
$var wire 1 # clk $end
$var wire 1 $ reset_l $end
$var wire 1 6 clk $end
$var wire 1 7 reset_l $end
$scope module u0 $end
$var wire 1 8 clk $end
$var wire 1 9 reset_l $end
$upscope $end
$scope module u1 $end
$var wire 1 : clk $end
$var wire 1 ; reset_l $end
$upscope $end
$scope module u2 $end
$var wire 1 < clk $end
$var wire 1 = reset_l $end
$upscope $end
$scope module u3 $end
$var wire 1 > clk $end
$var wire 1 ? reset_l $end
$upscope $end
$scope module u4 $end
$var wire 1 @ clk $end
$var wire 1 A reset_l $end
$upscope $end
$scope module u5 $end
$var wire 1 B clk $end
$var wire 1 C reset_l $end
$upscope $end
$scope module u6 $end
$var wire 1 D clk $end
$var wire 1 E reset_l $end
$upscope $end
$scope module u7 $end
$var wire 1 F clk $end
$var wire 1 G reset_l $end
$upscope $end
$upscope $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$scope module sub_top $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$scope module u0 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u1 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u2 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u3 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u4 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u5 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u6 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u7 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$scope module sub_top $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$scope module u0 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u1 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u2 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u3 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u4 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u5 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u6 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u7 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u0 $end
$var wire 1 , clk $end
$var wire 1 - reset_l $end
$scope module detail_code $end
$var wire 1 , clk $end
$var wire 1 - reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u1 $end
$var wire 1 / clk $end
$var wire 1 0 reset_l $end
$scope module detail_code $end
$var wire 1 / clk $end
$var wire 1 0 reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u2 $end
$var wire 1 2 clk $end
$var wire 1 3 reset_l $end
$scope module detail_code $end
$var wire 1 2 clk $end
$var wire 1 3 reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u3 $end
$var wire 1 5 clk $end
$var wire 1 6 reset_l $end
$scope module detail_code $end
$var wire 1 5 clk $end
$var wire 1 6 reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u4 $end
$var wire 1 8 clk $end
$var wire 1 9 reset_l $end
$scope module detail_code $end
$var wire 1 8 clk $end
$var wire 1 9 reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u5 $end
$var wire 1 ; clk $end
$var wire 1 < reset_l $end
$scope module detail_code $end
$var wire 1 ; clk $end
$var wire 1 < reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u6 $end
$var wire 1 > clk $end
$var wire 1 ? reset_l $end
$scope module detail_code $end
$var wire 1 > clk $end
$var wire 1 ? reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u7 $end
$var wire 1 A clk $end
$var wire 1 B reset_l $end
$scope module detail_code $end
$var wire 1 A clk $end
$var wire 1 B reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u0 $end
$var wire 1 D clk $end
$var wire 1 E reset_l $end
$scope module detail_code $end
$var wire 1 D clk $end
$var wire 1 E reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u1 $end
$var wire 1 G clk $end
$var wire 1 H reset_l $end
$scope module detail_code $end
$var wire 1 G clk $end
$var wire 1 H reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u2 $end
$var wire 1 J clk $end
$var wire 1 K reset_l $end
$scope module detail_code $end
$var wire 1 J clk $end
$var wire 1 K reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u3 $end
$var wire 1 M clk $end
$var wire 1 N reset_l $end
$scope module detail_code $end
$var wire 1 M clk $end
$var wire 1 N reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u4 $end
$var wire 1 P clk $end
$var wire 1 Q reset_l $end
$scope module detail_code $end
$var wire 1 P clk $end
$var wire 1 Q reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u5 $end
$var wire 1 S clk $end
$var wire 1 T reset_l $end
$scope module detail_code $end
$var wire 1 S clk $end
$var wire 1 T reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u6 $end
$var wire 1 V clk $end
$var wire 1 W reset_l $end
$scope module detail_code $end
$var wire 1 V clk $end
$var wire 1 W reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u7 $end
$var wire 1 Y clk $end
$var wire 1 Z reset_l $end
$scope module detail_code $end
$var wire 1 Y clk $end
$var wire 1 Z reset_l $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
0"
0#
0$
0%
06
07
0&
0'
0(
0)
0*
0+
0,
0-
0.
0/
00
01
02
03
04
05
06
08
09
0:
0;
0<
0=
0>
0?
0@
0A
0B
0C
0D
0E
0F
0G
0H
0J
0K
0M
0N
0P
0Q
0S
0T
0V
0W
0Y
0Z

View File

@ -1,268 +1,124 @@
$version Generated by VerilatedVcd $end
$timescale 1ps $end
$scope module top $end
$var wire 1 # clk $end
$var wire 1 $ reset_l $end
$var wire 1 " clk $end
$var wire 1 # reset_l $end
$scope module t $end
$var wire 1 # clk $end
$var wire 1 $ reset_l $end
$var wire 1 " clk $end
$var wire 1 # reset_l $end
$scope module u0_sub_top $end
$var wire 1 # clk $end
$var wire 1 $ reset_l $end
$var wire 1 $ clk $end
$var wire 1 % reset_l $end
$scope module u0 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u1 $end
$var wire 1 ( clk $end
$var wire 1 ) reset_l $end
$upscope $end
$scope module u2 $end
$var wire 1 * clk $end
$var wire 1 + reset_l $end
$upscope $end
$scope module u3 $end
$var wire 1 , clk $end
$var wire 1 - reset_l $end
$upscope $end
$scope module u4 $end
$var wire 1 . clk $end
$var wire 1 / reset_l $end
$upscope $end
$scope module u5 $end
$var wire 1 0 clk $end
$var wire 1 1 reset_l $end
$upscope $end
$scope module u6 $end
$var wire 1 2 clk $end
$var wire 1 3 reset_l $end
$upscope $end
$scope module u7 $end
$var wire 1 4 clk $end
$var wire 1 5 reset_l $end
$upscope $end
$upscope $end
$scope module u1_sub_top $end
$var wire 1 # clk $end
$var wire 1 $ reset_l $end
$var wire 1 6 clk $end
$var wire 1 7 reset_l $end
$scope module u0 $end
$var wire 1 8 clk $end
$var wire 1 9 reset_l $end
$upscope $end
$scope module u1 $end
$var wire 1 : clk $end
$var wire 1 ; reset_l $end
$upscope $end
$scope module u2 $end
$var wire 1 < clk $end
$var wire 1 = reset_l $end
$upscope $end
$scope module u3 $end
$var wire 1 > clk $end
$var wire 1 ? reset_l $end
$upscope $end
$scope module u4 $end
$var wire 1 @ clk $end
$var wire 1 A reset_l $end
$upscope $end
$scope module u5 $end
$var wire 1 B clk $end
$var wire 1 C reset_l $end
$upscope $end
$scope module u6 $end
$var wire 1 D clk $end
$var wire 1 E reset_l $end
$upscope $end
$scope module u7 $end
$var wire 1 F clk $end
$var wire 1 G reset_l $end
$upscope $end
$upscope $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$scope module sub_top $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$scope module u0 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u1 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u2 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u3 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u4 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u5 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u6 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$scope module u7 $end
$var wire 1 & clk $end
$var wire 1 ' reset_l $end
$upscope $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$scope module sub_top $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$scope module u0 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u1 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u2 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u3 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u4 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u5 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u6 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$scope module u7 $end
$var wire 1 ) clk $end
$var wire 1 * reset_l $end
$upscope $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u0 $end
$var wire 1 , clk $end
$var wire 1 - reset_l $end
$scope module detail_code $end
$var wire 1 , clk $end
$var wire 1 - reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u1 $end
$var wire 1 / clk $end
$var wire 1 0 reset_l $end
$scope module detail_code $end
$var wire 1 / clk $end
$var wire 1 0 reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u2 $end
$var wire 1 2 clk $end
$var wire 1 3 reset_l $end
$scope module detail_code $end
$var wire 1 2 clk $end
$var wire 1 3 reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u3 $end
$var wire 1 5 clk $end
$var wire 1 6 reset_l $end
$scope module detail_code $end
$var wire 1 5 clk $end
$var wire 1 6 reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u4 $end
$var wire 1 8 clk $end
$var wire 1 9 reset_l $end
$scope module detail_code $end
$var wire 1 8 clk $end
$var wire 1 9 reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u5 $end
$var wire 1 ; clk $end
$var wire 1 < reset_l $end
$scope module detail_code $end
$var wire 1 ; clk $end
$var wire 1 < reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u6 $end
$var wire 1 > clk $end
$var wire 1 ? reset_l $end
$scope module detail_code $end
$var wire 1 > clk $end
$var wire 1 ? reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u0_sub_top.sub_top.u7 $end
$var wire 1 A clk $end
$var wire 1 B reset_l $end
$scope module detail_code $end
$var wire 1 A clk $end
$var wire 1 B reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u0 $end
$var wire 1 D clk $end
$var wire 1 E reset_l $end
$scope module detail_code $end
$var wire 1 D clk $end
$var wire 1 E reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u1 $end
$var wire 1 G clk $end
$var wire 1 H reset_l $end
$scope module detail_code $end
$var wire 1 G clk $end
$var wire 1 H reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u2 $end
$var wire 1 J clk $end
$var wire 1 K reset_l $end
$scope module detail_code $end
$var wire 1 J clk $end
$var wire 1 K reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u3 $end
$var wire 1 M clk $end
$var wire 1 N reset_l $end
$scope module detail_code $end
$var wire 1 M clk $end
$var wire 1 N reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u4 $end
$var wire 1 P clk $end
$var wire 1 Q reset_l $end
$scope module detail_code $end
$var wire 1 P clk $end
$var wire 1 Q reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u5 $end
$var wire 1 S clk $end
$var wire 1 T reset_l $end
$scope module detail_code $end
$var wire 1 S clk $end
$var wire 1 T reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u6 $end
$var wire 1 V clk $end
$var wire 1 W reset_l $end
$scope module detail_code $end
$var wire 1 V clk $end
$var wire 1 W reset_l $end
$upscope $end
$upscope $end
$scope module top.t.u1_sub_top.sub_top.u7 $end
$var wire 1 Y clk $end
$var wire 1 Z reset_l $end
$scope module detail_code $end
$var wire 1 Y clk $end
$var wire 1 Z reset_l $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
0"
0#
0$
0%
06
07
0&
0'
0(
0)
0*
0+
0,
0-
0.
0/
00
01
02
03
04
05
06
08
09
0:
0;
0<
0=
0>
0?
0@
0A
0B
0C
0D
0E
0F
0G
0H
0J
0K
0M
0N
0P
0Q
0S
0T
0V
0W
0Y
0Z

View File

@ -3,4 +3,10 @@
| ^~~~
... For warning description see https://verilator.org/warn/IMPORTSTAR?v=latest
... Use "/* verilator lint_off IMPORTSTAR */" and lint_on around source to disable this message.
%Warning-UNUSEDPARAM: t/t_lint_importstar_bad.v:8:15: Parameter is not used: 'PAR'
: ... note: In instance 't'
8 | localparam PAR = 1;
| ^~~
... For warning description see https://verilator.org/warn/UNUSEDPARAM?v=latest
... Use "/* verilator lint_off UNUSEDPARAM */" and lint_on around source to disable this message.
%Error: Exiting due to