Internals: Refactor text based Ast constructs (#6280) (#6571)

Remove the large variety of ways raw "text" is represented in the Ast.
Particularly, the only thing that represents a string to be emitted in
the output is AstText.

There are 5 AstNodes that can contain AstText, and V3Emit will throw an
error if an AstText is encountered anywhere else:
- AstCStmt: Internally generated procedural statements involving raw
  text.
- AstCStmtUser: This is the old AstUCStmt, renamed so it sorts next to
  AstCStmt, as it's largely equivalent. We should never create this
  internally unless used to represent user input. It is used for $c,
  statements in the input, and for some 'systemc_* blocks.
- AstCExpr: Internally generaged expression involving raw text.
- AstCExprUser: This is the old AstUCFunc, renamed so it sorts next to
  AstCExpr. It is largely equivalent, but also has more optimizations
  disabled. This should never be created internally, it is only used for
  $c expressions in the input.
- AstTextBlock: Use by V3ProtectLib only, to generate the hierarchical
  wrappers.

Text "tracking" for indentation is always on for AstCStmt, AstCExpr, and
AstTextBlock, as these are always generated by us, and should always be
well formed.

Tracking is always off for AstCStmtUser and AstCExprUser, as these
contain arbitrary user input that might not be safe to parse for
indentation.

Remove subsequently redundant AstNodeSimpleText and AstNodeText types.

This patch also fixes incorrect indentation in emitted waveform tracing
functions, and makes the output more readable for hier block SV stubs.

With that, all raw text nodes are handled as a proper AstNodeStmt or
AstNodeExpr as required for #6280.
This commit is contained in:
Geza Lore
2025-10-21 12:41:29 +01:00
committed by GitHub
parent 14e3448ba6
commit cf275b6e58
36 changed files with 1443 additions and 1409 deletions
+16 -13
View File
@@ -528,19 +528,21 @@ class TraceVisitor final : public VNVisitor {
addInitStr("if (VL_UNLIKELY(!vlSymsp->__Vm_activity)) return;\n");
}
// Register function
std::string str;
AstCStmt* const cstmtp = new AstCStmt{flp};
m_regFuncp->addStmtsp(cstmtp);
if (traceType == VTraceType::CONSTANT) {
str = "tracep->addConstCb(";
cstmtp->add("tracep->addConstCb(");
cstmtp->add(new AstAddrOfCFunc{flp, funcp});
cstmtp->add(", " + std::to_string(funcNum) + ", vlSelf);");
} else if (traceType == VTraceType::FULL) {
str = "tracep->addFullCb(";
cstmtp->add("tracep->addFullCb(");
cstmtp->add(new AstAddrOfCFunc{flp, funcp});
cstmtp->add(", " + std::to_string(funcNum) + ", vlSelf);");
} else {
str = "tracep->addChgCb(";
cstmtp->add("tracep->addChgCb(");
cstmtp->add(new AstAddrOfCFunc{flp, funcp});
cstmtp->add(", " + std::to_string(funcNum) + ", vlSelf);");
}
m_regFuncp->addStmtsp(new AstText{flp, str, true});
m_regFuncp->addStmtsp(new AstAddrOfCFunc{flp, funcp});
m_regFuncp->addStmtsp(new AstText{flp, ", ", true});
m_regFuncp->addStmtsp(new AstConst{flp, funcNum});
m_regFuncp->addStmtsp(new AstText{flp, ", vlSelf);\n", true});
} else {
// Sub functions
funcp->argTypes(bufArg);
@@ -739,10 +741,11 @@ class TraceVisitor final : public VNVisitor {
// Register it
{
AstNode* const argsp = new AstText{fl, "tracep->addCleanupCb(", true};
argsp->addNext(new AstAddrOfCFunc{fl, cleanupFuncp});
argsp->addNext(new AstText{fl, ", vlSelf);"});
m_regFuncp->addStmtsp(new AstCStmt{fl, argsp});
AstCStmt* const cstmtp = new AstCStmt{fl};
m_regFuncp->addStmtsp(cstmtp);
cstmtp->add("tracep->addCleanupCb(");
cstmtp->add(new AstAddrOfCFunc{fl, cleanupFuncp});
cstmtp->add(", vlSelf);");
}
// Clear global activity flag