Generate AstNode accessors via astgen

Introduce the @astgen directives parsed by astgen, currently used for
the generation child node (operand) accessors. Please see the updated
internal documentation for details.
This commit is contained in:
Geza Lore 2022-09-15 19:43:56 +01:00
parent 0a8cfb8d2c
commit ce03293128
70 changed files with 1386 additions and 1530 deletions

View File

@ -96,10 +96,11 @@ this.
Each ``AstNode`` has pointers to up to four children, accessed by the
``op1p`` through ``op4p`` methods. These methods are then abstracted in a
specific Ast\* node class to a more specific name. For example with the
``AstIf`` node (for ``if`` statements), ``ifsp`` calls ``op2p`` to give the
``AstIf`` node (for ``if`` statements), ``thensp`` calls ``op2p`` to give the
pointer to the AST for the "then" block, while ``elsesp`` calls ``op3p`` to
give the pointer to the AST for the "else" block, or NULL if there is not
one.
one. These accessors are automatically generated by ``astgen`` after
parsing the ``@astgen`` directives in the specific ``AstNode`` subclasses.
``AstNode`` has the concept of a next and previous AST - for example the
next and previous statements in a block. Pointers to the AST for these
@ -501,22 +502,99 @@ code:
The ``astgen`` Script
---------------------
Some of the code implementing passes is extremely repetitive, and must be
implemented for each sub-class of ``AstNode``. However, while repetitive,
there is more variability than can be handled in C++ macros.
The ``astgen`` script is used to generate some of the repetitive C++ code
related to the ``AstNode`` type hierarchy. An example is the abstract ``visit``
methods in ``VNVisitor``. There are other uses, please see the ``*__gen*``
files in the bulid directories and the ``astgen`` script itself for details. A
description of the more advanced features of ``astgen`` are provided here.
In Verilator this is implemented by using a script, ``astgen`` to
pre-process the C++ code. For example in ``V3Const.cpp`` this is used to
implement the ``visit()`` functions for each binary operation using the
``TREEOP`` macro.
The original C source code is transformed into C code in the ``obj_opt``
Generating ``AstNode`` members
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Some of the member s of ``AstNode`` sub-classes are generated by ``astgen``.
These are emitted as pre-processor macro definitions, which then need to be
added to the ``AstNode`` sub-classes they correspond to. Specifically ``class
AstFoo`` should contain an instance of ``ASTGEN_MEMBERS_Foo;`` at class scope.
The ``astgen`` script checks and errors if this is not present. The method
generated depends on whether the class is a concrete final class, or an
abstract ``AstNode*`` base-class, and on ``@astgen`` directives present in
comment sections in the body of the ``AstNode`` sub-class definitions.
List of ``@astgen`` directives
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``@astgen`` directives in comments contained in the body of ``AstNode``
sub-class definitions are parsed and contribute to the code generated by
``astgen``. The general syntax is ``@astgen <keywords> := <description>``,
where ``<keywords>`` determines what is being defined, and ``<description>`` is
a ``<keywords>`` dependent description of the definition. The list of
``@astgen`` directives is as follows:
``op<N>`` operand directives
"""""""""""""""""""""""""""""
The ``op1``, ``op2``, ``op3`` and ``op4`` directives are used to describe the
name and type of the up to 4 child operands of a node. The syntax of the
``<description>`` field is ``<identifier> : <type>``, where ``<identifier>``
will be used as the base name of the generated operand accessors, and
``<type>`` is one of:
1. An ``AstNode`` sub-class, defining the operand to be of that type, always
no-null, and with an always null ``nextp()``. That is, the child node is
always present, and is a single ``AstNode`` (as opposed to a list).
2. ``Optional[<AstNode sub-class>]``. This is just like in point 1 above, but
defines the child node to be optional, meaning it may be null.
3. ``List[AstNode sub-class]`` describes a list operand, which means the child
node may have a non-null ``nextp()`` and in addition the child itself may be
null, representing an empty list.
An example of the full syntax of the directive is
``@astgen op1 := lhsp : AstNodeMath``.
``astnode`` generates accessors for the child nodes based on these directives.
For non-list children, the names of the getter and setter both are that of the
given ``<identifier>``. For list type children, the getter is ``<identifier>``,
and instead of the setter, there an ``add<Identifier>`` method is generated
that appends new nodes (or lists of nodes) to the child list.
``alias op<N>`` operand alias directives
""""""""""""""""""""""""""""""""""""""""
If a super-class already defined a name and type for a child node using the
``op<N>`` directive, but a more appropriate name exists in the context of a
sub-class, then the alias directive can be used to introduce an additional name
for the child node. The is ``alias op<N> := <identifier>`` where
``<identifier>`` is the new name. ``op<N>`` must have been defined in some
super-class of the current node.
Example: ``@astgen alias op1 := condp``
Additional features of ``astgen``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In addition to generating ``AstNode`` members as described above,
``astgen`` is also use to handle some of the repetitive implementation code
that is still variable enough not to be handled in C++ macros.
In particular, ``astgen`` is used to pre-process some of the C++ source
files. For example in ``V3Const.cpp``, it is used to implement the
``visit()`` functions for each binary operation using the ``TREEOP`` macro.
The original C++ source code is transformed into C++ code in the ``obj_opt``
and ``obj_dbg`` sub-directories (the former for the optimized version of
Verilator, the latter for the debug version). So for example
``V3Const.cpp`` into ``V3Const__gen.cpp``.
Visitor Functions -----------------
Visitor Functions
-----------------
Verilator uses the "Visitor" design pattern to implement its refinement and
optimization passes. This allows separation of the pass algorithm from the

View File

@ -216,7 +216,7 @@ private:
// METHODS
void addActive(AstActive* nodep) {
UASSERT_OBJ(m_scopep, nodep, "nullptr scope");
m_scopep->addActivep(nodep);
m_scopep->addBlocksp(nodep);
}
// VISITORS
void visit(AstScope* nodep) override {
@ -302,7 +302,7 @@ private:
LatchDetectGraphVertex* const parentp = m_graph.currentp();
LatchDetectGraphVertex* const branchp = m_graph.addPathVertex(parentp, "BRANCH", true);
m_graph.addPathVertex(branchp, "IF");
iterateAndNextNull(nodep->ifsp());
iterateAndNextNull(nodep->thensp());
m_graph.addPathVertex(branchp, "ELSE");
iterateAndNextNull(nodep->elsesp());
m_graph.currentp(parentp);
@ -458,7 +458,7 @@ private:
void visit(AstFinal* nodep) override {
// Relink to CFUNC for the final
UINFO(4, " FINAL " << nodep << endl);
if (!nodep->bodysp()) { // Empty, Kill it.
if (!nodep->stmtsp()) { // Empty, Kill it.
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
@ -471,10 +471,10 @@ private:
m_scopeFinalp->isStatic(false);
m_scopeFinalp->isLoose(true);
m_scopeFinalp->slow(true);
m_namer.scopep()->addActivep(m_scopeFinalp);
m_namer.scopep()->addBlocksp(m_scopeFinalp);
}
nodep->unlinkFrBack();
m_scopeFinalp->addStmtsp(nodep->bodysp()->unlinkFrBackWithNext());
m_scopeFinalp->addStmtsp(nodep->stmtsp()->unlinkFrBackWithNext());
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
@ -542,7 +542,7 @@ private:
UINFO(4, " ALW " << nodep << endl);
// if (debug() >= 9) nodep->dumpTree(cout, " Alw: ");
if (!nodep->bodysp()) {
if (!nodep->stmtsp()) {
// Empty always. Kill it.
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
@ -551,7 +551,7 @@ private:
}
void visit(AstAlwaysPostponed* nodep) override {
UINFO(4, " ALW " << nodep << endl);
if (!nodep->bodysp()) {
if (!nodep->stmtsp()) {
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}

View File

@ -70,7 +70,7 @@ private:
if (!m_monitorNumVarp) {
m_monitorNumVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__VmonitorNum",
nodep->findUInt64DType()};
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorNumVarp);
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(m_monitorNumVarp);
}
const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorNumVarp, access);
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
@ -80,7 +80,7 @@ private:
if (!m_monitorOffVarp) {
m_monitorOffVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__VmonitorOff",
nodep->findBitDType()};
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorOffVarp);
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(m_monitorOffVarp);
}
const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorOffVarp, access);
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
@ -147,7 +147,7 @@ private:
selfDestruct = true;
} else {
// V3Coverage assigned us a bucket to increment.
AstCoverInc* const covincp = VN_AS(snodep->coverincp(), CoverInc);
AstCoverInc* const covincp = VN_AS(snodep->coverincsp(), CoverInc);
UASSERT_OBJ(covincp, snodep, "Missing AstCoverInc under assertion");
covincp->unlinkFrBackWithNext(); // next() might have AstAssign for trace
if (message != "") covincp->declp()->comment(message);
@ -209,7 +209,7 @@ private:
iterateAndNextNull(ifp->condp());
// Recurse into the true case.
iterateAndNextNull(ifp->ifsp());
iterateAndNextNull(ifp->thensp());
// If the last else is not an else if, recurse into that too.
if (ifp->elsesp() && !nextifp) { //
@ -338,15 +338,15 @@ private:
sentreep->unlinkFrBack();
AstAlways* const alwaysp
= new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, nullptr);
m_modp->addStmtp(alwaysp);
m_modp->addStmtsp(alwaysp);
for (uint32_t i = 0; i < ticks; ++i) {
AstVar* const outvarp = new AstVar(
nodep->fileline(), VVarType::MODULETEMP,
"_Vpast_" + cvtToStr(m_modPastNum++) + "_" + cvtToStr(i), inp->dtypep());
m_modp->addStmtp(outvarp);
m_modp->addStmtsp(outvarp);
AstNode* const assp = new AstAssignDly(
nodep->fileline(), new AstVarRef(nodep->fileline(), outvarp, VAccess::WRITE), inp);
alwaysp->addStmtp(assp);
alwaysp->addStmtsp(assp);
// if (debug() >= 9) assp->dumpTree(cout, "-ass: ");
invarp = outvarp;
inp = new AstVarRef(nodep->fileline(), invarp, VAccess::READ);
@ -387,7 +387,7 @@ private:
stmtsp};
ifp->branchPred(VBranchPred::BP_UNLIKELY);
AstNode* const newp = new AstAlwaysPostponed{fl, ifp};
m_modp->addStmtp(newp);
m_modp->addStmtsp(newp);
} else if (nodep->displayType() == VDisplayType::DT_STROBE) {
nodep->displayType(VDisplayType::DT_DISPLAY);
// Need one-shot
@ -395,7 +395,7 @@ private:
const auto varp
= new AstVar{fl, VVarType::MODULETEMP, "__Vstrobe" + cvtToStr(m_modStrobeNum++),
nodep->findBitDType()};
m_modp->addStmtp(varp);
m_modp->addStmtsp(varp);
// Where $strobe was we do "__Vstrobe = '1;"
const auto newsetp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
new AstConst{fl, AstConst::BitTrue{}}};
@ -407,7 +407,7 @@ private:
AstNode* const newp = new AstAlwaysPostponed{fl, ifp};
stmtsp->addNext(new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
new AstConst{fl, AstConst::BitFalse{}}});
m_modp->addStmtp(newp);
m_modp->addStmtsp(newp);
}
}
void visit(AstMonitorOff* nodep) override {

View File

@ -84,7 +84,7 @@ private:
void visit(AstAlways* nodep) override {
iterateAndNextNull(nodep->sensesp());
if (nodep->sensesp()) m_seniAlwaysp = nodep->sensesp()->sensesp();
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
m_seniAlwaysp = nullptr;
}

View File

@ -61,7 +61,6 @@ bool AstNode::sameGateTree(const AstNode* node2p) const {
return sameTreeIter(this, node2p, true, true);
}
void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); }
int AstNodeArrayDType::left() const { return rangep()->leftConst(); }
int AstNodeArrayDType::right() const { return rangep()->rightConst(); }
int AstNodeArrayDType::hi() const { return rangep()->hiConst(); }
@ -71,13 +70,13 @@ VNumRange AstNodeArrayDType::declRange() const { return VNumRange{left(), right(
AstRange::AstRange(FileLine* fl, int left, int right)
: ASTGEN_SUPER_Range(fl) {
setOp2p(new AstConst{fl, static_cast<uint32_t>(left)});
setOp3p(new AstConst{fl, static_cast<uint32_t>(right)});
leftp(new AstConst{fl, static_cast<uint32_t>(left)});
rightp(new AstConst{fl, static_cast<uint32_t>(right)});
}
AstRange::AstRange(FileLine* fl, const VNumRange& range)
: ASTGEN_SUPER_Range(fl) {
setOp2p(new AstConst{fl, static_cast<uint32_t>(range.left())});
setOp3p(new AstConst{fl, static_cast<uint32_t>(range.right())});
leftp(new AstConst{fl, static_cast<uint32_t>(range.left())});
rightp(new AstConst{fl, static_cast<uint32_t>(range.right())});
}
int AstRange::leftConst() const {
AstConst* const constp = VN_CAST(leftp(), Const);
@ -97,7 +96,7 @@ AstPin::AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp)
: ASTGEN_SUPER_Pin(fl)
, m_pinNum{pinNum}
, m_name{varname->name()} {
setNOp1p(exprp);
this->exprp(exprp);
}
AstDpiExportUpdated::AstDpiExportUpdated(FileLine* fl, AstVarScope* varScopep)
@ -112,7 +111,7 @@ AstPackArrayDType::AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType
: ASTGEN_SUPER_PackArrayDType(fl) {
childDTypep(dtp); // Only for parser
refDTypep(nullptr);
setOp2p(rangep);
this->rangep(rangep);
dtypep(nullptr); // V3Width will resolve
const int width = subDTypep()->width() * rangep->elementsConst();
widthForce(width, width);
@ -120,7 +119,7 @@ AstPackArrayDType::AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType
AstPackArrayDType::AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep)
: ASTGEN_SUPER_PackArrayDType(fl) {
refDTypep(dtp);
setOp2p(rangep);
this->rangep(rangep);
dtypep(this);
const int width = subDTypep()->width() * rangep->elementsConst();
widthForce(width, width);
@ -141,20 +140,20 @@ bool AstActive::hasClocked() const { return m_sensesp->hasClocked(); }
AstElabDisplay::AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNode* exprsp)
: ASTGEN_SUPER_ElabDisplay(fl) {
setOp1p(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp});
addFmtp(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp});
m_displayType = dispType;
}
AstCStmt::AstCStmt(FileLine* fl, const string& textStmt)
: ASTGEN_SUPER_CStmt(fl) {
addNOp1p(new AstText{fl, textStmt, true});
addExprsp(new AstText{fl, textStmt, true});
}
AstCMath::AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut)
: ASTGEN_SUPER_CMath(fl)
, m_cleanOut{cleanOut}
, m_pure{true} {
addNOp1p(new AstText{fl, textStmt, true});
addExprsp(new AstText{fl, textStmt, true});
if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
}

View File

