Merge 2e25ccec30 into 56ed47ee7c
This commit is contained in:
commit
507b0c2afa
|
|
@ -299,6 +299,7 @@ protected:
|
|||
private:
|
||||
std::vector<bool> m_sigs_enabledVec; // Staging for m_sigs_enabledp
|
||||
std::vector<CallbackRecord> m_initCbs; // Routines to initialize tracing
|
||||
std::vector<bool> m_initCbsCalled; // Init callbacks already run for this open
|
||||
std::vector<CallbackRecord> m_constCbs; // Routines to perform const dump
|
||||
std::vector<CallbackRecord> m_constOffloadCbs; // Routines to perform offloaded const dump
|
||||
std::vector<CallbackRecord> m_fullCbs; // Routines to perform full dump
|
||||
|
|
@ -312,6 +313,7 @@ private:
|
|||
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
|
||||
bool m_rootInit = true; // Whether the current init callback was reached from the root
|
||||
// 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)
|
||||
|
|
@ -328,6 +330,7 @@ private:
|
|||
// to access duck-typed functions to avoid a virtual function call.
|
||||
T_Trace* self() { return static_cast<T_Trace*>(this); }
|
||||
|
||||
void runInitCallback(size_t index, bool rootInit) VL_MT_UNSAFE;
|
||||
void runCallbacks(const std::vector<CallbackRecord>& cbVec);
|
||||
void runOffloadedCallbacks(const std::vector<CallbackRecord>& cbVec);
|
||||
|
||||
|
|
@ -449,6 +452,7 @@ public:
|
|||
//=========================================================================
|
||||
// Non-hot path internal interface to Verilator generated code
|
||||
|
||||
bool rootInit() const VL_MT_UNSAFE { return m_rootInit; }
|
||||
void addModel(VerilatedModel*) VL_MT_SAFE_EXCLUDES(m_mutex);
|
||||
void addInitCb(initCb_t cb, void* userp, const std::string& name, bool isLibInstance,
|
||||
uint32_t nTraceCodes) VL_MT_SAFE;
|
||||
|
|
|
|||
|
|
@ -301,6 +301,25 @@ VerilatedTrace<VL_SUB_T, VL_BUF_T>::~VerilatedTrace() {
|
|||
//=========================================================================
|
||||
// Internals available to format-specific implementations
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::runInitCallback(size_t index,
|
||||
bool rootInit) VL_MT_UNSAFE {
|
||||
if (m_initCbsCalled[index]) return;
|
||||
|
||||
const CallbackRecord& cbr = m_initCbs[index];
|
||||
const uint32_t baseCode = nextCode();
|
||||
m_nextCode += cbr.m_nTraceCodes;
|
||||
|
||||
void* const prevInitUserp = m_initUserp;
|
||||
const bool prevRootInit = m_rootInit;
|
||||
m_initUserp = cbr.m_userp;
|
||||
m_rootInit = rootInit;
|
||||
cbr.m_initCb(cbr.m_userp, self(), baseCode);
|
||||
m_initUserp = prevInitUserp;
|
||||
m_rootInit = prevRootInit;
|
||||
m_initCbsCalled[index] = true;
|
||||
}
|
||||
|
||||
template <>
|
||||
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::traceInit() VL_MT_UNSAFE {
|
||||
// Note: It is possible to re-open a trace file (VCD in particular),
|
||||
|
|
@ -311,18 +330,13 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::traceInit() VL_MT_UNSAFE {
|
|||
m_numSignals = 0;
|
||||
m_maxBits = 0;
|
||||
m_sigs_enabledVec.clear();
|
||||
m_initCbsCalled.assign(m_initCbs.size(), false);
|
||||
|
||||
// Call all initialize callbacks for root (non-library) instances, which will:
|
||||
// Call all initialize callbacks for root 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) {
|
||||
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);
|
||||
}
|
||||
for (size_t i = 0; i < m_initCbs.size(); ++i) runInitCallback(i, true);
|
||||
|
||||
if (expectedCodes && nextCode() != expectedCodes) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
|
|
@ -728,14 +742,9 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addCleanupCb(cleanupCb_t cb, void* user
|
|||
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;
|
||||
for (size_t i = 0; i < m_initCbs.size(); ++i) {
|
||||
if (m_initCbs[i].m_name != name) continue;
|
||||
runInitCallback(i, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1271,6 +1271,7 @@ class AstNetlist final : public AstNode {
|
|||
// @astgen ptr := m_stlFirstIterationp: Optional[AstVarScope] // Settle first iteration flag
|
||||
VTimescale m_timeunit; // Global time unit
|
||||
VTimescale m_timeprecision; // Global time precision
|
||||
std::string m_resolvedTopModuleName; // Selected design top before wrapping under $root
|
||||
bool m_timescaleSpecified = false; // Input HDL specified timescale
|
||||
uint32_t m_nTraceCodes = 0; // Number of trace codes used by design
|
||||
public:
|
||||
|
|
@ -1314,10 +1315,16 @@ public:
|
|||
void timeprecisionMerge(FileLine*, const VTimescale& value);
|
||||
void timescaleSpecified(bool specified) { m_timescaleSpecified = specified; }
|
||||
bool timescaleSpecified() const { return m_timescaleSpecified; }
|
||||
const std::string& resolvedTopModuleName() const { return m_resolvedTopModuleName; }
|
||||
void resolvedTopModuleName(const std::string& value) { m_resolvedTopModuleName = value; }
|
||||
uint32_t nTraceCodes() const { return m_nTraceCodes; }
|
||||
void nTraceCodes(uint32_t value) { m_nTraceCodes = value; }
|
||||
AstVarScope* stlFirstIterationp();
|
||||
void clearStlFirstIterationp() { m_stlFirstIterationp = nullptr; }
|
||||
const std::string traceLibTopName() const {
|
||||
const std::string& name = resolvedTopModuleName();
|
||||
return prettyName(name.empty() ? v3Global.rootp()->topModulep()->name() : name);
|
||||
}
|
||||
};
|
||||
class AstPackageExport final : public AstNode {
|
||||
// A package export declaration
|
||||
|
|
|
|||
|
|
@ -528,10 +528,17 @@ class EmitCModel final : public EmitCFunc {
|
|||
|
||||
void emitTraceMethods(AstNodeModule* modp) {
|
||||
const string topModNameProtected = EmitCUtil::prefixNameProtect(modp);
|
||||
const string topTraceName
|
||||
= V3OutFormatter::quoteNameControls(v3Global.rootp()->traceLibTopName());
|
||||
|
||||
putSectionDelimiter("Trace configuration");
|
||||
|
||||
// Forward declaration
|
||||
if (!v3Global.opt.libCreate().empty()) {
|
||||
putns(modp, "\nvoid " + topModNameProtected + "__" + protect("trace_init_root") + "("
|
||||
+ topModNameProtected + "* vlSelf, " + v3Global.opt.traceClassBase()
|
||||
+ "* tracep);\n");
|
||||
}
|
||||
putns(modp, "\nvoid " + topModNameProtected + "__" + protect("trace_decl_types") + "("
|
||||
+ v3Global.opt.traceClassBase() + "* tracep);\n");
|
||||
putns(modp, "\nvoid " + topModNameProtected + "__" + protect("trace_init_top") + "("
|
||||
|
|
@ -553,11 +560,23 @@ class EmitCModel final : public EmitCFunc {
|
|||
puts("vlSymsp->__Vm_baseCode = code;\n");
|
||||
if (v3Global.opt.libCreate().empty()) {
|
||||
puts("tracep->pushPrefix(vlSymsp->name(), VerilatedTracePrefixType::SCOPE_MODULE);\n");
|
||||
} else {
|
||||
puts("if (tracep->rootInit()) {\n");
|
||||
puts("tracep->pushPrefix(vlSymsp->name(), VerilatedTracePrefixType::SCOPE_MODULE);\n");
|
||||
puts(topModNameProtected + "__" + protect("trace_init_root") + "(vlSelf, tracep);\n");
|
||||
puts("tracep->pushPrefix(\"" + topTraceName
|
||||
+ "\", VerilatedTracePrefixType::SCOPE_MODULE);\n");
|
||||
puts("}\n");
|
||||
}
|
||||
puts(topModNameProtected + "__" + protect("trace_decl_types") + "(tracep);\n");
|
||||
puts(topModNameProtected + "__" + protect("trace_init_top") + "(vlSelf, tracep);\n");
|
||||
if (v3Global.opt.libCreate().empty()) { //
|
||||
puts("tracep->popPrefix();\n");
|
||||
} else {
|
||||
puts("if (tracep->rootInit()) {\n");
|
||||
puts("tracep->popPrefix();\n");
|
||||
puts("tracep->popPrefix();\n");
|
||||
puts("}\n");
|
||||
}
|
||||
puts("}\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -167,6 +167,7 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) {
|
|||
UINFO(1, "No module found to wrap");
|
||||
return;
|
||||
}
|
||||
rootp->resolvedTopModuleName(oldmodp->name());
|
||||
|
||||
AstNodeModule* const newmodp = new AstModule{oldmodp->fileline(), "$root", oldmodp->libname()};
|
||||
newmodp->name(AstNode::encodeName(newmodp->name())); // so origName is nice
|
||||
|
|
|
|||
|
|
@ -197,8 +197,38 @@ class TraceVisitor final : public VNVisitor {
|
|||
// For activity set, what traces apply
|
||||
using TraceVec = std::multimap<ActCodeSet, TraceTraceVertex*>;
|
||||
|
||||
class TraceInitDeclCollector final : public VNVisitor {
|
||||
std::vector<AstTraceDecl*>& m_declps;
|
||||
std::set<const AstCFunc*> m_seenFuncps;
|
||||
|
||||
void visit(AstTraceDecl* nodep) override { m_declps.push_back(nodep); }
|
||||
void visit(AstCCall* nodep) override {
|
||||
if (AstCFunc* const funcp = nodep->funcp()) collect(funcp);
|
||||
}
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
explicit TraceInitDeclCollector(std::vector<AstTraceDecl*>& declps)
|
||||
: m_declps{declps} {}
|
||||
void collect(AstCFunc* funcp) {
|
||||
if (funcp && m_seenFuncps.insert(funcp).second) iterate(funcp);
|
||||
}
|
||||
};
|
||||
|
||||
// METHODS
|
||||
|
||||
static bool sameRootInitAlias(const AstTraceDecl* rootDeclp, const AstTraceDecl* topDeclp) {
|
||||
const VNumRange& rootBitRange = rootDeclp->bitRange();
|
||||
const VNumRange& topBitRange = topDeclp->bitRange();
|
||||
return rootDeclp->showname() == topDeclp->showname()
|
||||
&& rootDeclp->declDirection() == topDeclp->declDirection()
|
||||
&& rootDeclp->widthMin() == topDeclp->widthMin()
|
||||
&& rootBitRange.ranged() == topBitRange.ranged()
|
||||
&& (!rootBitRange.ranged()
|
||||
|| (rootBitRange.left() == topBitRange.left()
|
||||
&& rootBitRange.right() == topBitRange.right()));
|
||||
}
|
||||
|
||||
void detectDuplicates() {
|
||||
UINFO(9, "Finding duplicates");
|
||||
// Note uses user4
|
||||
|
|
@ -800,6 +830,32 @@ class TraceVisitor final : public VNVisitor {
|
|||
// Create the full and incremental dump functions
|
||||
createNonConstTraceFunctions(traces, nNonConstCodes, m_parallelism);
|
||||
|
||||
// Root-traced libraries alias wrapper IOs onto the existing top-module codes.
|
||||
if (!v3Global.opt.libCreate().empty()) {
|
||||
std::vector<AstTraceDecl*> rootDeclps;
|
||||
std::vector<AstTraceDecl*> topDeclps;
|
||||
TraceInitDeclCollector rootCollector{rootDeclps};
|
||||
TraceInitDeclCollector topCollector{topDeclps};
|
||||
for (AstNode* blockp = m_topScopep->blocksp(); blockp; blockp = blockp->nextp()) {
|
||||
AstCFunc* const funcp = VN_CAST(blockp, CFunc);
|
||||
if (funcp && VString::startsWith(funcp->name(), "trace_init_leaf_root__")) {
|
||||
rootCollector.collect(funcp);
|
||||
} else if (funcp && VString::startsWith(funcp->name(), "trace_init_leaf_top__")) {
|
||||
topCollector.collect(funcp);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<bool> used(topDeclps.size(), false);
|
||||
for (AstTraceDecl* const rootDeclp : rootDeclps) {
|
||||
for (size_t i = 0; i < topDeclps.size(); ++i) {
|
||||
if (used[i] || !sameRootInitAlias(rootDeclp, topDeclps[i])) continue;
|
||||
rootDeclp->code(topDeclps[i]->code());
|
||||
used[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove refs to traced values from TraceDecl nodes, these have now moved under
|
||||
// TraceInc
|
||||
for (const auto& i : traces) {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,10 @@ public:
|
|||
|
||||
// Emit Prefix adjustments to unwind the path back to its original state
|
||||
void unwind() {
|
||||
for (unsigned toPop = m_stack.size(); --toPop;) m_emit(new AstTracePopPrefix{m_flp});
|
||||
while (m_stack.size() > 1) {
|
||||
m_emit(new AstTracePopPrefix{m_flp});
|
||||
m_stack.pop_back();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -103,6 +106,8 @@ class TraceDeclVisitor final : public VNVisitor {
|
|||
std::set<const AstTraceDecl*> m_declUncalledps; // Declarations not called
|
||||
int m_topFuncSize = 0; // Size of the top function currently being built
|
||||
int m_subFuncSize = 0; // Size of the sub function currently being built
|
||||
size_t m_topScopeRootFuncCount = 0; // Top-scope init functions used only for wrapper IOs
|
||||
bool m_topScopeRootPhase = false; // Emitting top-scope wrapper IO declarations
|
||||
const int m_funcSizeLimit // Maximum size of a function
|
||||
= v3Global.opt.outputSplitCTrace() ? v3Global.opt.outputSplitCTrace()
|
||||
: std::numeric_limits<int>::max();
|
||||
|
|
@ -148,21 +153,21 @@ class TraceDeclVisitor final : public VNVisitor {
|
|||
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.
|
||||
// When creating a --lib-create library, drop the name of the selected top module.
|
||||
// This will be replaced by the instance name in the model that uses the library, or
|
||||
// restored at runtime if the library itself is traced as the root model. Other top
|
||||
// level entities ($unit, packages, ...) keep a '$libroot' wrapper so they still have
|
||||
// a stable location in the dump.
|
||||
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);
|
||||
// Wrapper primary IOs stay under $rootio so a root-traced library can restore
|
||||
// them under the runtime C++ instance name without affecting embedded use.
|
||||
if (prefix == "$rootio") return;
|
||||
m_path = m_path.substr(start + 1);
|
||||
if (v3Global.opt.topModule() != prefix) m_path = "$libroot " + m_path;
|
||||
if (v3Global.rootp()->traceLibTopName() != prefix) m_path = "$libroot " + m_path;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -260,7 +265,11 @@ class TraceDeclVisitor final : public VNVisitor {
|
|||
//
|
||||
FileLine* const flp = m_currScopep->fileline();
|
||||
const string n = cvtToStr(m_subFuncps.size());
|
||||
const string name{"trace_init_sub__" + m_currScopep->nameDotless() + "__" + n};
|
||||
const string name
|
||||
= m_currScopep == m_topScopep->scopep() && !v3Global.opt.libCreate().empty()
|
||||
? (m_topScopeRootPhase ? "trace_init_leaf_root__" : "trace_init_leaf_top__")
|
||||
+ n
|
||||
: "trace_init_sub__" + m_currScopep->nameDotless() + "__" + n;
|
||||
AstCFunc* const funcp = newCFunc(flp, name);
|
||||
funcp->addStmtsp(new AstCStmt{flp, "const int c = vlSymsp->__Vm_baseCode;"});
|
||||
m_subFuncps.push_back(funcp);
|
||||
|
|
@ -429,10 +438,11 @@ class TraceDeclVisitor final : public VNVisitor {
|
|||
m_entries.begin(), m_entries.end(),
|
||||
[](const TraceEntry& a, const TraceEntry& b) { return a.operatorCompare(b); });
|
||||
|
||||
// Build trace initialization functions for this AstScope
|
||||
FileLine* const flp = nodep->fileline();
|
||||
PathAdjustor pathAdjustor{flp, [&](AstNodeStmt* stmtp) { addToSubFunc(stmtp); }};
|
||||
for (const TraceEntry& entry : m_entries) {
|
||||
const bool splitRootPrimaryIos = nodep->isTop() && !v3Global.opt.libCreate().empty();
|
||||
const auto emitEntry = [&](const TraceEntry& entry) {
|
||||
AstVarScope* const vscp = entry.vscp();
|
||||
// Adjust name prefix based on path in hierarchy
|
||||
UINFO(9, "path='" << entry.path() << "' name='" << entry.name() << "' "
|
||||
<< (entry.cellp() ? static_cast<AstNode*>(entry.cellp())
|
||||
|
|
@ -441,7 +451,7 @@ class TraceDeclVisitor final : public VNVisitor {
|
|||
|
||||
m_traName = entry.name();
|
||||
|
||||
if (AstVarScope* const vscp = entry.vscp()) {
|
||||
if (vscp) {
|
||||
// This is a signal: build AstTraceDecl for it
|
||||
m_traVscp = vscp;
|
||||
const string& ignoreReason = vscIgnoreTrace(m_traVscp);
|
||||
|
|
@ -472,6 +482,23 @@ class TraceDeclVisitor final : public VNVisitor {
|
|||
addToSubFunc(stmtp);
|
||||
m_cellInitPlaceholders.emplace_back(nodep, cellp, stmtp);
|
||||
}
|
||||
};
|
||||
if (splitRootPrimaryIos) {
|
||||
m_topScopeRootPhase = true;
|
||||
for (const TraceEntry& entry : m_entries) {
|
||||
AstVarScope* const vscp = entry.vscp();
|
||||
if (!(vscp && vscp->varp()->isPrimaryIO())) continue;
|
||||
emitEntry(entry);
|
||||
}
|
||||
m_topScopeRootPhase = false;
|
||||
pathAdjustor.unwind();
|
||||
m_topScopeRootFuncCount = m_subFuncps.size();
|
||||
if (m_topScopeRootFuncCount) m_subFuncSize = m_funcSizeLimit + 1;
|
||||
}
|
||||
for (const TraceEntry& entry : m_entries) {
|
||||
AstVarScope* const vscp = entry.vscp();
|
||||
if (splitRootPrimaryIos && vscp && vscp->varp()->isPrimaryIO()) continue;
|
||||
emitEntry(entry);
|
||||
}
|
||||
pathAdjustor.unwind();
|
||||
m_traVscp = nullptr;
|
||||
|
|
@ -532,8 +559,6 @@ class TraceDeclVisitor final : public VNVisitor {
|
|||
|
||||
// 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;
|
||||
}
|
||||
|
|
@ -764,8 +789,22 @@ public:
|
|||
// push/pop pairs is a bit hard. It is cleaner to remove them.
|
||||
removeRedundantPrefixPushPop();
|
||||
|
||||
// Call the initialization functions of the root scope from the top function
|
||||
for (AstCFunc* const funcp : m_scopeInitFuncps.at(m_topScopep->scopep())) {
|
||||
const std::vector<AstCFunc*>& topScopeFuncps = m_scopeInitFuncps.at(m_topScopep->scopep());
|
||||
AstCFunc* rootFuncp = nullptr;
|
||||
if (!v3Global.opt.libCreate().empty()) {
|
||||
rootFuncp = newCFunc(flp, "trace_init_root");
|
||||
for (size_t i = 0; i < m_topScopeRootFuncCount; ++i) {
|
||||
AstCCall* const callp = new AstCCall{flp, topScopeFuncps.at(i)};
|
||||
callp->dtypeSetVoid();
|
||||
callp->argTypes("tracep");
|
||||
rootFuncp->addStmtsp(callp->makeStmt());
|
||||
}
|
||||
if (!m_topScopeRootFuncCount) rootFuncp->addStmtsp(new AstComment{flp, "Empty"});
|
||||
}
|
||||
|
||||
// Call the non-wrapper initialization functions of the root scope from the top function
|
||||
for (size_t i = m_topScopeRootFuncCount; i < topScopeFuncps.size(); ++i) {
|
||||
AstCFunc* const funcp = topScopeFuncps.at(i);
|
||||
AstCCall* const callp = new AstCCall{flp, funcp};
|
||||
callp->dtypeSetVoid();
|
||||
callp->argTypes("tracep");
|
||||
|
|
@ -792,6 +831,7 @@ public:
|
|||
AstCFunc* const topFuncp = m_topFuncps.front();
|
||||
topFuncp->name("trace_init_top");
|
||||
|
||||
if (rootFuncp && v3Global.opt.debugCheck()) checkCallsRecurse(rootFuncp);
|
||||
checkCalls(topFuncp);
|
||||
}
|
||||
~TraceDeclVisitor() override {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
#include <verilated.h>
|
||||
|
||||
#include VM_PREFIX_INCLUDE
|
||||
|
||||
extern "C" int sim_main(int argc, char* argv[]) {
|
||||
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
|
||||
const std::unique_ptr<VM_PREFIX> topp{new VM_PREFIX{contextp.get(), "top"}};
|
||||
|
||||
contextp->debug(0);
|
||||
contextp->traceEverOn(true);
|
||||
contextp->commandArgs(argc, argv);
|
||||
|
||||
while (!contextp->gotFinish()) {
|
||||
topp->eval();
|
||||
topp->clk = !topp->clk;
|
||||
contextp->timeInc(1);
|
||||
}
|
||||
|
||||
topp->final();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) { return sim_main(argc, argv); }
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define STRINGIFY(x) `"x`"
|
||||
|
||||
module t(
|
||||
input clk
|
||||
);
|
||||
|
||||
int cyc = 1;
|
||||
|
||||
Factorial factorial(
|
||||
.clk(clk),
|
||||
.i(cyc)
|
||||
);
|
||||
|
||||
initial begin
|
||||
$dumpfile(`STRINGIFY(`TEST_DUMPFILE));
|
||||
$dumpvars;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
cyc <= cyc+1;
|
||||
if (cyc == 5) begin
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
module Factorial(
|
||||
input clk,
|
||||
input int i
|
||||
);
|
||||
int fact = 1;
|
||||
always @(posedge clk) begin
|
||||
fact <= fact * i;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
$date
|
||||
Thu Apr 2 18:53:18 2026
|
||||
|
||||
$end
|
||||
$version
|
||||
Generated by VerilatedFst
|
||||
$end
|
||||
$timescale
|
||||
1ps
|
||||
$end
|
||||
$scope module top $end
|
||||
$var wire 1 ! clk $end
|
||||
$scope module t $end
|
||||
$var wire 1 ! clk $end
|
||||
$var int 32 " cyc [31:0] $end
|
||||
$scope module factorial $end
|
||||
$var wire 1 ! clk $end
|
||||
$var wire 32 " i [31:0] $end
|
||||
$var int 32 # fact [31:0] $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$enddefinitions $end
|
||||
#0
|
||||
$dumpvars
|
||||
b00000000000000000000000000000001 #
|
||||
b00000000000000000000000000000001 "
|
||||
0!
|
||||
$end
|
||||
#1
|
||||
1!
|
||||
b00000000000000000000000000000010 "
|
||||
#2
|
||||
0!
|
||||
#3
|
||||
1!
|
||||
b00000000000000000000000000000011 "
|
||||
b00000000000000000000000000000010 #
|
||||
#4
|
||||
0!
|
||||
#5
|
||||
1!
|
||||
b00000000000000000000000000000110 #
|
||||
b00000000000000000000000000000100 "
|
||||
#6
|
||||
0!
|
||||
#7
|
||||
1!
|
||||
b00000000000000000000000000000101 "
|
||||
b00000000000000000000000000011000 #
|
||||
#8
|
||||
0!
|
||||
#9
|
||||
1!
|
||||
b00000000000000000000000001111000 #
|
||||
b00000000000000000000000000000110 "
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#!/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 trace_lib_as_top_common
|
||||
|
||||
test.scenarios('vlt_all')
|
||||
|
||||
trace_lib_as_top_common.run(test)
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
// Generated by verilated_saif
|
||||
(SAIFILE
|
||||
(SAIFVERSION "2.0")
|
||||
(DIRECTION "backward")
|
||||
(PROGRAM_NAME "Verilator")
|
||||
(DIVIDER / )
|
||||
(TIMESCALE 1ps)
|
||||
(DURATION 9)
|
||||
(INSTANCE top
|
||||
(NET
|
||||
(clk (T0 5) (T1 4) (TZ 0) (TX 0) (TB 0) (TC 9))
|
||||
)
|
||||
(INSTANCE t
|
||||
(NET
|
||||
(clk (T0 5) (T1 4) (TZ 0) (TX 0) (TB 0) (TC 9))
|
||||
(cyc\[0\] (T0 4) (T1 5) (TZ 0) (TX 0) (TB 0) (TC 6))
|
||||
(cyc\[1\] (T0 5) (T1 4) (TZ 0) (TX 0) (TB 0) (TC 3))
|
||||
(cyc\[2\] (T0 5) (T1 4) (TZ 0) (TX 0) (TB 0) (TC 1))
|
||||
(cyc\[3\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[4\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[5\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[6\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[7\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[8\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[9\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[10\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[11\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[12\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[13\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[14\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[15\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[16\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[17\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[18\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[19\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[20\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[21\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[22\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[23\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[24\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[25\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[26\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[27\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[28\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[29\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[30\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(cyc\[31\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
)
|
||||
(INSTANCE factorial
|
||||
(NET
|
||||
(clk (T0 5) (T1 4) (TZ 0) (TX 0) (TB 0) (TC 9))
|
||||
(i\[0\] (T0 4) (T1 5) (TZ 0) (TX 0) (TB 0) (TC 6))
|
||||
(i\[1\] (T0 5) (T1 4) (TZ 0) (TX 0) (TB 0) (TC 3))
|
||||
(i\[2\] (T0 5) (T1 4) (TZ 0) (TX 0) (TB 0) (TC 1))
|
||||
(i\[3\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[4\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[5\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[6\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[7\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[8\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[9\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[10\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[11\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[12\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[13\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[14\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[15\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[16\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[17\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[18\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[19\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[20\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[21\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[22\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[23\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[24\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[25\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[26\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[27\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[28\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[29\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[30\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(i\[31\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[0\] (T0 6) (T1 3) (TZ 0) (TX 0) (TB 0) (TC 2))
|
||||
(fact\[1\] (T0 5) (T1 4) (TZ 0) (TX 0) (TB 0) (TC 2))
|
||||
(fact\[2\] (T0 7) (T1 2) (TZ 0) (TX 0) (TB 0) (TC 2))
|
||||
(fact\[3\] (T0 7) (T1 2) (TZ 0) (TX 0) (TB 0) (TC 1))
|
||||
(fact\[4\] (T0 7) (T1 2) (TZ 0) (TX 0) (TB 0) (TC 1))
|
||||
(fact\[5\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 1))
|
||||
(fact\[6\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 1))
|
||||
(fact\[7\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[8\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[9\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[10\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[11\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[12\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[13\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[14\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[15\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[16\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[17\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[18\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[19\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[20\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[21\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[22\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[23\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[24\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[25\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[26\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[27\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[28\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[29\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[30\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
(fact\[31\] (T0 9) (T1 0) (TZ 0) (TX 0) (TB 0) (TC 0))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#!/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 trace_lib_as_top_common
|
||||
|
||||
test.scenarios('vlt_all')
|
||||
|
||||
trace_lib_as_top_common.run(test)
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
$version Generated by VerilatedVcd $end
|
||||
$timescale 1ps $end
|
||||
$scope module top $end
|
||||
$var wire 1 " clk $end
|
||||
$scope module t $end
|
||||
$var wire 1 " clk $end
|
||||
$var wire 32 # cyc [31:0] $end
|
||||
$scope module factorial $end
|
||||
$var wire 1 " clk $end
|
||||
$var wire 32 # i [31:0] $end
|
||||
$var wire 32 $ fact [31:0] $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$enddefinitions $end
|
||||
|
||||
|
||||
#0
|
||||
0"
|
||||
b00000000000000000000000000000001 #
|
||||
b00000000000000000000000000000001 $
|
||||
#1
|
||||
1"
|
||||
b00000000000000000000000000000010 #
|
||||
#2
|
||||
0"
|
||||
#3
|
||||
1"
|
||||
b00000000000000000000000000000011 #
|
||||
b00000000000000000000000000000010 $
|
||||
#4
|
||||
0"
|
||||
#5
|
||||
1"
|
||||
b00000000000000000000000000000100 #
|
||||
b00000000000000000000000000000110 $
|
||||
#6
|
||||
0"
|
||||
#7
|
||||
1"
|
||||
b00000000000000000000000000000101 #
|
||||
b00000000000000000000000000011000 $
|
||||
#8
|
||||
0"
|
||||
#9
|
||||
1"
|
||||
b00000000000000000000000000000110 #
|
||||
b00000000000000000000000001111000 $
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#!/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 trace_lib_as_top_common
|
||||
|
||||
test.scenarios('vlt_all')
|
||||
|
||||
trace_lib_as_top_common.run(test)
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
# 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 os
|
||||
import platform
|
||||
import sys
|
||||
|
||||
|
||||
def run(test, *, verilator_flags2=()):
|
||||
fmt, = test.parse_name(r"t_trace_lib_as_top_([a-z]+)")
|
||||
|
||||
if platform.system() == "Windows":
|
||||
test.skip("Skipping on Windows: test depends on Unix-style shared-library loading")
|
||||
|
||||
# All test use the same SV file
|
||||
test.top_filename = "t/t_trace_lib_as_top.v"
|
||||
test.pli_filename = os.path.abspath("t/t_trace_lib_as_top.cpp")
|
||||
# Any variations after the format name must yield the exact same trace
|
||||
test.golden_filename = test.py_filename.rpartition(fmt)[0] + fmt + ".out"
|
||||
|
||||
flags = [
|
||||
f"--trace-{fmt}",
|
||||
]
|
||||
flags.extend(verilator_flags2)
|
||||
|
||||
cflags = (f'-DVM_PREFIX={test.vm_prefix} '
|
||||
f"-DVM_PREFIX_INCLUDE='<{test.vm_prefix}.h>' ")
|
||||
|
||||
# Compile and run without lib-create
|
||||
test.compile(verilator_flags2=[test.pli_filename] + flags +
|
||||
["--exe", "--build", "-CFLAGS", f'"{cflags}"'])
|
||||
test.execute()
|
||||
|
||||
test.trace_identical(test.trace_filename, test.golden_filename)
|
||||
|
||||
# Compile and run with lib-create
|
||||
test.compile(verilator_flags2=[test.pli_filename] + flags +
|
||||
["--build", "--lib-create", "simulator", "-CFLAGS", f'"{cflags}"'])
|
||||
|
||||
# Load library and execute the simulation loop
|
||||
# This is to avoid linking manually so that the test is portable
|
||||
# Running in test.run() instead of directly to keep output in the test log
|
||||
libsim = f"./{test.obj_dir}/libsimulator.so"
|
||||
pycode = ("import ctypes;"
|
||||
f"lib=ctypes.CDLL({libsim!r});"
|
||||
"lib.sim_main(0, None)")
|
||||
test.run(cmd=[sys.executable, "-c", f'"{pycode}"'], logfile=test.run_log_filename)
|
||||
|
||||
test.trace_identical(test.trace_filename, test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
Loading…
Reference in New Issue