2021-07-20 17:40:38 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Add common contents to modules
|
|
|
|
|
//
|
|
|
|
|
// Code available from: https://verilator.org
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2025-01-01 14:30:25 +01:00
|
|
|
// Copyright 2003-2025 by Wilson Snyder. This program is free software; you
|
2021-07-20 17:40:38 +02:00
|
|
|
// 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-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
// V3Common's Transformations:
|
|
|
|
|
//
|
|
|
|
|
// Each class:
|
|
|
|
|
// Create string access functions
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
2023-10-18 12:37:46 +02:00
|
|
|
#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT
|
|
|
|
|
|
2021-07-20 17:40:38 +02:00
|
|
|
#include "V3Common.h"
|
2022-08-05 11:56:57 +02:00
|
|
|
|
2021-07-20 17:40:38 +02:00
|
|
|
#include "V3EmitCBase.h"
|
|
|
|
|
|
2022-09-18 21:53:42 +02:00
|
|
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
|
|
|
|
|
2021-07-20 17:40:38 +02:00
|
|
|
//######################################################################
|
|
|
|
|
// Common component builders
|
|
|
|
|
|
2024-10-12 04:37:48 +02:00
|
|
|
string V3Common::makeToStringCall(AstNodeDType* nodep, const std::string& lhs) {
|
|
|
|
|
std::string stmt;
|
|
|
|
|
if (VN_IS(nodep->skipRefp(), BasicDType) && nodep->isWide()) {
|
|
|
|
|
stmt += "VL_TO_STRING_W(";
|
|
|
|
|
stmt += cvtToStr(nodep->widthWords());
|
|
|
|
|
stmt += ", ";
|
|
|
|
|
} else if (VN_IS(nodep->skipRefp(), BasicDType) && nodep->isWide()) {
|
|
|
|
|
stmt += "VL_TO_STRING_W(";
|
|
|
|
|
stmt += cvtToStr(nodep->widthWords());
|
|
|
|
|
stmt += ", ";
|
|
|
|
|
} else {
|
|
|
|
|
stmt += "VL_TO_STRING(";
|
|
|
|
|
}
|
|
|
|
|
stmt += lhs;
|
|
|
|
|
stmt += ")";
|
|
|
|
|
return stmt;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-20 17:40:38 +02:00
|
|
|
static void makeVlToString(AstClass* nodep) {
|
|
|
|
|
AstCFunc* const funcp
|
|
|
|
|
= new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"};
|
2025-08-26 04:05:40 +02:00
|
|
|
funcp->argTypes("const VlClassRef<" + EmitCUtil::prefixNameProtect(nodep) + ">& obj");
|
2021-07-20 17:40:38 +02:00
|
|
|
funcp->isMethod(false);
|
|
|
|
|
funcp->isConst(false);
|
|
|
|
|
funcp->isStatic(false);
|
|
|
|
|
funcp->protect(false);
|
2022-11-13 21:33:11 +01:00
|
|
|
AstNodeExpr* const exprp
|
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.
2025-10-21 13:41:29 +02:00
|
|
|
= new AstCExpr{nodep->fileline(), "obj ? obj->to_string() : \"null\""};
|
2021-07-20 17:40:38 +02:00
|
|
|
exprp->dtypeSetString();
|
|
|
|
|
funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
|
2022-09-15 20:43:56 +02:00
|
|
|
nodep->addStmtsp(funcp);
|
2021-07-20 17:40:38 +02:00
|
|
|
}
|
2022-10-20 12:31:00 +02:00
|
|
|
static void makeVlToString(AstIface* nodep) {
|
|
|
|
|
AstCFunc* const funcp
|
|
|
|
|
= new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"};
|
2025-08-26 04:05:40 +02:00
|
|
|
funcp->argTypes("const " + EmitCUtil::prefixNameProtect(nodep) + "* obj");
|
2022-10-20 12:31:00 +02:00
|
|
|
funcp->isMethod(false);
|
|
|
|
|
funcp->isConst(false);
|
|
|
|
|
funcp->isStatic(false);
|
|
|
|
|
funcp->protect(false);
|
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.
2025-10-21 13:41:29 +02:00
|
|
|
AstNodeExpr* const exprp = new AstCExpr{nodep->fileline(), "obj ? obj->name() : \"null\""};
|
2022-10-20 12:31:00 +02:00
|
|
|
exprp->dtypeSetString();
|
|
|
|
|
funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
|
|
|
|
|
nodep->addStmtsp(funcp);
|
|
|
|
|
}
|
2023-01-28 04:41:12 +01:00
|
|
|
static void makeVlToString(AstNodeUOrStructDType* nodep) {
|
2022-12-21 01:22:42 +01:00
|
|
|
AstNodeModule* const modp = nodep->classOrPackagep();
|
2023-05-07 03:41:17 +02:00
|
|
|
UASSERT_OBJ(modp, nodep, "Unlinked struct package");
|
2022-12-21 01:22:42 +01:00
|
|
|
AstCFunc* const funcp
|
|
|
|
|
= new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"};
|
2025-08-26 04:05:40 +02:00
|
|
|
funcp->argTypes("const " + EmitCUtil::prefixNameProtect(nodep) + "& obj");
|
2022-12-21 01:22:42 +01:00
|
|
|
funcp->isMethod(false);
|
|
|
|
|
funcp->isConst(false);
|
|
|
|
|
funcp->isStatic(false);
|
|
|
|
|
funcp->protect(false);
|
2025-09-26 14:25:47 +02:00
|
|
|
funcp->addStmtsp(new AstCStmt{nodep->fileline(), "std::string out;"});
|
2022-12-21 01:22:42 +01:00
|
|
|
for (const AstMemberDType* itemp = nodep->membersp(); itemp;
|
|
|
|
|
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
|
|
|
|
std::string stmt = "out += \"";
|
|
|
|
|
if (itemp == nodep->membersp()) {
|
|
|
|
|
stmt += "'{";
|
|
|
|
|
} else {
|
|
|
|
|
stmt += ", ";
|
|
|
|
|
}
|
2023-03-04 00:49:26 +01:00
|
|
|
stmt += VIdProtect::protect(itemp->prettyName()) + ":\" + ";
|
2024-10-12 04:37:48 +02:00
|
|
|
stmt += V3Common::makeToStringCall(itemp->dtypep(), "obj."s + itemp->nameProtect());
|
2025-09-26 14:25:47 +02:00
|
|
|
stmt += ";";
|
2022-12-21 01:22:42 +01:00
|
|
|
funcp->addStmtsp(new AstCStmt{nodep->fileline(), stmt});
|
|
|
|
|
}
|
2025-09-26 14:25:47 +02:00
|
|
|
funcp->addStmtsp(new AstCStmt{nodep->fileline(), "out += \"}\";"});
|
|
|
|
|
|
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.
2025-10-21 13:41:29 +02:00
|
|
|
AstCExpr* const exprp = new AstCExpr{nodep->fileline(), "out"};
|
2025-09-26 14:25:47 +02:00
|
|
|
exprp->dtypeSetString();
|
|
|
|
|
funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
|
|
|
|
|
|
2022-12-21 01:22:42 +01:00
|
|
|
modp->addStmtsp(funcp);
|
|
|
|
|
}
|
2021-07-20 17:40:38 +02:00
|
|
|
static void makeToString(AstClass* nodep) {
|
|
|
|
|
AstCFunc* const funcp = new AstCFunc{nodep->fileline(), "to_string", nullptr, "std::string"};
|
|
|
|
|
funcp->isConst(true);
|
|
|
|
|
funcp->isStatic(false);
|
|
|
|
|
funcp->protect(false);
|
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.
2025-10-21 13:41:29 +02:00
|
|
|
AstCExpr* const exprp = new AstCExpr{nodep->fileline(), R"("'{"s + to_string_middle() + "}")"};
|
2021-07-20 17:40:38 +02:00
|
|
|
exprp->dtypeSetString();
|
|
|
|
|
funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
|
2022-09-15 20:43:56 +02:00
|
|
|
nodep->addStmtsp(funcp);
|
2021-07-20 17:40:38 +02:00
|
|
|
}
|
|
|
|
|
static void makeToStringMiddle(AstClass* nodep) {
|
|
|
|
|
AstCFunc* const funcp
|
|
|
|
|
= new AstCFunc{nodep->fileline(), "to_string_middle", nullptr, "std::string"};
|
|
|
|
|
funcp->isConst(true);
|
|
|
|
|
funcp->isStatic(false);
|
|
|
|
|
funcp->protect(false);
|
2025-09-26 14:25:47 +02:00
|
|
|
funcp->addStmtsp(new AstCStmt{nodep->fileline(), "std::string out;"});
|
2021-07-20 17:40:38 +02:00
|
|
|
std::string comma;
|
|
|
|
|
for (AstNode* itemp = nodep->membersp(); itemp; itemp = itemp->nextp()) {
|
2021-11-13 19:50:44 +01:00
|
|
|
if (const auto* const varp = VN_CAST(itemp, Var)) {
|
2024-05-17 16:38:34 +02:00
|
|
|
if (!varp->isParam() && !varp->isInternal()
|
|
|
|
|
&& !(varp->dtypeSkipRefp()->basicp()
|
2025-07-25 12:13:46 +02:00
|
|
|
&& (varp->dtypeSkipRefp()->basicp()->isRandomGenerator()
|
|
|
|
|
|| varp->dtypeSkipRefp()->basicp()->isStdRandomGenerator()))) {
|
2021-07-20 17:40:38 +02:00
|
|
|
string stmt = "out += \"";
|
|
|
|
|
stmt += comma;
|
|
|
|
|
comma = ", ";
|
|
|
|
|
stmt += itemp->origNameProtect();
|
|
|
|
|
stmt += ":\" + ";
|
2024-10-12 04:37:48 +02:00
|
|
|
stmt += V3Common::makeToStringCall(itemp->dtypep(), itemp->nameProtect());
|
2025-09-26 14:25:47 +02:00
|
|
|
stmt += ";";
|
2021-07-20 17:40:38 +02:00
|
|
|
nodep->user1(true); // So what we extend dumps this
|
|
|
|
|
funcp->addStmtsp(new AstCStmt{nodep->fileline(), stmt});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-08-28 16:24:55 +02:00
|
|
|
if (nodep->extendsp()) {
|
2022-08-18 00:08:43 +02:00
|
|
|
string stmt = "out += ";
|
2021-07-20 17:40:38 +02:00
|
|
|
if (!comma.empty()) stmt += "\", \"+ ";
|
|
|
|
|
// comma = ", "; // Nothing further so not needed
|
2025-08-26 04:05:40 +02:00
|
|
|
stmt += EmitCUtil::prefixNameProtect(nodep->extendsp()->dtypep());
|
2025-09-26 14:25:47 +02:00
|
|
|
stmt += "::to_string_middle();";
|
2021-07-20 17:40:38 +02:00
|
|
|
nodep->user1(true); // So what we extend dumps this
|
|
|
|
|
funcp->addStmtsp(new AstCStmt{nodep->fileline(), stmt});
|
|
|
|
|
}
|
2025-09-26 14:25:47 +02:00
|
|
|
|
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.
2025-10-21 13:41:29 +02:00
|
|
|
AstCExpr* const exprp = new AstCExpr{nodep->fileline(), "out"};
|
2025-09-26 14:25:47 +02:00
|
|
|
exprp->dtypeSetString();
|
|
|
|
|
funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
|
|
|
|
|
|
2022-09-15 20:43:56 +02:00
|
|
|
nodep->addStmtsp(funcp);
|
2021-07-20 17:40:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// V3Common class functions
|
|
|
|
|
|
|
|
|
|
void V3Common::commonAll() {
|
2025-05-23 02:29:32 +02:00
|
|
|
UINFO(2, __FUNCTION__ << ":");
|
2022-08-18 00:08:43 +02:00
|
|
|
// NODE STATE
|
|
|
|
|
// Entire netlist:
|
|
|
|
|
// AstClass::user1() -> bool. True if class needs to_string dumper
|
|
|
|
|
const VNUser1InUse m_inuser1;
|
2021-07-20 17:40:38 +02:00
|
|
|
// Create common contents for each module
|
|
|
|
|
for (AstNode* nodep = v3Global.rootp()->modulesp(); nodep; nodep = nodep->nextp()) {
|
|
|
|
|
if (AstClass* const classp = VN_CAST(nodep, Class)) {
|
|
|
|
|
// Create ToString methods
|
|
|
|
|
makeVlToString(classp);
|
|
|
|
|
makeToString(classp);
|
|
|
|
|
makeToStringMiddle(classp);
|
2022-10-20 12:31:00 +02:00
|
|
|
} else if (AstIface* const ifacep = VN_CAST(nodep, Iface)) {
|
|
|
|
|
makeVlToString(ifacep);
|
2021-07-20 17:40:38 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-12-21 01:22:42 +01:00
|
|
|
for (AstNode* nodep = v3Global.rootp()->typeTablep()->typesp(); nodep;
|
|
|
|
|
nodep = nodep->nextp()) {
|
2023-01-28 04:41:12 +01:00
|
|
|
if (AstNodeUOrStructDType* const dtypep = VN_CAST(nodep, NodeUOrStructDType)) {
|
2022-12-21 01:22:42 +01:00
|
|
|
if (!dtypep->packed()) makeVlToString(dtypep);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-01-09 16:35:13 +01:00
|
|
|
V3Global::dumpCheckGlobalTree("common", 0, dumpTreeEitherLevel() >= 3);
|
2021-07-20 17:40:38 +02:00
|
|
|
}
|