Support proper automatic/static initialization, and remove STATICVAR warning (#6405). (#7086)

This commit is contained in:
Wilson Snyder 2026-02-24 14:04:43 -05:00 committed by GitHub
parent 3992da6027
commit 7607f0e7fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 914 additions and 282 deletions

View File

@ -28,6 +28,7 @@ Verilator 5.045 devel
* Support nested interface as port connection (#5066) (#6986). [Leela Pakanati]
* Support solve..before constraints (#5647) (#7123). [Yilou Wang]
* Support structure initial values (#6130).
* Support proper automatic/static initialization, and remove STATICVAR warning (#6405).
* Support vpi_put/vpi_get forcing of signals (#5933) (#6704). [Christian Hecken]
* Support detailed failure info for constraint violations (#6617) (#6883). [Yilou Wang]
* Support `unique` constraints (on 1D static arrays) (#6810) (#6878). [Srinivasan Venkataramanan]

View File

@ -1982,13 +1982,10 @@ List Of Warnings
.. option:: STATICVAR
Warns that a static variable declared in a loop with declaration assignment
was converted to automatic. Often such variables were intended to
instead be declared "automatic".
Historical, never issued since version 5.046.
Ignoring this warning may make Verilator differ from other simulators,
which will treat the variable as static. Verilator may in future versions also
treat the variable as static.
Warned that a static variable was declared in a loop with declaration
assignment, and Verilator converted it to an "automatic".
.. option:: STMTDLY

View File

@ -756,6 +756,38 @@ public:
ASTGEN_MEMBERS_AstFireEvent;
bool isDelayed() const { return m_delayed; }
};
class AstInitialAutomaticStmt final : public AstNodeStmt {
// Automatic variable initialization in a statement position
// Used during early stages to record an initial initialization of a variable
// Moves later to an appropriate constructor, or AstInitialAutomatic, or
// AstCFunc normal statement
// Children: {statement list usually only with assignments}
// @astgen op1 := stmtsp : List[AstNode]
public:
AstInitialAutomaticStmt(FileLine* fl, AstNode* stmtsp)
: ASTGEN_SUPER_InitialAutomaticStmt(fl) {
addStmtsp(stmtsp);
}
ASTGEN_MEMBERS_AstInitialAutomaticStmt;
int instrCount() const override { return 0; }
bool isPure() override { return true; }
};
class AstInitialStaticStmt final : public AstNodeStmt {
// Static variable initialization in a statement position
// Used during early stages to record a static initialization of a variable
// Moves later to an appropriate constructor, or AstInitialStatic, or
// AstCFunc normal statement
// Children: {statement list usually only with assignments}
// @astgen op1 := stmtsp : List[AstNode]
public:
AstInitialStaticStmt(FileLine* fl, AstNode* stmtsp)
: ASTGEN_SUPER_InitialStaticStmt(fl) {
addStmtsp(stmtsp);
}
ASTGEN_MEMBERS_AstInitialStaticStmt;
int instrCount() const override { return 0; }
bool isPure() override { return true; }
};
class AstJumpBlock final : public AstNodeStmt {
// Block of code that might contain AstJumpGo statements as children,
// which when exectued branch to right after the referenced AstJumpBlock.

View File

@ -68,6 +68,7 @@ class BeginVisitor final : public VNVisitor {
// STATE - for current visit position (use VL_RESTORER)
AstNodeModule* m_modp = nullptr; // Current module
AstNodeFTask* m_ftaskp = nullptr; // Current function/task
AstNodeProcedure* m_procedurep = nullptr; // Current procedure
AstNode* m_liftedp = nullptr; // Local nodes we are lifting into m_ftaskp
string m_displayScope; // Name of %m in $display/AstScopeName
string m_namedScope; // Name of begin blocks above us
@ -120,17 +121,6 @@ class BeginVisitor final : public VNVisitor {
}
// VISITORS
void visit(AstFork* nodep) override {
dotNames(nodep->name(), nodep->fileline(), "__FORK__");
iterateAndNextNull(nodep->stmtsp());
{
// Keep begins in forks to group their statements together
VL_RESTORER(m_keepBegins);
m_keepBegins = true;
iterateAndNextNull(nodep->forksp());
}
nodep->name("");
}
void visit(AstForeach* nodep) override {
VL_DO_DANGLING(V3Begin::convertToWhile(nodep), nodep);
}
@ -158,6 +148,11 @@ class BeginVisitor final : public VNVisitor {
m_unnamedScope = "";
iterateChildren(nodep);
}
void visit(AstNodeProcedure* nodep) override {
VL_RESTORER(m_procedurep);
m_procedurep = nodep;
iterateChildren(nodep);
}
void visit(AstNodeFTask* nodep) override {
UINFO(8, " " << nodep);
// Rename it
@ -212,6 +207,27 @@ class BeginVisitor final : public VNVisitor {
}
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
}
void visit(AstFork* nodep) override {
dotNames(nodep->name(), nodep->fileline(), "__FORK__");
iterateAndNextNull(nodep->stmtsp());
{
// Keep begins in forks to group their statements together
VL_RESTORER(m_keepBegins);
m_keepBegins = true;
iterateAndNextNull(nodep->forksp());
}
AstNode* addsp = nullptr;
if (AstNode* const declsp = nodep->declsp()) {
declsp->unlinkFrBackWithNext();
addsp = AstNode::addNext(addsp, declsp);
}
if (AstNode* const stmtsp = nodep->stmtsp()) {
stmtsp->unlinkFrBackWithNext();
addsp = AstNode::addNext(addsp, stmtsp);
}
if (addsp) nodep->addHereThisAsNext(addsp);
nodep->name("");
}
void visit(AstBegin* nodep) override {
// Begin blocks were only useful in variable creation, change names and delete
UINFO(8, " " << nodep);
@ -246,6 +262,41 @@ class BeginVisitor final : public VNVisitor {
}
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
void visit(AstNodeBlock* nodep) override {
// Begin/Fork blocks were only useful in variable creation, change names and delete
UINFO(8, " " << nodep);
VL_RESTORER(m_displayScope);
VL_RESTORER(m_namedScope);
VL_RESTORER(m_unnamedScope);
{
VL_RESTORER(m_keepBegins);
m_keepBegins = VN_IS(nodep, Fork);
dotNames(nodep->name(), nodep->fileline(),
VN_IS(nodep, Fork) ? "__FORK__" : "__BEGIN__");
iterateChildren(nodep);
}
// Cleanup
if (m_keepBegins) {
nodep->name("");
return;
}
AstNode* addsp = nullptr;
if (AstNode* const declsp = nodep->declsp()) {
declsp->unlinkFrBackWithNext();
addsp = AstNode::addNext(addsp, declsp);
}
if (AstNode* const stmtsp = nodep->stmtsp()) {
stmtsp->unlinkFrBackWithNext();
addsp = AstNode::addNext(addsp, stmtsp);
}
if (addsp) {
nodep->replaceWith(addsp);
} else {
nodep->unlinkFrBack();
}
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
void visit(AstVar* nodep) override {
// If static variable, move it outside a function.
if (nodep->lifetime().isStatic() && m_ftaskp) {
@ -263,6 +314,28 @@ class BeginVisitor final : public VNVisitor {
liftNode(nodep);
}
}
void visit(AstInitialAutomaticStmt* nodep) override {
// Automatic sets go at the current location
nodep->replaceWith(nodep->stmtsp()->unlinkFrBackWithNext());
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
void visit(AstInitialStaticStmt* nodep) override {
// As we moved static variables, move static initializers too
if (nodep->user1SetOnce()) return; // Don't double-add text's
AstNode* wasUnderp = m_ftaskp;
if (!m_ftaskp) wasUnderp = m_procedurep;
if (wasUnderp) {
if (nodep->stmtsp()) {
AstNode* const newp = new AstInitialStatic{
nodep->fileline(), nodep->stmtsp()->unlinkFrBackWithNext()};
wasUnderp->addHereThisAsNext(newp);
iterateChildren(newp);
}
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
} else {
nodep->v3fatalSrc("InitialStaticStmt under unexpected grand-parent");
}
}
void visit(AstTypedef* nodep) override {
if (m_unnamedScope != "") {
// Rename it

View File

@ -3329,6 +3329,17 @@ class ConstVisitor final : public VNVisitor {
varrefp->varp()->valuep(initvaluep);
}
}
void visit(AstCReset* nodep) override {
iterateChildren(nodep);
if (!m_doNConst) return;
const AstBasicDType* const bdtypep = VN_CAST(nodep->dtypep()->skipRefp(), BasicDType);
if (!bdtypep) return;
if (!bdtypep->isZeroInit()) return;
AstConst* const newp = new AstConst{nodep->fileline(), V3Number{nodep, bdtypep}};
UINFO(9, "CRESET(0) => CONST(0) " << nodep);
nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
void visit(AstCvtArrayToArray* nodep) override {
iterateChildren(nodep);
// Handle the case where we have a stream operation inside a cast conversion

View File

@ -456,21 +456,22 @@ void EmitCFunc::emitCCallArgs(const AstNodeCCall* nodep, const string& selfPoint
puts(")");
}
void EmitCFunc::emitDereference(AstNode* nodep, const string& pointer) {
std::string EmitCFunc::dereferenceString(const std::string& pointer) {
if (pointer[0] == '(' && pointer[1] == '&') {
// remove "address of" followed by immediate dereference
// Note: this relies on only the form '(&OBJECT)' being used by Verilator
putns(nodep, pointer.substr(2, pointer.length() - 3));
puts(".");
return pointer.substr(2, pointer.length() - 3) + '.';
} else {
if (pointer == "vlSelf" && m_usevlSelfRef) {
puts("vlSelfRef.");
return "vlSelfRef.";
} else {
putns(nodep, pointer);
puts("->");
return pointer + "->";
}
}
}
void EmitCFunc::emitDereference(AstNode* nodep, const string& pointer) {
putns(nodep, dereferenceString(pointer));
}
void EmitCFunc::emitCvtPackStr(AstNode* nodep) {
if (const AstConst* const constp = VN_CAST(nodep, Const)) {
@ -527,13 +528,16 @@ void EmitCFunc::emitSetVarConstant(const string& assignString, AstConst* constp)
puts(";\n");
}
void EmitCFunc::emitVarReset(AstVar* varp, bool constructing) {
// 'constructing' indicates that the object was just constructed, so no need to clear it also
void EmitCFunc::emitVarReset(const string& prefix, AstVar* varp, bool constructing) {
// 'constructing' indicates that the object was just constructed, so if it is a string or
// something that starts off clear already, no need to clear it again
AstNodeDType* const dtypep = varp->dtypep()->skipRefp();
const string vlSelf = VSelfPointerText::replaceThis(m_useSelfForThis, "this->");
const string varNameProtected = (VN_IS(m_modp, Class) || varp->isFuncLocal())
? varp->nameProtect()
: vlSelf + varp->nameProtect();
const string varNameProtected
= ((VN_IS(m_modp, Class) || varp->isFuncLocal()) || !prefix.empty())
? varp->nameProtect()
: vlSelf + varp->nameProtect();
const string newPrefix = prefix + varNameProtected;
if (varp->isIO() && m_modp->isTop() && optSystemC()) {
// System C top I/O doesn't need loading, as the lower level subinst code does it.}
} else if (varp->isParam()) {
@ -546,47 +550,45 @@ void EmitCFunc::emitVarReset(AstVar* varp, bool constructing) {
// TODO merge this functionality with V3EmitCConstInit.h visitors
if (VN_IS(dtypep, AssocArrayDType)) {
if (initarp->defaultp()) {
emitSetVarConstant(varNameProtected + ".atDefault()",
VN_AS(initarp->defaultp(), Const));
emitSetVarConstant(newPrefix + ".atDefault()", VN_AS(initarp->defaultp(), Const));
}
if (!constructing) puts(varNameProtected + ".clear();");
const auto& mapr = initarp->map();
for (const auto& itr : mapr) {
AstNode* const valuep = itr.second->valuep();
emitSetVarConstant(varNameProtected + ".at(" + cvtToStr(itr.first) + ")",
emitSetVarConstant(newPrefix + ".at(" + cvtToStr(itr.first) + ")",
VN_AS(valuep, Const));
}
} else if (VN_IS(dtypep, WildcardArrayDType)) {
if (initarp->defaultp()) {
emitSetVarConstant(varNameProtected + ".atDefault()",
VN_AS(initarp->defaultp(), Const));
emitSetVarConstant(newPrefix + ".atDefault()", VN_AS(initarp->defaultp(), Const));
}
if (!constructing) puts(varNameProtected + ".clear();");
if (!constructing) puts(newPrefix + ".clear();");
const auto& mapr = initarp->map();
for (const auto& itr : mapr) {
AstNode* const valuep = itr.second->valuep();
emitSetVarConstant(varNameProtected + ".at(" + cvtToStr(itr.first) + ")",
emitSetVarConstant(newPrefix + ".at(" + cvtToStr(itr.first) + ")",
VN_AS(valuep, Const));
}
} else if (AstUnpackArrayDType* const adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
if (initarp->defaultp()) {
puts("for (int __Vi = 0; __Vi < " + cvtToStr(adtypep->elementsConst()));
puts("; ++__Vi) {\n");
emitSetVarConstant(varNameProtected + "[__Vi]", VN_AS(initarp->defaultp(), Const));
emitSetVarConstant(newPrefix + "[__Vi]", VN_AS(initarp->defaultp(), Const));
puts("}\n");
}
const auto& mapr = initarp->map();
for (const auto& itr : mapr) {
AstNode* const valuep = itr.second->valuep();
emitSetVarConstant(varNameProtected + "[" + cvtToStr(itr.first) + "]",
emitSetVarConstant(newPrefix + "[" + cvtToStr(itr.first) + "]",
VN_AS(valuep, Const));
}
} else {
varp->v3fatalSrc("InitArray under non-arrayed var");
}
} else {
putns(varp, emitVarResetRecurse(varp, constructing, varNameProtected, dtypep, 0, "",
varp->valuep()));
putns(varp,
emitVarResetRecurse(varp, constructing, newPrefix, dtypep, 0, "", varp->valuep()));
}
}

View File

@ -209,12 +209,13 @@ public:
AstNode* thsp);
void emitCCallArgs(const AstNodeCCall* nodep, const string& selfPointer, bool inProcess);
void emitDereference(AstNode* nodep, const string& pointer);
std::string dereferenceString(const std::string& pointer);
void emitCvtPackStr(AstNode* nodep);
void emitCvtWideArray(AstNode* nodep, AstNode* fromp);
void emitConstant(AstConst* nodep);
void emitConstantString(const AstConst* nodep);
void emitSetVarConstant(const string& assignString, AstConst* constp);
void emitVarReset(AstVar* varp, bool constructing);
void emitVarReset(const string& prefix, AstVar* varp, bool constructing);
string emitVarResetRecurse(const AstVar* varp, bool constructing,
const string& varNameProtected, AstNodeDType* dtypep, int depth,
const string& suffix, const AstNode* valuep);
@ -526,8 +527,29 @@ public:
void visit(AstNodeAssign* nodep) override {
if (AstCReset* const resetp = VN_CAST(nodep->rhsp(), CReset)) {
AstVar* const varp = VN_AS(nodep->lhsp(), NodeVarRef)->varp();
emitVarReset(varp, resetp->constructing());
// TODO get rid of emitVarReset and instead let AstNodeAssign understand how to init
// anything
AstNode* fromp = nodep->lhsp();
// Fork needs to use a member select. Nothing else should be possible before VarRef.
if (AstMemberSel* const sfromp = VN_CAST(fromp, MemberSel)) {
// Fork-DynScope generated pointer to previously automatic variable
AstVar* const memberVarp = sfromp->varp();
fromp = sfromp->fromp();
if (AstNullCheck* const sfromp = VN_CAST(fromp, NullCheck)) fromp = sfromp->lhsp();
AstNodeVarRef* const fromVarRefp = VN_AS(fromp, NodeVarRef);
emitVarReset(
("VL_NULL_CHECK("s
+ (fromVarRefp->selfPointer().isEmpty()
? ""
: dereferenceString(fromVarRefp->selfPointerProtect(m_useSelfForThis)))
+ fromVarRefp->varp()->nameProtect() + ", \""
+ V3OutFormatter::quoteNameControls(protect(nodep->fileline()->filename()))
+ "\", " + std::to_string(nodep->fileline()->lineno()) + ")->"),
memberVarp, resetp->constructing());
} else {
AstVar* const varp = VN_AS(fromp, NodeVarRef)->varp();
emitVarReset("", varp, resetp->constructing());
}
return;
}
bool paren = true;

View File

@ -182,6 +182,8 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
}
void visit(AstInitialAutomatic* nodep) override { iterateChildrenConst(nodep); }
void visit(AstInitialStatic* nodep) override { iterateChildrenConst(nodep); }
void visit(AstInitialAutomaticStmt* nodep) override { iterateChildrenConst(nodep); }
void visit(AstInitialStaticStmt* nodep) override { iterateChildrenConst(nodep); }
void visit(AstAlways* nodep) override {
if (const AstAssignW* const ap = VN_CAST(nodep->stmtsp(), AssignW)) {
if (!ap->nextp()) {

View File

@ -335,13 +335,31 @@ class DynScopeVisitor final : public VNVisitor {
auto r = m_frames.emplace(nodep, framep);
if (r.second) m_frameOrder.push_back(nodep);
}
void bindInitIterate(AstNode* stmtsp, ForkDynScopeFrame* framep) {
for (AstNode* stmtp = stmtsp; stmtp; stmtp = stmtp->nextp()) {
if (AstAssign* const asgnp = VN_CAST(stmtp, Assign)) {
bindNodeToDynScope(asgnp->lhsp(), framep);
iterate(asgnp->rhsp());
} else if (AstInitialAutomaticStmt* astmtp
= VN_CAST(stmtp, InitialAutomaticStmt)) { // Moves in V3Begin
// Underlying assign RHS might use function argument, so can't just
// move whole thing into the new class's constructor/statements
bindInitIterate(astmtp->stmtsp(), framep);
} else if (AstInitialStaticStmt* astmtp
= VN_CAST(stmtp, InitialStaticStmt)) { // Moves in V3Begin
bindInitIterate(astmtp->stmtsp(), framep);
} else {
stmtp->v3fatalSrc("Invalid node under block item initialization part of fork");
}
}
}
bool needsDynScope(const AstVarRef* refp) const {
const AstVar* const varp = refp->varp();
const bool localLifetime = varp->isFuncLocal() || varp->lifetime().isAutomatic();
return
// Can this variable escape the scope
((m_forkDepth > varp->user1()) && localLifetime)
((m_forkDepth > varp->user1()) && varp->isFuncLocal())
&& varp->lifetime().isAutomatic()
&& (
// Is it mutated
(varp->isClassHandleValue() ? refp->user2() : refp->access().isWriteOrRW())
@ -384,18 +402,14 @@ class DynScopeVisitor final : public VNVisitor {
for (AstNode* declp = nodep->declsp(); declp; declp = declp->nextp()) {
AstVar* const varp = VN_CAST(declp, Var);
UASSERT_OBJ(varp, declp, "Invalid node under block item initialization part of fork");
if (!framep->instance().initialized()) framep->createInstancePrototype();
framep->captureVarInsert(varp);
bindNodeToDynScope(varp, framep);
}
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (AstAssign* const asgnp = VN_CAST(stmtp, Assign)) {
bindNodeToDynScope(asgnp->lhsp(), framep);
iterate(asgnp->rhsp());
} else {
stmtp->v3fatalSrc("Invalid node under block item initialization part of fork");
UASSERT_OBJ(!varp->lifetime().isNone(), nodep, "Variable's lifetime is unknown");
if (varp->lifetime().isAutomatic()) { // else V3Begin will move later
if (!framep->instance().initialized()) framep->createInstancePrototype();
framep->captureVarInsert(varp);
bindNodeToDynScope(varp, framep);
}
}
bindInitIterate(nodep->stmtsp(), framep);
for (AstNode* stmtp = nodep->forksp(); stmtp; stmtp = stmtp->nextp()) {
m_afterTimingControl = false;
@ -526,6 +540,7 @@ class ForkVisitor final : public VNVisitor {
// STATE - for current AstFork item
bool m_inFork = false; // Traversal in an async fork
bool m_inInitStmt = false; // Traversal in InitialStaticStmt/InitialAutomaticStmt
std::set<AstVar*> m_forkLocalsp; // Variables local to a given fork
AstVar* m_capturedVarsp = nullptr; // Local copies of captured variables
AstArg* m_capturedArgsp = nullptr; // References to captured variables (as args)
@ -650,7 +665,8 @@ class ForkVisitor final : public VNVisitor {
// If this ref is to a variable that will move into the task, then nothing to do
if (m_forkLocalsp.count(varp)) return;
if (nodep->access().isWriteOrRW() && (!nodep->isClassHandleValue() || nodep->user2())) {
if (nodep->access().isWriteOrRW() && (!nodep->isClassHandleValue() || nodep->user2())
&& !m_inInitStmt) {
nodep->v3warn(
E_LIFETIME,
"Invalid reference: Process might outlive variable "
@ -671,6 +687,17 @@ class ForkVisitor final : public VNVisitor {
}
iterateChildren(nodep);
}
void visit(AstInitialAutomaticStmt* nodep) override {
VL_RESTORER(m_inInitStmt);
m_inInitStmt = true;
iterateChildren(nodep);
}
void visit(AstInitialStaticStmt* nodep) override {
VL_RESTORER(m_inInitStmt);
m_inInitStmt = true;
iterateChildren(nodep);
}
void visit(AstThisRef* nodep) override {}
void visit(AstNode* nodep) override { iterateChildren(nodep); }

View File

@ -456,6 +456,13 @@ class GateOkVisitor final : public VNVisitorConst {
clearSimple("Not a buffer (goes to a clock)");
}
}
void visit(AstCReset* nodep) override {
if (!m_isSimple) return;
// CReset is pure because we can optimize assignments, but if is
// the only assignment to a variable we still need to initial
// assign to get randomization etc
clearSimple("CReset");
}
//--------------------
void visit(AstNode* nodep) override {
if (!m_isSimple) return; // Fastpath

View File

@ -39,6 +39,7 @@ class LinkLValueVisitor final : public VNVisitor {
bool m_setStrengthSpecified = false; // Set that var has assignment with strength specified.
bool m_inFunc = false; // Set if inside AstNodeFTask
bool m_inInitialStatic = false; // Set if inside AstInitialStatic
bool m_inInitialStaticStmt = false; // Set if inside AstInitialStaticStmt
VAccess m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
// VISITORS
@ -113,7 +114,7 @@ class LinkLValueVisitor final : public VNVisitor {
iterateAndNextNull(nodep->rhsp());
}
if (m_inInitialStatic && m_inFunc) {
if ((m_inInitialStatic || m_inInitialStaticStmt) && m_inFunc) {
const bool rhsHasIO = nodep->rhsp()->exists([](const AstNodeVarRef* const refp) {
// Exclude module I/O referenced from a function/task.
return refp->varp() && refp->varp()->isIO()
@ -147,6 +148,11 @@ class LinkLValueVisitor final : public VNVisitor {
m_inInitialStatic = true;
iterateChildren(nodep);
}
void visit(AstInitialStaticStmt* nodep) override {
VL_RESTORER(m_inInitialStaticStmt);
m_inInitialStaticStmt = true;
iterateChildren(nodep);
}
void visit(AstRelease* nodep) override {
VL_RESTORER(m_setRefLvalue);
VL_RESTORER(m_setContinuously);

View File

@ -57,6 +57,8 @@ class LinkParseVisitor final : public VNVisitor {
AstNodeProcedure* m_procedurep = nullptr; // Current procedure
AstNodeFTask* m_ftaskp = nullptr; // Current task
AstNodeBlock* m_blockp = nullptr; // Current AstNodeBlock
AstNodeStmt* m_blockAddAutomaticStmtp = nullptr; // Initial statements to add to block
AstNodeStmt* m_blockAddStaticStmtp = nullptr; // Initial statements to add to block
AstNodeDType* m_dtypep = nullptr; // Current data type
AstNodeExpr* m_defaultInSkewp = nullptr; // Current default input skew
AstNodeExpr* m_defaultOutSkewp = nullptr; // Current default output skew
@ -66,9 +68,9 @@ class LinkParseVisitor final : public VNVisitor {
int m_beginDepth = 0; // How many begin blocks above current node within current AstNodeModule
int m_randSequenceNum = 0; // RandSequence uniqify number
VLifetime m_lifetime = VLifetime::STATIC_IMPLICIT; // Propagating lifetime
bool m_insideLoop = false; // True if the node is inside a loop
bool m_lifetimeAllowed = false; // True to allow lifetime settings
bool m_moduleWithGenericIface = false; // If current module contains generic interface
std::set<AstVar*> m_portDups; // Non-ANSI port datatype duplicating input/output decls
// STATE - Statistic tracking
VDouble0 m_statModules; // Number of modules seen
@ -181,6 +183,54 @@ class LinkParseVisitor final : public VNVisitor {
<< nodep->warnContextSecondary());
}
void collectPorts(AstNode* nodeListp) {
// V3LinkDot hasn't run yet, so have VAR for pre-IEEE 'input' and
// separate var for pre-IEEE 'integer'.
std::unordered_map<std::string, AstVar*> portNames;
for (AstNode* nodep = nodeListp; nodep; nodep = nodep->nextp()) {
if (AstVar* const varp = VN_CAST(nodep, Var)) {
if (varp->isIO()) portNames.emplace(varp->name(), varp);
}
}
for (AstNode* nodep = nodeListp; nodep; nodep = nodep->nextp()) {
if (AstVar* const varp = VN_CAST(nodep, Var)) {
if (varp->isIO()) continue;
const auto it = portNames.find(varp->name());
if (it == portNames.end()) continue;
AstVar* const iop = it->second;
UINFO(9, "Non-ANSI port dtype declaration " << varp);
if (!iop->valuep() && varp->valuep())
iop->valuep(varp->valuep()->unlinkFrBackWithNext());
m_portDups.emplace(varp);
}
}
}
AstNode* getVarsAndUnlink(AstNode* stmtsp) {
AstNode* varsp = nullptr;
for (AstNode *nextp, *itemp = stmtsp; itemp; itemp = nextp) {
nextp = itemp->nextp();
if (VN_IS(itemp, Var)) varsp = AstNode::addNext(varsp, itemp->unlinkFrBack());
}
return varsp;
}
AstNodeStmt* getBlockAdds() {
AstNodeStmt* addsp = nullptr;
// Add a single AstInitial...Stmt as the statements within may
// depend on each other, e.g. "var a=1; var b=a;" (but must be a constant expression)
if (m_blockAddStaticStmtp)
addsp = AstNode::addNext(addsp,
new AstInitialStaticStmt{m_blockAddStaticStmtp->fileline(),
m_blockAddStaticStmtp});
if (m_blockAddAutomaticStmtp)
addsp = AstNode::addNext(
addsp, new AstInitialAutomaticStmt{m_blockAddAutomaticStmtp->fileline(),
m_blockAddAutomaticStmtp});
m_blockAddStaticStmtp = nullptr;
m_blockAddAutomaticStmtp = nullptr;
return addsp;
}
// VISITORS
void visit(AstNodeFTask* nodep) override {
if (nodep->user1SetOnce()) return; // Process only once.
@ -191,6 +241,10 @@ class LinkParseVisitor final : public VNVisitor {
cleanFileline(nodep);
VL_RESTORER(m_ftaskp);
m_ftaskp = nodep;
VL_RESTORER(m_blockAddAutomaticStmtp);
m_blockAddAutomaticStmtp = nullptr;
VL_RESTORER(m_blockAddStaticStmtp);
m_blockAddStaticStmtp = nullptr;
VL_RESTORER(m_lifetime);
VL_RESTORER(m_lifetimeAllowed);
m_lifetimeAllowed = true;
@ -212,7 +266,26 @@ class LinkParseVisitor final : public VNVisitor {
<< nodep->warnMore() << "... May have intended 'static "
<< nodep->verilogKwd() << "'");
}
VL_RESTORER(m_portDups);
collectPorts(nodep->stmtsp());
iterateChildren(nodep);
// If let, the statement must go first
AstNode* stmtsp = nullptr;
if (VN_IS(nodep, Let) && nodep->stmtsp()) stmtsp = nodep->stmtsp()->unlinkFrBack();
// Move all Vars to front of function
stmtsp = AstNode::addNextNull(stmtsp, getVarsAndUnlink(nodep->stmtsp()));
// Follow vars by m_blockAddp's (if any)
stmtsp = AstNode::addNextNull(stmtsp, getBlockAdds());
if (stmtsp) {
if (nodep->stmtsp()) {
nodep->stmtsp()->addHereThisAsNext(stmtsp);
} else {
nodep->addStmtsp(stmtsp);
}
}
}
void visit(AstNodeDType* nodep) override { visitIterateNodeDType(nodep); }
void visit(AstConstraint* nodep) override {
@ -267,19 +340,13 @@ class LinkParseVisitor final : public VNVisitor {
cleanFileline(nodep);
UINFO(9, "VAR " << nodep);
if (nodep->valuep()) nodep->hasUserInit(true);
if (m_insideLoop && nodep->lifetime().isNone() && nodep->varType() == VVarType::VAR
&& !nodep->direction().isAny()) {
nodep->lifetime(VLifetime::AUTOMATIC_IMPLICIT);
}
if (nodep->lifetime().isStatic() && m_insideLoop && nodep->valuep()) {
nodep->lifetime(VLifetime::AUTOMATIC_IMPLICIT);
nodep->v3warn(STATICVAR, "Static variable with assignment declaration declared in a "
"loop converted to automatic");
} else if (nodep->valuep() && nodep->lifetime().isNone() && m_lifetime.isStatic()
&& !nodep->isIO()
&& !nodep->isParam()
// In task, or a procedure but not Initial/Final as executed only once
&& ((m_ftaskp && !m_ftaskp->lifetime().isStaticExplicit()) || m_procedurep)) {
// IEEE 1800-2026 6.21: for loop variables are automatic. verilog.y is
// responsible for marking those.
if (nodep->valuep() && nodep->lifetime().isNone() && m_lifetime.isStatic()
&& !nodep->isIO()
&& !nodep->isParam()
// In task, or a procedure but not Initial/Final as executed only once
&& ((m_ftaskp && !m_ftaskp->lifetime().isStaticExplicit()) || m_procedurep)) {
if (VN_IS(m_modp, Module) && m_ftaskp) {
m_ftaskp->v3warn(
IMPLICITSTATIC,
@ -415,43 +482,75 @@ class LinkParseVisitor final : public VNVisitor {
// temporaries under an always aren't expected to be blocking
if (m_procedurep && VN_IS(m_procedurep, Always))
nodep->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
if (nodep->valuep()) {
FileLine* const fl = nodep->valuep()->fileline();
// A variable with an = value can be 4 things:
if (nodep->isParam() || (m_ftaskp && nodep->isNonOutput())) {
// Compute initial value
if (nodep->valuep() || nodep->needsCReset()) {
FileLine* const fl = nodep->valuep() ? nodep->valuep()->fileline() : nodep->fileline();
auto createValuep = [&]() -> AstNodeExpr* {
if (nodep->valuep()) {
return VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr);
} else {
return new AstCReset{fl, nodep, false};
}
};
// A variable can be in these positions related to having an initial value (or not):
if (m_portDups.find(nodep) != m_portDups.end()) {
// 0. Non-ANSI type declaration that is really a port, but we haven't resolved yet
// Earlier moved any valuep() under the duplicate to the IO declaration
UINFO(9, "VarInit case0 " << nodep);
} else if (nodep->isParam() || nodep->isGenVar()
|| (m_ftaskp && (nodep->isNonOutput() || nodep->isFuncReturn()))) {
// 1. Parameters and function inputs: It's a default to use if not overridden
UINFO(9, "VarInit case1 " << nodep);
} else if (!m_ftaskp && !VN_IS(m_modp, Class) && nodep->isNonOutput()
&& !nodep->isInput()) {
// 2. Module inout/ref/constref: const default to use
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: Default value on module inout/ref/constref: "
<< nodep->prettyNameQ());
nodep->valuep()->unlinkFrBack()->deleteTree();
} else if (m_blockp) {
UINFO(9, "VarInit case2 " << nodep);
if (nodep->valuep()) {
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: Default value on module inout/ref/constref: "
<< nodep->prettyNameQ());
nodep->valuep()->unlinkFrBack()->deleteTree();
}
} else if (m_blockp || m_ftaskp) {
// 3. Under blocks, it's an initial value to be under an assign
// TODO: This is wrong if it's a static variable right?
UINFO(9, "VarInit case3 " << nodep);
nodep->noCReset(true);
FileLine* const newfl = new FileLine{fl};
newfl->warnOff(V3ErrorCode::E_CONSTWRITTEN, true);
m_blockp->addStmtsp(
new AstAssign{newfl, new AstVarRef{newfl, nodep, VAccess::WRITE},
VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr)});
AstAssign* const assp
= new AstAssign{newfl, new AstParseRef{newfl, nodep->name()}, createValuep()};
if (nodep->lifetime().isAutomatic()) {
// May later make: new AstInitialAutomaticStmt{newfl, assp};
m_blockAddAutomaticStmtp = AstNode::addNext(m_blockAddAutomaticStmtp, assp);
} else {
// May later make: new AstInitialStaticStmt{newfl, assp};
m_blockAddStaticStmtp = AstNode::addNext(m_blockAddStaticStmtp, assp);
}
} else if (m_valueModp) {
// 4. Under modules/class, it's the time 0 initialziation value
// Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it
FileLine* const newfl = new FileLine{fl};
newfl->warnOff(V3ErrorCode::PROCASSWIRE, true);
newfl->warnOff(V3ErrorCode::E_CONSTWRITTEN, true);
// Create a ParseRef to the wire. We cannot use the var as it may be deleted if
// it's a port (see t_var_set_link.v)
AstAssign* const assp
= new AstAssign{newfl, new AstParseRef{newfl, nodep->name()},
VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr)};
if (nodep->lifetime().isAutomatic()) {
nodep->addNextHere(new AstInitialAutomatic{newfl, assp});
} else {
nodep->addNextHere(new AstInitialStatic{newfl, assp});
UINFO(9, "VarInit case4 " << nodep);
if (nodep->valuep()) {
nodep->noCReset(true);
FileLine* const newfl = new FileLine{fl};
newfl->warnOff(V3ErrorCode::PROCASSWIRE, true);
newfl->warnOff(V3ErrorCode::E_CONSTWRITTEN, true);
// Create a ParseRef to the wire. We cannot use the var as it may be deleted if
// it's a port (see t_var_set_link.v)
AstAssign* const assp = new AstAssign{
newfl, new AstParseRef{newfl, nodep->name()}, createValuep()};
AstNode* newInitp;
// Must make a unique InitialAutomatic/Static for each
// variable or otherwise V3Gate will assume ordering
// within, and not properly optimize.
if (nodep->lifetime().isAutomatic()) {
newInitp = new AstInitialAutomatic{newfl, assp};
} else {
newInitp = new AstInitialStatic{newfl, assp};
}
nodep->addNextHere(newInitp);
}
} else {
} else if (nodep->valuep()) {
nodep->v3fatalSrc("Variable with initializer in unexpected position");
}
}
@ -592,8 +691,6 @@ class LinkParseVisitor final : public VNVisitor {
// 2. ASTSELBIT(first, var0))
// 3. ASTSELLOOPVARS(first, var0..var1))
// 4. DOT(DOT(first, second), ASTSELBIT(third, var0))
VL_RESTORER(m_insideLoop);
m_insideLoop = true;
AstForeachHeader* const headerp = nodep->headerp();
if (!headerp->elementsp()) {
nodep->v3error("Foreach missing bracketed loop variable is no-operation"
@ -605,15 +702,11 @@ class LinkParseVisitor final : public VNVisitor {
}
void visit(AstRepeat* nodep) override {
cleanFileline(nodep);
VL_RESTORER(m_insideLoop);
m_insideLoop = true;
checkIndent(nodep, nodep->stmtsp());
iterateChildren(nodep);
}
void visit(AstLoop* nodep) override {
cleanFileline(nodep);
VL_RESTORER(m_insideLoop);
m_insideLoop = true;
if (VN_IS(nodep->stmtsp(), LoopTest)) {
checkIndent(nodep, nodep->stmtsp()->nextp());
} else {
@ -680,6 +773,10 @@ class LinkParseVisitor final : public VNVisitor {
nodep->v3warn(E_UNSUPPORTED, "Module cannot be named 'TOP' as conflicts with "
"Verilator top-level internals");
}
VL_RESTORER(m_portDups);
collectPorts(nodep->stmtsp());
iterateChildren(nodep);
if (AstModule* const modp = VN_CAST(nodep, Module)) {
modp->hasGenericIface(m_moduleWithGenericIface);
@ -781,14 +878,14 @@ class LinkParseVisitor final : public VNVisitor {
iterateChildren(nodep);
}
void visit(AstNodeBlock* nodep) override {
VL_RESTORER(m_blockAddAutomaticStmtp);
m_blockAddAutomaticStmtp = nullptr;
VL_RESTORER(m_blockAddStaticStmtp);
m_blockAddStaticStmtp = nullptr;
{
VL_RESTORER(m_blockp);
m_blockp = nodep;
// Temporarily unlink the statements so variable initializers can be inserted in order
AstNode* const stmtsp = nodep->stmtsp();
if (stmtsp) stmtsp->unlinkFrBackWithNext();
iterateAndNextNull(nodep->declsp());
nodep->addStmtsp(stmtsp);
}
if (AstBegin* const beginp = VN_CAST(nodep, Begin)) {
@ -797,6 +894,20 @@ class LinkParseVisitor final : public VNVisitor {
cleanFileline(nodep);
iterateAndNextNull(nodep->stmtsp());
if (AstFork* const forkp = VN_CAST(nodep, Fork)) iterateAndNextNull(forkp->forksp());
// Add statements created by AstVar vistor; can't do as-go because iteration
// would then get confused, additionally we did already iterate the contents
AstNode* stmtsp = nullptr;
// Move all Vars to front of function
stmtsp = AstNode::addNextNull(stmtsp, getVarsAndUnlink(nodep->stmtsp()));
// Follow vars by m_blockAddp's (if any)
stmtsp = AstNode::addNextNull(stmtsp, getBlockAdds());
if (stmtsp) {
if (nodep->stmtsp()) {
nodep->stmtsp()->addHereThisAsNext(stmtsp);
} else {
nodep->addStmtsp(stmtsp);
}
}
}
void visit(AstCase* nodep) override {
V3Control::applyCase(nodep);

View File

@ -574,6 +574,14 @@ private:
checkNodeInfo(nodep);
iterateChildrenConst(nodep);
}
void visit(AstInitialAutomaticStmt* nodep) override {
checkNodeInfo(nodep);
iterateChildrenConst(nodep);
}
void visit(AstInitialStaticStmt* nodep) override {
checkNodeInfo(nodep);
iterateChildrenConst(nodep);
}
void visit(AstInitialStatic* nodep) override {
if (jumpingOver()) return;
if (!m_params) {

View File

@ -836,10 +836,17 @@ public:
// If this is AstVarRef and referred in the sensitivity list of always@,
// return the sensitivity item
AstSenItem* backSenItemp() const {
if (const AstVarRef* const refp = VN_CAST(m_nodep, VarRef)) {
return VN_CAST(refp->backp(), SenItem);
}
return nullptr;
const AstVarRef* const refp = VN_CAST(m_nodep, VarRef);
if (!refp) return nullptr;
return VN_CAST(refp->backp(), SenItem);
}
AstNodeAssign* backCResetp() const {
const AstVarRef* const refp = VN_CAST(m_nodep, VarRef);
if (!refp) return nullptr;
AstNodeAssign* const assp = VN_CAST(refp->backp(), NodeAssign);
if (!assp) return nullptr;
if (!VN_IS(assp->rhsp(), CReset)) return nullptr;
return assp;
}
};
@ -1027,7 +1034,8 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl {
UINFO(4, var.varp()->prettyNameQ() << "[" << msb << ":" << lsb << "] used for "
<< ref.nodep()->prettyNameQ() << '\n');
// LSB of varp is always 0. "lsb - var.lsb()" means this. see also SplitNewVar
return new AstSel{fl, refp, lsb - var.lsb(), bitwidth};
AstNodeExpr* const newp = new AstSel{fl, refp, lsb - var.lsb(), bitwidth};
return newp;
}
}
static void connectPortAndVar(const std::vector<SplitNewVar>& vars, AstVar* portp,
@ -1083,6 +1091,7 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl {
dtypep->rangep(new AstRange{
varp->fileline(), VNumRange{newvar.msb(), newvar.lsb(), basicp->ascending()}});
newvar.varp(new AstVar{varp->fileline(), VVarType::VAR, name, dtypep});
newvar.varp()->lifetime(varp->lifetime());
newvar.varp()->propagateAttrFrom(varp);
newvar.varp()->funcLocal(varp->isFuncLocal() || varp->isFuncReturn());
// Enable this line to trace split variable directly:
@ -1092,6 +1101,15 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl {
UINFO(4, newvar.varp()->prettyNameQ() << " is added for " << varp->prettyNameQ());
}
}
static AstAssign* newAssignCReset(AstNodeAssign* cresetAssp, AstVar* attachVarp) {
AstCReset* const cresetp = VN_AS(cresetAssp->rhsp(), CReset);
AstCReset* const newCResetp = cresetp->cloneTree(false);
newCResetp->dtypeFrom(attachVarp);
AstAssign* const newp = new AstAssign{
cresetAssp->fileline(),
new AstVarRef{cresetAssp->fileline(), attachVarp, VAccess::WRITE}, newCResetp};
return newp;
}
static void updateReferences(AstVar* varp, PackedVarRef& pref,
const std::vector<SplitNewVar>& vars) {
for (const bool lvalue : {false, true}) { // Refer the new split variables
@ -1102,9 +1120,14 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl {
UASSERT_OBJ(varit != vars.end(), ref.nodep(), "Not found");
UASSERT(!(varit->msb() < ref.lsb() || ref.msb() < varit->lsb()),
"wrong search result");
AstNode* prevp;
AstNode* prevp = nullptr;
bool inSentitivityList = false;
if (AstSenItem* const senitemp = ref.backSenItemp()) {
AstNodeAssign* const cresetAssp = ref.backCResetp();
if (cresetAssp) {
// ASSIGN(VARREF old, CRESET) convert to a creset of each new var
cresetAssp->addNextHere(newAssignCReset(cresetAssp, varit->varp()));
} else if (AstSenItem* const senitemp = ref.backSenItemp()) {
// SENITEM(VARREF old) convert to a list of separate SenItems for each new var
AstNode* const oldsenrefp = senitemp->sensp();
oldsenrefp->replaceWith(
new AstVarRef{senitemp->fileline(), varit->varp(), VAccess::READ});
@ -1118,7 +1141,9 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl {
residue -= varit->bitwidth()) {
++varit;
UASSERT_OBJ(varit != vars.end(), ref.nodep(), "not enough split variables");
if (AstSenItem* const senitemp = VN_CAST(prevp, SenItem)) {
if (cresetAssp) {
cresetAssp->addNextHere(newAssignCReset(cresetAssp, varit->varp()));
} else if (AstSenItem* const senitemp = VN_CAST(prevp, SenItem)) {
prevp = new AstSenItem{
senitemp->fileline(), senitemp->edgeType(),
new AstVarRef{senitemp->fileline(), varit->varp(), VAccess::READ}};
@ -1135,7 +1160,9 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl {
// split()
if (varp->isIO() && (varp->isFuncLocal() || varp->isFuncReturn()))
connectPortAndVar(vars, varp, ref.nodep());
if (!inSentitivityList) ref.replaceNodeWith(prevp);
if (!inSentitivityList && !cresetAssp) ref.replaceNodeWith(prevp);
if (cresetAssp)
VL_DO_DANGLING(cresetAssp->unlinkFrBack()->deleteTree(), cresetAssp);
UASSERT_OBJ(varit->msb() >= ref.msb(), varit->varp(), "Out of range");
}
}

View File

@ -1296,6 +1296,7 @@ class TristateVisitor final : public TristateBaseVisitor {
void visitAssign(AstNodeAssign* nodep) {
VL_RESTORER(m_alhs);
VL_RESTORER(m_currentStrength);
if (VN_IS(nodep->rhsp(), CReset)) return;
if (m_graphing) {
if (AstAssignW* assignWp = VN_CAST(nodep, AssignW)) {
if (assignWp->timingControlp() || assignWp->getLhsNetDelay()) return;

View File

@ -117,17 +117,17 @@ private:
}
public:
void usedWhole() {
UINFO(9, "set u[*] " << m_varp->name());
void usedWhole(const AstNode* nodep) {
UINFO(9, "set u[*] " << m_varp->name() << " " << nodep);
m_wholeFlags[FLAG_USED] = true;
}
void drivenWhole() {
UINFO(9, "set d[*] " << m_varp->name());
void drivenWhole(const AstNode* nodep) {
UINFO(9, "set d[*] " << m_varp->name() << " " << nodep);
m_wholeFlags[FLAG_DRIVEN] = true;
}
void drivenWhole(const AstNodeVarRef* nodep, const FileLine* fileLinep, bool ftaskDef) {
m_ftaskDriven = ftaskDef && !isDrivenWhole();
drivenWhole();
drivenWhole(nodep);
m_nodep = nodep;
m_nodeFileLinep = fileLinep;
}
@ -301,7 +301,7 @@ public:
}
void drivenViaCall(const AstNodeFTaskRef* nodep) {
drivenWhole();
drivenWhole(nodep);
if (!m_callNodep) m_callNodep = nodep;
}
const AstNodeFTaskRef* callNodep() const { return m_callNodep; }
@ -323,6 +323,7 @@ class UndrivenVisitor final : public VNVisitorConst {
std::array<std::vector<UndrivenVarEntry*>, 3> m_entryps = {}; // Nodes to delete when finished
bool m_inBBox = false; // In black box; mark as driven+used
bool m_inContAssign = false; // In continuous assignment
bool m_inInitialSetup = false; // In InitialAutomatic*/InitialStatic* assignment LHS
bool m_inInitialStatic = false; // In InitialStatic
bool m_inProcAssign = false; // In procedural assignment
bool m_inFTaskRef = false; // In function or task call
@ -380,16 +381,16 @@ class UndrivenVisitor final : public VNVisitorConst {
// usr==2 for always-only checks.
UndrivenVarEntry* const entryp = getEntryp(nodep, usr);
if ((nodep->isNonOutput() && !funcInout) || nodep->isSigPublic()
|| nodep->isSigUserRWPublic()
|| nodep->hasUserInit() || nodep->isSigUserRWPublic()
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
entryp->drivenWhole();
entryp->drivenWhole(nodep);
}
if ((nodep->isWritable() && !funcInout) || nodep->isSigPublic()
|| nodep->isSigUserRWPublic() || nodep->isSigUserRdPublic()
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
entryp->usedWhole();
entryp->usedWhole(nodep);
}
if (nodep->valuep()) entryp->drivenWhole();
if (nodep->valuep()) entryp->drivenWhole(nodep->valuep());
}
// Discover variables used in bit definitions, etc
iterateChildrenConst(nodep);
@ -504,7 +505,10 @@ class UndrivenVisitor final : public VNVisitorConst {
<< otherWritep->warnContextSecondary());
}
}
entryp->drivenWhole(nodep, nodep->fileline(), ftaskDef);
if (!m_inInitialSetup || nodep->varp()->hasUserInit()) {
// Else don't count default initialization as a driver to a net/variable
entryp->drivenWhole(nodep, nodep->fileline(), ftaskDef);
}
if (m_alwaysCombp && entryp->isDrivenAlwaysCombWhole()
&& m_alwaysCombp != entryp->getAlwCombp()
&& m_alwaysCombp->fileline() == entryp->getAlwCombFileLinep())
@ -517,13 +521,14 @@ class UndrivenVisitor final : public VNVisitorConst {
if (m_alwaysp && m_inProcAssign && !entryp->procWritep())
entryp->procWritep(nodep);
}
if (m_inBBox || nodep->access().isReadOrRW()
|| fdrv
// Inouts have only isWrite set, as we don't have more
// information and operating on module boundary, treat as
// both read and writing
|| m_inInoutOrRefPin)
entryp->usedWhole();
if ((!m_inInitialSetup || nodep->varp()->hasUserInit())
&& (m_inBBox || nodep->access().isReadOrRW()
|| fdrv
// Inouts have only isWrite set, as we don't have more
// information and operating on module boundary, treat as
// both read and writing
|| m_inInoutOrRefPin))
entryp->usedWhole(nodep);
}
}
@ -537,9 +542,12 @@ class UndrivenVisitor final : public VNVisitorConst {
void visit(AstAssign* nodep) override {
VL_RESTORER(m_inProcAssign);
m_inProcAssign = true;
// Don't count default initialization as a driver to a net/variable
if (VN_IS(nodep->rhsp(), CReset)) return;
iterateChildrenConst(nodep);
{
VL_RESTORER(m_inInitialSetup);
m_inInitialSetup = false;
iterateConst(nodep->rhsp());
}
iterateConst(nodep->lhsp());
}
void visit(AstAssignDly* nodep) override {
VL_RESTORER(m_inProcAssign);
@ -551,9 +559,26 @@ class UndrivenVisitor final : public VNVisitorConst {
m_inContAssign = true;
iterateChildrenConst(nodep);
}
void visit(AstInitialAutomatic* nodep) override {
VL_RESTORER(m_inInitialSetup);
m_inInitialSetup = true;
iterateChildrenConst(nodep);
}
void visit(AstInitialAutomaticStmt* nodep) override {
VL_RESTORER(m_inInitialSetup);
m_inInitialSetup = true;
iterateChildrenConst(nodep);
}
void visit(AstInitialStatic* nodep) override {
VL_RESTORER(m_inInitialStatic);
m_inInitialStatic = true;
VL_RESTORER(m_inInitialSetup);
m_inInitialSetup = true;
iterateChildrenConst(nodep);
}
void visit(AstInitialStaticStmt* nodep) override {
VL_RESTORER(m_inInitialSetup);
m_inInitialSetup = true;
iterateChildrenConst(nodep);
}
void visit(AstAlways* nodep) override {

View File

@ -34,6 +34,7 @@ public:
class CaptureVisitor final : public VNVisitorConst {
V3UndrivenCapture& m_cap;
const AstNodeFTask* m_curTaskp = nullptr; // Current task
bool m_inInitialSetup = false; // In InitialAutomatic*/InitialStatic* assignment LHS
public:
explicit CaptureVisitor(V3UndrivenCapture& cap, AstNetlist* netlistp)
@ -51,8 +52,28 @@ private:
iterateAndNextConstNull(nodep->stmtsp());
}
void visit(AstInitialAutomaticStmt* nodep) override {
VL_RESTORER(m_inInitialSetup);
m_inInitialSetup = true;
iterateChildrenConst(nodep);
}
void visit(AstInitialStaticStmt* nodep) override {
VL_RESTORER(m_inInitialSetup);
m_inInitialSetup = true;
iterateChildrenConst(nodep);
}
void visit(AstAssign* nodep) override {
{
VL_RESTORER(m_inInitialSetup);
m_inInitialSetup = false;
iterateConst(nodep->rhsp());
}
iterateConst(nodep->lhsp());
}
void visit(AstNodeVarRef* nodep) override {
if (m_curTaskp && nodep->access().isWriteOrRW()) {
if (m_curTaskp && nodep->access().isWriteOrRW()
&& (nodep->varp()->hasUserInit() || !m_inInitialSetup)) {
UINFO(9, "undriven capture direct write in " << CaptureUtil::taskNameQ(m_curTaskp)
<< " var=" << nodep->varp()->prettyNameQ()
<< " at " << nodep->fileline());
@ -163,7 +184,7 @@ void V3UndrivenCapture::noteDirectWrite(const AstNodeFTask* taskp, AstVar* varp)
if (retVarp && varp == retVarp) return;
// Filter out duplicates.
if (info.directWritesSet.insert(varp).second) { info.directWrites.push_back(varp); }
if (info.directWritesSet.insert(varp).second) info.directWrites.push_back(varp);
}
void V3UndrivenCapture::noteCallEdge(const AstNodeFTask* callerp, const AstNodeFTask* calleep) {

View File

@ -5503,6 +5503,18 @@ class WidthVisitor final : public VNVisitor {
if (AstAssign* const aitemp = VN_CAST(nodep, Assign)) {
if (VN_IS(aitemp->rhsp(), Const) || VN_IS(aitemp->rhsp(), CReset)) return true;
}
if (AstInitialStaticStmt* const aitemp = VN_CAST(nodep, InitialStaticStmt)) {
for (AstNode* stmtp = aitemp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (!firstNewStatementOkRecurse(stmtp)) return false;
}
return true;
}
if (AstInitialAutomaticStmt* const aitemp = VN_CAST(nodep, InitialAutomaticStmt)) {
for (AstNode* stmtp = aitemp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (!firstNewStatementOkRecurse(stmtp)) return false;
}
return true;
}
return false;
}

View File

@ -36,14 +36,14 @@
{"type":"VAR","name":"b","addr":"(DB)","loc":"d,61:48,61:49","dtypep":"(M)","origName":"b","verilogName":"b","direction":"INPUT","isFuncLocal":true,"lifetime":"VAUTOMI","varType":"PORT","dtypeName":"string","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"ASSIGN","name":"","addr":"(EB)","loc":"d,61:17,61:30","dtypep":"(U)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(FB)","loc":"d,61:17,61:30","dtypep":"(U)"}
{"type":"CONST","name":"1'h0","addr":"(FB)","loc":"d,61:17,61:30","dtypep":"(GB)"}
],
"lhsp": [
{"type":"VARREF","name":"strings_equal","addr":"(GB)","loc":"d,61:17,61:30","dtypep":"(U)","access":"WR","varp":"(BB)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"strings_equal","addr":"(HB)","loc":"d,61:17,61:30","dtypep":"(U)","access":"WR","varp":"(BB)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(HB)","loc":"d,62:7,62:13","dtypep":"(U)",
{"type":"ASSIGN","name":"","addr":"(IB)","loc":"d,62:7,62:13","dtypep":"(U)",
"rhsp": [
{"type":"EQN","name":"","addr":"(IB)","loc":"d,62:16,62:18","dtypep":"(JB)",
{"type":"EQN","name":"","addr":"(JB)","loc":"d,62:16,62:18","dtypep":"(GB)",
"lhsp": [
{"type":"VARREF","name":"a","addr":"(KB)","loc":"d,62:14,62:15","dtypep":"(M)","access":"RD","varp":"(CB)","varScopep":"UNLINKED","classOrPackagep":"(O)"}
],
@ -63,7 +63,7 @@
"miscsp": [
{"type":"TYPETABLE","name":"","addr":"(C)","loc":"a,0:0,0:0","constraintRefp":"UNLINKED","emptyQueuep":"UNLINKED","queueIndexp":"UNLINKED","streamp":"UNLINKED","voidp":"(OB)",
"typesp": [
{"type":"BASICDTYPE","name":"logic","addr":"(JB)","loc":"d,22:14,22:15","dtypep":"(JB)","keyword":"logic","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(GB)","loc":"d,22:14,22:15","dtypep":"(GB)","keyword":"logic","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(RB)","loc":"d,25:21,25:22","dtypep":"(RB)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"string","addr":"(M)","loc":"d,73:7,73:13","dtypep":"(M)","keyword":"string","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"int","addr":"(Q)","loc":"d,8:9,8:12","dtypep":"(Q)","keyword":"int","range":"31:0","generic":true,"signed":true,"rangep": []},

View File

@ -324,7 +324,8 @@
end
000011 begin
+000011 point: comment=block hier=top.t.t1
Cls c;
000011 Cls c;
+000011 point: comment=block hier=top.t.t1
000011 c = new(1'b1);
+000011 point: comment=block hier=top.t.t1
000011 c.fauto();
@ -458,7 +459,8 @@
000010 function arr_t get_arr;
+000010 point: comment=block hier=top.t.cond1
arr_t arr;
000010 arr_t arr;
+000010 point: comment=block hier=top.t.cond1
000010 return arr;
+000010 point: comment=block hier=top.t.cond1
endfunction

View File

@ -115,6 +115,7 @@ BRDA:225,0,0,1
BRDA:225,0,1,10
DA:226,1
DA:229,11
DA:230,11
DA:231,11
DA:232,11
DA:233,11
@ -153,6 +154,7 @@ DA:323,21
DA:324,21
DA:325,21
DA:328,10
DA:329,10
DA:330,10
DA:333,31
BRDA:333,0,0,0

View File

@ -401,8 +401,10 @@
-000001 point: comment=block hier=top.t
%000001 automatic cls null_obj = null;
-000001 point: comment=block hier=top.t
automatic int q[5];
automatic int qv[$];
%000001 automatic int q[5];
-000001 point: comment=block hier=top.t
%000001 automatic int qv[$];
-000001 point: comment=block hier=top.t
%000001 q = '{1, 2, 2, 4, 3};
-000001 point: comment=block hier=top.t

View File

@ -126,6 +126,7 @@ module Vt_debug_emitv_t;
initial begin
begin : unnamedblk1
int signed other;
other = /*CRESET*/;
begin
begin : unnamedblk2
int signed i;
@ -690,6 +691,7 @@ module Vt_debug_emitv_sub;
task inc;
input int signed i;
output int signed o;
o = /*CRESET*/;
o = ({32'h1{{1'h0, i[31:1]}}} + 32'h1);
endtask
function f;

View File

@ -125,7 +125,7 @@ test.file_grep_not(test.obj_dir + "/" + test.vm_prefix + "_classes.mk", "vm_clas
test.file_grep_not(test.obj_dir + "/" + test.vm_prefix + "_classes.mk", "vm_classes_2")
# Check combine count
test.file_grep(test.stats, r'Node count, CFILE + (\d+)', (276 if test.vltmt else 259))
test.file_grep(test.stats, r'Node count, CFILE + (\d+)', (275 if test.vltmt else 258))
test.file_grep(test.stats, r'Makefile targets, VM_CLASSES_FAST + (\d+)', 2)
test.file_grep(test.stats, r'Makefile targets, VM_CLASSES_SLOW + (\d+)', 2)

View File

@ -18,6 +18,6 @@ test.compile(
test.execute()
if test.vlt:
test.file_grep(test.stats, r'Optimizations, Const bit op reduction\s+(\d+)', 3416)
test.file_grep(test.stats, r'Optimizations, Const bit op reduction\s+(\d+)', 3888)
test.passes()

View File

@ -31,9 +31,9 @@ test.compile(v_flags2=[
if test.vltmt:
test.file_grep(test.obj_dir + "/V" + test.name + "__hier.dir/V" + test.name + "__stats.txt",
r'Optimizations, Thread schedule count\s+(\d+)', 4)
r'Optimizations, Thread schedule count\s+(\d+)', 3)
test.file_grep(test.obj_dir + "/V" + test.name + "__hier.dir/V" + test.name + "__stats.txt",
r'Optimizations, Thread schedule total tasks\s+(\d+)', 6)
r'Optimizations, Thread schedule total tasks\s+(\d+)', 5)
test.execute()

View File

@ -7,7 +7,7 @@
{"type":"VAR","name":"__Vtrigprevexpr___TOP__clk__0","addr":"(N)","loc":"d,11:8,11:9","dtypep":"(K)","origName":"__Vtrigprevexpr___TOP__clk__0","verilogName":"__Vtrigprevexpr___TOP__clk__0","direction":"NONE","lifetime":"NONE","varType":"MODULETEMP","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"__VactPhaseResult","addr":"(O)","loc":"d,11:8,11:9","dtypep":"(P)","origName":"__VactPhaseResult","verilogName":"__VactPhaseResult","direction":"NONE","noReset":true,"lifetime":"NONE","varType":"MODULETEMP","dtypeName":"bit","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"__VnbaPhaseResult","addr":"(Q)","loc":"d,11:8,11:9","dtypep":"(P)","origName":"__VnbaPhaseResult","verilogName":"__VnbaPhaseResult","direction":"NONE","noReset":true,"lifetime":"NONE","varType":"MODULETEMP","dtypeName":"bit","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cyc","addr":"(R)","loc":"d,23:17,23:20","dtypep":"(S)","origName":"cyc","verilogName":"cyc","direction":"NONE","lifetime":"VSTATICI","varType":"VAR","dtypeName":"integer","hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cyc","addr":"(R)","loc":"d,23:17,23:20","dtypep":"(S)","origName":"cyc","verilogName":"cyc","direction":"NONE","noCReset":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"integer","hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"__VactIterCount","addr":"(T)","loc":"d,11:8,11:9","dtypep":"(U)","origName":"__VactIterCount","verilogName":"__VactIterCount","direction":"NONE","noReset":true,"lifetime":"NONE","varType":"MODULETEMP","dtypeName":"bit","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"__VactTriggered","addr":"(V)","loc":"d,11:8,11:9","dtypep":"(W)","origName":"__VactTriggered","verilogName":"__VactTriggered","direction":"NONE","lifetime":"NONE","varType":"MODULETEMP","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"__VnbaTriggered","addr":"(X)","loc":"d,11:8,11:9","dtypep":"(W)","origName":"__VnbaTriggered","verilogName":"__VnbaTriggered","direction":"NONE","lifetime":"NONE","varType":"MODULETEMP","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
@ -2859,175 +2859,178 @@
"lhsp": [
{"type":"VARREF","name":"clk","addr":"(YPB)","loc":"d,15:10,15:13","dtypep":"(K)","access":"WR","varp":"(J)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(ZPB)","loc":"d,23:17,23:20","dtypep":"(S)",
{"type":"ASSIGN","name":"","addr":"(ZPB)","loc":"d,24:9,24:10","dtypep":"(M)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(AQB)","loc":"d,23:17,23:20","dtypep":"(S)","constructing":true}
{"type":"CRESET","name":"","addr":"(AQB)","loc":"d,24:9,24:10","dtypep":"(M)","constructing":true}
],
"lhsp": [
{"type":"VARREF","name":"t.cyc","addr":"(BQB)","loc":"d,23:17,23:20","dtypep":"(S)","access":"WR","varp":"(R)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"t.e","addr":"(BQB)","loc":"d,24:9,24:10","dtypep":"(M)","access":"WR","varp":"(L)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(CQB)","loc":"d,24:9,24:10","dtypep":"(M)",
{"type":"ASSIGN","name":"","addr":"(CQB)","loc":"d,11:8,11:9","dtypep":"(W)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(DQB)","loc":"d,24:9,24:10","dtypep":"(M)","constructing":true}
{"type":"CRESET","name":"","addr":"(DQB)","loc":"d,11:8,11:9","dtypep":"(W)","constructing":true}
],
"lhsp": [
{"type":"VARREF","name":"t.e","addr":"(EQB)","loc":"d,24:9,24:10","dtypep":"(M)","access":"WR","varp":"(L)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"__VactTriggered","addr":"(EQB)","loc":"d,11:8,11:9","dtypep":"(W)","access":"WR","varp":"(V)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(FQB)","loc":"d,11:8,11:9","dtypep":"(W)",
{"type":"ASSIGN","name":"","addr":"(FQB)","loc":"d,11:8,11:9","dtypep":"(K)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(GQB)","loc":"d,11:8,11:9","dtypep":"(W)","constructing":true}
{"type":"CRESET","name":"","addr":"(GQB)","loc":"d,11:8,11:9","dtypep":"(K)","constructing":true}
],
"lhsp": [
{"type":"VARREF","name":"__VactTriggered","addr":"(HQB)","loc":"d,11:8,11:9","dtypep":"(W)","access":"WR","varp":"(V)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"__Vtrigprevexpr___TOP__clk__0","addr":"(HQB)","loc":"d,11:8,11:9","dtypep":"(K)","access":"WR","varp":"(N)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(IQB)","loc":"d,11:8,11:9","dtypep":"(K)",
{"type":"ASSIGN","name":"","addr":"(IQB)","loc":"d,11:8,11:9","dtypep":"(W)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(JQB)","loc":"d,11:8,11:9","dtypep":"(K)","constructing":true}
{"type":"CRESET","name":"","addr":"(JQB)","loc":"d,11:8,11:9","dtypep":"(W)","constructing":true}
],
"lhsp": [
{"type":"VARREF","name":"__Vtrigprevexpr___TOP__clk__0","addr":"(KQB)","loc":"d,11:8,11:9","dtypep":"(K)","access":"WR","varp":"(N)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(LQB)","loc":"d,11:8,11:9","dtypep":"(W)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(MQB)","loc":"d,11:8,11:9","dtypep":"(W)","constructing":true}
],
"lhsp": [
{"type":"VARREF","name":"__VnbaTriggered","addr":"(NQB)","loc":"d,11:8,11:9","dtypep":"(W)","access":"WR","varp":"(X)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"__VnbaTriggered","addr":"(KQB)","loc":"d,11:8,11:9","dtypep":"(W)","access":"WR","varp":"(X)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": []}
]},
{"type":"CUSE","name":"$unit","addr":"(OQB)","loc":"a,0:0,0:0","useType":"INT_FWD"}
{"type":"CUSE","name":"$unit","addr":"(LQB)","loc":"a,0:0,0:0","useType":"INT_FWD"}
]},
{"type":"PACKAGE","name":"$unit","addr":"(E)","loc":"a,0:0,0:0","origName":"__024unit","verilogName":"\\$unit ","level":2,"inLibrary":true,"timeunit":"NONE","inlinesp": [],
"stmtsp": [
{"type":"VAR","name":"__Venumtab_enum_next1","addr":"(DC)","loc":"d,17:12,17:16","dtypep":"(CC)","origName":"__Venumtab_enum_next1","verilogName":"__Venumtab_enum_next1","direction":"NONE","isConst":true,"lifetime":"VSTATIC","varType":"MODULETEMP","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],
"valuep": [
{"type":"INITARRAY","name":"","addr":"(PQB)","loc":"d,17:12,17:16","dtypep":"(CC)","initList":" [1]=(QQB) [3]=(RQB) [4]=(SQB)",
{"type":"INITARRAY","name":"","addr":"(MQB)","loc":"d,17:12,17:16","dtypep":"(CC)","initList":" [1]=(NQB) [3]=(OQB) [4]=(PQB)",
"defaultp": [
{"type":"CONST","name":"4'h0","addr":"(TQB)","loc":"d,17:12,17:16","dtypep":"(UB)"}
{"type":"CONST","name":"4'h0","addr":"(QQB)","loc":"d,17:12,17:16","dtypep":"(UB)"}
],
"initsp": [
{"type":"INITITEM","name":"","addr":"(QQB)","loc":"d,17:12,17:16",
{"type":"INITITEM","name":"","addr":"(NQB)","loc":"d,17:12,17:16",
"valuep": [
{"type":"CONST","name":"4'h3","addr":"(UQB)","loc":"d,19:30,19:31","dtypep":"(UB)"}
{"type":"CONST","name":"4'h3","addr":"(RQB)","loc":"d,19:30,19:31","dtypep":"(UB)"}
]},
{"type":"INITITEM","name":"","addr":"(RQB)","loc":"d,17:12,17:16",
{"type":"INITITEM","name":"","addr":"(OQB)","loc":"d,17:12,17:16",
"valuep": [
{"type":"CONST","name":"4'h4","addr":"(VQB)","loc":"d,20:30,20:31","dtypep":"(UB)"}
{"type":"CONST","name":"4'h4","addr":"(SQB)","loc":"d,20:30,20:31","dtypep":"(UB)"}
]},
{"type":"INITITEM","name":"","addr":"(SQB)","loc":"d,17:12,17:16",
{"type":"INITITEM","name":"","addr":"(PQB)","loc":"d,17:12,17:16",
"valuep": [
{"type":"CONST","name":"4'h1","addr":"(WQB)","loc":"d,18:30,18:31","dtypep":"(UB)"}
{"type":"CONST","name":"4'h1","addr":"(TQB)","loc":"d,18:30,18:31","dtypep":"(UB)"}
]}
]}
],"attrsp": []},
{"type":"VAR","name":"__Venumtab_enum_prev1","addr":"(XI)","loc":"d,17:12,17:16","dtypep":"(WI)","origName":"__Venumtab_enum_prev1","verilogName":"__Venumtab_enum_prev1","direction":"NONE","isConst":true,"lifetime":"VSTATIC","varType":"MODULETEMP","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],
"valuep": [
{"type":"INITARRAY","name":"","addr":"(XQB)","loc":"d,17:12,17:16","dtypep":"(WI)","initList":" [1]=(YQB) [3]=(ZQB) [4]=(ARB)",
{"type":"INITARRAY","name":"","addr":"(UQB)","loc":"d,17:12,17:16","dtypep":"(WI)","initList":" [1]=(VQB) [3]=(WQB) [4]=(XQB)",
"defaultp": [
{"type":"CONST","name":"4'h0","addr":"(BRB)","loc":"d,17:12,17:16","dtypep":"(UB)"}
{"type":"CONST","name":"4'h0","addr":"(YQB)","loc":"d,17:12,17:16","dtypep":"(UB)"}
],
"initsp": [
{"type":"INITITEM","name":"","addr":"(YQB)","loc":"d,17:12,17:16",
{"type":"INITITEM","name":"","addr":"(VQB)","loc":"d,17:12,17:16",
"valuep": [
{"type":"CONST","name":"4'h4","addr":"(CRB)","loc":"d,20:30,20:31","dtypep":"(UB)"}
{"type":"CONST","name":"4'h4","addr":"(ZQB)","loc":"d,20:30,20:31","dtypep":"(UB)"}
]},
{"type":"INITITEM","name":"","addr":"(ZQB)","loc":"d,17:12,17:16",
{"type":"INITITEM","name":"","addr":"(WQB)","loc":"d,17:12,17:16",
"valuep": [
{"type":"CONST","name":"4'h1","addr":"(DRB)","loc":"d,18:30,18:31","dtypep":"(UB)"}
{"type":"CONST","name":"4'h1","addr":"(ARB)","loc":"d,18:30,18:31","dtypep":"(UB)"}
]},
{"type":"INITITEM","name":"","addr":"(ARB)","loc":"d,17:12,17:16",
{"type":"INITITEM","name":"","addr":"(XQB)","loc":"d,17:12,17:16",
"valuep": [
{"type":"CONST","name":"4'h3","addr":"(ERB)","loc":"d,19:30,19:31","dtypep":"(UB)"}
{"type":"CONST","name":"4'h3","addr":"(BRB)","loc":"d,19:30,19:31","dtypep":"(UB)"}
]}
]}
],"attrsp": []},
{"type":"VAR","name":"__Venumtab_enum_name1","addr":"(JM)","loc":"d,17:12,17:16","dtypep":"(IM)","origName":"__Venumtab_enum_name1","verilogName":"__Venumtab_enum_name1","direction":"NONE","isConst":true,"lifetime":"VSTATIC","varType":"MODULETEMP","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],
"valuep": [
{"type":"INITARRAY","name":"","addr":"(FRB)","loc":"d,17:12,17:16","dtypep":"(IM)","initList":" [1]=(GRB) [3]=(HRB) [4]=(IRB)",
{"type":"INITARRAY","name":"","addr":"(CRB)","loc":"d,17:12,17:16","dtypep":"(IM)","initList":" [1]=(DRB) [3]=(ERB) [4]=(FRB)",
"defaultp": [
{"type":"CONST","name":"\\\"\\\"","addr":"(JRB)","loc":"d,17:12,17:16","dtypep":"(SB)"}
{"type":"CONST","name":"\\\"\\\"","addr":"(GRB)","loc":"d,17:12,17:16","dtypep":"(SB)"}
],
"initsp": [
{"type":"INITITEM","name":"","addr":"(GRB)","loc":"d,17:12,17:16",
{"type":"INITITEM","name":"","addr":"(DRB)","loc":"d,17:12,17:16",
"valuep": [
{"type":"CONST","name":"\\\"E01\\\"","addr":"(KRB)","loc":"d,17:12,17:16","dtypep":"(SB)"}
{"type":"CONST","name":"\\\"E01\\\"","addr":"(HRB)","loc":"d,17:12,17:16","dtypep":"(SB)"}
]},
{"type":"INITITEM","name":"","addr":"(HRB)","loc":"d,17:12,17:16",
{"type":"INITITEM","name":"","addr":"(ERB)","loc":"d,17:12,17:16",
"valuep": [
{"type":"CONST","name":"\\\"E03\\\"","addr":"(LRB)","loc":"d,17:12,17:16","dtypep":"(SB)"}
{"type":"CONST","name":"\\\"E03\\\"","addr":"(IRB)","loc":"d,17:12,17:16","dtypep":"(SB)"}
]},
{"type":"INITITEM","name":"","addr":"(IRB)","loc":"d,17:12,17:16",
{"type":"INITITEM","name":"","addr":"(FRB)","loc":"d,17:12,17:16",
"valuep": [
{"type":"CONST","name":"\\\"E04\\\"","addr":"(MRB)","loc":"d,17:12,17:16","dtypep":"(SB)"}
{"type":"CONST","name":"\\\"E04\\\"","addr":"(JRB)","loc":"d,17:12,17:16","dtypep":"(SB)"}
]}
]}
],"attrsp": []},
{"type":"SCOPE","name":"$unit","addr":"(NRB)","loc":"a,0:0,0:0","aboveScopep":"(Z)","aboveCellp":"(Y)","modp":"(E)","varsp": [],"blocksp": [],"inlinesp": []},
{"type":"CFUNC","name":"_ctor_var_reset","addr":"(ORB)","loc":"a,0:0,0:0","slow":true,"scopep":"UNLINKED","argsp": [],"varsp": [],
{"type":"SCOPE","name":"$unit","addr":"(KRB)","loc":"a,0:0,0:0","aboveScopep":"(Z)","aboveCellp":"(Y)","modp":"(E)","varsp": [],"blocksp": [],"inlinesp": []},
{"type":"CFUNC","name":"_ctor_var_reset","addr":"(LRB)","loc":"a,0:0,0:0","slow":true,"scopep":"UNLINKED","argsp": [],"varsp": [],
"stmtsp": [
{"type":"ASSIGN","name":"","addr":"(PRB)","loc":"d,17:12,17:16","dtypep":"(CC)",
{"type":"ASSIGN","name":"","addr":"(MRB)","loc":"d,17:12,17:16","dtypep":"(CC)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(QRB)","loc":"d,17:12,17:16","dtypep":"(CC)","constructing":true}
{"type":"CRESET","name":"","addr":"(NRB)","loc":"d,17:12,17:16","dtypep":"(CC)","constructing":true}
],
"lhsp": [
{"type":"VARREF","name":"__Venumtab_enum_next1","addr":"(RRB)","loc":"d,17:12,17:16","dtypep":"(CC)","access":"WR","varp":"(DC)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"__Venumtab_enum_next1","addr":"(ORB)","loc":"d,17:12,17:16","dtypep":"(CC)","access":"WR","varp":"(DC)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(SRB)","loc":"d,17:12,17:16","dtypep":"(WI)",
{"type":"ASSIGN","name":"","addr":"(PRB)","loc":"d,17:12,17:16","dtypep":"(WI)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(TRB)","loc":"d,17:12,17:16","dtypep":"(WI)","constructing":true}
{"type":"CRESET","name":"","addr":"(QRB)","loc":"d,17:12,17:16","dtypep":"(WI)","constructing":true}
],
"lhsp": [
{"type":"VARREF","name":"__Venumtab_enum_prev1","addr":"(URB)","loc":"d,17:12,17:16","dtypep":"(WI)","access":"WR","varp":"(XI)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"__Venumtab_enum_prev1","addr":"(RRB)","loc":"d,17:12,17:16","dtypep":"(WI)","access":"WR","varp":"(XI)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(VRB)","loc":"d,17:12,17:16","dtypep":"(IM)",
{"type":"ASSIGN","name":"","addr":"(SRB)","loc":"d,17:12,17:16","dtypep":"(IM)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(WRB)","loc":"d,17:12,17:16","dtypep":"(IM)","constructing":true}
{"type":"CRESET","name":"","addr":"(TRB)","loc":"d,17:12,17:16","dtypep":"(IM)","constructing":true}
],
"lhsp": [
{"type":"VARREF","name":"__Venumtab_enum_name1","addr":"(XRB)","loc":"d,17:12,17:16","dtypep":"(IM)","access":"WR","varp":"(JM)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"__Venumtab_enum_name1","addr":"(URB)","loc":"d,17:12,17:16","dtypep":"(IM)","access":"WR","varp":"(JM)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": []}
]}
]}
],
"filesp": [
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__Syms__Slow.cpp","addr":"(YRB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__Syms.h","addr":"(ZRB)","loc":"a,0:0,0:0","tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck.h","addr":"(ASB)","loc":"a,0:0,0:0","tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck.cpp","addr":"(BSB)","loc":"a,0:0,0:0","source":true,"tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__pch.h","addr":"(CSB)","loc":"a,0:0,0:0","tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root.h","addr":"(DSB)","loc":"a,0:0,0:0","tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit.h","addr":"(ESB)","loc":"a,0:0,0:0","tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__Slow.cpp","addr":"(FSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__0__Slow.cpp","addr":"(GSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__0.cpp","addr":"(HSB)","loc":"a,0:0,0:0","source":true,"tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit__Slow.cpp","addr":"(ISB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit__0__Slow.cpp","addr":"(JSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []}
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__Syms__Slow.cpp","addr":"(VRB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__Syms.h","addr":"(WRB)","loc":"a,0:0,0:0","tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck.h","addr":"(XRB)","loc":"a,0:0,0:0","tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck.cpp","addr":"(YRB)","loc":"a,0:0,0:0","source":true,"tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__pch.h","addr":"(ZRB)","loc":"a,0:0,0:0","tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root.h","addr":"(ASB)","loc":"a,0:0,0:0","tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit.h","addr":"(BSB)","loc":"a,0:0,0:0","tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__Slow.cpp","addr":"(CSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__0__Slow.cpp","addr":"(DSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__0.cpp","addr":"(ESB)","loc":"a,0:0,0:0","source":true,"tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit__Slow.cpp","addr":"(FSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []},
{"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit__0__Slow.cpp","addr":"(GSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []}
],
"miscsp": [
{"type":"TYPETABLE","name":"","addr":"(C)","loc":"a,0:0,0:0","constraintRefp":"UNLINKED","emptyQueuep":"UNLINKED","queueIndexp":"UNLINKED","streamp":"UNLINKED","voidp":"(DB)",
"typesp": [
{"type":"BASICDTYPE","name":"logic","addr":"(K)","loc":"d,33:24,33:27","dtypep":"(K)","keyword":"logic","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(HC)","loc":"d,53:16,53:17","dtypep":"(HC)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(KSB)","loc":"d,17:17,17:18","dtypep":"(KSB)","keyword":"logic","range":"3:0","generic":true,"rangep": []},
{"type":"ENUMDTYPE","name":"t.my_t","addr":"(LSB)","loc":"d,17:12,17:16","dtypep":"(LSB)","enum":true,"refDTypep":"(KSB)","childDTypep": [],
{"type":"BASICDTYPE","name":"logic","addr":"(HSB)","loc":"d,17:17,17:18","dtypep":"(HSB)","keyword":"logic","range":"3:0","generic":true,"rangep": []},
{"type":"ENUMDTYPE","name":"t.my_t","addr":"(ISB)","loc":"d,17:12,17:16","dtypep":"(ISB)","enum":true,"refDTypep":"(HSB)","childDTypep": [],
"itemsp": [
{"type":"ENUMITEM","name":"E01","addr":"(MSB)","loc":"d,18:24,18:27","dtypep":"(UB)","rangep": [],
{"type":"ENUMITEM","name":"E01","addr":"(JSB)","loc":"d,18:24,18:27","dtypep":"(UB)","rangep": [],
"valuep": [
{"type":"CONST","name":"4'h1","addr":"(NSB)","loc":"d,18:30,18:31","dtypep":"(UB)"}
{"type":"CONST","name":"4'h1","addr":"(KSB)","loc":"d,18:30,18:31","dtypep":"(UB)"}
]},
{"type":"ENUMITEM","name":"E03","addr":"(OSB)","loc":"d,19:24,19:27","dtypep":"(UB)","rangep": [],
{"type":"ENUMITEM","name":"E03","addr":"(LSB)","loc":"d,19:24,19:27","dtypep":"(UB)","rangep": [],
"valuep": [
{"type":"CONST","name":"4'h3","addr":"(PSB)","loc":"d,19:30,19:31","dtypep":"(UB)"}
{"type":"CONST","name":"4'h3","addr":"(MSB)","loc":"d,19:30,19:31","dtypep":"(UB)"}
]},
{"type":"ENUMITEM","name":"E04","addr":"(QSB)","loc":"d,20:24,20:27","dtypep":"(UB)","rangep": [],
{"type":"ENUMITEM","name":"E04","addr":"(NSB)","loc":"d,20:24,20:27","dtypep":"(UB)","rangep": [],
"valuep": [
{"type":"CONST","name":"4'h4","addr":"(RSB)","loc":"d,20:30,20:31","dtypep":"(UB)"}
{"type":"CONST","name":"4'h4","addr":"(OSB)","loc":"d,20:30,20:31","dtypep":"(UB)"}
]}
]},
{"type":"BASICDTYPE","name":"integer","addr":"(S)","loc":"d,23:4,23:11","dtypep":"(S)","keyword":"integer","range":"31:0","generic":true,"signed":true,"rangep": []},
{"type":"REFDTYPE","name":"my_t","addr":"(M)","loc":"d,24:4,24:8","dtypep":"(LSB)","typedefp":"UNLINKED","refDTypep":"(LSB)","classOrPackagep":"UNLINKED","typeofp": [],"classOrPackageOpp": [],"paramsp": []},
{"type":"REFDTYPE","name":"my_t","addr":"(M)","loc":"d,24:4,24:8","dtypep":"(ISB)","typedefp":"UNLINKED","refDTypep":"(ISB)","classOrPackagep":"UNLINKED","typeofp": [],"classOrPackageOpp": [],"paramsp": []},
{"type":"BASICDTYPE","name":"string","addr":"(SB)","loc":"d,28:4,28:10","dtypep":"(SB)","keyword":"string","generic":true,"rangep": []},
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(CC)","loc":"d,17:12,17:16","dtypep":"(CC)","declRange":"[7:0]","refDTypep":"(LSB)","childDTypep": [],
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(CC)","loc":"d,17:12,17:16","dtypep":"(CC)","declRange":"[7:0]","refDTypep":"(ISB)","childDTypep": [],
"rangep": [
{"type":"RANGE","name":"","addr":"(PSB)","loc":"d,17:12,17:16",
"leftp": [
{"type":"CONST","name":"32'h7","addr":"(QSB)","loc":"d,17:12,17:16","dtypep":"(HC)"}
],
"rightp": [
{"type":"CONST","name":"32'h0","addr":"(RSB)","loc":"d,17:12,17:16","dtypep":"(HC)"}
]}
]},
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(WI)","loc":"d,17:12,17:16","dtypep":"(WI)","declRange":"[7:0]","refDTypep":"(ISB)","childDTypep": [],
"rangep": [
{"type":"RANGE","name":"","addr":"(SSB)","loc":"d,17:12,17:16",
"leftp": [
@ -3037,7 +3040,7 @@
{"type":"CONST","name":"32'h0","addr":"(USB)","loc":"d,17:12,17:16","dtypep":"(HC)"}
]}
]},
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(WI)","loc":"d,17:12,17:16","dtypep":"(WI)","declRange":"[7:0]","refDTypep":"(LSB)","childDTypep": [],
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(IM)","loc":"d,17:12,17:16","dtypep":"(IM)","isCompound":true,"declRange":"[7:0]","refDTypep":"(SB)","childDTypep": [],
"rangep": [
{"type":"RANGE","name":"","addr":"(VSB)","loc":"d,17:12,17:16",
"leftp": [
@ -3047,27 +3050,17 @@
{"type":"CONST","name":"32'h0","addr":"(XSB)","loc":"d,17:12,17:16","dtypep":"(HC)"}
]}
]},
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(IM)","loc":"d,17:12,17:16","dtypep":"(IM)","isCompound":true,"declRange":"[7:0]","refDTypep":"(SB)","childDTypep": [],
"rangep": [
{"type":"RANGE","name":"","addr":"(YSB)","loc":"d,17:12,17:16",
"leftp": [
{"type":"CONST","name":"32'h7","addr":"(ZSB)","loc":"d,17:12,17:16","dtypep":"(HC)"}
],
"rightp": [
{"type":"CONST","name":"32'h0","addr":"(ATB)","loc":"d,17:12,17:16","dtypep":"(HC)"}
]}
]},
{"type":"BASICDTYPE","name":"logic","addr":"(LB)","loc":"d,23:23,23:24","dtypep":"(LB)","keyword":"logic","range":"31:0","generic":true,"signed":true,"rangep": []},
{"type":"VOIDDTYPE","name":"","addr":"(DB)","loc":"a,0:0,0:0","dtypep":"(DB)"},
{"type":"BASICDTYPE","name":"bit","addr":"(HN)","loc":"a,0:0,0:0","dtypep":"(HN)","keyword":"bit","range":"63:0","generic":true,"rangep": []},
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(W)","loc":"d,11:8,11:9","dtypep":"(W)","declRange":"[0:0]","refDTypep":"(HN)","childDTypep": [],
"rangep": [
{"type":"RANGE","name":"","addr":"(BTB)","loc":"d,11:8,11:9",
{"type":"RANGE","name":"","addr":"(YSB)","loc":"d,11:8,11:9",
"leftp": [
{"type":"CONST","name":"32'h0","addr":"(CTB)","loc":"d,11:8,11:9","dtypep":"(HC)"}
{"type":"CONST","name":"32'h0","addr":"(ZSB)","loc":"d,11:8,11:9","dtypep":"(HC)"}
],
"rightp": [
{"type":"CONST","name":"32'h0","addr":"(DTB)","loc":"d,11:8,11:9","dtypep":"(HC)"}
{"type":"CONST","name":"32'h0","addr":"(ATB)","loc":"d,11:8,11:9","dtypep":"(HC)"}
]}
]},
{"type":"BASICDTYPE","name":"IData","addr":"(IP)","loc":"a,0:0,0:0","dtypep":"(IP)","keyword":"IData","range":"31:0","generic":true,"rangep": []},
@ -3081,9 +3074,9 @@
]},
{"type":"CONSTPOOL","name":"","addr":"(D)","loc":"a,0:0,0:0",
"modulep": [
{"type":"MODULE","name":"@CONST-POOL@","addr":"(ETB)","loc":"a,0:0,0:0","origName":"@CONST-POOL@","verilogName":"@CONST-POOL@","level":0,"timeunit":"NONE","inlinesp": [],
{"type":"MODULE","name":"@CONST-POOL@","addr":"(BTB)","loc":"a,0:0,0:0","origName":"@CONST-POOL@","verilogName":"@CONST-POOL@","level":0,"timeunit":"NONE","inlinesp": [],
"stmtsp": [
{"type":"SCOPE","name":"TOP","addr":"(FTB)","loc":"a,0:0,0:0","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(ETB)","varsp": [],"blocksp": [],"inlinesp": []}
{"type":"SCOPE","name":"TOP","addr":"(CTB)","loc":"a,0:0,0:0","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(BTB)","varsp": [],"blocksp": [],"inlinesp": []}
]}
]}
]}

View File

@ -82,26 +82,26 @@
"lhsp": [
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__val","addr":"(KC)","loc":"d,15:57,15:60","dtypep":"(H)","access":"WR","varp":"(SB)","varScopep":"(RB)","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(LC)","loc":"d,16:17,16:20","dtypep":"(K)",
{"type":"ASSIGN","name":"","addr":"(LC)","loc":"d,15:34,15:37","dtypep":"(K)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(MC)","loc":"d,16:17,16:20","dtypep":"(K)"}
{"type":"CRESET","name":"","addr":"(MC)","loc":"d,15:34,15:37","dtypep":"(K)"}
],
"lhsp": [
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__ret","addr":"(NC)","loc":"d,16:17,16:20","dtypep":"(K)","access":"WR","varp":"(UB)","varScopep":"(TB)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__Vfuncout","addr":"(NC)","loc":"d,15:34,15:37","dtypep":"(K)","access":"WR","varp":"(QB)","varScopep":"(PB)","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(OC)","loc":"d,17:13,17:14","dtypep":"(WB)",
{"type":"ASSIGN","name":"","addr":"(OC)","loc":"d,16:17,16:20","dtypep":"(K)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(PC)","loc":"d,17:13,17:14","dtypep":"(WB)"}
{"type":"CRESET","name":"","addr":"(PC)","loc":"d,16:17,16:20","dtypep":"(K)"}
],
"lhsp": [
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__i","addr":"(QC)","loc":"d,17:13,17:14","dtypep":"(WB)","access":"WR","varp":"(XB)","varScopep":"(VB)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__ret","addr":"(QC)","loc":"d,16:17,16:20","dtypep":"(K)","access":"WR","varp":"(UB)","varScopep":"(TB)","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(RC)","loc":"d,15:34,15:37","dtypep":"(K)",
{"type":"ASSIGN","name":"","addr":"(RC)","loc":"d,17:13,17:14","dtypep":"(WB)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(SC)","loc":"d,15:34,15:37","dtypep":"(K)"}
{"type":"CRESET","name":"","addr":"(SC)","loc":"d,17:13,17:14","dtypep":"(WB)"}
],
"lhsp": [
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__Vfuncout","addr":"(TC)","loc":"d,15:34,15:37","dtypep":"(K)","access":"WR","varp":"(QB)","varScopep":"(PB)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__i","addr":"(TC)","loc":"d,17:13,17:14","dtypep":"(WB)","access":"WR","varp":"(XB)","varScopep":"(VB)","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(UC)","loc":"d,18:11,18:12","dtypep":"(WB)",
"rhsp": [
@ -204,26 +204,26 @@
"lhsp": [
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__val","addr":"(ME)","loc":"d,15:57,15:60","dtypep":"(H)","access":"WR","varp":"(BC)","varScopep":"(AC)","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(NE)","loc":"d,16:17,16:20","dtypep":"(K)",
{"type":"ASSIGN","name":"","addr":"(NE)","loc":"d,15:34,15:37","dtypep":"(K)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(OE)","loc":"d,16:17,16:20","dtypep":"(K)"}
{"type":"CRESET","name":"","addr":"(OE)","loc":"d,15:34,15:37","dtypep":"(K)"}
],
"lhsp": [
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__ret","addr":"(PE)","loc":"d,16:17,16:20","dtypep":"(K)","access":"WR","varp":"(DC)","varScopep":"(CC)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__Vfuncout","addr":"(PE)","loc":"d,15:34,15:37","dtypep":"(K)","access":"WR","varp":"(ZB)","varScopep":"(YB)","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(QE)","loc":"d,17:13,17:14","dtypep":"(WB)",
{"type":"ASSIGN","name":"","addr":"(QE)","loc":"d,16:17,16:20","dtypep":"(K)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(RE)","loc":"d,17:13,17:14","dtypep":"(WB)"}
{"type":"CRESET","name":"","addr":"(RE)","loc":"d,16:17,16:20","dtypep":"(K)"}
],
"lhsp": [
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__i","addr":"(SE)","loc":"d,17:13,17:14","dtypep":"(WB)","access":"WR","varp":"(FC)","varScopep":"(EC)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__ret","addr":"(SE)","loc":"d,16:17,16:20","dtypep":"(K)","access":"WR","varp":"(DC)","varScopep":"(CC)","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(TE)","loc":"d,15:34,15:37","dtypep":"(K)",
{"type":"ASSIGN","name":"","addr":"(TE)","loc":"d,17:13,17:14","dtypep":"(WB)",
"rhsp": [
{"type":"CRESET","name":"","addr":"(UE)","loc":"d,15:34,15:37","dtypep":"(K)"}
{"type":"CRESET","name":"","addr":"(UE)","loc":"d,17:13,17:14","dtypep":"(WB)"}
],
"lhsp": [
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__Vfuncout","addr":"(VE)","loc":"d,15:34,15:37","dtypep":"(K)","access":"WR","varp":"(ZB)","varScopep":"(YB)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__i","addr":"(VE)","loc":"d,17:13,17:14","dtypep":"(WB)","access":"WR","varp":"(FC)","varScopep":"(EC)","classOrPackagep":"UNLINKED"}
],"timingControlp": []},
{"type":"ASSIGN","name":"","addr":"(WE)","loc":"d,18:11,18:12","dtypep":"(WB)",
"rhsp": [

View File

@ -12,6 +12,8 @@ import vltest_bootstrap
test.scenarios('vlt')
test.top_filename = "t/t_static_in_loop.v"
test.lint(fails=True, expect_filename=test.golden_filename)
test.compile()
test.execute()
test.passes()

View File

@ -6,9 +6,9 @@
module t;
initial begin
automatic int x = 0;
static int x = 0;
while (x < 10) begin : outer_loop
automatic int y = 0;
static int y = 0;
while (y < x) begin : inner_loop
static int a = 0;
a++;
@ -16,7 +16,7 @@ module t;
end
x++;
end
if (outer_loop.inner_loop.a != 45) $stop;
if (outer_loop.inner_loop.a != 9) $stop;
$write("*-* All Finished *-*\n");
$finish;

View File

@ -34,19 +34,6 @@
-V{t#,#}+ Vt_timing_debug2_t__03a__03aLocalWaitClass::_ctor_var_reset
-V{t#,#}+ Vt_timing_debug2_t__03a__03aClkClass::new
-V{t#,#}+ Vt_timing_debug2_t__03a__03aClkClass::_ctor_var_reset
-V{t#,#}+ Vt_timing_debug2___024root___timing_ready
-V{t#,#}+ Vt_timing_debug2___024root___eval_initial
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__0
-V{t#,#}+ Vt_timing_debug2___024root____VbeforeTrig_h########__0
-V{t#,#} Suspending process waiting for @([event] t.ec.e) at t/t_timing_class.v:111
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__1
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__2
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__3
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__4
-V{t#,#}+ Vt_timing_debug2_t__03a__03aClkClass::__VnoInFunc_count_5
-V{t#,#} Suspending process waiting for @(posedge t::ClkClass.clk) at t/t_timing_class.v:97
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__5
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__6
-V{t#,#}+ Vt_timing_debug2_t__03a__03aDelayClass::new
-V{t#,#}+ Vt_timing_debug2_t__03a__03aDelayClass::_ctor_var_reset
-V{t#,#}+ Vt_timing_debug2_t__03a__03aDelay10::new
@ -65,6 +52,19 @@
-V{t#,#}+ Vt_timing_debug2_t__03a__03aNoDelay::_ctor_var_reset
-V{t#,#}+ Vt_timing_debug2_t__03a__03aAssignDelayClass::new
-V{t#,#}+ Vt_timing_debug2_t__03a__03aAssignDelayClass::_ctor_var_reset
-V{t#,#}+ Vt_timing_debug2___024root___timing_ready
-V{t#,#}+ Vt_timing_debug2___024root___eval_initial
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__0
-V{t#,#}+ Vt_timing_debug2___024root____VbeforeTrig_h########__0
-V{t#,#} Suspending process waiting for @([event] t.ec.e) at t/t_timing_class.v:111
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__1
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__2
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__3
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__4
-V{t#,#}+ Vt_timing_debug2_t__03a__03aClkClass::__VnoInFunc_count_5
-V{t#,#} Suspending process waiting for @(posedge t::ClkClass.clk) at t/t_timing_class.v:97
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__5
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__6
-V{t#,#}+ Vt_timing_debug2_t__03a__03aDelay10::__VnoInFunc_do_delay
-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__7
-V{t#,#}+ Vt_timing_debug2_t__03a__03aForkClass::new

View File

@ -0,0 +1,18 @@
#!/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.scenarios('simulator')
test.compile(verilator_flags2=['--timing'])
test.execute()
test.passes()

View File

@ -0,0 +1,226 @@
// 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
// verilog_format: off
`define stop $stop
`define checkd(gotv,expv) if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end
`define checkd_elab(gotv,expv) if ((gotv) !== (expv)) begin $error("%%Error: %s:%0d: got=%0d exp=%0d", `__FILE__,`__LINE__, (gotv), (expv)); end
// verilog_format: on
class Cls;
task tsk();
for (int i = 0; i < 3; i++) begin
/*automatic*/ int tj_auto;
/*automatic*/ int tj_auto_init = 10;
/*automatic*/ int tqueue_auto[$];
/*automatic*/ int tqueue_auto_init[$] = '{1};
static int tj_static; // = 0
static int tj_static_init = 10;
static int tqueue_static[$];
static int tqueue_static_init[$] = '{1};
$display("Function iteration %0d:", i);
tj_auto = tj_auto + 1;
`checkd(tj_auto, 1);
tj_auto_init = tj_auto_init + 1;
`checkd(tj_auto_init, 11);
`checkd(tqueue_auto.size(), 0);
tqueue_auto.push_back(i + 10);
`checkd(tqueue_auto.size(), 1);
`checkd(tqueue_auto_init.size(), 1);
tqueue_auto_init.push_back(i + 20);
`checkd(tqueue_auto_init.size(), 2);
tj_static = tj_static + 1;
`checkd(tj_static, i + 1);
tj_static_init = tj_static_init + 1;
`checkd(tj_static_init, i + 1 + 10);
tqueue_static.push_back(i + 20);
`checkd(tqueue_static.size(), i + 1);
tqueue_static_init.push_back(i + 20);
`checkd(tqueue_static_init.size(), i + 2);
end
endtask
endclass
module t;
function int func_const_kj_init();
int r;
for (int i = 0; i < 3; i++) begin
automatic int kj;
automatic int kj_init = 10;
kj = kj + 1;
`checkd_elab(kj, 1);
kj_init = kj_init + 1;
`checkd_elab(kj_init, 11);
r = kj_init;
end
return r;
endfunction
localparam FUNC_CONST_KJ_INIT = func_const_kj_init();
task forked;
automatic int forktop = 100;
for (int i = 0; i < 3; i++) begin
// fork declarations are executed before all parallel statements (IEEE 1800-2023 9.3.2)
fork : f_named
// Automatics-in-forks Verilator will move to a VDynScope class
automatic int fj_auto;
automatic int fj_auto_init = 10;
automatic int fqueue_auto[$];
automatic int fqueue_auto_init[$] = '{1};
// Statics-in-forks will stay in the original task
static int fj_static; // = 0
static int fj_static_init = 10;
static int fqueue_static[$];
static int fqueue_static_init[$] = '{1};
begin
$display("Fork iteration %0d:", i);
++forktop;
fj_auto = fj_auto + 1;
`checkd(fj_auto, 1);
fj_auto_init = fj_auto_init + 1;
`checkd(fj_auto_init, 11);
`checkd(fqueue_auto.size(), 0);
fqueue_auto.push_back(i + 10);
`checkd(fqueue_auto.size(), 1);
`checkd(fqueue_auto_init.size(), 1);
fqueue_auto_init.push_back(i + 20);
`checkd(fqueue_auto_init.size(), 2);
fj_static = fj_static + 1;
`checkd(fj_static, i + 1);
fj_static_init = fj_static_init + 1;
`checkd(fj_static_init, i + 1 + 10);
fqueue_static.push_back(i + 20);
`checkd(fqueue_static.size(), i + 1);
fqueue_static_init.push_back(i + 20);
`checkd(fqueue_static_init.size(), i + 2);
end
join
end
`checkd(forktop, 100 + 3);
endtask
task forked_begin;
// fork declarations are executed before all parallel statements (IEEE 1800-2023 9.3.2)
fork : f_named
for (int i = 0; i < 3; i++) begin
// Automatics-in-zorks Verilator will move to a VDynScope class
automatic int zj_auto;
automatic int zj_auto_init = 10;
automatic int zqueue_auto[$];
automatic int zqueue_auto_init[$] = '{1};
// Statics-in-forks will stay in the original task
static int zj_static; // = 0
static int zj_static_init = 10;
static int zqueue_static[$];
static int zqueue_static_init[$] = '{1};
begin
$display("Fork-begin iteration %0d:", i);
zj_auto = zj_auto + 1;
`checkd(zj_auto, 1);
zj_auto_init = zj_auto_init + 1;
`checkd(zj_auto_init, 11);
`checkd(zqueue_auto.size(), 0);
zqueue_auto.push_back(i + 10);
`checkd(zqueue_auto.size(), 1);
`checkd(zqueue_auto_init.size(), 1);
zqueue_auto_init.push_back(i + 20);
`checkd(zqueue_auto_init.size(), 2);
zj_static = zj_static + 1;
`checkd(zj_static, i + 1);
zj_static_init = zj_static_init + 1;
`checkd(zj_static_init, i + 1 + 10);
zqueue_static.push_back(i + 20);
`checkd(zqueue_static.size(), i + 1);
zqueue_static_init.push_back(i + 20);
`checkd(zqueue_static_init.size(), i + 2);
end
end
join
endtask
initial begin
Cls c;
c = new();
c.tsk();
`checkd(FUNC_CONST_KJ_INIT, 11);
for (int i = 0; i < 3; i++) begin : p_named
automatic int pj_auto;
automatic int pj_auto_init = 10;
automatic int pqueue_auto[$];
automatic int pqueue_auto_init[$] = '{1};
static int pj_static; // = 0
static int pj_static_init = 10;
static int pqueue_static[$];
static int pqueue_static_init[$] = '{1};
$display("Process iteration %0d:", i);
pj_auto = pj_auto + 1;
`checkd(pj_auto, 1);
`checkd(p_named.pj_auto, 1);
pj_auto_init = pj_auto_init + 1;
`checkd(pj_auto_init, 11);
`checkd(pqueue_auto.size(), 0);
pqueue_auto.push_back(i + 10);
`checkd(pqueue_auto.size(), 1);
`checkd(pqueue_auto_init.size(), 1);
pqueue_auto_init.push_back(i + 20);
`checkd(pqueue_auto_init.size(), 2);
pj_static = pj_static + 1;
`checkd(pj_static, i + 1);
pj_static_init = pj_static_init + 1;
`checkd(pj_static_init, i + 1 + 10);
pqueue_static.push_back(i + 10);
`checkd(pqueue_static.size(), i + 1);
pqueue_static_init.push_back(i + 20);
`checkd(pqueue_static_init.size(), i + 2);
end
forked();
forked_begin();
$finish;
end
endmodule

View File

@ -135,7 +135,7 @@ C 'ft/t_wrapper_context.vl17n23ttogglepagev_toggle/topocounter[9]:0-
C 'ft/t_wrapper_context.vl17n23ttogglepagev_toggle/topocounter[9]:1->0htop0.top' 0
C 'ft/t_wrapper_context.vl18n16ttogglepagev_toggle/topodone_o:0->1htop0.top' 1
C 'ft/t_wrapper_context.vl18n16ttogglepagev_toggle/topodone_o:1->0htop0.top' 0
C 'ft/t_wrapper_context.vl21n3tlinepagev_line/topoblockS21,24,28,30-32htop0.top' 1
C 'ft/t_wrapper_context.vl21n3tlinepagev_line/topoblockS21-24,28,30-32htop0.top' 1
C 'ft/t_wrapper_context.vl35n3tlinepagev_line/topoblockS35htop0.top' 11
C 'ft/t_wrapper_context.vl36n5tbranchpagev_branch/topoifS36htop0.top' 1
C 'ft/t_wrapper_context.vl36n6tbranchpagev_branch/topoelseS37htop0.top' 10

View File

@ -135,7 +135,7 @@ C 'ft/t_wrapper_context.vl17n23ttogglepagev_toggle/topocounter[9]:0-
C 'ft/t_wrapper_context.vl17n23ttogglepagev_toggle/topocounter[9]:1->0htop1.top' 0
C 'ft/t_wrapper_context.vl18n16ttogglepagev_toggle/topodone_o:0->1htop1.top' 1
C 'ft/t_wrapper_context.vl18n16ttogglepagev_toggle/topodone_o:1->0htop1.top' 0
C 'ft/t_wrapper_context.vl21n3tlinepagev_line/topoblockS21,24,28,30-32htop1.top' 1
C 'ft/t_wrapper_context.vl21n3tlinepagev_line/topoblockS21-24,28,30-32htop1.top' 1
C 'ft/t_wrapper_context.vl35n3tlinepagev_line/topoblockS35htop1.top' 6
C 'ft/t_wrapper_context.vl36n5tbranchpagev_branch/topoifS36htop1.top' 1
C 'ft/t_wrapper_context.vl36n6tbranchpagev_branch/topoelseS37htop1.top' 5