@ -132,11 +132,13 @@ private:
};
class AstNodeArrayDType VL_NOT_FINAL : public AstNodeDType {
// Array data type, ie "some_dtype var_name [2:0]"
// Children: DTYPE (moved to refDTypep() in V3Width)
// Children: RANGE (array bounds)
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
// @astgen op2 := rangep : Optional[AstRange] // array bounds
private:
AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing)
AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable
AstNode* rangenp() const { return reinterpret_cast<AstNode*>(rangep()); }
protected:
AstNodeArrayDType(VNType t, FileLine* fl)
: AstNodeDType{t, fl} {}
@ -165,14 +167,10 @@ public:
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()));
}
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
AstRange* rangep() const { return VN_AS(op2p(), Range); } // op2 = Array(s) of variable
inline void rangep(AstRange* nodep);
// METHODS
AstBasicDType* basicp() const override {
return subDTypep()->basicp();
@ -193,6 +191,7 @@ public:
};
class AstNodeUOrStructDType VL_NOT_FINAL : public AstNodeDType {
// A struct or union; common handling
// @astgen op1 := membersp : List[AstMemberDType]
private:
// TYPES
using MemberNameMap = std::map<const std::string, AstMemberDType*>;
@ -233,16 +232,11 @@ public:
int widthAlignBytes() const override;
// (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
int widthTotalBytes() const override;
// op1 = members
bool similarDType(AstNodeDType* samep) const override {
return this == samep; // We don't compare members, require exact equivalence
}
string name() const override { return m_name; }
void name(const string& flag) override { m_name = flag; }
AstMemberDType* membersp() const {
return VN_AS(op1p(), MemberDType);
} // op1 = AstMember list
void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
bool packed() const { return m_packed; }
// packed() but as don't support unpacked, presently all structs
static bool packedUnsup() { return true; }
@ -263,33 +257,31 @@ public:
// === AstNode ===
class AstEnumItem final : public AstNode {
// @astgen op1 := rangep : Optional[AstRange] // Range for name appending
// @astgen op2 := valuep : Optional[AstNode]
private:
string m_name;
public:
// Parents: ENUM
AstEnumItem(FileLine* fl, const string& name, AstNode* rangep, AstNode* initp)
AstEnumItem(FileLine* fl, const string& name, AstRange* rangep, AstNode* valuep)
: ASTGEN_SUPER_EnumItem(fl)
, m_name{name} {
addNOp1p(rangep);
addNOp2p(initp);
this->rangep(rangep);
this->valuep(valuep);
}
ASTGEN_MEMBERS_EnumItem;
string name() const override { return m_name; }
bool maybePointedTo() const override { return true; }
bool hasDType() const override { return true; }
void name(const string& flag) override { m_name = flag; }
AstRange* rangep() const { return VN_AS(op1p(), Range); } // op1 = Range for name appending
void rangep(AstRange* nodep) { addOp1p((AstNode*)nodep); }
AstNode* valuep() const { return op2p(); } // op2 = Value
void valuep(AstNode* nodep) { addOp2p(nodep); }
};
// === AstNodeDType ===
class AstAssocArrayDType final : public AstNodeDType {
// Associative array data type, ie "[some_dtype]"
// Children: DTYPE (moved to refDTypep() in V3Width)
// Children: DTYPE (the key, which remains here as a pointer)
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
// @astgen op2 := keyChildDTypep : AstNodeDType // the key, which remains here as a pointer
private:
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
AstNodeDType* m_keyDTypep; // Keys of this type (after widthing)
@ -335,9 +327,6 @@ public:
void dumpSmall(std::ostream& str) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* getChild2DTypep() const override { return keyChildDTypep(); }
// op1 = Range of variable
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
@ -347,9 +336,6 @@ public:
//
AstNodeDType* keyDTypep() const { return m_keyDTypep ? m_keyDTypep : keyChildDTypep(); }
void keyDTypep(AstNodeDType* nodep) { m_keyDTypep = nodep; }
// op1 = Range of variable
AstNodeDType* keyChildDTypep() const { return VN_AS(op2p(), NodeDType); }
void keyChildDTypep(AstNodeDType* nodep) { setOp2p(nodep); }
// METHODS
AstBasicDType* basicp() const override { return nullptr; }
AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
@ -361,7 +347,7 @@ public:
};
class AstBasicDType final : public AstNodeDType {
// Builtin atomic/vectored data type
// Children: RANGE (converted to constant in V3Width)
// @astgen op1 := rangep : Optional[AstRange] // Range of variable
private:
struct Members {
VBasicDTypeKwd m_keyword; // (also in VBasicTypeKey) What keyword created basic type
@ -415,8 +401,6 @@ public:
BROKEN_RTN(dtypep() != this);
return nullptr;
}
AstRange* rangep() const { return VN_AS(op1p(), Range); } // op1 = Range of variable
void rangep(AstRange* nodep) { setNOp1p((AstNode*)nodep); }
void setSignedState(const VSigning& signst) {
// Note NOSIGN does NOT change the state; this is required by the parser
if (signst == VSigning::UNSIGNED) {
@ -470,21 +454,18 @@ public:
class AstBracketArrayDType final : public AstNodeDType {
// Associative/Queue/Normal array data type, ie "[dtype_or_expr]"
// only for early parsing then becomes another data type
// Children: DTYPE (moved to refDTypep() in V3Width)
// Children: DTYPE (the key)
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
// @astgen op2 := elementsp : AstNode // ??? key dtype ???
public:
AstBracketArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* elementsp)
AstBracketArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* childDTypep,
AstNode* elementsp)
: ASTGEN_SUPER_BracketArrayDType(fl) {
setOp1p(dtp); // Only for parser
setOp2p(elementsp); // Only for parser
this->childDTypep(childDTypep);
this->elementsp(elementsp);
}
ASTGEN_MEMBERS_BracketArrayDType;
bool similarDType(AstNodeDType* samep) const override { V3ERROR_NA_RETURN(false); }
// op1 = Range of variable
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
AstNodeDType* subDTypep() const override { return childDTypep(); }
// op2 = Range of variable
AstNode* elementsp() const { return op2p(); }
// METHODS
// Will be removed in V3Width, which relies on this
// being a child not a dtype pointed node
@ -499,16 +480,16 @@ public:
};
class AstClassRefDType final : public AstNodeDType {
// Reference to a class
// Children: PINs (for parameter settings)
// @astgen op1 := paramsp: List[AstPin]
private:
AstClass* m_classp; // data type pointed to, BELOW the AstTypedef
AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy
public:
AstClassRefDType(FileLine* fl, AstClass* classp, AstNode* paramsp)
AstClassRefDType(FileLine* fl, AstClass* classp, AstPin* paramsp)
: ASTGEN_SUPER_ClassRefDType(fl)
, m_classp{classp} {
dtypep(this);
addNOp4p(paramsp);
this->dtypep(this);
this->addParamsp(paramsp);
}
ASTGEN_MEMBERS_ClassRefDType;
// METHODS
@ -537,13 +518,13 @@ public:
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
AstClass* classp() const { return m_classp; }
void classp(AstClass* nodep) { m_classp = nodep; }
AstPin* paramsp() const { return VN_AS(op4p(), Pin); }
bool isCompound() const override { return true; }
};
class AstConstDType final : public AstNodeDType {
// const data type, ie "const some_dtype var_name [2:0]"
// ConstDType are removed in V3LinkLValue and become AstVar::isConst.
// When more generic types are supported AstConstDType will be propagated further.
// @astgen op1 := childDTypep : Optional[AstNodeDType]
private:
AstNodeDType* m_refDTypep = nullptr; // Inherit from this base data type
public:
@ -571,9 +552,6 @@ public:
return skipRefp()->similarDType(samep->skipRefp());
}
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Range of variable
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
@ -594,6 +572,7 @@ class AstDefImplicitDType final : public AstNodeDType {
// For parsing enum/struct/unions that are declared with a variable rather than typedef
// This allows "var enum {...} a,b" to share the enum definition for both variables
// After link, these become typedefs
// @astgen op1 := childDTypep : Optional[AstNodeDType]
private:
string m_name;
void* m_containerp; // In what scope is the name unique, so we can know what are duplicate
@ -620,9 +599,6 @@ public:
return type() == samep->type() && same(samep);
}
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Range of variable
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const override { return dtypep() ? dtypep() : childDTypep(); }
void* containerp() const { return m_containerp; }
// METHODS
@ -640,7 +616,7 @@ public:
};
class AstDynArrayDType final : public AstNodeDType {
// Dynamic array data type, ie "[]"
// Children: DTYPE (moved to refDTypep() in V3Width)
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
private:
AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing)
public:
@ -677,9 +653,6 @@ public:
string prettyDTypeName() const override;
void dumpSmall(std::ostream& str) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Range of variable
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
@ -722,19 +695,20 @@ public:
};
class AstEnumDType final : public AstNodeDType {
// Parents: TYPEDEF/MODULE
// Children: ENUMVALUEs
// @astgen op1 := childDTypep : Optional[AstNodeDType]
// @astgen op2 := itemsp : List[AstEnumItem]
private:
string m_name; // Name from upper typedef, if any
AstNodeDType* m_refDTypep = nullptr; // Elements are of this type after V3Width
const int m_uniqueNum = 0;
public:
AstEnumDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* itemsp)
AstEnumDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstEnumItem* itemsp)
: ASTGEN_SUPER_EnumDType(fl)
, m_uniqueNum{uniqueNumInc()} {
childDTypep(dtp); // Only for parser
refDTypep(nullptr);
addNOp2p(itemsp);
addItemsp(itemsp);
dtypep(nullptr); // V3Width will resolve
widthFromSub(subDTypep());
}
@ -754,16 +728,12 @@ public:
}
bool similarDType(AstNodeDType* samep) const override { return this == samep; }
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } // op1 = Data type
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
// op1 = Range of variable
AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
string name() const override { return m_name; }
void name(const string& flag) override { m_name = flag; }
AstEnumItem* itemsp() const { return VN_AS(op2p(), EnumItem); } // op2 = AstEnumItem's
// METHODS
AstBasicDType* basicp() const override { return subDTypep()->basicp(); }
AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); }
@ -835,6 +805,7 @@ public:
class AstMemberDType final : public AstNodeDType {
// A member of a struct/union
// PARENT: AstNodeUOrStructDType
// @astgen op1 := childDTypep : Optional[AstNodeDType]
private:
AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing)
string m_name; // Name of variable
@ -869,9 +840,6 @@ public:
if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep();
}
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Range of variable
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
@ -904,6 +872,7 @@ public:
class AstParamTypeDType final : public AstNodeDType {
// Parents: MODULE
// A parameter type statement; much like a var or typedef
// @astgen op1 := childDTypep : Optional[AstNodeDType]
private:
const VVarType m_varType; // Type of variable (for localparam vs. param)
string m_name; // Name of variable
@ -918,9 +887,6 @@ public:
}
ASTGEN_MEMBERS_ParamTypeDType;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Type assigning to
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const override { return dtypep() ? dtypep() : childDTypep(); }
AstBasicDType* basicp() const override { return subDTypep()->basicp(); }
AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); }
@ -972,20 +938,21 @@ public:
};
class AstQueueDType final : public AstNodeDType {
// Queue array data type, ie "[ $ ]"
// Children: DTYPE (moved to refDTypep() in V3Width)
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
// @astgen op2 := boundp : Optional[AstNode]
private:
AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing)
public:
AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* boundp)
: ASTGEN_SUPER_QueueDType(fl) {
setNOp2p(boundp);
childDTypep(dtp); // Only for parser
this->childDTypep(dtp);
this->boundp(boundp);
refDTypep(nullptr);
dtypep(nullptr); // V3Width will resolve
}
AstQueueDType(FileLine* fl, AstNodeDType* dtp, AstNode* boundp)
: ASTGEN_SUPER_QueueDType(fl) {
setNOp2p(boundp);
this->boundp(boundp);
refDTypep(dtp);
dtypep(dtp);
}
@ -1011,13 +978,8 @@ public:
void dumpSmall(std::ostream& str) const override;
string prettyDTypeName() const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Range of variable
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNode* boundp() const { return op2p(); } // op2 = Bound, nullptr = none
void boundp(AstNode* nodep) { setNOp2p(nodep); }
inline int boundConst() const;
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
@ -1034,6 +996,9 @@ public:
bool isCompound() const override { return true; }
};
class AstRefDType final : public AstNodeDType {
// @astgen op1 := typeofp : AstNode
// @astgen op2 := classOrPackageOpp : Optional[AstNode]
// @astgen op3 := paramsp : List[AstPin]
private:
// Pre-Width must reference the Typeref, not what it points to, as some child
// types like AstBracketArrayType will disappear and can't lose the handle
@ -1046,16 +1011,16 @@ public:
AstRefDType(FileLine* fl, const string& name)
: ASTGEN_SUPER_RefDType(fl)
, m_name{name} {}
AstRefDType(FileLine* fl, const string& name, AstNode* classOrPackagep, AstNode* paramsp)
AstRefDType(FileLine* fl, const string& name, AstNode* classOrPackagep, AstPin* paramsp)
: ASTGEN_SUPER_RefDType(fl)
, m_name{name} {
setNOp3p(classOrPackagep);
addNOp4p(paramsp);
this->classOrPackageOpp(classOrPackagep);
addParamsp(paramsp);
}
class FlagTypeOfExpr {}; // type(expr) for parser only
AstRefDType(FileLine* fl, FlagTypeOfExpr, AstNode* typeofp)
: ASTGEN_SUPER_RefDType(fl) {
setOp2p(typeofp);
this->typeofp(typeofp);
}
ASTGEN_MEMBERS_RefDType;
// METHODS
@ -1106,7 +1071,6 @@ public:
int widthAlignBytes() const override { return dtypeSkipRefp()->widthAlignBytes(); }
int widthTotalBytes() const override { return dtypeSkipRefp()->widthTotalBytes(); }
void name(const string& flag) override { m_name = flag; }
// op1 = Range of variable
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
AstTypedef* typedefp() const { return m_typedefp; }
void typedefp(AstTypedef* nodep) { m_typedefp = nodep; }
@ -1116,9 +1080,6 @@ public:
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
AstNode* typeofp() const { return op2p(); }
AstNode* classOrPackageOpp() const { return op3p(); }
AstPin* paramsp() const { return VN_AS(op4p(), Pin); }
bool isCompound() const override {
v3fatalSrc("call isCompound on subdata type, not reference");
return false;
@ -1126,7 +1087,7 @@ public:
};
class AstUnsizedArrayDType final : public AstNodeDType {
// Unsized/open-range Array data type, ie "some_dtype var_name []"
// Children: DTYPE (moved to refDTypep() in V3Width)
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
private:
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
public:
@ -1149,9 +1110,6 @@ public:
bool similarDType(AstNodeDType* samep) const override;
void dumpSmall(std::ostream& str) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Range of variable
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
@ -1194,7 +1152,7 @@ public:
};
class AstWildcardArrayDType final : public AstNodeDType {
// Wildcard index type associative array data type, ie "some_dtype var_name [*]"
// Children: DTYPE (moved to refDTypep() in V3Width)
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
private:
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
public:
@ -1217,9 +1175,6 @@ public:
bool similarDType(AstNodeDType* samep) const override;
void dumpSmall(std::ostream& str) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Range of variable
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
@ -1237,8 +1192,6 @@ public:
// === AstNodeArrayDType ===
class AstPackArrayDType final : public AstNodeArrayDType {
// Packed array data type, ie "some_dtype [2:0] var_name"
// Children: DTYPE (moved to refDTypep() in V3Width)
// Children: RANGE (array bounds)
public:
inline AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep);
inline AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep);
@ -1248,15 +1201,13 @@ public:
};
class AstUnpackArrayDType final : public AstNodeArrayDType {
// Array data type, ie "some_dtype var_name [2:0]"
// Children: DTYPE (moved to refDTypep() in V3Width)
// Children: RANGE (array bounds)
bool m_isCompound = false; // Non-POD subDType, or parent requires compound
public:
AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep)
: ASTGEN_SUPER_UnpackArrayDType(fl) {
childDTypep(dtp); // Only for parser
this->childDTypep(dtp); // Only for parser
this->rangep(rangep);
refDTypep(nullptr);
setOp2p((AstNode*)rangep);
dtypep(nullptr); // V3Width will resolve
// For backward compatibility AstNodeArrayDType and others inherit
// width and signing from the subDType/base type
@ -1264,8 +1215,8 @@ public:
}
AstUnpackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep)
: ASTGEN_SUPER_UnpackArrayDType(fl) {
this->rangep(rangep);
refDTypep(dtp);
setOp2p((AstNode*)rangep);
dtypep(this);
// For backward compatibility AstNodeArrayDType and others inherit
// width and signing from the subDType/base type

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -188,8 +188,8 @@ void AstBasicDType::init(VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int
widthForce(rangep->elementsConst(),
rangep->elementsConst()); // Maybe unknown if parameters underneath it
}
setNOp1p(rangep);
dtypep(this);
this->rangep(rangep);
this->dtypep(this);
}
void AstBasicDType::cvtRangeConst() {
@ -660,25 +660,15 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) {
} else {
return nullptr;
}
} else if (VN_IS(nodep, VarRef)) {
if (VN_AS(nodep, VarRef)->varp()->isSc()) {
return VN_AS(nodep, VarRef)->varp();
} else if (AstVarRef* const vrefp = VN_CAST(nodep, VarRef)) {
if (vrefp->varp()->isSc()) {
return vrefp->varp();
} else {
return nullptr;
}
} else if (VN_IS(nodep, ArraySel)) {
if (nodep->op1p()) {
if (AstVar* p = scVarRecurse(nodep->op1p())) return p;
}
if (nodep->op2p()) {
if (AstVar* p = scVarRecurse(nodep->op2p())) return p;
}
if (nodep->op3p()) {
if (AstVar* p = scVarRecurse(nodep->op3p())) return p;
}
if (nodep->op4p()) {
if (AstVar* p = scVarRecurse(nodep->op4p())) return p;
}
} else if (AstArraySel* const arraySelp = VN_CAST(nodep, ArraySel)) {
if (AstVar* const p = scVarRecurse(arraySelp->fromp())) return p;
if (AstVar* const p = scVarRecurse(arraySelp->bitp())) return p;
}
return nullptr;
}
@ -1070,8 +1060,8 @@ AstConstPool::AstConstPool(FileLine* fl)
: ASTGEN_SUPER_ConstPool(fl)
, m_modp{new AstModule(fl, "@CONST-POOL@")}
, m_scopep{new AstScope(fl, m_modp, "@CONST-POOL@", nullptr, nullptr)} {
addOp1p(m_modp);
m_modp->addStmtp(m_scopep);
this->modulep(m_modp);
m_modp->addStmtsp(m_scopep);
}
const char* AstConstPool::broken() const {
BROKEN_RTN(m_modp && !m_modp->brokeExists());
@ -1085,9 +1075,9 @@ AstVarScope* AstConstPool::createNewEntry(const string& name, AstNode* initp) {
varp->isConst(true);
varp->isStatic(true);
varp->valuep(initp->cloneTree(false));
m_modp->addStmtp(varp);
m_modp->addStmtsp(varp);
AstVarScope* const varScopep = new AstVarScope(fl, m_scopep, varp);
m_scopep->addVarp(varScopep);
m_scopep->addVarsp(varScopep);
return varScopep;
}
@ -1233,7 +1223,7 @@ void AstWhile::addBeforeStmt(AstNode* newp, AstNode* belowp) {
} else if (belowp == condp()) {
// Goes before condition, IE in preconditions
addPrecondsp(newp);
} else if (belowp == bodysp()) {
} else if (belowp == stmtsp()) {
// Was first statement in body, so new front
belowp->addHereThisAsNext(newp);
} else {
@ -1250,12 +1240,12 @@ void AstWhile::addNextStmt(AstNode* newp, AstNode* belowp) {
belowp->addNextHere(newp);
} else if (belowp == condp()) {
// Becomes first statement in body, body may have been empty
if (bodysp()) {
bodysp()->addHereThisAsNext(newp);
if (stmtsp()) {
stmtsp()->addHereThisAsNext(newp);
} else {
addBodysp(newp);
addStmtsp(newp);
}
} else if (belowp == bodysp()) {
} else if (belowp == stmtsp()) {
// Next statement in body
belowp->addNextHere(newp);
} else {
@ -1521,19 +1511,15 @@ void AstInitArray::cloneRelink() {
if (it->second->clonep()) it->second = it->second->clonep();
}
}
AstNode* AstInitArray::addIndexValuep(uint64_t index, AstNode* newp) {
// Returns old value, caller must garbage collect
AstNode* oldp = nullptr;
void AstInitArray::addIndexValuep(uint64_t index, AstNode* newp) {
const auto it = m_map.find(index);
if (it != m_map.end()) {
oldp = it->second->valuep();
it->second->valuep(newp);
} else {
AstInitItem* const itemp = new AstInitItem(fileline(), newp);
m_map.emplace(index, itemp);
addOp2p(itemp);
addInitsp(itemp);
}
return oldp;
}
AstNode* AstInitArray::getIndexValuep(uint64_t index) const {
const auto it = m_map.find(index);
@ -1808,7 +1794,7 @@ AstPackage* AstNetlist::dollarUnitPkgAddp() {
m_dollarUnitPkgp->inLibrary(true);
m_dollarUnitPkgp->modTrace(false); // may reconsider later
m_dollarUnitPkgp->internal(true);
addModulep(m_dollarUnitPkgp);
addModulesp(m_dollarUnitPkgp);
}
return m_dollarUnitPkgp;
}
@ -1816,7 +1802,7 @@ void AstNetlist::createTopScope(AstScope* scopep) {
UASSERT(scopep, "Must not be nullptr");
UASSERT_OBJ(!m_topScopep, scopep, "TopScope already exits");
m_topScopep = new AstTopScope{scopep->modp()->fileline(), scopep};
scopep->modp()->addStmtp(v3Global.rootp()->topScopep());
scopep->modp()->addStmtsp(v3Global.rootp()->topScopep());
}
void AstNodeModule::dump(std::ostream& str) const {
this->AstNode::dump(str);

View File

@ -115,7 +115,7 @@ private:
}
} else {
// Move to module
m_modp->addStmtp(nodep);
m_modp->addStmtsp(nodep);
}
}
@ -214,7 +214,7 @@ private:
UINFO(8, " rename to " << nodep->name() << endl);
// Move to module
nodep->unlinkFrBack();
m_modp->addStmtp(nodep);
m_modp->addStmtsp(nodep);
}
iterateChildren(nodep);
}
@ -233,10 +233,10 @@ private:
const string scname = nodep->forFormat() ? m_displayScope : m_namedScope;
if (!scname.empty()) {
// To keep correct visual order, must add before other Text's
AstNode* const afterp = nodep->scopeAttrp();
AstText* const afterp = nodep->scopeAttrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->scopeAttrp(new AstText{nodep->fileline(), string("__DOT__") + scname});
if (afterp) nodep->scopeAttrp(afterp);
nodep->addScopeAttrp(new AstText{nodep->fileline(), string("__DOT__") + scname});
if (afterp) nodep->addScopeAttrp(afterp);
}
iterateChildren(nodep);
}

View File

@ -70,7 +70,7 @@ private:
{
// Do if
reset();
iterateAndNextNull(nodep->ifsp());
iterateAndNextNull(nodep->thensp());
const int ifLikely = m_likely;
const int ifUnlikely = m_unlikely;
// Do else

View File

@ -275,9 +275,9 @@ private:
pushLocalScope();
processEnter(nodep);
processAndIterate(nodep->condp());
if (AstNode* const ifsp = nodep->ifsp()) {
if (AstNode* const thensp = nodep->thensp()) {
pushLocalScope();
processAndIterateList(ifsp);
processAndIterateList(thensp);
popLocalScope();
}
if (AstNode* const elsesp = nodep->elsesp()) {

View File

@ -77,7 +77,7 @@ private:
if (!preventUnusedStmt.empty()) {
funcp->addStmtsp(new AstCStmt{m_modp->fileline(), preventUnusedStmt});
}
m_modp->addStmtp(funcp);
m_modp->addStmtsp(funcp);
m_numStmts = 0;
return funcp;
}
@ -136,7 +136,7 @@ void V3CCtors::evalAsserts() {
funcp->isLoose(true);
funcp->slow(false);
funcp->ifdef("VL_DEBUG");
modp->addStmtp(funcp);
modp->addStmtsp(funcp);
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
if (AstVar* const varp = VN_CAST(np, Var)) {
if (varp->isPrimaryInish() && !varp->isSc()) {
@ -209,7 +209,7 @@ void V3CCtors::cctorsAll() {
// If can be referred to by base pointer, need virtual delete
funcp->isVirtual(classp->isExtended());
funcp->slow(false);
modp->addStmtp(funcp);
modp->addStmtsp(funcp);
}
}
}

View File

@ -51,7 +51,7 @@ class CUseVisitor final : public VNVisitor {
void addNewUse(AstNode* nodep, VUseType useType, const string& name) {
if (m_didUse.emplace(useType, name).second) {
AstCUse* const newp = new AstCUse{nodep->fileline(), useType, name};
m_modp->addStmtp(newp);
m_modp->addStmtsp(newp);
UINFO(8, "Insert " << newp << endl);
}
}

View File

@ -245,7 +245,7 @@ private:
// Convert valueItem from AstCaseItem* to the expression
// Not done earlier, as we may now have a nullptr because it's just a ";" NOP branch
for (uint32_t i = 0; i < numCases; ++i) {
m_valueItem[i] = VN_AS(m_valueItem[i], CaseItem)->bodysp();
m_valueItem[i] = VN_AS(m_valueItem[i], CaseItem)->stmtsp();
}
return true; // All is fine
}
@ -346,7 +346,7 @@ private:
itemp = VN_AS(itemp->nextp(), CaseItem)) {
if (!itemp->condsp()) {
// Default clause. Just make true, we'll optimize it away later
itemp->condsp(new AstConst(itemp->fileline(), AstConst::BitTrue()));
itemp->addCondsp(new AstConst(itemp->fileline(), AstConst::BitTrue()));
hadDefault = true;
} else {
// Expressioned clause
@ -397,7 +397,7 @@ private:
}
}
// Replace expression in tree
itemp->condsp(ifexprp);
itemp->addCondsp(ifexprp);
}
}
VL_DO_DANGLING(cexprp->deleteTree(), cexprp);
@ -420,7 +420,7 @@ private:
AstIf* itemnextp = nullptr;
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
itemp = VN_AS(itemp->nextp(), CaseItem)) {
AstNode* const istmtsp = itemp->bodysp(); // Maybe null -- no action.
AstNode* const istmtsp = itemp->stmtsp(); // Maybe null -- no action.
if (istmtsp) istmtsp->unlinkFrBackWithNext();
// Expressioned clause
AstNode* const ifexprp = itemp->condsp()->unlinkFrBack();
@ -452,7 +452,7 @@ private:
if (itemnextp) {
itemnextp->addElsesp(newp);
} else {
groupnextp->addIfsp(newp); // First in a new group
groupnextp->addThensp(newp); // First in a new group
}
itemnextp = newp;
}

View File

@ -67,7 +67,7 @@ public:
m_tlChgFuncp->isStatic(false);
m_tlChgFuncp->isLoose(true);
m_tlChgFuncp->declPrivate(true);
m_scopetopp->addActivep(m_tlChgFuncp);
m_scopetopp->addBlocksp(m_tlChgFuncp);
// Each change detection function needs at least one AstChangeDet
// to ensure that V3EmitC outputs the necessary code.
maybeCreateMidChg();
@ -86,7 +86,7 @@ public:
m_chgFuncp->isStatic(false);
m_chgFuncp->isLoose(true);
m_chgFuncp->declPrivate(true);
m_scopetopp->addActivep(m_chgFuncp);
m_scopetopp->addBlocksp(m_chgFuncp);
// Add a top call to it
AstCCall* const callp = new AstCCall{m_scopetopp->fileline(), m_chgFuncp};
@ -218,9 +218,9 @@ public:
// CHANGEDET(VARREF(_last), VARREF(var))
AstVar* const newvarp
= new AstVar{varp->fileline(), VVarType::MODULETEMP, newvarname, varp};
m_state.m_topModp->addStmtp(newvarp);
m_state.m_topModp->addStmtsp(newvarp);
m_newvscp = new AstVarScope{m_vscp->fileline(), m_state.m_scopetopp, newvarp};
m_state.m_scopetopp->addVarp(m_newvscp);
m_state.m_scopetopp->addVarsp(m_newvscp);
m_varEqnp = new AstVarRef{m_vscp->fileline(), m_vscp, VAccess::READ};
m_newLvEqnp = new AstVarRef{m_vscp->fileline(), m_newvscp, VAccess::WRITE};

View File

