Internals: Cleanup some V3LinkParse code; ignore whitespace if diff. No functional change.
This commit is contained in:
parent
ad6379b762
commit
9e664a3921
|
|
@ -44,13 +44,14 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
// TYPES
|
// TYPES
|
||||||
using ImplTypedefMap = std::map<std::string, AstTypedef*>;
|
using ImplTypedefMap = std::map<std::string, AstTypedef*>;
|
||||||
|
|
||||||
// STATE
|
// STATE - across all visitors
|
||||||
AstVar* m_varp = nullptr; // Variable we're under
|
|
||||||
ImplTypedefMap m_implTypedef; // Created typedefs for each <container,name>
|
|
||||||
std::unordered_set<FileLine*> m_filelines; // Filelines that have been seen
|
std::unordered_set<FileLine*> m_filelines; // Filelines that have been seen
|
||||||
bool m_inAlways = false; // Inside an always
|
|
||||||
AstNodeModule* m_valueModp
|
// STATE - for current visit position (use VL_RESTORER)
|
||||||
= nullptr; // If set, move AstVar->valuep() initial values to this module
|
// If set, move AstVar->valuep() initial values to this module
|
||||||
|
ImplTypedefMap m_implTypedef; // Created typedefs for each <container,name>
|
||||||
|
AstVar* m_varp = nullptr; // Variable we're under
|
||||||
|
AstNodeModule* m_valueModp = nullptr;
|
||||||
AstNodeModule* m_modp = nullptr; // Current module
|
AstNodeModule* m_modp = nullptr; // Current module
|
||||||
AstNodeFTask* m_ftaskp = nullptr; // Current task
|
AstNodeFTask* m_ftaskp = nullptr; // Current task
|
||||||
AstNodeDType* m_dtypep = nullptr; // Current data type
|
AstNodeDType* m_dtypep = nullptr; // Current data type
|
||||||
|
|
@ -61,27 +62,29 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
int m_genblkNum = 0; // Begin block number, 0=none seen
|
int m_genblkNum = 0; // Begin block number, 0=none seen
|
||||||
int m_beginDepth = 0; // How many begin blocks above current node within current AstNodeModule
|
int m_beginDepth = 0; // How many begin blocks above current node within current AstNodeModule
|
||||||
VLifetime m_lifetime = VLifetime::STATIC; // Propagating lifetime
|
VLifetime m_lifetime = VLifetime::STATIC; // Propagating lifetime
|
||||||
|
bool m_inAlways = false; // Inside an always
|
||||||
bool m_insideLoop = false; // True if the node is inside a loop
|
bool m_insideLoop = false; // True if the node is inside a loop
|
||||||
bool m_lifetimeAllowed = false; // True to allow lifetime settings
|
bool m_lifetimeAllowed = false; // True to allow lifetime settings
|
||||||
VDouble0 m_statModules; // Number of modules seen
|
|
||||||
bool m_moduleWithGenericIface = false; // If current module contains generic interface
|
bool m_moduleWithGenericIface = false; // If current module contains generic interface
|
||||||
|
|
||||||
|
// STATE - Statistic tracking
|
||||||
|
VDouble0 m_statModules; // Number of modules seen
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void cleanFileline(AstNode* nodep) {
|
void cleanFileline(AstNode* nodep) {
|
||||||
if (!nodep->user2SetOnce()) { // Process once
|
if (nodep->user2SetOnce()) return; // Process once
|
||||||
// We make all filelines unique per AstNode. This allows us to
|
// We make all filelines unique per AstNode. This allows us to
|
||||||
// later turn off messages on a fileline when an issue is found
|
// later turn off messages on a fileline when an issue is found
|
||||||
// so that messages on replicated blocks occur only once,
|
// so that messages on replicated blocks occur only once,
|
||||||
// without suppressing other token's messages as a side effect.
|
// without suppressing other token's messages as a side effect.
|
||||||
// We could have verilog.l create a new one on every token,
|
// We could have verilog.l create a new one on every token,
|
||||||
// but that's a lot more structures than only doing AST nodes.
|
// but that's a lot more structures than only doing AST nodes.
|
||||||
// TODO: Many places copy the filename when suppressing warnings,
|
// TODO: Many places copy the filename when suppressing warnings,
|
||||||
// perhaps audit to make consistent and this is no longer needed
|
// perhaps audit to make consistent and this is no longer needed
|
||||||
if (m_filelines.find(nodep->fileline()) != m_filelines.end()) {
|
if (m_filelines.find(nodep->fileline()) != m_filelines.end()) {
|
||||||
nodep->fileline(new FileLine{nodep->fileline()});
|
nodep->fileline(new FileLine{nodep->fileline()});
|
||||||
}
|
|
||||||
m_filelines.insert(nodep->fileline());
|
|
||||||
}
|
}
|
||||||
|
m_filelines.insert(nodep->fileline());
|
||||||
}
|
}
|
||||||
|
|
||||||
string nameFromTypedef(AstNode* nodep) {
|
string nameFromTypedef(AstNode* nodep) {
|
||||||
|
|
@ -101,12 +104,11 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitIterateNodeDType(AstNodeDType* nodep) {
|
void visitIterateNodeDType(AstNodeDType* nodep) {
|
||||||
if (!nodep->user1SetOnce()) { // Process only once.
|
if (nodep->user1SetOnce()) return; // Process only once.
|
||||||
cleanFileline(nodep);
|
cleanFileline(nodep);
|
||||||
VL_RESTORER(m_dtypep);
|
VL_RESTORER(m_dtypep);
|
||||||
m_dtypep = nodep;
|
m_dtypep = nodep;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nestedIfBegin(AstBegin* nodep) { // Point at begin inside the GenIf
|
bool nestedIfBegin(AstBegin* nodep) { // Point at begin inside the GenIf
|
||||||
|
|
@ -178,71 +180,69 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
void visit(AstNodeFTask* nodep) override {
|
void visit(AstNodeFTask* nodep) override {
|
||||||
if (!nodep->user1SetOnce()) { // Process only once.
|
if (nodep->user1SetOnce()) return; // Process only once.
|
||||||
// Mark class methods
|
// Mark class methods
|
||||||
if (VN_IS(m_modp, Class)) nodep->classMethod(true);
|
if (VN_IS(m_modp, Class)) nodep->classMethod(true);
|
||||||
|
|
||||||
V3Control::applyFTask(m_modp, nodep);
|
V3Control::applyFTask(m_modp, nodep);
|
||||||
cleanFileline(nodep);
|
cleanFileline(nodep);
|
||||||
VL_RESTORER(m_ftaskp);
|
VL_RESTORER(m_ftaskp);
|
||||||
VL_RESTORER(m_lifetime);
|
VL_RESTORER(m_lifetime);
|
||||||
m_ftaskp = nodep;
|
m_ftaskp = nodep;
|
||||||
VL_RESTORER(m_lifetimeAllowed);
|
VL_RESTORER(m_lifetimeAllowed);
|
||||||
m_lifetimeAllowed = true;
|
m_lifetimeAllowed = true;
|
||||||
if (!nodep->lifetime().isNone()) {
|
if (!nodep->lifetime().isNone()) {
|
||||||
m_lifetime = nodep->lifetime();
|
m_lifetime = nodep->lifetime();
|
||||||
} else {
|
} else {
|
||||||
if (nodep->classMethod()) {
|
if (nodep->classMethod()) {
|
||||||
// Class methods are automatic by default
|
// Class methods are automatic by default
|
||||||
m_lifetime = VLifetime::AUTOMATIC;
|
m_lifetime = VLifetime::AUTOMATIC;
|
||||||
} else if (nodep->dpiImport() || VN_IS(nodep, Property)) {
|
} else if (nodep->dpiImport() || VN_IS(nodep, Property)) {
|
||||||
// DPI-imported functions and properties don't have lifetime specifiers
|
// DPI-imported functions and properties don't have lifetime specifiers
|
||||||
m_lifetime = VLifetime::NONE;
|
m_lifetime = VLifetime::NONE;
|
||||||
}
|
}
|
||||||
nodep->lifetime(m_lifetime);
|
nodep->lifetime(m_lifetime);
|
||||||
for (AstNode* itemp = nodep->stmtsp(); itemp; itemp = itemp->nextp()) {
|
for (AstNode* itemp = nodep->stmtsp(); itemp; itemp = itemp->nextp()) {
|
||||||
AstVar* const varp = VN_CAST(itemp, Var);
|
AstVar* const varp = VN_CAST(itemp, Var);
|
||||||
if (varp && varp->valuep() && varp->lifetime().isNone()
|
if (varp && varp->valuep() && varp->lifetime().isNone()
|
||||||
&& nodep->lifetime().isStatic() && !varp->isIO()) {
|
&& nodep->lifetime().isStatic() && !varp->isIO()) {
|
||||||
if (VN_IS(m_modp, Module)) {
|
if (VN_IS(m_modp, Module)) {
|
||||||
nodep->v3warn(IMPLICITSTATIC,
|
nodep->v3warn(IMPLICITSTATIC,
|
||||||
"Function/task's lifetime implicitly set to static\n"
|
"Function/task's lifetime implicitly set to static\n"
|
||||||
<< nodep->warnMore()
|
<< nodep->warnMore()
|
||||||
<< "... Suggest use 'function automatic' or "
|
<< "... Suggest use 'function automatic' or "
|
||||||
"'function static'\n"
|
"'function static'\n"
|
||||||
<< nodep->warnContextPrimary() << '\n'
|
<< nodep->warnContextPrimary() << '\n'
|
||||||
<< varp->warnOther()
|
<< varp->warnOther()
|
||||||
<< "... Location of implicit static variable\n"
|
<< "... Location of implicit static variable\n"
|
||||||
<< varp->warnContextSecondary() << '\n'
|
<< varp->warnContextSecondary() << '\n'
|
||||||
<< "... Suggest use 'function automatic' or "
|
<< "... Suggest use 'function automatic' or "
|
||||||
"'function static'");
|
"'function static'");
|
||||||
} else {
|
} else {
|
||||||
varp->v3warn(IMPLICITSTATIC,
|
varp->v3warn(IMPLICITSTATIC,
|
||||||
"Variable's lifetime implicitly set to static\n"
|
"Variable's lifetime implicitly set to static\n"
|
||||||
<< nodep->warnMore()
|
<< nodep->warnMore()
|
||||||
<< "... Suggest use 'static' before "
|
<< "... Suggest use 'static' before "
|
||||||
"variable declaration'");
|
"variable declaration'");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nodep->classMethod() && nodep->lifetime().isStatic()) {
|
|
||||||
nodep->v3error("Class function/task cannot be static lifetime ('"
|
|
||||||
<< nodep->verilogKwd() << " static') (IEEE 1800-2023 6.21)\n"
|
|
||||||
<< nodep->warnMore() << "... May have intended 'static "
|
|
||||||
<< nodep->verilogKwd() << "'");
|
|
||||||
}
|
|
||||||
iterateChildren(nodep);
|
|
||||||
}
|
}
|
||||||
|
if (nodep->classMethod() && nodep->lifetime().isStatic()) {
|
||||||
|
nodep->v3error("Class function/task cannot be static lifetime ('"
|
||||||
|
<< nodep->verilogKwd() << " static') (IEEE 1800-2023 6.21)\n"
|
||||||
|
<< nodep->warnMore() << "... May have intended 'static "
|
||||||
|
<< nodep->verilogKwd() << "'");
|
||||||
|
}
|
||||||
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstNodeFTaskRef* nodep) override {
|
void visit(AstNodeFTaskRef* nodep) override {
|
||||||
if (!nodep->user1SetOnce()) { // Process only once.
|
if (nodep->user1SetOnce()) return; // Process only once.
|
||||||
cleanFileline(nodep);
|
cleanFileline(nodep);
|
||||||
UINFO(5, " " << nodep);
|
UINFO(5, " " << nodep);
|
||||||
VL_RESTORER(m_valueModp);
|
VL_RESTORER(m_valueModp);
|
||||||
m_valueModp = nullptr;
|
m_valueModp = nullptr;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void visit(AstNodeDType* nodep) override { visitIterateNodeDType(nodep); }
|
void visit(AstNodeDType* nodep) override { visitIterateNodeDType(nodep); }
|
||||||
void visit(AstConstraint* nodep) override {
|
void visit(AstConstraint* nodep) override {
|
||||||
|
|
@ -673,7 +673,7 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
V3Control::applyCoverageBlock(m_modp, nodep);
|
V3Control::applyCoverageBlock(m_modp, nodep);
|
||||||
cleanFileline(nodep);
|
cleanFileline(nodep);
|
||||||
VL_RESTORER(m_beginDepth);
|
VL_RESTORER(m_beginDepth);
|
||||||
m_beginDepth++;
|
++m_beginDepth;
|
||||||
const AstNode* const backp = nodep->backp();
|
const AstNode* const backp = nodep->backp();
|
||||||
// IEEE says directly nested item is not a new block
|
// IEEE says directly nested item is not a new block
|
||||||
// The genblk name will get attached to the if true/false LOWER begin block(s)
|
// The genblk name will get attached to the if true/false LOWER begin block(s)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue