Internals: Simplify AstScopeName (#6280)

Reduce reliance on AstText where not necessary.
This commit is contained in:
Geza Lore 2025-10-14 12:08:35 +01:00
parent 0c712d7c60
commit 794247450f
6 changed files with 45 additions and 60 deletions

View File

@ -2060,13 +2060,13 @@ public:
};
class AstScopeName final : public AstNodeExpr {
// For display %m and DPI context imports
// Parents: DISPLAY
// @astgen op1 := scopeAttrp : List[AstText]
// @astgen op2 := scopeEntrp : List[AstText]
// Parents: AstSFormatF, AstNodeFTaskRef, AstNodeFTask
std::string m_scopeAttr;
std::string m_scopeEntr;
bool m_dpiExport = false; // Is for dpiExport
const bool m_forFormat; // Is for a format %m
string scopeNameFormatter(AstText* scopeTextp) const;
string scopePrettyNameFormatter(AstText* scopeTextp) const;
static std::string scopeNameFormatter(const std::string& text);
static std::string scopePrettyNameFormatter(const std::string& text);
public:
class ForFormat {};
@ -2078,28 +2078,32 @@ public:
ASTGEN_MEMBERS_AstScopeName;
bool sameNode(const AstNode* samep) const override {
const AstScopeName* const sp = VN_DBG_AS(samep, ScopeName);
return (m_dpiExport == sp->m_dpiExport && m_forFormat == sp->m_forFormat);
return m_scopeAttr == sp->m_scopeAttr //
&& m_scopeEntr == sp->m_scopeEntr //
&& m_dpiExport == sp->m_dpiExport //
&& m_forFormat == sp->m_forFormat;
}
string emitVerilog() override { return ""; }
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }
void dump(std::ostream& str = std::cout) const override;
void dumpJson(std::ostream& str = std::cout) const override;
string scopeSymName() const { // Name for __Vscope variable including children
return scopeNameFormatter(scopeAttrp());
}
string scopeDpiName() const { // Name for DPI import scope
return scopeNameFormatter(scopeEntrp());
}
string scopePrettySymName() const { // Name for __Vscope variable including children
return scopePrettyNameFormatter(scopeAttrp());
}
string scopePrettyDpiName() const { // Name for __Vscope variable including children
return scopePrettyNameFormatter(scopeEntrp());
}
// ACCESSORS
const std::string& scopeAttr() const { return m_scopeAttr; }
void scopeAttr(const std::string& val) { m_scopeAttr = val; }
const std::string& scopeEntr() const { return m_scopeEntr; }
void scopeEntr(const std::string& val) { m_scopeEntr = val; }
bool dpiExport() const { return m_dpiExport; }
void dpiExport(bool flag) { m_dpiExport = flag; }
bool forFormat() const { return m_forFormat; }
// Name for __Vscope variable including children
string scopeSymName() const { return scopeNameFormatter(m_scopeAttr); }
// Name for DPI import scope
string scopeDpiName() const { return scopeNameFormatter(m_scopeEntr); }
// Name for __Vscope variable including children
string scopePrettySymName() const { return scopePrettyNameFormatter(m_scopeAttr); }
// Name for __Vscope variable including children
string scopePrettyDpiName() const { return scopePrettyNameFormatter(m_scopeEntr); }
};
class AstSelLoopVars final : public AstNodeExpr {
// Parser only concept "[id, id, id]" for a foreach statement

View File

@ -1211,28 +1211,22 @@ AstVarScope* AstScope::createTempLike(const string& name, const AstVarScope* vsc
return createTemp(name, vscp->dtypep());
}
string AstScopeName::scopePrettyNameFormatter(AstText* scopeTextp) const {
string out;
for (AstText* textp = scopeTextp; textp; textp = VN_AS(textp->nextp(), Text)) {
out += textp->text();
}
std::string AstScopeName::scopePrettyNameFormatter(const std::string& text) {
std::string out = text;
// TOP will be replaced by top->name()
if (out.substr(0, 10) == "__DOT__TOP") out.replace(0, 10, "");
if (out.substr(0, 7) == "__DOT__") out.replace(0, 7, "");
if (out.substr(0, 1) == ".") out.replace(0, 1, "");
return AstNode::prettyName(out);
}
string AstScopeName::scopeNameFormatter(AstText* scopeTextp) const {
string out;
for (AstText* textp = scopeTextp; textp; textp = VN_AS(textp->nextp(), Text)) {
out += textp->text();
}
std::string AstScopeName::scopeNameFormatter(const std::string& text) {
std::string out = text;
if (out.substr(0, 10) == "__DOT__TOP") out.replace(0, 10, "");
if (out.substr(0, 7) == "__DOT__") out.replace(0, 7, "");
if (out.substr(0, 1) == ".") out.replace(0, 1, "");
string::size_type pos;
while ((pos = out.find('.')) != string::npos) out.replace(pos, 1, "__");
while ((pos = out.find("__DOT__")) != string::npos) out.replace(pos, 7, "__");
std::string::size_type pos;
while ((pos = out.find('.')) != std::string::npos) out.replace(pos, 1, "__");
while ((pos = out.find("__DOT__")) != std::string::npos) out.replace(pos, 7, "__");
return out;
}
@ -2813,10 +2807,14 @@ void AstScopeName::dump(std::ostream& str) const {
this->AstNodeExpr::dump(str);
if (dpiExport()) str << " [DPIEX]";
if (forFormat()) str << " [FMT]";
str << " scopeAttr=\"" << m_scopeAttr << "\"";
str << " scopeEntr=\"" << m_scopeEntr << "\"";
}
void AstScopeName::dumpJson(std::ostream& str) const {
dumpJsonBoolFunc(str, dpiExport);
dumpJsonBoolFunc(str, forFormat);
dumpJsonStr(str, "scopeAttr", m_scopeAttr);
dumpJsonStr(str, "scopeEntr", m_scopeEntr);
dumpJsonGen(str);
}
void AstSenTree::dump(std::ostream& str) const {

View File

@ -293,14 +293,9 @@ class BeginVisitor final : public VNVisitor {
// Similar code in V3Inline
if (nodep->user1SetOnce()) return; // Don't double-add text's
// DPI svGetScope doesn't include function name, but %m does
const string scname = nodep->forFormat() ? m_displayScope : m_namedScope;
if (!scname.empty()) {
// To keep correct visual order, must add before other Text's
AstText* const afterp = nodep->scopeAttrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->addScopeAttrp(new AstText{nodep->fileline(), "__DOT__"s + scname});
if (afterp) nodep->addScopeAttrp(afterp);
}
const std::string scname = nodep->forFormat() ? m_displayScope : m_namedScope;
// To keep correct visual order, must add before exising
if (!scname.empty()) nodep->scopeAttr("__DOT__"s + scname + nodep->scopeAttr());
iterateChildren(nodep);
}
void visit(AstNodeCoverDecl* nodep) override {

View File

@ -393,15 +393,9 @@ class InlineRelinkVisitor final : public VNVisitor {
void visit(AstScopeName* nodep) override {
// If there's a %m in the display text, we add a special node that will contain the name()
// Similar code in V3Begin
// To keep correct visual order, must add before other Text's
AstText* afterp = nodep->scopeAttrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->addScopeAttrp(new AstText{nodep->fileline(), "__DOT__"s + m_cellp->name()});
if (afterp) nodep->addScopeAttrp(afterp);
afterp = nodep->scopeEntrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->addScopeEntrp(new AstText{nodep->fileline(), "__DOT__"s + m_cellp->name()});
if (afterp) nodep->addScopeEntrp(afterp);
// To keep correct visual order, must add before exising
nodep->scopeAttr("__DOT__" + m_cellp->name() + nodep->scopeAttr());
nodep->scopeEntr("__DOT__" + m_cellp->name() + nodep->scopeEntr());
iterateChildren(nodep);
}
void visit(AstNodeCoverDecl* nodep) override {

View File

@ -291,15 +291,9 @@ class ScopeVisitor final : public VNVisitor {
const string prefix = "__DOT__"s + m_scopep->name();
// TOP and above will be the user's name().
// Note 'TOP.' is stripped by scopePrettyName
// To keep correct visual order, must add before other Text's
AstText* afterp = nodep->scopeAttrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->addScopeAttrp(new AstText{nodep->fileline(), prefix});
if (afterp) nodep->addScopeAttrp(afterp);
afterp = nodep->scopeEntrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->addScopeEntrp(new AstText{nodep->fileline(), prefix});
if (afterp) nodep->addScopeEntrp(afterp);
// To keep correct visual order, must add before existing
nodep->scopeAttr(prefix + nodep->scopeAttr());
nodep->scopeEntr(prefix + nodep->scopeEntr());
iterateChildren(nodep);
}
void visit(AstScope* nodep) override {

View File

@ -1303,8 +1303,8 @@ class TaskVisitor final : public VNVisitor {
if (nodep->dpiExport()) {
AstScopeName* const snp = nodep->scopeNamep();
UASSERT_OBJ(snp, nodep, "Missing scoping context");
snp->dpiExport(
true); // The AstScopeName is really a statement(ish) for tracking, not a function
// The AstScopeName is really a statement(ish) for tracking, not a function
snp->dpiExport(true);
snp->unlinkFrBack();
cfuncp->addInitsp(snp);
}