@ -54,7 +54,7 @@ private:
// Move this class
nodep->name(m_prefix + nodep->name());
nodep->unlinkFrBack();
v3Global.rootp()->addModulep(nodep);
v3Global.rootp()->addModulesp(nodep);
// Make containing package
// Note origName is the same as the class origName so errors look correct
AstClassPackage* const packagep
@ -62,7 +62,7 @@ private:
packagep->name(nodep->name() + "__Vclpkg");
nodep->classOrPackagep(packagep);
packagep->classp(nodep);
v3Global.rootp()->addModulep(packagep);
v3Global.rootp()->addModulesp(packagep);
// Add package to hierarchy
AstCell* const cellp = new AstCell{packagep->fileline(),
packagep->fileline(),
@ -72,7 +72,7 @@ private:
nullptr,
nullptr};
cellp->modp(packagep);
v3Global.rootp()->topModulep()->addStmtp(cellp);
v3Global.rootp()->topModulep()->addStmtsp(cellp);
// Find class's scope
// Alternative would be to move this and related to V3Scope
const AstScope* classScopep = nullptr;
@ -85,7 +85,7 @@ private:
AstScope* const scopep
= new AstScope{nodep->fileline(), packagep, classScopep->name(),
classScopep->aboveScopep(), classScopep->aboveCellp()};
packagep->addStmtp(scopep);
packagep->addStmtsp(scopep);
// Iterate
VL_RESTORER(m_prefix);
VL_RESTORER(m_classPackagep);
@ -178,15 +178,15 @@ public:
AstScope* const scopep = moved.second;
UINFO(9, "moving " << nodep << " to " << scopep << endl);
if (VN_IS(nodep, NodeFTask)) {
scopep->addActivep(nodep->unlinkFrBack());
scopep->addBlocksp(nodep->unlinkFrBack());
} else if (VN_IS(nodep, Var)) {
AstVarScope* const vscp = VN_AS(nodep->user1p(), VarScope);
vscp->scopep(scopep);
vscp->unlinkFrBack();
scopep->addVarp(vscp);
scopep->addVarsp(vscp);
} else if (VN_IS(nodep, Initial) || VN_IS(nodep, InitialStatic)) {
nodep->unlinkFrBack();
scopep->addActivep(nodep);
scopep->addBlocksp(nodep);
} else {
nodep->v3fatalSrc("Bad case");
}
@ -196,7 +196,7 @@ public:
AstNodeModule* const modp = moved.second;
UINFO(9, "moving " << nodep << " to " << modp << endl);
nodep->unlinkFrBack();
modp->addStmtp(nodep);
modp->addStmtsp(nodep);
}
}
};

View File

@ -236,7 +236,7 @@ private:
setClean(nodep, false);
// We always clean, as we don't trust those pesky users.
if (!VN_IS(nodep->backp(), And)) insertClean(nodep);
ensureCleanAndNext(nodep->bodysp());
ensureCleanAndNext(nodep->exprsp());
}
void visit(AstTraceDecl* nodep) override {
// No cleaning, or would loose pointer to enum
@ -259,7 +259,7 @@ private:
void visit(AstNodeCond* nodep) override {
iterateChildren(nodep);
ensureClean(nodep->condp());
setClean(nodep, isClean(nodep->expr1p()) && isClean(nodep->expr2p()));
setClean(nodep, isClean(nodep->thenp()) && isClean(nodep->elsep()));
}
void visit(AstWhile* nodep) override {
iterateChildren(nodep);
@ -276,7 +276,7 @@ private:
}
void visit(AstUCStmt* nodep) override {
iterateChildren(nodep);
ensureCleanAndNext(nodep->bodysp());
ensureCleanAndNext(nodep->exprsp());
}
void visit(AstNodeCCall* nodep) override {
iterateChildren(nodep);

View File

@ -102,10 +102,10 @@ private:
AstVar* const newvarp = new AstVar(vscp->fileline(), VVarType::MODULETEMP, newvarname,
VFlagLogicPacked{}, 1);
newvarp->noReset(true); // Reset by below assign
m_modp->addStmtp(newvarp);
m_modp->addStmtsp(newvarp);
AstVarScope* const newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
vscp->user1p(newvscp);
m_scopep->addVarp(newvscp);
m_scopep->addVarsp(newvscp);
// Add init
AstNode* fromp = new AstVarRef(newvarp->fileline(), vscp, VAccess::READ);
if (v3Global.opt.xInitialEdge()) fromp = new AstNot(fromp->fileline(), fromp);
@ -202,7 +202,7 @@ private:
funcp->slow(slow);
funcp->isConst(false);
funcp->declPrivate(true);
m_topScopep->scopep()->addActivep(funcp);
m_topScopep->scopep()->addBlocksp(funcp);
return funcp;
}
void splitCheck(AstCFunc* ofuncp) {
@ -229,7 +229,7 @@ private:
funcp->isStatic(false);
funcp->isLoose(true);
funcp->slow(ofuncp->slow());
m_topScopep->scopep()->addActivep(funcp);
m_topScopep->scopep()->addBlocksp(funcp);
//
AstCCall* const callp = new AstCCall{funcp->fileline(), funcp};
ofuncp->addStmtsp(callp);
@ -297,7 +297,7 @@ private:
m_scopep = nullptr;
}
void visit(AstNodeProcedure* nodep) override {
if (AstNode* const stmtsp = nodep->bodysp()) {
if (AstNode* const stmtsp = nodep->stmtsp()) {
stmtsp->unlinkFrBackWithNext();
nodep->addNextHere(stmtsp);
}
@ -316,7 +316,7 @@ private:
// We could add another IF to detect posedges, and only increment if so.
// It's another whole branch though versus a potential memory miss.
// We'll go with the miss.
newp->addIfsp(new AstAssign(nodep->fileline(), changeWrp, origp->cloneTree(false)));
newp->addThensp(new AstAssign(nodep->fileline(), changeWrp, origp->cloneTree(false)));
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
@ -367,7 +367,7 @@ private:
m_mtaskBodyp->addStmtsp(m_lastIfp);
}
// Move statements to if
m_lastIfp->addIfsp(stmtsp);
m_lastIfp->addThensp(stmtsp);
} else if (nodep->hasInitial() || nodep->hasSettle()) {
nodep->v3fatalSrc("MTask should not include initial/settle logic.");
} else {
@ -393,7 +393,7 @@ private:
addToEvalLoop(m_lastIfp);
}
// Move statements to if
m_lastIfp->addIfsp(stmtsp);
m_lastIfp->addThensp(stmtsp);
} else if (nodep->hasInitial()) {
// Don't need to: clearLastSen();, as we're adding it to different cfunc
// Move statements to function

View File

@ -43,7 +43,7 @@ static void makeVlToString(AstClass* nodep) {
AstNode* const exprp = new AstCMath{nodep->fileline(), "obj ? obj->to_string() : \"null\"", 0};
exprp->dtypeSetString();
funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
nodep->addStmtp(funcp);
nodep->addStmtsp(funcp);
}
static void makeToString(AstClass* nodep) {
AstCFunc* const funcp = new AstCFunc{nodep->fileline(), "to_string", nullptr, "std::string"};
@ -54,7 +54,7 @@ static void makeToString(AstClass* nodep) {
= new AstCMath{nodep->fileline(), R"(std::string{"'{"} + to_string_middle() + "}")", 0};
exprp->dtypeSetString();
funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
nodep->addStmtp(funcp);
nodep->addStmtsp(funcp);
}
static void makeToStringMiddle(AstClass* nodep) {
AstCFunc* const funcp
@ -96,7 +96,7 @@ static void makeToStringMiddle(AstClass* nodep) {
funcp->addStmtsp(new AstCStmt{nodep->fileline(), stmt});
}
funcp->addStmtsp(new AstCStmt{nodep->fileline(), "return out;\n"});
nodep->addStmtp(funcp);
nodep->addStmtsp(funcp);
}
//######################################################################

View File

@ -193,11 +193,11 @@ public:
const VPragmaType type
= m_inlineValue ? VPragmaType::INLINE_MODULE : VPragmaType::NO_INLINE_MODULE;
AstNode* const nodep = new AstPragma(modp->fileline(), type);
modp->addStmtp(nodep);
modp->addStmtsp(nodep);
}
for (const auto& itr : m_modPragmas) {
AstNode* const nodep = new AstPragma{modp->fileline(), itr};
modp->addStmtp(nodep);
modp->addStmtsp(nodep);
}
}

View File

@ -1042,20 +1042,19 @@ private:
// as high as possible, which is usally the right choice, except for this.
AstNodeCond* const condp = VN_CAST(nodep->rhsp(), NodeCond);
if (!condp) return false;
if (!VN_IS(condp->expr1p(), Const) && !VN_IS(condp->expr2p(), Const)) return false;
if (!VN_IS(condp->thenp(), Const) && !VN_IS(condp->elsep(), Const)) return false;
AstConst* const maskp = VN_CAST(nodep->lhsp(), Const);
if (!maskp) return false;
UINFO(4, "AND(CONSTm, CONDcond(c, i, e))->CONDcond(c, AND(m,i), AND(m, e)) " << nodep
<< endl);
AstNodeCond* const newp = static_cast<AstNodeCond*>(
condp->cloneType(condp->condp()->unlinkFrBack(),
new AstAnd(nodep->fileline(), maskp->cloneTree(false),
condp->expr1p()->unlinkFrBack()),
new AstAnd(nodep->fileline(), maskp->cloneTree(false),
condp->expr2p()->unlinkFrBack())));
AstNodeCond* const newp = static_cast<AstNodeCond*>(condp->cloneType(
condp->condp()->unlinkFrBack(),
new AstAnd(nodep->fileline(), maskp->cloneTree(false), condp->thenp()->unlinkFrBack()),
new AstAnd(nodep->fileline(), maskp->cloneTree(false),
condp->elsep()->unlinkFrBack())));
newp->dtypeFrom(nodep);
newp->expr1p()->dtypeFrom(nodep); // As And might have been to change widths
newp->expr2p()->dtypeFrom(nodep);
newp->thenp()->dtypeFrom(nodep); // As And might have been to change widths
newp->elsep()->dtypeFrom(nodep);
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
return true;
@ -1443,19 +1442,19 @@ private:
}
}
bool ifSameAssign(const AstNodeIf* nodep) {
const AstNodeAssign* const ifp = VN_CAST(nodep->ifsp(), NodeAssign);
const AstNodeAssign* const elsep = VN_CAST(nodep->elsesp(), NodeAssign);
if (!ifp || ifp->nextp()) return false; // Must be SINGLE statement
if (!elsep || elsep->nextp()) return false;
if (ifp->type() != elsep->type()) return false; // Can't mix an assigndly and an assign
if (!ifp->lhsp()->sameGateTree(elsep->lhsp())) return false;
if (!ifp->rhsp()->gateTree()) return false;
if (!elsep->rhsp()->gateTree()) return false;
const AstNodeAssign* const thensp = VN_CAST(nodep->thensp(), NodeAssign);
const AstNodeAssign* const elsesp = VN_CAST(nodep->elsesp(), NodeAssign);
if (!thensp || thensp->nextp()) return false; // Must be SINGLE statement
if (!elsesp || elsesp->nextp()) return false;
if (thensp->type() != elsesp->type()) return false; // Can't mix an assigndly with assign
if (!thensp->lhsp()->sameGateTree(elsesp->lhsp())) return false;
if (!thensp->rhsp()->gateTree()) return false;
if (!elsesp->rhsp()->gateTree()) return false;
return true;
}
bool operandIfIf(const AstNodeIf* nodep) {
if (nodep->elsesp()) return false;
const AstNodeIf* const lowerIfp = VN_CAST(nodep->ifsp(), NodeIf);
const AstNodeIf* const lowerIfp = VN_CAST(nodep->thensp(), NodeIf);
if (!lowerIfp || lowerIfp->nextp()) return false;
if (nodep->type() != lowerIfp->type()) return false;
if (afterComment(lowerIfp->elsesp())) return false;
@ -2097,8 +2096,8 @@ private:
AstVar* const temp2p
= new AstVar(sel2p->fileline(), VVarType::BLOCKTEMP,
m_concswapNames.get(sel2p), VFlagLogicPacked(), msb2 - lsb2 + 1);
m_modp->addStmtp(temp1p);
m_modp->addStmtp(temp2p);
m_modp->addStmtsp(temp1p);
m_modp->addStmtsp(temp2p);
AstNodeAssign* const asn1ap
= VN_AS(nodep->cloneType(
new AstVarRef(sel1p->fileline(), temp1p, VAccess::WRITE), sel1p),
@ -2862,7 +2861,7 @@ private:
varrefp->unlinkFrBack();
AstInitial* const newinitp = new AstInitial(
nodep->fileline(), new AstAssign(nodep->fileline(), varrefp, exprp));
m_modp->addStmtp(newinitp);
m_modp->addStmtsp(newinitp);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
// Set the initial value right in the variable so we can constant propagate
AstNode* const initvaluep = exprp->cloneTree(false);
@ -2892,7 +2891,7 @@ private:
keepp = nodep->elsesp();
} else if (!m_doV || constp->isNeqZero()) { // Might be X in Verilog
UINFO(4, "IF(!0,{x},{any}) => {x}: " << nodep << endl);
keepp = nodep->ifsp();
keepp = nodep->thensp();
} else {
UINFO(4, "IF condition is X, retaining: " << nodep << endl);
return;
@ -2904,7 +2903,7 @@ private:
nodep->unlinkFrBack();
}
VL_DO_DANGLING(nodep->deleteTree(), nodep);
} else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
} else if (!afterComment(nodep->thensp()) && !afterComment(nodep->elsesp())) {
if (!isTreePureRecurse(nodep->condp())) {
// Condition has side effect - leave - perhaps in
// future simplify to remove all but side effect terms
@ -2912,27 +2911,27 @@ private:
// Empty block, remove it
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
} else if (!afterComment(nodep->ifsp())) {
} else if (!afterComment(nodep->thensp())) {
UINFO(4, "IF({x}) nullptr {...} => IF(NOT{x}}: " << nodep << endl);
AstNode* const condp = nodep->condp();
AstNode* const elsesp = nodep->elsesp();
condp->unlinkFrBackWithNext();
elsesp->unlinkFrBackWithNext();
if (nodep->ifsp()) { // Must have been comment
nodep->ifsp()->unlinkFrBackWithNext()->deleteTree();
if (nodep->thensp()) { // Must have been comment
nodep->thensp()->unlinkFrBackWithNext()->deleteTree();
}
nodep->condp(new AstLogNot(condp->fileline(),
condp)); // LogNot, as C++ optimization also possible
nodep->addIfsp(elsesp);
nodep->addThensp(elsesp);
} else if (((VN_IS(nodep->condp(), Not) && nodep->condp()->width() == 1)
|| VN_IS(nodep->condp(), LogNot))
&& nodep->ifsp() && nodep->elsesp()) {
&& nodep->thensp() && nodep->elsesp()) {
UINFO(4, "IF(NOT {x}) => IF(x) swapped if/else" << nodep << endl);
AstNode* const condp
= VN_AS(nodep->condp(), NodeUniop)->lhsp()->unlinkFrBackWithNext();
AstNode* const ifsp = nodep->ifsp()->unlinkFrBackWithNext();
AstNode* const thensp = nodep->thensp()->unlinkFrBackWithNext();
AstNode* const elsesp = nodep->elsesp()->unlinkFrBackWithNext();
AstIf* const ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
AstIf* const ifp = new AstIf(nodep->fileline(), condp, elsesp, thensp);
ifp->branchPred(nodep->branchPred().invert());
nodep->replaceWith(ifp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
@ -2940,25 +2939,25 @@ private:
UINFO(
4,
"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})\n");
AstNodeAssign* const ifp = VN_AS(nodep->ifsp(), NodeAssign);
AstNodeAssign* const elsep = VN_AS(nodep->elsesp(), NodeAssign);
ifp->unlinkFrBack();
AstNodeAssign* const thensp = VN_AS(nodep->thensp(), NodeAssign);
AstNodeAssign* const elsesp = VN_AS(nodep->elsesp(), NodeAssign);
thensp->unlinkFrBack();
AstNode* const condp = nodep->condp()->unlinkFrBack();
AstNode* const truep = ifp->rhsp()->unlinkFrBack();
AstNode* const falsep = elsep->rhsp()->unlinkFrBack();
ifp->rhsp(new AstCond(truep->fileline(), condp, truep, falsep));
nodep->replaceWith(ifp);
AstNode* const truep = thensp->rhsp()->unlinkFrBack();
AstNode* const falsep = elsesp->rhsp()->unlinkFrBack();
thensp->rhsp(new AstCond(truep->fileline(), condp, truep, falsep));
nodep->replaceWith(thensp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
} else if (false // Disabled, as vpm assertions are faster
// without due to short-circuiting
&& operandIfIf(nodep)) {
UINFO(9, "IF({a}) IF({b}) => IF({a} && {b})" << endl);
AstNodeIf* const lowerIfp = VN_AS(nodep->ifsp(), NodeIf);
AstNodeIf* const lowerIfp = VN_AS(nodep->thensp(), NodeIf);
AstNode* const condp = nodep->condp()->unlinkFrBack();
AstNode* const lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext();
AstNode* const lowerThensp = lowerIfp->thensp()->unlinkFrBackWithNext();
AstNode* const lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext();
nodep->condp(new AstLogAnd(lowerIfp->fileline(), condp, lowerCondp));
lowerIfp->replaceWith(lowerIfsp);
lowerIfp->replaceWith(lowerThensp);
VL_DO_DANGLING(lowerIfp->deleteTree(), lowerIfp);
} else if (operandBoolShift(nodep->condp())) {
replaceBoolShift(nodep->condp());
@ -3015,8 +3014,10 @@ private:
pformatp->text(pformatp->text() + nformatp->text());
if (!prevp->addNewline() && nodep->addNewline()) pformatp->text(pformatp->text() + "\n");
if (nformatp->exprsp()) pformatp->addExprsp(nformatp->exprsp()->unlinkFrBackWithNext());
if (nformatp->scopeNamep())
pformatp->scopeNamep(nformatp->scopeNamep()->unlinkFrBackWithNext());
if (AstScopeName* const scopeNamep = nformatp->scopeNamep()) {
scopeNamep->unlinkFrBackWithNext();
pformatp->scopeNamep(scopeNamep);
}
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return true;
}
@ -3300,19 +3301,19 @@ private:
TREEOPC("AstAnd {$lhsp.isOne, matchRedundantClean(nodep)}", "DONE") // 1 & (a == b) -> (IData)(a == b)
// Trinary ops
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
TREEOP ("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
TREEOP ("AstNodeCond{$condp.isNeqZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr1p)");
TREEOPA("AstNodeCond{$condp.isZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr2p)");
TREEOPA("AstNodeCond{$condp.isNeqZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr1p)");
TREEOP ("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)");
TREEOP ("AstNodeCond{$condp.isZero, $thenp, $elsep}", "replaceWChild(nodep,$elsep)");
TREEOP ("AstNodeCond{$condp.isNeqZero, $thenp, $elsep}", "replaceWChild(nodep,$thenp)");
TREEOPA("AstNodeCond{$condp.isZero, $thenp.castConst, $elsep.castConst}", "replaceWChild(nodep,$elsep)");
TREEOPA("AstNodeCond{$condp.isNeqZero, $thenp.castConst, $elsep.castConst}", "replaceWChild(nodep,$thenp)");
TREEOP ("AstNodeCond{$condp, operandsSame($thenp,,$elsep)}","replaceWChild(nodep,$thenp)");
// This visit function here must allow for short-circuiting.
TREEOPS("AstCond {$lhsp.isZero}", "replaceWIteratedThs(nodep)");
TREEOPS("AstCond {$lhsp.isNeqZero}", "replaceWIteratedRhs(nodep)");
TREEOP ("AstCond{$condp.castNot, $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}");
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstLogOr {$condp, $expr2p}"); // a?1:b == a||b
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstLogAnd{$condp, $expr1p}"); // a?b:0 == a&&b
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstLogOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~a||b
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstLogAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&&b
TREEOP ("AstCond{$condp.castNot, $thenp, $elsep}", "AstCond{$condp->op1p(), $elsep, $thenp}");
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp.isAllOnes, $elsep}", "AstLogOr {$condp, $elsep}"); // a?1:b == a||b
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp, $elsep.isZero}", "AstLogAnd{$condp, $thenp}"); // a?b:0 == a&&b
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp, $elsep.isAllOnes}", "AstLogOr {AstNot{$condp}, $thenp}"); // a?b:1 == ~a||b
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp.isZero, $elsep}", "AstLogAnd{AstNot{$condp}, $elsep}"); // a?0:b == ~a&&b
TREEOP ("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
// Prefer constants on left, since that often needs a shift, it lets
// constant red remove the shift

View File

@ -119,7 +119,7 @@ private:
AstCoverDecl* const declp = new AstCoverDecl(fl, page, comment, linescov, offset);
declp->hier(hier);
m_modp->addStmtp(declp);
m_modp->addStmtsp(declp);
UINFO(9, "new " << declp << endl);
AstCoverInc* const incp = new AstCoverInc(fl, declp);
@ -128,7 +128,7 @@ private:
incp->findUInt32DType());
varp->trace(true);
varp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true);
m_modp->addStmtp(varp);
m_modp->addStmtsp(varp);
UINFO(5, "New coverage trace: " << varp << endl);
AstAssign* const assp = new AstAssign(
incp->fileline(), new AstVarRef(incp->fileline(), varp, VAccess::WRITE),
@ -245,11 +245,11 @@ private:
= newCoverInc(nodep->fileline(), "", "v_line", "block",
linesCov(m_state, nodep), 0, traceNameForLine(nodep, "block"));
if (AstNodeProcedure* const itemp = VN_CAST(nodep, NodeProcedure)) {
itemp->addStmtp(newp);
itemp->addStmtsp(newp);
} else if (AstNodeFTask* const itemp = VN_CAST(nodep, NodeFTask)) {
itemp->addStmtsp(newp);
} else if (AstWhile* const itemp = VN_CAST(nodep, While)) {
itemp->addBodysp(newp);
itemp->addStmtsp(newp);
} else {
nodep->v3fatalSrc("Bad node type");
}
@ -283,7 +283,7 @@ private:
AstVar* const chgVarp
= new AstVar(nodep->fileline(), VVarType::MODULETEMP, newvarname, nodep);
chgVarp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true);
m_modp->addStmtp(chgVarp);
m_modp->addStmtsp(chgVarp);
// Create bucket for each dimension * bit.
// This is necessarily an O(n^2) expansion, which is why
@ -304,7 +304,7 @@ private:
newCoverInc(varp->fileline(), "", "v_toggle", varp->name() + above.m_comment, "", 0,
""),
above.m_varRefp->cloneTree(true), above.m_chgRefp->cloneTree(true));
m_modp->addStmtp(newp);
m_modp->addStmtsp(newp);
}
void toggleVarRecurse(AstNodeDType* dtypep, int depth, // per-iteration
@ -388,7 +388,7 @@ private:
if (m_state.m_on) {
// An else-if. When we iterate the if, use "elsif" marking
const bool elsif
= nodep->ifsp() && VN_IS(nodep->elsesp(), If) && !nodep->elsesp()->nextp();
= nodep->thensp() && VN_IS(nodep->elsesp(), If) && !nodep->elsesp()->nextp();
if (elsif) VN_AS(nodep->elsesp(), If)->user1(true);
const bool first_elsif = !nodep->user1() && elsif;
const bool cont_elsif = nodep->user1() && elsif;
@ -403,7 +403,7 @@ private:
CheckState elseState;
{
createHandle(nodep);
iterateAndNextNull(nodep->ifsp());
iterateAndNextNull(nodep->thensp());
lineTrack(nodep);
ifState = m_state;
}
@ -422,9 +422,9 @@ private:
// Normal if. Linecov shows what's inside the if (not condition that is
// always executed)
UINFO(4, " COVER-branch: " << nodep << endl);
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_branch", "if",
linesCov(ifState, nodep), 0,
traceNameForLine(nodep, "if")));
nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_branch", "if",
linesCov(ifState, nodep), 0,
traceNameForLine(nodep, "if")));
// The else has a column offset of 1 to uniquify it relative to the if
// As "if" and "else" are more than one character wide, this won't overlap
// another token
@ -436,18 +436,18 @@ private:
else if (first_elsif || cont_elsif) {
UINFO(4, " COVER-elsif: " << nodep << endl);
if (ifState.lineCoverageOn(nodep)) {
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif",
linesCov(ifState, nodep), 0,
traceNameForLine(nodep, "elsif")));
nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_line", "elsif",
linesCov(ifState, nodep), 0,
traceNameForLine(nodep, "elsif")));
}
// and we don't insert the else as the child if-else will do so
} else {
// Cover as separate blocks (not a branch as is not two-legged)
if (ifState.lineCoverageOn(nodep)) {
UINFO(4, " COVER-half-if: " << nodep << endl);
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if",
linesCov(ifState, nodep), 0,
traceNameForLine(nodep, "if")));
nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_line", "if",
linesCov(ifState, nodep), 0,
traceNameForLine(nodep, "if")));
}
if (elseState.lineCoverageOn(nodep)) {
UINFO(4, " COVER-half-el: " << nodep << endl);
@ -468,11 +468,11 @@ private:
VL_RESTORER(m_state);
{
createHandle(nodep);
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
if (m_state.lineCoverageOn(nodep)) { // if the case body didn't disable it
lineTrack(nodep);
UINFO(4, " COVER: " << nodep << endl);
nodep->addBodysp(newCoverInc(nodep->fileline(), "", "v_line", "case",
nodep->addStmtsp(newCoverInc(nodep->fileline(), "", "v_line", "case",
linesCov(m_state, nodep), 0,
traceNameForLine(nodep, "case")));
}
@ -486,12 +486,12 @@ private:
m_state.m_on = true; // Always do cover blocks, even if there's a $stop
createHandle(nodep);
iterateChildren(nodep);
if (!nodep->coverincp() && v3Global.opt.coverageUser()) {
if (!nodep->coverincsp() && v3Global.opt.coverageUser()) {
// Note the name may be overridden by V3Assert processing
lineTrack(nodep);
nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover",
linesCov(m_state, nodep), 0,
m_beginHier + "_vlCoverageUserTrace"));
nodep->addCoverincsp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover",
linesCov(m_state, nodep), 0,
m_beginHier + "_vlCoverageUserTrace"));
}
}
}

