Strengthen AstNode types to AstNodeExpr

Declare every AstNode children and variables as AstNodeExpr where we
statically know this is the appropriate sub-type.
This commit is contained in:
Geza Lore 2022-11-13 20:33:11 +00:00
parent 352d0b4582
commit 3abb65d732
52 changed files with 1742 additions and 1572 deletions

View File

@ -59,8 +59,8 @@ private:
nodep->displayType(VDisplayType::DT_WRITE);
nodep->fmtp()->text(assertDisplayMessage(nodep, prefix, nodep->fmtp()->text()));
// cppcheck-suppress nullPointer
AstNode* const timenewp = new AstTime{nodep->fileline(), m_modp->timeunit()};
if (AstNode* const timesp = nodep->fmtp()->exprsp()) {
AstNodeExpr* const timenewp = new AstTime{nodep->fileline(), m_modp->timeunit()};
if (AstNodeExpr* const timesp = nodep->fmtp()->exprsp()) {
timesp->unlinkFrBackWithNext();
timenewp->addNext(timesp);
}
@ -69,7 +69,7 @@ private:
nodep->fmtp()->scopeNamep(new AstScopeName{nodep->fileline(), true});
}
}
AstSampled* newSampledExpr(AstNode* nodep) {
AstSampled* newSampledExpr(AstNodeExpr* nodep) {
const auto sampledp = new AstSampled{nodep->fileline(), nodep};
sampledp->dtypeFrom(nodep);
return sampledp;
@ -98,16 +98,16 @@ private:
// Add a internal if to check assertions are on.
// Don't make this a AND term, as it's unlikely to need to test this.
FileLine* const fl = nodep->fileline();
AstNodeIf* const newp = new AstIf{
fl,
(force ? new AstConst{fl, AstConst::BitTrue{}}
: // If assertions are off, have constant propagation rip them out later
// This allows syntax errors and such to be detected normally.
(v3Global.opt.assertOn()
? static_cast<AstNode*>(
new AstCExpr{fl, "vlSymsp->_vm_contextp__->assertOn()", 1})
: static_cast<AstNode*>(new AstConst{fl, AstConst::BitFalse{}}))),
nodep};
// If assertions are off, have constant propagation rip them out later
// This allows syntax errors and such to be detected normally.
AstNodeExpr* const condp
= force ? static_cast<AstNodeExpr*>(new AstConst{fl, AstConst::BitTrue{}})
: v3Global.opt.assertOn()
? static_cast<AstNodeExpr*>(
new AstCExpr{fl, "vlSymsp->_vm_contextp__->assertOn()", 1})
: static_cast<AstNodeExpr*>(new AstConst{fl, AstConst::BitFalse{}});
AstNodeIf* const newp = new AstIf{fl, condp, nodep};
newp->isBoundsCheck(true); // To avoid LATCH warning
newp->user1(true); // Don't assert/cover this if
return newp;
@ -133,7 +133,7 @@ private:
void newPslAssertion(AstNodeCoverOrAssert* nodep, AstNode* failsp) {
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
AstNode* const propp = nodep->propp()->unlinkFrBackWithNext();
AstNodeExpr* const propp = VN_AS(nodep->propp()->unlinkFrBackWithNext(), NodeExpr);
AstSenTree* const sentreep = nodep->sentreep();
const string& message = nodep->name();
AstNode* passsp = nodep->passsp();
@ -211,7 +211,7 @@ private:
if (nodep->user1SetOnce()) return;
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
const AstNodeIf* ifp = nodep;
AstNode* propp = nullptr;
AstNodeExpr* propp = nullptr;
bool hasDefaultElse = false;
do {
// If this statement ends with 'else if', then nextIf will point to the
@ -228,7 +228,7 @@ private:
}
// Build a bitmask of the true predicates
AstNode* const predp = ifp->condp()->cloneTree(false);
AstNodeExpr* const predp = ifp->condp()->cloneTree(false);
if (propp) {
propp = new AstConcat{nodep->fileline(), predp, propp};
} else {
@ -249,10 +249,10 @@ private:
// Note: if this ends with an 'else', then we don't need to validate that one of the
// predicates evaluates to true.
AstNode* const ohot
AstNodeExpr* const ohot
= ((allow_none || hasDefaultElse)
? static_cast<AstNode*>(new AstOneHot0{nodep->fileline(), propp})
: static_cast<AstNode*>(new AstOneHot{nodep->fileline(), propp}));
? static_cast<AstNodeExpr*>(new AstOneHot0{nodep->fileline(), propp})
: static_cast<AstNodeExpr*>(new AstOneHot{nodep->fileline(), propp}));
AstIf* const checkifp
= new AstIf{nodep->fileline(), new AstLogNot{nodep->fileline(), ohot},
newFireAssert(nodep, "'unique if' statement violated"), newifp};
@ -290,11 +290,12 @@ private:
if (!has_default && !nodep->itemsp()) {
// Not parallel, but harmlessly so.
} else {
AstNode* propp = nullptr;
AstNodeExpr* propp = nullptr;
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
itemp = VN_AS(itemp->nextp(), CaseItem)) {
for (AstNode* icondp = itemp->condsp(); icondp; icondp = icondp->nextp()) {
AstNode* onep;
for (AstNodeExpr* icondp = itemp->condsp(); icondp;
icondp = VN_AS(icondp->nextp(), NodeExpr)) {
AstNodeExpr* onep;
if (AstInsideRange* const rcondp = VN_CAST(icondp, InsideRange)) {
onep = rcondp->newAndFromInside(nodep->exprp(),
rcondp->lhsp()->cloneTree(true),
@ -319,10 +320,11 @@ private:
if (!propp) propp = new AstConst{nodep->fileline(), AstConst::BitFalse{}};
const bool allow_none = has_default || nodep->unique0Pragma();
AstNode* const ohot
= (allow_none
? static_cast<AstNode*>(new AstOneHot0{nodep->fileline(), propp})
: static_cast<AstNode*>(new AstOneHot{nodep->fileline(), propp}));
AstNodeExpr* const ohot
= (allow_none ? static_cast<AstNodeExpr*>(
new AstOneHot0{nodep->fileline(), propp})
: static_cast<AstNodeExpr*>(
new AstOneHot{nodep->fileline(), propp}));
AstIf* const ifp = new AstIf{
nodep->fileline(), new AstLogNot{nodep->fileline(), ohot},
newFireAssert(nodep,
@ -345,8 +347,8 @@ private:
ticks = VN_AS(nodep->ticksp(), Const)->toUInt();
}
UASSERT_OBJ(ticks >= 1, nodep, "0 tick should have been checked in V3Width");
AstNode* const exprp = nodep->exprp()->unlinkFrBack();
AstNode* inp = newSampledExpr(exprp);
AstNodeExpr* const exprp = nodep->exprp()->unlinkFrBack();
AstNodeExpr* inp = newSampledExpr(exprp);
AstVar* invarp = nullptr;
AstSenTree* const sentreep = nodep->sentreep();
sentreep->unlinkFrBack();

View File

@ -46,7 +46,7 @@ private:
// Reset each always:
AstSenItem* m_seniAlwaysp = nullptr; // Last sensitivity in always
// Reset each assertion:
AstNode* m_disablep = nullptr; // Last disable
AstNodeExpr* m_disablep = nullptr; // Last disable
// METHODS
@ -113,7 +113,7 @@ private:
}
// If disable iff is in outer property, move it to inner
if (nodep->disablep()) {
AstNode* const disablep = nodep->disablep()->unlinkFrBack();
AstNodeExpr* const disablep = nodep->disablep()->unlinkFrBack();
propExprp->disablep(disablep);
}
@ -170,9 +170,9 @@ private:
if (nodep->sentreep()) return; // Already processed
iterateChildren(nodep);
FileLine* const fl = nodep->fileline();
AstNode* exprp = nodep->exprp()->unlinkFrBack();
AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack();
if (exprp->width() > 1) exprp = new AstSel(fl, exprp, 0, 1);
AstNode* const past = new AstPast(fl, exprp, nullptr);
AstNodeExpr* const past = new AstPast(fl, exprp, nullptr);
past->dtypeFrom(exprp);
exprp = new AstAnd(fl, past, new AstNot(fl, exprp->cloneTree(false)));
exprp->dtypeSetBit();
@ -189,9 +189,9 @@ private:
if (nodep->sentreep()) return; // Already processed
iterateChildren(nodep);
FileLine* const fl = nodep->fileline();
AstNode* exprp = nodep->exprp()->unlinkFrBack();
AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack();
if (exprp->width() > 1) exprp = new AstSel(fl, exprp, 0, 1);
AstNode* const past = new AstPast(fl, exprp, nullptr);
AstNodeExpr* const past = new AstPast(fl, exprp, nullptr);
past->dtypeFrom(exprp);
exprp = new AstAnd(fl, new AstNot(fl, past), exprp->cloneTree(false));
exprp->dtypeSetBit();
@ -203,8 +203,8 @@ private:
if (nodep->sentreep()) return; // Already processed
iterateChildren(nodep);
FileLine* const fl = nodep->fileline();
AstNode* exprp = nodep->exprp()->unlinkFrBack();
AstNode* const past = new AstPast(fl, exprp, nullptr);
AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack();
AstNodeExpr* const past = new AstPast(fl, exprp, nullptr);
past->dtypeFrom(exprp);
exprp = new AstEq(fl, past, exprp->cloneTree(false));
exprp->dtypeSetBit();
@ -217,14 +217,14 @@ private:
if (nodep->sentreep()) return; // Already processed
FileLine* const fl = nodep->fileline();
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* lhsp = nodep->lhsp()->unlinkFrBack();
if (m_disablep) lhsp = new AstAnd(fl, new AstNot(fl, m_disablep), lhsp);
AstNode* const past = new AstPast(fl, lhsp, nullptr);
AstNodeExpr* const past = new AstPast(fl, lhsp, nullptr);
past->dtypeFrom(lhsp);
AstNode* const exprp = new AstOr(fl, new AstNot(fl, past), rhsp);
AstNodeExpr* const exprp = new AstOr(fl, new AstNot(fl, past), rhsp);
exprp->dtypeSetBit();
nodep->replaceWith(exprp);
nodep->sentreep(newSenTree(nodep));
@ -238,8 +238,8 @@ private:
if (m_senip)
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Only one PSL clock allowed per assertion");
// Block is the new expression to evaluate
AstNode* blockp = nodep->propp()->unlinkFrBack();
if (AstNode* const disablep = nodep->disablep()) {
AstNodeExpr* blockp = VN_AS(nodep->propp()->unlinkFrBack(), NodeExpr);
if (AstNodeExpr* const disablep = nodep->disablep()) {
m_disablep = disablep->cloneTree(false);
if (VN_IS(nodep->backp(), Cover)) {
blockp = new AstAnd(disablep->fileline(),

View File

@ -1877,8 +1877,8 @@ public:
void addNextHere(AstNode* newp); // Insert newp at this->nextp
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
void replaceWith(AstNode* newp); // Replace current node in tree with new node
AstNode* unlinkFrBack(VNRelinker* linkerp
= nullptr); // Unlink this from whoever points to it.
// Unlink this from whoever points to it.
AstNode* unlinkFrBack(VNRelinker* linkerp = nullptr);
// Unlink this from whoever points to it, keep entire next list with unlinked node
AstNode* unlinkFrBackWithNext(VNRelinker* linkerp = nullptr);
void swapWith(AstNode* bp);

View File

@ -130,7 +130,7 @@ bool AstBasicDType::littleEndian() const {
bool AstActive::hasClocked() const { return m_sensesp->hasClocked(); }
bool AstActive::hasCombo() const { return m_sensesp->hasCombo(); }
AstElabDisplay::AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNode* exprsp)
AstElabDisplay::AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNodeExpr* exprsp)
: ASTGEN_SUPER_ElabDisplay(fl) {
addFmtp(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp});
m_displayType = dispType;

View File

@ -261,13 +261,13 @@ public:
// === AstNode ===
class AstEnumItem final : public AstNode {
// @astgen op1 := rangep : Optional[AstRange] // Range for name appending
// @astgen op2 := valuep : Optional[AstNode]
// @astgen op2 := valuep : Optional[AstNodeExpr]
private:
string m_name;
public:
// Parents: ENUM
AstEnumItem(FileLine* fl, const string& name, AstRange* rangep, AstNode* valuep)
AstEnumItem(FileLine* fl, const string& name, AstRange* rangep, AstNodeExpr* valuep)
: ASTGEN_SUPER_EnumItem(fl)
, m_name{name} {
this->rangep(rangep);
@ -972,18 +972,18 @@ public:
class AstQueueDType final : public AstNodeDType {
// Queue array data type, ie "[ $ ]"
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
// @astgen op2 := boundp : Optional[AstNode]
// @astgen op2 := boundp : Optional[AstNodeExpr]
private:
AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing)
public:
AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* boundp)
AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNodeExpr* boundp)
: ASTGEN_SUPER_QueueDType(fl) {
this->childDTypep(dtp);
this->boundp(boundp);
refDTypep(nullptr);
dtypep(nullptr); // V3Width will resolve
}
AstQueueDType(FileLine* fl, AstNodeDType* dtp, AstNode* boundp)
AstQueueDType(FileLine* fl, AstNodeDType* dtp, AstNodeExpr* boundp)
: ASTGEN_SUPER_QueueDType(fl) {
this->boundp(boundp);
refDTypep(dtp);
@ -1032,7 +1032,7 @@ public:
};
class AstRefDType final : public AstNodeDType {
// @astgen op1 := typeofp : Optional[AstNode]
// @astgen op2 := classOrPackageOpp : Optional[AstNode]
// @astgen op2 := classOrPackageOpp : Optional[AstNodeExpr]
// @astgen op3 := paramsp : List[AstPin]
private:
// Pre-Width must reference the Typeref, not what it points to, as some child
@ -1046,7 +1046,7 @@ public:
AstRefDType(FileLine* fl, const string& name)
: ASTGEN_SUPER_RefDType(fl)
, m_name{name} {}
AstRefDType(FileLine* fl, const string& name, AstNode* classOrPackagep, AstPin* paramsp)
AstRefDType(FileLine* fl, const string& name, AstNodeExpr* classOrPackagep, AstPin* paramsp)
: ASTGEN_SUPER_RefDType(fl)
, m_name{name} {
this->classOrPackageOpp(classOrPackagep);

File diff suppressed because it is too large Load Diff

View File

@ -310,11 +310,11 @@ public:
};
class AstNodeAssign VL_NOT_FINAL : public AstNodeStmt {
// Iteration is in order, and we want rhsp to be visited first (which is the execution order)
// @astgen op1 := rhsp : AstNode
// @astgen op2 := lhsp : AstNode
// @astgen op1 := rhsp : AstNodeExpr
// @astgen op2 := lhsp : AstNodeExpr
// @astgen op3 := timingControlp : Optional[AstNode]
protected:
AstNodeAssign(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp,
AstNodeAssign(VNType t, FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp,
AstNode* timingControlp = nullptr)
: AstNodeStmt{t, fl} {
this->rhsp(rhsp);
@ -326,7 +326,7 @@ protected:
public:
ASTGEN_MEMBERS_AstNodeAssign;
// Clone single node, just get same type back.
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0;
virtual AstNodeAssign* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) = 0;
bool hasDType() const override { return true; }
virtual bool cleanRhs() const { return true; }
int instrCount() const override { return widthInstrs(); }
@ -336,11 +336,11 @@ public:
virtual bool brokeLhsMustBeLvalue() const = 0;
};
class AstNodeCase VL_NOT_FINAL : public AstNodeStmt {
// @astgen op1 := exprp : AstNode // Condition (scurtinee) expression
// @astgen op1 := exprp : AstNodeExpr // Condition (scurtinee) expression
// @astgen op2 := itemsp : List[AstCaseItem]
// @astgen op3 := notParallelp : List[AstNode] // assertion code for non-full case's
protected:
AstNodeCase(VNType t, FileLine* fl, AstNode* exprp, AstCaseItem* itemsp)
AstNodeCase(VNType t, FileLine* fl, AstNodeExpr* exprp, AstCaseItem* itemsp)
: AstNodeStmt{t, fl} {
this->exprp(exprp);
this->addItemsp(itemsp);
@ -377,11 +377,11 @@ public:
};
class AstNodeFor VL_NOT_FINAL : public AstNodeStmt {
// @astgen op1 := initsp : List[AstNode]
// @astgen op2 := condp : AstNode
// @astgen op2 := condp : AstNodeExpr
// @astgen op3 := incsp : List[AstNode]
// @astgen op4 := stmtsp : List[AstNode]
protected:
AstNodeFor(VNType t, FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp,
AstNodeFor(VNType t, FileLine* fl, AstNode* initsp, AstNodeExpr* condp, AstNode* incsp,
AstNode* stmtsp)
: AstNodeStmt{t, fl} {
this->addInitsp(initsp);
@ -397,14 +397,14 @@ public:
bool same(const AstNode* /*samep*/) const override { return true; }
};
class AstNodeIf VL_NOT_FINAL : public AstNodeStmt {
// @astgen op1 := condp : AstNode
// @astgen op1 := condp : AstNodeExpr
// @astgen op2 := thensp : List[AstNode]
// @astgen op3 := elsesp : List[AstNode]
private:
VBranchPred m_branchPred; // Branch prediction as taken/untaken?
bool m_isBoundsCheck; // True if this if node is for assertion/bounds checking
protected:
AstNodeIf(VNType t, FileLine* fl, AstNode* condp, AstNode* thensp, AstNode* elsesp)
AstNodeIf(VNType t, FileLine* fl, AstNodeExpr* condp, AstNode* thensp, AstNode* elsesp)
: AstNodeStmt{t, fl} {
this->condp(condp);
this->addThensp(thensp);
@ -427,15 +427,15 @@ public:
}
};
class AstNodeReadWriteMem VL_NOT_FINAL : public AstNodeStmt {
// @astgen op1 := filenamep : AstNode
// @astgen op2 := memp : AstNode
// @astgen op3 := lsbp : Optional[AstNode]
// @astgen op4 := msbp : Optional[AstNode]
// @astgen op1 := filenamep : AstNodeExpr
// @astgen op2 := memp : AstNodeExpr
// @astgen op3 := lsbp : Optional[AstNodeExpr]
// @astgen op4 := msbp : Optional[AstNodeExpr]
const bool m_isHex; // readmemh, not readmemb
public:
AstNodeReadWriteMem(VNType t, FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp,
AstNode* lsbp, AstNode* msbp)
AstNodeReadWriteMem(VNType t, FileLine* fl, bool hex, AstNodeExpr* filenamep,
AstNodeExpr* memp, AstNodeExpr* lsbp, AstNodeExpr* msbp)
: AstNodeStmt(t, fl)
, m_isHex(hex) {
this->filenamep(filenamep);
@ -518,21 +518,6 @@ public:
inline bool hasClocked() const;
inline bool hasCombo() const;
};
class AstArg final : public AstNode {
// An argument to a function/task
// @astgen op1 := exprp : Optional[AstNode] // nullptr if omitted
string m_name; // Pin name, or "" for number based interconnect
public:
AstArg(FileLine* fl, const string& name, AstNode* exprp)
: ASTGEN_SUPER_Arg(fl)
, m_name{name} {
this->exprp(exprp);
}
ASTGEN_MEMBERS_AstArg;
string name() const override { return m_name; } // * = Pin name, ""=go by number
void name(const string& name) override { m_name = name; }
bool emptyConnectNoNext() const { return !exprp() && name() == "" && !nextp(); }
};
class AstBind final : public AstNode {
// Parents: MODULE
// Children: CELL
@ -718,10 +703,10 @@ public:
};
class AstCaseItem final : public AstNode {
// Single item of a case statement
// @astgen op1 := condsp : List[AstNode]
// @astgen op1 := condsp : List[AstNodeExpr]
// @astgen op2 := stmtsp : List[AstNode]
public:
AstCaseItem(FileLine* fl, AstNode* condsp, AstNode* stmtsp)
AstCaseItem(FileLine* fl, AstNodeExpr* condsp, AstNode* stmtsp)
: ASTGEN_SUPER_CaseItem(fl) {
this->addCondsp(condsp);
this->addStmtsp(stmtsp);
@ -731,23 +716,6 @@ public:
bool isDefault() const { return condsp() == nullptr; }
bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); }
};
class AstCastSize final : public AstNode {
// Cast to specific size; signed/twostate inherited from lower element per IEEE
// @astgen op1 := lhsp : AstNode
// @astgen op2 := rhsp : AstNode
public:
AstCastSize(FileLine* fl, AstNode* lhsp, AstConst* rhsp)
: ASTGEN_SUPER_CastSize(fl) {
this->lhsp(lhsp);
this->rhsp(rhsp);
}
ASTGEN_MEMBERS_AstCastSize;
// No hasDType because widthing removes this node before the hasDType check
virtual string emitVerilog() { return "((%r)'(%l))"; }
virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); }
virtual bool cleanLhs() const { return true; }
virtual bool sizeMattersLhs() const { return false; }
};
class AstCell final : public AstNode {
// A instantiation cell or interface call (don't know which until link)
// @astgen op1 := pinsp : List[AstPin] // List of port assignments
@ -799,20 +767,6 @@ public:
void recursive(bool flag) { m_recursive = flag; }
bool recursive() const { return m_recursive; }
};
class AstCellArrayRef final : public AstNode {
// As-of-yet unlinkable reference into an array of cells
// @astgen op1 := selp : List[AstNode] // Select expression
string m_name; // Array name
public:
AstCellArrayRef(FileLine* fl, const string& name, AstNode* selp)
: ASTGEN_SUPER_CellArrayRef(fl)
, m_name{name} {
this->addSelp(selp);
}
ASTGEN_MEMBERS_AstCellArrayRef;
// ACCESSORS
string name() const override { return m_name; } // * = Array name
};
class AstCellInline final : public AstNode {
// A instantiation cell that was removed by inlining
// For communication between V3Inline and V3LinkDot,
@ -844,23 +798,6 @@ public:
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
VTimescale timeunit() const { return m_timeunit; }
};
class AstCellRef final : public AstNode {
// As-of-yet unlinkable reference into a cell
// @astgen op1 := cellp : AstNode
// @astgen op2 := exprp : AstNode
private:
string m_name; // Cell name
public:
AstCellRef(FileLine* fl, const string& name, AstNode* cellp, AstNode* exprp)
: ASTGEN_SUPER_CellRef(fl)
, m_name{name} {
this->cellp(cellp);
this->exprp(exprp);
}
ASTGEN_MEMBERS_AstCellRef;
// ACCESSORS
string name() const override { return m_name; } // * = Array name
};
class AstClassExtends final : public AstNode {
// Children: List of AstParseRef for packages/classes
// during early parse, then moves to dtype
@ -876,43 +813,6 @@ public:
string verilogKwd() const override { return "extends"; }
AstClass* classp() const; // Class being extended (after link)
};
class AstClassOrPackageRef final : public AstNode {
// @astgen op1 := paramsp : List[AstPin]
private:
string m_name;
// Node not NodeModule to appease some early parser usage
AstNode* m_classOrPackageNodep; // Package hierarchy
public:
AstClassOrPackageRef(FileLine* fl, const string& name, AstNode* classOrPackageNodep,
AstPin* paramsp)
: ASTGEN_SUPER_ClassOrPackageRef(fl)
, m_name{name}
, m_classOrPackageNodep{classOrPackageNodep} {
this->addParamsp(paramsp);
}
ASTGEN_MEMBERS_AstClassOrPackageRef;
// METHODS
const char* broken() const override {
BROKEN_RTN(m_classOrPackageNodep && !m_classOrPackageNodep->brokeExists());
return nullptr;
}
void cloneRelink() override {
if (m_classOrPackageNodep && m_classOrPackageNodep->clonep()) {
m_classOrPackageNodep = m_classOrPackageNodep->clonep();
}
}
bool same(const AstNode* samep) const override {
return (m_classOrPackageNodep
== static_cast<const AstClassOrPackageRef*>(samep)->m_classOrPackageNodep);
}
void dump(std::ostream& str = std::cout) const override;
string name() const override { return m_name; } // * = Var name
AstNode* classOrPackageNodep() const { return m_classOrPackageNodep; }
void classOrPackageNodep(AstNode* nodep) { m_classOrPackageNodep = nodep; }
AstNodeModule* classOrPackagep() const;
AstPackage* packagep() const { return VN_CAST(classOrPackageNodep(), Package); }
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackageNodep = (AstNode*)nodep; }
};
class AstClocking final : public AstNode {
// Set default clock region
// Parents: MODULE
@ -934,7 +834,7 @@ class AstConstPool final : public AstNode {
AstModule* const m_modp; // The Module holding the Scope below ...
AstScope* const m_scopep; // Scope holding the constant variables
AstVarScope* createNewEntry(const string& name, AstNode* initp);
AstVarScope* createNewEntry(const string& name, AstNodeExpr* initp);
public:
explicit AstConstPool(FileLine* fl);
@ -960,11 +860,11 @@ public:
class AstDefParam final : public AstNode {
// A defparam assignment
// Parents: MODULE
// @astgen op1 := rhsp : AstNode
// @astgen op1 := rhsp : AstNodeExpr
string m_name; // Name of variable getting set
string m_path; // Dotted cellname to set parameter of
public:
AstDefParam(FileLine* fl, const string& path, const string& name, AstNode* rhsp)
AstDefParam(FileLine* fl, const string& path, const string& name, AstNodeExpr* rhsp)
: ASTGEN_SUPER_DefParam(fl)
, m_name{name}
, m_path{path} {
@ -1000,7 +900,7 @@ private:
VDisplayType m_displayType;
public:
inline AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNode* exprsp);
inline AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNodeExpr* exprsp);
ASTGEN_MEMBERS_AstElabDisplay;
const char* broken() const override {
BROKEN_RTN(!fmtp());
@ -1064,50 +964,14 @@ public:
}
ASTGEN_MEMBERS_AstImplicit;
};
class AstInitArray final : public AstNode {
// Set a var to a map of values
// The list of initsp() is not relevant
// If default is specified, the vector may be sparse, and not provide each value.
// Key values are C++ array style, with lo() at index 0
// Parents: ASTVAR::init()
// @astgen op1 := defaultp : Optional[AstNode] // Default, if sparse
// @astgen op2 := initsp : List[AstNode] // Initial value expressions
//
public:
using KeyItemMap = std::map<uint64_t, AstInitItem*>;
private:
KeyItemMap m_map; // Node value for each array index
public:
AstInitArray(FileLine* fl, AstNodeDType* newDTypep, AstNode* defaultp)
: ASTGEN_SUPER_InitArray(fl) {
dtypep(newDTypep);
this->defaultp(defaultp);
}
ASTGEN_MEMBERS_AstInitArray;
void dump(std::ostream& str) const override;
const char* broken() const override;
void cloneRelink() override;
bool hasDType() const override { return true; }
bool same(const AstNode* samep) const override {
// Only works if exact same children, instead should override comparison
// of children list, and instead use map-vs-map key/value compare
return m_map == static_cast<const AstInitArray*>(samep)->m_map;
}
void addValuep(AstNode* newp) { addIndexValuep(m_map.size(), newp); }
const KeyItemMap& map() const { return m_map; }
void addIndexValuep(uint64_t index, AstNode* newp);
AstNode* getIndexValuep(uint64_t index) const;
AstNode* getIndexDefaultedValuep(uint64_t index) const;
};
class AstInitItem final : public AstNode {
// Container for a item in an init array
// This container is present so that the value underneath may get replaced with a new nodep
// and the upper AstInitArray's map will remain correct (pointing to this InitItem)
// @astgen op1 := valuep : AstNode
// @astgen op1 := valuep : AstNodeExpr
public:
// Parents: INITARRAY
AstInitItem(FileLine* fl, AstNode* valuep)
AstInitItem(FileLine* fl, AstNodeExpr* valuep)
: ASTGEN_SUPER_InitItem(fl) {
this->valuep(valuep);
}
@ -1317,7 +1181,7 @@ public:
};
class AstPin final : public AstNode {
// A port or parameter assignment on an instantiaton
// @astgen op1 := exprp : Optional[AstNode] // Expression connected (nullptr if unconnected)
// @astgen op1 := exprp : Optional[AstNode] // NodeExpr or NodeDType (nullptr if unconnected)
private:
int m_pinNum; // Pin number
string m_name; // Pin name, or "" for number based interconnect
@ -1353,7 +1217,7 @@ public:
};
class AstPort final : public AstNode {
// A port (in/out/inout) on a module
// @astgen op1 := exprp : Optional[AstNode] // Expression connected to port
// @astgen op1 := exprp : Optional[AstNodeExpr] // Expression connected to port
const int m_pinNum; // Pin number
const string m_name; // Name of pin
public:
@ -1385,10 +1249,10 @@ class AstPropSpec final : public AstNode {
// Parents: ASSERT|COVER (property)
// Children: SENITEM, Properties
// @astgen op1 := sensesp : Optional[AstSenItem]
// @astgen op2 := disablep : Optional[AstNode]
// @astgen op2 := disablep : Optional[AstNodeExpr]
// @astgen op3 := propp : AstNode
public:
AstPropSpec(FileLine* fl, AstSenItem* sensesp, AstNode* disablep, AstNode* propp)
AstPropSpec(FileLine* fl, AstSenItem* sensesp, AstNodeExpr* disablep, AstNode* propp)
: ASTGEN_SUPER_PropSpec(fl) {
this->sensesp(sensesp);
this->disablep(disablep);
@ -1400,12 +1264,12 @@ public:
} // Used under Cover, which expects a bool child
};
class AstPull final : public AstNode {
// @astgen op1 := lhsp : AstNode
// @astgen op1 := lhsp : AstNodeExpr
const bool m_direction;
public:
AstPull(FileLine* fl, AstNode* lhsp, bool direction)
AstPull(FileLine* fl, AstNodeExpr* lhsp, bool direction)
: ASTGEN_SUPER_Pull(fl)
, m_direction{direction} {
this->lhsp(lhsp);
@ -1455,24 +1319,9 @@ public:
AstVarScope* createTemp(const string& name, AstNodeDType* dtypep);
AstVarScope* createTempLike(const string& name, AstVarScope* vscp);
};
class AstSelLoopVars final : public AstNode {
// Parser only concept "[id, id, id]" for a foreach statement
// Unlike normal selects elements is a list
// @astgen op1 := fromp : AstNode
// @astgen op2 := elementsp : List[AstNode]
public:
AstSelLoopVars(FileLine* fl, AstNode* fromp, AstNode* elementsp)
: ASTGEN_SUPER_SelLoopVars(fl) {
this->fromp(fromp);
this->addElementsp(elementsp);
}
ASTGEN_MEMBERS_AstSelLoopVars;
bool same(const AstNode* /*samep*/) const override { return true; }
bool maybePointedTo() const override { return false; }
};
class AstSenItem final : public AstNode {
// Parents: SENTREE
// @astgen op1 := sensp : Optional[AstNode] // Sensitivity expression
// @astgen op1 := sensp : Optional[AstNodeExpr] // Sensitivity expression
VEdgeType m_edgeType; // Edge type
public:
class Combo {}; // for constructor type-overload selection
@ -1481,7 +1330,7 @@ public:
class Initial {}; // for constructor type-overload selection
class Final {}; // for constructor type-overload selection
class Never {}; // for constructor type-overload selection
AstSenItem(FileLine* fl, VEdgeType edgeType, AstNode* senp)
AstSenItem(FileLine* fl, VEdgeType edgeType, AstNodeExpr* senp)
: ASTGEN_SUPER_SenItem(fl)
, m_edgeType{edgeType} {
this->sensp(senp);
@ -1695,7 +1544,7 @@ class AstVar final : public AstNode {
// @astgen op2 := delayp : Optional[AstDelay] // Net delay
// Initial value that never changes (static const), or constructor argument for
// MTASKSTATE variables
// @astgen op3 := valuep : Optional[AstNode]
// @astgen op3 := valuep : Optional[AstNode] // May be a DType for type parameter defaults
// @astgen op4 := attrsp : List[AstNode] // Attributes during early parse
string m_name; // Name of variable
@ -2381,7 +2230,7 @@ public:
class AstBracketRange final : public AstNodeRange {
// Parser only concept "[lhsp]", a AstUnknownRange, QueueRange or Range,
// unknown until lhsp type is determined
// @astgen op1 := elementsp : AstNode
// @astgen op1 := elementsp : AstNode // Expr or DType
public:
AstBracketRange(FileLine* fl, AstNode* elementsp)
: ASTGEN_SUPER_BracketRange(fl) {
@ -2397,10 +2246,10 @@ public:
};
class AstRange final : public AstNodeRange {
// Range specification, for use under variables and cells
// @astgen op1 := leftp : AstNode
// @astgen op2 := rightp : AstNode
// @astgen op1 := leftp : AstNodeExpr
// @astgen op2 := rightp : AstNodeExpr
public:
AstRange(FileLine* fl, AstNode* leftp, AstNode* rightp)
AstRange(FileLine* fl, AstNodeExpr* leftp, AstNodeExpr* rightp)
: ASTGEN_SUPER_Range(fl) {
this->leftp(leftp);
this->rightp(rightp);
@ -2490,9 +2339,9 @@ public:
};
class AstCReturn final : public AstNodeStmt {
// C++ return from a function
// @astgen op1 := lhsp : AstNode
// @astgen op1 := lhsp : AstNodeExpr
public:
AstCReturn(FileLine* fl, AstNode* lhsp)
AstCReturn(FileLine* fl, AstNodeExpr* lhsp)
: ASTGEN_SUPER_CReturn(fl) {
this->lhsp(lhsp);
}
@ -2516,7 +2365,6 @@ public:
};
class AstComment final : public AstNodeStmt {
// Some comment to put into the output stream
// Parents: {statement list}
const string m_name; // Text of comment
const bool m_showAt; // Show "at <fileline>"
public:
@ -2541,9 +2389,6 @@ public:
};
class AstCoverDecl final : public AstNodeStmt {
// Coverage analysis point declaration
// Parents: {statement list}
// Children: none
private:
AstCoverDecl* m_dataDeclp = nullptr; // [After V3CoverageJoin] Pointer to duplicate
// declaration to get data from instead
string m_page;
@ -2597,9 +2442,6 @@ public:
};
class AstCoverInc final : public AstNodeStmt {
// Coverage analysis point; increment coverage count
// Parents: {statement list}
// Children: none
private:
AstCoverDecl* m_declp; // [After V3Coverage] Pointer to declaration
public:
AstCoverInc(FileLine* fl, AstCoverDecl* declp)
@ -2628,10 +2470,10 @@ class AstCoverToggle final : public AstNodeStmt {
// Toggle analysis of given signal
// Parents: MODULE
// @astgen op1 := incp : AstCoverInc
// @astgen op2 := origp : AstNode
// @astgen op3 := changep : AstNode
// @astgen op2 := origp : AstNodeExpr
// @astgen op3 := changep : AstNodeExpr
public:
AstCoverToggle(FileLine* fl, AstCoverInc* incp, AstNode* origp, AstNode* changep)
AstCoverToggle(FileLine* fl, AstCoverInc* incp, AstNodeExpr* origp, AstNodeExpr* changep)
: ASTGEN_SUPER_CoverToggle(fl) {
this->incp(incp);
this->origp(origp);
@ -2649,10 +2491,10 @@ public:
};
class AstDelay final : public AstNodeStmt {
// Delay statement
// @astgen op1 := lhsp : AstNode // Delay value
// @astgen op1 := lhsp : AstNodeExpr // Delay value
// @astgen op2 := stmtsp : List[AstNode] // Statements under delay
public:
AstDelay(FileLine* fl, AstNode* lhsp)
AstDelay(FileLine* fl, AstNodeExpr* lhsp)
: ASTGEN_SUPER_Delay(fl) {
this->lhsp(lhsp);
}
@ -2661,7 +2503,6 @@ public:
bool same(const AstNode* /*samep*/) const override { return true; }
};
class AstDisable final : public AstNodeStmt {
private:
string m_name; // Name of block
public:
AstDisable(FileLine* fl, const string& name)
@ -2684,19 +2525,19 @@ public:
class AstDisplay final : public AstNodeStmt {
// Parents: stmtlist
// @astgen op1 := fmtp : AstSFormatF
// @astgen op2 := filep : Optional[AstNode] // file (must be a VarRef)
// @astgen op2 := filep : Optional[AstNodeExpr] // file (must resolve to a VarRef)
private:
VDisplayType m_displayType;
public:
AstDisplay(FileLine* fl, VDisplayType dispType, const string& text, AstNode* filep,
AstNode* exprsp, char missingArgChar = 'd')
AstDisplay(FileLine* fl, VDisplayType dispType, const string& text, AstNodeExpr* filep,
AstNodeExpr* exprsp, char missingArgChar = 'd')
: ASTGEN_SUPER_Display(fl)
, m_displayType{dispType} {
this->fmtp(new AstSFormatF{fl, text, true, exprsp, missingArgChar});
this->filep(filep);
}
AstDisplay(FileLine* fl, VDisplayType dispType, AstNode* filep, AstNode* exprsp,
AstDisplay(FileLine* fl, VDisplayType dispType, AstNodeExpr* filep, AstNodeExpr* exprsp,
char missingArgChar = 'd')
: ASTGEN_SUPER_Display(fl)
, m_displayType{dispType} {
@ -2729,11 +2570,11 @@ public:
};
class AstDoWhile final : public AstNodeStmt {
// @astgen op1 := precondsp : List[AstNode]
// @astgen op2 := condp : AstNode
// @astgen op2 := condp : AstNodeExpr
// @astgen op3 := stmtsp : List[AstNode]
// @astgen op4 := incsp : List[AstNode]
public:
AstDoWhile(FileLine* fl, AstNode* conditionp, AstNode* stmtsp = nullptr,
AstDoWhile(FileLine* fl, AstNodeExpr* conditionp, AstNode* stmtsp = nullptr,
AstNode* incsp = nullptr)
: ASTGEN_SUPER_DoWhile(fl) {
condp(conditionp);
@ -2750,10 +2591,10 @@ public:
class AstDumpCtl final : public AstNodeStmt {
// $dumpon etc
// Parents: expr
// @astgen op1 := exprp : Optional[AstNode] // Expression based on type of control statement
// @astgen op1 := exprp : Optional[AstNodeExpr] // Expression based on type of statement
const VDumpCtlType m_ctlType; // Type of operation
public:
AstDumpCtl(FileLine* fl, VDumpCtlType ctlType, AstNode* exprp = nullptr)
AstDumpCtl(FileLine* fl, VDumpCtlType ctlType, AstNodeExpr* exprp = nullptr)
: ASTGEN_SUPER_DumpCtl(fl)
, m_ctlType{ctlType} {
this->exprp(exprp);
@ -2784,9 +2625,9 @@ public:
};
class AstFClose final : public AstNodeStmt {
// Parents: stmtlist
// @astgen op1 := filep : AstNode // file (must be a VarRef)
// @astgen op1 := filep : AstNodeExpr // file (must be a VarRef)
public:
AstFClose(FileLine* fl, AstNode* filep)
AstFClose(FileLine* fl, AstNodeExpr* filep)
: ASTGEN_SUPER_FClose(fl) {
this->filep(filep);
}
@ -2801,9 +2642,9 @@ public:
};
class AstFFlush final : public AstNodeStmt {
// Parents: stmtlist
// @astgen op1 := filep : Optional[AstNode] // file (must be a VarRef)
// @astgen op1 := filep : Optional[AstNodeExpr] // file (must be a VarRef)
public:
AstFFlush(FileLine* fl, AstNode* filep)
AstFFlush(FileLine* fl, AstNodeExpr* filep)
: ASTGEN_SUPER_FFlush(fl) {
this->filep(filep);
}
@ -2818,11 +2659,11 @@ public:
};
class AstFOpen final : public AstNodeStmt {
// Although a system function in IEEE, here a statement which sets the file pointer (MCD)
// @astgen op1 := filep : AstNode
// @astgen op2 := filenamep : AstNode
// @astgen op3 := modep : AstNode
// @astgen op1 := filep : AstNodeExpr
// @astgen op2 := filenamep : AstNodeExpr
// @astgen op3 := modep : AstNodeExpr
public:
AstFOpen(FileLine* fl, AstNode* filep, AstNode* filenamep, AstNode* modep)
AstFOpen(FileLine* fl, AstNodeExpr* filep, AstNodeExpr* filenamep, AstNodeExpr* modep)
: ASTGEN_SUPER_FOpen(fl) {
this->filep(filep);
this->filenamep(filenamep);
@ -2839,10 +2680,10 @@ public:
};
class AstFOpenMcd final : public AstNodeStmt {
// Although a system function in IEEE, here a statement which sets the file pointer (MCD)
// @astgen op1 := filep : AstNode
// @astgen op2 := filenamep : AstNode
// @astgen op1 := filep : AstNodeExpr
// @astgen op2 := filenamep : AstNodeExpr
public:
AstFOpenMcd(FileLine* fl, AstNode* filep, AstNode* filenamep)
AstFOpenMcd(FileLine* fl, AstNodeExpr* filep, AstNodeExpr* filenamep)
: ASTGEN_SUPER_FOpenMcd(fl) {
this->filep(filep);
this->filenamep(filenamep);
@ -2871,10 +2712,10 @@ public:
};
class AstFireEvent final : public AstNodeStmt {
// '-> _' and '->> _' event trigger statements
// @astgen op1 := operandp : AstNode
// @astgen op1 := operandp : AstNodeExpr
const bool m_delayed; // Delayed (->>) vs non-delayed (->)
public:
AstFireEvent(FileLine* fl, AstNode* operandp, bool delayed)
AstFireEvent(FileLine* fl, AstNodeExpr* operandp, bool delayed)
: ASTGEN_SUPER_FireEvent(fl)
, m_delayed{delayed} {
this->operandp(operandp);
@ -3026,19 +2867,19 @@ public:
};
class AstRelease final : public AstNodeStmt {
// Procedural 'release' statement
// @astgen op1 := lhsp : AstNode
// @astgen op1 := lhsp : AstNodeExpr
public:
AstRelease(FileLine* fl, AstNode* lhsp)
AstRelease(FileLine* fl, AstNodeExpr* lhsp)
: ASTGEN_SUPER_Release(fl) {
this->lhsp(lhsp);
}
ASTGEN_MEMBERS_AstRelease;
};
class AstRepeat final : public AstNodeStmt {
// @astgen op1 := countp : AstNode
// @astgen op1 := countp : AstNodeExpr
// @astgen op2 := stmtsp : List[AstNode]
public:
AstRepeat(FileLine* fl, AstNode* countp, AstNode* stmtsp)
AstRepeat(FileLine* fl, AstNodeExpr* countp, AstNode* stmtsp)
: ASTGEN_SUPER_Repeat(fl) {
this->countp(countp);
this->addStmtsp(stmtsp);
@ -3050,9 +2891,9 @@ public:
bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); }
};
class AstReturn final : public AstNodeStmt {
// @astgen op1 := lhsp : Optional[AstNode]
// @astgen op1 := lhsp : Optional[AstNodeExpr]
public:
explicit AstReturn(FileLine* fl, AstNode* lhsp = nullptr)
explicit AstReturn(FileLine* fl, AstNodeExpr* lhsp = nullptr)
: ASTGEN_SUPER_Return(fl) {
this->lhsp(lhsp);
}
@ -3065,15 +2906,15 @@ public:
class AstSFormat final : public AstNodeStmt {
// Parents: statement container
// @astgen op1 := fmtp : AstSFormatF
// @astgen op2 := lhsp : AstNode
// @astgen op2 := lhsp : AstNodeExpr
public:
AstSFormat(FileLine* fl, AstNode* lhsp, const string& text, AstNode* exprsp,
AstSFormat(FileLine* fl, AstNodeExpr* lhsp, const string& text, AstNodeExpr* exprsp,
char missingArgChar = 'd')
: ASTGEN_SUPER_SFormat(fl) {
this->fmtp(new AstSFormatF{fl, text, true, exprsp, missingArgChar});
this->lhsp(lhsp);
}
AstSFormat(FileLine* fl, AstNode* lhsp, AstNode* exprsp, char missingArgChar = 'd')
AstSFormat(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* exprsp, char missingArgChar = 'd')
: ASTGEN_SUPER_SFormat(fl) {
this->fmtp(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp, missingArgChar});
this->lhsp(lhsp);
@ -3130,10 +2971,11 @@ public:
bool same(const AstNode* samep) const override { return fileline() == samep->fileline(); }
};
class AstSysFuncAsTask final : public AstNodeStmt {
// TODO: This is superseded by AstStmtExpr, remove
// Call what is normally a system function (with a return) in a non-return context
// @astgen op1 := lhsp : AstNode
// @astgen op1 := lhsp : AstNodeExpr
public:
AstSysFuncAsTask(FileLine* fl, AstNode* lhsp)
AstSysFuncAsTask(FileLine* fl, AstNodeExpr* lhsp)
: ASTGEN_SUPER_SysFuncAsTask(fl) {
this->lhsp(lhsp);
}
@ -3148,9 +2990,9 @@ public:
};
class AstSystemT final : public AstNodeStmt {
// $system used as task
// @astgen op1 := lhsp : AstNode
// @astgen op1 := lhsp : AstNodeExpr
public:
AstSystemT(FileLine* fl, AstNode* lhsp)
AstSystemT(FileLine* fl, AstNodeExpr* lhsp)
: ASTGEN_SUPER_SystemT(fl) {
this->lhsp(lhsp);
}
@ -3165,13 +3007,13 @@ public:
};
class AstTimeFormat final : public AstNodeStmt {
// Parents: stmtlist
// @astgen op1 := unitsp : AstNode
// @astgen op2 := precisionp : AstNode
// @astgen op3 := suffixp : AstNode
// @astgen op4 := widthp : AstNode
// @astgen op1 := unitsp : AstNodeExpr
// @astgen op2 := precisionp : AstNodeExpr
// @astgen op3 := suffixp : AstNodeExpr
// @astgen op4 := widthp : AstNodeExpr
public:
AstTimeFormat(FileLine* fl, AstNode* unitsp, AstNode* precisionp, AstNode* suffixp,
AstNode* widthp)
AstTimeFormat(FileLine* fl, AstNodeExpr* unitsp, AstNodeExpr* precisionp, AstNodeExpr* suffixp,
AstNodeExpr* widthp)
: ASTGEN_SUPER_TimeFormat(fl) {
this->unitsp(unitsp);
this->precisionp(precisionp);
@ -3191,7 +3033,7 @@ class AstTraceDecl final : public AstNodeStmt {
// Separate from AstTraceInc; as a declaration can't be deleted
// Parents: {statement list}
// Expression being traced - Moved to AstTraceInc by V3Trace
// @astgen op1 := valuep : Optional[AstNode]
// @astgen op1 := valuep : Optional[AstNodeExpr]
private:
uint32_t m_code = 0; // Trace identifier code; converted to ASCII by trace routines
const string m_showname; // Name of variable
@ -3204,7 +3046,7 @@ private:
public:
AstTraceDecl(FileLine* fl, const string& showname,
AstVar* varp, // For input/output state etc
AstNode* valuep, const VNumRange& bitRange, const VNumRange& arrayRange)
AstNodeExpr* valuep, const VNumRange& bitRange, const VNumRange& arrayRange)
: ASTGEN_SUPER_TraceDecl(fl)
, m_showname{showname}
, m_bitRange{bitRange}
@ -3239,7 +3081,7 @@ public:
class AstTraceInc final : public AstNodeStmt {
// Trace point dump
// @astgen op1 := precondsp : List[AstNode] // Statements to emit before this node
// @astgen op2 := valuep : AstNode // Expression being traced (from decl)
// @astgen op2 := valuep : AstNodeExpr // Expression being traced (from decl)
private:
AstTraceDecl* m_declp; // Pointer to declaration
@ -3300,7 +3142,7 @@ public:
};
class AstUCStmt final : public AstNodeStmt {
// User $c statement
// @astgen op1 := exprsp : List[AstNode]
// @astgen op1 := exprsp : List[AstNode] // (some are AstText)
public:
AstUCStmt(FileLine* fl, AstNode* exprsp)
: ASTGEN_SUPER_UCStmt(fl) {
@ -3314,10 +3156,10 @@ public:
bool same(const AstNode* /*samep*/) const override { return true; }
};
class AstWait final : public AstNodeStmt {
// @astgen op1 := condp : AstNode
// @astgen op1 := condp : AstNodeExpr
// @astgen op2 := stmtsp : List[AstNode]
public:
AstWait(FileLine* fl, AstNode* condp, AstNode* stmtsp)
AstWait(FileLine* fl, AstNodeExpr* condp, AstNode* stmtsp)
: ASTGEN_SUPER_Wait(fl) {
this->condp(condp);
this->addStmtsp(stmtsp);
@ -3335,11 +3177,11 @@ public:
};
class AstWhile final : public AstNodeStmt {
// @astgen op1 := precondsp : List[AstNode]
// @astgen op2 := condp : AstNode
// @astgen op2 := condp : AstNodeExpr
// @astgen op3 := stmtsp : List[AstNode]
// @astgen op4 := incsp : List[AstNode]
public:
AstWhile(FileLine* fl, AstNode* condp, AstNode* stmtsp = nullptr, AstNode* incsp = nullptr)
AstWhile(FileLine* fl, AstNodeExpr* condp, AstNode* stmtsp = nullptr, AstNode* incsp = nullptr)
: ASTGEN_SUPER_While(fl) {
this->condp(condp);
this->addStmtsp(stmtsp);
@ -3355,43 +3197,17 @@ public:
void addNextStmt(AstNode* newp, AstNode* belowp) override;
bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); }
};
class AstWith final : public AstNodeStmt {
// Used as argument to method, then to AstCMethodHard
// dtypep() contains the with lambda's return dtype
// Parents: funcref (similar to AstArg)
// Children: LambdaArgRef that declares the item variable
// Children: LambdaArgRef that declares the item.index variable
// Children: expression (equation establishing the with)
// @astgen op1 := indexArgRefp : AstLambdaArgRef
// @astgen op2 := valueArgRefp : AstLambdaArgRef
// @astgen op3 := exprp : AstNode
public:
AstWith(FileLine* fl, AstLambdaArgRef* indexArgRefp, AstLambdaArgRef* valueArgRefp,
AstNode* exprp)
: ASTGEN_SUPER_With(fl) {
this->indexArgRefp(indexArgRefp);
this->valueArgRefp(valueArgRefp);
this->exprp(exprp);
}
ASTGEN_MEMBERS_AstWith;
bool same(const AstNode* /*samep*/) const override { return true; }
bool hasDType() const override { return true; }
const char* broken() const override {
BROKEN_RTN(!indexArgRefp()); // varp needed to know lambda's arg dtype
BROKEN_RTN(!valueArgRefp()); // varp needed to know lambda's arg dtype
return nullptr;
}
};
// === AstNodeAssign ===
class AstAssign final : public AstNodeAssign {
public:
AstAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr)
AstAssign(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp,
AstNode* timingControlp = nullptr)
: ASTGEN_SUPER_Assign(fl, lhsp, rhsp, timingControlp) {
dtypeFrom(lhsp);
}
ASTGEN_MEMBERS_AstAssign;
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
AstNodeAssign* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) override {
AstNode* const controlp = timingControlp() ? timingControlp()->cloneTree(false) : nullptr;
return new AstAssign{fileline(), lhsp, rhsp, controlp};
}
@ -3402,17 +3218,20 @@ class AstAssignAlias final : public AstNodeAssign {
// If both sides are wires, there's no LHS vs RHS,
public:
AstAssignAlias(FileLine* fl, AstVarRef* lhsp, AstVarRef* rhsp)
: ASTGEN_SUPER_AssignAlias(fl, (AstNode*)lhsp, (AstNode*)rhsp) {}
: ASTGEN_SUPER_AssignAlias(fl, (AstNodeExpr*)lhsp, (AstNodeExpr*)rhsp) {}
ASTGEN_MEMBERS_AstAssignAlias;
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { V3ERROR_NA_RETURN(nullptr); }
AstNodeAssign* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) override {
V3ERROR_NA_RETURN(nullptr);
}
bool brokeLhsMustBeLvalue() const override { return false; }
};
class AstAssignDly final : public AstNodeAssign {
public:
AstAssignDly(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr)
AstAssignDly(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp,
AstNode* timingControlp = nullptr)
: ASTGEN_SUPER_AssignDly(fl, lhsp, rhsp, timingControlp) {}
ASTGEN_MEMBERS_AstAssignDly;
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
AstNodeAssign* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) override {
AstNode* const controlp = timingControlp() ? timingControlp()->cloneTree(false) : nullptr;
return new AstAssignDly{fileline(), lhsp, rhsp, controlp};
}
@ -3423,10 +3242,10 @@ public:
class AstAssignForce final : public AstNodeAssign {
// Procedural 'force' statement
public:
AstAssignForce(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
AstAssignForce(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
: ASTGEN_SUPER_AssignForce(fl, lhsp, rhsp) {}
ASTGEN_MEMBERS_AstAssignForce;
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
AstNodeAssign* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) override {
return new AstAssignForce{fileline(), lhsp, rhsp};
}
bool brokeLhsMustBeLvalue() const override { return true; }
@ -3434,10 +3253,10 @@ public:
class AstAssignPost final : public AstNodeAssign {
// Like Assign, but predelayed assignment requiring special order handling
public:
AstAssignPost(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
AstAssignPost(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
: ASTGEN_SUPER_AssignPost(fl, lhsp, rhsp) {}
ASTGEN_MEMBERS_AstAssignPost;
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
AstNodeAssign* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) override {
return new AstAssignPost{fileline(), lhsp, rhsp};
}
bool brokeLhsMustBeLvalue() const override { return true; }
@ -3445,10 +3264,10 @@ public:
class AstAssignPre final : public AstNodeAssign {
// Like Assign, but predelayed assignment requiring special order handling
public:
AstAssignPre(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
AstAssignPre(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
: ASTGEN_SUPER_AssignPre(fl, lhsp, rhsp) {}
ASTGEN_MEMBERS_AstAssignPre;
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
AstNodeAssign* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) override {
return new AstAssignPre{fileline(), lhsp, rhsp};
}
bool brokeLhsMustBeLvalue() const override { return true; }
@ -3456,12 +3275,12 @@ public:
class AstAssignVarScope final : public AstNodeAssign {
// Assign two VarScopes to each other
public:
AstAssignVarScope(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
AstAssignVarScope(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
: ASTGEN_SUPER_AssignVarScope(fl, lhsp, rhsp) {
dtypeFrom(rhsp);
}
ASTGEN_MEMBERS_AstAssignVarScope;
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
AstNodeAssign* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) override {
return new AstAssignVarScope{fileline(), lhsp, rhsp};
}
bool brokeLhsMustBeLvalue() const override { return false; }
@ -3470,10 +3289,11 @@ class AstAssignW final : public AstNodeAssign {
// Like assign, but wire/assign's in verilog, the only setting of the specified variable
// @astgen op4 := strengthSpecp : Optional[AstStrengthSpec]
public:
AstAssignW(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr)
AstAssignW(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp,
AstNode* timingControlp = nullptr)
: ASTGEN_SUPER_AssignW(fl, lhsp, rhsp, timingControlp) {}
ASTGEN_MEMBERS_AstAssignW;
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
AstNodeAssign* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) override {
AstNode* const controlp = timingControlp() ? timingControlp()->cloneTree(false) : nullptr;
return new AstAssignW{fileline(), lhsp, rhsp, controlp};
}
@ -3489,8 +3309,6 @@ public:
// === AstNodeCase ===
class AstCase final : public AstNodeCase {
// Case statement
// Parents: {statement list}
private:
VCaseType m_casex; // 0=case, 1=casex, 2=casez
bool m_fullPragma = false; // Synthesis full_case
bool m_parallelPragma = false; // Synthesis parallel_case
@ -3498,7 +3316,7 @@ private:
bool m_unique0Pragma = false; // unique0 case
bool m_priorityPragma = false; // priority case
public:
AstCase(FileLine* fl, VCaseType casex, AstNode* exprp, AstCaseItem* itemsp)
AstCase(FileLine* fl, VCaseType casex, AstNodeExpr* exprp, AstCaseItem* itemsp)
: ASTGEN_SUPER_Case(fl, exprp, itemsp)
, m_casex{casex} {}
ASTGEN_MEMBERS_AstCase;
@ -3524,9 +3342,8 @@ public:
};
class AstGenCase final : public AstNodeCase {
// Generate Case statement
// Parents: {statement list}
public:
AstGenCase(FileLine* fl, AstNode* exprp, AstCaseItem* itemsp)
AstGenCase(FileLine* fl, AstNodeExpr* exprp, AstCaseItem* itemsp)
: ASTGEN_SUPER_GenCase(fl, exprp, itemsp) {}
ASTGEN_MEMBERS_AstGenCase;
};
@ -3572,7 +3389,7 @@ public:
// === AstNodeFor ===
class AstGenFor final : public AstNodeFor {
public:
AstGenFor(FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, AstNode* stmtsp)
AstGenFor(FileLine* fl, AstNode* initsp, AstNodeExpr* condp, AstNode* incsp, AstNode* stmtsp)
: ASTGEN_SUPER_GenFor(fl, initsp, condp, incsp, stmtsp) {}
ASTGEN_MEMBERS_AstGenFor;
};
@ -3580,7 +3397,7 @@ public:
// === AstNodeIf ===
class AstGenIf final : public AstNodeIf {
public:
AstGenIf(FileLine* fl, AstNode* condp, AstNode* thensp, AstNode* elsesp)
AstGenIf(FileLine* fl, AstNodeExpr* condp, AstNode* thensp, AstNode* elsesp)
: ASTGEN_SUPER_GenIf(fl, condp, thensp, elsesp) {}
ASTGEN_MEMBERS_AstGenIf;
};
@ -3590,7 +3407,7 @@ private:
bool m_unique0Pragma = false; // unique0 case
bool m_priorityPragma = false; // priority case
public:
AstIf(FileLine* fl, AstNode* condp, AstNode* thensp = nullptr, AstNode* elsesp = nullptr)
AstIf(FileLine* fl, AstNodeExpr* condp, AstNode* thensp = nullptr, AstNode* elsesp = nullptr)
: ASTGEN_SUPER_If(fl, condp, thensp, elsesp) {}
ASTGEN_MEMBERS_AstIf;
bool uniquePragma() const { return m_uniquePragma; }
@ -3604,8 +3421,8 @@ public:
// === AstNodeReadWriteMem ===
class AstReadMem final : public AstNodeReadWriteMem {
public:
AstReadMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp,
AstNode* msbp)
AstReadMem(FileLine* fl, bool hex, AstNodeExpr* filenamep, AstNodeExpr* memp,
AstNodeExpr* lsbp, AstNodeExpr* msbp)
: ASTGEN_SUPER_ReadMem(fl, hex, filenamep, memp, lsbp, msbp) {}
ASTGEN_MEMBERS_AstReadMem;
string verilogKwd() const override { return (isHex() ? "$readmemh" : "$readmemb"); }
@ -3613,8 +3430,8 @@ public:
};
class AstWriteMem final : public AstNodeReadWriteMem {
public:
AstWriteMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp,
AstNode* msbp)
AstWriteMem(FileLine* fl, bool hex, AstNodeExpr* filenamep, AstNodeExpr* memp,
AstNodeExpr* lsbp, AstNodeExpr* msbp)
: ASTGEN_SUPER_WriteMem(fl, hex, filenamep, memp, lsbp, msbp) {}
ASTGEN_MEMBERS_AstWriteMem;
string verilogKwd() const override { return (isHex() ? "$writememh" : "$writememb"); }

View File

@ -252,7 +252,7 @@ int AstNodeUOrStructDType::widthAlignBytes() const {
}
}
AstNodeBiop* AstEq::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
AstNodeBiop* AstEq::newTyped(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp) {
if (lhsp->isString() && rhsp->isString()) {
return new AstEqN(fl, lhsp, rhsp);
} else if (lhsp->isDouble() && rhsp->isDouble()) {
@ -262,7 +262,7 @@ AstNodeBiop* AstEq::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
}
}
AstNodeBiop* AstEqWild::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
AstNodeBiop* AstEqWild::newTyped(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp) {
if (lhsp->isString() && rhsp->isString()) {
return new AstEqN(fl, lhsp, rhsp);
} else if (lhsp->isDouble() && rhsp->isDouble()) {
@ -279,13 +279,13 @@ AstExecGraph::AstExecGraph(FileLine* fileline, const string& name)
AstExecGraph::~AstExecGraph() { VL_DO_DANGLING(delete m_depGraphp, m_depGraphp); }
AstNode* AstInsideRange::newAndFromInside(AstNode* exprp, AstNode* lhsp, AstNode* rhsp) {
AstNode* const ap = new AstGte(fileline(), exprp->cloneTree(true), lhsp);
AstNode* const bp = new AstLte(fileline(), exprp->cloneTree(true), rhsp);
AstNodeExpr* AstInsideRange::newAndFromInside(AstNodeExpr* exprp, AstNodeExpr* lhsp,
AstNodeExpr* rhsp) {
AstNodeExpr* const ap = new AstGte{fileline(), exprp->cloneTree(true), lhsp};
AstNodeExpr* const bp = new AstLte{fileline(), exprp->cloneTree(true), rhsp};
ap->fileline()->modifyWarnOff(V3ErrorCode::UNSIGNED, true);
bp->fileline()->modifyWarnOff(V3ErrorCode::CMPCONST, true);
AstNode* const newp = new AstAnd(fileline(), ap, bp);
return newp;
return new AstAnd(fileline(), ap, bp);
}
AstConst* AstConst::parseParamLiteral(FileLine* fl, const string& literal) {
@ -1122,7 +1122,7 @@ const char* AstConstPool::broken() const {
return nullptr;
}
AstVarScope* AstConstPool::createNewEntry(const string& name, AstNode* initp) {
AstVarScope* AstConstPool::createNewEntry(const string& name, AstNodeExpr* initp) {
FileLine* const fl = initp->fileline();
AstVar* const varp = new AstVar(fl, VVarType::MODULETEMP, name, initp->dtypep());
varp->isConst(true);
@ -1575,7 +1575,7 @@ void AstInitArray::cloneRelink() {
if (it->second->clonep()) it->second = it->second->clonep();
}
}
void AstInitArray::addIndexValuep(uint64_t index, AstNode* newp) {
void AstInitArray::addIndexValuep(uint64_t index, AstNodeExpr* newp) {
const auto it = m_map.find(index);
if (it != m_map.end()) {
it->second->valuep(newp);
@ -1585,7 +1585,7 @@ void AstInitArray::addIndexValuep(uint64_t index, AstNode* newp) {
addInitsp(itemp);
}
}
AstNode* AstInitArray::getIndexValuep(uint64_t index) const {
AstNodeExpr* AstInitArray::getIndexValuep(uint64_t index) const {
const auto it = m_map.find(index);
if (it == m_map.end()) {
return nullptr;
@ -1593,8 +1593,8 @@ AstNode* AstInitArray::getIndexValuep(uint64_t index) const {
return it->second->valuep();
}
}
AstNode* AstInitArray::getIndexDefaultedValuep(uint64_t index) const {
AstNode* valuep = getIndexValuep(index);
AstNodeExpr* AstInitArray::getIndexDefaultedValuep(uint64_t index) const {
AstNodeExpr* valuep = getIndexValuep(index);
if (!valuep) valuep = defaultp();
return valuep;
}
@ -2302,8 +2302,8 @@ void AstCUse::dump(std::ostream& str) const {
AstAlways* AstAssignW::convertToAlways() {
const bool hasTimingControl = isTimingControl();
AstNode* const lhs1p = lhsp()->unlinkFrBack();
AstNode* const rhs1p = rhsp()->unlinkFrBack();
AstNodeExpr* const lhs1p = lhsp()->unlinkFrBack();
AstNodeExpr* const rhs1p = rhsp()->unlinkFrBack();
AstNode* const controlp = timingControlp() ? timingControlp()->unlinkFrBack() : nullptr;
FileLine* const flp = fileline();
AstNode* bodysp = new AstAssign{flp, lhs1p, rhs1p, controlp};

View File

@ -152,7 +152,7 @@ void V3CCtors::evalAsserts() {
AstVarRef* const vrefp
= new AstVarRef{varp->fileline(), varp, VAccess::READ};
vrefp->selfPointer("this");
AstNode* newp = vrefp;
AstNodeExpr* newp = vrefp;
if (varp->isWide()) {
newp = new AstWordSel{
varp->fileline(), newp,
@ -167,8 +167,7 @@ void V3CCtors::evalAsserts() {
new AstCStmt{varp->fileline(), "Verilated::overWidthError(\""
+ varp->prettyName() + "\");"}};
ifp->branchPred(VBranchPred::BP_UNLIKELY);
newp = ifp;
funcp->addStmtsp(newp);
funcp->addStmtsp(ifp);
}
}
}

View File

@ -250,7 +250,7 @@ private:
return true; // All is fine
}
AstNode* replaceCaseFastRecurse(AstNode* cexprp, int msb, uint32_t upperValue) {
AstNode* replaceCaseFastRecurse(AstNodeExpr* cexprp, int msb, uint32_t upperValue) {
if (msb < 0) {
// There's no space for a IF. We know upperValue is thus down to a specific
// exact value, so just return the tree value
@ -290,9 +290,9 @@ private:
// V3Number nummask (cexprp, cexprp->width(), (1UL<<msb));
// AstNode* and1p = new AstAnd(cexprp->fileline(), cexprp->cloneTree(false),
// new AstConst(cexprp->fileline(), nummask));
AstNode* const and1p
AstNodeExpr* const and1p
= new AstSel(cexprp->fileline(), cexprp->cloneTree(false), msb, 1);
AstNode* const eqp
AstNodeExpr* const eqp
= new AstNeq(cexprp->fileline(), new AstConst(cexprp->fileline(), 0), and1p);
AstIf* const ifp = new AstIf(cexprp->fileline(), eqp, tree1p, tree0p);
ifp->user3(1); // So we don't bother to clone it
@ -304,7 +304,7 @@ private:
// CASEx(cexpr,....
// -> tree of IF(msb, IF(msb-1, 11, 10)
// IF(msb-1, 01, 00))
AstNode* const cexprp = nodep->exprp()->unlinkFrBack();
AstNodeExpr* const cexprp = nodep->exprp()->unlinkFrBack();
if (debug() >= 9) { // LCOV_EXCL_START
for (uint32_t i = 0; i < (1UL << m_caseWidth); ++i) {
@ -337,7 +337,7 @@ private:
// -> IF((cexpr==icond1),istmts1,
// IF((EQ (AND MASK cexpr) (AND MASK icond1)
// ,istmts2, istmts3
AstNode* const cexprp = nodep->exprp()->unlinkFrBack();
AstNodeExpr* const cexprp = nodep->exprp()->unlinkFrBack();
// We'll do this in two stages. First stage, convert the conditions to
// the appropriate IF AND terms.
if (debug() >= 9) nodep->dumpTree(cout, " _comp_IN: ");
@ -350,13 +350,13 @@ private:
hadDefault = true;
} else {
// Expressioned clause
AstNode* icondNextp = nullptr;
AstNode* ifexprp = nullptr; // If expression to test
for (AstNode* icondp = itemp->condsp(); icondp; icondp = icondNextp) {
icondNextp = icondp->nextp();
AstNodeExpr* icondNextp = nullptr;
AstNodeExpr* ifexprp = nullptr; // If expression to test
for (AstNodeExpr* icondp = itemp->condsp(); icondp; icondp = icondNextp) {
icondNextp = VN_AS(icondp->nextp(), NodeExpr);
icondp->unlinkFrBack();
AstNode* condp = nullptr; // Default is to use and1p/and2p
AstNodeExpr* condp = nullptr; // Default is to use and1p/and2p
AstConst* const iconstp = VN_CAST(icondp, Const);
if (iconstp && neverItem(nodep, iconstp)) {
// X in casez can't ever be executed
@ -375,10 +375,10 @@ private:
nummask.opBitsNonX(iconstp->num());
V3Number numval(itemp, iconstp->width());
numval.opBitsOne(iconstp->num());
AstNode* const and1p
AstNodeExpr* const and1p
= new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
new AstConst(itemp->fileline(), nummask));
AstNode* const and2p = new AstAnd(
AstNodeExpr* const and2p = new AstAnd(
itemp->fileline(), new AstConst(itemp->fileline(), numval),
new AstConst(itemp->fileline(), nummask));
VL_DO_DANGLING(icondp->deleteTree(), icondp);
@ -386,8 +386,8 @@ private:
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
} else {
// Not a caseX mask, we can build CASEEQ(cexpr icond)
AstNode* const and1p = cexprp->cloneTree(false);
AstNode* const and2p = icondp;
AstNodeExpr* const and1p = cexprp->cloneTree(false);
AstNodeExpr* const and2p = icondp;
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
}
if (!ifexprp) {
@ -423,7 +423,7 @@ private:
AstNode* const istmtsp = itemp->stmtsp(); // Maybe null -- no action.
if (istmtsp) istmtsp->unlinkFrBackWithNext();
// Expressioned clause
AstNode* const ifexprp = itemp->condsp()->unlinkFrBack();
AstNodeExpr* const ifexprp = itemp->condsp()->unlinkFrBack();
{ // Prepare for next group
if (++depth > CASE_ENCODER_GROUP_DEPTH) depth = 1;
if (depth == 1) { // First group or starting new group
@ -436,13 +436,13 @@ private:
}
groupnextp = newp;
} else { // Continue group, modify if condition to OR in this new condition
AstNode* const condp = groupnextp->condp()->unlinkFrBack();
AstNodeExpr* const condp = groupnextp->condp()->unlinkFrBack();
groupnextp->condp(
new AstOr(ifexprp->fileline(), condp, ifexprp->cloneTree(true)));
}
}
{ // Make the new lower IF and attach in the tree
AstNode* itemexprp = ifexprp;
AstNodeExpr* itemexprp = ifexprp;
VL_DANGLING(ifexprp);
if (depth == CASE_ENCODER_GROUP_DEPTH) { // End of group - can skip the condition
VL_DO_DANGLING(itemexprp->deleteTree(), itemexprp);

View File

@ -63,7 +63,7 @@ private:
// METHODS
void insertCast(AstNode* nodep, int needsize) { // We'll insert ABOVE passed node
void insertCast(AstNodeExpr* nodep, int needsize) { // We'll insert ABOVE passed node
UINFO(4, " NeedCast " << nodep << endl);
VNRelinker relinkHandle;
nodep->unlinkFrBack(&relinkHandle);
@ -87,7 +87,7 @@ private:
return VL_IDATASIZE;
}
}
void ensureCast(AstNode* nodep) {
void ensureCast(AstNodeExpr* nodep) {
if (castSize(nodep->backp()) != castSize(nodep) || !nodep->user1()) {
insertCast(nodep, castSize(nodep->backp()));
}
@ -101,13 +101,12 @@ private:
insertCast(nodep->lhsp(), VL_IDATASIZE);
}
}
void ensureNullChecked(AstNode* nodep) {
void ensureNullChecked(AstNodeExpr* nodep) {
// TODO optimize to track null checked values and avoid where possible
if (!VN_IS(nodep->backp(), NullCheck)) {
VNRelinker relinkHandle;
nodep->unlinkFrBack(&relinkHandle);
AstNode* const newp = new AstNullCheck{nodep->fileline(), nodep};
relinkHandle.relink(newp);
relinkHandle.relink(new AstNullCheck{nodep->fileline(), nodep});
}
}

View File

@ -121,7 +121,7 @@ private:
}
// Operate on nodes
void insertClean(AstNode* nodep) { // We'll insert ABOVE passed node
void insertClean(AstNodeExpr* nodep) { // We'll insert ABOVE passed node
UINFO(4, " NeedClean " << nodep << endl);
VNRelinker relinkHandle;
nodep->unlinkFrBack(&relinkHandle);
@ -134,14 +134,14 @@ private:
cleanp->dtypeFrom(nodep); // Otherwise the AND normally picks LHS
relinkHandle.relink(cleanp);
}
void ensureClean(AstNode* nodep) {
void ensureClean(AstNodeExpr* nodep) {
computeCppWidth(nodep);
if (!isClean(nodep)) insertClean(nodep);
}
void ensureCleanAndNext(AstNode* nodep) {
void ensureCleanAndNext(AstNodeExpr* nodep) {
// Editing list, careful looping!
for (AstNode* exprp = nodep; exprp;) {
AstNode* const nextp = exprp->nextp();
for (AstNodeExpr* exprp = nodep; exprp;) {
AstNodeExpr* const nextp = VN_AS(exprp->nextp(), NodeExpr);
ensureClean(exprp);
exprp = nextp;
}
@ -237,7 +237,9 @@ 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->exprsp());
for (AstNode* argp = nodep->exprsp(); argp; argp = argp->nextp()) {
if (AstNodeExpr* const exprp = VN_CAST(argp, NodeExpr)) ensureClean(exprp);
}
}
void visit(AstTraceDecl* nodep) override {
// No cleaning, or would loose pointer to enum
@ -277,7 +279,9 @@ private:
}
void visit(AstUCStmt* nodep) override {
iterateChildren(nodep);
ensureCleanAndNext(nodep->exprsp());
for (AstNode* argp = nodep->exprsp(); argp; argp = argp->nextp()) {
if (AstNodeExpr* const exprp = VN_CAST(argp, NodeExpr)) ensureClean(exprp);
}
}
void visit(AstNodeCCall* nodep) override {
iterateChildren(nodep);

View File

@ -46,11 +46,11 @@ VL_DEFINE_DEBUG_FUNCTIONS;
class ConvertWriteRefsToRead final : public VNVisitor {
private:
// MEMBERS
AstNode* m_result = nullptr;
AstNodeExpr* m_result = nullptr;
// CONSTRUCTORS
explicit ConvertWriteRefsToRead(AstNode* nodep) {
m_result = iterateSubtreeReturnEdits(nodep);
explicit ConvertWriteRefsToRead(AstNodeExpr* nodep) {
m_result = VN_AS(iterateSubtreeReturnEdits(nodep), NodeExpr);
}
// VISITORS
@ -65,7 +65,7 @@ private:
void visit(AstNode* nodep) override { iterateChildren(nodep); }
public:
static AstNode* main(AstNode* nodep) { return ConvertWriteRefsToRead(nodep).m_result; }
static AstNodeExpr* main(AstNodeExpr* nodep) { return ConvertWriteRefsToRead(nodep).m_result; }
};
//######################################################################
@ -82,11 +82,11 @@ private:
// METHODS
AstNode* createSenseEquation(AstSenItem* nodesp) {
AstNode* senEqnp = nullptr;
AstNodeExpr* createSenseEquation(AstSenItem* nodesp) {
AstNodeExpr* senEqnp = nullptr;
for (AstSenItem* senp = nodesp; senp; senp = VN_AS(senp->nextp(), SenItem)) {
UASSERT_OBJ(senp->edgeType() == VEdgeType::ET_TRUE, senp, "Should have been lowered");
AstNode* const senOnep = senp->sensp()->cloneTree(false);
AstNodeExpr* const senOnep = senp->sensp()->cloneTree(false);
senEqnp = senEqnp ? new AstOr{senp->fileline(), senEqnp, senOnep} : senOnep;
}
return senEqnp;
@ -111,7 +111,7 @@ private:
return newvscp;
}
AstIf* makeActiveIf(AstSenTree* sensesp) {
AstNode* const senEqnp = createSenseEquation(sensesp->sensesp());
AstNodeExpr* const senEqnp = createSenseEquation(sensesp->sensesp());
UASSERT_OBJ(senEqnp, sensesp, "No sense equation, shouldn't be in sequent activation.");
AstIf* const newifp = new AstIf{sensesp->fileline(), senEqnp};
return newifp;
@ -126,9 +126,9 @@ private:
// COVERTOGGLE(INC, ORIG, CHANGE) ->
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
AstNode* const incp = nodep->incp()->unlinkFrBack();
AstNode* const origp = nodep->origp()->unlinkFrBack();
AstNode* const changeWrp = nodep->changep()->unlinkFrBack();
AstNode* const changeRdp = ConvertWriteRefsToRead::main(changeWrp->cloneTree(false));
AstNodeExpr* const origp = nodep->origp()->unlinkFrBack();
AstNodeExpr* const changeWrp = nodep->changep()->unlinkFrBack();
AstNodeExpr* const changeRdp = ConvertWriteRefsToRead::main(changeWrp->cloneTree(false));
AstIf* const newp
= new AstIf{nodep->fileline(), new AstXor{nodep->fileline(), origp, changeRdp}, incp};
// We could add another IF to detect posedges, and only increment if so.

View File

@ -42,7 +42,8 @@ static void makeVlToString(AstClass* nodep) {
funcp->isConst(false);
funcp->isStatic(false);
funcp->protect(false);
AstNode* const exprp = new AstCExpr{nodep->fileline(), "obj ? obj->to_string() : \"null\"", 0};
AstNodeExpr* const exprp
= new AstCExpr{nodep->fileline(), "obj ? obj->to_string() : \"null\"", 0};
exprp->dtypeSetString();
funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
nodep->addStmtsp(funcp);
@ -55,7 +56,7 @@ static void makeVlToString(AstIface* nodep) {
funcp->isConst(false);
funcp->isStatic(false);
funcp->protect(false);
AstNode* const exprp = new AstCExpr{nodep->fileline(), "obj ? obj->name() : \"null\"", 0};
AstNodeExpr* const exprp = new AstCExpr{nodep->fileline(), "obj ? obj->name() : \"null\"", 0};
exprp->dtypeSetString();
funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
nodep->addStmtsp(funcp);
@ -65,7 +66,7 @@ static void makeToString(AstClass* nodep) {
funcp->isConst(true);
funcp->isStatic(false);
funcp->protect(false);
AstNode* const exprp
AstCExpr* const exprp
= new AstCExpr{nodep->fileline(), R"(std::string{"'{"} + to_string_middle() + "}")", 0};
exprp->dtypeSetString();
funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});

View File

@ -80,7 +80,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
// Holds a node to be added as a term in the reduction tree, it's equivalent op count, and a
// bool indicating if the term is clean (0/1 value, or if the top bits might be dirty)
using ResultTerm = std::tuple<AstNode*, unsigned, bool>;
using ResultTerm = std::tuple<AstNodeExpr*, unsigned, bool>;
class LeafInfo final { // Leaf node (either AstConst or AstVarRef)
// MEMBERS
@ -243,7 +243,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
FileLine* const fl = m_refp->fileline();
// Get the term we are referencing (the WordSel, if wide, otherwise just the VarRef)
AstNode* srcp = VN_CAST(m_refp->backp(), WordSel);
AstNodeExpr* srcp = VN_CAST(m_refp->backp(), WordSel);
if (!srcp) srcp = m_refp;
srcp = srcp->cloneTree(false);
@ -260,7 +260,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
UASSERT(maskVal != 0, "Should have been recognized as having const 0 result");
// Parts of the return value
AstNode* resultp = srcp; // The tree for this term
AstNodeExpr* resultp = srcp; // The tree for this term
unsigned ops = 0; // Number of ops in this term
bool clean = false; // Whether the term is clean (has value 0 or 1)
@ -344,9 +344,9 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
unsigned m_ops; // Number of operations such as And, Or, Xor, Sel...
int m_lsb = 0; // Current LSB
LeafInfo* m_leafp = nullptr; // AstConst or AstVarRef that currently looking for
const AstNode* const m_rootp; // Root of this AST subtree
const AstNodeExpr* const m_rootp; // Root of this AST subtree
std::vector<std::pair<AstNode*, FrozenNodeInfo>>
std::vector<std::pair<AstNodeExpr*, FrozenNodeInfo>>
m_frozenNodes; // Nodes that cannot be optimized
std::vector<BitPolarityEntry> m_bitPolarities; // Polarity of bits found during iterate()
std::vector<std::unique_ptr<VarInfo>> m_varInfos; // VarInfo for each variable, [0] is nullptr
@ -529,7 +529,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
Restorer restorer{*this};
LeafInfo leafInfo{m_lsb};
m_leafp = &leafInfo;
AstNode* opp = right ? nodep->rhsp() : nodep->lhsp();
AstNodeExpr* opp = right ? nodep->rhsp() : nodep->lhsp();
const bool origFailed = m_failed;
iterate(opp);
if (leafInfo.constp() || m_failed) {
@ -625,7 +625,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
}
// CONSTRUCTORS
ConstBitOpTreeVisitor(AstNode* nodep, unsigned externalOps)
ConstBitOpTreeVisitor(AstNodeExpr* nodep, unsigned externalOps)
: m_ops{externalOps}
, m_rootp{nodep} {
// Fill nullptr at [0] because AstVarScope::user4 is 0 by default
@ -656,8 +656,8 @@ public:
// (3'b000 != (3'b011 & v)) | v[2] => 3'b000 != (3'b111 & v)
// Reduction ops are transformed in the same way.
// &{v[0], v[1]} => 2'b11 == (2'b11 & v)
static AstNode* simplify(AstNode* nodep, int resultWidth, unsigned externalOps,
VDouble0& reduction) {
static AstNodeExpr* simplify(AstNodeExpr* nodep, int resultWidth, unsigned externalOps,
VDouble0& reduction) {
UASSERT_OBJ(1 <= resultWidth && resultWidth <= 64, nodep, "resultWidth out of range");
// Walk tree, gathering all terms referenced in expression
@ -673,7 +673,7 @@ public:
// whether we have clean/dirty terms. visitor.m_varInfos appears in deterministic order,
// so the optimized tree is deterministic as well.
std::vector<AstNode*> termps;
std::vector<AstNodeExpr*> termps;
termps.reserve(visitor.m_varInfos.size() - 1);
unsigned resultOps = 0;
bool hasCleanTerm = false;
@ -683,7 +683,7 @@ public:
if (!v) continue; // Skip nullptr at m_varInfos[0]
if (v->hasConstResult()) {
// If a constant term is known, we can either drop it or the whole tree is constant
AstNode* resultp = nullptr;
AstNodeExpr* resultp = nullptr;
if (v->getConstResult()) {
UASSERT_OBJ(visitor.isOrTree(), nodep,
"Only OR tree can yield known 1 result");
@ -715,10 +715,11 @@ public:
}
}
std::map<FrozenNodeInfo, std::vector<AstNode*>> frozenNodes; // Group by FrozenNodeInfo
// Group by FrozenNodeInfo
std::map<FrozenNodeInfo, std::vector<AstNodeExpr*>> frozenNodes;
// Check if frozen terms are clean or not
for (const auto& frozenInfo : visitor.m_frozenNodes) {
AstNode* const termp = frozenInfo.first;
AstNodeExpr* const termp = frozenInfo.first;
// Comparison operators are clean
if ((VN_IS(termp, Eq) || VN_IS(termp, Neq) || VN_IS(termp, Lt) || VN_IS(termp, Lte)
|| VN_IS(termp, Gt) || VN_IS(termp, Gte))
@ -752,8 +753,8 @@ public:
if (debug() >= 9) { // LCOV_EXCL_START
cout << "Bitop tree considered: " << endl;
for (AstNode* const termp : termps) termp->dumpTree("Reduced term: ");
for (const std::pair<AstNode*, FrozenNodeInfo>& termp : visitor.m_frozenNodes) {
for (AstNodeExpr* const termp : termps) termp->dumpTree("Reduced term: ");
for (const std::pair<AstNodeExpr*, FrozenNodeInfo>& termp : visitor.m_frozenNodes) {
termp.first->dumpTree("Frozen term with lsb " + std::to_string(termp.second.m_lsb)
+ " polarity " + std::to_string(termp.second.m_polarity)
+ ": ");
@ -767,8 +768,8 @@ public:
// (all of which were zeroes)
if (termps.empty() && visitor.m_frozenNodes.empty()) {
reduction += visitor.m_ops;
AstNode* const resultp = needsFlip ? new AstConst{fl, AstConst::BitTrue{}}
: new AstConst{fl, AstConst::BitFalse{}};
AstNodeExpr* const resultp = needsFlip ? new AstConst{fl, AstConst::BitTrue{}}
: new AstConst{fl, AstConst::BitFalse{}};
resultp->dtypeChgWidth(resultWidth, 1);
return resultp;
}
@ -783,7 +784,7 @@ public:
reduction += visitor.m_ops - resultOps;
// Reduction op to combine terms
const auto reduce = [&visitor, fl](AstNode* lhsp, AstNode* rhsp) -> AstNode* {
const auto reduce = [&visitor, fl](AstNodeExpr* lhsp, AstNodeExpr* rhsp) -> AstNodeExpr* {
if (!lhsp) return rhsp;
if (visitor.isAndTree()) {
return new AstAnd{fl, lhsp, rhsp};
@ -795,15 +796,15 @@ public:
};
// Compute result by reducing all terms
AstNode* resultp = nullptr;
for (AstNode* const termp : termps) { //
AstNodeExpr* resultp = nullptr;
for (AstNodeExpr* const termp : termps) { //
resultp = reduce(resultp, termp);
}
// Add any frozen terms to the reduction
for (auto&& nodes : frozenNodes) {
// nodes.second has same lsb and polarity
AstNode* termp = nullptr;
for (AstNode* const itemp : nodes.second) {
AstNodeExpr* termp = nullptr;
for (AstNodeExpr* const itemp : nodes.second) {
termp = reduce(termp, itemp->unlinkFrBack());
}
if (nodes.first.m_lsb > 0) { // LSB is not 0, so shiftR
@ -961,7 +962,7 @@ private:
// When bool is casted to int, the value is either 0 or 1
AstConst* const constp = VN_AS(andp->lhsp(), Const);
UASSERT_OBJ(constp && constp->isOne(), andp->lhsp(), "TRREEOPC must meet this condition");
AstNode* const rhsp = andp->rhsp();
AstNodeExpr* const rhsp = andp->rhsp();
AstCCast* ccastp = nullptr;
const auto isEqOrNeq
= [](AstNode* nodep) -> bool { return VN_IS(nodep, Eq) || VN_IS(nodep, Neq); };
@ -999,7 +1000,7 @@ private:
// Someday we'll sort the biops completely and this can be simplified
// This often results from our simplified clock generation:
// if (rst) ... else if (enable)... -> OR(rst,AND(!rst,enable))
AstNode* ap;
AstNodeExpr* ap;
AstNodeBiop* andp;
if (VN_IS(nodep->lhsp(), And)) {
andp = VN_AS(nodep->lhsp(), And);
@ -1011,7 +1012,7 @@ private:
return false;
}
const AstNodeUniop* notp;
AstNode* cp;
AstNodeExpr* cp;
if (VN_IS(andp->lhsp(), Not)) {
notp = VN_AS(andp->lhsp(), Not);
cp = andp->rhsp();
@ -1021,7 +1022,7 @@ private:
} else {
return false;
}
AstNode* const bp = notp->lhsp();
AstNodeExpr* const bp = notp->lhsp();
if (!operandsSame(ap, bp)) return false;
// Do it
cp->unlinkFrBack();
@ -1140,7 +1141,7 @@ private:
return false;
}
bool matchBitOpTree(AstNode* nodep) {
bool matchBitOpTree(AstNodeExpr* nodep) {
if (nodep->widthMin() != 1) return false;
if (!v3Global.opt.fConstBitOpTree()) return false;
@ -1277,8 +1278,8 @@ private:
&& nodep->lsbConst() == 0))
return false;
if (debug() >= 9) nodep->dumpTree(cout, "SEL(BI)-in:");
AstNode* const bilhsp = bip->lhsp()->unlinkFrBack();
AstNode* const birhsp = bip->rhsp()->unlinkFrBack();
AstNodeExpr* const bilhsp = bip->lhsp()->unlinkFrBack();
AstNodeExpr* const birhsp = bip->rhsp()->unlinkFrBack();
bip->lhsp(new AstSel(nodep->fileline(), bilhsp, 0, nodep->widthConst()));
bip->rhsp(new AstSel(nodep->fileline(), birhsp, 0, nodep->widthConst()));
if (debug() >= 9) bip->dumpTree(cout, "SEL(BI)-ou:");
@ -1294,7 +1295,7 @@ private:
&& VN_IS(nodep->widthp(), Const))) {
return false;
}
AstNode* const ap = shiftp->lhsp();
AstNodeExpr* const ap = shiftp->lhsp();
AstConst* const bp = VN_AS(shiftp->rhsp(), Const);
AstConst* const lp = VN_AS(nodep->lsbp(), Const);
if (bp->isWide() || bp->num().isFourState() || bp->num().isNegative() || lp->isWide()
@ -1321,7 +1322,7 @@ private:
// would be incorrect. See also operandBiExtendConst
AstExtend* const extendp = VN_CAST(nodep->rhsp(), Extend);
if (!extendp) return false;
AstNode* const smallerp = extendp->lhsp();
AstNodeExpr* const smallerp = extendp->lhsp();
const int subsize = smallerp->width();
AstConst* const constp = VN_CAST(nodep->lhsp(), Const);
if (!constp) return false;
@ -1477,7 +1478,7 @@ private:
const int rend = (rstart->toSInt() + rwidth->toSInt());
return (rend == lstart->toSInt());
}
bool ifMergeAdjacent(AstNode* lhsp, AstNode* rhsp) {
bool ifMergeAdjacent(AstNodeExpr* lhsp, AstNodeExpr* rhsp) {
// called by concatmergeable to determine if {lhsp, rhsp} make sense
if (!v3Global.opt.fAssemble()) return false; // opt disabled
// two same varref
@ -1514,7 +1515,7 @@ private:
if (rend == rfromp->width() && lstart->toSInt() == 0) return true;
return false;
}
bool concatMergeable(const AstNode* lhsp, const AstNode* rhsp, unsigned depth) {
bool concatMergeable(const AstNodeExpr* lhsp, const AstNodeExpr* rhsp, unsigned depth) {
// determine if {a OP b, c OP d} => {a, c} OP {b, d} is advantageous
if (!v3Global.opt.fAssemble()) return false; // opt disabled
if (lhsp->type() != rhsp->type()) return false;
@ -1575,7 +1576,7 @@ private:
VL_DO_DANGLING(replaceNum(nodep, val), nodep);
}
void replaceZero(AstNode* nodep) { VL_DO_DANGLING(replaceNum(nodep, 0), nodep); }
void replaceZeroChkPure(AstNode* nodep, AstNode* checkp) {
void replaceZeroChkPure(AstNode* nodep, AstNodeExpr* checkp) {
// For example, "0 * n" -> 0 if n has no side effects
// Else strength reduce it to 0 & n.
// If ever change the operation note AstAnd rule specially ignores this created pattern
@ -1637,7 +1638,7 @@ private:
// Replacement functions.
// These all take a node and replace it with something else
void replaceWChild(AstNode* nodep, AstNode* childp) {
void replaceWChild(AstNode* nodep, AstNodeExpr* childp) {
// NODE(..., CHILD(...)) -> CHILD(...)
childp->unlinkFrBackWithNext();
// If replacing a SEL for example, the data type comes from the parent (is less wide).
@ -1646,7 +1647,7 @@ private:
nodep->replaceWith(childp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void replaceWChildBool(AstNode* nodep, AstNode* childp) {
void replaceWChildBool(AstNode* nodep, AstNodeExpr* childp) {
// NODE(..., CHILD(...)) -> REDOR(CHILD(...))
childp->unlinkFrBack();
if (childp->width1()) {
@ -1688,10 +1689,10 @@ private:
// BIASV(CONSTa, BIASV(CONSTb, c)) -> BIASV( BIASV_CONSTED(a,b), c)
// BIASV(SAMEa, BIASV(SAMEb, c)) -> BIASV( BIASV(SAMEa,SAMEb), c)
// nodep->dumpTree(cout, " repAsvConst_old: ");
AstNode* const ap = nodep->lhsp();
AstNodeExpr* const ap = nodep->lhsp();
AstNodeBiop* const rp = VN_AS(nodep->rhsp(), NodeBiop);
AstNode* const bp = rp->lhsp();
AstNode* const cp = rp->rhsp();
AstNodeExpr* const bp = rp->lhsp();
AstNodeExpr* const cp = rp->rhsp();
ap->unlinkFrBack();
bp->unlinkFrBack();
cp->unlinkFrBack();
@ -1706,9 +1707,9 @@ private:
void replaceAsvLUp(AstNodeBiop* nodep) {
// BIASV(BIASV(CONSTll,lr),r) -> BIASV(CONSTll,BIASV(lr,r))
AstNodeBiop* const lp = VN_AS(nodep->lhsp()->unlinkFrBack(), NodeBiop);
AstNode* const llp = lp->lhsp()->unlinkFrBack();
AstNode* const lrp = lp->rhsp()->unlinkFrBack();
AstNode* const rp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const llp = lp->lhsp()->unlinkFrBack();
AstNodeExpr* const lrp = lp->rhsp()->unlinkFrBack();
AstNodeExpr* const rp = nodep->rhsp()->unlinkFrBack();
nodep->lhsp(llp);
nodep->rhsp(lp);
lp->lhsp(lrp);
@ -1717,10 +1718,10 @@ private:
}
void replaceAsvRUp(AstNodeBiop* nodep) {
// BIASV(l,BIASV(CONSTrl,rr)) -> BIASV(CONSTrl,BIASV(l,rr))
AstNode* const lp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const lp = nodep->lhsp()->unlinkFrBack();
AstNodeBiop* const rp = VN_AS(nodep->rhsp()->unlinkFrBack(), NodeBiop);
AstNode* const rlp = rp->lhsp()->unlinkFrBack();
AstNode* const rrp = rp->rhsp()->unlinkFrBack();
AstNodeExpr* const rlp = rp->lhsp()->unlinkFrBack();
AstNodeExpr* const rrp = rp->rhsp()->unlinkFrBack();
nodep->lhsp(rlp);
nodep->rhsp(rp);
rp->lhsp(lp);
@ -1733,11 +1734,11 @@ private:
// nodep ^lp ^llp ^lrp ^rp ^rlp ^rrp
// (Or/And may also be reversed)
AstNodeBiop* const lp = VN_AS(nodep->lhsp()->unlinkFrBack(), NodeBiop);
AstNode* const llp = lp->lhsp()->unlinkFrBack();
AstNode* const lrp = lp->rhsp()->unlinkFrBack();
AstNodeExpr* const llp = lp->lhsp()->unlinkFrBack();
AstNodeExpr* const lrp = lp->rhsp()->unlinkFrBack();
AstNodeBiop* const rp = VN_AS(nodep->rhsp()->unlinkFrBack(), NodeBiop);
AstNode* const rlp = rp->lhsp()->unlinkFrBack();
AstNode* const rrp = rp->rhsp()->unlinkFrBack();
AstNodeExpr* const rlp = rp->lhsp()->unlinkFrBack();
AstNodeExpr* const rrp = rp->rhsp()->unlinkFrBack();
nodep->replaceWith(lp);
if (operandsSame(llp, rlp)) {
lp->lhsp(llp);
@ -1764,11 +1765,11 @@ private:
// Or(Shift(ll,CONSTlr),Shift(rl,CONSTrr==lr)) -> Shift(Or(ll,rl),CONSTlr)
// (Or/And may also be reversed)
AstNodeBiop* const lp = VN_AS(nodep->lhsp()->unlinkFrBack(), NodeBiop);
AstNode* const llp = lp->lhsp()->unlinkFrBack();
AstNode* const lrp = lp->rhsp()->unlinkFrBack();
AstNodeExpr* const llp = lp->lhsp()->unlinkFrBack();
AstNodeExpr* const lrp = lp->rhsp()->unlinkFrBack();
AstNodeBiop* const rp = VN_AS(nodep->rhsp()->unlinkFrBack(), NodeBiop);
AstNode* const rlp = rp->lhsp()->unlinkFrBack();
AstNode* const rrp = rp->rhsp()->unlinkFrBack();
AstNodeExpr* const rlp = rp->lhsp()->unlinkFrBack();
AstNodeExpr* const rrp = rp->rhsp()->unlinkFrBack();
nodep->replaceWith(lp);
lp->lhsp(nodep);
lp->rhsp(lrp);
@ -1803,10 +1804,10 @@ private:
void replaceConcatMerge(AstConcat* nodep) {
AstNodeBiop* const lp = VN_AS(nodep->lhsp(), NodeBiop);
AstNodeBiop* const rp = VN_AS(nodep->rhsp(), NodeBiop);
AstNode* const llp = lp->lhsp()->cloneTree(false);
AstNode* const lrp = lp->rhsp()->cloneTree(false);
AstNode* const rlp = rp->lhsp()->cloneTree(false);
AstNode* const rrp = rp->rhsp()->cloneTree(false);
AstNodeExpr* const llp = lp->lhsp()->cloneTree(false);
AstNodeExpr* const lrp = lp->rhsp()->cloneTree(false);
AstNodeExpr* const rlp = rp->lhsp()->cloneTree(false);
AstNodeExpr* const rrp = rp->rhsp()->cloneTree(false);
if (concatMergeable(lp, rp, 0)) {
AstConcat* const newlp = new AstConcat(rlp->fileline(), llp, rlp);
AstConcat* const newrp = new AstConcat(rrp->fileline(), lrp, rrp);
@ -1824,21 +1825,21 @@ private:
nodep->v3fatalSrc("tried to merge two Concat which are not adjacent");
}
}
void replaceExtend(AstNode* nodep, AstNode* arg0p) {
void replaceExtend(AstNode* nodep, AstNodeExpr* arg0p) {
// -> EXTEND(nodep)
// like a AstExtend{$rhsp}, but we need to set the width correctly from base node
arg0p->unlinkFrBack();
AstNode* const newp
AstNodeExpr* const newp
= (VN_IS(nodep, ExtendS)
? static_cast<AstNode*>(new AstExtendS{nodep->fileline(), arg0p})
: static_cast<AstNode*>(new AstExtend{nodep->fileline(), arg0p}));
? static_cast<AstNodeExpr*>(new AstExtendS{nodep->fileline(), arg0p})
: static_cast<AstNodeExpr*>(new AstExtend{nodep->fileline(), arg0p}));
newp->dtypeFrom(nodep);
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void replacePowShift(AstNodeBiop* nodep) { // Pow or PowS
UINFO(5, "POW(2,b)->SHIFTL(1,b) " << nodep << endl);
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstShiftL* const newp
= new AstShiftL(nodep->fileline(), new AstConst(nodep->fileline(), 1), rhsp);
newp->dtypeFrom(nodep);
@ -1849,7 +1850,7 @@ private:
void replaceMulShift(AstMul* nodep) { // Mul, but not MulS as not simple shift
UINFO(5, "MUL(2^n,b)->SHIFTL(b,n) " << nodep << endl);
const int amount = VN_AS(nodep->lhsp(), Const)->num().mostSetBitP1() - 1; // 2^n->n+1
AstNode* const opp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const opp = nodep->rhsp()->unlinkFrBack();
AstShiftL* const newp
= new AstShiftL(nodep->fileline(), opp, new AstConst(nodep->fileline(), amount));
newp->dtypeFrom(nodep);
@ -1859,7 +1860,7 @@ private:
void replaceDivShift(AstDiv* nodep) { // Mul, but not MulS as not simple shift
UINFO(5, "DIV(b,2^n)->SHIFTR(b,n) " << nodep << endl);
const int amount = VN_AS(nodep->rhsp(), Const)->num().mostSetBitP1() - 1; // 2^n->n+1
AstNode* const opp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const opp = nodep->lhsp()->unlinkFrBack();
AstShiftR* const newp
= new AstShiftR(nodep->fileline(), opp, new AstConst(nodep->fileline(), amount));
newp->dtypeFrom(nodep);
@ -1871,7 +1872,7 @@ private:
const int amount = VN_AS(nodep->rhsp(), Const)->num().mostSetBitP1() - 1; // 2^n->n+1
V3Number mask(nodep, nodep->width());
mask.setMask(amount);
AstNode* const opp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const opp = nodep->lhsp()->unlinkFrBack();
AstAnd* const newp
= new AstAnd(nodep->fileline(), opp, new AstConst(nodep->fileline(), mask));
newp->dtypeFrom(nodep);
@ -1884,9 +1885,9 @@ private:
nodep->unlinkFrBack(&handle);
AstNodeBiop* const lhsp = VN_AS(nodep->lhsp(), NodeBiop);
lhsp->unlinkFrBack();
AstNode* const shiftp = nodep->rhsp()->unlinkFrBack();
AstNode* const ap = lhsp->lhsp()->unlinkFrBack();
AstNode* const bp = lhsp->rhsp()->unlinkFrBack();
AstNodeExpr* const shiftp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const ap = lhsp->lhsp()->unlinkFrBack();
AstNodeExpr* const bp = lhsp->rhsp()->unlinkFrBack();
AstNodeBiop* const shift1p = nodep;
AstNodeBiop* const shift2p = nodep->cloneTree(true);
shift1p->lhsp(ap);
@ -1904,9 +1905,9 @@ private:
if (debug() >= 9) nodep->dumpTree(cout, " repShiftShift_old: ");
AstNodeBiop* const lhsp = VN_AS(nodep->lhsp(), NodeBiop);
lhsp->unlinkFrBack();
AstNode* const ap = lhsp->lhsp()->unlinkFrBack();
AstNode* const shift1p = lhsp->rhsp()->unlinkFrBack();
AstNode* const shift2p = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const ap = lhsp->lhsp()->unlinkFrBack();
AstNodeExpr* const shift1p = lhsp->rhsp()->unlinkFrBack();
AstNodeExpr* const shift2p = nodep->rhsp()->unlinkFrBack();
// Shift1p and shift2p may have different sizes, both are
// self-determined so sum with infinite width
if (nodep->type() == lhsp->type()) {
@ -1927,7 +1928,7 @@ private:
const int newshift = shift1 + shift2;
VL_DO_DANGLING(shift1p->deleteTree(), shift1p);
VL_DO_DANGLING(shift2p->deleteTree(), shift2p);
AstNode* newp;
AstNodeExpr* newp;
V3Number mask1(nodep, nodep->width());
V3Number ones(nodep, nodep->width());
ones.setMask(nodep->width());
@ -1999,9 +2000,9 @@ private:
UINFO(4, " && " << nextp << endl);
// nodep->dumpTree(cout, "comb1: ");
// nextp->dumpTree(cout, "comb2: ");
AstNode* const rhs1p = nodep->rhsp()->unlinkFrBack();
AstNode* const rhs2p = nextp->rhsp()->unlinkFrBack();
AstNode* newp;
AstNodeExpr* const rhs1p = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const rhs2p = nextp->rhsp()->unlinkFrBack();
AstNodeAssign* newp;
if (lsbFirstAssign) {
newp = nodep->cloneType(new AstSel(sel1p->fileline(), varref1p->unlinkFrBack(),
sel1p->lsbConst(), sel1p->width() + sel2p->width()),
@ -2072,11 +2073,11 @@ private:
}
if (debug() >= 9) nodep->dumpTree(cout, " Ass_old: ");
// Unlink the stuff
AstNode* const lc1p = VN_AS(nodep->lhsp(), Concat)->lhsp()->unlinkFrBack();
AstNode* const lc2p = VN_AS(nodep->lhsp(), Concat)->rhsp()->unlinkFrBack();
AstNode* const conp = VN_AS(nodep->lhsp(), Concat)->unlinkFrBack();
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* const rhs2p = rhsp->cloneTree(false);
AstNodeExpr* const lc1p = VN_AS(nodep->lhsp(), Concat)->lhsp()->unlinkFrBack();
AstNodeExpr* const lc2p = VN_AS(nodep->lhsp(), Concat)->rhsp()->unlinkFrBack();
AstNodeExpr* const conp = VN_AS(nodep->lhsp(), Concat)->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const rhs2p = rhsp->cloneTree(false);
// Calc widths
const int lsb2 = 0;
const int msb2 = lsb2 + lc2p->width() - 1;
@ -2090,8 +2091,8 @@ private:
//*** Not cloneTree; just one node.
AstNodeAssign* newp = nullptr;
if (!need_temp) {
AstNodeAssign* const asn1ap = VN_AS(nodep->cloneType(lc1p, sel1p), NodeAssign);
AstNodeAssign* const asn2ap = VN_AS(nodep->cloneType(lc2p, sel2p), NodeAssign);
AstNodeAssign* const asn1ap = nodep->cloneType(lc1p, sel1p);
AstNodeAssign* const asn2ap = nodep->cloneType(lc2p, sel2p);
asn1ap->dtypeFrom(sel1p);
asn2ap->dtypeFrom(sel2p);
newp = AstNode::addNext(newp, asn1ap);
@ -2103,29 +2104,21 @@ private:
// We could create just one temp variable, but we'll get better optimization
// if we make one per term.
AstVar* const temp1p
= new AstVar(sel1p->fileline(), VVarType::BLOCKTEMP,
m_concswapNames.get(sel1p), VFlagLogicPacked(), msb1 - lsb1 + 1);
= new AstVar{sel1p->fileline(), VVarType::BLOCKTEMP,
m_concswapNames.get(sel1p), VFlagLogicPacked(), msb1 - lsb1 + 1};
AstVar* const temp2p
= new AstVar(sel2p->fileline(), VVarType::BLOCKTEMP,
m_concswapNames.get(sel2p), VFlagLogicPacked(), msb2 - lsb2 + 1);
= new AstVar{sel2p->fileline(), VVarType::BLOCKTEMP,
m_concswapNames.get(sel2p), VFlagLogicPacked(), msb2 - lsb2 + 1};
m_modp->addStmtsp(temp1p);
m_modp->addStmtsp(temp2p);
AstNodeAssign* const asn1ap
= VN_AS(nodep->cloneType(
new AstVarRef(sel1p->fileline(), temp1p, VAccess::WRITE), sel1p),
NodeAssign);
AstNodeAssign* const asn2ap
= VN_AS(nodep->cloneType(
new AstVarRef(sel2p->fileline(), temp2p, VAccess::WRITE), sel2p),
NodeAssign);
AstNodeAssign* const asn1bp
= VN_AS(nodep->cloneType(
lc1p, new AstVarRef(sel1p->fileline(), temp1p, VAccess::READ)),
NodeAssign);
AstNodeAssign* const asn2bp
= VN_AS(nodep->cloneType(
lc2p, new AstVarRef(sel2p->fileline(), temp2p, VAccess::READ)),
NodeAssign);
AstNodeAssign* const asn1ap = nodep->cloneType(
new AstVarRef{sel1p->fileline(), temp1p, VAccess::WRITE}, sel1p);
AstNodeAssign* const asn2ap = nodep->cloneType(
new AstVarRef{sel2p->fileline(), temp2p, VAccess::WRITE}, sel2p);
AstNodeAssign* const asn1bp = nodep->cloneType(
lc1p, new AstVarRef{sel1p->fileline(), temp1p, VAccess::READ});
AstNodeAssign* const asn2bp = nodep->cloneType(
lc2p, new AstVarRef{sel2p->fileline(), temp2p, VAccess::READ});
asn1ap->dtypeFrom(temp1p);
asn1bp->dtypeFrom(temp1p);
asn2ap->dtypeFrom(temp2p);
@ -2147,9 +2140,9 @@ private:
// The right-streaming operator on rhs of assignment does not
// change the order of bits. Eliminate stream but keep its lhsp
// Unlink the stuff
AstNode* const srcp = VN_AS(nodep->rhsp(), StreamR)->lhsp()->unlinkFrBack();
AstNodeExpr* const srcp = VN_AS(nodep->rhsp(), StreamR)->lhsp()->unlinkFrBack();
AstNode* const sizep = VN_AS(nodep->rhsp(), StreamR)->rhsp()->unlinkFrBack();
AstNode* const streamp = VN_AS(nodep->rhsp(), StreamR)->unlinkFrBack();
AstNodeExpr* const streamp = VN_AS(nodep->rhsp(), StreamR)->unlinkFrBack();
nodep->rhsp(srcp);
// Cleanup
VL_DO_DANGLING(sizep->deleteTree(), sizep);
@ -2161,9 +2154,9 @@ private:
const int dWidth = VN_AS(nodep->lhsp(), StreamL)->lhsp()->width();
const int sWidth = nodep->rhsp()->width();
// Unlink the stuff
AstNode* const dstp = VN_AS(nodep->lhsp(), StreamL)->lhsp()->unlinkFrBack();
AstNode* streamp = VN_AS(nodep->lhsp(), StreamL)->unlinkFrBack();
AstNode* const srcp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const dstp = VN_AS(nodep->lhsp(), StreamL)->lhsp()->unlinkFrBack();
AstNodeExpr* streamp = VN_AS(nodep->lhsp(), StreamL)->unlinkFrBack();
AstNodeExpr* const srcp = nodep->rhsp()->unlinkFrBack();
// Connect the rhs to the stream operator and update its width
VN_AS(streamp, StreamL)->lhsp(srcp);
streamp->dtypeSetLogicUnsized(srcp->width(), srcp->widthMin(), VSigning::UNSIGNED);
@ -2182,10 +2175,10 @@ private:
const int dWidth = VN_AS(nodep->lhsp(), StreamR)->lhsp()->width();
const int sWidth = nodep->rhsp()->width();
// Unlink the stuff
AstNode* const dstp = VN_AS(nodep->lhsp(), StreamR)->lhsp()->unlinkFrBack();
AstNodeExpr* const dstp = VN_AS(nodep->lhsp(), StreamR)->lhsp()->unlinkFrBack();
AstNode* const sizep = VN_AS(nodep->lhsp(), StreamR)->rhsp()->unlinkFrBack();
AstNode* const streamp = VN_AS(nodep->lhsp(), StreamR)->unlinkFrBack();
AstNode* srcp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const streamp = VN_AS(nodep->lhsp(), StreamR)->unlinkFrBack();
AstNodeExpr* srcp = nodep->rhsp()->unlinkFrBack();
if (sWidth > dWidth) {
srcp = new AstSel(streamp->fileline(), srcp, sWidth - dWidth, dWidth);
}
@ -2218,7 +2211,8 @@ private:
void replaceBoolShift(AstNode* nodep) {
if (debug() >= 9) nodep->dumpTree(cout, " bshft_old: ");
AstConst* const andConstp = VN_AS(VN_AS(nodep, And)->lhsp(), Const);
AstNode* const fromp = VN_AS(VN_AS(nodep, And)->rhsp(), ShiftR)->lhsp()->unlinkFrBack();
AstNodeExpr* const fromp
= VN_AS(VN_AS(nodep, And)->rhsp(), ShiftR)->lhsp()->unlinkFrBack();
AstConst* const shiftConstp
= VN_AS(VN_AS(VN_AS(nodep, And)->rhsp(), ShiftR)->rhsp(), Const);
V3Number val(andConstp, andConstp->width());
@ -2296,8 +2290,8 @@ private:
void swapSides(AstNodeBiCom* nodep) {
// COMMUTATIVE({a},CONST) -> COMMUTATIVE(CONST,{a})
// This simplifies later optimizations
AstNode* const lhsp = nodep->lhsp()->unlinkFrBackWithNext();
AstNode* const rhsp = nodep->rhsp()->unlinkFrBackWithNext();
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBackWithNext();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBackWithNext();
nodep->lhsp(rhsp);
nodep->rhsp(lhsp);
iterate(nodep); // Again?
@ -2333,8 +2327,8 @@ private:
const AstConcat* const bcConcp = VN_CAST(nodep->rhsp(), Concat);
if (!abConcp && !bcConcp) return 0;
if (bcConcp) {
AstNode* const ap = nodep->lhsp();
AstNode* const bp = bcConcp->lhsp();
AstNodeExpr* const ap = nodep->lhsp();
AstNodeExpr* const bp = bcConcp->lhsp();
// If a+b == 32,64,96 etc, then we want to have a+b together on LHS
if (VL_BITBIT_I(ap->width() + bp->width()) == 0) return 2; // Transform 2: to abConc
} else { // abConcp
@ -2352,11 +2346,11 @@ private:
// like that, so on 32 bit boundaries, we'll do the opposite form.
UINFO(4, "Move concat: " << nodep << endl);
if (operandConcatMove(nodep) > 1) {
AstNode* const ap = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const ap = nodep->lhsp()->unlinkFrBack();
AstConcat* const bcConcp = VN_AS(nodep->rhsp(), Concat);
bcConcp->unlinkFrBack();
AstNode* const bp = bcConcp->lhsp()->unlinkFrBack();
AstNode* const cp = bcConcp->rhsp()->unlinkFrBack();
AstNodeExpr* const bp = bcConcp->lhsp()->unlinkFrBack();
AstNodeExpr* const cp = bcConcp->rhsp()->unlinkFrBack();
AstConcat* const abConcp = new AstConcat(bcConcp->fileline(), ap, bp);
nodep->lhsp(abConcp);
nodep->rhsp(cp);
@ -2367,9 +2361,9 @@ private:
} else {
AstConcat* const abConcp = VN_AS(nodep->lhsp(), Concat);
abConcp->unlinkFrBack();
AstNode* const ap = abConcp->lhsp()->unlinkFrBack();
AstNode* const bp = abConcp->rhsp()->unlinkFrBack();
AstNode* const cp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const ap = abConcp->lhsp()->unlinkFrBack();
AstNodeExpr* const bp = abConcp->rhsp()->unlinkFrBack();
AstNodeExpr* const cp = nodep->rhsp()->unlinkFrBack();
AstConcat* const bcConcp = new AstConcat(abConcp->fileline(), bp, cp);
nodep->lhsp(ap);
nodep->rhsp(bcConcp);
@ -2393,8 +2387,8 @@ private:
void replaceLogEq(AstLogEq* nodep) {
// LOGEQ(a,b) => AstLogAnd{AstLogOr{AstLogNot{a},b},AstLogOr{AstLogNot{b},a}}
AstNode* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
// Do exactly as IEEE says, might result in extra terms, so in future may do differently
AstLogAnd* const newp = new AstLogAnd(
nodep->fileline(),
@ -2410,13 +2404,13 @@ private:
void replaceSelSel(AstSel* nodep) {
// SEL(SEL({x},a,b),c,d) => SEL({x},a+c,d)
AstSel* const belowp = VN_AS(nodep->fromp(), Sel);
AstNode* const fromp = belowp->fromp()->unlinkFrBack();
AstNode* const widthp = nodep->widthp()->unlinkFrBack();
AstNode* const lsb1p = nodep->lsbp()->unlinkFrBack();
AstNode* const lsb2p = belowp->lsbp()->unlinkFrBack();
AstNodeExpr* const fromp = belowp->fromp()->unlinkFrBack();
AstNodeExpr* const widthp = nodep->widthp()->unlinkFrBack();
AstNodeExpr* const lsb1p = nodep->lsbp()->unlinkFrBack();
AstNodeExpr* const lsb2p = belowp->lsbp()->unlinkFrBack();
// Eliminate lower range
UINFO(4, "Elim Lower range: " << nodep << endl);
AstNode* newlsbp;
AstNodeExpr* newlsbp;
if (VN_IS(lsb1p, Const) && VN_IS(lsb2p, Const)) {
newlsbp = new AstConst(lsb1p->fileline(),
VN_AS(lsb1p, Const)->toUInt() + VN_AS(lsb2p, Const)->toUInt());
@ -2427,13 +2421,13 @@ private:
// potentially smaller lsb1p's width, but don't insert a redundant AstExtend.
// Note that due to some sloppiness in earlier passes, lsb1p might actually be wider,
// so extend to the wider type.
AstNode* const widep = lsb1p->width() > lsb2p->width() ? lsb1p : lsb2p;
AstNode* const lhsp = widep->width() > lsb2p->width()
? new AstExtend{lsb2p->fileline(), lsb2p}
: lsb2p;
AstNode* const rhsp = widep->width() > lsb1p->width()
? new AstExtend{lsb1p->fileline(), lsb1p}
: lsb1p;
AstNodeExpr* const widep = lsb1p->width() > lsb2p->width() ? lsb1p : lsb2p;
AstNodeExpr* const lhsp = widep->width() > lsb2p->width()
? new AstExtend{lsb2p->fileline(), lsb2p}
: lsb2p;
AstNodeExpr* const rhsp = widep->width() > lsb1p->width()
? new AstExtend{lsb1p->fileline(), lsb1p}
: lsb1p;
lhsp->dtypeFrom(widep);
rhsp->dtypeFrom(widep);
newlsbp = new AstAdd{lsb1p->fileline(), lhsp, rhsp};
@ -2447,8 +2441,8 @@ private:
void replaceSelConcat(AstSel* nodep) {
// SEL(CONCAT(a,b),c,d) => SEL(a or b, . .)
AstConcat* const conp = VN_AS(nodep->fromp(), Concat);
AstNode* const conLhsp = conp->lhsp();
AstNode* const conRhsp = conp->rhsp();
AstNodeExpr* const conLhsp = conp->lhsp();
AstNodeExpr* const conRhsp = conp->rhsp();
if (static_cast<int>(nodep->lsbConst()) >= conRhsp->width()) {
conLhsp->unlinkFrBack();
AstSel* const newp
@ -2478,10 +2472,10 @@ private:
// SEL(REPLICATE(from,rep),lsb,width) => SEL(from,0,width) as long
// as SEL's width <= b's width
AstReplicate* const repp = VN_AS(nodep->fromp(), Replicate);
AstNode* const fromp = repp->lhsp();
AstNodeExpr* const fromp = repp->lhsp();
AstConst* const lsbp = VN_CAST(nodep->lsbp(), Const);
if (!lsbp) return false;
AstNode* const widthp = nodep->widthp();
AstNodeExpr* const widthp = nodep->widthp();
if (!VN_IS(widthp, Const)) return false;
UASSERT_OBJ(fromp->width(), nodep, "Not widthed");
if ((lsbp->toUInt() / fromp->width())
@ -2502,7 +2496,7 @@ private:
bool operandRepRep(AstReplicate* nodep) {
// REPLICATE(REPLICATE2(from2,cnt2),cnt1) => REPLICATE(from2,(cnt1+cnt2))
AstReplicate* const rep2p = VN_AS(nodep->lhsp(), Replicate);
AstNode* const from2p = rep2p->lhsp();
AstNodeExpr* const from2p = rep2p->lhsp();
AstConst* const cnt1p = VN_CAST(nodep->rhsp(), Const);
if (!cnt1p) return false;
AstConst* const cnt2p = VN_CAST(rep2p->rhsp(), Const);
@ -2523,9 +2517,9 @@ private:
// CONCAT(REP(fromp,cnt1),fromp) -> REPLICATE(fromp,cnt1+1)
// CONCAT(fromp,REP(fromp,cnt1)) -> REPLICATE(fromp,1+cnt1)
// CONCAT(REP(fromp,cnt1),REP(fromp,cnt2)) -> REPLICATE(fromp,cnt1+cnt2)
AstNode* from1p = nodep->lhsp();
AstNodeExpr* from1p = nodep->lhsp();
uint32_t cnt1 = 1;
AstNode* from2p = nodep->rhsp();
AstNodeExpr* from2p = nodep->rhsp();
uint32_t cnt2 = 1;
if (VN_IS(from1p, Replicate)) {
AstConst* const cnt1p = VN_CAST(VN_CAST(from1p, Replicate)->rhsp(), Const);
@ -2552,11 +2546,11 @@ private:
// SEL(BUFIF1(a,b),1,bit) => BUFIF1(SEL(a,1,bit),SEL(b,1,bit))
AstNodeBiop* const fromp = VN_AS(nodep->fromp()->unlinkFrBack(), NodeBiop);
UASSERT_OBJ(fromp, nodep, "Called on non biop");
AstNode* const lsbp = nodep->lsbp()->unlinkFrBack();
AstNode* const widthp = nodep->widthp()->unlinkFrBack();
AstNodeExpr* const lsbp = nodep->lsbp()->unlinkFrBack();
AstNodeExpr* const widthp = nodep->widthp()->unlinkFrBack();
//
AstNode* const bilhsp = fromp->lhsp()->unlinkFrBack();
AstNode* const birhsp = fromp->rhsp()->unlinkFrBack();
AstNodeExpr* const bilhsp = fromp->lhsp()->unlinkFrBack();
AstNodeExpr* const birhsp = fromp->rhsp()->unlinkFrBack();
//
fromp->lhsp(
new AstSel(nodep->fileline(), bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
@ -2569,10 +2563,10 @@ private:
// SEL(NOT(a),1,bit) => NOT(SEL(a,bit))
AstNodeUniop* const fromp = VN_AS(nodep->fromp()->unlinkFrBack(), NodeUniop);
UASSERT_OBJ(fromp, nodep, "Called on non biop");
AstNode* const lsbp = nodep->lsbp()->unlinkFrBack();
AstNode* const widthp = nodep->widthp()->unlinkFrBack();
AstNodeExpr* const lsbp = nodep->lsbp()->unlinkFrBack();
AstNodeExpr* const widthp = nodep->widthp()->unlinkFrBack();
//
AstNode* const bilhsp = fromp->lhsp()->unlinkFrBack();
AstNodeExpr* const bilhsp = fromp->lhsp()->unlinkFrBack();
//
fromp->lhsp(new AstSel(nodep->fileline(), bilhsp, lsbp, widthp));
fromp->dtypeFrom(nodep);
@ -2901,7 +2895,7 @@ private:
// ASSIGNW (VARREF, const) -> INITIAL ( ASSIGN (VARREF, const) )
UINFO(4, "constAssignW " << nodep << endl);
// Make a initial assignment
AstNode* const exprp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const exprp = nodep->rhsp()->unlinkFrBack();
varrefp->unlinkFrBack();
AstInitial* const newinitp = new AstInitial(
nodep->fileline(), new AstAssign(nodep->fileline(), varrefp, exprp));
@ -2957,7 +2951,7 @@ private:
}
} else if (!afterComment(nodep->thensp())) {
UINFO(4, "IF({x}) nullptr {...} => IF(NOT{x}}: " << nodep << endl);
AstNode* const condp = nodep->condp();
AstNodeExpr* const condp = nodep->condp();
AstNode* const elsesp = nodep->elsesp();
condp->unlinkFrBackWithNext();
elsesp->unlinkFrBackWithNext();
@ -2971,7 +2965,7 @@ private:
|| VN_IS(nodep->condp(), LogNot))
&& nodep->thensp() && nodep->elsesp()) {
UINFO(4, "IF(NOT {x}) => IF(x) swapped if/else" << nodep << endl);
AstNode* const condp
AstNodeExpr* const condp
= VN_AS(nodep->condp(), NodeUniop)->lhsp()->unlinkFrBackWithNext();
AstNode* const thensp = nodep->thensp()->unlinkFrBackWithNext();
AstNode* const elsesp = nodep->elsesp()->unlinkFrBackWithNext();
@ -2986,9 +2980,9 @@ private:
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 = thensp->rhsp()->unlinkFrBack();
AstNode* const falsep = elsesp->rhsp()->unlinkFrBack();
AstNodeExpr* const condp = nodep->condp()->unlinkFrBack();
AstNodeExpr* const truep = thensp->rhsp()->unlinkFrBack();
AstNodeExpr* const falsep = elsesp->rhsp()->unlinkFrBack();
thensp->rhsp(new AstCond(truep->fileline(), condp, truep, falsep));
nodep->replaceWith(thensp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
@ -2997,9 +2991,9 @@ private:
&& operandIfIf(nodep)) {
UINFO(9, "IF({a}) IF({b}) => IF({a} && {b})" << endl);
AstNodeIf* const lowerIfp = VN_AS(nodep->thensp(), NodeIf);
AstNode* const condp = nodep->condp()->unlinkFrBack();
AstNodeExpr* const condp = nodep->condp()->unlinkFrBack();
AstNode* const lowerThensp = lowerIfp->thensp()->unlinkFrBackWithNext();
AstNode* const lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext();
AstNodeExpr* const lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext();
nodep->condp(new AstLogAnd(lowerIfp->fileline(), condp, lowerCondp));
lowerIfp->replaceWith(lowerThensp);
VL_DO_DANGLING(lowerIfp->deleteTree(), lowerIfp);
@ -3355,7 +3349,7 @@ private:
// 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, $thenp, $elsep}", "AstCond{$condp->op1p(), $elsep, $thenp}");
TREEOP ("AstCond{$condp.castNot, $thenp, $elsep}", "AstCond{$condp->castNot()->lhsp(), $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
@ -3386,36 +3380,36 @@ private:
TREEOP1("AstLt {$lhsp.isAllOnes, $rhsp, $lhsp->width()==$rhsp->width()}", "replaceNumLimited(nodep,0)");
TREEOP1("AstGte {$lhsp.isAllOnes, $rhsp, $lhsp->width()==$rhsp->width()}", "replaceNumLimited(nodep,1)");
// Two level bubble pushing
TREEOP ("AstNot {$lhsp.castNot, $lhsp->width()==VN_AS($lhsp,,Not)->lhsp()->width()}", "replaceWChild(nodep, $lhsp->op1p())"); // NOT(NOT(x))->x
TREEOP ("AstLogNot{$lhsp.castLogNot}", "replaceWChild(nodep, $lhsp->op1p())"); // LOGNOT(LOGNOT(x))->x
TREEOPV("AstNot {$lhsp.castEqCase, $lhsp.width1}","AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castNeqCase}", "AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castEqWild, $lhsp.width1}","AstNeqWild{$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castEqWild}", "AstNeqWild{$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castNeqWild, $lhsp.width1}","AstEqWild {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castNeqWild}", "AstEqWild {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castEq, $lhsp.width1}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castEq}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castNeq, $lhsp.width1}", "AstEq {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castNeq}", "AstEq {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castLt, $lhsp.width1}", "AstGte {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castLt}", "AstGte {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castLtS, $lhsp.width1}", "AstGteS{$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castLtS}", "AstGteS{$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castLte, $lhsp.width1}", "AstGt {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castLte}", "AstGt {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castLteS, $lhsp.width1}", "AstGtS {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castLteS}", "AstGtS {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castGt, $lhsp.width1}", "AstLte {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castGt}", "AstLte {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castGtS, $lhsp.width1}", "AstLteS{$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castGtS}", "AstLteS{$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castGte, $lhsp.width1}", "AstLt {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castGte}", "AstLt {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castGteS, $lhsp.width1}", "AstLtS {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castGteS}", "AstLtS {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstNot {$lhsp.castNot, $lhsp->width()==VN_AS($lhsp,,Not)->lhsp()->width()}", "replaceWChild(nodep, $lhsp->castNot()->lhsp())"); // NOT(NOT(x))->x
TREEOP ("AstLogNot{$lhsp.castLogNot}", "replaceWChild(nodep, $lhsp->castLogNot()->lhsp())"); // LOGNOT(LOGNOT(x))->x
TREEOPV("AstNot {$lhsp.castEqCase, $lhsp.width1}","AstNeqCase{$lhsp->castEqCase()->lhsp(),$lhsp->castEqCase()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->castEqCase()->lhsp(),$lhsp->castEqCase()->rhsp()}");
TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase{$lhsp->castNeqCase()->lhsp(),$lhsp->castNeqCase()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castNeqCase}", "AstEqCase {$lhsp->castNeqCase()->lhsp(),$lhsp->castNeqCase()->rhsp()}");
TREEOPV("AstNot {$lhsp.castEqWild, $lhsp.width1}","AstNeqWild{$lhsp->castEqWild()->lhsp(),$lhsp->castEqWild()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castEqWild}", "AstNeqWild{$lhsp->castEqWild()->lhsp(),$lhsp->castEqWild()->rhsp()}");
TREEOPV("AstNot {$lhsp.castNeqWild, $lhsp.width1}","AstEqWild{$lhsp->castNeqWild()->lhsp(),$lhsp->castNeqWild()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castNeqWild}", "AstEqWild {$lhsp->castNeqWild()->lhsp(),$lhsp->castNeqWild()->rhsp()}");
TREEOPV("AstNot {$lhsp.castEq, $lhsp.width1}", "AstNeq {$lhsp->castEq()->lhsp(),$lhsp->castEq()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castEq}", "AstNeq {$lhsp->castEq()->lhsp(),$lhsp->castEq()->rhsp()}");
TREEOPV("AstNot {$lhsp.castNeq, $lhsp.width1}", "AstEq {$lhsp->castNeq()->lhsp(),$lhsp->castNeq()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castNeq}", "AstEq {$lhsp->castNeq()->lhsp(),$lhsp->castNeq()->rhsp()}");
TREEOPV("AstNot {$lhsp.castLt, $lhsp.width1}", "AstGte {$lhsp->castLt()->lhsp(),$lhsp->castLt()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castLt}", "AstGte {$lhsp->castLt()->lhsp(),$lhsp->castLt()->rhsp()}");
TREEOPV("AstNot {$lhsp.castLtS, $lhsp.width1}", "AstGteS{$lhsp->castLtS()->lhsp(),$lhsp->castLtS()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castLtS}", "AstGteS{$lhsp->castLtS()->lhsp(),$lhsp->castLtS()->rhsp()}");
TREEOPV("AstNot {$lhsp.castLte, $lhsp.width1}", "AstGt {$lhsp->castLte()->lhsp(),$lhsp->castLte()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castLte}", "AstGt {$lhsp->castLte()->lhsp(),$lhsp->castLte()->rhsp()}");
TREEOPV("AstNot {$lhsp.castLteS, $lhsp.width1}", "AstGtS {$lhsp->castLteS()->lhsp(),$lhsp->castLteS()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castLteS}", "AstGtS {$lhsp->castLteS()->lhsp(),$lhsp->castLteS()->rhsp()}");
TREEOPV("AstNot {$lhsp.castGt, $lhsp.width1}", "AstLte {$lhsp->castGt()->lhsp(),$lhsp->castGt()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castGt}", "AstLte {$lhsp->castGt()->lhsp(),$lhsp->castGt()->rhsp()}");
TREEOPV("AstNot {$lhsp.castGtS, $lhsp.width1}", "AstLteS{$lhsp->castGtS()->lhsp(),$lhsp->castGtS()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castGtS}", "AstLteS{$lhsp->castGtS()->lhsp(),$lhsp->castGtS()->rhsp()}");
TREEOPV("AstNot {$lhsp.castGte, $lhsp.width1}", "AstLt {$lhsp->castGte()->lhsp(),$lhsp->castGte()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castGte}", "AstLt {$lhsp->castGte()->lhsp(),$lhsp->castGte()->rhsp()}");
TREEOPV("AstNot {$lhsp.castGteS, $lhsp.width1}", "AstLtS {$lhsp->castGteS()->lhsp(),$lhsp->castGteS()->rhsp()}");
TREEOP ("AstLogNot{$lhsp.castGteS}", "AstLtS {$lhsp->castGteS()->lhsp(),$lhsp->castGteS()->rhsp()}");
// Not common, but avoids compiler warnings about over shifting
TREEOP ("AstShiftL{operandHugeShiftL(nodep)}", "replaceZero(nodep)");
TREEOP ("AstShiftR{operandHugeShiftR(nodep)}", "replaceZero(nodep)");

View File

@ -20,14 +20,16 @@
#include "config_build.h"
#include "verilatedos.h"
class AstNetlist;
class AstNode;
#include "V3Ast.h"
//============================================================================
class V3Const final {
public:
static AstNode* constifyParamsEdit(AstNode* nodep);
static AstNodeExpr* constifyParamsEdit(AstNodeExpr* exprp) {
return VN_AS(constifyParamsEdit(static_cast<AstNode*>(exprp)), NodeExpr);
}
static AstNode* constifyGenerateParamsEdit(AstNode* nodep);
// Only do constant pushing, without removing dead logic
static void constifyAllLive(AstNetlist* nodep);
@ -40,9 +42,15 @@ public:
// Only the current node and lower
// Return new node that may have replaced nodep
static AstNode* constifyEditCpp(AstNode* nodep);
static AstNodeExpr* constifyEditCpp(AstNodeExpr* exprp) {
return VN_AS(constifyEditCpp(static_cast<AstNode*>(exprp)), NodeExpr);
}
// Only the current node and lower
// Return new node that may have replaced nodep
static AstNode* constifyEdit(AstNode* nodep);
static AstNodeExpr* constifyEdit(AstNodeExpr* exprp) {
return VN_AS(constifyEdit(static_cast<AstNode*>(exprp)), NodeExpr);
}
// Only the current node and lower, with special SenTree optimization
// Return new node that may have replaced nodep
static AstNode* constifyExpensiveEdit(AstNode* nodep);

View File

@ -47,9 +47,9 @@ private:
struct ToggleEnt {
const string m_comment; // Comment for coverage dump
AstNode* m_varRefp; // How to get to this element
AstNode* m_chgRefp; // How to get to this element
ToggleEnt(const string& comment, AstNode* vp, AstNode* cp)
AstNodeExpr* m_varRefp; // How to get to this element
AstNodeExpr* m_chgRefp; // How to get to this element
ToggleEnt(const string& comment, AstNodeExpr* vp, AstNodeExpr* cp)
: m_comment{comment}
, m_varRefp{vp}
, m_chgRefp{cp} {}

View File

@ -215,12 +215,12 @@ private:
}
}
AstNode* createDlyOnSet(AstAssignDly* nodep, AstNode* lhsp) {
AstNodeExpr* createDlyOnSet(AstAssignDly* nodep, AstNodeExpr* lhsp) {
// Create delayed assignment
// See top of this file for transformation
// Return the new LHS for the assignment, Null = unlink
// Find selects
AstNode* newlhsp = nullptr; // nullptr = unlink old assign
AstNodeExpr* newlhsp = nullptr; // nullptr = unlink old assign
const AstSel* bitselp = nullptr;
AstArraySel* arrayselp = nullptr;
AstVarRef* varrefp = nullptr;
@ -242,10 +242,10 @@ private:
UINFO(4, "AssignDlyOnSet: " << nodep << endl);
}
//=== Dimensions: __Vdlyvdim__
std::deque<AstNode*> dimvalp; // Assignment value for each dimension of assignment
std::deque<AstNodeExpr*> dimvalp; // Assignment value for each dimension of assignment
AstNode* dimselp = arrayselp;
for (; VN_IS(dimselp, ArraySel); dimselp = VN_AS(dimselp, ArraySel)->fromp()) {
AstNode* const valp = VN_AS(dimselp, ArraySel)->bitp()->unlinkFrBack();
AstNodeExpr* const valp = VN_AS(dimselp, ArraySel)->bitp()->unlinkFrBack();
dimvalp.push_front(valp);
}
if (dimselp) varrefp = VN_AS(dimselp, VarRef);
@ -255,9 +255,9 @@ private:
const AstVar* const oldvarp = varrefp->varp();
const int modVecNum = m_scopeVecMap[varrefp->varScopep()]++;
//
std::deque<AstNode*> dimreadps; // Read value for each dimension of assignment
std::deque<AstNodeExpr*> dimreadps; // Read value for each dimension of assignment
for (unsigned dimension = 0; dimension < dimvalp.size(); dimension++) {
AstNode* const dimp = dimvalp[dimension];
AstNodeExpr* const dimp = dimvalp[dimension];
if (VN_IS(dimp, Const)) { // bit = const, can just use it
dimreadps.push_front(dimp);
} else {
@ -274,9 +274,9 @@ private:
}
//
//=== Bitselect: __Vdlyvlsb__
AstNode* bitreadp = nullptr; // Code to read Vdlyvlsb
AstNodeExpr* bitreadp = nullptr; // Code to read Vdlyvlsb
if (bitselp) {
AstNode* const lsbvaluep = bitselp->lsbp()->unlinkFrBack();
AstNodeExpr* const lsbvaluep = bitselp->lsbp()->unlinkFrBack();
if (VN_IS(bitselp->fromp(), Const)) {
// vlsb = constant, can just push constant into where we use it
bitreadp = lsbvaluep;
@ -294,7 +294,7 @@ private:
}
//
//=== Value: __Vdlyvval__
AstNode* valreadp; // Code to read Vdlyvval
AstNodeExpr* valreadp; // Code to read Vdlyvval
if (VN_IS(nodep->rhsp(), Const)) {
// vval = constant, can just push constant into where we use it
valreadp = nodep->rhsp()->unlinkFrBack();
@ -342,7 +342,7 @@ private:
// This ensures that multiple assignments to the same memory will result
// in correctly ordered code - the last assignment must be last.
// It also has the nice side effect of assisting cache locality.
AstNode* selectsp = varrefp;
AstNodeExpr* selectsp = varrefp;
for (int dimension = int(dimreadps.size()) - 1; dimension >= 0; --dimension) {
selectsp = new AstArraySel(nodep->fileline(), selectsp, dimreadps[dimension]);
}
@ -519,8 +519,8 @@ private:
|| (VN_IS(nodep->lhsp(), Sel)
&& VN_IS(VN_AS(nodep->lhsp(), Sel)->fromp(), ArraySel));
if (m_procp->isSuspendable() || isArray) {
AstNode* const lhsp = nodep->lhsp();
AstNode* const newlhsp = createDlyOnSet(nodep, lhsp);
AstNodeExpr* const lhsp = nodep->lhsp();
AstNodeExpr* const newlhsp = createDlyOnSet(nodep, lhsp);
if (m_inLoop && isArray) {
nodep->v3warn(BLKLOOPINIT, "Unsupported: Delayed assignment to array inside for "
"loops (non-delayed is ok - see docs)");

View File

@ -52,7 +52,7 @@ private:
// METHODS
void createDeepTemp(AstNode* nodep) {
void createDeepTemp(AstNodeExpr* nodep) {
UINFO(6, " Deep " << nodep << endl);
// if (debug() >= 9) nodep->dumpTree(cout, "deep:");
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::STMTTEMP,

View File

@ -299,7 +299,7 @@ class DfgToAstVisitor final : DfgVisitor {
});
}
void addResultEquation(FileLine* flp, AstNode* lhsp, AstNode* rhsp) {
void addResultEquation(FileLine* flp, AstNodeExpr* lhsp, AstNodeExpr* rhsp) {
m_modp->addStmtsp(new AstAssignW{flp, lhsp, rhsp});
++m_ctx.m_resultEquations;
}

View File

@ -92,17 +92,19 @@ private:
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
static AstNode* newWordAssign(AstNodeAssign* placep, int word, AstNode* lhsp, AstNode* rhsp) {
static AstNode* newWordAssign(AstNodeAssign* placep, int word, AstNodeExpr* lhsp,
AstNodeExpr* rhsp) {
FileLine* const fl = placep->fileline();
return new AstAssign{fl,
new AstWordSel{fl, lhsp->cloneTree(true),
new AstConst{fl, static_cast<uint32_t>(word)}},
rhsp};
}
static void addWordAssign(AstNodeAssign* placep, int word, AstNode* lhsp, AstNode* rhsp) {
static void addWordAssign(AstNodeAssign* placep, int word, AstNodeExpr* lhsp,
AstNodeExpr* rhsp) {
insertBefore(placep, newWordAssign(placep, word, lhsp, rhsp));
}
static void addWordAssign(AstNodeAssign* placep, int word, AstNode* rhsp) {
static void addWordAssign(AstNodeAssign* placep, int word, AstNodeExpr* rhsp) {
addWordAssign(placep, word, placep->lhsp(), rhsp);
}
@ -117,7 +119,7 @@ private:
if (nodep->op4p()) fixCloneLvalue(nodep->op4p());
}
static AstNode* newAstWordSelClone(AstNode* nodep, int word) {
static AstNodeExpr* newAstWordSelClone(AstNodeExpr* nodep, int word) {
// Get the specified word number from a wide array
// Or, if it's a long/quad, do appropriate conversion to wide
// Concat may pass negative word numbers, that means it wants a zero
@ -126,11 +128,11 @@ private:
return new AstWordSel{fl, nodep->cloneTree(true),
new AstConst{fl, static_cast<uint32_t>(word)}};
} else if (nodep->isQuad() && word == 0) {
AstNode* const quadfromp = nodep->cloneTree(true);
AstNodeExpr* const quadfromp = nodep->cloneTree(true);
quadfromp->dtypeSetBitUnsized(VL_QUADSIZE, quadfromp->widthMin(), VSigning::UNSIGNED);
return new AstCCast{fl, quadfromp, VL_EDATASIZE};
} else if (nodep->isQuad() && word == 1) {
AstNode* const quadfromp = nodep->cloneTree(true);
AstNodeExpr* const quadfromp = nodep->cloneTree(true);
quadfromp->dtypeSetBitUnsized(VL_QUADSIZE, quadfromp->widthMin(), VSigning::UNSIGNED);
return new AstCCast{
fl, new AstShiftR{fl, quadfromp, new AstConst{fl, VL_EDATASIZE}, VL_EDATASIZE},
@ -142,16 +144,16 @@ private:
}
}
static AstNode* newWordGrabShift(FileLine* fl, int word, AstNode* lhsp, int shift) {
static AstNodeExpr* newWordGrabShift(FileLine* fl, int word, AstNodeExpr* lhsp, int shift) {
// Extract the expression to grab the value for the specified word, if it's the shift
// of shift bits from lhsp
AstNode* newp;
AstNodeExpr* newp;
// Negative word numbers requested for lhs when it's "before" what we want.
// We get a 0 then.
const int othword = word - shift / VL_EDATASIZE;
AstNode* const llowp = newAstWordSelClone(lhsp, othword);
AstNodeExpr* const llowp = newAstWordSelClone(lhsp, othword);
if (const int loffset = VL_BITBIT_E(shift)) {
AstNode* const lhip = newAstWordSelClone(lhsp, othword - 1);
AstNodeExpr* const lhip = newAstWordSelClone(lhsp, othword - 1);
const int nbitsonright = VL_EDATASIZE - loffset; // bits that end up in lword
newp = new AstOr{
fl,
@ -170,8 +172,8 @@ private:
return newp;
}
static AstNode* newWordSel(FileLine* fl, AstNode* fromp, AstNode* lsbp,
uint32_t wordOffset = 0) {
static AstNodeExpr* newWordSel(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* lsbp,
uint32_t wordOffset = 0) {
// Return equation to get the VL_BITWORD of a constant or non-constant
UASSERT_OBJ(fromp->isWide(), fromp, "Only need AstWordSel on wide from's");
if (wordOffset >= static_cast<uint32_t>(fromp->widthWords())) {
@ -181,7 +183,7 @@ private:
// AstCondBound is protecting above this node.
return new AstConst{fl, AstConst::SizedEData(), 0};
} else {
AstNode* wordp;
AstNodeExpr* wordp;
FileLine* const lfl = lsbp->fileline();
if (VN_IS(lsbp, Const)) {
wordp = new AstConst{lfl, wordOffset + VL_BITWORD_E(VN_AS(lsbp, Const)->toUInt())};
@ -197,7 +199,7 @@ private:
}
}
static AstNode* dropCondBound(AstNode* nodep) {
static AstNodeExpr* dropCondBound(AstNodeExpr* nodep) {
// Experimental only...
// If there's a CONDBOUND safety to keep arrays in bounds,
// we're going to AND it to a value that always fits inside a
@ -208,7 +210,7 @@ private:
return nodep;
}
static AstNode* newSelBitBit(AstNode* lsbp) {
static AstNodeExpr* newSelBitBit(AstNodeExpr* lsbp) {
// Return equation to get the VL_BITBIT of a constant or non-constant
FileLine* const fl = lsbp->fileline();
if (VN_IS(lsbp, Const)) {
@ -320,8 +322,8 @@ private:
if (nodep->isWide()) {
// See under ASSIGN(EXTEND)
} else {
AstNode* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* newp = lhsp;
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* newp = lhsp;
if (nodep->isQuad()) {
if (lhsp->isQuad()) {
lhsp->dtypeFrom(nodep); // Just mark it, else nop
@ -359,28 +361,29 @@ private:
FileLine* const nfl = nodep->fileline();
FileLine* const lfl = nodep->lsbp()->fileline();
FileLine* const ffl = nodep->fromp()->fileline();
AstNode* lowwordp = newWordSel(ffl, nodep->fromp()->cloneTree(true), nodep->lsbp());
AstNodeExpr* lowwordp
= newWordSel(ffl, nodep->fromp()->cloneTree(true), nodep->lsbp());
if (nodep->isQuad() && !lowwordp->isQuad()) {
lowwordp = new AstCCast{nfl, lowwordp, nodep};
}
AstNode* const lowp
AstNodeExpr* const lowp
= new AstShiftR{nfl, lowwordp, newSelBitBit(nodep->lsbp()), nodep->width()};
// If > 1 bit, we might be crossing the word boundary
AstNode* midp = nullptr;
AstNodeExpr* midp = nullptr;
if (nodep->widthConst() > 1) {
const uint32_t midMsbOffset
= std::min<uint32_t>(nodep->widthConst(), VL_EDATASIZE) - 1;
AstNode* const midMsbp = new AstAdd{lfl, new AstConst{lfl, midMsbOffset},
nodep->lsbp()->cloneTree(false)};
AstNode* midwordp = // SEL(from,[midwordnum])
AstNodeExpr* const midMsbp = new AstAdd{lfl, new AstConst{lfl, midMsbOffset},
nodep->lsbp()->cloneTree(false)};
AstNodeExpr* midwordp = // SEL(from,[midwordnum])
newWordSel(ffl, nodep->fromp()->cloneTree(true), midMsbp, 0);
// newWordSel clones the index, so delete it
VL_DO_DANGLING(midMsbp->deleteTree(), midMsbp);
if (nodep->isQuad() && !midwordp->isQuad()) {
midwordp = new AstCCast{nfl, midwordp, nodep};
}
AstNode* const midshiftp = new AstSub{lfl, new AstConst{lfl, VL_EDATASIZE},
newSelBitBit(nodep->lsbp())};
AstNodeExpr* const midshiftp = new AstSub{lfl, new AstConst{lfl, VL_EDATASIZE},
newSelBitBit(nodep->lsbp())};
// If we're selecting bit zero, then all 32 bits in the mid word
// get shifted << by 32 bits, so ignore them.
const V3Number zero{nodep, longOrQuadWidth(nodep)};
@ -395,19 +398,19 @@ private:
new AstShiftL{nfl, midwordp, midshiftp, nodep->width()}};
}
// If > 32 bits, we might be crossing the second word boundary
AstNode* hip = nullptr;
AstNodeExpr* hip = nullptr;
if (nodep->widthConst() > VL_EDATASIZE) {
const uint32_t hiMsbOffset = nodep->widthConst() - 1;
AstNode* const hiMsbp = new AstAdd{lfl, new AstConst{lfl, hiMsbOffset},
nodep->lsbp()->cloneTree(false)};
AstNode* hiwordp = // SEL(from,[hiwordnum])
AstNodeExpr* const hiMsbp = new AstAdd{lfl, new AstConst{lfl, hiMsbOffset},
nodep->lsbp()->cloneTree(false)};
AstNodeExpr* hiwordp = // SEL(from,[hiwordnum])
newWordSel(ffl, nodep->fromp()->cloneTree(true), hiMsbp);
// newWordSel clones the index, so delete it
VL_DO_DANGLING(hiMsbp->deleteTree(), hiMsbp);
if (nodep->isQuad() && !hiwordp->isQuad()) {
hiwordp = new AstCCast{nfl, hiwordp, nodep};
}
AstNode* const hishiftp = new AstCond{
AstNodeExpr* const hishiftp = new AstCond{
nfl,
// lsb % VL_EDATASIZE == 0 ?
new AstEq{nfl, new AstConst{nfl, 0}, newSelBitBit(nodep->lsbp())},
@ -418,7 +421,7 @@ private:
hip = new AstShiftL{nfl, hiwordp, hishiftp, nodep->width()};
}
AstNode* newp = lowp;
AstNodeExpr* newp = lowp;
if (midp) newp = new AstOr{nfl, midp, newp};
if (hip) newp = new AstOr{nfl, hip, newp};
newp->dtypeFrom(nodep);
@ -426,11 +429,11 @@ private:
} else { // Long/Quad from Long/Quad
UINFO(8, " SEL->SHIFT " << nodep << endl);
FileLine* const fl = nodep->fileline();
AstNode* fromp = nodep->fromp()->unlinkFrBack();
AstNode* const lsbp = nodep->lsbp()->unlinkFrBack();
AstNodeExpr* fromp = nodep->fromp()->unlinkFrBack();
AstNodeExpr* const lsbp = nodep->lsbp()->unlinkFrBack();
if (nodep->isQuad() && !fromp->isQuad()) { fromp = new AstCCast{fl, fromp, nodep}; }
// {large}>>32 requires 64-bit shift operation; then cast
AstNode* newp = new AstShiftR{fl, fromp, dropCondBound(lsbp), fromp->width()};
AstNodeExpr* newp = new AstShiftR{fl, fromp, dropCondBound(lsbp), fromp->width()};
newp->dtypeFrom(fromp);
if (!nodep->isQuad() && fromp->isQuad()) { newp = new AstCCast{fl, newp, nodep}; }
newp->dtypeFrom(nodep);
@ -456,21 +459,21 @@ private:
FileLine* const lfl = rhsp->lsbp()->fileline();
for (int w = 0; w < nodep->widthWords(); ++w) {
// Grab lowest bits
AstNode* const lowwordp
AstNodeExpr* const lowwordp
= newWordSel(rfl, rhsp->fromp()->cloneTree(true), rhsp->lsbp(), w);
AstNode* const lowp
AstNodeExpr* const lowp
= new AstShiftR{rfl, lowwordp, newSelBitBit(rhsp->lsbp()), VL_EDATASIZE};
// Upper bits
const V3Number zero{nodep, VL_EDATASIZE, 0};
AstNode* const midwordp = // SEL(from,[1+wordnum])
AstNodeExpr* const midwordp = // SEL(from,[1+wordnum])
newWordSel(ffl, rhsp->fromp()->cloneTree(true), rhsp->lsbp(), w + 1);
AstNode* const midshiftp
AstNodeExpr* const midshiftp
= new AstSub{lfl, new AstConst{lfl, VL_EDATASIZE}, newSelBitBit(rhsp->lsbp())};
AstNode* const midmayp = new AstShiftL{rfl, midwordp, midshiftp, VL_EDATASIZE};
AstNode* const midp = new AstCond{
AstNodeExpr* const midmayp = new AstShiftL{rfl, midwordp, midshiftp, VL_EDATASIZE};
AstNodeExpr* const midp = new AstCond{
rfl, new AstEq{rfl, new AstConst{rfl, 0}, newSelBitBit(rhsp->lsbp())},
new AstConst{rfl, zero}, midmayp};
AstNode* const newp = new AstOr{nfl, midp, lowp};
AstNodeExpr* const newp = new AstOr{nfl, midp, lowp};
addWordAssign(nodep, w, newp);
}
return true;
@ -491,8 +494,8 @@ private:
if (VN_IS(lhsp->lsbp(), Const)) {
// The code should work without this constant test, but it won't
// constify as nicely as we'd like.
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* const destp = lhsp->fromp()->unlinkFrBack();
AstNodeExpr* rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const destp = lhsp->fromp()->unlinkFrBack();
const int lsb = lhsp->lsbConst();
const int msb = lhsp->msbConst();
V3Number maskset{nodep, destp->widthMin()};
@ -504,7 +507,7 @@ private:
for (int w = 0; w < destp->widthWords(); ++w) {
if (w >= VL_BITWORD_E(lsb) && w <= VL_BITWORD_E(msb)) {
// else we would just be setting it to the same exact value
AstNode* oldvalp = newAstWordSelClone(destp, w);
AstNodeExpr* oldvalp = newAstWordSelClone(destp, w);
fixCloneLvalue(oldvalp);
if (!ones) {
oldvalp = new AstAnd{
@ -514,7 +517,7 @@ private:
}
// Appropriate word of new value to insert:
AstNode* newp = newWordGrabShift(lfl, w, rhsp, lsb);
AstNodeExpr* newp = newWordGrabShift(lfl, w, rhsp, lsb);
// Apply cleaning at the top word of the destination
// (no cleaning to do if dst's width is a whole number
@ -524,7 +527,7 @@ private:
cleanmask.setMask(VL_BITBIT_E(destp->widthMin()));
newp = new AstAnd{lfl, newp, new AstConst{lfl, cleanmask}};
}
AstNode* const orp
AstNodeExpr* const orp
= V3Const::constifyEditCpp(new AstOr{lfl, oldvalp, newp});
addWordAssign(nodep, w, destp, orp);
}
@ -534,7 +537,7 @@ private:
} else {
UINFO(8, " ASSIGNSEL(const,narrow) " << nodep << endl);
if (destp->isQuad() && !rhsp->isQuad()) { rhsp = new AstCCast{nfl, rhsp, nodep}; }
AstNode* oldvalp = destp->cloneTree(true);
AstNodeExpr* oldvalp = destp->cloneTree(true);
fixCloneLvalue(oldvalp);
if (!ones) { oldvalp = new AstAnd{lfl, new AstConst{lfl, maskold}, oldvalp}; }
@ -543,20 +546,21 @@ private:
// valid range of nodep which we apply to the new shifted RHS.
V3Number cleanmask{nodep, destp->widthMin()};
cleanmask.setMask(destp->widthMin());
AstNode* const shifted = new AstShiftL{
AstNodeExpr* const shifted = new AstShiftL{
lfl, rhsp, new AstConst{lfl, static_cast<uint32_t>(lsb)}, destp->width()};
AstNode* const cleaned = new AstAnd{lfl, shifted, new AstConst{lfl, cleanmask}};
AstNode* const orp = V3Const::constifyEditCpp(new AstOr{lfl, oldvalp, cleaned});
AstNode* newp = new AstAssign{nfl, destp, orp};
insertBefore(nodep, newp);
AstNodeExpr* const cleaned
= new AstAnd{lfl, shifted, new AstConst{lfl, cleanmask}};
AstNodeExpr* const orp
= V3Const::constifyEditCpp(new AstOr{lfl, oldvalp, cleaned});
insertBefore(nodep, new AstAssign{nfl, destp, orp});
}
return true;
} else { // non-const select offset
if (destwide && lhsp->widthConst() == 1) {
UINFO(8, " ASSIGNSEL(varlsb,wide,1bit) " << nodep << endl);
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* const destp = lhsp->fromp()->unlinkFrBack();
AstNode* oldvalp = newWordSel(lfl, destp->cloneTree(true), lhsp->lsbp());
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const destp = lhsp->fromp()->unlinkFrBack();
AstNodeExpr* oldvalp = newWordSel(lfl, destp->cloneTree(true), lhsp->lsbp());
fixCloneLvalue(oldvalp);
if (!ones) {
oldvalp = new AstAnd{
@ -570,8 +574,8 @@ private:
oldvalp};
}
// Restrict the shift amount to 0-31, see bug804.
AstNode* const shiftp = new AstAnd{nfl, lhsp->lsbp()->cloneTree(true),
new AstConst{nfl, VL_EDATASIZE - 1}};
AstNodeExpr* const shiftp = new AstAnd{nfl, lhsp->lsbp()->cloneTree(true),
new AstConst{nfl, VL_EDATASIZE - 1}};
AstNode* const newp = new AstAssign{
nfl, newWordSel(nfl, destp, lhsp->lsbp()),
new AstOr{lfl, oldvalp, new AstShiftL{lfl, rhsp, shiftp, VL_EDATASIZE}}};
@ -592,9 +596,9 @@ private:
} else {
UINFO(8, " ASSIGNSEL(varlsb,narrow) " << nodep << endl);
// nodep->dumpTree(cout, "- old: ");
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* const destp = lhsp->fromp()->unlinkFrBack();
AstNode* oldvalp = destp->cloneTree(true);
AstNodeExpr* rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const destp = lhsp->fromp()->unlinkFrBack();
AstNodeExpr* oldvalp = destp->cloneTree(true);
fixCloneLvalue(oldvalp);
V3Number maskwidth{nodep, destp->widthMin()};
@ -609,7 +613,7 @@ private:
lhsp->lsbp()->cloneTree(true), destp->width()}},
oldvalp};
}
AstNode* newp
AstNodeExpr* newp
= new AstShiftL{lfl, rhsp, lhsp->lsbp()->cloneTree(true), destp->width()};
// Apply cleaning to the new value being inserted. Mask is
// slightly wider than necessary to avoid an AND with all ones
@ -621,9 +625,7 @@ private:
newp = new AstAnd{lfl, newp, new AstConst{lfl, cleanmask}};
}
newp = new AstAssign{nfl, destp, new AstOr{lfl, oldvalp, newp}};
// newp->dumpTree(cout, "- new: ");
insertBefore(nodep, newp);
insertBefore(nodep, new AstAssign{nfl, destp, new AstOr{lfl, oldvalp, newp}});
return true;
}
}
@ -637,12 +639,12 @@ private:
} else {
UINFO(8, " CONCAT " << nodep << endl);
FileLine* const fl = nodep->fileline();
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* rhsp = nodep->rhsp()->unlinkFrBack();
const uint32_t rhsshift = rhsp->widthMin();
if (nodep->isQuad() && !lhsp->isQuad()) { lhsp = new AstCCast{fl, lhsp, nodep}; }
if (nodep->isQuad() && !rhsp->isQuad()) { rhsp = new AstCCast{fl, rhsp, nodep}; }
AstNode* const newp = new AstOr{
AstNodeExpr* const newp = new AstOr{
fl, new AstShiftL{fl, lhsp, new AstConst{fl, rhsshift}, nodep->width()}, rhsp};
newp->dtypeFrom(nodep); // Unsigned
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
@ -673,8 +675,8 @@ private:
// See under ASSIGN(WIDE)
} else {
FileLine* const fl = nodep->fileline();
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* newp;
AstNodeExpr* lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* newp;
const int lhswidth = lhsp->widthMin();
if (lhswidth == 1) {
UINFO(8, " REPLICATE(w1) " << nodep << endl);
@ -707,13 +709,13 @@ private:
UINFO(8, " Wordize ASSIGN(REPLICATE) " << nodep << endl);
if (!doExpand(rhsp)) return false;
FileLine* const fl = nodep->fileline();
AstNode* const lhsp = rhsp->lhsp();
AstNodeExpr* const lhsp = rhsp->lhsp();
const int lhswidth = lhsp->widthMin();
const AstConst* const constp = VN_AS(rhsp->rhsp(), Const);
UASSERT_OBJ(constp, rhsp, "Replication value isn't a constant. Checked earlier!");
const uint32_t times = constp->toUInt();
for (int w = 0; w < rhsp->widthWords(); ++w) {
AstNode* newp;
AstNodeExpr* newp;
if (lhswidth == 1) {
newp = new AstNegate{fl, lhsp->cloneTree(true)};
// Replicate always unsigned
@ -737,10 +739,10 @@ private:
UINFO(8, " Wordize EQ/NEQ " << nodep << endl);
// -> (0=={or{for each_word{WORDSEL(lhs,#)^WORDSEL(rhs,#)}}}
FileLine* const fl = nodep->fileline();
AstNode* newp = nullptr;
AstNodeExpr* newp = nullptr;
for (int w = 0; w < nodep->lhsp()->widthWords(); ++w) {
AstNode* const eqp = new AstXor{fl, newAstWordSelClone(nodep->lhsp(), w),
newAstWordSelClone(nodep->rhsp(), w)};
AstNodeExpr* const eqp = new AstXor{fl, newAstWordSelClone(nodep->lhsp(), w),
newAstWordSelClone(nodep->rhsp(), w)};
newp = newp ? new AstOr{fl, newp, eqp} : eqp;
}
if (VN_IS(nodep, Neq)) {
@ -761,17 +763,17 @@ private:
if (nodep->lhsp()->isWide()) {
UINFO(8, " Wordize REDOR " << nodep << endl);
// -> (0!={or{for each_word{WORDSEL(lhs,#)}}}
AstNode* newp = nullptr;
AstNodeExpr* newp = nullptr;
for (int w = 0; w < nodep->lhsp()->widthWords(); ++w) {
AstNode* const eqp = newAstWordSelClone(nodep->lhsp(), w);
AstNodeExpr* const eqp = newAstWordSelClone(nodep->lhsp(), w);
newp = newp ? new AstOr{fl, newp, eqp} : eqp;
}
newp = new AstNeq{fl, new AstConst{fl, AstConst::SizedEData(), 0}, newp};
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
} else {
UINFO(8, " REDOR->EQ " << nodep << endl);
AstNode* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* const newp = new AstNeq{
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const newp = new AstNeq{
fl, new AstConst{fl, AstConst::WidthedValue(), longOrQuadWidth(nodep), 0}, lhsp};
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
}
@ -783,9 +785,9 @@ private:
if (nodep->lhsp()->isWide()) {
UINFO(8, " Wordize REDAND " << nodep << endl);
// -> (0!={and{for each_word{WORDSEL(lhs,#)}}}
AstNode* newp = nullptr;
AstNodeExpr* newp = nullptr;
for (int w = 0; w < nodep->lhsp()->widthWords(); ++w) {
AstNode* eqp = newAstWordSelClone(nodep->lhsp(), w);
AstNodeExpr* eqp = newAstWordSelClone(nodep->lhsp(), w);
if (w == nodep->lhsp()->widthWords() - 1) {
// Rather than doing a (slowish) ==##, we OR in the
// bits that aren't part of the mask
@ -801,8 +803,8 @@ private:
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
} else {
UINFO(8, " REDAND->EQ " << nodep << endl);
AstNode* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* const newp = new AstEq{fl, new AstConst{fl, wordMask(lhsp)}, lhsp};
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const newp = new AstEq{fl, new AstConst{fl, wordMask(lhsp)}, lhsp};
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
}
}
@ -813,9 +815,9 @@ private:
UINFO(8, " Wordize REDXOR " << nodep << endl);
// -> (0!={redxor{for each_word{XOR(WORDSEL(lhs,#))}}}
FileLine* const fl = nodep->fileline();
AstNode* newp = nullptr;
AstNodeExpr* newp = nullptr;
for (int w = 0; w < nodep->lhsp()->widthWords(); ++w) {
AstNode* const eqp = newAstWordSelClone(nodep->lhsp(), w);
AstNodeExpr* const eqp = newAstWordSelClone(nodep->lhsp(), w);
newp = newp ? new AstXor{fl, newp, eqp} : eqp;
}
newp = new AstRedXor{fl, newp};

View File

@ -174,8 +174,8 @@ class ForceConvertVisitor final : public VNVisitor {
pushDeletep(nodep);
FileLine* const flp = nodep->fileline();
AstNode* const lhsp = nodep->lhsp(); // The LValue we are forcing
AstNode* const rhsp = nodep->rhsp(); // The value we are forcing it to
AstNodeExpr* const lhsp = nodep->lhsp(); // The LValue we are forcing
AstNodeExpr* const rhsp = nodep->rhsp(); // The value we are forcing it to
// Set corresponding enable signals to ones
V3Number ones{lhsp, lhsp->width()};
@ -210,7 +210,7 @@ class ForceConvertVisitor final : public VNVisitor {
pushDeletep(nodep);
FileLine* const flp = nodep->fileline();
AstNode* const lhsp = nodep->lhsp(); // The LValue we are releasing
AstNodeExpr* const lhsp = nodep->lhsp(); // The LValue we are releasing
// Set corresponding enable signals to zero
V3Number zero{lhsp, lhsp->width()};

View File

@ -70,14 +70,14 @@ private:
// Use user1p on the PIN to indicate we created an assign for this pin
if (!nodep->user1SetOnce()) {
// Make an ASSIGNW (expr, pin)
AstNode* const exprp = nodep->exprp()->cloneTree(false);
AstNodeExpr* const exprp = VN_AS(nodep->exprp(), NodeExpr)->cloneTree(false);
UASSERT_OBJ(exprp->width() == nodep->modVarp()->width(), nodep,
"Width mismatch, should have been handled in pinReconnectSimple");
if (nodep->modVarp()->isInoutish()) {
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
} else if (nodep->modVarp()->isWritable()) {
AstNode* const rhsp = new AstVarXRef(exprp->fileline(), nodep->modVarp(),
m_cellp->name(), VAccess::READ);
AstNodeExpr* const rhsp = new AstVarXRef(exprp->fileline(), nodep->modVarp(),
m_cellp->name(), VAccess::READ);
AstAssignW* const assp = new AstAssignW(exprp->fileline(), exprp, rhsp);
m_cellp->addNextHere(assp);
} else if (nodep->modVarp()->isNonOutput()) {
@ -97,8 +97,8 @@ private:
IfaceRefDType))) {
// Create an AstAssignVarScope for Vars to Cells so we can
// link with their scope later
AstNode* const lhsp = new AstVarXRef(exprp->fileline(), nodep->modVarp(),
m_cellp->name(), VAccess::READ);
AstNodeExpr* const lhsp = new AstVarXRef(exprp->fileline(), nodep->modVarp(),
m_cellp->name(), VAccess::READ);
const AstVarRef* const refp = VN_CAST(exprp, VarRef);
const AstVarXRef* const xrefp = VN_CAST(exprp, VarXRef);
UASSERT_OBJ(refp || xrefp, exprp,
@ -334,7 +334,7 @@ private:
const int arraySelNum = rangep->littleEndian()
? (rangep->elementsConst() - 1 - m_instSelNum)
: m_instSelNum;
AstNode* exprp = nodep->exprp()->unlinkFrBack();
AstNodeExpr* exprp = VN_AS(nodep->exprp(), NodeExpr)->unlinkFrBack();
exprp = new AstArraySel(exprp->fileline(), exprp, arraySelNum);
nodep->exprp(exprp);
} else if (expwidth == modwidth) {
@ -348,7 +348,7 @@ private:
<< m_cellRangep->leftConst() << ":"
<< m_cellRangep->rightConst() << "]");
}
AstNode* exprp = nodep->exprp()->unlinkFrBack();
AstNodeExpr* exprp = VN_AS(nodep->exprp(), NodeExpr)->unlinkFrBack();
const bool inputPin = nodep->modVarp()->isNonOutput();
if (!inputPin
&& !VN_IS(exprp, VarRef)
@ -489,10 +489,10 @@ class InstStatic final {
private:
InstStatic() = default; // Static class
static AstNode* extendOrSel(FileLine* fl, AstNode* rhsp, AstNode* cmpWidthp) {
static AstNodeExpr* extendOrSel(FileLine* fl, AstNodeExpr* rhsp, AstNode* cmpWidthp) {
if (cmpWidthp->width() > rhsp->width()) {
rhsp = (rhsp->isSigned() ? static_cast<AstNode*>(new AstExtendS{fl, rhsp})
: static_cast<AstNode*>(new AstExtend{fl, rhsp}));
rhsp = (rhsp->isSigned() ? static_cast<AstNodeExpr*>(new AstExtendS{fl, rhsp})
: static_cast<AstNodeExpr*>(new AstExtend{fl, rhsp}));
// Need proper widthMin, which may differ from AstSel created above
rhsp->dtypeFrom(cmpWidthp);
} else if (cmpWidthp->width() < rhsp->width()) {
@ -553,7 +553,7 @@ public:
// Make a new temp wire
// if (1 || debug() >= 9) pinp->dumpTree(cout, "-in_pin:");
V3Inst::checkOutputShort(pinp);
AstNode* const pinexprp = pinp->exprp()->unlinkFrBack();
AstNodeExpr* const pinexprp = VN_AS(pinp->exprp(), NodeExpr)->unlinkFrBack();
const string newvarname
= (string(pinVarp->isWritable() ? "__Vcellout" : "__Vcellinp")
// Prevent name conflict if both tri & non-tri add signals
@ -568,12 +568,12 @@ public:
" direct one-to-one connection (without any expression)");
} else if (pinVarp->isWritable()) {
// See also V3Inst
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, VAccess::READ);
AstNodeExpr* rhsp = new AstVarRef(pinp->fileline(), newvarp, VAccess::READ);
UINFO(5, "pinRecon width " << pinVarp->width() << " >? " << rhsp->width() << " >? "
<< pinexprp->width() << endl);
rhsp = extendOrSel(pinp->fileline(), rhsp, pinVarp);
pinp->exprp(new AstVarRef(newvarp->fileline(), newvarp, VAccess::WRITE));
AstNode* const rhsSelp = extendOrSel(pinp->fileline(), rhsp, pinexprp);
AstNodeExpr* const rhsSelp = extendOrSel(pinp->fileline(), rhsp, pinexprp);
assignp = new AstAssignW(pinp->fileline(), pinexprp, rhsSelp);
} else {
// V3 width should have range/extended to make the widths correct

View File

@ -1223,7 +1223,7 @@ class LinkDotFindVisitor final : public VNVisitor {
// new value.
if (v3Global.opt.hasParameter(nodep->name())) {
const string svalue = v3Global.opt.parameter(nodep->name());
if (AstNode* const valuep
if (AstConst* const valuep
= AstConst::parseParamLiteral(nodep->fileline(), svalue)) {
UINFO(9, " replace parameter " << nodep << endl);
UINFO(9, " with " << valuep << endl);
@ -1366,7 +1366,7 @@ class LinkDotFindVisitor final : public VNVisitor {
// DOT(x, SELLOOPVARS(var, loops)) -> SELLOOPVARS(DOT(x, var), loops)
if (AstDot* const dotp = VN_CAST(nodep->arrayp(), Dot)) {
if (AstSelLoopVars* const loopvarsp = VN_CAST(dotp->rhsp(), SelLoopVars)) {
AstNode* const fromp = loopvarsp->fromp()->unlinkFrBack();
AstNodeExpr* const fromp = loopvarsp->fromp()->unlinkFrBack();
loopvarsp->unlinkFrBack();
dotp->replaceWith(loopvarsp);
dotp->rhsp(fromp);
@ -1540,7 +1540,7 @@ private:
if (!cellp) {
nodep->v3error("In defparam, instance " << nodep->path() << " never declared");
} else {
AstNode* const exprp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const exprp = nodep->rhsp()->unlinkFrBack();
UINFO(9, "Defparam cell " << nodep->path() << "." << nodep->name() << " attach-to "
<< cellp << " <= " << exprp << endl);
// Don't need to check the name of the defparam exists. V3Param does.
@ -2295,7 +2295,7 @@ private:
nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else { // Dot midpoint
AstNode* newp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* newp = nodep->rhsp()->unlinkFrBack();
if (m_ds.m_unresolved) {
AstCellRef* const crp = new AstCellRef(nodep->fileline(), nodep->name(),
nodep->lhsp()->unlinkFrBack(), newp);
@ -2358,8 +2358,8 @@ private:
return;
} else if (m_ds.m_dotPos == DP_MEMBER) {
// Found a Var, everything following is membership. {scope}.{var}.HERE {member}
AstNode* const varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack();
AstNode* const newp
AstNodeExpr* const varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack();
AstNodeExpr* const newp
= new AstMemberSel(nodep->fileline(), varEtcp, VFlagChildDType(), nodep->name());
if (m_ds.m_dotErr) {
nodep->unlinkFrBack(); // Avoid circular node loop on errors
@ -2545,7 +2545,8 @@ private:
m_ds.m_dotPos = DP_SCOPE;
UINFO(9, " modport -> iface varref " << foundp->nodep() << endl);
// We lose the modport name here, so we cannot detect mismatched modports.
AstNode* newp = new AstVarRef{nodep->fileline(), ifaceRefVarp, VAccess::READ};
AstNodeExpr* newp
= new AstVarRef{nodep->fileline(), ifaceRefVarp, VAccess::READ};
auto* const cellarrayrefp = VN_CAST(m_ds.m_unlinkedScopep, CellArrayRef);
if (cellarrayrefp) {
// iface[vec].modport became CellArrayRef(iface, lsb)
@ -2811,8 +2812,8 @@ private:
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_MEMBER) {
// Found a Var, everything following is method call.
// {scope}.{var}.HERE {method} ( ARGS )
AstNode* const varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack();
AstNode* argsp = nullptr;
AstNodeExpr* const varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack();
AstNodeExpr* argsp = nullptr;
if (nodep->pinsp()) argsp = nodep->pinsp()->unlinkFrBackWithNext();
AstNode* const newp = new AstMethodCall(nodep->fileline(), varEtcp, VFlagChildDType(),
nodep->name(), argsp);
@ -2965,7 +2966,7 @@ private:
}
}
if (m_ds.m_unresolved && m_ds.m_dotPos == DP_SCOPE) {
AstNode* const exprp = nodep->bitp()->unlinkFrBack();
AstNodeExpr* const exprp = nodep->bitp()->unlinkFrBack();
AstCellArrayRef* const newp
= new AstCellArrayRef(nodep->fileline(), nodep->fromp()->name(), exprp);
nodep->replaceWith(newp);

View File

@ -205,8 +205,8 @@ private:
UASSERT_OBJ(nodep, constp, "Expecting CONST");
AstConst* const newconstp = constp->cloneTree(true);
AstNode* const storetop = nodep->thsp();
AstNode* const valuep = nodep->rhsp();
AstNodeExpr* const storetop = nodep->thsp();
AstNodeExpr* const valuep = nodep->rhsp();
storetop->unlinkFrBack();
valuep->unlinkFrBack();
@ -247,7 +247,7 @@ private:
insertBeforeStmt(nodep, varp);
// Define what operation will we be doing
AstNode* operp;
AstNodeExpr* operp;
if (VN_IS(nodep, PostSub) || VN_IS(nodep, PreSub)) {
operp = new AstSub(fl, new AstVarRef(fl, varrefp->varp(), VAccess::READ), newconstp);
} else {

View File

@ -159,7 +159,7 @@ private:
// So later optimizations don't need to deal with them,
// REPEAT(count,body) -> loop=count,WHILE(loop>0) { body, loop-- }
// Note var can be signed or unsigned based on original number.
AstNode* const countp = nodep->countp()->unlinkFrBackWithNext();
AstNodeExpr* const countp = nodep->countp()->unlinkFrBackWithNext();
const string name = string("__Vrepeat") + cvtToStr(m_modRepeatNum++);
// Spec says value is integral, if negative is ignored
AstVar* const varp
@ -172,8 +172,8 @@ private:
nodep->fileline(), new AstVarRef(nodep->fileline(), varp, VAccess::WRITE),
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, VAccess::READ),
new AstConst(nodep->fileline(), 1)));
AstNode* const zerosp = new AstConst(nodep->fileline(), AstConst::Signed32(), 0);
AstNode* const condp = new AstGtS(
AstNodeExpr* const zerosp = new AstConst(nodep->fileline(), AstConst::Signed32(), 0);
AstNodeExpr* const condp = new AstGtS(
nodep->fileline(), new AstVarRef(nodep->fileline(), varp, VAccess::READ), zerosp);
AstNode* const bodysp = nodep->stmtsp();
if (bodysp) bodysp->unlinkFrBackWithNext();
@ -210,7 +210,7 @@ private:
m_loopInc = true;
iterateAndNextNull(nodep->incsp());
}
AstNode* const condp = nodep->condp() ? nodep->condp()->unlinkFrBack() : nullptr;
AstNodeExpr* const condp = nodep->condp() ? nodep->condp()->unlinkFrBack() : nullptr;
AstNode* const bodyp = nodep->stmtsp() ? nodep->stmtsp()->unlinkFrBack() : nullptr;
AstNode* const incsp = nodep->incsp() ? nodep->incsp()->unlinkFrBack() : nullptr;
AstWhile* const whilep = new AstWhile{nodep->fileline(), condp, bodyp, incsp};

View File

@ -181,7 +181,7 @@ private:
FileLine* const flp = nodep->fileline();
for (int i = left; i != (right + increment); i += increment, offset_from_init++) {
const string name = nodep->name() + cvtToStr(i);
AstNode* valuep = nullptr;
AstNodeExpr* valuep = nullptr;
if (nodep->valuep()) {
valuep
= new AstAdd(flp, nodep->valuep()->cloneTree(true),
@ -266,7 +266,7 @@ private:
newfl->warnOff(V3ErrorCode::PROCASSWIRE, true);
auto* const assp
= new AstAssign(newfl, new AstVarRef(newfl, nodep->name(), VAccess::WRITE),
nodep->valuep()->unlinkFrBack());
VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr));
if (nodep->lifetime().isAutomatic()) {
nodep->addNextHere(new AstInitialAutomatic{newfl, assp});
} else {
@ -274,9 +274,9 @@ private:
}
} // 4. Under blocks, it's an initial value to be under an assign
else {
nodep->addNextHere(new AstAssign(fl,
new AstVarRef(fl, nodep->name(), VAccess::WRITE),
nodep->valuep()->unlinkFrBack()));
nodep->addNextHere(
new AstAssign(fl, new AstVarRef(fl, nodep->name(), VAccess::WRITE),
VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr)));
}
}
if (nodep->isIfaceRef() && !nodep->isIfaceParent() && !v3Global.opt.topIfacesSupported()) {

View File

@ -136,7 +136,7 @@ bool areDisjoint(const std::set<const AstVar*>& a, const std::set<const AstVar*>
// Structure containing information required for code motion/merging
struct StmtProperties {
AstNode* m_condp = nullptr; // The condition expression, if a conditional node
AstNodeExpr* m_condp = nullptr; // The condition expression, if a conditional node
std::set<const AstVar*> m_rdVars; // Variables read by this statement
std::set<const AstVar*> m_wrVars; // Variables writen by this statement
bool m_isFence = false; // Nothing should move across this statement, nor should it be merged
@ -178,8 +178,8 @@ class CodeMotionAnalysisVisitor final : public VNVisitor {
StmtProperties* m_propsp = nullptr; // StmtProperties structure of current AstNodeStmt
// Extract condition expression from a megeable conditional statement, if any
static AstNode* extractCondition(const AstNodeStmt* nodep) {
AstNode* conditionp = nullptr;
static AstNodeExpr* extractCondition(const AstNodeStmt* nodep) {
AstNodeExpr* conditionp = nullptr;
if (const AstNodeAssign* const assignp = VN_CAST(nodep, NodeAssign)) {
if (AstNodeCond* const conditionalp = extractCondFromRhs(assignp->rhsp())) {
conditionp = conditionalp->condp();
@ -199,7 +199,7 @@ class CodeMotionAnalysisVisitor final : public VNVisitor {
m_propsp = &m_stmtProperties(nodep);
// Extract condition from statement
if (AstNode* const condp = extractCondition(nodep)) {
if (AstNodeExpr* const condp = extractCondition(nodep)) {
// Remember condition node. We always need this as it is used in the later
// traversal.
m_propsp->m_condp = condp;
@ -447,7 +447,7 @@ private:
VDouble0 m_statLongestList; // Statistic tracking
AstNode* m_mgFirstp = nullptr; // First node in merged sequence
AstNode* m_mgCondp = nullptr; // The condition of the first node
AstNodeExpr* m_mgCondp = nullptr; // The condition of the first node
const AstNode* m_mgLastp = nullptr; // Last node in merged sequence
const AstNode* m_mgNextp = nullptr; // Next node in list being examined
uint32_t m_listLenght = 0; // Length of current list
@ -578,10 +578,10 @@ private:
// Apply (1'b1 & _) cleaning mask if necessary. This is required because this pass is after
// V3Clean, and sometimes we have an AstAnd with a 1-bit condition on one side, but a more
// than 1-bit value on the other side, so we need to keep only the LSB.
static AstNode* maskLsb(AstNode* nodep) {
static AstNodeExpr* maskLsb(AstNodeExpr* nodep) {
if (yieldsOneOrZero(nodep)) return nodep;
// Otherwise apply masking
AstNode* const maskp = new AstConst{nodep->fileline(), AstConst::BitTrue()};
AstConst* const maskp = new AstConst{nodep->fileline(), AstConst::BitTrue()};
// Mask on left, as conventional
return new AstAnd{nodep->fileline(), maskp, nodep};
}
@ -589,11 +589,11 @@ private:
// Fold the RHS expression of an assignment assuming the given condition state.
// Unlink bits from the RHS which is only used once, and can be reused (is an unomdified
// sub-tree). What remains of the RHS is expected to be deleted by the caller.
AstNode* foldAndUnlink(AstNode* rhsp, bool condTrue) {
AstNodeExpr* foldAndUnlink(AstNodeExpr* rhsp, bool condTrue) {
if (rhsp->sameTree(m_mgCondp)) {
return new AstConst{rhsp->fileline(), AstConst::BitTrue{}, condTrue};
} else if (const AstNodeCond* const condp = extractCondFromRhs(rhsp)) {
AstNode* const resp
AstNodeExpr* const resp
= condTrue ? condp->thenp()->unlinkFrBack() : condp->elsep()->unlinkFrBack();
if (condp == rhsp) return resp;
if (const AstAnd* const andp = VN_CAST(rhsp, And)) {
@ -671,7 +671,7 @@ private:
++m_statMergedItems;
if (AstNodeAssign* const assignp = VN_CAST(currp, NodeAssign)) {
// Unlink RHS and clone to get the 2 assignments (reusing assignp)
AstNode* const rhsp = assignp->rhsp()->unlinkFrBack();
AstNodeExpr* const rhsp = assignp->rhsp()->unlinkFrBack();
AstNodeAssign* const thenp = assignp;
AstNodeAssign* const elsep = assignp->cloneTree(false);
// Construct the new RHSs and add to branches
@ -739,7 +739,7 @@ private:
return false;
}
bool addToList(AstNodeStmt* nodep, AstNode* condp) {
bool addToList(AstNodeStmt* nodep, AstNodeExpr* condp) {
// Set up head of new list if node is first in list
if (!m_mgFirstp) {
UASSERT_OBJ(condp, nodep, "Cannot start new list without condition");
@ -825,7 +825,7 @@ private:
// VISITORS
void visit(AstNodeAssign* nodep) override {
if (AstNode* const condp = (*m_stmtPropertiesp)(nodep).m_condp) {
if (AstNodeExpr* const condp = (*m_stmtPropertiesp)(nodep).m_condp) {
// Check if mergeable
if (!checkOrMakeMergeable(nodep)) return;
// Close potentially incompatible pending merge

View File

@ -69,14 +69,14 @@ void V3ParseImp::parserClear() {
//======================================================================
// V3ParseGrammar functions requiring bison state
AstArg* V3ParseGrammar::argWrapList(AstNode* nodep) {
AstArg* V3ParseGrammar::argWrapList(AstNodeExpr* nodep) {
// Convert list of expressions to list of arguments
if (!nodep) return nullptr;
AstArg* outp = nullptr;
AstBegin* const tempp = new AstBegin{nodep->fileline(), "[EditWrapper]", nodep};
while (nodep) {
AstNode* const nextp = nodep->nextp();
AstNode* const exprp = nodep->unlinkFrBack();
AstNodeExpr* const nextp = VN_AS(nodep->nextp(), NodeExpr);
AstNodeExpr* const exprp = nodep->unlinkFrBack();
nodep = nextp;
outp = AstNode::addNext(outp, new AstArg{exprp->fileline(), "", exprp});
}

View File

@ -69,7 +69,7 @@ private:
return (VN_IS(nodep->lhsp(), VarRef) && !AstVar::scVarRecurse(nodep->lhsp())
&& VN_IS(nodep->rhsp(), Const));
}
void checkNode(AstNode* nodep) {
void checkNode(AstNodeExpr* nodep) {
// Consider adding a temp for this expression.
// We need to avoid adding temps to the following:
// ASSIGN(x, *here*)
@ -116,7 +116,7 @@ private:
}
}
void createDeepTemp(AstNode* nodep, bool noSubst) {
void createDeepTemp(AstNodeExpr* nodep, bool noSubst) {
if (nodep->user1SetOnce()) return; // Only add another assignment for this node
VNRelinker relinker;
@ -236,7 +236,7 @@ private:
&& nodep->width() < (1LL << nodep->rhsp()->widthMin())) {
VNRelinker replaceHandle;
nodep->unlinkFrBack(&replaceHandle);
AstNode* constzerop;
AstNodeExpr* constzerop;
const int m1value
= nodep->widthMin() - 1; // Constant of width-1; not changing dtype width
if (nodep->signedFlavor()) {
@ -253,7 +253,7 @@ private:
}
constzerop->dtypeFrom(nodep); // unsigned
AstNode* const constwidthp
AstNodeExpr* const constwidthp
= new AstConst(nodep->fileline(), AstConst::WidthedValue(),
nodep->rhsp()->widthMin(), m1value);
constwidthp->dtypeFrom(nodep->rhsp()); // unsigned
@ -352,8 +352,9 @@ private:
// There's another display next; we can just wait to flush
} else {
UINFO(4, "Autoflush " << nodep << endl);
nodep->addNextHere(new AstFFlush(nodep->fileline(),
AstNode::cloneTreeNull(nodep->filep(), true)));
nodep->addNextHere(
new AstFFlush{nodep->fileline(),
VN_AS(AstNode::cloneTreeNull(nodep->filep(), true), NodeExpr)});
}
}
}
@ -361,7 +362,7 @@ private:
iterateChildren(nodep);
// Any strings sent to a display must be var of string data type,
// to avoid passing a pointer to a temporary.
for (AstNode* expp = nodep->exprsp(); expp; expp = expp->nextp()) {
for (AstNodeExpr* expp = nodep->exprsp(); expp; expp = VN_AS(expp->nextp(), NodeExpr)) {
if (expp->dtypep()->basicp() && expp->dtypep()->basicp()->isString()
&& !VN_IS(expp, VarRef)) {
createDeepTemp(expp, true);

View File

@ -184,7 +184,7 @@ private:
= new AstVarRef{fl, enumValueTabp(enumDtp), VAccess::READ};
tabRefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
AstRand* const randp = new AstRand{fl, nullptr, false};
AstNode* const moddivp = new AstModDiv{
AstNodeExpr* const moddivp = new AstModDiv{
fl, randp, new AstConst{fl, static_cast<uint32_t>(enumDtp->itemCount())}};
randp->dtypep(varrefp->findBasicDType(VBasicDTypeKwd::UINT32));
moddivp->dtypep(enumDtp);
@ -296,7 +296,7 @@ private:
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
itemp = VN_AS(itemp->nextp(), CaseItem)) {
AstNode* const condp = itemp->condsp()->unlinkFrBack();
AstNodeExpr* const condp = itemp->condsp()->unlinkFrBack();
sump
= new AstAdd{condp->fileline(), sump, new AstExtend{itemp->fileline(), condp, 64}};
AstNode* const stmtsp
@ -318,7 +318,7 @@ private:
ifsp->addElsesp(dispp);
AstNode* newp = randVarp;
AstNode* randp = new AstRand{fl, nullptr, false};
AstNodeExpr* randp = new AstRand{fl, nullptr, false};
randp->dtypeSetUInt64();
newp->addNext(new AstAssign{fl, new AstVarRef{fl, randVarp, VAccess::WRITE},
new AstAdd{fl, new AstConst{fl, AstConst::Unsized64{}, 1},

View File

@ -107,8 +107,8 @@ private:
AstNode* const initp = new AstAssign(fl, new AstVarRef(fl, itp, VAccess::WRITE),
new AstConst(fl, m_mgIndexLo));
AstNode* const condp = new AstLte(fl, new AstVarRef(fl, itp, VAccess::READ),
new AstConst(fl, m_mgIndexHi));
AstNodeExpr* const condp = new AstLte(fl, new AstVarRef(fl, itp, VAccess::READ),
new AstConst(fl, m_mgIndexHi));
AstNode* const incp = new AstAssign(
fl, new AstVarRef(fl, itp, VAccess::WRITE),
new AstAdd(fl, new AstConst(fl, 1), new AstVarRef(fl, itp, VAccess::READ)));
@ -118,15 +118,15 @@ private:
whilep->addStmtsp(bodyp);
// Replace constant index with new loop index
AstNode* const offsetp
AstNodeExpr* const offsetp
= m_mgOffset == 0 ? nullptr : new AstConst(fl, std::abs(m_mgOffset));
AstNode* const lbitp = m_mgSelLp->bitp();
AstNode* const lvrefp = new AstVarRef(fl, itp, VAccess::READ);
AstNodeExpr* const lbitp = m_mgSelLp->bitp();
AstNodeExpr* const lvrefp = new AstVarRef(fl, itp, VAccess::READ);
lbitp->replaceWith(m_mgOffset > 0 ? new AstAdd(fl, lvrefp, offsetp) : lvrefp);
VL_DO_DANGLING(lbitp->deleteTree(), lbitp);
if (m_mgSelRp) { // else constant and no replace
AstNode* const rbitp = m_mgSelRp->bitp();
AstNode* const rvrefp = new AstVarRef(fl, itp, VAccess::READ);
AstNodeExpr* const rbitp = m_mgSelRp->bitp();
AstNodeExpr* const rvrefp = new AstVarRef(fl, itp, VAccess::READ);
rbitp->replaceWith(m_mgOffset < 0 ? new AstAdd(fl, rvrefp, offsetp) : rvrefp);
VL_DO_DANGLING(rbitp->deleteTree(), lbitp);
}

View File

@ -64,7 +64,7 @@ class SenExprBuilder final {
}
// METHODS
AstNode* getCurr(AstNode* exprp) {
AstNodeExpr* getCurr(AstNodeExpr* exprp) {
// For simple expressions like varrefs or selects, just use them directly
if (isSimpleExpr(exprp)) return exprp->cloneTree(false);
@ -89,7 +89,7 @@ class SenExprBuilder final {
}
return new AstVarRef{flp, currp, VAccess::READ};
}
AstVarScope* getPrev(AstNode* exprp) {
AstVarScope* getPrev(AstNodeExpr* exprp) {
FileLine* const flp = exprp->fileline();
const auto rdCurr = [=]() { return getCurr(exprp); };
@ -150,9 +150,9 @@ class SenExprBuilder final {
return prevp;
}
std::pair<AstNode*, bool> createTerm(AstSenItem* senItemp) {
std::pair<AstNodeExpr*, bool> createTerm(AstSenItem* senItemp) {
FileLine* const flp = senItemp->fileline();
AstNode* const senp = senItemp->sensp();
AstNodeExpr* const senp = senItemp->sensp();
const auto currp = [=]() { return getCurr(senp); };
const auto prevp = [=]() { return new AstVarRef{flp, getPrev(senp), VAccess::READ}; };
@ -215,14 +215,14 @@ class SenExprBuilder final {
public:
// Returns the expression computing the trigger, and a bool indicating that
// this trigger should be fired on the first evaluation (at initialization)
std::pair<AstNode*, bool> build(const AstSenTree* senTreep) {
std::pair<AstNodeExpr*, bool> build(const AstSenTree* senTreep) {
FileLine* const flp = senTreep->fileline();
AstNode* resultp = nullptr;
AstNodeExpr* resultp = nullptr;
bool firedAtInitialization = false;
for (AstSenItem* senItemp = senTreep->sensesp(); senItemp;
senItemp = VN_AS(senItemp->nextp(), SenItem)) {
const auto& pair = createTerm(senItemp);
if (AstNode* const termp = pair.first) {
if (AstNodeExpr* const termp = pair.first) {
resultp = resultp ? new AstOr{flp, resultp, termp} : termp;
firedAtInitialization |= pair.second;
}

View File

@ -191,7 +191,7 @@ public:
for (V3TaskConnects::iterator conIt = tconnects->begin();
conIt != tconnects->end(); ++conIt) {
AstVar* const portp = conIt->first;
AstNode* const pinp = conIt->second->exprp();
AstNodeExpr* const pinp = conIt->second->exprp();
AstNodeDType* const dtypep = pinp->dtypep();
if (AstConst* const valp = fetchConstNull(pinp)) {
stack << "\n " << portp->prettyName() << " = "
@ -248,26 +248,26 @@ private:
}
public:
void newValue(AstNode* nodep, const AstNode* valuep) {
void newValue(AstNode* nodep, const AstNodeExpr* valuep) {
if (const AstConst* const constp = VN_CAST(valuep, Const)) {
newConst(nodep)->num().opAssign(constp->num());
} else if (fetchValueNull(nodep) != valuep) {
// const_cast, as clonep() is set on valuep, but nothing should care
setValue(nodep, newTrackedClone(const_cast<AstNode*>(valuep)));
setValue(nodep, newTrackedClone(const_cast<AstNodeExpr*>(valuep)));
}
}
void newOutValue(AstNode* nodep, const AstNode* valuep) {
void newOutValue(AstNode* nodep, const AstNodeExpr* valuep) {
if (const AstConst* const constp = VN_CAST(valuep, Const)) {
newOutConst(nodep)->num().opAssign(constp->num());
} else if (fetchOutValueNull(nodep) != valuep) {
// const_cast, as clonep() is set on valuep, but nothing should care
setOutValue(nodep, newTrackedClone(const_cast<AstNode*>(valuep)));
setOutValue(nodep, newTrackedClone(const_cast<AstNodeExpr*>(valuep)));
}
}
private:
AstNode* newTrackedClone(AstNode* nodep) {
AstNode* const newp = nodep->cloneTree(false);
AstNodeExpr* newTrackedClone(AstNodeExpr* nodep) {
AstNodeExpr* const newp = nodep->cloneTree(false);
m_reclaimValuesp.push_back(newp);
return newp;
}
@ -293,16 +293,16 @@ private:
}
public:
AstNode* fetchValueNull(AstNode* nodep) { return nodep->user3p(); }
AstNodeExpr* fetchValueNull(AstNode* nodep) { return VN_AS(nodep->user3p(), NodeExpr); }
private:
AstNode* fetchOutValueNull(AstNode* nodep) { return nodep->user2p(); }
AstNodeExpr* fetchOutValueNull(AstNode* nodep) { return VN_AS(nodep->user2p(), NodeExpr); }
AstConst* fetchConstNull(AstNode* nodep) { return VN_CAST(fetchValueNull(nodep), Const); }
AstConst* fetchOutConstNull(AstNode* nodep) {
return VN_CAST(fetchOutValueNull(nodep), Const);
}
AstNode* fetchValue(AstNode* nodep) {
AstNode* const valuep = fetchValueNull(nodep);
AstNodeExpr* fetchValue(AstNode* nodep) {
AstNodeExpr* const valuep = fetchValueNull(nodep);
UASSERT_OBJ(valuep, nodep, "No value found for node.");
// UINFO(9, " fetch val " << *valuep << " on " << nodep << endl);
return valuep;
@ -332,12 +332,12 @@ public:
}
private:
void setValue(AstNode* nodep, const AstNode* valuep) {
void setValue(AstNode* nodep, const AstNodeExpr* valuep) {
UASSERT_OBJ(valuep, nodep, "Simulate setting null value");
UINFO(9, " set val " << valuep->name() << " on " << nodep << endl);
nodep->user3p((void*)valuep);
}
void setOutValue(AstNode* nodep, const AstNode* valuep) {
void setOutValue(AstNode* nodep, const AstNodeExpr* valuep) {
UASSERT_OBJ(valuep, nodep, "Simulate setting null value");
UINFO(9, " set oval " << valuep->name() << " on " << nodep << endl);
nodep->user2p((void*)valuep);
@ -386,7 +386,7 @@ private:
// True to jump over this node - all visitors must call this up front
return (m_jumpp && m_jumpp->labelp() != nodep);
}
void assignOutValue(AstNodeAssign* nodep, AstNode* vscp, const AstNode* valuep) {
void assignOutValue(AstNodeAssign* nodep, AstNode* vscp, const AstNodeExpr* valuep) {
if (VN_IS(nodep, AssignDly)) {
// Don't do setValue, as value isn't yet visible to following statements
newOutValue(vscp, valuep);
@ -443,10 +443,10 @@ private:
}
vscp->user1(vscp->user1() | VU_RV);
const bool isConst = nodep->varp()->isParam() && nodep->varp()->valuep();
AstNode* const valuep
AstNodeExpr* const valuep
= isConst ? fetchValueNull(nodep->varp()->valuep()) : nullptr;
if (isConst
&& valuep) { // Propagate PARAM constants for constant function analysis
// Propagate PARAM constants for constant function analysis
if (isConst && valuep) {
if (!m_checkOnly && optimizable()) newValue(vscp, valuep);
} else {
if (m_checkOnly) varRefCb(nodep);
@ -458,7 +458,7 @@ private:
"LHS varref should be handled in AstAssign visitor.");
{
// Return simulation value - copy by reference instead of value for speed
AstNode* valuep = fetchValueNull(vscp);
AstNodeExpr* valuep = fetchValueNull(vscp);
if (!valuep) {
if (m_params) {
clearOptimizable(
@ -697,7 +697,7 @@ private:
m_reclaimValuesp.push_back(initp);
}
const uint32_t index = fetchConst(selp->bitp())->toUInt();
AstNode* const valuep = newTrackedClone(fetchValue(nodep->rhsp()));
AstNodeExpr* const valuep = newTrackedClone(fetchValue(nodep->rhsp()));
UINFO(9, " set val[" << index << "] = " << valuep << endl);
// Values are in the "real" tree under the InitArray so can eventually extract it,
// Not in the usual setValue (pointed to by user2/3p)
@ -803,7 +803,7 @@ private:
if (AstInitArray* const initp = VN_CAST(fetchValueNull(nodep->fromp()), InitArray)) {
AstConst* const indexp = fetchConst(nodep->bitp());
const uint32_t offset = indexp->num().toUInt();
AstNode* const itemp = initp->getIndexDefaultedValuep(offset);
AstNodeExpr* const itemp = initp->getIndexDefaultedValuep(offset);
if (!itemp) {
clearOptimizable(nodep, "Array initialization has too few elements, need element "
+ cvtToStr(offset));

View File

@ -60,7 +60,7 @@ class SliceVisitor final : public VNVisitor {
bool m_assignError = false; // True if the current assign already has an error
// METHODS
AstNode* cloneAndSel(AstNode* nodep, int elements, int offset) {
AstNodeExpr* cloneAndSel(AstNode* nodep, int elements, int offset) {
// Insert an ArraySel, except for a few special cases
const AstUnpackArrayDType* const arrayp
= VN_CAST(nodep->dtypep()->skipRefp(), UnpackArrayDType);
@ -73,7 +73,8 @@ class SliceVisitor final : public VNVisitor {
V3Error::incErrors(); // Otherwise might infinite loop
}
m_assignError = true;
return nodep->cloneTree(false); // Likely will cause downstream errors
// Likely will cause downstream errors
return VN_AS(nodep, NodeExpr)->cloneTree(false);
}
if (arrayp->rangep()->elementsConst() != elements) {
if (!m_assignError) {
@ -85,19 +86,18 @@ class SliceVisitor final : public VNVisitor {
elements = 1;
offset = 0;
}
AstNode* newp;
AstNodeExpr* newp;
if (const AstInitArray* const initp = VN_CAST(nodep, InitArray)) {
UINFO(9, " cloneInitArray(" << elements << "," << offset << ") " << nodep << endl);
const int leOffset = !arrayp->rangep()->littleEndian()
? arrayp->rangep()->elementsConst() - 1 - offset
: offset;
AstNode* itemp = initp->getIndexDefaultedValuep(leOffset);
AstNodeExpr* const itemp = initp->getIndexDefaultedValuep(leOffset);
if (!itemp) {
nodep->v3error("Array initialization has too few elements, need element "
<< offset);
itemp = initp->initsp();
}
newp = itemp->cloneTree(false);
newp = itemp ? itemp->cloneTree(false) : new AstConst{nodep->fileline(), 0};
} else if (AstNodeCond* const snodep = VN_CAST(nodep, NodeCond)) {
UINFO(9, " cloneCond(" << elements << "," << offset << ") " << nodep << endl);
return snodep->cloneType(snodep->condp()->cloneTree(false),
@ -116,14 +116,16 @@ class SliceVisitor final : public VNVisitor {
const int leOffset = !arrayp->rangep()->littleEndian()
? arrayp->rangep()->elementsConst() - 1 - offset
: offset;
newp = new AstArraySel{nodep->fileline(), nodep->cloneTree(false), leOffset};
newp = new AstArraySel{nodep->fileline(), VN_AS(nodep, NodeExpr)->cloneTree(false),
leOffset};
} else {
if (!m_assignError) {
nodep->v3error(nodep->prettyTypeName()
<< " unexpected in assignment to unpacked array");
}
m_assignError = true;
newp = nodep->cloneTree(false); // Likely will cause downstream errors
// Likely will cause downstream errors
newp = VN_AS(nodep, NodeExpr)->cloneTree(false);
}
return newp;
}
@ -143,9 +145,8 @@ class SliceVisitor final : public VNVisitor {
const int elements = arrayp->rangep()->elementsConst();
for (int offset = 0; offset < elements; ++offset) {
AstNodeAssign* const newp
= VN_AS(nodep->cloneType(cloneAndSel(nodep->lhsp(), elements, offset),
cloneAndSel(nodep->rhsp(), elements, offset)),
NodeAssign);
= nodep->cloneType(cloneAndSel(nodep->lhsp(), elements, offset),
cloneAndSel(nodep->rhsp(), elements, offset));
if (debug() >= 9) newp->dumpTree(cout, "-new ");
newlistp = AstNode::addNext(newlistp, newp);
}

View File

@ -132,7 +132,7 @@ struct SplitVarImpl {
// AstNodeModule::user1() -> Block number counter for generating unique names
const VNUser1InUse m_user1InUse; // Only used in SplitUnpackedVarVisitor
static AstNodeAssign* newAssign(FileLine* fileline, AstNode* lhsp, AstNode* rhsp,
static AstNodeAssign* newAssign(FileLine* fileline, AstNodeExpr* lhsp, AstNodeExpr* rhsp,
const AstVar* varp) {
if (varp->isFuncLocal() || varp->isFuncReturn()) {
return new AstAssign{fileline, lhsp, rhsp};
@ -621,9 +621,9 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl {
= (context && VN_IS(context, NodeFTaskRef)) || (assignp && VN_IS(assignp, Assign));
for (int i = 0; i < dtypep->elementsConst(); ++i) {
AstNode* lhsp
AstNodeExpr* lhsp
= newVarRef(fl, vars.at(start_idx + i), lvalue ? VAccess::WRITE : VAccess::READ);
AstNode* rhsp = new AstArraySel{
AstNodeExpr* rhsp = new AstArraySel{
fl, newVarRef(fl, varp, !lvalue ? VAccess::WRITE : VAccess::READ), i};
AstNode* const refp = lhsp;
UINFO(9, "Creating assign idx:" << i << " + " << start_idx << "\n");
@ -655,12 +655,12 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl {
const bool lvalue = varp->direction().isWritable();
FileLine* const fl = varp->fileline();
for (size_t i = 0; i < vars.size(); ++i) {
AstNode* const nodes[] = {
AstNodeExpr* const nodes[] = {
new AstArraySel{fl, newVarRef(fl, varp, lvalue ? VAccess::WRITE : VAccess::READ),
static_cast<int>(i)},
newVarRef(fl, vars.at(i), !lvalue ? VAccess::WRITE : VAccess::READ)};
AstNode* const lhsp = nodes[lvalue ? 0 : 1];
AstNode* const rhsp = nodes[lvalue ? 1 : 0];
AstNodeExpr* const lhsp = nodes[lvalue ? 0 : 1];
AstNodeExpr* const rhsp = nodes[lvalue ? 1 : 0];
AstNodeAssign* const assignp = newAssign(fl, lhsp, rhsp, varp);
if (insertp) {
if (lvalue) { // Just after writing to the temporary variable
@ -1025,8 +1025,8 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl {
void visit(AstNode* nodep) override { iterateChildren(nodep); }
// Extract necessary bit range from a newly created variable to meet ref
static AstNode* extractBits(const PackedVarRefEntry& ref, const SplitNewVar& var,
const VAccess access) {
static AstNodeExpr* extractBits(const PackedVarRefEntry& ref, const SplitNewVar& var,
const VAccess access) {
FileLine* const fl = ref.nodep()->fileline();
AstVarRef* const refp = new AstVarRef{fl, var.varp(), access};
if (ref.lsb() <= var.lsb() && var.msb() <= ref.msb()) { // Use the entire bits
@ -1049,10 +1049,10 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl {
const bool in = portp->isReadOnly();
FileLine* const fl = portp->fileline();
for (const SplitNewVar& var : vars) {
AstNode* rhsp
AstNodeExpr* rhsp
= new AstSel{fl, new AstVarRef{fl, portp, !in ? VAccess::WRITE : VAccess::READ},
var.lsb(), var.bitwidth()};
AstNode* lhsp = new AstVarRef{fl, var.varp(), in ? VAccess::WRITE : VAccess::READ};
AstNodeExpr* lhsp = new AstVarRef{fl, var.varp(), in ? VAccess::WRITE : VAccess::READ};
if (!in) std::swap(lhsp, rhsp);
AstNodeAssign* const assignp = newAssign(fl, lhsp, rhsp, portp);
if (insertp) {
@ -1134,9 +1134,10 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl {
new AstVarRef{senitemp->fileline(), varit->varp(), VAccess::READ}};
senitemp->addNextHere(prevp);
} else {
AstNode* const bitsp
AstNodeExpr* const bitsp
= extractBits(ref, *varit, lvalue ? VAccess::WRITE : VAccess::READ);
prevp = new AstConcat{ref.nodep()->fileline(), bitsp, prevp};
prevp = new AstConcat{ref.nodep()->fileline(), bitsp,
VN_AS(prevp, NodeExpr)};
}
}
// If varp is an argument of task/func, need to update temporary var
@ -1174,8 +1175,8 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl {
connectPortAndVar(vars, varp, nullptr);
} else if (varp->isTrace()) {
// Let's reuse the original variable for tracing
AstNode* rhsp = new AstVarRef{vars.front().varp()->fileline(), vars.front().varp(),
VAccess::READ};
AstNodeExpr* rhsp = new AstVarRef{vars.front().varp()->fileline(),
vars.front().varp(), VAccess::READ};
FileLine* const fl = varp->fileline();
for (size_t i = 1; i < vars.size(); ++i) {
rhsp = new AstConcat{fl, new AstVarRef{fl, vars[i].varp(), VAccess::READ},

View File

@ -119,7 +119,7 @@ public:
m_wordUse = true;
}
// ACCESSORS
AstNode* substWhole(AstNode* errp) {
AstNodeExpr* substWhole(AstNode* errp) {
if (!m_varp->isWide() && !m_whole.m_complex && m_whole.m_assignp && !m_wordAssign) {
const AstNodeAssign* const assp = m_whole.m_assignp;
UASSERT_OBJ(assp, errp, "Reading whole that was never assigned");
@ -129,7 +129,7 @@ public:
}
}
// Return what to substitute given word number for
AstNode* substWord(AstNode* errp, int word) {
AstNodeExpr* substWord(AstNode* errp, int word) {
if (!m_whole.m_complex && !m_whole.m_assignp && !m_words[word].m_complex) {
const AstNodeAssign* const assp = getWordAssignp(word);
UASSERT_OBJ(assp, errp, "Reading a word that was never assigned, or bad word #");
@ -287,9 +287,9 @@ private:
}
if (!hit) iterate(nodep->lhsp());
}
void replaceSubstEtc(AstNode* nodep, AstNode* substp) {
void replaceSubstEtc(AstNode* nodep, AstNodeExpr* substp) {
if (debug() > 5) nodep->dumpTree(cout, " substw_old: ");
AstNode* newp = substp->cloneTree(true);
AstNodeExpr* newp = substp->cloneTree(true);
if (!nodep->isQuad() && newp->isQuad()) {
newp = new AstCCast{newp->fileline(), newp, nodep};
}
@ -308,7 +308,7 @@ private:
const int word = constp->toUInt();
UINFO(8, " USEword" << word << " " << varrefp << endl);
SubstVarEntry* const entryp = getEntryp(varrefp);
if (AstNode* const substp = entryp->substWord(nodep, word)) {
if (AstNodeExpr* const substp = entryp->substWord(nodep, word)) {
// Check that the RHS hasn't changed value since we recorded it.
const SubstUseVisitor visitor{substp, entryp->getWordStep(word)};
if (visitor.ok()) {
@ -335,7 +335,7 @@ private:
if (nodep->access().isWriteOrRW()) {
UINFO(8, " ASSIGNcpx " << nodep << endl);
entryp->assignComplex();
} else if (AstNode* const substp = entryp->substWhole(nodep)) {
} else if (AstNodeExpr* const substp = entryp->substWhole(nodep)) {
// Check that the RHS hasn't changed value since we recorded it.
const SubstUseVisitor visitor{substp, entryp->getWholeStep()};
if (visitor.ok()) {

View File

@ -336,7 +336,7 @@ private:
AstNode* createLookupInput(FileLine* fl, AstVarScope* indexVscp) {
// Concat inputs into a single temp variable (inside always)
// First var in inVars becomes the LSB of the concat
AstNode* concatp = nullptr;
AstNodeExpr* concatp = nullptr;
for (AstVarScope* invscp : m_inVarps) {
AstVarRef* const refp = new AstVarRef{fl, invscp, VAccess::READ};
if (concatp) {
@ -359,8 +359,8 @@ private:
AstVarScope* outputAssignedTableVscp) {
FileLine* const fl = nodep->fileline();
for (TableOutputVar& tov : m_outVarps) {
AstNode* const alhsp = new AstVarRef{fl, tov.varScopep(), VAccess::WRITE};
AstNode* const arhsp = select(fl, tov.tabeVarScopep(), indexVscp);
AstNodeExpr* const alhsp = new AstVarRef{fl, tov.varScopep(), VAccess::WRITE};
AstNodeExpr* const arhsp = select(fl, tov.tabeVarScopep(), indexVscp);
AstNode* outsetp = m_assignDly
? static_cast<AstNode*>(new AstAssignDly{fl, alhsp, arhsp})
: static_cast<AstNode*>(new AstAssign{fl, alhsp, arhsp});
@ -369,7 +369,7 @@ private:
if (tov.mayBeUnassigned()) {
V3Number outputChgMask{nodep, static_cast<int>(m_outVarps.size()), 0};
outputChgMask.setBit(tov.ord(), 1);
AstNode* const condp
AstNodeExpr* const condp
= new AstAnd{fl, select(fl, outputAssignedTableVscp, indexVscp),
new AstConst{fl, outputChgMask}};
outsetp = new AstIf{fl, condp, outsetp};

View File

@ -435,7 +435,7 @@ private:
for (const auto& itr : tconnects) {
AstVar* const portp = itr.first;
AstArg* const argp = itr.second;
AstNode* const pinp = argp->exprp();
AstNodeExpr* const pinp = argp->exprp();
portp->unlinkFrBack();
pushDeletep(portp); // Remove it from the clone (not original)
if (!pinp) {
@ -564,7 +564,7 @@ private:
const V3TaskConnects tconnects = V3Task::taskConnects(refp, refp->taskp()->stmtsp());
for (const auto& itr : tconnects) {
AstVar* const portp = itr.first;
AstNode* const pinp = itr.second->exprp();
AstNodeExpr* const pinp = itr.second->exprp();
if (!pinp) {
// Too few arguments in function call
} else {
@ -615,7 +615,7 @@ private:
if (refp->taskp()->dpiContext()) {
// __Vscopep
AstNode* const snp = refp->scopeNamep()->unlinkFrBack();
AstScopeName* const snp = refp->scopeNamep()->unlinkFrBack();
UASSERT_OBJ(snp, refp, "Missing scoping context");
ccallp->addArgsp(snp);
// __Vfilenamep
@ -630,7 +630,7 @@ private:
for (AstNode* pinp = refp->pinsp(); pinp; pinp = nextpinp) {
nextpinp = pinp->nextp();
// Move pin to the CCall, removing all Arg's
AstNode* const exprp = VN_AS(pinp, Arg)->exprp();
AstNodeExpr* const exprp = VN_AS(pinp, Arg)->exprp();
exprp->unlinkFrBack();
ccallp->addArgsp(exprp);
}
@ -721,7 +721,7 @@ private:
AstNode* newp = nullptr;
const int widthWords = portp->basicp()->widthWords();
for (int i = 0; i < total; ++i) {
AstNode* srcp = new AstVarRef(portvscp->fileline(), portvscp, VAccess::WRITE);
AstNodeExpr* srcp = new AstVarRef(portvscp->fileline(), portvscp, VAccess::WRITE);
// extract a scalar from multi-dimensional array (internal format)
for (auto&& dimStride : dimStrides) {
const size_t dimIdx = (i / dimStride.second) % dimStride.first->elementsConst();
@ -744,7 +744,7 @@ private:
from += "[" + cvtToStr(i * coef) + "]";
}
from += ket;
AstNode* const rhsp = new AstSel(
AstNodeExpr* const rhsp = new AstSel(
portp->fileline(), new AstCExpr(portp->fileline(), from, cwidth, false), 0,
portp->width());
stmtp = new AstAssign(portp->fileline(), srcp, rhsp);
@ -1629,7 +1629,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp)
for (int i = 0; i < tpinnum; ++i) {
AstVar* const portp = tconnects[i].first;
if (!tconnects[i].second || !tconnects[i].second->exprp()) {
AstNode* newvaluep = nullptr;
AstNodeExpr* newvaluep = nullptr;
if (!portp->valuep()) {
nodep->v3error("Missing argument on non-defaulted argument "
<< portp->prettyNameQ() << " in function call to "
@ -1639,7 +1639,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp)
// The default value for this port might be a constant
// expression that hasn't been folded yet. Try folding it
// now; we don't have much to lose if it fails.
newvaluep = V3Const::constifyParamsEdit(portp->valuep());
newvaluep = V3Const::constifyParamsEdit(VN_AS(portp->valuep(), NodeExpr));
if (!VN_IS(newvaluep, Const)) {
// Problem otherwise is we might have a varref, task
// call, or something else that only makes sense in the
@ -1653,7 +1653,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp)
newvaluep = newvaluep->cloneTree(true);
}
} else {
newvaluep = portp->valuep()->cloneTree(true);
newvaluep = VN_AS(portp->valuep(), NodeExpr)->cloneTree(true);
}
// To avoid problems with callee needing to know to deleteTree
// or not, we make this into a pin

View File

@ -91,7 +91,7 @@ private:
// to this sentree
// Ast{NodeProcedure,CFunc,Begin}::user2() -> bool. Set true if process/task is
// suspendable
// AstSenTree::user2() -> AstText*. Debug info passed to the
// AstSenTree::user2() -> AstCExpr*. Debug info passed to the
// timing schedulers
// Ast{NodeProcedure,CFunc,Begin}::user3() -> DependencyVertex*. Vertex in m_depGraph
const VNUser1InUse m_user1InUse;
@ -286,24 +286,29 @@ private:
return VN_AS(sensesp->user1p(), VarScope);
}
// Creates a string describing the sentree
AstText* createEventDescription(AstSenTree* const sensesp) const {
AstCExpr* createEventDescription(AstSenTree* const sensesp) const {
if (!sensesp->user2p()) {
std::stringstream ss;
ss << '"';
V3EmitV::verilogForTree(sensesp, ss);
ss << '"';
auto* const commentp = new AstText{sensesp->fileline(), ss.str()};
auto* const commentp = new AstCExpr{sensesp->fileline(), ss.str(), 0};
commentp->dtypeSetString();
sensesp->user2p(commentp);
return commentp;
}
return VN_AS(sensesp->user2p(), Text)->cloneTree(false);
return VN_AS(sensesp->user2p(), CExpr)->cloneTree(false);
}
// Adds debug info to a hardcoded method call
void addDebugInfo(AstCMethodHard* const methodp) const {
if (v3Global.opt.protectIds()) return;
FileLine* const flp = methodp->fileline();
methodp->addPinsp(new AstText{flp, '"' + flp->filename() + '"'});
methodp->addPinsp(new AstText{flp, cvtToStr(flp->lineno())});
AstCExpr* const ap = new AstCExpr{flp, '"' + flp->filename() + '"', 0};
ap->dtypeSetString();
methodp->addPinsp(ap);
AstCExpr* const bp = new AstCExpr{flp, cvtToStr(flp->lineno()), 0};
bp->dtypeSetString();
methodp->addPinsp(bp);
}
// Adds debug info to a trigSched.trigger() call
void addEventDebugInfo(AstCMethodHard* const methodp, AstSenTree* const sensesp) const {
@ -491,7 +496,7 @@ private:
}
void visit(AstDelay* nodep) override {
FileLine* const flp = nodep->fileline();
AstNode* valuep = V3Const::constifyEdit(nodep->lhsp()->unlinkFrBack());
AstNodeExpr* valuep = V3Const::constifyEdit(nodep->lhsp()->unlinkFrBack());
auto* const constp = VN_CAST(valuep, Const);
if (constp && constp->isZero()) {
nodep->v3warn(ZERODLY, "Unsupported: #0 delays do not schedule process resumption in "
@ -632,7 +637,8 @@ private:
// do that. These intra-assignment vars will later be passed to forked processes by value.
AstNode* const insertBeforep = VN_IS(m_procp, CFunc) ? controlp : nullptr;
// Function for replacing values with intermediate variables
const auto replaceWithIntermediate = [&](AstNode* const valuep, const std::string& name) {
const auto replaceWithIntermediate = [&](AstNodeExpr* const valuep,
const std::string& name) {
AstVarScope* const newvscp = createTemp(flp, name, valuep->dtypep(), insertBeforep);
valuep->replaceWith(new AstVarRef{flp, newvscp, VAccess::READ});
controlp->addHereThisAsNext(
@ -665,7 +671,7 @@ private:
// TODO: Find a way to do this without introducing this var. Perhaps make
// V3SchedAcyclic recognize awaits and prevent it from treating this kind of logic as
// cyclic
AstNode* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
std::string varname;
if (auto* const refp = VN_CAST(lhsp, VarRef)) {
varname = m_contAssignVarNames.get(refp->name());
@ -696,7 +702,7 @@ private:
FileLine* const flp = nodep->fileline();
AstNode* const stmtsp = nodep->stmtsp();
if (stmtsp) stmtsp->unlinkFrBackWithNext();
AstNode* const condp = V3Const::constifyEdit(nodep->condp()->unlinkFrBack());
AstNodeExpr* const condp = V3Const::constifyEdit(nodep->condp()->unlinkFrBack());
auto* const constp = VN_CAST(condp, Const);
if (constp) {
condp->v3warn(WAITCONST, "Wait statement condition is constant");

View File

@ -421,7 +421,7 @@ private:
graphSimplify(false);
}
AstNode* selectActivity(FileLine* flp, uint32_t acode, const VAccess& access) {
AstNodeExpr* selectActivity(FileLine* flp, uint32_t acode, const VAccess& access) {
return new AstArraySel(flp, new AstVarRef(flp, m_activityVscp, access), acode);
}
@ -667,12 +667,12 @@ private:
if (!prevActSet || actSet != *prevActSet) {
FileLine* const flp = m_topScopep->fileline();
const bool always = actSet.count(TraceActivityVertex::ACTIVITY_ALWAYS) != 0;
AstNode* condp = nullptr;
AstNodeExpr* condp = nullptr;
if (always) {
condp = new AstConst(flp, 1); // Always true, will be folded later
} else {
for (const uint32_t actCode : actSet) {
AstNode* const selp = selectActivity(flp, actCode, VAccess::READ);
AstNodeExpr* const selp = selectActivity(flp, actCode, VAccess::READ);
condp = condp ? new AstOr(flp, condp, selp) : selp;
}
}

View File

@ -128,7 +128,7 @@ private:
};
std::vector<Signal> m_signals; // Signals under current scope
AstVarScope* m_traVscp = nullptr; // Current AstVarScope we are constructing AstTraceDecls for
AstNode* m_traValuep = nullptr; // Value expression for current signal
AstNodeExpr* m_traValuep = nullptr; // Value expression for current signal
string m_traName; // Name component for current signal
VDouble0 m_statSigs; // Statistic tracking

View File

@ -465,7 +465,7 @@ class TristateVisitor final : public TristateBaseVisitor {
AstConst* const newp = new AstConst{nodep->fileline(), num};
return newp;
}
AstNode* getEnp(AstNode* nodep) {
AstNodeExpr* getEnp(AstNode* nodep) {
if (nodep->user1p()) {
if (AstVarRef* const refp = VN_CAST(nodep, VarRef)) {
if (refp->varp()->isIO()) {
@ -480,7 +480,7 @@ class TristateVisitor final : public TristateBaseVisitor {
nodep->user1p(newAllZerosOrOnes(nodep, true));
}
// Otherwise return the previous output enable
return nodep->user1p();
return VN_AS(nodep->user1p(), NodeExpr);
}
AstVar* getCreateEnVarp(AstVar* invarp) {
// Return the master __en for the specified input variable
@ -501,7 +501,7 @@ class TristateVisitor final : public TristateBaseVisitor {
numz0.opNot(numz); // Z->0, else 1
return new AstConst{fl, numz0};
}
AstNode* getEnExprBasedOnOriginalp(AstNode* const nodep) {
AstNodeExpr* getEnExprBasedOnOriginalp(AstNodeExpr* const nodep) {
if (AstVarRef* const varrefp = VN_CAST(nodep, VarRef)) {
return new AstVarRef{varrefp->fileline(), getCreateEnVarp(varrefp->varp()),
VAccess::READ};
@ -514,17 +514,17 @@ class TristateVisitor final : public TristateBaseVisitor {
// whole extend.
// Unlink lhsp before copying to save unnecessary copy of lhsp
AstNode* const lhsp = extendp->lhsp()->unlinkFrBack();
AstNodeExpr* const lhsp = extendp->lhsp()->unlinkFrBack();
AstExtend* const enExtendp = extendp->cloneTree(false);
extendp->lhsp(lhsp);
AstNode* const enLhsp = getEnExprBasedOnOriginalp(lhsp);
AstNodeExpr* const enLhsp = getEnExprBasedOnOriginalp(lhsp);
enExtendp->lhsp(new AstNot{enLhsp->fileline(), enLhsp});
return new AstNot{enExtendp->fileline(), enExtendp};
} else if (AstSel* const selp = VN_CAST(nodep, Sel)) {
AstNode* const fromp = selp->fromp()->unlinkFrBack();
AstNodeExpr* const fromp = selp->fromp()->unlinkFrBack();
AstSel* const enSelp = selp->cloneTree(false);
selp->fromp(fromp);
AstNode* const enFromp = getEnExprBasedOnOriginalp(fromp);
AstNodeExpr* const enFromp = getEnExprBasedOnOriginalp(fromp);
enSelp->fromp(enFromp);
return enSelp;
} else {
@ -566,10 +566,10 @@ class TristateVisitor final : public TristateBaseVisitor {
}
}
AstNode* newEnableDeposit(AstSel* selp, AstNode* enp) {
AstNodeExpr* newEnableDeposit(AstSel* selp, AstNodeExpr* enp) {
// Form a "deposit" instruction for given enable, using existing select as a template.
// Would be nicer if we made this a new AST type
AstNode* const newp = new AstShiftL(
AstNodeExpr* const newp = new AstShiftL(
selp->fileline(), new AstExtend(selp->fileline(), enp, selp->fromp()->width()),
selp->lsbp()->cloneTree(false), selp->fromp()->width());
return newp;
@ -659,8 +659,8 @@ class TristateVisitor final : public TristateBaseVisitor {
// For each driver seperate variables (normal and __en) are created and initialized with
// values. In case of normal variable, the original expression is reused. Their values are
// aggregated using | to form one expression, which are assigned to varp end envarp.
AstNode* orp = nullptr;
AstNode* enp = nullptr;
AstNodeExpr* orp = nullptr;
AstNodeExpr* enp = nullptr;
for (auto it = beginStrength; it != endStrength; it++) {
AstVarRef* refp = it->m_varrefp;
@ -689,14 +689,14 @@ class TristateVisitor final : public TristateBaseVisitor {
nodep->addStmtsp(enLhspAssignp);
// now append this driver to the driver logic.
AstNode* const ref1p = new AstVarRef{refp->fileline(), newLhsp, VAccess::READ};
AstNode* const ref2p = new AstVarRef{refp->fileline(), newEnLhsp, VAccess::READ};
AstNode* const andp = new AstAnd{refp->fileline(), ref1p, ref2p};
AstNodeExpr* const ref1p = new AstVarRef{refp->fileline(), newLhsp, VAccess::READ};
AstNodeExpr* const ref2p = new AstVarRef{refp->fileline(), newEnLhsp, VAccess::READ};
AstNodeExpr* const andp = new AstAnd{refp->fileline(), ref1p, ref2p};
// or this to the others
orp = (!orp) ? andp : new AstOr{refp->fileline(), orp, andp};
AstNode* const ref3p = new AstVarRef{refp->fileline(), newEnLhsp, VAccess::READ};
AstNodeExpr* const ref3p = new AstVarRef{refp->fileline(), newEnLhsp, VAccess::READ};
enp = (!enp) ? ref3p : new AstOr{ref3p->fileline(), enp, ref3p};
}
AstNode* const assp = new AstAssignW{
@ -742,8 +742,8 @@ class TristateVisitor final : public TristateBaseVisitor {
envarp = VN_AS(invarp->user1p(), Var); // From CASEEQ, foo === 1'bz
}
AstNode* orp = nullptr;
AstNode* enp = nullptr;
AstNodeExpr* orp = nullptr;
AstNodeExpr* enp = nullptr;
const int w = lhsp->width();
std::sort(refsp->begin(), refsp->end(),
@ -774,7 +774,7 @@ class TristateVisitor final : public TristateBaseVisitor {
aggregateTriSameStrength(nodep, varStrengthp, enVarStrengthp, beginStrength,
endStrength);
AstNode* exprCurrentStrengthp;
AstNodeExpr* exprCurrentStrengthp;
if (enp) {
// If weaker driver should be overwritten by a stronger, replace its value with z
exprCurrentStrengthp
@ -785,7 +785,7 @@ class TristateVisitor final : public TristateBaseVisitor {
}
orp = (!orp) ? exprCurrentStrengthp : new AstOr{fl, orp, exprCurrentStrengthp};
AstNode* enVarStrengthRefp = new AstVarRef{fl, enVarStrengthp, VAccess::READ};
AstNodeExpr* enVarStrengthRefp = new AstVarRef{fl, enVarStrengthp, VAccess::READ};
enp = (!enp) ? enVarStrengthRefp : new AstOr{fl, enp, enVarStrengthRefp};
@ -798,7 +798,7 @@ class TristateVisitor final : public TristateBaseVisitor {
const AstPull* const pullp = static_cast<AstPull*>(lhsp->user3p());
bool pull1 = pullp && pullp->direction() == 1; // Else default is down
AstNode* undrivenp;
AstNodeExpr* undrivenp;
if (envarp) {
undrivenp = new AstNot{envarp->fileline(),
new AstVarRef{envarp->fileline(), envarp, VAccess::READ}};
@ -1033,20 +1033,20 @@ class TristateVisitor final : public TristateBaseVisitor {
// expression 1 or 2 have an output enable '__en' signal. If the
// condition has an enable, not sure what to do, so generate an
// error.
AstNode* const condp = nodep->condp();
AstNodeExpr* const condp = nodep->condp();
if (condp->user1p()) {
condp->v3warn(E_UNSUPPORTED, "Unsupported: don't know how to deal with "
"tristate logic in the conditional expression");
}
AstNode* const thenp = nodep->thenp();
AstNode* const elsep = nodep->elsep();
AstNodeExpr* const thenp = nodep->thenp();
AstNodeExpr* const elsep = nodep->elsep();
if (thenp->user1p() || elsep->user1p()) { // else no tristates
m_tgraph.didProcess(nodep);
AstNode* const en1p = getEnp(thenp);
AstNode* const en2p = getEnp(elsep);
AstNodeExpr* const en1p = getEnp(thenp);
AstNodeExpr* 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
AstNodeExpr* 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)
@ -1069,7 +1069,8 @@ class TristateVisitor final : public TristateBaseVisitor {
UINFO(9, dbgState() << nodep << endl);
if (nodep->user1p()) {
// Form a "deposit" instruction. Would be nicer if we made this a new AST type
AstNode* const newp = newEnableDeposit(nodep, nodep->user1p());
AstNodeExpr* const newp
= newEnableDeposit(nodep, VN_AS(nodep->user1p(), NodeExpr));
nodep->fromp()->user1p(newp); // Push to varref (etc)
if (debug() >= 9) newp->dumpTree(cout, "-assign-sel; ");
m_tgraph.didProcess(nodep);
@ -1083,8 +1084,8 @@ class TristateVisitor final : public TristateBaseVisitor {
<< nodep->prettyTypeName());
}
if (nodep->fromp()->user1p()) { // SEL(VARREF, lsb)
AstNode* const en1p = getEnp(nodep->fromp());
AstNode* const enp
AstNodeExpr* const en1p = getEnp(nodep->fromp());
AstNodeExpr* const enp
= new AstSel(nodep->fileline(), en1p, nodep->lsbp()->cloneTree(true),
nodep->widthp()->cloneTree(true));
UINFO(9, " newsel " << enp << endl);
@ -1110,7 +1111,7 @@ class TristateVisitor final : public TristateBaseVisitor {
UINFO(9, dbgState() << nodep << endl);
if (nodep->user1p()) {
// Each half of the concat gets a select of the enable expression
AstNode* const enp = nodep->user1p();
AstNodeExpr* const enp = VN_AS(nodep->user1p(), NodeExpr);
nodep->user1p(nullptr);
nodep->lhsp()->user1p(new AstSel(nodep->fileline(), enp->cloneTree(true),
nodep->rhsp()->width(),
@ -1125,13 +1126,13 @@ class TristateVisitor final : public TristateBaseVisitor {
UINFO(9, dbgState() << nodep << endl);
// Generate the new output enable signal, just as a concat
// identical to the data concat
AstNode* const expr1p = nodep->lhsp();
AstNode* const expr2p = nodep->rhsp();
AstNodeExpr* const expr1p = nodep->lhsp();
AstNodeExpr* const expr2p = nodep->rhsp();
if (expr1p->user1p() || expr2p->user1p()) { // else no tristates
m_tgraph.didProcess(nodep);
AstNode* const en1p = getEnp(expr1p);
AstNode* const en2p = getEnp(expr2p);
AstNode* const enp = new AstConcat(nodep->fileline(), en1p, en2p);
AstNodeExpr* const en1p = getEnp(expr1p);
AstNodeExpr* const en2p = getEnp(expr2p);
AstNodeExpr* const enp = new AstConcat(nodep->fileline(), en1p, en2p);
UINFO(9, " newconc " << enp << endl);
nodep->user1p(enp); // propagate up CONCAT(lhsp->enable, rhsp->enable)
expr1p->user1p(nullptr);
@ -1156,10 +1157,10 @@ class TristateVisitor final : public TristateBaseVisitor {
return;
}
m_tgraph.didProcess(nodep);
AstNode* const expr1p = nodep->lhsp()->unlinkFrBack();
AstNode* const expr2p = nodep->rhsp()->unlinkFrBack();
AstNode* enp;
if (AstNode* const en2p = expr2p->user1p()) {
AstNodeExpr* const expr1p = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const expr2p = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* enp;
if (AstNodeExpr* const en2p = VN_AS(expr2p->user1p(), NodeExpr)) {
enp = new AstAnd(nodep->fileline(), expr1p, en2p);
} else {
enp = expr1p;
@ -1199,22 +1200,22 @@ class TristateVisitor final : public TristateBaseVisitor {
// have to define what is means to OR 1'bz with other
// expressions. Here I take the approach that when one expression
// is 0, that is passes the other.
AstNode* const expr1p = nodep->lhsp();
AstNode* const expr2p = nodep->rhsp();
AstNodeExpr* const expr1p = nodep->lhsp();
AstNodeExpr* const expr2p = nodep->rhsp();
if (!expr1p->user1p() && !expr2p->user1p()) {
return; // no tristates in either expression, so nothing to do
}
m_tgraph.didProcess(nodep);
AstNode* const en1p = getEnp(expr1p);
AstNode* const en2p = getEnp(expr2p);
AstNode* subexpr1p = expr1p->cloneTree(false);
AstNode* subexpr2p = expr2p->cloneTree(false);
AstNodeExpr* const en1p = getEnp(expr1p);
AstNodeExpr* const en2p = getEnp(expr2p);
AstNodeExpr* subexpr1p = expr1p->cloneTree(false);
AstNodeExpr* subexpr2p = expr2p->cloneTree(false);
if (isAnd) {
subexpr1p = new AstNot(nodep->fileline(), subexpr1p);
subexpr2p = new AstNot(nodep->fileline(), subexpr2p);
}
// calc new output enable
AstNode* const enp = new AstOr(
AstNodeExpr* const enp = new AstOr(
nodep->fileline(), new AstAnd(nodep->fileline(), en1p, en2p),
new AstOr(nodep->fileline(),
new AstAnd(nodep->fileline(), en1p->cloneTree(false), subexpr1p),
@ -1301,12 +1302,12 @@ class TristateVisitor final : public TristateBaseVisitor {
AstConst* const constp = VN_CAST(nodep->lhsp(), Const);
if (constp && constp->user1p()) {
// 3'b1z0 -> ((3'b101 == in__en) && (3'b100 == in))
AstNode* const rhsp = nodep->rhsp();
AstNodeExpr* const rhsp = nodep->rhsp();
rhsp->unlinkFrBack();
FileLine* const fl = nodep->fileline();
AstNode* enRhsp;
AstNodeExpr* enRhsp;
if (rhsp->user1p()) {
enRhsp = rhsp->user1p();
enRhsp = VN_AS(rhsp->user1p(), NodeExpr);
rhsp->user1p(nullptr);
} else {
enRhsp = getEnExprBasedOnOriginalp(rhsp);
@ -1315,7 +1316,7 @@ class TristateVisitor final : public TristateBaseVisitor {
= VN_AS(constp->user1p(), Const)
->num(); // visit(AstConst) already split into en/ones
const V3Number& oneIfEnOne = constp->num();
AstNode* newp
AstNodeExpr* newp
= new AstLogAnd{fl, new AstEq{fl, new AstConst{fl, oneIfEn}, enRhsp},
// Keep the caseeq if there are X's present
new AstEqCase{fl, new AstConst{fl, oneIfEnOne}, rhsp}};
@ -1328,11 +1329,12 @@ class TristateVisitor final : public TristateBaseVisitor {
} else if (constp && nodep->rhsp()->user1p()) {
FileLine* const fl = nodep->fileline();
constp->unlinkFrBack();
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* newp = new AstLogAnd{
fl, new AstEq{fl, newAllZerosOrOnes(constp, false), rhsp->user1p()},
// Keep the caseeq if there are X's present
new AstEqCase{fl, constp, rhsp}};
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* newp = new AstLogAnd{fl,
new AstEq{fl, newAllZerosOrOnes(constp, false),
VN_AS(rhsp->user1p(), NodeExpr)},
// Keep the caseeq if there are X's present
new AstEqCase{fl, constp, rhsp}};
if (neq) newp = new AstLogNot{fl, newp};
rhsp->user1p(nullptr);
UINFO(9, " newceq " << newp << endl);
@ -1376,7 +1378,7 @@ class TristateVisitor final : public TristateBaseVisitor {
if (!dropop[1]) iterateAndNextNull(nodep->thsp());
if (!dropop[2]) iterateAndNextNull(nodep->fhsp());
} else {
AstNode* nonXp = nullptr;
AstNodeExpr* nonXp = nullptr;
if (!dropop[0]) {
nonXp = nodep->rhsp();
} else if (!dropop[1]) {
@ -1400,7 +1402,7 @@ class TristateVisitor final : public TristateBaseVisitor {
UINFO(4, " COUNTBITS('z)-> " << nodep << endl);
VNRelinker relinkHandle;
nodep->unlinkFrBack(&relinkHandle);
AstNode* newp = new AstCountOnes(
AstNodeExpr* newp = new AstCountOnes(
nodep->fileline(), new AstVarRef(nodep->fileline(), envarp, VAccess::READ));
if (nonXp) { // Need to still count '0 or '1 or 'x's
if (dropop[0]) {
@ -1545,7 +1547,7 @@ class TristateVisitor final : public TristateBaseVisitor {
// Therefore, create the enable, output and separate input pin,
// then pinReconnectSimple all
// Create the output enable pin, connect to new signal
AstNode* enrefp;
AstNodeExpr* enrefp;
{
AstVar* const enVarp = new AstVar(nodep->fileline(), VVarType::MODULETEMP,
nodep->name() + "__en" + cvtToStr(m_unique++),
@ -1580,8 +1582,8 @@ class TristateVisitor final : public TristateBaseVisitor {
<< nodep->prettyNameQ());
}
} else {
AstNode* const outexprp
= nodep->exprp()->cloneTree(false); // Note has lvalue() set
AstNodeExpr* const outexprp
= VN_AS(nodep->exprp(), NodeExpr)->cloneTree(false); // Note has lvalue() set
outpinp = new AstPin(nodep->fileline(), nodep->pinNum(),
outModVarp->name(), // should be {var}"__out"
outexprp);

View File

@ -68,7 +68,7 @@ private:
// METHODS
void replaceBoundLvalue(AstNode* nodep, AstNode* condp) {
void replaceBoundLvalue(AstNodeExpr* nodep, AstNodeExpr* condp) {
// Spec says a out-of-range LHS SEL results in a NOP.
// This is a PITA. We could:
// 1. IF(...) around an ASSIGN,
@ -101,11 +101,11 @@ private:
m_assigndlyp->replaceWith(newp);
VL_DO_CLEAR(pushDeletep(m_assigndlyp), m_assigndlyp = nullptr);
}
AstNode* prep = nodep;
AstNodeExpr* prep = nodep;
// Scan back to put the condlvalue above all selects (IE top of the lvalue)
while (VN_IS(prep->backp(), NodeSel) || VN_IS(prep->backp(), Sel)) {
prep = prep->backp();
prep = VN_AS(prep->backp(), NodeExpr);
}
FileLine* const fl = nodep->fileline();
VL_DANGLING(nodep); // Zap it so we don't use it by mistake - use prep
@ -115,8 +115,8 @@ private:
if (const AstIf* const ifp = VN_AS(prep->user2p(), If)) {
UASSERT_OBJ(!needDly, prep, "Should have already converted to non-delay");
VNRelinker replaceHandle;
AstNode* const earliercondp = ifp->condp()->unlinkFrBack(&replaceHandle);
AstNode* const newp = new AstLogAnd(condp->fileline(), condp, earliercondp);
AstNodeExpr* const earliercondp = ifp->condp()->unlinkFrBack(&replaceHandle);
AstNodeExpr* const newp = new AstLogAnd(condp->fileline(), condp, earliercondp);
UINFO(4, "Edit BOUNDLVALUE " << newp << endl);
replaceHandle.relink(newp);
} else {
@ -207,9 +207,9 @@ private:
VL_DO_DANGLING(V3Const::constifyEdit(nodep), nodep);
return;
} else {
AstNode* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* newp;
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* newp;
// If we got ==1'bx it can never be true (but 1'bx==1'bx can be!)
if (((VN_IS(lhsp, Const) && VN_AS(lhsp, Const)->num().isFourState())
|| (VN_IS(rhsp, Const) && VN_AS(rhsp, Const)->num().isFourState()))) {
@ -239,9 +239,9 @@ private:
VL_DO_DANGLING(V3Const::constifyEdit(nodep), nodep);
return;
} else {
AstNode* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* newp;
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* newp;
if (!VN_IS(rhsp, Const)) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: RHS of ==? or !=? must be "
"constant to be synthesizable"); // Says spec.
@ -253,9 +253,9 @@ private:
nummask.opBitsNonX(VN_AS(rhsp, Const)->num());
V3Number numval(rhsp, rhsp->width());
numval.opBitsOne(VN_AS(rhsp, Const)->num());
AstNode* const and1p = new AstAnd(nodep->fileline(), lhsp,
new AstConst(nodep->fileline(), nummask));
AstNode* const and2p = new AstConst(nodep->fileline(), numval);
AstNodeExpr* const and1p = new AstAnd(nodep->fileline(), lhsp,
new AstConst(nodep->fileline(), nummask));
AstNodeExpr* const and2p = new AstConst(nodep->fileline(), numval);
if (VN_IS(nodep, EqWild)) {
newp = new AstEq(nodep->fileline(), and1p, and2p);
} else {
@ -290,7 +290,7 @@ private:
dropop[2] = VN_IS(nodep->fhsp(), Const) && VN_AS(nodep->fhsp(), Const)->num().isAnyX();
UINFO(4, " COUNTBITS(" << dropop[0] << dropop[1] << dropop[2] << " " << nodep << endl);
AstNode* nonXp = nullptr;
AstNodeExpr* nonXp = nullptr;
if (!dropop[0]) {
nonXp = nodep->rhsp();
} else if (!dropop[1]) {
@ -394,10 +394,11 @@ private:
if (debug() >= 9) nodep->dumpTree(cout, "sel_old: ");
// If (maxmsb >= selected), we're in bound
AstNode* condp = new AstGte(nodep->fileline(),
new AstConst(nodep->fileline(), AstConst::WidthedValue(),
nodep->lsbp()->width(), maxmsb),
nodep->lsbp()->cloneTree(false));
AstNodeExpr* condp
= new AstGte(nodep->fileline(),
new AstConst(nodep->fileline(), AstConst::WidthedValue(),
nodep->lsbp()->width(), maxmsb),
nodep->lsbp()->cloneTree(false));
// See if the condition is constant true (e.g. always in bound due to constant select)
// Note below has null backp(); the Edit function knows how to deal with that.
condp = V3Const::constifyEdit(condp);
@ -452,10 +453,11 @@ private:
if (debug() >= 9) nodep->dumpTree(cout, "arraysel_old: ");
// See if the condition is constant true
AstNode* condp = new AstGte(nodep->fileline(),
new AstConst(nodep->fileline(), AstConst::WidthedValue(),
nodep->bitp()->width(), declElements - 1),
nodep->bitp()->cloneTree(false));
AstNodeExpr* condp
= new AstGte(nodep->fileline(),
new AstConst(nodep->fileline(), AstConst::WidthedValue(),
nodep->bitp()->width(), declElements - 1),
nodep->bitp()->cloneTree(false));
// Note below has null backp(); the Edit function knows how to deal with that.
condp = V3Const::constifyEdit(condp);
if (condp->isOne()) {
@ -483,8 +485,8 @@ private:
} else if (!lvalue) { // Mid-multidimension read, just use zero
// ARRAYSEL(...) -> ARRAYSEL(COND(LT(bit<maxbit), bit, 0))
VNRelinker replaceHandle;
AstNode* const bitp = nodep->bitp()->unlinkFrBack(&replaceHandle);
AstNode* const newp = new AstCondBound(
AstNodeExpr* const bitp = nodep->bitp()->unlinkFrBack(&replaceHandle);
AstNodeExpr* const newp = new AstCondBound(
bitp->fileline(), condp, bitp,
new AstConst(bitp->fileline(), AstConst::WidthedValue(), bitp->width(), 0));
// Added X's, tristate them too

View File

@ -770,22 +770,10 @@ private:
iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH);
V3Const::constifyParamsEdit(nodep->rhsp()); // rhsp may change
const AstConst* const constp = VN_CAST(nodep->rhsp(), Const);
AstBasicDType* const basicp = VN_CAST(nodep->rhsp(), BasicDType);
if (!constp && !basicp) {
nodep->v3error("Slice size isn't a constant or basic data type.");
return;
}
if (basicp) { // Convert data type to a constant size
AstConst* const newp = new AstConst(basicp->fileline(), basicp->width());
nodep->rhsp()->replaceWith(newp);
pushDeletep(basicp);
if (const AstConst* const constp = VN_CAST(nodep->rhsp(), Const)) {
if (constp->toUInt() == 0) nodep->v3error("Slice size cannot be zero.");
} else {
const uint32_t sliceSize = constp->toUInt();
if (!sliceSize) {
nodep->v3error("Slice size cannot be zero.");
return;
}
nodep->v3error("Slice size isn't a constant or basic data type.");
}
nodep->dtypeSetLogicUnsized(nodep->lhsp()->width(), nodep->lhsp()->widthMin(),
VSigning::UNSIGNED);
@ -1444,8 +1432,8 @@ private:
if (VN_IS(dtypep, QueueDType)) {
switch (nodep->attrType()) {
case VAttrType::DIM_SIZE: {
AstNode* const newp = new AstCMethodHard(
nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size");
AstNodeExpr* const fromp = VN_AS(nodep->fromp()->unlinkFrBack(), NodeExpr);
AstNode* const newp = new AstCMethodHard{nodep->fileline(), fromp, "size"};
newp->dtypeSetSigned32();
newp->didWidth(true);
newp->protect(false);
@ -1462,8 +1450,9 @@ private:
}
case VAttrType::DIM_RIGHT:
case VAttrType::DIM_HIGH: {
AstNode* const sizep = new AstCMethodHard(
nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size");
AstNodeExpr* const fromp = VN_AS(nodep->fromp()->unlinkFrBack(), NodeExpr);
AstNodeExpr* const sizep
= new AstCMethodHard{nodep->fileline(), fromp, "size"};
sizep->dtypeSetSigned32();
sizep->didWidth(true);
sizep->protect(false);
@ -1475,7 +1464,7 @@ private:
break;
}
case VAttrType::DIM_INCREMENT: {
AstNode* const newp
AstNodeExpr* const newp
= new AstConst(nodep->fileline(), AstConst::Signed32(), -1);
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
@ -1493,9 +1482,9 @@ private:
if (!nodep->dimp() || msbdim < 1) {
if (VN_IS(dtypep, BasicDType) && dtypep->basicp()->isString()) {
// IEEE undocumented but $bits(string) must give length(string) * 8
AstNodeExpr* const fromp = VN_AS(nodep->fromp()->unlinkFrBack(), NodeExpr);
AstNode* const newp = new AstShiftL{
nodep->fileline(),
new AstLenN{nodep->fileline(), nodep->fromp()->unlinkFrBack()},
nodep->fileline(), new AstLenN{nodep->fileline(), fromp},
new AstConst{nodep->fileline(), 3}, // * 8
32};
nodep->replaceWith(newp);
@ -1516,8 +1505,8 @@ private:
} else { // Need a runtime lookup table. Yuk.
UASSERT_OBJ(nodep->fromp() && dtypep, nodep, "Unsized expression");
AstVar* const varp = dimensionVarp(dtypep, nodep->attrType(), msbdim);
AstNode* const dimp = nodep->dimp()->unlinkFrBack();
AstNode* const newp
AstNodeExpr* const dimp = nodep->dimp()->unlinkFrBack();
AstNodeExpr* const newp
= new AstArraySel{nodep->fileline(), newVarRefDollarUnit(varp), dimp};
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
@ -1610,7 +1599,7 @@ private:
newp = new AstUnpackArrayDType(
nodep->fileline(), VFlagChildDType(), childp,
new AstRange(nodep->fileline(), new AstConst(elementsp->fileline(), 0),
new AstSub(elementsp->fileline(), elementsp,
new AstSub(elementsp->fileline(), VN_AS(elementsp, NodeExpr),
new AstConst(elementsp->fileline(), 1))));
}
nodep->replaceWith(newp);
@ -1769,7 +1758,7 @@ private:
UASSERT_OBJ(enumDtp, nodep, "$cast determined as enum, but not enum type");
const uint64_t maxval = enumMaxValue(nodep, enumDtp);
const bool assoc = maxval > ENUM_LOOKUP_BITS;
AstNode* testp = nullptr;
AstNodeExpr* testp = nullptr;
FileLine* const fl_novalue = new FileLine{fl};
fl_novalue->warnOff(V3ErrorCode::ENUMVALUE, true);
if (assoc) {
@ -1881,7 +1870,7 @@ private:
// For now, replace it ASAP, so widthing can propagate easily
// The cast may change signing, but we don't know the sign yet. Make it so.
// Note we don't sign fromp() that would make the algorithm O(n^2) if lots of casting.
AstNode* newp = nullptr;
AstNodeExpr* newp = nullptr;
if (bad) {
} else if (const AstBasicDType* const basicp = toDtp->basicp()) {
if (!basicp->isDouble() && !fromDtp->isDouble()) {
@ -1942,10 +1931,9 @@ private:
void visit(AstCastSize* nodep) override {
// IEEE: Signedness of result is same as self-determined signedness
// However, the result is same as BITSEL, so we do not sign extend the LHS
UASSERT_OBJ(VN_IS(nodep->rhsp(), Const), nodep, "Unsupported: Non-const cast of size");
// if (debug()) nodep->dumpTree(cout, " CastSizePre: ");
if (m_vup->prelim()) {
int width = VN_AS(nodep->rhsp(), Const)->toSInt();
int width = nodep->rhsp()->toSInt();
if (width < 1) {
nodep->v3error("Size-changing cast to zero or negative size");
width = 1;
@ -1996,7 +1984,8 @@ private:
: nodep->findBitDType(width, width, underDtp->numeric()));
nodep->dtypep(outDtp);
// We ignore warnings as that is sort of the point of a cast
widthCheckSized(nodep, "Cast expr", underp, outDtp, EXTEND_EXP, false);
widthCheckSized(nodep, "Cast expr", VN_AS(underp, NodeExpr), outDtp, EXTEND_EXP,
false);
VL_DANGLING(underp);
}
}
@ -2403,10 +2392,10 @@ private:
nodep->dtypeSetBit();
if (debug() >= 9) nodep->dumpTree(cout, "-inside-in: ");
// Now rip out the inside and replace with simple math
AstNode* newp = nullptr;
for (AstNode *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) {
nextip = itemp->nextp(); // Will be unlinking
AstNode* inewp;
AstNodeExpr* newp = nullptr;
for (AstNodeExpr *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) {
nextip = VN_AS(itemp->nextp(), NodeExpr); // Will be unlinking
AstNodeExpr* inewp;
const AstNodeDType* const itemDtp = itemp->dtypep()->skipRefp();
if (AstInsideRange* const irangep = VN_CAST(itemp, InsideRange)) {
// Similar logic in V3Case
@ -2878,7 +2867,7 @@ private:
} else if (nodep->name() == "exists") { // function int exists(input index)
// IEEE really should have made this a "bit" return
methodOkArguments(nodep, 1, 1);
AstNode* const index_exprp = methodCallWildcardIndexExpr(nodep, adtypep);
AstNodeExpr* const index_exprp = methodCallWildcardIndexExpr(nodep, adtypep);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(), "exists",
index_exprp->unlinkFrBack()};
newp->dtypeSetSigned32();
@ -2891,7 +2880,7 @@ private:
"clear"};
newp->dtypeSetVoid();
} else {
AstNode* const index_exprp = methodCallWildcardIndexExpr(nodep, adtypep);
AstNodeExpr* const index_exprp = methodCallWildcardIndexExpr(nodep, adtypep);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"erase", index_exprp->unlinkFrBack()};
newp->dtypeSetVoid();
@ -2954,7 +2943,7 @@ private:
|| nodep->name() == "next" //
|| nodep->name() == "prev") {
methodOkArguments(nodep, 1, 1);
AstNode* const index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
AstNodeExpr* const index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), // first/last/next/prev
index_exprp->unlinkFrBack());
@ -2963,7 +2952,7 @@ private:
} else if (nodep->name() == "exists") { // function int exists(input index)
// IEEE really should have made this a "bit" return
methodOkArguments(nodep, 1, 1);
AstNode* const index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
AstNodeExpr* const index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "exists",
index_exprp->unlinkFrBack());
newp->dtypeSetSigned32();
@ -2976,7 +2965,7 @@ private:
"clear");
newp->dtypeSetVoid();
} else {
AstNode* const index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
AstNodeExpr* const index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"erase", index_exprp->unlinkFrBack());
newp->dtypeSetVoid();
@ -3039,14 +3028,15 @@ private:
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
AstNode* methodCallAssocIndexExpr(AstMethodCall* nodep, AstAssocArrayDType* adtypep) {
AstNodeExpr* methodCallAssocIndexExpr(AstMethodCall* nodep, AstAssocArrayDType* adtypep) {
AstNode* const index_exprp = VN_CAST(nodep->pinsp(), Arg)->exprp();
iterateCheck(nodep, "index", index_exprp, CONTEXT_DET, FINAL, adtypep->keyDTypep(),
EXTEND_EXP);
VL_DANGLING(index_exprp); // May have been edited
return VN_AS(nodep->pinsp(), Arg)->exprp();
}
AstNode* methodCallWildcardIndexExpr(AstMethodCall* nodep, AstWildcardArrayDType* adtypep) {
AstNodeExpr* methodCallWildcardIndexExpr(AstMethodCall* nodep,
AstWildcardArrayDType* adtypep) {
AstNode* const index_exprp = VN_CAST(nodep->pinsp(), Arg)->exprp();
iterateCheck(nodep, "index", index_exprp, CONTEXT_DET, FINAL, adtypep->findStringDType(),
EXTEND_EXP);
@ -3172,7 +3162,7 @@ private:
"clear");
newp->dtypeSetVoid();
} else {
AstNode* const index_exprp = methodCallQueueIndexExpr(nodep);
AstNodeExpr* const index_exprp = methodCallQueueIndexExpr(nodep);
if (index_exprp->isZero()) { // delete(0) is a pop_front
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"pop_front");
@ -3187,7 +3177,7 @@ private:
} else if (nodep->name() == "insert") {
methodOkArguments(nodep, 2, 2);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
AstNode* const index_exprp = methodCallQueueIndexExpr(nodep);
AstNodeExpr* const index_exprp = methodCallQueueIndexExpr(nodep);
AstArg* const argp = VN_AS(nodep->pinsp()->nextp(), Arg);
iterateCheckTyped(nodep, "insert value", argp->exprp(), adtypep->subDTypep(), BOTH);
if (index_exprp->isZero()) { // insert(0, ...) is a push_front
@ -3285,7 +3275,7 @@ private:
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
AstNode* methodCallQueueIndexExpr(AstMethodCall* nodep) {
AstNodeExpr* methodCallQueueIndexExpr(AstMethodCall* nodep) {
AstNode* const index_exprp = VN_AS(nodep->pinsp(), Arg)->exprp();
iterateCheckSigned32(nodep, "index", index_exprp, BOTH);
VL_DANGLING(index_exprp); // May have been edited
@ -3304,7 +3294,7 @@ private:
= VN_CAST(classp->findMember(nodep->name()), NodeFTask)) {
userIterate(ftaskp, nullptr);
if (ftaskp->lifetime().isStatic()) {
AstNode* argsp = nullptr;
AstNodeExpr* argsp = nullptr;
if (nodep->pinsp()) argsp = nodep->pinsp()->unlinkFrBackWithNext();
AstNodeFTaskRef* newp = nullptr;
if (VN_IS(ftaskp, Task)) {
@ -3369,10 +3359,10 @@ private:
if (methodId) {
methodOkArguments(nodep, 0, 0);
FileLine* const fl = nodep->fileline();
AstNode* newp = nullptr;
AstNodeExpr* newp = nullptr;
for (int i = 0; i < adtypep->elementsConst(); ++i) {
AstNode* const arrayRef = nodep->fromp()->cloneTree(false);
AstNode* const selector = new AstArraySel(fl, arrayRef, i);
AstNodeExpr* const arrayRef = nodep->fromp()->cloneTree(false);
AstNodeExpr* const selector = new AstArraySel(fl, arrayRef, i);
if (!newp) {
newp = selector;
} else {
@ -3446,8 +3436,8 @@ private:
const bool ignoreCase = nodep->name()[0] == 'i';
methodOkArguments(nodep, 1, 1);
AstArg* const argp = VN_AS(nodep->pinsp(), Arg);
AstNode* const lhs = nodep->fromp()->unlinkFrBack();
AstNode* const rhs = argp->exprp()->unlinkFrBack();
AstNodeExpr* const lhs = nodep->fromp()->unlinkFrBack();
AstNodeExpr* const rhs = argp->exprp()->unlinkFrBack();
AstNode* const newp = new AstCompareNN(nodep->fileline(), lhs, rhs, ignoreCase);
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
@ -3456,8 +3446,8 @@ private:
AstArg* const arg0p = VN_AS(nodep->pinsp(), Arg);
AstArg* const arg1p = VN_AS(arg0p->nextp(), Arg);
AstNodeVarRef* const fromp = VN_AS(nodep->fromp()->unlinkFrBack(), VarRef);
AstNode* const rhsp = arg0p->exprp()->unlinkFrBack();
AstNode* const thsp = arg1p->exprp()->unlinkFrBack();
AstNodeExpr* const rhsp = arg0p->exprp()->unlinkFrBack();
AstNodeExpr* const thsp = arg1p->exprp()->unlinkFrBack();
AstVarRef* const varrefp
= new AstVarRef(nodep->fileline(), fromp->varp(), VAccess::READ);
AstNode* const newp = new AstAssign(
@ -3468,19 +3458,19 @@ private:
} else if (nodep->name() == "getc") {
methodOkArguments(nodep, 1, 1);
AstArg* const arg0p = VN_AS(nodep->pinsp(), Arg);
AstNode* const lhsp = nodep->fromp()->unlinkFrBack();
AstNode* const rhsp = arg0p->exprp()->unlinkFrBack();
AstNode* const newp = new AstGetcN(nodep->fileline(), lhsp, rhsp);
AstNodeExpr* const lhsp = nodep->fromp()->unlinkFrBack();
AstNodeExpr* const rhsp = arg0p->exprp()->unlinkFrBack();
AstNodeExpr* const newp = new AstGetcN(nodep->fileline(), lhsp, rhsp);
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
} else if (nodep->name() == "substr") {
methodOkArguments(nodep, 2, 2);
AstArg* const arg0p = VN_AS(nodep->pinsp(), Arg);
AstArg* const arg1p = VN_AS(arg0p->nextp(), Arg);
AstNode* const lhsp = nodep->fromp()->unlinkFrBack();
AstNode* const rhsp = arg0p->exprp()->unlinkFrBack();
AstNode* const thsp = arg1p->exprp()->unlinkFrBack();
AstNode* const newp = new AstSubstrN(nodep->fileline(), lhsp, rhsp, thsp);
AstNodeExpr* const lhsp = nodep->fromp()->unlinkFrBack();
AstNodeExpr* const rhsp = arg0p->exprp()->unlinkFrBack();
AstNodeExpr* const thsp = arg1p->exprp()->unlinkFrBack();
AstNodeExpr* const newp = new AstSubstrN(nodep->fileline(), lhsp, rhsp, thsp);
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
} else if (nodep->name() == "atobin" || nodep->name() == "atohex"
@ -3628,7 +3618,7 @@ private:
// So detach, add next and reattach
VNRelinker relinkHandle;
patp->unlinkFrBack(&relinkHandle);
while (AstNode* const movep = patp->lhssp()->nextp()) {
while (AstNodeExpr* const movep = VN_AS(patp->lhssp()->nextp(), NodeExpr)) {
movep->unlinkFrBack(); // Not unlinkFrBackWithNext, just one
AstNode* newkeyp = nullptr;
if (patp->keyp()) newkeyp = patp->keyp()->cloneTree(true);
@ -3743,7 +3733,7 @@ private:
if (patp) patp = VN_AS(patp->nextp(), PatMember);
}
}
AstNode* newp = nullptr;
AstNodeExpr* newp = nullptr;
for (AstMemberDType* memp = vdtypep->membersp(); memp;
memp = VN_AS(memp->nextp(), MemberDType)) {
const auto it = patmap.find(memp);
@ -3773,9 +3763,9 @@ private:
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
}
AstNode* nestedvalueConcat_patternUOrStruct(AstNodeUOrStructDType* memp_vdtypep,
AstPatMember* defaultp, AstNode* newp,
AstPattern* nodep, DTypeMap dtypemap) {
AstNodeExpr* nestedvalueConcat_patternUOrStruct(AstNodeUOrStructDType* memp_vdtypep,
AstPatMember* defaultp, AstNodeExpr* newp,
AstPattern* nodep, DTypeMap dtypemap) {
AstPatMember* patp = nullptr;
for (AstMemberDType* memp_nested = memp_vdtypep->membersp(); memp_nested;
memp_nested = VN_AS(memp_nested->nextp(), MemberDType)) {
@ -3816,11 +3806,11 @@ private:
return patp;
}
AstNode* valueConcat_patternUOrStruct(AstPatMember* patp, AstNode* newp, AstMemberDType* memp,
AstPattern* nodep) {
AstNodeExpr* valueConcat_patternUOrStruct(AstPatMember* patp, AstNodeExpr* newp,
AstMemberDType* memp, AstPattern* nodep) {
if (patp) {
patp->dtypep(memp);
AstNode* const valuep = patternMemberValueIterate(patp);
AstNodeExpr* const valuep = patternMemberValueIterate(patp);
if (!newp) {
newp = valuep;
} else {
@ -3858,11 +3848,11 @@ private:
if (patp) {
// Don't want the RHS an array
patp->dtypep(arrayDtp->subDTypep());
AstNode* const valuep = patternMemberValueIterate(patp);
AstNodeExpr* const valuep = patternMemberValueIterate(patp);
if (VN_IS(arrayDtp, UnpackArrayDType)) {
if (!newp) {
AstInitArray* const newap
= new AstInitArray(nodep->fileline(), arrayDtp, nullptr);
= new AstInitArray{nodep->fileline(), arrayDtp, nullptr};
newp = newap;
}
VN_AS(newp, InitArray)->addIndexValuep(ent - range.lo(), valuep);
@ -3870,7 +3860,8 @@ private:
if (!newp) {
newp = valuep;
} else {
AstConcat* const concatp = new AstConcat(patp->fileline(), newp, valuep);
AstConcat* const concatp
= new AstConcat{patp->fileline(), VN_AS(newp, NodeExpr), valuep};
newp = concatp;
newp->dtypeSetLogicSized(concatp->lhsp()->width()
+ concatp->rhsp()->width(),
@ -3892,12 +3883,12 @@ private:
void patternAssoc(AstPattern* nodep, AstAssocArrayDType* arrayDtp, AstPatMember* defaultp) {
AstNode* defaultValuep = nullptr;
if (defaultp) defaultValuep = defaultp->lhssp()->unlinkFrBack();
AstNode* newp = new AstConsAssoc(nodep->fileline(), defaultValuep);
AstNodeExpr* newp = new AstConsAssoc(nodep->fileline(), defaultValuep);
newp->dtypeFrom(arrayDtp);
for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp;
patp = VN_AS(patp->nextp(), PatMember)) {
patp->dtypep(arrayDtp->subDTypep());
AstNode* const valuep = patternMemberValueIterate(patp);
AstNodeExpr* const valuep = patternMemberValueIterate(patp);
AstNode* const keyp = patp->keyp();
auto* const newap
= new AstSetAssoc(nodep->fileline(), newp, keyp->unlinkFrBack(), valuep);
@ -3917,7 +3908,7 @@ private:
for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp;
patp = VN_AS(patp->nextp(), PatMember)) {
patp->dtypep(arrayDtp->subDTypep());
AstNode* const valuep = patternMemberValueIterate(patp);
AstNodeExpr* const valuep = patternMemberValueIterate(patp);
AstNode* const keyp = patp->keyp();
auto* const newap
= new AstSetWildcard{nodep->fileline(), newp, keyp->unlinkFrBack(), valuep};
@ -3934,7 +3925,7 @@ private:
for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp;
patp = VN_AS(patp->nextp(), PatMember)) {
patp->dtypep(arrayp->subDTypep());
AstNode* const valuep = patternMemberValueIterate(patp);
AstNodeExpr* const valuep = patternMemberValueIterate(patp);
auto* const newap = new AstConsDynArray(nodep->fileline(), valuep, newp);
newap->dtypeFrom(arrayp);
newp = newap;
@ -3949,7 +3940,7 @@ private:
for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp;
patp = VN_AS(patp->nextp(), PatMember)) {
patp->dtypep(arrayp->subDTypep());
AstNode* const valuep = patternMemberValueIterate(patp);
AstNodeExpr* const valuep = patternMemberValueIterate(patp);
auto* const newap = new AstConsQueue(nodep->fileline(), valuep, newp);
newap->dtypeFrom(arrayp);
newp = newap;
@ -3963,7 +3954,7 @@ private:
const VNumRange range = bdtypep->declRange();
PatVecMap patmap = patVectorMap(nodep, range);
UINFO(9, "ent " << range.hi() << " to " << range.lo() << endl);
AstNode* newp = nullptr;
AstNodeExpr* newp = nullptr;
for (int ent = range.hi(); ent >= range.lo(); --ent) {
AstPatMember* newpatp = nullptr;
AstPatMember* patp = nullptr;
@ -3983,7 +3974,7 @@ private:
// Determine initial values
vdtypep = nodep->findBitDType();
patp->dtypep(vdtypep);
AstNode* const valuep = patternMemberValueIterate(patp);
AstNodeExpr* const valuep = patternMemberValueIterate(patp);
{ // Packed. Convert to concat for now.
if (!newp) {
newp = valuep;
@ -4007,15 +3998,15 @@ private:
// if (debug() >= 9) newp->dumpTree("-apat-out: ");
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
}
AstNode* patternMemberValueIterate(AstPatMember* patp) {
AstNodeExpr* patternMemberValueIterate(AstPatMember* patp) {
// Determine values - might be another InitArray
userIterate(patp, WidthVP(patp->dtypep(), BOTH).p());
// Convert to InitArray or constify immediately
AstNode* valuep = patp->lhssp()->unlinkFrBack();
AstNodeExpr* valuep = patp->lhssp()->unlinkFrBack();
if (VN_IS(valuep, Const)) {
// Forming a AstConcat will cause problems with
// unsized (uncommitted sized) constants
if (AstNode* const newp
if (AstConst* const newp
= WidthCommitVisitor::newIfConstCommitSize(VN_AS(valuep, Const))) {
VL_DO_DANGLING(pushDeletep(valuep), valuep);
valuep = newp;
@ -4179,7 +4170,7 @@ private:
UASSERT_OBJ(loopsp, nodep, "No loop variables under foreach");
// if (debug()) nodep->dumpTree(cout, "-foreach-old: ");
userIterateAndNext(loopsp->fromp(), WidthVP(SELF, BOTH).p());
AstNode* const fromp = loopsp->fromp();
AstNodeExpr* const fromp = loopsp->fromp();
UASSERT_OBJ(fromp->dtypep(), fromp, "Missing data type");
AstNodeDType* fromDtp = fromp->dtypep()->skipRefp();
// Split into for loop
@ -4248,10 +4239,11 @@ private:
sizep->dtypeSetSigned32();
sizep->didWidth(true);
sizep->protect(false);
AstNode* const condp
AstNodeExpr* const condp
= new AstLt{fl, new AstVarRef{fl, varp, VAccess::READ}, sizep};
AstNode* const incp = new AstAdd{fl, new AstConst{fl, AstConst::Signed32{}, 1},
new AstVarRef{fl, varp, VAccess::READ}};
AstNodeExpr* const incp
= new AstAdd{fl, new AstConst{fl, AstConst::Signed32{}, 1},
new AstVarRef{fl, varp, VAccess::READ}};
loopp = createForeachLoop(nodep, bodyPointp, varp, leftp, condp, incp);
}
// Prep for next
@ -4267,10 +4259,10 @@ private:
AstVar* const first_varp = new AstVar{
fl, VVarType::BLOCKTEMP, varp->name() + "__Vfirst", VFlagBitPacked{}, 1};
first_varp->usedLoopIdx(true);
AstNode* const firstp = new AstMethodCall{
AstNodeExpr* const firstp = new AstMethodCall{
fl, fromp->cloneTree(false), "first",
new AstArg{fl, "", new AstVarRef{fl, varp, VAccess::READWRITE}}};
AstNode* const nextp = new AstMethodCall{
AstNodeExpr* const nextp = new AstMethodCall{
fl, fromp->cloneTree(false), "next",
new AstArg{fl, "", new AstVarRef{fl, varp, VAccess::READWRITE}}};
AstNode* const first_clearp
@ -4322,10 +4314,10 @@ private:
AstNode* createForeachLoopRanged(AstForeach* nodep, AstNode* bodysp, AstVar* varp,
const VNumRange& declRange) {
FileLine* const fl = varp->fileline();
auto* const leftp = new AstConst{fl, AstConst::Signed32{}, declRange.left()};
auto* const rightp = new AstConst{fl, AstConst::Signed32{}, declRange.right()};
AstNode* condp;
AstNode* incp;
AstNodeExpr* const leftp = new AstConst{fl, AstConst::Signed32{}, declRange.left()};
AstNodeExpr* const rightp = new AstConst{fl, AstConst::Signed32{}, declRange.right()};
AstNodeExpr* condp;
AstNodeExpr* incp;
if (declRange.left() < declRange.right()) {
condp = new AstLte{fl, new AstVarRef{fl, varp, VAccess::READ}, rightp};
incp = new AstAdd{fl, new AstConst{fl, AstConst::Signed32{}, 1},
@ -4337,8 +4329,8 @@ private:
}
return createForeachLoop(nodep, bodysp, varp, leftp, condp, incp);
}
AstNode* createForeachLoop(AstForeach* nodep, AstNode* bodysp, AstVar* varp, AstNode* leftp,
AstNode* condp, AstNode* incp) {
AstNode* createForeachLoop(AstForeach* nodep, AstNode* bodysp, AstVar* varp,
AstNodeExpr* leftp, AstNodeExpr* condp, AstNodeExpr* incp) {
FileLine* const fl = varp->fileline();
auto* const whilep = new AstWhile{
fl, condp, bodysp, new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE}, incp}};
@ -4454,7 +4446,7 @@ private:
UINFO(9, " Display in " << nodep->text() << endl);
string newFormat;
bool inPct = false;
AstNode* argp = nodep->exprsp();
AstNodeExpr* argp = nodep->exprsp();
const string txt = nodep->text();
string fmt;
for (char ch : txt) {
@ -4472,7 +4464,7 @@ private:
case 'l': break; // %m - auto insert "library"
case 'd': { // Convert decimal to either 'd' or '#'
if (argp) {
AstNode* const nextp = argp->nextp();
AstNodeExpr* const nextp = VN_AS(argp->nextp(), NodeExpr);
if (argp->isDouble()) {
spliceCvtS(argp, true, 64);
ch = '~';
@ -4501,14 +4493,18 @@ private:
newFormat += "%@";
VNRelinker handle;
argp->unlinkFrBack(&handle);
AstCExpr* const newp
= new AstCExpr(nodep->fileline(), "VL_TO_STRING(", 0, true);
FileLine* const flp = nodep->fileline();
AstCExpr* const newp = new AstCExpr{flp, nullptr};
newp->addExprsp(new AstText{flp, "VL_TO_STRING(", true});
newp->addExprsp(argp);
newp->addExprsp(new AstText(nodep->fileline(), ")", true));
newp->addExprsp(new AstText{flp, ")", true});
newp->dtypeSetString();
newp->pure(true);
newp->protect(false);
handle.relink(newp);
// Set argp to what we replaced it with, as we will keep processing the
// next argument.
argp = newp;
} else {
added = true;
if (fmt == "%0") {
@ -4517,19 +4513,19 @@ private:
newFormat += "%d";
}
}
if (argp) argp = argp->nextp();
if (argp) argp = VN_AS(argp->nextp(), NodeExpr);
break;
}
case 's': { // Convert string to pack string
if (argp && argp->dtypep()->basicp()->isString()) { // Convert it
ch = '@';
}
if (argp) argp = argp->nextp();
if (argp) argp = VN_AS(argp->nextp(), NodeExpr);
break;
}
case 't': { // Convert decimal time to realtime
if (argp) {
AstNode* const nextp = argp->nextp();
AstNodeExpr* const nextp = VN_AS(argp->nextp(), NodeExpr);
if (argp->isDouble()) ch = '^'; // Convert it
if (nodep->timeunit().isNone()) {
nodep->v3fatalSrc("display %t has no time units");
@ -4541,7 +4537,7 @@ private:
case 'f': // FALLTHRU
case 'g': {
if (argp) {
AstNode* const nextp = argp->nextp();
AstNodeExpr* const nextp = VN_AS(argp->nextp(), NodeExpr);
if (!argp->isDouble()) {
iterateCheckReal(nodep, "Display argument", argp, BOTH);
}
@ -4559,11 +4555,11 @@ private:
} else {
ch = nodep->missingArgChar();
}
if (argp) argp = argp->nextp();
if (argp) argp = VN_AS(argp->nextp(), NodeExpr);
break;
}
default: { // Most operators, just move to next argument
if (argp) argp = argp->nextp();
if (argp) argp = VN_AS(argp->nextp(), NodeExpr);
break;
}
} // switch
@ -5124,7 +5120,7 @@ private:
for (const auto& tconnect : tconnects) {
const AstVar* const portp = tconnect.first;
AstArg* const argp = tconnect.second;
AstNode* pinp = argp->exprp();
AstNodeExpr* pinp = argp->exprp();
if (!pinp) continue; // Argument error we'll find later
// Prelim may cause the node to get replaced; we've lost our
// pointer, so need to iterate separately later
@ -5133,11 +5129,10 @@ private:
UINFO(4, " sformat via metacomment: " << nodep << endl);
VNRelinker handle;
argp->unlinkFrBackWithNext(&handle); // Format + additional args, if any
AstNode* argsp = nullptr;
AstNodeExpr* argsp = nullptr;
while (AstArg* const nextargp = VN_AS(argp->nextp(), Arg)) {
argsp = AstNode::addNext(
argsp, nextargp->exprp()
->unlinkFrBackWithNext()); // Expression goes to SFormatF
// Expression goes to SFormatF
argsp = argsp->addNext(nextargp->exprp()->unlinkFrBackWithNext());
nextargp->unlinkFrBack()->deleteTree(); // Remove the call's Arg wrapper
}
string format;
@ -5167,7 +5162,7 @@ private:
UINFO(4, " Add CvtPackString: " << pinp << endl);
VNRelinker handle;
pinp->unlinkFrBack(&handle); // No next, that's the next pin
AstNode* const newp = new AstCvtPackString(pinp->fileline(), pinp);
AstNodeExpr* const newp = new AstCvtPackString(pinp->fileline(), pinp);
handle.relink(newp);
pinp = newp;
}
@ -5181,7 +5176,7 @@ private:
for (const auto& tconnect : tconnects) {
AstVar* const portp = tconnect.first;
const AstArg* const argp = tconnect.second;
AstNode* const pinp = argp->exprp();
AstNodeExpr* const pinp = argp->exprp();
if (!pinp) continue; // Argument error we'll find later
// Change data types based on above accept completion
if (nodep->taskp()->dpiImport()) checkUnpackedArrayArgs(portp, pinp);
@ -5194,7 +5189,7 @@ private:
for (const auto& tconnect : tconnects) {
const AstVar* const portp = tconnect.first;
const AstArg* const argp = tconnect.second;
AstNode* const pinp = argp->exprp();
AstNodeExpr* const pinp = argp->exprp();
if (!pinp) continue; // Argument error we'll find later
// Do PRELIM again, because above accept may have exited early
// due to node replacement
@ -5827,7 +5822,7 @@ private:
return false;
}
void fixWidthExtend(AstNode* nodep, AstNodeDType* expDTypep, ExtendRule extendRule) {
void fixWidthExtend(AstNodeExpr* nodep, AstNodeDType* expDTypep, ExtendRule extendRule) {
// Fix the width mismatch by extending or truncating bits
// *ONLY* call this from checkWidth()
// Truncation is rarer, but can occur: parameter [3:0] FOO = 64'h12312;
@ -5848,7 +5843,7 @@ private:
V3Number num(nodep, expWidth);
num.opAssign(constp->num());
num.isSigned(false);
AstNode* const newp = new AstConst(nodep->fileline(), num);
AstNodeExpr* const newp = new AstConst(nodep->fileline(), num);
constp->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(constp), constp);
VL_DANGLING(nodep);
@ -5857,7 +5852,7 @@ private:
// Trunc - Extract
VNRelinker linker;
nodep->unlinkFrBack(&linker);
AstNode* const newp = new AstSel(nodep->fileline(), nodep, 0, expWidth);
AstNodeExpr* const newp = new AstSel(nodep->fileline(), nodep, 0, expWidth);
newp->didWidth(true); // Don't replace dtype with unsigned
linker.relink(newp);
nodep = newp;
@ -5872,9 +5867,9 @@ private:
case EXTEND_LHS: doSigned = nodep->isSigned(); break;
default: nodep->v3fatalSrc("bad case");
}
AstNode* const newp
= (doSigned ? static_cast<AstNode*>(new AstExtendS{nodep->fileline(), nodep})
: static_cast<AstNode*>(new AstExtend{nodep->fileline(), nodep}));
AstNodeExpr* const newp
= (doSigned ? static_cast<AstNodeExpr*>(new AstExtendS{nodep->fileline(), nodep})
: static_cast<AstNodeExpr*>(new AstExtend{nodep->fileline(), nodep}));
linker.relink(newp);
nodep = newp;
}
@ -5882,14 +5877,14 @@ private:
// For AstVar init() among others
// TODO do all to-real and to-integer conversions in this function
// rather than in callers
AstNode* const newp = spliceCvtD(nodep);
AstNodeExpr* const newp = spliceCvtD(nodep);
nodep = newp;
}
nodep->dtypeFrom(expDTypep);
UINFO(4, " _new: " << nodep << endl);
}
void fixWidthReduce(AstNode* nodep) {
void fixWidthReduce(AstNodeExpr* nodep) {
// Fix the width mismatch by adding a reduction OR operator
// IF (A(CONSTwide)) becomes IF (A(CONSTreduced))
// IF (A(somewide)) becomes IF (A(REDOR(somewide)))
@ -5902,7 +5897,7 @@ private:
V3Number num(nodep, expWidth);
num.opRedOr(constp->num());
num.isSigned(expSigned);
AstNode* const newp = new AstConst(nodep->fileline(), num);
AstNodeExpr* const newp = new AstConst(nodep->fileline(), num);
constp->replaceWith(newp);
VL_DO_DANGLING(constp->deleteTree(), constp);
VL_DANGLING(nodep);
@ -5910,7 +5905,7 @@ private:
} else {
VNRelinker linker;
nodep->unlinkFrBack(&linker);
AstNode* const newp = new AstRedOr(nodep->fileline(), nodep);
AstNodeExpr* const newp = new AstRedOr(nodep->fileline(), nodep);
linker.relink(newp);
nodep = newp;
}
@ -5918,14 +5913,14 @@ private:
UINFO(4, " _new: " << nodep << endl);
}
bool fixAutoExtend(AstNode*& nodepr, int expWidth) {
bool fixAutoExtend(AstNodeExpr*& nodepr, int expWidth) {
// For SystemVerilog '0,'1,'x,'z, autoextend and don't warn
if (AstConst* const constp = VN_CAST(nodepr, Const)) {
if (constp->num().autoExtend() && !constp->num().sized() && constp->width() == 1) {
// Make it the proper size. Careful of proper extension of 0's/1's
V3Number num(constp, expWidth);
num.opRepl(constp->num(), expWidth); // {width{'1}}
AstNode* const newp = new AstConst(constp->fileline(), num);
AstNodeExpr* const newp = new AstConst(constp->fileline(), num);
// Spec says always unsigned with proper width
if (debug() > 4) constp->dumpTree(cout, " fixAutoExtend_old: ");
if (debug() > 4) newp->dumpTree(cout, " _new: ");
@ -5943,7 +5938,7 @@ private:
<< expWidth << " bits: " << constp->prettyName());
V3Number num(constp, expWidth);
num.opExtendXZ(constp->num(), constp->width());
AstNode* const newp = new AstConst(constp->fileline(), num);
AstNodeExpr* const newp = new AstConst(constp->fileline(), num);
// Spec says always unsigned with proper width
if (debug() > 4) constp->dumpTree(cout, " fixUnszExtend_old: ");
if (debug() > 4) newp->dumpTree(cout, " _new: ");
@ -6037,7 +6032,7 @@ private:
if (stage & PRELIM) {
underp = userIterateSubtreeReturnEdits(underp, WidthVP(SELF, PRELIM).p());
}
underp = checkCvtUS(underp);
underp = VN_IS(underp, NodeExpr) ? checkCvtUS(VN_AS(underp, NodeExpr)) : underp;
AstNodeDType* const expDTypep = underp->dtypep();
underp = iterateCheck(nodep, side, underp, SELF, FINAL, expDTypep, EXTEND_EXP);
if (underp) {} // cppcheck
@ -6076,14 +6071,14 @@ private:
VNRelinker linker;
underp->unlinkFrBack(&linker);
AstNode* const newp
= new AstNeqD(nodep->fileline(), underp,
= new AstNeqD(nodep->fileline(), VN_AS(underp, NodeExpr),
new AstConst(nodep->fileline(), AstConst::RealDouble(), 0.0));
linker.relink(newp);
} else if (VN_IS(underVDTypep, ClassRefDType)
|| (VN_IS(underVDTypep, BasicDType)
&& VN_AS(underVDTypep, BasicDType)->keyword() == VBasicDTypeKwd::CHANDLE)) {
// Allow warning-free "if (handle)"
VL_DO_DANGLING(fixWidthReduce(underp), underp); // Changed
VL_DO_DANGLING(fixWidthReduce(VN_AS(underp, NodeExpr)), underp); // Changed
} else if (!underVDTypep->basicp()) {
nodep->v3error("Logical operator " << nodep->prettyTypeName()
<< " expects a non-complex data type on the "
@ -6105,7 +6100,7 @@ private:
: "")
<< " bits.");
}
VL_DO_DANGLING(fixWidthReduce(underp), underp); // Changed
VL_DO_DANGLING(fixWidthReduce(VN_AS(underp, NodeExpr)), underp); // Changed
}
}
}
@ -6131,17 +6126,17 @@ private:
} else if (expDTypep->isDouble() && !underp->isDouble()) {
AstNode* const oldp
= underp; // Need FINAL on children; otherwise splice would block it
underp = spliceCvtD(underp);
underp = spliceCvtD(VN_AS(underp, NodeExpr));
underp = userIterateSubtreeReturnEdits(oldp, WidthVP(SELF, FINAL).p());
} else if (!expDTypep->isDouble() && underp->isDouble()) {
AstNode* const oldp
= underp; // Need FINAL on children; otherwise splice would block it
underp = spliceCvtS(underp, true, expDTypep->width()); // Round RHS
underp = spliceCvtS(VN_AS(underp, NodeExpr), true, expDTypep->width()); // Round RHS
underp = userIterateSubtreeReturnEdits(oldp, WidthVP(SELF, FINAL).p());
} else if (expDTypep->isString() && !underp->dtypep()->isString()) {
AstNode* const oldp
= underp; // Need FINAL on children; otherwise splice would block it
underp = spliceCvtString(underp);
underp = spliceCvtString(VN_AS(underp, NodeExpr));
underp = userIterateSubtreeReturnEdits(oldp, WidthVP(SELF, FINAL).p());
} else {
const AstBasicDType* const expBasicp = expDTypep->basicp();
@ -6185,7 +6180,8 @@ private:
}
// Note the check uses the expected size, not the child's subDTypep as we want the
// child node's width to end up correct for the assignment (etc)
widthCheckSized(nodep, side, underp, expDTypep, extendRule, warnOn);
widthCheckSized(nodep, side, VN_AS(underp, NodeExpr), expDTypep, extendRule,
warnOn);
} else if (!VN_IS(expDTypep->skipRefp(), IfaceRefDType)
&& VN_IS(underp->dtypep()->skipRefp(), IfaceRefDType)) {
underp->v3error(ucfirst(nodep->prettyOperatorName())
@ -6226,9 +6222,10 @@ private:
return underp;
}
void widthCheckSized(AstNode* nodep, const char* side,
AstNode* underp, // Node to be checked or have typecast added in front of
AstNodeDType* expDTypep, ExtendRule extendRule, bool warnOn = true) {
void
widthCheckSized(AstNode* nodep, const char* side,
AstNodeExpr* underp, // Node to be checked or have typecast added in front of
AstNodeDType* expDTypep, ExtendRule extendRule, bool warnOn = true) {
// Issue warnings on sized number width mismatches, then do appropriate size extension
// Generally iterateCheck is what is wanted instead of this
// UINFO(9,"wchk "<<side<<endl<<" "<<nodep<<endl<<" "<<underp<<endl<<" e="<<expDTypep<<"
@ -6305,7 +6302,7 @@ private:
//----------------------------------------------------------------------
// SIGNED/DOUBLE METHODS
AstNode* checkCvtUS(AstNode* nodep) {
AstNodeExpr* checkCvtUS(AstNodeExpr* nodep) {
if (nodep && nodep->isDouble()) {
nodep->v3error("Expected integral (non-" << nodep->dtypep()->prettyDTypeName()
<< ") input to "
@ -6315,14 +6312,14 @@ private:
return nodep;
}
AstNode* spliceCvtD(AstNode* nodep) {
AstNodeExpr* spliceCvtD(AstNodeExpr* nodep) {
// For integer used in REAL context, convert to real
// We don't warn here, "2.0 * 2" is common and reasonable
if (nodep && !nodep->dtypep()->skipRefp()->isDouble()) {
UINFO(6, " spliceCvtD: " << nodep << endl);
VNRelinker linker;
nodep->unlinkFrBack(&linker);
AstNode* newp;
AstNodeExpr* newp;
if (nodep->dtypep()->skipRefp()->isSigned()) {
newp = new AstISToRD(nodep->fileline(), nodep);
} else {
@ -6334,7 +6331,7 @@ private:
return nodep;
}
}
AstNode* spliceCvtS(AstNode* nodep, bool warnOn, int width) {
AstNodeExpr* spliceCvtS(AstNodeExpr* nodep, bool warnOn, int width) {
// IEEE-2012 11.8.1: Signed: Type coercion creates signed
// 11.8.2: Argument to convert is self-determined
if (nodep && nodep->dtypep()->skipRefp()->isDouble()) {
@ -6352,7 +6349,7 @@ private:
}
}
if (warnOn) nodep->v3warn(REALCVT, "Implicit conversion of real to integer");
AstNode* const newp = new AstRToIRoundS(nodep->fileline(), nodep);
AstNodeExpr* const newp = new AstRToIRoundS(nodep->fileline(), nodep);
linker.relink(newp);
newp->dtypeSetBitSized(width, VSigning::SIGNED);
return newp;
@ -6360,14 +6357,14 @@ private:
return nodep;
}
}
AstNode* spliceCvtString(AstNode* nodep) {
AstNodeExpr* spliceCvtString(AstNodeExpr* nodep) {
// IEEE-2012 11.8.1: Signed: Type coercion creates signed
// 11.8.2: Argument to convert is self-determined
if (nodep && !(nodep->dtypep()->basicp() && nodep->dtypep()->basicp()->isString())) {
UINFO(6, " spliceCvtString: " << nodep << endl);
VNRelinker linker;
nodep->unlinkFrBack(&linker);
AstNode* const newp = new AstCvtPackString(nodep->fileline(), nodep);
AstNodeExpr* const newp = new AstCvtPackString(nodep->fileline(), nodep);
linker.relink(newp);
return newp;
} else {
@ -6393,8 +6390,8 @@ private:
default: break;
}
FileLine* const fl = nodep->fileline();
AstNode* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeBiop* newp = nullptr;
switch (nodep->type()) {
case VNType::atGt: newp = new AstGtS(fl, lhsp, rhsp); break;
@ -6428,8 +6425,8 @@ private:
// Return new node or nullptr if nothing
if (nodep->doubleFlavor()) return nullptr;
FileLine* const fl = nodep->fileline();
AstNode* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeBiop* newp = nullptr;
// No width change on output;... // All below have bool or double outputs
switch (nodep->type()) {
@ -6467,8 +6464,8 @@ private:
// Return new node or nullptr if nothing
if (nodep->stringFlavor()) return nullptr;
FileLine* const fl = nodep->fileline();
AstNode* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeBiop* newp = nullptr;
// No width change on output;... // All below have bool or double outputs
switch (nodep->type()) {
@ -6499,7 +6496,7 @@ private:
// Return new node or nullptr if nothing
if (nodep->doubleFlavor()) return nullptr;
FileLine* const fl = nodep->fileline();
AstNode* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeExpr* const lhsp = nodep->lhsp()->unlinkFrBack();
AstNodeUniop* newp = nullptr;
switch (nodep->type()) {
case VNType::atNegate: newp = new AstNegateD(fl, lhsp); break;
@ -6744,7 +6741,7 @@ private:
// Find valid values and populate
UASSERT_OBJ(nodep->itemsp(), nodep, "enum without items");
std::map<uint64_t, AstNode*> values;
std::map<uint64_t, AstNodeExpr*> values;
{
AstEnumItem* const firstp = nodep->itemsp();
const AstEnumItem* prevp = firstp; // Prev must start with last item
@ -6942,7 +6939,7 @@ private:
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
AstNode* newVarRefDollarUnit(AstVar* nodep) {
AstVarRef* newVarRefDollarUnit(AstVar* nodep) {
AstVarRef* const varrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::READ};
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
return varrefp;

View File

@ -116,7 +116,7 @@ private:
return FromData(errp, ddtypep, fromRange);
}
AstNode* newSubNeg(AstNode* lhsp, int32_t rhs) {
AstNodeExpr* newSubNeg(AstNodeExpr* lhsp, int32_t rhs) {
// Return lhs-rhs, but if rhs is negative use an add, so we won't
// have to deal with signed math and related 32bit sign extension problems
if (rhs == 0) {
@ -126,17 +126,16 @@ private:
V3Number num(lhsp, lhsp->width());
num.opSub(VN_AS(lhsp, Const)->num(), V3Number(lhsp, 32, rhs));
num.isSigned(lhsp->isSigned());
AstNode* const newp = new AstConst(lhsp->fileline(), num);
return newp;
return new AstConst(lhsp->fileline(), num);
} else if (rhs > 0) {
AstNode* const newp
AstNodeExpr* const newp
= new AstSub(lhsp->fileline(), lhsp,
new AstConst(lhsp->fileline(), AstConst::Unsized32(), rhs));
// We must make sure sub gets sign of original value, not from the constant
newp->dtypeFrom(lhsp);
return newp;
} else { // rhs < 0;
AstNode* const newp
AstNodeExpr* const newp
= new AstAdd(lhsp->fileline(), lhsp,
new AstConst(lhsp->fileline(), AstConst::Unsized32(), -rhs));
// We must make sure sub gets sign of original value, not from the constant
@ -144,16 +143,16 @@ private:
return newp;
}
}
AstNode* newSubNeg(int32_t lhs, AstNode* rhsp) {
AstNodeExpr* newSubNeg(int32_t lhs, AstNodeExpr* rhsp) {
// Return lhs-rhs
// We must make sure sub gets sign of original value
AstNode* const newp = new AstSub(
AstNodeExpr* const newp = new AstSub(
rhsp->fileline(), new AstConst(rhsp->fileline(), AstConst::Unsized32(), lhs), rhsp);
newp->dtypeFrom(rhsp); // Important as AstSub default is lhs's sign
return newp;
}
AstNode* newSubLsbOf(AstNode* underp, const VNumRange& fromRange) {
AstNodeExpr* newSubLsbOf(AstNodeExpr* underp, const VNumRange& fromRange) {
// Account for a variable's LSB in bit selections
// Will likely become SUB(underp, lsb_of_signal).
// Don't report WIDTH warnings etc here, as may be inside a
@ -165,12 +164,10 @@ private:
} else {
if (fromRange.littleEndian()) {
// reg [1:3] was swapped to [3:1] (lsbEndianedp==3) and needs a SUB(3,under)
AstNode* const newp = newSubNeg(fromRange.hi(), underp);
return newp;
return newSubNeg(fromRange.hi(), underp);
} else {
// reg [3:1] needs a SUB(under,1)
AstNode* const newp = newSubNeg(underp, fromRange.lo());
return newp;
return newSubNeg(underp, fromRange.lo());
}
}
}
@ -209,8 +206,8 @@ private:
UINFO(6, "SELBIT " << nodep << endl);
if (debug() >= 9) nodep->backp()->dumpTree(cout, "--SELBT0: ");
// lhsp/rhsp do not need to be constant
AstNode* const fromp = nodep->fromp()->unlinkFrBack();
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack(); // bit we're extracting
AstNodeExpr* const fromp = nodep->fromp()->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack(); // bit we're extracting
if (debug() >= 9) nodep->dumpTree(cout, "--SELBT2: ");
const FromData fromdata = fromDataForArray(nodep, fromp);
AstNodeDType* const ddtypep = fromdata.m_dtypep;
@ -218,7 +215,7 @@ private:
UINFO(6, " ddtypep " << ddtypep << endl);
if (const AstUnpackArrayDType* const adtypep = VN_CAST(ddtypep, UnpackArrayDType)) {
// SELBIT(array, index) -> ARRAYSEL(array, index)
AstNode* subp = rhsp;
AstNodeExpr* subp = rhsp;
if (fromRange.lo() != 0 || fromRange.hi() < 0) {
subp = newSubNeg(subp, fromRange.lo());
}
@ -229,7 +226,7 @@ private:
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else if (const AstPackArrayDType* const adtypep = VN_CAST(ddtypep, PackArrayDType)) {
// SELBIT(array, index) -> SEL(array, index*width-of-subindex, width-of-subindex)
AstNode* subp = rhsp;
AstNodeExpr* subp = rhsp;
if (fromRange.littleEndian()) {
subp = newSubNeg(fromRange.hi(), subp);
} else {
@ -253,7 +250,7 @@ private:
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else if (const AstAssocArrayDType* const adtypep = VN_CAST(ddtypep, AssocArrayDType)) {
// SELBIT(array, index) -> ASSOCSEL(array, index)
AstNode* const subp = rhsp;
AstNodeExpr* const subp = rhsp;
AstAssocSel* const newp = new AstAssocSel(nodep->fileline(), fromp, subp);
newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference
if (debug() >= 9) newp->dumpTree(cout, "--SELBTn: ");
@ -262,7 +259,7 @@ private:
} else if (const AstWildcardArrayDType* const adtypep
= VN_CAST(ddtypep, WildcardArrayDType)) {
// SELBIT(array, index) -> WILDCARDSEL(array, index)
AstNode* const subp = rhsp;
AstNodeExpr* const subp = rhsp;
AstWildcardSel* const newp = new AstWildcardSel{nodep->fileline(), fromp, subp};
newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference
if (debug() >= 9) newp->dumpTree(cout, "--SELBTn: ");
@ -270,7 +267,7 @@ private:
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else if (const AstDynArrayDType* const adtypep = VN_CAST(ddtypep, DynArrayDType)) {
// SELBIT(array, index) -> CMETHODCALL(queue, "at", index)
AstNode* const subp = rhsp;
AstNodeExpr* const subp = rhsp;
AstCMethodHard* const newp = new AstCMethodHard(nodep->fileline(), fromp, "at", subp);
newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off queue reference
if (debug() >= 9) newp->dumpTree(cout, "--SELBTq: ");
@ -278,7 +275,7 @@ private:
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else if (const AstQueueDType* const adtypep = VN_CAST(ddtypep, QueueDType)) {
// SELBIT(array, index) -> CMETHODCALL(queue, "at", index)
AstNode* const subp = rhsp;
AstNodeExpr* const subp = rhsp;
AstCMethodHard* const newp = new AstCMethodHard(nodep->fileline(), fromp, "at", subp);
newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off queue reference
if (debug() >= 9) newp->dumpTree(cout, "--SELBTq: ");
@ -291,7 +288,7 @@ private:
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: String array operation on non-variable");
}
AstNode* newp;
AstNodeExpr* newp;
if (varrefp && varrefp->access().isReadOnly()) {
newp = new AstGetcN(nodep->fileline(), fromp, rhsp);
} else {
@ -345,9 +342,9 @@ private:
"First value of [a:b] isn't a constant, maybe you want +: or -:");
checkConstantOrReplace(nodep->rightp(),
"Second value of [a:b] isn't a constant, maybe you want +: or -:");
AstNode* const fromp = nodep->fromp()->unlinkFrBack();
AstNode* const msbp = nodep->rhsp()->unlinkFrBack();
AstNode* const lsbp = nodep->thsp()->unlinkFrBack();
AstNodeExpr* const fromp = nodep->fromp()->unlinkFrBack();
AstNodeExpr* const msbp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const lsbp = nodep->thsp()->unlinkFrBack();
int32_t msb = VN_AS(msbp, Const)->toSInt();
int32_t lsb = VN_AS(lsbp, Const)->toSInt();
const int32_t elem = (msb > lsb) ? (msb - lsb + 1) : (lsb - msb + 1);
@ -424,7 +421,7 @@ private:
msb = lsb;
lsb = x;
}
AstNode* const widthp
AstNodeExpr* const widthp
= new AstConst(msbp->fileline(),
AstConst::Unsized32(), // Unsized so width from user
msb + 1 - lsb);
@ -447,7 +444,7 @@ private:
msb = lsb;
lsb = x;
}
AstNode* const widthp
AstNodeExpr* const widthp
= new AstConst(msbp->fileline(),
AstConst::Unsized32(), // Unsized so width from user
msb + 1 - lsb);
@ -493,9 +490,9 @@ private:
checkConstantOrReplace(nodep->thsp(), "Width of :+ or :- bit extract isn't a constant");
if (debug() >= 9) nodep->dumpTree(cout, "--SELPM3: ");
// Now replace it with an AstSel
AstNode* const fromp = nodep->fromp()->unlinkFrBack();
AstNode* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* const widthp = nodep->thsp()->unlinkFrBack();
AstNodeExpr* const fromp = nodep->fromp()->unlinkFrBack();
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* const widthp = nodep->thsp()->unlinkFrBack();
warnTri(rhsp);
const int width = VN_AS(widthp, Const)->toSInt();
if (width > (1 << 28)) {
@ -536,13 +533,13 @@ private:
|| (VN_IS(ddtypep, NodeUOrStructDType)
&& VN_AS(ddtypep, NodeUOrStructDType)->packedUnsup())) {
int elwidth = 1;
AstNode* newwidthp = widthp;
AstNodeExpr* newwidthp = widthp;
if (const AstPackArrayDType* const adtypep = VN_CAST(ddtypep, PackArrayDType)) {
elwidth = adtypep->width() / fromRange.elements();
newwidthp
= new AstConst(nodep->fileline(), AstConst::Unsized32(), width * elwidth);
}
AstNode* newlsbp = nullptr;
AstNodeExpr* newlsbp = nullptr;
if (VN_IS(nodep, SelPlus)) {
if (fromRange.littleEndian()) {
// SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width)

View File

@ -425,9 +425,10 @@ class Cpt:
key=lambda val: self._exec_syms[val]):
argnp = self._exec_syms[sym]
arg = self.add_nodep(sym)
out += "AstNode* " + argnp + " = " + arg + "->unlinkFrBack();\n"
out += "AstNodeExpr* " + argnp + " = " + arg + "->unlinkFrBack();\n"
out += "AstNode* newp = " + self._exec_new_recurse(aref) + ";\n"
out += "AstNodeExpr* newp = " + self._exec_new_recurse(
aref) + ";\n"
out += "nodep->replaceWith(newp);"
out += "VL_DO_DANGLING(nodep->deleteTree(), nodep);"
elif func == "NEVER":
@ -918,12 +919,18 @@ def write_ast_macros(filename):
for node in AstNodeList:
fh.write("#define ASTGEN_MEMBERS_Ast{t} \\\n".format(t=node.name))
emitBlock('''\
static Ast{t}* cloneTreeNull(Ast{t}* nodep, bool cloneNextLink) {{
return nodep ? nodep->cloneTree(cloneNextLink) : nullptr;
Ast{t}* unlinkFrBack(VNRelinker* linkerp = nullptr) {{
return static_cast<Ast{t}*>(AstNode::unlinkFrBack(linkerp));
}}
Ast{t}* unlinkFrBackWithNext(VNRelinker* linkerp = nullptr) {{
return static_cast<Ast{t}*>(AstNode::unlinkFrBackWithNext(linkerp));
}}
Ast{t}* cloneTree(bool cloneNext) {{
return static_cast<Ast{t}*>(AstNode::cloneTree(cloneNext));
}}
static Ast{t}* cloneTreeNull(Ast{t}* nodep, bool cloneNextLink) {{
return nodep ? nodep->cloneTree(cloneNextLink) : nullptr;
}}
Ast{t}* clonep() const VL_MT_SAFE {{ return static_cast<Ast{t}*>(AstNode::clonep()); }}
Ast{t}* addNext(Ast{t}* nodep) {{ return static_cast<Ast{t}*>(AstNode::addNext(this, nodep)); }}
''',

View File

@ -112,7 +112,7 @@ public:
}
// METHODS
AstArg* argWrapList(AstNode* nodep);
AstArg* argWrapList(AstNodeExpr* nodep);
bool allTracingOn(FileLine* fl) {
return v3Global.opt.trace() && m_tracingParse && fl->tracingOn();
}
@ -155,7 +155,7 @@ public:
AstNode::addNext<AstNode, AstNode>(nodep, new AstStop(fileline, true));
return nodep;
}
AstNode* createGatePin(AstNode* exprp) {
AstNodeExpr* createGatePin(AstNodeExpr* exprp) {
AstRange* const rangep = m_gateRangep;
if (!rangep) {
return exprp;
@ -2238,7 +2238,7 @@ enumNameRangeE<rangep>: // IEEE: second part of enum_name_declaration
{ $$ = new AstRange{$1, $2, $4}; }
;
enumNameStartE<nodep>: // IEEE: third part of enum_name_declaration
enumNameStartE<nodeExprp>: // IEEE: third part of enum_name_declaration
/* empty */ { $$ = nullptr; }
| '=' constExpr { $$ = $2; }
;
@ -2790,7 +2790,7 @@ delay_control<delayp>: //== IEEE: delay_control
{ $$ = new AstDelay{$<fl>1, $3}; RISEFALLDLYUNSUP($3); DEL($5); DEL($7); }
;
delay_value<nodep>: // ==IEEE:delay_value
delay_value<nodeExprp>: // ==IEEE:delay_value
// // IEEE: ps_identifier
packageClassScopeE varRefBase { $$ = AstDot::newIfPkg($<fl>2, $1, $2); }
| yaINTNUM { $$ = new AstConst($<fl>1, *$1); }
@ -2798,11 +2798,11 @@ delay_value<nodep>: // ==IEEE:delay_value
| timeNumAdjusted { $$ = $1; }
;
delayExpr<nodep>:
delayExpr<nodeExprp>:
expr { $$ = $1; }
;
minTypMax<nodep>: // IEEE: mintypmax_expression and constant_mintypmax_expression
minTypMax<nodeExprp>: // IEEE: mintypmax_expression and constant_mintypmax_expression
delayExpr { $$ = $1; }
| delayExpr ':' delayExpr ':' delayExpr { $$ = $3; MINTYPMAXDLYUNSUP($3); DEL($1); DEL($5); }
;
@ -3312,20 +3312,24 @@ statement_item<nodep>: // IEEE: statement_item
FileLine* const newfl = new FileLine{$$->fileline()};
newfl->warnOff(V3ErrorCode::IGNOREDRETURN, true);
$$->fileline(newfl);
if (AstNodeExpr* const exprp = VN_CAST($$, NodeExpr)) $$ = exprp->makeStmt(); }
$$ = VN_AS($$, NodeExpr)->makeStmt(); }
| yVOID yP_TICK '(' expr '.' task_subroutine_callNoMethod ')' ';'
{ $$ = new AstDot{$5, false, $4, $6};
FileLine* const newfl = new FileLine{$6->fileline()};
newfl->warnOff(V3ErrorCode::IGNOREDRETURN, true);
$6->fileline(newfl);
if (AstNodeExpr* const exprp = VN_CAST($$, NodeExpr)) $$ = exprp->makeStmt(); }
$$ = VN_AS($$, NodeExpr)->makeStmt(); }
| yVOID yP_TICK '(' system_t_call ')' ';'
{ $$ = $4;
FileLine* const newfl = new FileLine{$$->fileline()};
newfl->warnOff(V3ErrorCode::IGNOREDRETURN, true);
$$->fileline(newfl); }
// // Expr included here to resolve our not knowing what is a method call
// // Expr here must result in a subroutine_call
| task_subroutine_callNoMethod ';'
{ $$ = $1;
if (AstNodeExpr* const exprp = VN_CAST($$, NodeExpr)) $$ = exprp->makeStmt(); }
| task_subroutine_callNoMethod ';' { $$ = $1->makeStmt(); }
//UNSUP fexpr '.' array_methodNoRoot ';' { UNSUP }
| fexpr '.' task_subroutine_callNoMethod ';' { $$ = (new AstDot{$<fl>2, false, $1, $3})->makeStmt(); }
| system_t_call ';' { $$ = $1; }
//UNSUP fexprScope ';' { UNSUP }
// // Not here in IEEE; from class_constructor_declaration
// // Because we've joined class_constructor_declaration into generic functions
@ -3496,14 +3500,14 @@ finc_or_dec_expression<nodeExprp>: // ==IEEE: inc_or_dec_expression
//UNSUP BISONPRE_COPY(inc_or_dec_expression,{s/~l~/pev_/g}) // {copied}
//UNSUP ;
class_new<nodep>: // ==IEEE: class_new
class_new<nodeExprp>: // ==IEEE: class_new
// // Special precence so (...) doesn't match expr
yNEW__ETC { $$ = new AstNew($1, nullptr); }
| yNEW__ETC expr { $$ = new AstNewCopy($1, $2); }
| yNEW__PAREN '(' list_of_argumentsE ')' { $$ = new AstNew($1, $3); }
;
dynamic_array_new<nodep>: // ==IEEE: dynamic_array_new
dynamic_array_new<nodeExprp>: // ==IEEE: dynamic_array_new
yNEW__ETC '[' expr ']' { $$ = new AstNewDynamic($1, $3, nullptr); }
| yNEW__ETC '[' expr ']' '(' expr ')' { $$ = new AstNewDynamic($1, $3, $6); }
;
@ -3569,16 +3573,16 @@ rand_case_itemList<caseItemp>: // IEEE: { rand_case_item + ... }
| rand_case_itemList expr colon stmtBlock { $$ = $1->addNext(new AstCaseItem{$3, $2, $4}); }
;
open_range_list<nodep>: // ==IEEE: open_range_list + open_value_range
open_range_list<nodeExprp>: // ==IEEE: open_range_list + open_value_range
open_value_range { $$ = $1; }
| open_range_list ',' open_value_range { $$ = $1->addNext($3); }
;
open_value_range<nodep>: // ==IEEE: open_value_range
open_value_range<nodeExprp>: // ==IEEE: open_value_range
value_range { $$ = $1; }
;
value_range<nodep>: // ==IEEE: value_range
value_range<nodeExprp>: // ==IEEE: value_range
expr { $$ = $1; }
| '[' expr ':' expr ']' { $$ = new AstInsideRange($1, $2, $4); }
;
@ -3588,7 +3592,7 @@ value_range<nodep>: // ==IEEE: value_range
//UNSUP | '[' cgexpr ':' cgexpr ']' { }
//UNSUP ;
caseCondList<nodep>: // IEEE: part of case_item
caseCondList<nodeExprp>: // IEEE: part of case_item
expr { $$ = $1; }
| caseCondList ',' expr { $$ = $1->addNext($3); }
;
@ -3752,14 +3756,13 @@ funcRef<nodeExprp>: // IEEE: part of tf_call
//UNSUP: idDotted is really just id to allow dotted method calls
;
task_subroutine_callNoMethod<nodep>: // function_subroutine_callNoMethod (as task)
task_subroutine_callNoMethod<nodeExprp>: // function_subroutine_callNoMethod (as task)
// // IEEE: tf_call
taskRef { $$ = $1; }
// // funcref below not task ref to avoid conflict, must later handle either
| funcRef yWITH__PAREN '(' expr ')' { $$ = new AstWithParse{$2, $1, $4}; }
// // can call as method and yWITH without parenthesis
| id yWITH__PAREN '(' expr ')' { $$ = new AstWithParse{$2, new AstFuncRef{$<fl>1, *$1, nullptr}, $4}; }
| system_t_call { $$ = $1; }
// // IEEE: method_call requires a "." so is in expr
// // IEEE: ['std::'] not needed, as normal std package resolution will find it
// // IEEE: randomize_call
@ -3785,9 +3788,11 @@ function_subroutine_callNoMethod<nodeExprp>: // IEEE: function_subroutine
| funcRef yWITH__CUR '{' '}' { $$ = new AstWithParse{$2, $1, nullptr}; }
;
system_t_call<nodep>: // IEEE: system_tf_call (as task)
system_t_call<nodeStmtp>: // IEEE: system_tf_call (as task)
//
yaD_PLI systemDpiArgsE { $$ = new AstTaskRef($<fl>1, *$1, $2); VN_CAST($$, TaskRef)->pli(true); }
yaD_PLI systemDpiArgsE { AstTaskRef* const refp = new AstTaskRef{$<fl>1, *$1, $2};
refp->pli(true);
$$ = refp->makeStmt(); }
//
| yD_DUMPPORTS '(' idDotted ',' expr ')' { $$ = new AstDumpCtl($<fl>1, VDumpCtlType::FILE, $5); DEL($3);
$$->addNext(new AstDumpCtl($<fl>1, VDumpCtlType::VARS,
@ -3928,7 +3933,7 @@ system_f_call<nodeExprp>: // IEEE: system_tf_call (as func)
| system_f_call_or_t { $$ = $1; }
;
systemDpiArgsE<nodep>: // IEEE: part of system_if_call for aruments of $dpi call
systemDpiArgsE<argp>: // IEEE: part of system_if_call for aruments of $dpi call
parenE { $$ = nullptr; }
| '(' exprList ')' { $$ = GRAMMARP->argWrapList($2); }
;
@ -4088,7 +4093,7 @@ exprOrDataType<nodep>: // expr | data_type: combined to prevent conflic
//UNSUP | exprOrDataTypeList ',' exprOrDataType { $$ = addNextNull($1, $3); }
//UNSUP ;
list_of_argumentsE<nodep>: // IEEE: [list_of_arguments]
list_of_argumentsE<nodeExprp>: // IEEE: [list_of_arguments]
argsDottedList { $$ = $1; }
| argsExprListE
{ if (VN_IS($1, Arg) && VN_CAST($1, Arg)->emptyConnectNoNext()) {
@ -4325,7 +4330,7 @@ array_methodNoRoot<nodeFTaskRefp>:
| yUNIQUE { $$ = new AstFuncRef($1, "unique", nullptr); }
;
array_methodWith<nodep>:
array_methodWith<nodeExprp>:
array_methodNoRoot parenE { $$ = $1; }
| array_methodNoRoot parenE yWITH__PAREN '(' expr ')'
{ $$ = new AstWithParse{$3, $1, $5}; }
@ -4390,7 +4395,7 @@ dpi_tf_TraceInitE<cbool>: // Verilator extension
// ~p~ means this is a (p)arenthetized expression
// it will get replaced by "", or "s"equence
exprEqE<nodep>: // IEEE: optional '=' expression (part of param_assignment)
exprEqE<nodeExprp>: // IEEE: optional '=' expression (part of param_assignment)
// // constant_param_expression: '$' is in expr
/*empty*/ { $$ = nullptr; }
| '=' expr { $$ = $2; }
@ -4766,12 +4771,12 @@ commaVRDListE<nodep>:
| ',' vrdList { $$ = $2; }
;
argsExprList<nodep>: // IEEE: part of list_of_arguments (used where ,, isn't legal)
argsExprList<nodeExprp>: // IEEE: part of list_of_arguments (used where ,, isn't legal)
expr { $$ = $1; }
| argsExprList ',' expr { $$ = $1->addNext($3); }
;
argsExprListE<nodep>: // IEEE: part of list_of_arguments
argsExprListE<nodeExprp>: // IEEE: part of list_of_arguments
argsExprOneE { $$ = $1; }
| argsExprListE ',' argsExprOneE { $$ = $1->addNext($3); }
;
@ -4781,7 +4786,7 @@ argsExprListE<nodep>: // IEEE: part of list_of_arguments
//UNSUP | pev_argsExprListE ',' pev_argsExprOneE { $$ = addNextNull($1, $3); }
//UNSUP ;
argsExprOneE<nodep>: // IEEE: part of list_of_arguments
argsExprOneE<nodeExprp>: // IEEE: part of list_of_arguments
/*empty*/ { $$ = new AstArg(CRELINE(), "", nullptr); }
| expr { $$ = new AstArg($1->fileline(), "", $1); }
;
@ -4791,7 +4796,7 @@ argsExprOneE<nodep>: // IEEE: part of list_of_arguments
//UNSUP | pev_expr { $$ = $1; }
//UNSUP ;
argsDottedList<nodep>: // IEEE: part of list_of_arguments
argsDottedList<nodeExprp>: // IEEE: part of list_of_arguments
argsDotted { $$ = $1; }
| argsDottedList ',' argsDotted { $$ = addNextNull($1, $3); }
;
@ -4801,7 +4806,7 @@ argsDottedList<nodep>: // IEEE: part of list_of_arguments
//UNSUP | pev_argsDottedList ',' pev_argsDotted { $$ = addNextNull($1, $3); }
//UNSUP ;
argsDotted<nodep>: // IEEE: part of list_of_arguments
argsDotted<nodeExprp>: // IEEE: part of list_of_arguments
'.' idAny '(' ')' { $$ = new AstArg($<fl>2, *$2, nullptr); }
| '.' idAny '(' expr ')' { $$ = new AstArg($<fl>2, *$2, $4); }
;
@ -4811,7 +4816,7 @@ argsDotted<nodep>: // IEEE: part of list_of_arguments
//UNSUP | '.' idAny '(' pev_expr ')' { $$ = new AstArg($<fl>2, *$2, $4); }
//UNSUP ;
streaming_concatenation<nodeExprp>: // ==IEEE: streaming_concatenation
streaming_concatenation<nodeStreamp>: // ==IEEE: streaming_concatenation
// // Need to disambiguate {<< expr-{ ... expr-} stream_concat }
// // From {<< stream-{ ... stream-} }
// // Likewise simple_type's idScoped from constExpr's idScope
@ -4824,12 +4829,16 @@ streaming_concatenation<nodeExprp>: // ==IEEE: streaming_concatenation
| '{' yP_SRIGHT stream_concatenation '}'
{ $$ = new AstStreamR($2, $3, new AstConst($2, 1)); }
| '{' yP_SLEFT stream_expressionOrDataType stream_concatenation '}'
{ $$ = new AstStreamL($2, $4, $3); }
{ AstNodeExpr* const bitsp = VN_IS($3, NodeExpr) ? VN_AS($3, NodeExpr)
: new AstAttrOf{$1, VAttrType::DIM_BITS, $3};
$$ = new AstStreamL($2, $4, bitsp); }
| '{' yP_SRIGHT stream_expressionOrDataType stream_concatenation '}'
{ $$ = new AstStreamR($2, $4, $3); }
{ AstNodeExpr* const bitsp = VN_IS($3, NodeExpr) ? VN_AS($3, NodeExpr)
: new AstAttrOf{$1, VAttrType::DIM_BITS, $3};
$$ = new AstStreamR($2, $4, bitsp); }
;
stream_concatenation<nodep>: // ==IEEE: stream_concatenation
stream_concatenation<nodeExprp>: // ==IEEE: stream_concatenation
// // '{' { stream_expression } '}'
'{' cateList '}' { $$ = $2; }
;
@ -5017,24 +5026,24 @@ gateFront<nodep>:
| gateRangeE '(' { $$ = $1; $<fl>$ = $<fl>2; }
;
gateAndPinList<nodep>:
gateAndPinList<nodeExprp>:
gatePinExpr { $$ = $1; }
| gateAndPinList ',' gatePinExpr { $$ = new AstAnd($2,$1,$3); }
;
gateOrPinList<nodep>:
gateOrPinList<nodeExprp>:
gatePinExpr { $$ = $1; }
| gateOrPinList ',' gatePinExpr { $$ = new AstOr($2,$1,$3); }
;
gateXorPinList<nodep>:
gateXorPinList<nodeExprp>:
gatePinExpr { $$ = $1; }
| gateXorPinList ',' gatePinExpr { $$ = new AstXor($2,$1,$3); }
;
gateUnsupPinList<nodep>:
gateUnsupPinList<nodeExprp>:
gatePinExpr { $$ = $1; }
| gateUnsupPinList ',' gatePinExpr { $$ = $1->addNext($3); }
;
gatePinExpr<nodep>:
gatePinExpr<nodeExprp>:
expr { $$ = GRAMMARP->createGatePin($1); }
;
@ -5188,7 +5197,7 @@ idClassSel<nodeExprp>: // Misc Ref to dotted, and/or arraye
| packageClassScope idDotted { $$ = new AstDot($<fl>2, true, $1, $2); }
;
idClassSelForeach<nodep>:
idClassSelForeach<nodeExprp>:
idDottedForeach { $$ = $1; }
// // IEEE: [ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select
| yTHIS '.' idDottedForeach
@ -5206,7 +5215,7 @@ idDotted<nodeExprp>:
| idDottedMore { $$ = $1; }
;
idDottedForeach<nodep>:
idDottedForeach<nodeExprp>:
yD_ROOT '.' idDottedMoreForeach
{ $$ = new AstDot($2, false, new AstParseRef($<fl>1, VParseRefExp::PX_ROOT, "$root"), $3); }
| idDottedMoreForeach { $$ = $1; }
@ -5217,7 +5226,7 @@ idDottedMore<nodeExprp>:
| idDottedMore '.' idArrayed { $$ = new AstDot($2, false, $1, $3); }
;
idDottedMoreForeach<nodep>:
idDottedMoreForeach<nodeExprp>:
idArrayedForeach { $$ = $1; }
| idDottedMoreForeach '.' idArrayedForeach { $$ = new AstDot($2, false, $1, $3); }
;
@ -5238,7 +5247,7 @@ idArrayed<nodeExprp>: // IEEE: id + select
| idArrayed '[' expr yP_MINUSCOLON constExpr ']' { $$ = new AstSelMinus($2, $1, $3, $5); }
;
idArrayedForeach<nodep>: // IEEE: id + select (under foreach expression)
idArrayedForeach<nodeExprp>: // IEEE: id + select (under foreach expression)
id
{ $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, *$1, nullptr, nullptr); }
// // IEEE: id + part_select_range/constant_part_select_range
@ -5607,7 +5616,7 @@ sequence_formal_typeNoDt<nodeDTypep>: // ==IEEE: sequence_formal_type (w/o data
//UNSUP | sexpr ';' { $$ = $1; }
//UNSUP ;
property_spec<nodep>: // IEEE: property_spec
property_spec<propSpecp>: // IEEE: property_spec
//UNSUP: This rule has been super-specialized to what is supported now
//UNSUP remove below
'@' '(' senitemEdge ')' yDISABLE yIFF '(' expr ')' pexpr
@ -5686,7 +5695,7 @@ property_spec<nodep>: // IEEE: property_spec
//UNSUP | BISONPRE_COPY_ONCE(expr,{s/~l~/pev_/g; s/~p~/pev_/g; s/~noPar__IGNORE~/yP_PAR__IGNORE /g; }) // {copied}
//UNSUP ;
pexpr<nodep>: // IEEE: property_expr (The name pexpr is important as regexps just add an "p" to expr.)
pexpr<nodeExprp>: // IEEE: property_expr (The name pexpr is important as regexps just add an "p" to expr.)
//UNSUP: This rule has been super-specialized to what is supported now
//UNSUP remove below
//
@ -5701,7 +5710,7 @@ pexpr<nodep>: // IEEE: property_expr (The name pexpr is important as regexps j
| expr { $$ = $1; }
;
complex_pexpr<nodep>: // IEEE: part of property_expr, see comments there
complex_pexpr<nodeExprp>: // IEEE: part of property_expr, see comments there
expr yP_ORMINUSGT pexpr { $$ = new AstLogOr($2, new AstLogNot($2, $1), $3); }
| expr yP_OREQGT pexpr { $$ = new AstImplication($2, $1, $3); }
| yNOT pexpr %prec prNEGATION { $$ = new AstLogNot{$1, $2}; }
@ -6406,7 +6415,7 @@ packageClassScopeNoId<nodep>: // IEEE: [package_scope] not followed by yaID
packageClassScope { $$ = $1; $<scp>$ = $<scp>1; SYMP->nextId(nullptr); }
;
packageClassScopeE<nodep>: // IEEE: [package_scope]
packageClassScopeE<nodeExprp>: // IEEE: [package_scope]
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // TODO: To support classes should return generic type, not packagep
@ -6415,7 +6424,7 @@ packageClassScopeE<nodep>: // IEEE: [package_scope]
| packageClassScope { $$ = $1; $<scp>$ = $<scp>1; }
;
packageClassScope<nodep>: // IEEE: class_scope
packageClassScope<nodeExprp>: // IEEE: class_scope
// // IEEE: "class_type yP_COLONCOLON"
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
@ -6428,7 +6437,7 @@ packageClassScope<nodep>: // IEEE: class_scope
{ $$ = new AstDot($2, true, $1, $3); $<scp>$ = $<scp>3; }
;
packageClassScopeList<nodep>: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
packageClassScopeList<nodeExprp>: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
// // Or IEEE: [package_scope]
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
@ -6439,7 +6448,7 @@ packageClassScopeList<nodep>: // IEEE: class_type: "id [ parameter_value_assig
{ $$ = new AstDot($<fl>2, true, $1, $2); $<scp>$ = $<scp>2; }
;
packageClassScopeItem<nodep>: // IEEE: package_scope or [package_scope]::[class_scope]
packageClassScopeItem<nodeExprp>: // IEEE: package_scope or [package_scope]::[class_scope]
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
@ -6455,7 +6464,7 @@ packageClassScopeItem<nodep>: // IEEE: package_scope or [package_scope]::[clas
{ $$ = new AstClassOrPackageRef($<fl>1, *$1, $<scp>1, $2); $<scp>$ = $<scp>1; }
;
dollarUnitNextId<nodep>: // $unit
dollarUnitNextId<nodeExprp>: // $unit
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // Must call nextId without any additional tokens following
@ -6464,7 +6473,7 @@ dollarUnitNextId<nodep>: // $unit
SYMP->nextId(PARSEP->rootp()); }
;
localNextId<nodep>: // local
localNextId<nodeExprp>: // local
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // Must call nextId without any additional tokens following

View File

@ -0,0 +1,15 @@
%Error: t/t_stream_bad.v:12:32: Expecting expression to be constant, but can't convert a RAND to constant.
: ... In instance t
12 | initial packed_data_32 = {<<$random{byte_in}};
| ^~~~~~~
%Error: t/t_stream_bad.v:12:30: Slice size isn't a constant or basic data type.
: ... In instance t
12 | initial packed_data_32 = {<<$random{byte_in}};
| ^~
%Warning-WIDTH: t/t_stream_bad.v:12:27: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's STREAML generates 8 bits.
: ... In instance t
12 | initial packed_data_32 = {<<$random{byte_in}};
| ^
... For warning description see https://verilator.org/warn/WIDTH?v=latest
... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.
%Error: Exiting due to

19
test_regress/t/t_stream_bad.pl Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,14 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Geza Lore.
// SPDX-License-Identifier: CC0-1.0
module t;
logic [31:0] packed_data_32;
byte byte_in[4];
initial packed_data_32 = {<<$random{byte_in}};
endmodule

View File

@ -72,63 +72,115 @@
: ... In instance t
136 | {<<32{reg_out}} = v_packed_data_128;
| ^
%Error: t/t_stream_integer_type.v:150:33: Operator STREAML expected non-datatype RHS but 'byte' is a datatype.
: ... In instance t
150 | packed_data_32 = {<<byte{byte_in}};
| ^~~~
%Warning-WIDTH: t/t_stream_integer_type.v:150:28: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's STREAML generates 8 bits.
: ... In instance t
150 | packed_data_32 = {<<byte{byte_in}};
| ^
%Error: t/t_stream_integer_type.v:151:33: Operator STREAML expected non-datatype RHS but 'shortint' is a datatype.
: ... In instance t
151 | packed_data_64 = {<<shortint{shortint_in}};
| ^~~~~~~~
%Warning-WIDTH: t/t_stream_integer_type.v:151:28: Operator ASSIGN expects 64 bits on the Assign RHS, but Assign RHS's STREAML generates 16 bits.
: ... In instance t
151 | packed_data_64 = {<<shortint{shortint_in}};
| ^
%Error: t/t_stream_integer_type.v:152:33: Operator STREAML expected non-datatype RHS but 'int' is a datatype.
: ... In instance t
152 | packed_data_128 = {<<int{int_in}};
| ^~~
%Warning-WIDTH: t/t_stream_integer_type.v:152:28: Operator ASSIGN expects 128 bits on the Assign RHS, but Assign RHS's STREAML generates 32 bits.
: ... In instance t
152 | packed_data_128 = {<<int{int_in}};
| ^
%Error: t/t_stream_integer_type.v:153:33: Operator STREAML expected non-datatype RHS but 'integer' is a datatype.
: ... In instance t
153 | packed_data_128_i = {<<integer{integer_in}};
| ^~~~~~~
%Warning-WIDTH: t/t_stream_integer_type.v:153:28: Operator ASSIGN expects 128 bits on the Assign RHS, but Assign RHS's STREAML generates 32 bits.
: ... In instance t
153 | packed_data_128_i = {<<integer{integer_in}};
| ^
%Error: t/t_stream_integer_type.v:154:33: Operator STREAML expected non-datatype RHS but 'longint' is a datatype.
: ... In instance t
154 | packed_data_256 = {<<longint{longint_in}};
| ^~~~~~~
%Warning-WIDTH: t/t_stream_integer_type.v:154:28: Operator ASSIGN expects 256 bits on the Assign RHS, but Assign RHS's STREAML generates 64 bits.
: ... In instance t
154 | packed_data_256 = {<<longint{longint_in}};
| ^
%Error: t/t_stream_integer_type.v:155:33: Operator STREAML expected non-datatype RHS but 'time' is a datatype.
: ... In instance t
155 | packed_time_256 = {<<time{time_in}};
| ^~~~
%Warning-WIDTH: t/t_stream_integer_type.v:155:28: Operator ASSIGN expects 256 bits on the Assign RHS, but Assign RHS's STREAML generates 64 bits.
: ... In instance t
155 | packed_time_256 = {<<time{time_in}};
| ^
%Error: t/t_stream_integer_type.v:156:33: Operator STREAML expected non-datatype RHS but 'test_byte' is a datatype.
: ... In instance t
156 | v_packed_data_32 = {<<test_byte{bit_in}};
| ^~~~~~~~~
%Error: t/t_stream_integer_type.v:156:31: Slice size isn't a constant or basic data type.
: ... In instance t
156 | v_packed_data_32 = {<<test_byte{bit_in}};
| ^~
%Error: Internal Error: t/t_stream_integer_type.v:156:28: ../V3Width.cpp:#: Node has no type
: ... In instance t
%Warning-WIDTH: t/t_stream_integer_type.v:156:28: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's STREAML generates 8 bits.
: ... In instance t
156 | v_packed_data_32 = {<<test_byte{bit_in}};
| ^
%Warning-WIDTH: t/t_stream_integer_type.v:157:28: Operator ASSIGN expects 64 bits on the Assign RHS, but Assign RHS's STREAML generates 16 bits.
: ... In instance t
157 | v_packed_data_64 = {<<test_short{logic_in}};
| ^
%Warning-WIDTH: t/t_stream_integer_type.v:158:28: Operator ASSIGN expects 128 bits on the Assign RHS, but Assign RHS's STREAML generates 32 bits.
: ... In instance t
158 | v_packed_data_128 = {<<test_word{reg_in}};
| ^
%Warning-WIDTH: t/t_stream_integer_type.v:160:37: Operator ASSIGN expects 8 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_32' generates 32 bits.
: ... In instance t
160 | {<<byte{byte_out}} = packed_data_32;
| ^
%Warning-WIDTH: t/t_stream_integer_type.v:161:37: Operator ASSIGN expects 16 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_64' generates 64 bits.
: ... In instance t
161 | {<<shortint{shortint_out}} = packed_data_64;
| ^
%Warning-WIDTH: t/t_stream_integer_type.v:162:37: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_128' generates 128 bits.
: ... In instance t
162 | {<<int{int_out}} = packed_data_128;
| ^
%Warning-WIDTH: t/t_stream_integer_type.v:163:37: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_128_i' generates 128 bits.
: ... In instance t
163 | {<<integer{integer_out}} = packed_data_128_i;
| ^
%Warning-WIDTH: t/t_stream_integer_type.v:164:37: Operator ASSIGN expects 64 bits on the Assign RHS, but Assign RHS's VARREF 'packed_data_256' generates 256 bits.
: ... In instance t
164 | {<<longint{longint_out}} = packed_data_256;
| ^
%Warning-WIDTH: t/t_stream_integer_type.v:165:37: Operator ASSIGN expects 64 bits on the Assign RHS, but Assign RHS's VARREF 'packed_time_256' generates 256 bits.
: ... In instance t
165 | {<<time{time_out}} = packed_time_256;
| ^
%Warning-WIDTH: t/t_stream_integer_type.v:166:37: Operator ASSIGN expects 8 bits on the Assign RHS, but Assign RHS's VARREF 'v_packed_data_32' generates 32 bits.
: ... In instance t
166 | {<<test_byte{bit_out}} = v_packed_data_32;
| ^
%Warning-WIDTH: t/t_stream_integer_type.v:167:37: Operator ASSIGN expects 16 bits on the Assign RHS, but Assign RHS's VARREF 'v_packed_data_64' generates 64 bits.
: ... In instance t
167 | {<<test_short{logic_out}} = v_packed_data_64;
| ^
%Warning-WIDTH: t/t_stream_integer_type.v:168:37: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS's VARREF 'v_packed_data_128' generates 128 bits.
: ... In instance t
168 | {<<test_word{reg_out}} = v_packed_data_128;
| ^
%Error: t/t_stream_integer_type.v:128:11: SEL is not an unpacked array, but is in an unpacked array context
128 | {<<8{byte_out}} = packed_data_32;
| ^~
%Error: t/t_stream_integer_type.v:129:11: SEL is not an unpacked array, but is in an unpacked array context
129 | {<<16{shortint_out}} = packed_data_64;
| ^~
%Error: t/t_stream_integer_type.v:130:11: SEL is not an unpacked array, but is in an unpacked array context
130 | {<<32{int_out}} = packed_data_128;
| ^~
%Error: t/t_stream_integer_type.v:131:11: SEL is not an unpacked array, but is in an unpacked array context
131 | {<<32{integer_out}} = packed_data_128_i;
| ^~
%Error: t/t_stream_integer_type.v:132:11: SEL is not an unpacked array, but is in an unpacked array context
132 | {<<64{longint_out}} = packed_data_256;
| ^~
%Error: t/t_stream_integer_type.v:133:11: SEL is not an unpacked array, but is in an unpacked array context
133 | {<<64{time_out}} = packed_time_256;
| ^~
%Error: t/t_stream_integer_type.v:134:11: SEL is not an unpacked array, but is in an unpacked array context
134 | {<<8{bit_out}} = v_packed_data_32;
| ^~
%Error: t/t_stream_integer_type.v:135:11: SEL is not an unpacked array, but is in an unpacked array context
135 | {<<16{logic_out}} = v_packed_data_64;
| ^~
%Error: t/t_stream_integer_type.v:136:11: SEL is not an unpacked array, but is in an unpacked array context
136 | {<<32{reg_out}} = v_packed_data_128;
| ^~
%Error: t/t_stream_integer_type.v:160:11: SEL is not an unpacked array, but is in an unpacked array context
160 | {<<byte{byte_out}} = packed_data_32;
| ^~
%Error: t/t_stream_integer_type.v:161:11: SEL is not an unpacked array, but is in an unpacked array context
161 | {<<shortint{shortint_out}} = packed_data_64;
| ^~
%Error: t/t_stream_integer_type.v:162:11: SEL is not an unpacked array, but is in an unpacked array context
162 | {<<int{int_out}} = packed_data_128;
| ^~
%Error: t/t_stream_integer_type.v:163:11: SEL is not an unpacked array, but is in an unpacked array context
163 | {<<integer{integer_out}} = packed_data_128_i;
| ^~
%Error: Exiting due to