View File

@ -153,13 +153,13 @@ private:
varp = new AstVar(oldvarscp->fileline(), VVarType::BLOCKTEMP, name,
VFlagBitPacked(), width);
}
addmodp->addStmtp(varp);
addmodp->addStmtsp(varp);
m_modVarMap.emplace(std::make_pair(addmodp, name), varp);
}
AstVarScope* const varscp
= new AstVarScope(oldvarscp->fileline(), oldvarscp->scopep(), varp);
oldvarscp->scopep()->addVarp(varscp);
oldvarscp->scopep()->addVarsp(varscp);
return varscp;
}
@ -356,11 +356,11 @@ private:
postLogicp = new AstIf(nodep->fileline(),
new AstVarRef(nodep->fileline(), setvscp, VAccess::READ));
UINFO(9, " Created " << postLogicp << endl);
finalp->addStmtp(postLogicp);
finalp->addStmtsp(postLogicp);
finalp->user3p(setvscp); // Remember IF's vset variable
finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it
}
postLogicp->addIfsp(new AstAssign(nodep->fileline(), selectsp, valreadp));
postLogicp->addThensp(new AstAssign(nodep->fileline(), selectsp, valreadp));
return newlhsp;
}

View File

@ -57,7 +57,7 @@ private:
funcp->isStatic(m_cfuncp->isStatic());
funcp->isLoose(m_cfuncp->isLoose());
funcp->addStmtsp(nodep);
scopep->addActivep(funcp);
scopep->addBlocksp(funcp);
// Call sub function at the point where the body was removed from
AstCCall* const callp = new AstCCall(nodep->fileline(), funcp);
if (VN_IS(m_modp, Class)) {

View File

@ -257,7 +257,7 @@ private:
// If it's under a scope, move it up to the top
if (m_scopep) {
nodep->unlinkFrBack();
m_modp->addStmtp(nodep);
m_modp->addStmtsp(nodep);
if (nodep->funcPublic()) {
// There may be multiple public functions by the same name;

View File

@ -828,7 +828,7 @@ public:
puts("while (");
iterateAndNextNull(nodep->condp());
puts(") {\n");
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
iterateAndNextNull(nodep->incsp());
iterateAndNextNull(nodep->precondsp()); // Need to recompute before next loop
puts("}\n");
@ -842,7 +842,7 @@ public:
iterateAndNextNull(nodep->condp());
if (!nodep->branchPred().unknown()) puts(")");
puts(") {\n");
iterateAndNextNull(nodep->ifsp());
iterateAndNextNull(nodep->thensp());
puts("}");
if (!nodep->elsesp()) {
puts("\n");
@ -935,17 +935,17 @@ public:
}
void visit(AstCStmt* nodep) override {
putbs("");
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->exprsp());
}
void visit(AstCMath* nodep) override {
putbs("");
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->exprsp());
}
void visit(AstUCStmt* nodep) override {
VL_RESTORER(m_inUC);
m_inUC = true;
putsDecoration(ifNoProtect("// $c statement at " + nodep->fileline()->ascii() + "\n"));
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->exprsp());
puts("\n");
}
void visit(AstUCFunc* nodep) override {
@ -953,7 +953,7 @@ public:
m_inUC = true;
puts("\n");
putsDecoration(ifNoProtect("// $c function at " + nodep->fileline()->ascii() + "\n"));
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->exprsp());
puts("\n");
}
@ -1033,15 +1033,15 @@ public:
}
void visit(AstNodeCond* nodep) override {
// Widths match up already, so we'll just use C++'s operator w/o any temps.
if (nodep->expr1p()->isWide()) {
emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->expr1p(), nodep->expr2p());
if (nodep->thenp()->isWide()) {
emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->thenp(), nodep->elsep());
} else {
putbs("(");
iterateAndNextNull(nodep->condp());
putbs(" ? ");
iterateAndNextNull(nodep->expr1p());
iterateAndNextNull(nodep->thenp());
putbs(" : ");
iterateAndNextNull(nodep->expr2p());
iterateAndNextNull(nodep->elsep());
puts(")");
}
}

View File

@ -110,7 +110,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
iterateAndNextConstNull(nodep->sensesp());
}
putbs(" begin\n");
iterateAndNextConstNull(nodep->bodysp());
iterateAndNextConstNull(nodep->stmtsp());
putqs(nodep, "end\n");
}
void visit(AstAlwaysPublic* nodep) override {
@ -122,7 +122,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
iterateAndNextConstNull(nodep->sensesp());
}
putqs(nodep, " ");
iterateAndNextConstNull(nodep->bodysp());
iterateAndNextConstNull(nodep->stmtsp());
putqs(nodep, "*/\n");
}
void visit(AstNodeAssign* nodep) override {
@ -204,7 +204,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
putbs("default");
}
putfs(nodep, ": begin ");
iterateAndNextConstNull(nodep->bodysp());
iterateAndNextConstNull(nodep->stmtsp());
putqs(nodep, "end\n");
}
void visit(AstComment* nodep) override {
@ -326,14 +326,14 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
iterateAndNextConstNull(nodep->incsp());
}
puts(") begin\n");
iterateAndNextConstNull(nodep->bodysp());
iterateAndNextConstNull(nodep->stmtsp());
putqs(nodep, "end\n");
}
void visit(AstRepeat* nodep) override {
putfs(nodep, "repeat (");
iterateAndNextConstNull(nodep->countp());
puts(") begin\n");
iterateAndNextConstNull(nodep->bodysp());
iterateAndNextConstNull(nodep->stmtsp());
putfs(nodep, "end\n");
}
void visit(AstWhile* nodep) override {
@ -341,7 +341,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
putfs(nodep, "while (");
iterateAndNextConstNull(nodep->condp());
puts(") begin\n");
iterateAndNextConstNull(nodep->bodysp());
iterateAndNextConstNull(nodep->stmtsp());
iterateAndNextConstNull(nodep->incsp());
iterateAndNextConstNull(nodep->precondsp()); // Need to recompute before next loop
putfs(nodep, "end\n");
@ -356,7 +356,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
puts("if (");
iterateAndNextConstNull(nodep->condp());
puts(") begin\n");
iterateAndNextConstNull(nodep->ifsp());
iterateAndNextConstNull(nodep->thensp());
if (nodep->elsesp()) {
putqs(nodep, "end\n");
putqs(nodep, "else begin\n");
@ -401,22 +401,22 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
void visit(AstScopeName* nodep) override {}
void visit(AstCStmt* nodep) override {
putfs(nodep, "$_CSTMT(");
iterateAndNextConstNull(nodep->bodysp());
iterateAndNextConstNull(nodep->exprsp());
puts(");\n");
}
void visit(AstCMath* nodep) override {
putfs(nodep, "$_CMATH(");
iterateAndNextConstNull(nodep->bodysp());
iterateAndNextConstNull(nodep->exprsp());
puts(");\n");
}
void visit(AstUCStmt* nodep) override {
putfs(nodep, "$c(");
iterateAndNextConstNull(nodep->bodysp());
iterateAndNextConstNull(nodep->exprsp());
puts(");\n");
}
void visit(AstUCFunc* nodep) override {
putfs(nodep, "$c(");
iterateAndNextConstNull(nodep->bodysp());
iterateAndNextConstNull(nodep->exprsp());
puts(")");
}
@ -521,9 +521,9 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
putbs("(");
iterateAndNextConstNull(nodep->condp());
putfs(nodep, " ? ");
iterateAndNextConstNull(nodep->expr1p());
iterateAndNextConstNull(nodep->thenp());
putbs(" : ");
iterateAndNextConstNull(nodep->expr2p());
iterateAndNextConstNull(nodep->elsep());
puts(")");
}
void visit(AstRange* nodep) override {

View File

@ -306,8 +306,8 @@ private:
for (int w = 0; w < nodep->widthWords(); ++w) {
addWordAssign(nodep, w,
new AstCond{fl, rhsp->condp()->cloneTree(true),
newAstWordSelClone(rhsp->expr1p(), w),
newAstWordSelClone(rhsp->expr2p(), w)});
newAstWordSelClone(rhsp->thenp(), w),
newAstWordSelClone(rhsp->elsep(), w)});
}
return true;
}

View File

@ -109,7 +109,7 @@ class ForceConvertVisitor final : public VNVisitor {
new AstSenTree{flp, new AstSenItem{flp, AstSenItem::Initial{}}}};
activep->sensesStorep(activep->sensesp());
activep->addStmtsp(new AstInitial{flp, assignp});
vscp->scopep()->addActivep(activep);
vscp->scopep()->addBlocksp(activep);
}
{ // Add the combinational override
@ -127,7 +127,7 @@ class ForceConvertVisitor final : public VNVisitor {
new AstSenTree{flp, new AstSenItem{flp, AstSenItem::Combo{}}}};
activep->sensesStorep(activep->sensesp());
activep->addStmtsp(new AstAssignW{flp, lhsp, rhsp});
vscp->scopep()->addActivep(activep);
vscp->scopep()->addBlocksp(activep);
}
}
};

View File

@ -921,7 +921,7 @@ private:
if (m_dedupable) {
if (!m_always) {
m_always = true;
iterateAndNextNull(alwaysp->bodysp());
iterateAndNextNull(alwaysp->stmtsp());
} else {
m_dedupable = false;
}
@ -936,7 +936,7 @@ private:
if (m_always && !m_ifCondp && !ifp->elsesp()) {
// we're under an always, this is the first IF, and there's no else
m_ifCondp = ifp->condp();
iterateAndNextNull(ifp->ifsp());
iterateAndNextNull(ifp->thensp());
} else {
m_dedupable = false;
}

View File

@ -76,13 +76,13 @@ private:
// ASSIGN(VARREF(inpclk), VARREF(var))
AstVar* const newvarp
= new AstVar(varp->fileline(), VVarType::MODULETEMP, newvarname, varp);
m_topModp->addStmtp(newvarp);
m_topModp->addStmtsp(newvarp);
AstVarScope* const newvscp = new AstVarScope(vscp->fileline(), m_scopetopp, newvarp);
m_scopetopp->addVarp(newvscp);
m_scopetopp->addVarsp(newvscp);
AstAssign* const asninitp = new AstAssign(
vscp->fileline(), new AstVarRef(vscp->fileline(), newvscp, VAccess::WRITE),
new AstVarRef(vscp->fileline(), vscp, VAccess::READ));
m_scopetopp->addFinalClkp(asninitp);
m_scopetopp->addFinalClksp(asninitp);
//
vscp->user2p(newvscp);
}

View File

@ -294,15 +294,15 @@ private:
UASSERT_OBJ(exprconstp || exprvarrefp, nodep,
"Unknown interconnect type; pinReconnectSimple should have cleared up");
if (exprconstp) {
m_modp->addStmtp(new AstAssignW(flp, new AstVarRef(flp, nodep, VAccess::WRITE),
exprconstp->cloneTree(false)));
m_modp->addStmtsp(new AstAssignW(flp, new AstVarRef(flp, nodep, VAccess::WRITE),
exprconstp->cloneTree(false)));
} else if (nodep->user3()) {
// Public variable at the lower module end - we need to make sure we propagate
// the logic changes up and down; if we aliased, we might
// remove the change detection on the output variable.
UINFO(9, "public pin assign: " << exprvarrefp << endl);
UASSERT_OBJ(!nodep->isNonOutput(), nodep, "Outputs only - inputs use AssignAlias");
m_modp->addStmtp(
m_modp->addStmtsp(
new AstAssignW(flp, new AstVarRef(flp, exprvarrefp->varp(), VAccess::WRITE),
new AstVarRef(flp, nodep, VAccess::READ)));
} else if (nodep->isSigPublic() && VN_IS(nodep->dtypep(), UnpackArrayDType)) {
@ -310,11 +310,11 @@ private:
// instead of aliased, because otherwise it will pass V3Slice and invalid
// code will be emitted.
UINFO(9, "assign to public and unpacked: " << nodep << endl);
m_modp->addStmtp(
m_modp->addStmtsp(
new AstAssignW{flp, new AstVarRef{flp, nodep, VAccess::WRITE},
new AstVarRef{flp, exprvarrefp->varp(), VAccess::READ}});
} else if (nodep->isIfaceRef()) {
m_modp->addStmtp(
m_modp->addStmtsp(
new AstAssignVarScope(flp, new AstVarRef(flp, nodep, VAccess::WRITE),
new AstVarRef(flp, exprvarrefp->varp(), VAccess::READ)));
FileLine* const flbp = exprvarrefp->varp()->fileline();
@ -323,7 +323,7 @@ private:
} else {
// Do to inlining child's variable now within the same
// module, so a AstVarRef not AstVarXRef below
m_modp->addStmtp(
m_modp->addStmtsp(
new AstAssignAlias(flp, new AstVarRef(flp, nodep, VAccess::WRITE),
new AstVarRef(flp, exprvarrefp->varp(), VAccess::READ)));
FileLine* const flbp = exprvarrefp->varp()->fileline();
@ -423,16 +423,16 @@ private:
// 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
AstNode* afterp = nodep->scopeAttrp();
AstText* afterp = nodep->scopeAttrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->scopeAttrp(
nodep->addScopeAttrp(
new AstText{nodep->fileline(), std::string{"__DOT__"} + m_cellp->name()});
if (afterp) nodep->scopeAttrp(afterp);
if (afterp) nodep->addScopeAttrp(afterp);
afterp = nodep->scopeEntrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->scopeEntrp(
nodep->addScopeEntrp(
new AstText{nodep->fileline(), std::string{"__DOT__"} + m_cellp->name()});
if (afterp) nodep->scopeEntrp(afterp);
if (afterp) nodep->addScopeEntrp(afterp);
iterateChildren(nodep);
}
void visit(AstCoverDecl* nodep) override {
@ -566,7 +566,7 @@ private:
// Move statements under the module we are inlining into
if (AstNode* const stmtsp = newmodp->stmtsp()) {
stmtsp->unlinkFrBackWithNext();
m_modp->addStmtp(stmtsp);
m_modp->addStmtsp(stmtsp);
}
// Clear any leftover ports, etc
VL_DO_DANGLING(newmodp->deleteTree(), newmodp);
@ -649,7 +649,7 @@ private:
}
if (VN_IS(nodep->modp(), Iface)) {
nodep->addIntfRefp(new AstIntfRef{nodep->fileline(), m_scope});
nodep->addIntfRefsp(new AstIntfRef{nodep->fileline(), m_scope});
}
{
AstNodeModule* const modp = nodep->modp();
@ -666,7 +666,7 @@ private:
if ((cellp = VN_CAST(fromVarp->user1p(), Cell)) || (cellp = irdtp->cellp())) {
varp->user1p(cellp);
const string alias = m_scope + "__DOT__" + pinp->name();
cellp->addIntfRefp(new AstIntfRef(pinp->fileline(), alias));
cellp->addIntfRefsp(new AstIntfRef(pinp->fileline(), alias));
}
}
@ -695,7 +695,7 @@ private:
string alias;
if (!m_scope.empty()) alias = m_scope + "__DOT__";
alias += varlp->name();
cellp->addIntfRefp(new AstIntfRef(varlp->fileline(), alias));
cellp->addIntfRefsp(new AstIntfRef(varlp->fileline(), alias));
}
//--------------------
void visit(AstNodeMath*) override {} // Accelerate

View File

@ -170,7 +170,7 @@ private:
UINFO(8, "ifsp:\n");
m_instrCount = 0;
iterateAndNextNull(nodep->ifsp());
iterateAndNextNull(nodep->thensp());
uint32_t ifCount = m_instrCount;
if (nodep->branchPred().unlikely()) ifCount = 0;
@ -185,7 +185,7 @@ private:
if (nodep->elsesp()) nodep->elsesp()->user4(0); // Don't dump it
} else {
m_instrCount = savedCount + elseCount;
if (nodep->ifsp()) nodep->ifsp()->user4(0); // Don't dump it
if (nodep->thensp()) nodep->thensp()->user4(0); // Don't dump it
}
}
void visit(AstNodeCond* nodep) override {
@ -197,20 +197,20 @@ private:
UINFO(8, "?\n");
m_instrCount = 0;
iterateAndNextNull(nodep->expr1p());
iterateAndNextNull(nodep->thenp());
const uint32_t ifCount = m_instrCount;
UINFO(8, ":\n");
m_instrCount = 0;
iterateAndNextNull(nodep->expr2p());
iterateAndNextNull(nodep->elsep());
const uint32_t elseCount = m_instrCount;
if (ifCount < elseCount) {
m_instrCount = savedCount + elseCount;
if (nodep->expr1p()) nodep->expr1p()->user4(0); // Don't dump it
if (nodep->thenp()) nodep->thenp()->user4(0); // Don't dump it
} else {
m_instrCount = savedCount + ifCount;
if (nodep->expr2p()) nodep->expr2p()->user4(0); // Don't dump it
if (nodep->elsep()) nodep->elsep()->user4(0); // Don't dump it
}
}
void visit(AstActive* nodep) override {

View File

@ -340,7 +340,7 @@ private:
LifeBlock* const elseLifep = new LifeBlock(prevLifep, m_statep);
{
m_lifep = ifLifep;
iterateAndNextNull(nodep->ifsp());
iterateAndNextNull(nodep->thensp());
}
{
m_lifep = elseLifep;
@ -375,7 +375,7 @@ private:
}
{
m_lifep = bodyLifep;
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
iterateAndNextNull(nodep->incsp());
}
m_lifep = prevLifep;

View File

@ -268,7 +268,7 @@ private:
{
m_modp = modp;
// Important that this adds to end, as next iterate assumes does all cells
modp->addStmtp(cellsp);
modp->addStmtsp(cellsp);
iterateAndNextNull(cellsp);
}
}
@ -321,7 +321,7 @@ private:
otherModp->recursiveClone(true);
// user1 etc will retain its pre-clone value
cellmodp->user2p(otherModp);
v3Global.rootp()->addModulep(otherModp);
v3Global.rootp()->addModulesp(otherModp);
new V3GraphEdge(&m_graph, vertex(cellmodp), vertex(otherModp), 1,
false);
}

View File

@ -994,7 +994,7 @@ class LinkDotFindVisitor final : public VNVisitor {
if (!nodep->isExternDef()) {
// Move it to proper spot under the target class
nodep->unlinkFrBack();
classp->addStmtp(nodep);
classp->addStmtsp(nodep);
nodep->isExternDef(true); // So we check there's a matching extern
nodep->classOrPackagep()->unlinkFrBack()->deleteTree();
}
@ -1030,7 +1030,7 @@ class LinkDotFindVisitor final : public VNVisitor {
newvarp->funcReturn(true);
newvarp->trace(false); // Not user visible
newvarp->attrIsolateAssign(nodep->attrIsolateAssign());
nodep->addFvarp(newvarp);
nodep->fvarp(newvarp);
// Explicit insert required, as the var name shadows the upper level's task name
m_statep->insertSym(m_curSymp, newvarp->name(), newvarp,
nullptr /*classOrPackagep*/);
@ -1938,7 +1938,7 @@ private:
VFlagLogicPacked{}, 1);
newp->trace(modp->modTrace());
nodep->varp(newp);
modp->addStmtp(newp);
modp->addStmtsp(newp);
// Link it to signal list, must add the variable under the module;
// current scope might be lower now
m_statep->insertSym(moduleSymp, newp->name(), newp, nullptr /*classOrPackagep*/);
@ -3097,7 +3097,7 @@ private:
nodep->classOrPackagep(foundp->classOrPackagep());
}
} else if (AstClass* const defp = foundp ? VN_AS(foundp->nodep(), Class) : nullptr) {
AstNode* const paramsp = nodep->paramsp();
AstPin* const paramsp = nodep->paramsp();
if (paramsp) paramsp->unlinkFrBackWithNext();
AstClassRefDType* const newp
= new AstClassRefDType{nodep->fileline(), defp, paramsp};

View File

@ -106,7 +106,7 @@ private:
iterateAndNextNull(nodep->condp());
// Body insert just before themselves
m_insStmtp = nullptr; // First thing should be new statement
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
iterateAndNextNull(nodep->incsp());
// Done the loop
m_insStmtp = nullptr; // Next thing should be new statement
@ -131,7 +131,7 @@ private:
m_insStmtp = nodep;
iterateAndNextNull(nodep->condp());
m_insStmtp = nullptr;
iterateAndNextNull(nodep->ifsp());
iterateAndNextNull(nodep->thensp());
iterateAndNextNull(nodep->elsesp());
m_insStmtp = nullptr;
}
@ -143,7 +143,7 @@ private:
iterateAndNextNull(nodep->condsp());
}
m_insStmtp = nullptr; // Next thing should be new statement
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
}
void visit(AstNodeFor* nodep) override { // LCOV_EXCL_LINE
nodep->v3fatalSrc(

View File

@ -69,7 +69,7 @@ private:
underp = VN_AS(nodep, NodeFTask)->stmtsp();
} else if (VN_IS(nodep, Foreach)) {
if (endOfIter) {
underp = VN_AS(nodep, Foreach)->bodysp();
underp = VN_AS(nodep, Foreach)->stmtsp();
} else {
underp = nodep;
under_and_next = false; // IE we skip the entire foreach
@ -78,7 +78,7 @@ private:
if (endOfIter) {
// Note we jump to end of bodysp; a FOR loop has its
// increment under incsp() which we don't skip
underp = VN_AS(nodep, While)->bodysp();
underp = VN_AS(nodep, While)->stmtsp();
} else {
underp = nodep;
under_and_next = false; // IE we skip the entire while
@ -157,7 +157,7 @@ private:
AstVar* const varp
= new AstVar(nodep->fileline(), VVarType::BLOCKTEMP, name, nodep->findSigned32DType());
varp->usedLoopIdx(true);
m_modp->addStmtp(varp);
m_modp->addStmtsp(varp);
AstNode* initsp = new AstAssign(
nodep->fileline(), new AstVarRef(nodep->fileline(), varp, VAccess::WRITE), countp);
AstNode* const decp = new AstAssign(
@ -167,7 +167,7 @@ private:
AstNode* const zerosp = new AstConst(nodep->fileline(), AstConst::Signed32(), 0);
AstNode* const condp = new AstGtS(
nodep->fileline(), new AstVarRef(nodep->fileline(), varp, VAccess::READ), zerosp);
AstNode* const bodysp = nodep->bodysp();
AstNode* const bodysp = nodep->stmtsp();
if (bodysp) bodysp->unlinkFrBackWithNext();
AstNode* newp = new AstWhile(nodep->fileline(), condp, bodysp, decp);
initsp = initsp->addNext(newp);
@ -178,7 +178,7 @@ private:
void visit(AstWait* nodep) override {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: wait statements");
// Statements we'll just execute immediately; equivalent to if they followed this
if (AstNode* const bodysp = nodep->bodysp()) {
if (AstNode* const bodysp = nodep->stmtsp()) {
bodysp->unlinkFrBackWithNext();
nodep->replaceWith(bodysp);
} else {
@ -195,7 +195,7 @@ private:
m_loopInc = false;
iterateAndNextNull(nodep->precondsp());
iterateAndNextNull(nodep->condp());
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
m_loopInc = true;
iterateAndNextNull(nodep->incsp());
}
@ -204,7 +204,7 @@ private:
VL_RESTORER(m_loopp);
{
m_loopp = nodep;
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
}
}
void visit(AstReturn* nodep) override {

View File

@ -76,7 +76,7 @@ void V3LinkLevel::modSortByLevel() {
UINFO(9, "modSortByLevel() sorted\n"); // Comment required for gcc4.6.3 / bug666
for (AstNodeModule* nodep : mods) nodep->unlinkFrBack();
UASSERT_OBJ(!v3Global.rootp()->modulesp(), v3Global.rootp(), "Unlink didn't work");
for (AstNodeModule* nodep : mods) v3Global.rootp()->addModulep(nodep);
for (AstNodeModule* nodep : mods) v3Global.rootp()->addModulesp(nodep);
UINFO(9, "modSortByLevel() done\n"); // Comment required for gcc4.6.3 / bug666
V3Global::dumpCheckGlobalTree("cells", false, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}
@ -154,7 +154,7 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) {
newmodp->modPublic(true);
newmodp->protect(false);
newmodp->timeunit(oldmodp->timeunit());
rootp->addModulep(newmodp);
rootp->addModulesp(newmodp);
// TODO the module creation above could be done after linkcells, but
// the rest must be done after data type resolution
@ -170,7 +170,7 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) {
// with module names/"v"
modp->name(), modp->name(), nullptr, nullptr, nullptr);
cellp->modp(modp);
newmodp->addStmtp(cellp);
newmodp->addStmtsp(cellp);
}
}
@ -213,7 +213,7 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
(!v3Global.opt.l2Name().empty() ? v3Global.opt.l2Name() : oldmodp->name()),
oldmodp->name(), nullptr, nullptr, nullptr);
cellp->modp(oldmodp);
newmodp->addStmtp(cellp);
newmodp->addStmtsp(cellp);
// Add pins
for (AstNode* subnodep = oldmodp->stmtsp(); subnodep; subnodep = subnodep->nextp()) {
@ -229,7 +229,7 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
AstVar* const varp = oldvarp->cloneTree(false);
varp->name(name);
varp->protect(false);
newmodp->addStmtp(varp);
newmodp->addStmtsp(varp);
varp->sigPublic(true); // User needs to be able to get to it...
if (oldvarp->isIO()) {
oldvarp->primaryIO(false);

View File

@ -372,7 +372,7 @@ private:
// lvalue is true, because we know we have a verilator public_flat_rw
// but someday we may be more general
const bool lvalue = m_varp->isSigUserRWPublic();
nodep->addStmtp(
nodep->addStmtsp(
new AstVarRef(nodep->fileline(), m_varp, lvalue ? VAccess::WRITE : VAccess::READ));
}
}
@ -596,7 +596,7 @@ private:
sensesp->unlinkFrBackWithNext();
alwaysp->sensesp(sensesp);
}
if (nodep->stmtsp()) alwaysp->addStmtp(nodep->stmtsp()->unlinkFrBackWithNext());
if (nodep->stmtsp()) alwaysp->addStmtsp(nodep->stmtsp()->unlinkFrBackWithNext());
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
}

View File

@ -86,7 +86,7 @@ private:
// Initial assignments under function/tasks can just be simple
// assignments without the initial
if (m_ftaskp) {
VL_DO_DANGLING(nodep->replaceWith(nodep->bodysp()->unlinkFrBackWithNext()), nodep);
VL_DO_DANGLING(nodep->replaceWith(nodep->stmtsp()->unlinkFrBackWithNext()), nodep);
}
}
void visit(AstNodeCoverOrAssert* nodep) override {
@ -483,7 +483,7 @@ private:
}
varoutp = varp;
// Tie off
m_modp->addStmtp(
m_modp->addStmtsp(
new AstAssignW(varp->fileline(),
new AstVarRef(varp->fileline(), varp, VAccess::WRITE),
new AstConst(varp->fileline(), AstConst::BitFalse())));

View File

@ -565,7 +565,7 @@ private:
return false;
}
if (const AstNodeCond* const condp = VN_CAST(nodep, NodeCond)) {
return yieldsOneOrZero(condp->expr1p()) && yieldsOneOrZero(condp->expr2p());
return yieldsOneOrZero(condp->thenp()) && yieldsOneOrZero(condp->elsep());
}
if (const AstCCast* const castp = VN_CAST(nodep, CCast)) {
// Cast never sign extends
@ -593,7 +593,7 @@ private:
return new AstConst{rhsp->fileline(), AstConst::BitTrue{}, condTrue};
} else if (const AstNodeCond* const condp = extractCondFromRhs(rhsp)) {
AstNode* const resp
= condTrue ? condp->expr1p()->unlinkFrBack() : condp->expr2p()->unlinkFrBack();
= condTrue ? condp->thenp()->unlinkFrBack() : condp->elsep()->unlinkFrBack();
if (condp == rhsp) return resp;
if (const AstAnd* const andp = VN_CAST(rhsp, And)) {
UASSERT_OBJ(andp->rhsp() == condp, rhsp, "Should not try to fold this");
@ -676,7 +676,7 @@ private:
// Construct the new RHSs and add to branches
thenp->rhsp(foldAndUnlink(rhsp, true));
elsep->rhsp(foldAndUnlink(rhsp, false));
resultp->addIfsp(thenp);
resultp->addThensp(thenp);
resultp->addElsesp(elsep);
// Cleanup
VL_DO_DANGLING(rhsp->deleteTree(), rhsp);
@ -684,8 +684,8 @@ private:
AstNodeIf* const ifp = VN_AS(currp, NodeIf);
UASSERT_OBJ(ifp, currp, "Must be AstNodeIf");
// Move branch contents under new if
if (AstNode* const listp = ifp->ifsp()) {
resultp->addIfsp(listp->unlinkFrBackWithNext());
if (AstNode* const listp = ifp->thensp()) {
resultp->addThensp(listp->unlinkFrBackWithNext());
}
if (AstNode* const listp = ifp->elsesp()) {
resultp->addElsesp(listp->unlinkFrBackWithNext());
@ -695,7 +695,7 @@ private:
}
} while (nextp);
// Merge the branches of the resulting AstIf after re-analysis
if (resultp->ifsp()) m_workQueuep->push(resultp->ifsp());
if (resultp->thensp()) m_workQueuep->push(resultp->thensp());
if (resultp->elsesp()) m_workQueuep->push(resultp->elsesp());
} else if (AstNodeIf* const ifp = VN_CAST(m_mgFirstp, NodeIf)) {
// There was nothing to merge this AstNodeIf with, so try to merge its branches.
@ -711,7 +711,7 @@ private:
AstNode::user2ClearTree();
// Merge recursively within the branches of an un-merged AstNodeIF
if (recursivep) {
iterateAndNextNull(recursivep->ifsp());
iterateAndNextNull(recursivep->thensp());
iterateAndNextNull(recursivep->elsesp());
// Close a pending merge to ensure merge state is
// reset as expected at the end of this function
@ -840,7 +840,7 @@ private:
// Check if mergeable
if (!checkOrMakeMergeable(nodep)) {
// If not mergeable, try to merge the branches
iterateAndNextNull(nodep->ifsp());
iterateAndNextNull(nodep->thensp());
iterateAndNextNull(nodep->elsesp());
return;
}

View File

@ -1789,7 +1789,7 @@ void OrderProcess::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* d
<< " s=" << cvtToHex(scopep) << " " << lvertexp << endl);
AstActive* const newActivep
= processMoveOneLogic(lvertexp, m_pomNewFuncp /*ref*/, m_pomNewStmts /*ref*/);
if (newActivep) m_scopetop.addActivep(newActivep);
if (newActivep) m_scopetop.addBlocksp(newActivep);
processMoveDoneOne(vertexp);
}
@ -1811,7 +1811,7 @@ AstActive* OrderProcess::processMoveOneLogic(const OrderLogicVertex* lvertexp,
// procedures. Everything else is handled in one go
AstNodeProcedure* const procp = VN_CAST(nodep, NodeProcedure);
if (procp && !v3Global.opt.profCFuncs()) {
nodep = procp->bodysp();
nodep = procp->stmtsp();
pushDeletep(procp);
}
@ -1831,7 +1831,7 @@ AstActive* OrderProcess::processMoveOneLogic(const OrderLogicVertex* lvertexp,
newFuncpr->isLoose(true);
newStmtsr = 0;
if (domainp->hasInitial() || domainp->hasSettle()) newFuncpr->slow(true);
scopep->addActivep(newFuncpr);
scopep->addBlocksp(newFuncpr);
// Create top call to it
AstCCall* const callp = new AstCCall(nodep->fileline(), newFuncpr);
// Where will we be adding the call?
@ -1886,7 +1886,7 @@ void OrderProcess::processMTasksInitial(InitialLogicE logic_type) {
}
AstActive* const newActivep
= processMoveOneLogic(initp, initCFunc /*ref*/, initStmts /*ref*/);
if (newActivep) m_scopetop.addActivep(newActivep);
if (newActivep) m_scopetop.addBlocksp(newActivep);
}
}
@ -1966,7 +1966,7 @@ void OrderProcess::processMTasks() {
// of the MTask graph.
FileLine* const rootFlp = v3Global.rootp()->fileline();
AstExecGraph* const execGraphp = new AstExecGraph{rootFlp, "eval"};
m_scopetop.addActivep(execGraphp);
m_scopetop.addBlocksp(execGraphp);
// Create CFuncs and bodies for each MTask.
GraphStream<MTaskVxIdLessThan> emit_mtasks(&mtasks);
@ -2018,7 +2018,7 @@ void OrderProcess::processMTasks() {
const MTaskState& fromState = mtaskStates[fromp->id()];
new V3GraphEdge(depGraphp, fromState.m_execMTaskp, state.m_execMTaskp, 1);
}
execGraphp->addMTaskBodyp(bodyp);
execGraphp->addMTaskBodiesp(bodyp);
}
}

View File

@ -1132,7 +1132,7 @@ class ParamVisitor final : public VNVisitor {
// NOT recurse the body.
V3Const::constifyGenerateParamsEdit(nodep->condp()); // condp may change
if (const AstConst* const constp = VN_CAST(nodep->condp(), Const)) {
if (AstNode* const keepp = (constp->isZero() ? nodep->elsesp() : nodep->ifsp())) {
if (AstNode* const keepp = (constp->isZero() ? nodep->elsesp() : nodep->thensp())) {
keepp->unlinkFrBackWithNext();
nodep->replaceWith(keepp);
} else {
@ -1150,9 +1150,7 @@ class ParamVisitor final : public VNVisitor {
//! expression, since this is currently restricted to simple comparisons. If we ever do
//! move to more generic constant expressions, such code will be needed here.
void visit(AstBegin* nodep) override {
if (nodep->genforp()) {
AstGenFor* const forp = VN_AS(nodep->genforp(), GenFor);
UASSERT_OBJ(forp, nodep, "Non-GENFOR under generate-for BEGIN");
if (AstGenFor* const forp = VN_AS(nodep->genforp(), GenFor)) {
// We should have a GENFOR under here. We will be replacing the begin,
// so process here rather than at the generate to avoid iteration problems
UINFO(9, " BEGIN " << nodep << endl);
@ -1211,7 +1209,7 @@ class ParamVisitor final : public VNVisitor {
if (const AstConst* const ccondp = VN_CAST(ep, Const)) {
V3Number match(nodep, 1);
match.opEq(ccondp->num(), exprp->num());
if (!keepp && match.isNeqZero()) keepp = itemp->bodysp();
if (!keepp && match.isNeqZero()) keepp = itemp->stmtsp();
} else {
itemp->v3error("Generate Case item does not evaluate to constant");
}
@ -1222,7 +1220,7 @@ class ParamVisitor final : public VNVisitor {
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
itemp = VN_AS(itemp->nextp(), CaseItem)) {
if (itemp->isDefault()) {
if (!keepp) keepp = itemp->bodysp();
if (!keepp) keepp = itemp->stmtsp();
}
}
// Replace
@ -1269,7 +1267,7 @@ public:
});
// Re-insert modules
for (AstNodeModule* const modp : modps) netlistp->addModulep(modp);
for (AstNodeModule* const modp : modps) netlistp->addModulesp(modp);
}
}
~ParamVisitor() override = default;

View File

@ -283,7 +283,7 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
if (errmsg != "") return; // Threw error already
// Create fake node for later error reporting
AstNodeModule* const nodep = new AstNotFoundModule(fileline, modname);
v3Global.rootp()->addModulep(nodep);
v3Global.rootp()->addModulesp(nodep);
return;
}

View File

@ -3051,7 +3051,7 @@ static void addMTaskToFunction(const ThreadSchedule& schedule, const uint32_t th
AstVar* const varp = new AstVar(fl, VVarType::MODULETEMP, name, mtaskStateDtypep);
varp->valuep(new AstConst(fl, nDependencies));
varp->protect(false); // Do not protect as we still have references in AstText
modp->addStmtp(varp);
modp->addStmtsp(varp);
// For now, reference is still via text bashing
addStrStmt("vlSelf->" + name + +".waitUntilUpstreamDone(even_cycle);\n");
}
@ -3112,7 +3112,7 @@ static const std::vector<AstCFunc*> createThreadFunctions(const ThreadSchedule&
const uint32_t threadId = schedule.threadId(thread.front());
const string name{"__Vthread__" + tag + "__" + cvtToStr(threadId)};
AstCFunc* const funcp = new AstCFunc(fl, name, nullptr, "void");
modp->addStmtp(funcp);
modp->addStmtsp(funcp);
funcps.push_back(funcp);
funcp->isStatic(true); // Uses void self pointer, so static and hand rolled
funcp->isLoose(true);
@ -3140,7 +3140,7 @@ static const std::vector<AstCFunc*> createThreadFunctions(const ThreadSchedule&
= new AstVar(fl, VVarType::MODULETEMP, "__Vm_mtaskstate_final", mtaskStateDtypep);
varp->valuep(new AstConst(fl, funcps.size()));
varp->protect(false); // Do not protect as we still have references in AstText
modp->addStmtp(varp);
modp->addStmtsp(varp);
return funcps;
}

View File

@ -176,7 +176,7 @@ private:
iterateAndNextNull(nodep->condp());
m_inWhilep = nullptr;
startStatement(nodep);
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
iterateAndNextNull(nodep->incsp());
m_stmtp = nullptr;
}
@ -329,7 +329,7 @@ private:
}
void visit(AstNodeCond* nodep) override {
iterateChildren(nodep);
if (nodep->expr1p()->isWide() && !VN_IS(nodep->condp(), Const)
if (nodep->thenp()->isWide() && !VN_IS(nodep->condp(), Const)
&& !VN_IS(nodep->condp(), VarRef)) {
// We're going to need the expression several times in the expanded code,
// so might as well make it a common expression

View File

@ -95,7 +95,7 @@ private:
}
void addComment(AstTextBlock* txtp, FileLine* fl, const string& comment) {
txtp->addNodep(new AstComment{fl, comment});
txtp->addNodesp(new AstComment{fl, comment});
}
void hashComment(AstTextBlock* txtp, FileLine* fl) {
@ -143,7 +143,7 @@ private:
// Module declaration
m_modPortsp = new AstTextBlock{fl, "module " + m_libName + " (\n", false, true};
txtp->addNodep(m_modPortsp);
txtp->addNodesp(m_modPortsp);
txtp->addText(fl, ");\n\n");
// Timescale
@ -177,7 +177,7 @@ private:
"(\n",
false, true};
m_comboPortsp->addText(fl, "chandle handle__V\n");
txtp->addNodep(m_comboPortsp);
txtp->addNodesp(m_comboPortsp);
txtp->addText(fl, ");\n\n");
seqComment(txtp, fl);
if (m_hasClk) {
@ -187,7 +187,7 @@ private:
"(\n",
false, true};
m_seqPortsp->addText(fl, "chandle handle__V\n");
txtp->addNodep(m_seqPortsp);
txtp->addNodesp(m_seqPortsp);
txtp->addText(fl, ");\n\n");
}
comboIgnoreComment(txtp, fl);
@ -197,7 +197,7 @@ private:
"(\n",
false, true};
m_comboIgnorePortsp->addText(fl, "chandle handle__V\n");
txtp->addNodep(m_comboIgnorePortsp);
txtp->addNodesp(m_comboIgnorePortsp);
txtp->addText(fl, ");\n\n");
finalComment(txtp, fl);
@ -227,17 +227,17 @@ private:
txtp->addText(fl, "\n");
m_comboDeclsp = new AstTextBlock{fl};
txtp->addNodep(m_comboDeclsp);
txtp->addNodesp(m_comboDeclsp);
m_seqDeclsp = new AstTextBlock{fl};
txtp->addNodep(m_seqDeclsp);
txtp->addNodesp(m_seqDeclsp);
m_tmpDeclsp = new AstTextBlock{fl};
txtp->addNodep(m_tmpDeclsp);
txtp->addNodesp(m_tmpDeclsp);
// CPP hash value
addComment(txtp, fl, "Hash value to make sure this file and the corresponding");
addComment(txtp, fl, "library agree");
m_hashValuep = new AstTextBlock{fl, "localparam int protectlib_hash__V = 32'd"};
txtp->addNodep(m_hashValuep);
txtp->addNodesp(m_hashValuep);
txtp->addText(fl, "\n");
// Initial
@ -256,7 +256,7 @@ private:
+ m_libName + "_protectlib_combo_update(\n",
false, true};
m_comboParamsp->addText(fl, "handle__V\n");
txtp->addNodep(m_comboParamsp);
txtp->addNodesp(m_comboParamsp);
txtp->addText(fl, ");\n");
txtp->addText(fl, "end\n\n");
@ -264,21 +264,21 @@ private:
if (m_hasClk) {
addComment(txtp, fl, "Evaluate clock edges");
m_clkSensp = new AstTextBlock{fl, "always @(", false, true};
txtp->addNodep(m_clkSensp);
txtp->addNodesp(m_clkSensp);
txtp->addText(fl, ") begin\n");
m_comboIgnoreParamsp
= new AstTextBlock{fl, m_libName + "_protectlib_combo_ignore(\n", false, true};
m_comboIgnoreParamsp->addText(fl, "handle__V\n");
txtp->addNodep(m_comboIgnoreParamsp);
txtp->addNodesp(m_comboIgnoreParamsp);
txtp->addText(fl, ");\n");
m_seqParamsp = new AstTextBlock{
fl, "last_seq_seqnum__V <= " + m_libName + "_protectlib_seq_update(\n", false,
true};
m_seqParamsp->addText(fl, "handle__V\n");
txtp->addNodep(m_seqParamsp);
txtp->addNodesp(m_seqParamsp);
txtp->addText(fl, ");\n");
m_nbAssignsp = new AstTextBlock{fl};
txtp->addNodep(m_nbAssignsp);
txtp->addNodesp(m_nbAssignsp);
txtp->addText(fl, "end\n\n");
}
@ -288,13 +288,13 @@ private:
if (m_hasClk) {
m_seqAssignsp = new AstTextBlock{fl, "if (last_seq_seqnum__V > "
"last_combo_seqnum__V) begin\n"};
txtp->addNodep(m_seqAssignsp);
txtp->addNodesp(m_seqAssignsp);
m_comboAssignsp = new AstTextBlock{fl, "end\nelse begin\n"};
txtp->addNodep(m_comboAssignsp);
txtp->addNodesp(m_comboAssignsp);
txtp->addText(fl, "end\n");
} else {
m_comboAssignsp = new AstTextBlock{fl, ""};
txtp->addNodep(m_comboAssignsp);
txtp->addNodesp(m_comboAssignsp);
}
txtp->addText(fl, "end\n\n");
@ -341,7 +341,7 @@ private:
+ "_protectlib_check_hash"
"(int protectlib_hash__V) {\n");
m_cHashValuep = new AstTextBlock{fl, "const int expected_hash__V = "};
txtp->addNodep(m_cHashValuep);
txtp->addNodesp(m_cHashValuep);
txtp->addText(fl, /**/ "if (protectlib_hash__V != expected_hash__V) {\n");
txtp->addText(fl, /****/ "fprintf(stderr, \"%%Error: cannot use " + m_libName
+ " library, "
@ -364,13 +364,13 @@ private:
m_cComboParamsp = new AstTextBlock{
fl, "long long " + m_libName + "_protectlib_combo_update(\n", false, true};
m_cComboParamsp->addText(fl, "void* vhandlep__V\n");
txtp->addNodep(m_cComboParamsp);
txtp->addNodesp(m_cComboParamsp);
txtp->addText(fl, ")\n");
m_cComboInsp = new AstTextBlock{fl, "{\n"};
castPtr(fl, m_cComboInsp);
txtp->addNodep(m_cComboInsp);
txtp->addNodesp(m_cComboInsp);
m_cComboOutsp = new AstTextBlock{fl, "handlep__V->eval();\n"};
txtp->addNodep(m_cComboOutsp);
txtp->addNodesp(m_cComboOutsp);
txtp->addText(fl, "return handlep__V->m_seqnum++;\n");
txtp->addText(fl, "}\n\n");
@ -379,13 +379,13 @@ private:
m_cSeqParamsp = new AstTextBlock{
fl, "long long " + m_libName + "_protectlib_seq_update(\n", false, true};
m_cSeqParamsp->addText(fl, "void* vhandlep__V\n");
txtp->addNodep(m_cSeqParamsp);
txtp->addNodesp(m_cSeqParamsp);
txtp->addText(fl, ")\n");
m_cSeqClksp = new AstTextBlock{fl, "{\n"};
castPtr(fl, m_cSeqClksp);
txtp->addNodep(m_cSeqClksp);
txtp->addNodesp(m_cSeqClksp);
m_cSeqOutsp = new AstTextBlock{fl, "handlep__V->eval();\n"};
txtp->addNodep(m_cSeqOutsp);
txtp->addNodesp(m_cSeqOutsp);
txtp->addText(fl, "return handlep__V->m_seqnum++;\n");
txtp->addText(fl, "}\n\n");
}
@ -394,7 +394,7 @@ private:
m_cIgnoreParamsp = new AstTextBlock{
fl, "void " + m_libName + "_protectlib_combo_ignore(\n", false, true};
m_cIgnoreParamsp->addText(fl, "void* vhandlep__V\n");
txtp->addNodep(m_cIgnoreParamsp);
txtp->addNodesp(m_cIgnoreParamsp);
txtp->addText(fl, ")\n");
txtp->addText(fl, "{ }\n\n");
@ -448,7 +448,7 @@ private:
void handleClock(AstVar* varp) {
FileLine* const fl = varp->fileline();
handleInput(varp);
m_seqPortsp->addNodep(varp->cloneTree(false));
m_seqPortsp->addNodesp(varp->cloneTree(false));
if (m_hasClk) {
m_seqParamsp->addText(fl, varp->name() + "\n");
m_clkSensp->addText(fl, "posedge " + varp->name() + " or negedge " + varp->name());
@ -460,30 +460,30 @@ private:
void handleDataInput(AstVar* varp) {
FileLine* const fl = varp->fileline();
handleInput(varp);
m_comboPortsp->addNodep(varp->cloneTree(false));
m_comboPortsp->addNodesp(varp->cloneTree(false));
m_comboParamsp->addText(fl, varp->name() + "\n");
m_comboIgnorePortsp->addNodep(varp->cloneTree(false));
m_comboIgnorePortsp->addNodesp(varp->cloneTree(false));
if (m_hasClk) m_comboIgnoreParamsp->addText(fl, varp->name() + "\n");
m_cComboParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
m_cComboInsp->addText(fl, cInputConnection(varp));
m_cIgnoreParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
}
void handleInput(AstVar* varp) { m_modPortsp->addNodep(varp->cloneTree(false)); }
void handleInput(AstVar* varp) { m_modPortsp->addNodesp(varp->cloneTree(false)); }
static void addLocalVariable(AstTextBlock* textp, AstVar* varp, const char* suffix) {
AstVar* const newVarp
= new AstVar{varp->fileline(), VVarType::VAR, varp->name() + suffix, varp->dtypep()};
textp->addNodep(newVarp);
textp->addNodesp(newVarp);
}
void handleOutput(AstVar* varp) {
FileLine* const fl = varp->fileline();
m_modPortsp->addNodep(varp->cloneTree(false));
m_comboPortsp->addNodep(varp->cloneTree(false));
m_modPortsp->addNodesp(varp->cloneTree(false));
m_comboPortsp->addNodesp(varp->cloneTree(false));
m_comboParamsp->addText(fl, varp->name() + "_combo__V\n");
if (m_hasClk) {
m_seqPortsp->addNodep(varp->cloneTree(false));
m_seqPortsp->addNodesp(varp->cloneTree(false));
m_seqParamsp->addText(fl, varp->name() + "_tmp__V\n");
}

View File

@ -144,7 +144,7 @@ private:
varp->isStatic(true);
varp->valuep(initp);
// Add to root, as don't know module we are in, and aids later structure sharing
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp);
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp);
UASSERT_OBJ(nodep->itemsp(), nodep, "Enum without items");
for (AstEnumItem* itemp = nodep->itemsp(); itemp;
itemp = VN_AS(itemp->nextp(), EnumItem)) {

View File

@ -114,7 +114,7 @@ private:
AstWhile* const whilep = new AstWhile(fl, condp, nullptr, incp);
initp->addNext(whilep);
bodyp->replaceWith(initp);
whilep->addBodysp(bodyp);
whilep->addStmtsp(bodyp);
// Replace constant index with new loop index
AstNode* const offsetp

View File

@ -135,7 +135,7 @@ private:
if (m_modp->isTop()) {
v3Global.rootp()->createTopScope(m_scopep);
} else {
m_modp->addStmtp(m_scopep);
m_modp->addStmtsp(m_scopep);
}
// Copy blocks into this scope
@ -188,7 +188,7 @@ private:
UINFO(4, " Move " << nodep << endl);
AstNode* const clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
m_scopep->addBlocksp(clonep);
iterateChildren(clonep); // We iterate under the *clone*
}
void visit(AstAssignAlias* nodep) override {
@ -196,7 +196,7 @@ private:
UINFO(4, " Move " << nodep << endl);
AstNode* const clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
m_scopep->addBlocksp(clonep);
iterateChildren(clonep); // We iterate under the *clone*
}
void visit(AstAssignVarScope* nodep) override {
@ -204,7 +204,7 @@ private:
UINFO(4, " Move " << nodep << endl);
AstNode* const clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
m_scopep->addBlocksp(clonep);
iterateChildren(clonep); // We iterate under the *clone*
}
void visit(AstAssignW* nodep) override {
@ -212,7 +212,7 @@ private:
UINFO(4, " Move " << nodep << endl);
AstNode* const clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
m_scopep->addBlocksp(clonep);
iterateChildren(clonep); // We iterate under the *clone*
}
void visit(AstAlwaysPublic* nodep) override {
@ -220,7 +220,7 @@ private:
UINFO(4, " Move " << nodep << endl);
AstNode* const clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
m_scopep->addBlocksp(clonep);
iterateChildren(clonep); // We iterate under the *clone*
}
void visit(AstCoverToggle* nodep) override {
@ -228,7 +228,7 @@ private:
UINFO(4, " Move " << nodep << endl);
AstNode* const clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
m_scopep->addBlocksp(clonep);
iterateChildren(clonep); // We iterate under the *clone*
}
void visit(AstCFunc* nodep) override {
@ -236,7 +236,7 @@ private:
UINFO(4, " CFUNC " << nodep << endl);
AstCFunc* const clonep = nodep->cloneTree(false);
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
m_scopep->addBlocksp(clonep);
clonep->scopep(m_scopep);
// We iterate under the *clone*
iterateChildren(clonep);
@ -253,7 +253,7 @@ private:
clonep = nodep->cloneTree(false);
}
nodep->user2p(clonep);
m_scopep->addActivep(clonep);
m_scopep->addBlocksp(clonep);
// We iterate under the *clone*
iterateChildren(clonep);
}
@ -272,7 +272,7 @@ private:
}
UASSERT_OBJ(m_scopep, nodep, "No scope for var");
m_varScopes.emplace(std::make_pair(nodep, m_scopep), varscp);
m_scopep->addVarp(varscp);
m_scopep->addVarsp(varscp);
}
}
void visit(AstVarRef* nodep) override {
@ -295,14 +295,14 @@ private:
// 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
AstNode* afterp = nodep->scopeAttrp();
AstText* afterp = nodep->scopeAttrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->scopeAttrp(new AstText(nodep->fileline(), prefix));
if (afterp) nodep->scopeAttrp(afterp);
nodep->addScopeAttrp(new AstText(nodep->fileline(), prefix));
if (afterp) nodep->addScopeAttrp(afterp);
afterp = nodep->scopeEntrp();
if (afterp) afterp->unlinkFrBackWithNext();
nodep->scopeEntrp(new AstText(nodep->fileline(), prefix));
if (afterp) nodep->scopeEntrp(afterp);
nodep->addScopeEntrp(new AstText(nodep->fileline(), prefix));
if (afterp) nodep->addScopeEntrp(afterp);
iterateChildren(nodep);
}
void visit(AstScope* nodep) override {

View File

@ -64,7 +64,7 @@ public:
// Not found, create a new one
AstSenTree* const newSenTreep = senTreep->cloneTree(false);
m_topScopep->addSenTreep(newSenTreep);
m_topScopep->addSenTreesp(newSenTreep);
m_trees.emplace(*newSenTreep);
return newSenTreep;
}

View File

@ -513,7 +513,7 @@ private:
iterateAndNextNull(nodep->condp());
if (optimizable()) {
if (fetchConst(nodep->condp())->num().isNeqZero()) {
iterateAndNextNull(nodep->ifsp());
iterateAndNextNull(nodep->thensp());
} else {
iterateAndNextNull(nodep->elsesp());
}
@ -647,11 +647,11 @@ private:
iterate(nodep->condp());
if (optimizable()) {
if (fetchConst(nodep->condp())->num().isNeqZero()) {
iterate(nodep->expr1p());
newValue(nodep, fetchValue(nodep->expr1p()));
iterate(nodep->thenp());
newValue(nodep, fetchValue(nodep->thenp()));
} else {
iterate(nodep->expr2p());
newValue(nodep, fetchValue(nodep->expr2p()));
iterate(nodep->elsep());
newValue(nodep, fetchValue(nodep->elsep()));
}
}
}
@ -835,7 +835,7 @@ private:
V3Number match{nodep, 1};
match.opEq(fetchConst(nodep->exprp())->num(), fetchConst(ep)->num());
if (match.isNeqZero()) {
iterateAndNextNull(itemp->bodysp());
iterateAndNextNull(itemp->stmtsp());
hit = true;
}
}
@ -847,7 +847,7 @@ private:
itemp = VN_AS(itemp->nextp(), CaseItem)) {
if (hit) break;
if (!hit && itemp->isDefault()) {
iterateAndNextNull(itemp->bodysp());
iterateAndNextNull(itemp->stmtsp());
hit = true;
}
}
@ -917,7 +917,7 @@ private:
if (!fetchConst(nodep->condp())->num().isNeqZero()) { //
break;
}
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
iterateAndNextNull(nodep->incsp());
if (loops++ > unrollCount() * 16) {
clearOptimizable(nodep, "Loop unrolling took too long; probably this is an"
@ -952,7 +952,7 @@ private:
if (!fetchConst(nodep->condp())->num().isNeqZero()) { //
break;
}
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
if (jumpingOver(nodep)) break;
iterateAndNextNull(nodep->incsp());
if (jumpingOver(nodep)) break;

View File

@ -101,8 +101,8 @@ class SliceVisitor final : public VNVisitor {
} else if (AstNodeCond* const snodep = VN_CAST(nodep, NodeCond)) {
UINFO(9, " cloneCond(" << elements << "," << offset << ") " << nodep << endl);
return snodep->cloneType(snodep->condp()->cloneTree(false),
cloneAndSel(snodep->expr1p(), elements, offset),
cloneAndSel(snodep->expr2p(), elements, offset));
cloneAndSel(snodep->thenp(), elements, offset),
cloneAndSel(snodep->elsep(), elements, offset));
} else if (const AstSliceSel* const snodep = VN_CAST(nodep, SliceSel)) {
UINFO(9, " cloneSliceSel(" << elements << "," << offset << ") " << nodep << endl);
const int leOffset = (snodep->declRange().lo()

View File

@ -601,14 +601,14 @@ protected:
UINFO(4, " ALW " << nodep << endl);
if (debug() >= 9) nodep->dumpTree(cout, " alwIn:: ");
scoreboardClear();
processBlock(nodep->bodysp());
processBlock(nodep->stmtsp());
if (debug() >= 9) nodep->dumpTree(cout, " alwOut: ");
}
void visit(AstNodeIf* nodep) override {
UINFO(4, " IF " << nodep << endl);
iterateAndNextNull(nodep->condp());
processBlock(nodep->ifsp());
processBlock(nodep->thensp());
processBlock(nodep->elsesp());
}
@ -713,14 +713,14 @@ public:
// Put a placeholder node into stmtp to track our position.
// We'll strip these out after the blocks are fully cloned.
AstSplitPlaceholder* const placeholderp = makePlaceholderp();
alwaysp->addStmtp(placeholderp);
alwaysp->addStmtsp(placeholderp);
m_addAfter[color] = placeholderp;
m_newBlocksp->push_back(alwaysp);
}
// Scan the body of the always. We'll handle if/else
// specially, everything else is a leaf node that we can
// just clone into one of the split always blocks.
iterateAndNextNull(m_origAlwaysp->bodysp());
iterateAndNextNull(m_origAlwaysp->stmtsp());
}
protected:
@ -776,7 +776,7 @@ protected:
m_addAfter[color] = if_placeholderp;
}
iterateAndNextNull(nodep->ifsp());
iterateAndNextNull(nodep->thensp());
for (const auto& color : colors) m_addAfter[color] = clones[color]->elsesp();
@ -804,7 +804,7 @@ class RemovePlaceholdersVisitor final : public VNVisitor {
VL_RESTORER(m_isPure);
m_isPure = true;
iterateChildren(nodep);
if (!nodep->ifsp() && !nodep->elsesp() && m_isPure) pushDeletep(nodep->unlinkFrBack());
if (!nodep->thensp() && !nodep->elsesp() && m_isPure) pushDeletep(nodep->unlinkFrBack());
}
void visit(AstAlways* nodep) override {
VL_RESTORER(m_isPure);
@ -812,7 +812,7 @@ class RemovePlaceholdersVisitor final : public VNVisitor {
iterateChildren(nodep);
if (m_isPure) {
bool emptyOrCommentOnly = true;
for (AstNode* bodysp = nodep->bodysp(); bodysp; bodysp = bodysp->nextp()) {
for (AstNode* bodysp = nodep->stmtsp(); bodysp; bodysp = bodysp->nextp()) {
// If this always block contains only AstComment, remove here.
// V3Gate will remove anyway.
if (!VN_IS(bodysp, Comment)) {
@ -955,7 +955,7 @@ protected:
void visit(AstAlways* nodep) override {
// build the scoreboard
scoreboardClear();
scanBlock(nodep->bodysp());
scanBlock(nodep->stmtsp());
if (m_noReorderWhy != "") {
// We saw a jump or something else rare that we don't handle.
@ -989,7 +989,7 @@ protected:
m_curIfConditional = nodep;
iterateAndNextNull(nodep->condp());
m_curIfConditional = nullptr;
scanBlock(nodep->ifsp());
scanBlock(nodep->thensp());
scanBlock(nodep->elsesp());
}

View File

@ -191,16 +191,16 @@ struct SplitVarImpl {
template <class T_ALWAYSLIKE>
void insertBeginCore(T_ALWAYSLIKE* ap, AstNodeStmt* stmtp, AstNodeModule* modp) {
if (ap->isJustOneBodyStmt() && ap->bodysp() == stmtp) {
if (ap->isJustOneBodyStmt() && ap->stmtsp() == stmtp) {
stmtp->unlinkFrBack();
// Insert begin-end because temp value may be inserted to this block later.
const std::string name = "__VsplitVarBlk" + cvtToStr(modp->user1Inc(1));
ap->addStmtp(new AstBegin{ap->fileline(), name, stmtp});
ap->addStmtsp(new AstBegin{ap->fileline(), name, stmtp});
}
}
void insertBeginCore(AstInitial* initp, AstNodeStmt* stmtp, AstNodeModule* modp) {
if (initp->isJustOneBodyStmt() && initp->bodysp() == stmtp) {
if (initp->isJustOneBodyStmt() && initp->stmtsp() == stmtp) {
stmtp->unlinkFrBack();
// Insert begin-end because temp value may be inserted to this block later.
FileLine* const fl = initp->fileline();
@ -477,7 +477,7 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl {
if (nodep->sensesp()) { // When visiting sensitivity list, always is the context
setContextAndIterate(nodep, nodep->sensesp());
}
for (AstNode* bodysp = nodep->bodysp(); bodysp; bodysp = bodysp->nextp()) {
for (AstNode* bodysp = nodep->stmtsp(); bodysp; bodysp = bodysp->nextp()) {
iterate(bodysp);
}
};
@ -485,7 +485,7 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl {
if (nodep->sensesp()) { // When visiting sensitivity list, always is the context
setContextAndIterate(nodep, nodep->sensesp());
}
for (AstNode* bodysp = nodep->bodysp(); bodysp; bodysp = bodysp->nextp()) {
for (AstNode* bodysp = nodep->stmtsp(); bodysp; bodysp = bodysp->nextp()) {
iterate(bodysp);
}
}

View File

@ -141,7 +141,7 @@ private:
{
m_counting = false;
m_instrs = 0.0;
iterateAndNextConstNull(nodep->ifsp());
iterateAndNextConstNull(nodep->thensp());
ifInstrs = m_instrs;
}
}
@ -158,7 +158,7 @@ private:
// Now collect the stats
if (m_counting) {
if (ifInstrs >= elseInstrs) {
iterateAndNextConstNull(nodep->ifsp());
iterateAndNextConstNull(nodep->thensp());
} else {
iterateAndNextConstNull(nodep->elsesp());
}

View File

@ -253,9 +253,9 @@ private:
AstVar* const indexVarp
= new AstVar{fl, VVarType::BLOCKTEMP, "__Vtableidx" + cvtToStr(m_modTables),
VFlagBitPacked{}, static_cast<int>(m_inWidthBits)};
m_modp->addStmtp(indexVarp);
m_modp->addStmtsp(indexVarp);
AstVarScope* const indexVscp = new AstVarScope{indexVarp->fileline(), m_scopep, indexVarp};
m_scopep->addVarp(indexVscp);
m_scopep->addVarsp(indexVscp);
// The 'output assigned' table builder
TableBuilder outputAssignedTableBuilder{fl};
@ -274,8 +274,8 @@ private:
// Link it in.
// Keep sensitivity list, but delete all else
nodep->bodysp()->unlinkFrBackWithNext()->deleteTree();
nodep->addStmtp(stmtsp);
nodep->stmtsp()->unlinkFrBackWithNext()->deleteTree();
nodep->addStmtsp(stmtsp);
if (debug() >= 6) nodep->dumpTree(cout, " table_new: ");
}

View File

@ -250,7 +250,7 @@ private:
}
UASSERT_OBJ(m_ctorp, nodep, "class constructor missing"); // LinkDot always makes it
for (AstInitialAutomatic* initialp : m_initialps) {
if (AstNode* const newp = initialp->bodysp()) {
if (AstNode* const newp = initialp->stmtsp()) {
newp->unlinkFrBackWithNext();
if (!m_ctorp->stmtsp()) {
m_ctorp->addStmtsp(newp);
@ -371,7 +371,7 @@ private:
newvarp->funcLocal(true);
funcp->addInitsp(newvarp);
AstVarScope* const newvscp = new AstVarScope(funcp->fileline(), m_scopep, newvarp);
m_scopep->addVarp(newvscp);
m_scopep->addVarsp(newvscp);
return newvscp;
}
AstVarScope* createInputVar(AstCFunc* funcp, const string& name, VBasicDTypeKwd kwd) {
@ -381,7 +381,7 @@ private:
newvarp->direction(VDirection::INPUT);
funcp->addArgsp(newvarp);
AstVarScope* const newvscp = new AstVarScope(funcp->fileline(), m_scopep, newvarp);
m_scopep->addVarp(newvscp);
m_scopep->addVarsp(newvscp);
return newvscp;
}
AstVarScope* createVarScope(AstVar* invarp, const string& name) {
@ -397,9 +397,9 @@ private:
= new AstVar{invarp->fileline(), VVarType::BLOCKTEMP, name, invarp};
newvarp->funcLocal(false);
newvarp->propagateAttrFrom(invarp);
m_modp->addStmtp(newvarp);
m_modp->addStmtsp(newvarp);
AstVarScope* const newvscp = new AstVarScope{newvarp->fileline(), m_scopep, newvarp};
m_scopep->addVarp(newvscp);
m_scopep->addVarsp(newvscp);
return newvscp;
}
}
@ -766,7 +766,7 @@ private:
funcp->protect(false);
funcp->cname(nodep->cname());
// Add DPI Export to top, since it's a global function
m_topScopep->scopep()->addActivep(funcp);
m_topScopep->scopep()->addBlocksp(funcp);
{ // Create dispatch wrapper
// Note this function may dispatch to myfunc on a different class.
@ -855,9 +855,9 @@ private:
// doesn't rip up the variables on us
args += ");\n";
AstCStmt* const newp = new AstCStmt(nodep->fileline(), "(*__Vcb)(");
newp->addBodysp(argnodesp);
newp->addExprsp(argnodesp);
VL_DANGLING(argnodesp);
newp->addBodysp(new AstText(nodep->fileline(), args, true));
newp->addExprsp(new AstText(nodep->fileline(), args, true));
funcp->addStmtsp(newp);
}
@ -899,7 +899,7 @@ private:
funcp->protect(false);
funcp->pure(nodep->pure());
// Add DPI Import to top, since it's a global function
m_topScopep->scopep()->addActivep(funcp);
m_topScopep->scopep()->addBlocksp(funcp);
makePortList(nodep, funcp);
return funcp;
}
@ -1064,9 +1064,9 @@ private:
FileLine* const fl = m_topScopep->fileline();
AstVar* const varp
= new AstVar{fl, VVarType::VAR, "__Vdpi_export_trigger", VFlagBitPacked{}, 1};
m_topScopep->scopep()->modp()->addStmtp(varp);
m_topScopep->scopep()->modp()->addStmtsp(varp);
dpiExportTriggerp = new AstVarScope{fl, m_topScopep->scopep(), varp};
m_topScopep->scopep()->addVarp(dpiExportTriggerp);
m_topScopep->scopep()->addVarsp(dpiExportTriggerp);
v3Global.rootp()->dpiExportTriggerp(dpiExportTriggerp);
}
return dpiExportTriggerp;
@ -1134,7 +1134,7 @@ private:
AstVarScope* rtnvscp = nullptr;
if (rtnvarp) {
rtnvscp = new AstVarScope(rtnvarp->fileline(), m_scopep, rtnvarp);
m_scopep->addVarp(rtnvscp);
m_scopep->addVarsp(rtnvscp);
rtnvarp->user2p(rtnvscp);
}
@ -1228,7 +1228,7 @@ private:
}
AstVarScope* const newvscp
= new AstVarScope{portp->fileline(), m_scopep, portp};
m_scopep->addVarp(newvscp);
m_scopep->addVarsp(newvscp);
portp->user2p(newvscp);
}
}
@ -1314,9 +1314,9 @@ private:
new AstVarRef{fl, dpiExportTriggerp, VAccess::READ}}},
nullptr};
for (AstVarScope* const varScopep : writtenps) {
alwaysp->addStmtp(new AstDpiExportUpdated{fl, varScopep});
alwaysp->addStmtsp(new AstDpiExportUpdated{fl, varScopep});
}
m_scopep->addActivep(alwaysp);
m_scopep->addBlocksp(alwaysp);
}
}
@ -1516,7 +1516,7 @@ private:
iterateAndNextNull(nodep->condp());
// Body insert just before themselves
m_insStmtp = nullptr; // First thing should be new statement
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
iterateAndNextNull(nodep->incsp());
// Done the loop
m_insStmtp = nullptr; // Next thing should be new statement

View File

@ -454,9 +454,9 @@ private:
v3Global.rootp()->typeTablep()->addTypesp(newArrDtp);
AstVar* const newvarp
= new AstVar(flp, VVarType::MODULETEMP, "__Vm_traceActivity", newArrDtp);
m_topModp->addStmtp(newvarp);
m_topModp->addStmtsp(newvarp);
AstVarScope* const newvscp = new AstVarScope(flp, m_topScopep, newvarp);
m_topScopep->addVarp(newvscp);
m_topScopep->addVarsp(newvscp);
m_activityVscp = newvscp;
// Insert activity setters
@ -493,7 +493,7 @@ private:
funcp->slow(full);
funcp->isStatic(isTopFunc);
// Add it to top scope
m_topScopep->addActivep(funcp);
m_topScopep->addBlocksp(funcp);
const auto addInitStr = [funcp, flp](const string& str) -> void {
funcp->addInitsp(new AstCStmt(flp, str));
};
@ -676,7 +676,7 @@ private:
// Add TraceInc node
AstTraceInc* const incp
= new AstTraceInc(declp->fileline(), declp, /* full: */ false, baseCode);
ifp->addIfsp(incp);
ifp->addThensp(incp);
subStmts += incp->nodeCount();
// Track partitioning
@ -698,7 +698,7 @@ private:
cleanupFuncp->slow(false);
cleanupFuncp->isStatic(true);
cleanupFuncp->isLoose(true);
m_topScopep->addActivep(cleanupFuncp);
m_topScopep->addBlocksp(cleanupFuncp);
cleanupFuncp->addInitsp(new AstCStmt(fl, voidSelfAssign(m_topModp)));
cleanupFuncp->addInitsp(new AstCStmt(fl, symClassAssign()));
@ -755,7 +755,7 @@ private:
m_regFuncp->slow(true);
m_regFuncp->isStatic(false);
m_regFuncp->isLoose(true);
m_topScopep->addActivep(m_regFuncp);
m_topScopep->addBlocksp(m_regFuncp);
// Create the full dump functions, also allocates signal numbers
createFullTraceFunction(traces, nFullCodes, m_parallelism);

View File

@ -162,7 +162,7 @@ private:
funcp->isStatic(false);
funcp->isLoose(true);
funcp->slow(true);
topScopep->addActivep(funcp);
topScopep->addBlocksp(funcp);
return funcp;
}
@ -303,8 +303,8 @@ private:
scopeName = scopeName.substr(0, lastDot + 1);
const size_t scopeLen = scopeName.length();
UASSERT_OBJ(cellp->intfRefp(), cellp, "Interface without tracing reference");
for (AstIntfRef *irp = cellp->intfRefp(), *nextIrp; irp; irp = nextIrp) {
UASSERT_OBJ(cellp->intfRefsp(), cellp, "Interface without tracing reference");
for (AstIntfRef *irp = cellp->intfRefsp(), *nextIrp; irp; irp = nextIrp) {
nextIrp = VN_AS(irp->nextp(), IntfRef);
const string irpName = irp->prettyName();

View File

@ -422,7 +422,7 @@ class TristateVisitor final : public TristateBaseVisitor {
"Unsupported: Creating tristate signal not underneath a module: "
<< nodep->prettyNameQ());
} else {
m_modp->addStmtp(newp);
m_modp->addStmtsp(newp);
}
}
void associateLogic(AstNode* fromp, AstNode* top) {
@ -554,7 +554,7 @@ class TristateVisitor final : public TristateBaseVisitor {
AstNode* const newp = new AstAssignW(varp->fileline(), varrefp, constp);
UINFO(9, " newoev " << newp << endl);
varrefp->user1p(newAllZerosOrOnes(varp, false));
nodep->addStmtp(newp);
nodep->addStmtsp(newp);
mapInsertLhsVarRef(varrefp); // insertTristates will convert
// // to a varref to the __out# variable
}
@ -627,7 +627,7 @@ class TristateVisitor final : public TristateBaseVisitor {
lhsp->name() + "__out" + cvtToStr(m_unique),
VFlagBitPacked(), w); // 2-state ok; sep enable
UINFO(9, " newout " << newlhsp << endl);
nodep->addStmtp(newlhsp);
nodep->addStmtsp(newlhsp);
refp->varp(newlhsp); // assign the new var to the varref
refp->name(newlhsp->name());
@ -636,13 +636,13 @@ class TristateVisitor final : public TristateBaseVisitor {
lhsp->name() + "__en" + cvtToStr(m_unique++),
VFlagBitPacked(), w); // 2-state ok
UINFO(9, " newenp " << newenp << endl);
nodep->addStmtp(newenp);
nodep->addStmtsp(newenp);
AstNode* const enassp = new AstAssignW(
refp->fileline(), new AstVarRef(refp->fileline(), newenp, VAccess::WRITE),
getEnp(refp));
UINFO(9, " newass " << enassp << endl);
nodep->addStmtp(enassp);
nodep->addStmtsp(enassp);
// now append this driver to the driver logic.
AstNode* const ref1p = new AstVarRef(refp->fileline(), newlhsp, VAccess::READ);
@ -675,7 +675,7 @@ class TristateVisitor final : public TristateBaseVisitor {
VL_DO_DANGLING(undrivenp->deleteTree(), undrivenp);
}
if (envarp) {
nodep->addStmtp(new AstAssignW(
nodep->addStmtsp(new AstAssignW(
enp->fileline(), new AstVarRef(envarp->fileline(), envarp, VAccess::WRITE), enp));
}
// __out (child) or <in> (parent) = drive-value expression
@ -683,7 +683,7 @@ class TristateVisitor final : public TristateBaseVisitor {
lhsp->fileline(), new AstVarRef(lhsp->fileline(), lhsp, VAccess::WRITE), orp);
assp->user2(U2_BOTH); // Don't process further; already resolved
if (debug() >= 9) assp->dumpTree(cout, "-lhsp-eqn: ");
nodep->addStmtp(assp);
nodep->addStmtsp(assp);
}
void addToAssignmentList(AstAssignW* nodep) {
@ -864,11 +864,11 @@ class TristateVisitor final : public TristateBaseVisitor {
if (m_graphing) {
iterateChildren(nodep);
if (m_alhs) {
associateLogic(nodep, nodep->expr1p());
associateLogic(nodep, nodep->expr2p());
associateLogic(nodep, nodep->thenp());
associateLogic(nodep, nodep->elsep());
} else {
associateLogic(nodep->expr1p(), nodep);
associateLogic(nodep->expr2p(), nodep);
associateLogic(nodep->thenp(), nodep);
associateLogic(nodep->elsep(), nodep);
}
} else {
if (m_alhs && nodep->user1p()) {
@ -887,20 +887,20 @@ class TristateVisitor final : public TristateBaseVisitor {
condp->v3warn(E_UNSUPPORTED, "Unsupported: don't know how to deal with "
"tristate logic in the conditional expression");
}
AstNode* const expr1p = nodep->expr1p();
AstNode* const expr2p = nodep->expr2p();
if (expr1p->user1p() || expr2p->user1p()) { // else no tristates
AstNode* const thenp = nodep->thenp();
AstNode* const elsep = nodep->elsep();
if (thenp->user1p() || elsep->user1p()) { // else no tristates
m_tgraph.didProcess(nodep);
AstNode* const en1p = getEnp(expr1p);
AstNode* const en2p = getEnp(expr2p);
AstNode* const en1p = getEnp(thenp);
AstNode* const en2p = getEnp(elsep);
// The output enable of a cond is a cond of the output enable of the
// two expressions with the same conditional.
AstNode* const enp
= new AstCond(nodep->fileline(), condp->cloneTree(false), en1p, en2p);
UINFO(9, " newcond " << enp << endl);
nodep->user1p(enp); // propagate up COND(lhsp->enable, rhsp->enable)
expr1p->user1p(nullptr);
expr2p->user1p(nullptr);
thenp->user1p(nullptr);
elsep->user1p(nullptr);
}
}
}
@ -1391,7 +1391,7 @@ class TristateVisitor final : public TristateBaseVisitor {
UINFO(9, " newpin " << enpinp << endl);
enpinp->user2(U2_BOTH); // don't iterate the pin later
nodep->addNextHere(enpinp);
m_modp->addStmtp(enVarp);
m_modp->addStmtsp(enVarp);
enrefp = new AstVarRef(nodep->fileline(), enVarp, VAccess::READ);
UINFO(9, " newvrf " << enrefp << endl);
if (debug() >= 9) enpinp->dumpTree(cout, "-pin-ena: ");
@ -1608,7 +1608,7 @@ class TristateVisitor final : public TristateBaseVisitor {
void visit(AstCaseItem* nodep) override {
// don't deal with casez compare '???? values
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
}
void visit(AstCell* nodep) override {

View File

@ -120,7 +120,7 @@ private:
} else {
AstVar* const varp
= new AstVar(fl, VVarType::MODULETEMP, m_lvboundNames.get(prep), prep->dtypep());
m_modp->addStmtp(varp);
m_modp->addStmtsp(varp);
AstNode* const abovep = prep->backp(); // Grab above point before we replace 'prep'
prep->replaceWith(new AstVarRef(fl, varp, VAccess::WRITE));
AstIf* const newp = new AstIf(
@ -173,7 +173,7 @@ private:
m_constXCvt = false; // Avoid losing the X's in casex
iterateAndNextNull(nodep->condsp());
m_constXCvt = true;
iterateAndNextNull(nodep->bodysp());
iterateAndNextNull(nodep->stmtsp());
}
}
void visit(AstNodeDType* nodep) override {
@ -353,9 +353,9 @@ private:
// Add inits in front of other statement.
// In the future, we should stuff the initp into the module's constructor.
AstNode* const afterp = m_modp->stmtsp()->unlinkFrBackWithNext();
m_modp->addStmtp(newvarp);
m_modp->addStmtp(newinitp);
m_modp->addStmtp(afterp);
m_modp->addStmtsp(newvarp);
m_modp->addStmtsp(newinitp);
m_modp->addStmtsp(afterp);
if (debug() >= 9) newref1p->dumpTree(cout, " _new: ");
if (debug() >= 9) newvarp->dumpTree(cout, " _new: ");
if (debug() >= 9) newinitp->dumpTree(cout, " _new: ");

View File

@ -387,21 +387,21 @@ private:
if (nodep->backp()->nextp() == nodep) initp = nodep->backp();
// Grab assignment
AstNode* incp = nullptr; // Should be last statement
AstNode* bodysp = nodep->bodysp();
AstNode* stmtsp = nodep->stmtsp();
if (nodep->incsp()) V3Const::constifyEdit(nodep->incsp());
// cppcheck-suppress duplicateCondition
if (nodep->incsp()) {
incp = nodep->incsp();
} else {
for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {}
for (incp = nodep->stmtsp(); incp && incp->nextp(); incp = incp->nextp()) {}
if (incp) VL_DO_DANGLING(V3Const::constifyEdit(incp), incp);
// Again, as may have changed
bodysp = nodep->bodysp();
for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {}
if (incp == bodysp) bodysp = nullptr;
stmtsp = nodep->stmtsp();
for (incp = nodep->stmtsp(); incp && incp->nextp(); incp = incp->nextp()) {}
if (incp == stmtsp) stmtsp = nullptr;
}
// And check it
if (forUnrollCheck(nodep, initp, nodep->precondsp(), nodep->condp(), incp, bodysp)) {
if (forUnrollCheck(nodep, initp, nodep->precondsp(), nodep->condp(), incp, stmtsp)) {
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Did replacement
}
}
@ -426,7 +426,7 @@ private:
// deleted by V3Const.
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
} else if (forUnrollCheck(nodep, nodep->initsp(), nullptr, nodep->condp(),
nodep->incsp(), nodep->bodysp())) {
nodep->incsp(), nodep->stmtsp())) {
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Did replacement
} else {
nodep->v3error("For loop doesn't have genvar index, or is malformed");

View File

@ -188,7 +188,7 @@ class VariableOrder final {
stmtsp->unlinkFrBackWithNext();
AstNode::addNext<AstNode, AstNode>(firstp, stmtsp);
}
modp->addStmtp(firstp);
modp->addStmtsp(firstp);
}
}

View File

@ -462,22 +462,22 @@ private:
iterateCheckBool(nodep, "Conditional Test", nodep->condp(), BOTH);
// Determine sub expression widths only relying on what's in the subops
// CONTEXT determined, but need data type for pattern assignments
userIterateAndNext(nodep->expr1p(), WidthVP(m_vup->dtypeNullp(), PRELIM).p());
userIterateAndNext(nodep->expr2p(), WidthVP(m_vup->dtypeNullp(), PRELIM).p());
userIterateAndNext(nodep->thenp(), WidthVP(m_vup->dtypeNullp(), PRELIM).p());
userIterateAndNext(nodep->elsep(), WidthVP(m_vup->dtypeNullp(), PRELIM).p());
// Calculate width of this expression.
// First call (prelim()) m_vup->width() is probably zero, so we'll return
// the size of this subexpression only.
// Second call (final()) m_vup->width() is probably the expression size, so
// the expression includes the size of the output too.
if (nodep->expr1p()->isDouble() || nodep->expr2p()->isDouble()) {
if (nodep->thenp()->isDouble() || nodep->elsep()->isDouble()) {
nodep->dtypeSetDouble();
} else if (nodep->expr1p()->isString() || nodep->expr2p()->isString()) {
} else if (nodep->thenp()->isString() || nodep->elsep()->isString()) {
nodep->dtypeSetString();
} else {
const int width = std::max(nodep->expr1p()->width(), nodep->expr2p()->width());
const int width = std::max(nodep->thenp()->width(), nodep->elsep()->width());
const int mwidth
= std::max(nodep->expr1p()->widthMin(), nodep->expr2p()->widthMin());
const bool issigned = nodep->expr1p()->isSigned() && nodep->expr2p()->isSigned();
= std::max(nodep->thenp()->widthMin(), nodep->elsep()->widthMin());
const bool issigned = nodep->thenp()->isSigned() && nodep->elsep()->isSigned();
nodep->dtypeSetLogicUnsized(width, mwidth, VSigning::fromBool(issigned));
}
}
@ -486,9 +486,9 @@ private:
AstNodeDType* const subDTypep = expDTypep;
nodep->dtypeFrom(expDTypep);
// Error report and change sizes for suboperands of this node.
iterateCheck(nodep, "Conditional True", nodep->expr1p(), CONTEXT, FINAL, subDTypep,
iterateCheck(nodep, "Conditional True", nodep->thenp(), CONTEXT, FINAL, subDTypep,
EXTEND_EXP);
iterateCheck(nodep, "Conditional False", nodep->expr2p(), CONTEXT, FINAL, subDTypep,
iterateCheck(nodep, "Conditional False", nodep->elsep(), CONTEXT, FINAL, subDTypep,
EXTEND_EXP);
}
}
@ -1834,7 +1834,7 @@ private:
castSized(nodep, nodep->fromp(), width);
// Note castSized might modify nodep->fromp()
} else {
iterateCheck(nodep, "value", nodep->lhsp(), SELF, FINAL, fromDtp, EXTEND_EXP,
iterateCheck(nodep, "value", nodep->fromp(), SELF, FINAL, fromDtp, EXTEND_EXP,
false);
}
if (basicp->isDouble() && !nodep->fromp()->isDouble()) {
@ -1866,14 +1866,14 @@ private:
<< toDtp->prettyDTypeNameQ());
}
if (!newp) newp = nodep->fromp()->unlinkFrBack();
nodep->lhsp(newp);
nodep->fromp(newp);
// if (debug()) nodep->dumpTree(cout, " CastOut: ");
// if (debug()) nodep->backp()->dumpTree(cout, " CastOutUpUp: ");
}
if (m_vup->final()) {
iterateCheck(nodep, "value", nodep->lhsp(), SELF, FINAL, nodep->lhsp()->dtypep(),
iterateCheck(nodep, "value", nodep->fromp(), SELF, FINAL, nodep->fromp()->dtypep(),
EXTEND_EXP, false);
AstNode* const underp = nodep->lhsp()->unlinkFrBack();
AstNode* const underp = nodep->fromp()->unlinkFrBack();
// if (debug()) underp->dumpTree(cout, " CastRep: ");
nodep->replaceWith(underp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
@ -3972,7 +3972,7 @@ private:
userIterateAndNext(nodep->exprp(), WidthVP(CONTEXT, PRELIM).p());
for (AstCaseItem *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) {
nextip = VN_AS(itemp->nextp(), CaseItem); // Prelim may cause the node to get replaced
if (!VN_IS(nodep, GenCase)) userIterateAndNext(itemp->bodysp(), nullptr);
if (!VN_IS(nodep, GenCase)) userIterateAndNext(itemp->stmtsp(), nullptr);
for (AstNode *nextcp, *condp = itemp->condsp(); condp; condp = nextcp) {
nextcp = condp->nextp(); // Prelim may cause the node to get replaced
VL_DO_DANGLING(userIterate(condp, WidthVP(CONTEXT, PRELIM).p()), condp);
@ -4015,27 +4015,27 @@ private:
userIterateAndNext(nodep->initsp(), nullptr);
iterateCheckBool(nodep, "For Test Condition", nodep->condp(),
BOTH); // it's like an if() condition.
if (!VN_IS(nodep, GenFor)) userIterateAndNext(nodep->bodysp(), nullptr);
if (!VN_IS(nodep, GenFor)) userIterateAndNext(nodep->stmtsp(), nullptr);
userIterateAndNext(nodep->incsp(), nullptr);
}
void visit(AstRepeat* nodep) override {
assertAtStatement(nodep);
userIterateAndNext(nodep->countp(), WidthVP(SELF, BOTH).p());
userIterateAndNext(nodep->bodysp(), nullptr);
userIterateAndNext(nodep->stmtsp(), nullptr);
}
void visit(AstWhile* nodep) override {
assertAtStatement(nodep);
userIterateAndNext(nodep->precondsp(), nullptr);
iterateCheckBool(nodep, "For Test Condition", nodep->condp(),
BOTH); // it's like an if() condition.
userIterateAndNext(nodep->bodysp(), nullptr);
userIterateAndNext(nodep->stmtsp(), nullptr);
userIterateAndNext(nodep->incsp(), nullptr);
}
void visit(AstNodeIf* nodep) override {
assertAtStatement(nodep);
// if (debug()) nodep->dumpTree(cout, " IfPre: ");
if (!VN_IS(nodep, GenIf)) { // for m_paramsOnly
userIterateAndNext(nodep->ifsp(), nullptr);
userIterateAndNext(nodep->thensp(), nullptr);
userIterateAndNext(nodep->elsesp(), nullptr);
}
iterateCheckBool(nodep, "If", nodep->condp(), BOTH); // it's like an if() condition.
@ -4056,7 +4056,7 @@ private:
UASSERT_OBJ(fromp->dtypep(), fromp, "Missing data type");
AstNodeDType* fromDtp = fromp->dtypep()->skipRefp();
// Split into for loop
AstNode* bodyp = nodep->bodysp(); // Might be null
AstNode* bodyp = nodep->stmtsp(); // Might be null
if (bodyp) bodyp->unlinkFrBackWithNext();
// We record where the body needs to eventually go with bodyPointp
// (Can't use bodyp as might be null)
@ -4348,8 +4348,8 @@ private:
argp->unlinkFrBack(&handle);
AstCMath* const newp
= new AstCMath(nodep->fileline(), "VL_TO_STRING(", 0, true);
newp->addBodysp(argp);
newp->addBodysp(new AstText(nodep->fileline(), ")", true));
newp->addExprsp(argp);
newp->addExprsp(new AstText(nodep->fileline(), ")", true));
newp->dtypeSetString();
newp->pure(true);
newp->protect(false);
@ -6356,7 +6356,7 @@ private:
varp->isStatic(true);
varp->valuep(initp);
// Add to root, as don't know module we are in, and aids later structure sharing
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp);
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp);
// Element 0 is a non-index and has speced values
initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, 0));
for (unsigned i = 1; i < msbdim + 1; ++i) {
@ -6421,7 +6421,7 @@ private:
varp->isStatic(true);
varp->valuep(initp);
// Add to root, as don't know module we are in, and aids later structure sharing
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp);
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp);
// Default for all unspecified values
if (attrType == VAttrType::ENUM_NAME) {

View File

@ -24,6 +24,8 @@ class Node:
self._file = file # File this class is defined in
self._lineno = lineno # Line this class is defined on
self._ordIdx = None # Ordering index of this class
self._arity = -1 # Arity of node
self._ops = {} # Operands of node
@property
def name(self):
@ -33,6 +35,10 @@ class Node:
def superClass(self):
return self._superClass
@property
def isRoot(self):
return self.superClass is None
@property
def isCompleted(self):
return isinstance(self._subClasses, tuple)
@ -50,6 +56,20 @@ class Node:
assert not self.isCompleted
self._subClasses.append(subClass)
def addOp(self, n, name, monad, kind):
assert 1 <= n <= 4
self._ops[n] = (name, monad, kind)
self._arity = max(self._arity, n)
def getOp(self, n):
assert 1 <= n <= 4
op = self._ops.get(n, None)
if op is not None:
return op
if not self.isRoot:
return self.superClass.getOp(n)
return None
# Computes derived properties over entire class hierarchy.
# No more changes to the hierarchy are allowed once this was called
def complete(self, typeId=0, ordIdx=0):
@ -62,6 +82,11 @@ class Node:
self._ordIdx = ordIdx
ordIdx = ordIdx + 1
if self.isRoot:
self._arity = 0
else:
self._arity = max(self._arity, self._superClass.arity)
# Leaves
if self.isLeaf:
self._typeId = typeId
@ -78,11 +103,6 @@ class Node:
assert self.isCompleted
return self._subClasses
@property
def isRoot(self):
assert self.isCompleted
return self.superClass is None
@property
def isLeaf(self):
assert self.isCompleted
@ -140,6 +160,11 @@ class Node:
assert self.isCompleted
return self._ordIdx
@property
def arity(self):
assert self.isCompleted
return self._arity
def isSubClassOf(self, other):
assert self.isCompleted
if self is other:
@ -495,6 +520,25 @@ class Cpt:
######################################################################
def partitionAndStrip(string, separator):
return map(lambda _: _.strip(), string.partition(separator))
def parseOpType(string):
match = re.match(r'^(\w+)\[(\w+)\]$', string)
if match:
monad, kind = match.groups()
if monad not in ("Optional", "List"):
return None
kind = parseOpType(kind)
if not kind or kind[0]:
return None
return monad, kind[1]
if re.match(r'^Ast(\w+)$', string):
return "", string[3:]
return None
def read_types(filename):
hasErrors = False
@ -539,12 +583,65 @@ def read_types(filename):
node = Node(classn, superClass, filename, lineno)
superClass.addSubClass(node)
Nodes[classn] = node
if not node:
continue
if re.match(r'^\s*ASTGEN_MEMBERS_' + node.name + ';', line):
hasAstgenMembers = True
match = re.match(r'^\s*//\s*@astgen\s+(.*)$', line)
if match:
decl = re.sub(r'//.*$', '', match.group(1))
what, sep, rest = partitionAndStrip(decl, ":=")
what = re.sub(r'\s+', ' ', what)
if not sep:
error(
lineno,
"Malformed '@astgen' directive (expecting '<keywords> := <description>'): "
+ decl)
elif what in ("op1", "op2", "op3", "op4"):
n = int(what[-1])
ident, sep, kind = partitionAndStrip(rest, ":")
ident = ident.strip()
if not sep or not re.match(r'^\w+$', ident):
error(
lineno, "Malformed '@astgen " + what +
"' directive (expecting '" + what +
" := <identifier> : <type>': " + decl)
else:
kind = parseOpType(kind)
if not kind:
error(
lineno, "Bad type for '@astgen " + what +
"' (expecting Ast*, Optional[Ast*], or List[Ast*]):"
+ decl)
elif node.getOp(n) is not None:
error(
lineno, "Already defined " + what + " for " +
node.name)
else:
node.addOp(n, ident, *kind)
elif what in ("alias op1", "alias op2", "alias op3",
"alias op4"):
n = int(what[-1])
ident = rest.strip()
if not re.match(r'^\w+$', ident):
error(
lineno, "Malformed '@astgen " + what +
"' directive (expecting '" + what +
" := <identifier>': " + decl)
else:
op = node.getOp(n)
if op is None:
error(lineno,
"Alaised op" + str(n) + " is not defined")
else:
node.addOp(n, ident, *op[1:])
else:
line = re.sub(r'//.*$', '', line)
if re.match(r'.*[Oo]p[1-9].*', line):
error(lineno,
"Use generated accessors to access op<N> operands")
checkFinishedNode(node)
if hasErrors:
sys.exit("%Error: Stopping due to errors reported above")
@ -614,6 +711,7 @@ def write_report(filename):
fh.write("\nClasses:\n")
for node in SortedNodes:
fh.write(" class Ast%-17s\n" % node.name)
fh.write(" arity: {}\n".format(node.arity))
fh.write(" parent: ")
for superClass in node.allSuperClasses:
if not superClass.isRoot:
@ -759,6 +857,42 @@ def write_macros(filename):
''',
t=node.name)
for n in (1, 2, 3, 4):
op = node.getOp(n)
if not op:
continue
name, monad, kind = op
retrieve = ("VN_AS(op{n}p(), {kind})" if kind != "Node" else
"op{n}p()").format(n=n, kind=kind)
if monad == "List":
emitBlock('''\
Ast{kind}* {name}() const {{ return {retrieve}; }}
void add{Name}(Ast{kind}* nodep) {{ addNOp{n}p(reinterpret_cast<AstNode*>(nodep)); }}
''',
kind=kind,
name=name,
Name=name[0].upper() + name[1:],
n=n,
retrieve=retrieve)
elif monad == "Optional":
emitBlock('''\
Ast{kind}* {name}() const {{ return {retrieve}; }}
void {name}(Ast{kind}* nodep) {{ setNOp{n}p(reinterpret_cast<AstNode*>(nodep)); }}
''',
kind=kind,
name=name,
n=n,
retrieve=retrieve)
else:
emitBlock('''\
Ast{kind}* {name}() const {{ return {retrieve}; }}
void {name}(Ast{kind}* nodep) {{ setOp{n}p(reinterpret_cast<AstNode*>(nodep)); }}
''',
kind=kind,
name=name,
n=n,
retrieve=retrieve)
fh.write(
" static_assert(true, \"\")\n") # Swallowing the semicolon

View File

@ -391,9 +391,8 @@ def clean_input(filename, outname):
if not re.match(r'^\s*$', line):
sys.exit(
"%Error: " + filename + ":" + str(lineno) + ": Need " +
needmore +
" more blank lines to keep line numbers are constant\n"
)
str(needmore) +
" more blank lines to keep line numbers constant\n")
needmore -= 1
else:
lines.append(line)

View File

@ -1068,6 +1068,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
%start source_text
@ -1092,8 +1093,8 @@ description: // ==IEEE: description
| interface_declaration { }
| program_declaration { }
| package_declaration { }
| package_item { if ($1) PARSEP->unitPackage($1->fileline())->addStmtp($1); }
| bind_directive { if ($1) PARSEP->unitPackage($1->fileline())->addStmtp($1); }
| package_item { if ($1) PARSEP->unitPackage($1->fileline())->addStmtsp($1); }
| bind_directive { if ($1) PARSEP->unitPackage($1->fileline())->addStmtsp($1); }
// unsupported // IEEE: config_declaration
// // Verilator only
| yaT_RESETALL { } // Else, under design, and illegal based on IEEE 22.3
@ -1119,7 +1120,7 @@ timeunits_declaration<nodep>: // ==IEEE: timeunits_declaration
package_declaration: // ==IEEE: package_declaration
packageFront package_itemListE yENDPACKAGE endLabelE
{ $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2);
if ($2) $1->addStmtsp($2);
GRAMMARP->m_modp = nullptr;
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>4,$1,$4); }
@ -1132,7 +1133,7 @@ packageFront<nodeModulep>:
$$->lifetime($2);
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
PARSEP->rootp()->addModulep($$);
PARSEP->rootp()->addModulesp($$);
SYMP->pushNew($$);
GRAMMARP->m_modp = $$; }
;
@ -1228,18 +1229,18 @@ module_declaration: // ==IEEE: module_declaration
modFront importsAndParametersE portsStarE ';'
/*cont*/ module_itemListE yENDMODULE endLabelE
{ $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2);
if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
if ($2) $1->addStmtsp($2);
if ($3) $1->addStmtsp($3);
if ($5) $1->addStmtsp($5);
GRAMMARP->m_modp = nullptr;
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>7,$1,$7); }
| udpFront parameter_port_listE portsStarE ';'
/*cont*/ module_itemListE yENDPRIMITIVE endLabelE
{ $1->modTrace(false); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2);
if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
if ($2) $1->addStmtsp($2);
if ($3) $1->addStmtsp($3);
if ($5) $1->addStmtsp($5);
GRAMMARP->m_tracingParse = true;
GRAMMARP->m_modp = nullptr;
SYMP->popScope($1);
@ -1259,7 +1260,7 @@ modFront<nodeModulep>:
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
$$->unconnectedDrive(PARSEP->unconnectedDrive());
PARSEP->rootp()->addModulep($$);
PARSEP->rootp()->addModulesp($$);
SYMP->pushNew($$);
GRAMMARP->m_modp = $$; }
;
@ -1275,9 +1276,9 @@ udpFront<nodeModulep>:
{ $$ = new AstPrimitive($<fl>3, *$3); $$->inLibrary(true);
$$->lifetime($2);
$$->modTrace(false);
$$->addStmtp(new AstPragma($<fl>3, VPragmaType::INLINE_MODULE));
$$->addStmtsp(new AstPragma($<fl>3, VPragmaType::INLINE_MODULE));
GRAMMARP->m_tracingParse = false;
PARSEP->rootp()->addModulep($$);
PARSEP->rootp()->addModulesp($$);
SYMP->pushNew($$); }
;
@ -1489,9 +1490,9 @@ interface_declaration: // IEEE: interface_declaration + interface_nonan
// // timeunits_delcarationE is instead in interface_item
intFront importsAndParametersE portsStarE ';'
interface_itemListE yENDINTERFACE endLabelE
{ if ($2) $1->addStmtp($2);
if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
{ if ($2) $1->addStmtsp($2);
if ($3) $1->addStmtsp($3);
if ($5) $1->addStmtsp($5);
SYMP->popScope($1); }
| yEXTERN intFront parameter_port_listE portsStarE ';'
{ BBUNSUP($<fl>1, "Unsupported: extern interface"); }
@ -1502,7 +1503,7 @@ intFront<nodeModulep>:
{ $$ = new AstIface($<fl>3, *$3);
$$->inLibrary(true);
$$->lifetime($2);
PARSEP->rootp()->addModulep($$);
PARSEP->rootp()->addModulesp($$);
SYMP->pushNew($$); }
;
@ -1578,9 +1579,9 @@ program_declaration: // IEEE: program_declaration + program_nonansi_h
pgmFront parameter_port_listE portsStarE ';'
/*cont*/ program_itemListE yENDPROGRAM endLabelE
{ $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2);
if ($3) $1->addStmtp($3);
if ($5) $1->addStmtp($5);
if ($2) $1->addStmtsp($2);
if ($3) $1->addStmtsp($3);
if ($5) $1->addStmtsp($5);
GRAMMARP->m_modp = nullptr;
SYMP->popScope($1);
GRAMMARP->endLabel($<fl>7,$1,$7); }
@ -1596,7 +1597,7 @@ pgmFront<nodeModulep>:
$$->inLibrary(PARSEP->inLibrary() || $$->fileline()->celldefineOn());
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
PARSEP->rootp()->addModulep($$);
PARSEP->rootp()->addModulesp($$);
SYMP->pushNew($$);
GRAMMARP->m_modp = $$; }
;
@ -2008,12 +2009,13 @@ struct_unionDecl<nodeUOrStructDTypep>: // IEEE: part of data_type
{ $$ = $<nodeUOrStructDTypep>5; $$->addMembersp($6); SYMP->popScope($$); }
;
struct_union_memberList<nodep>: // IEEE: { struct_union_member }
struct_union_memberList<memberDTypep>: // IEEE: { struct_union_member }
struct_union_member { $$ = $1; }
| struct_union_memberList struct_union_member { $$ = addNextNull($1, $2); }
;
struct_union_member<nodep>: // ==IEEE: struct_union_member
struct_union_member<memberDTypep>: // ==IEEE: struct_union_member
// // UNSUP random_qualifer not propagagted until have randomize support
random_qualifierE data_type_or_void
/*mid*/ { GRAMMARP->m_memDTypep = $2; } // As a list follows, need to attach this dtype to each member.
@ -2021,7 +2023,7 @@ struct_union_member<nodep>: // ==IEEE: struct_union_member
| vlTag { $$ = nullptr; }
;
list_of_member_decl_assignments<nodep>: // Derived from IEEE: list_of_variable_decl_assignments
list_of_member_decl_assignments<memberDTypep>: // Derived from IEEE: list_of_variable_decl_assignments
member_decl_assignment { $$ = $1; }
| list_of_member_decl_assignments ',' member_decl_assignment { $$ = addNextNull($1, $3); }
;
@ -2177,17 +2179,17 @@ enum_base_typeE<nodeDTypep>: // IEEE: enum_base_type
$$ = GRAMMARP->createArray(refp, $3, true); }
;
enum_nameList<nodep>:
enum_nameList<enumItemp>:
enum_name_declaration { $$ = $1; }
| enum_nameList ',' enum_name_declaration { $$ = addNextNull($1, $3); }
;
enum_name_declaration<nodep>: // ==IEEE: enum_name_declaration
enum_name_declaration<enumItemp>: // ==IEEE: enum_name_declaration
idAny/*enum_identifier*/ enumNameRangeE enumNameStartE
{ $$ = new AstEnumItem($<fl>1, *$1, $2, $3); }
;
enumNameRangeE<nodep>: // IEEE: second part of enum_name_declaration
enumNameRangeE<rangep>: // IEEE: second part of enum_name_declaration
/* empty */
{ $$ = nullptr; }
| '[' intnumAsConst ']'
@ -2472,7 +2474,7 @@ continuous_assign<nodep>: // IEEE: continuous_assign
if ($3)
for (auto* nodep = $$; nodep; nodep = nodep->nextp()) {
auto* const assignp = VN_AS(nodep, NodeAssign);
assignp->addTimingControlp(nodep == $$ ? $3 : $3->cloneTree(false));
assignp->timingControlp(nodep == $$ ? $3 : $3->cloneTree(false));
}
}
;
@ -2634,7 +2636,7 @@ loop_generate_construct<nodep>: // ==IEEE: loop_generate_construct
}
// Statements are under 'genforp' as cells under this
// for loop won't get an extra layer of hierarchy tacked on
blkp->addGenforp(new AstGenFor($1, initp, $5, $7, lowerNoBegp));
blkp->genforp(new AstGenFor($1, initp, $5, $7, lowerNoBegp));
$$ = blkp;
VL_DO_DANGLING(lowerBegp->deleteTree(), lowerBegp);
}
@ -2679,12 +2681,12 @@ genvar_iteration<nodep>: // ==IEEE: genvar_iteration
new AstConst{$2, AstConst::StringToParse{}, "'b1"}}}; }
;
case_generate_itemListE<nodep>: // IEEE: [{ case_generate_itemList }]
case_generate_itemListE<caseItemp>: // IEEE: [{ case_generate_itemList }]
/* empty */ { $$ = nullptr; }
| case_generate_itemList { $$ = $1; }
;
case_generate_itemList<nodep>: // IEEE: { case_generate_itemList }
case_generate_itemList<caseItemp>: // IEEE: { case_generate_itemList }
~c~case_generate_item { $$ = $1; }
| ~c~case_generate_itemList ~c~case_generate_item { $$ = $1; $1->addNext($2); }
;
@ -2693,7 +2695,7 @@ case_generate_itemList<nodep>: // IEEE: { case_generate_itemList }
//UNSUP BISONPRE_COPY(case_generate_itemList,{s/~c~/c_/g}) // {copied}
//UNSUP ;
case_generate_item<nodep>: // ==IEEE: case_generate_item
case_generate_item<caseItemp>: // ==IEEE: case_generate_item
caseCondList colon generate_block_or_null { $$ = new AstCaseItem{$2, $1, $3}; }
| yDEFAULT colon generate_block_or_null { $$ = new AstCaseItem{$1, nullptr, $3}; }
| yDEFAULT generate_block_or_null { $$ = new AstCaseItem{$1, nullptr, $2}; }
@ -2768,7 +2770,7 @@ netSig<varp>: // IEEE: net_decl_assignment - one element from
{ $$ = VARDONEA($<fl>1, *$1, nullptr, $2);
auto* const assignp = new AstAssignW{$3, new AstVarRef{$<fl>1, *$1, VAccess::WRITE}, $4};
if (GRAMMARP->m_netStrengthp) assignp->strengthSpecp(GRAMMARP->m_netStrengthp->cloneTree(false));
if ($$->delayp()) assignp->addTimingControlp($$->delayp()->unlinkFrBack()); // IEEE 1800-2017 10.3.3
if ($$->delayp()) assignp->timingControlp($$->delayp()->unlinkFrBack()); // IEEE 1800-2017 10.3.3
AstNode::addNext<AstNode, AstNode>($$, assignp); } | netId variable_dimensionList sigAttrListE
{ $$ = VARDONEA($<fl>1,*$1, $2, $3); }
;
@ -4110,19 +4112,19 @@ funcId<nodeFTaskp>: // IEEE: function_data_type_or_implicit
// // function_data_type expanded here to prevent conflicts with implicit_type:empty vs data_type:ID
/**/ fIdScoped
{ $$ = $1;
$$->addFvarp(new AstBasicDType($<fl>1, LOGIC_IMPLICIT));
$$->fvarp(new AstBasicDType($<fl>1, LOGIC_IMPLICIT));
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>1); }
| signingE rangeList fIdScoped
{ $$ = $3;
$$->addFvarp(GRAMMARP->addRange(new AstBasicDType($<fl>3, LOGIC_IMPLICIT, $1), $2,true));
$$->fvarp(GRAMMARP->addRange(new AstBasicDType($<fl>3, LOGIC_IMPLICIT, $1), $2,true));
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>3); }
| signing fIdScoped
{ $$ = $2;
$$->addFvarp(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $1));
$$->fvarp(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $1));
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>2); }
| data_type fIdScoped
{ $$ = $2;
$$->addFvarp($1);
$$->fvarp($1);
SYMP->pushNewUnderNodeOrCurrent($$, $<scp>2); }
// // To verilator tasks are the same as void functions (we separately detect time passing)
| yVOID taskId
@ -4992,12 +4994,12 @@ combinational_body<nodep>: // IEEE: combinational_body + sequential_body
yTABLE tableEntryList yENDTABLE { $$ = new AstUdpTable($1,$2); }
;
tableEntryList<nodep>: // IEEE: { combinational_entry | sequential_entry }
tableEntryList<udpTableLinep>: // IEEE: { combinational_entry | sequential_entry }
tableEntry { $$ = $1; }
| tableEntryList tableEntry { $$ = addNextNull($1, $2); }
;
tableEntry<nodep>: // IEEE: combinational_entry + sequential_entry
tableEntry<udpTableLinep>: // IEEE: combinational_entry + sequential_entry
yaTABLELINE { $$ = new AstUdpTableLine($<fl>1,*$1); }
| error { $$ = nullptr; }
;
@ -6227,14 +6229,14 @@ classVirtualE<cbool>:
| yVIRTUAL__CLASS { $$ = true; }
;
classExtendsE<nodep>: // IEEE: part of class_declaration
classExtendsE<classExtendsp>: // IEEE: part of class_declaration
// // The classExtendsE rule relys on classFront having the
// // new class scope correct via classFront
/* empty */ { $$ = nullptr; $<scp>$ = nullptr; }
| yEXTENDS classExtendsList { $$ = $2; $<scp>$ = $<scp>2; }
;
classExtendsList<nodep>: // IEEE: part of class_declaration
classExtendsList<classExtendsp>: // IEEE: part of class_declaration
classExtendsOne { $$ = $1; $<scp>$ = $<scp>1; }
| classExtendsList ',' classExtendsOne
{ $$ = $3; $<scp>$ = $<scp>3;
@ -6242,7 +6244,7 @@ classExtendsList<nodep>: // IEEE: part of class_declaration
"and unsupported for interface classes."); }
;
classExtendsOne<nodep>: // IEEE: part of class_declaration
classExtendsOne<classExtendsp>: // IEEE: part of class_declaration
class_typeExtImpList
{ $$ = new AstClassExtends($1->fileline(), $1);
$<scp>$ = $<scp>1; }