From 1899a875a4ff9932364fa30a9faae29b9f610fb4 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 7 Sep 2020 17:09:25 -0400 Subject: [PATCH] Internals: Create VAccess class. No functional change intended. --- src/V3Assert.cpp | 6 +-- src/V3Ast.h | 41 +++++++++++++++---- src/V3AstNodes.cpp | 4 +- src/V3AstNodes.h | 28 ++++++------- src/V3Broken.cpp | 2 +- src/V3CCtors.cpp | 7 ++-- src/V3Cast.cpp | 6 +-- src/V3Cdc.cpp | 2 +- src/V3Changed.cpp | 6 +-- src/V3Clock.cpp | 29 ++++++++------ src/V3Const.cpp | 32 ++++++++------- src/V3Coverage.cpp | 9 +++-- src/V3Delayed.cpp | 49 +++++++++++++---------- src/V3Depth.cpp | 6 +-- src/V3Descope.cpp | 5 ++- src/V3Expand.cpp | 2 +- src/V3Gate.cpp | 13 +++--- src/V3GenClk.cpp | 10 ++--- src/V3Inline.cpp | 24 ++++++----- src/V3Inst.cpp | 33 ++++++++------- src/V3Life.cpp | 2 +- src/V3LifePost.cpp | 4 +- src/V3LinkDot.cpp | 24 ++++++----- src/V3LinkInc.cpp | 21 +++++----- src/V3LinkJump.cpp | 14 +++---- src/V3LinkLValue.cpp | 40 +++++++++---------- src/V3LinkLevel.cpp | 7 ++-- src/V3LinkParse.cpp | 29 ++++++++------ src/V3LinkResolve.cpp | 8 ++-- src/V3Localize.cpp | 2 +- src/V3MergeCond.cpp | 2 +- src/V3Order.cpp | 5 ++- src/V3Param.cpp | 2 +- src/V3ParseGrammar.cpp | 2 +- src/V3Premit.cpp | 8 ++-- src/V3Reloop.cpp | 14 +++---- src/V3Simulate.h | 4 +- src/V3Split.cpp | 4 +- src/V3SplitAs.cpp | 4 +- src/V3SplitVar.cpp | 91 +++++++++++++++++++++++------------------- src/V3Subst.cpp | 6 +-- src/V3Table.cpp | 23 ++++++----- src/V3Task.cpp | 35 ++++++++-------- src/V3Trace.cpp | 16 ++++---- src/V3TraceDecl.cpp | 2 +- src/V3Tristate.cpp | 75 ++++++++++++++++++---------------- src/V3Undriven.cpp | 12 +++--- src/V3Unknown.cpp | 25 ++++++------ src/V3Unroll.cpp | 4 +- src/V3Width.cpp | 40 +++++++++---------- src/V3WidthSel.cpp | 2 +- src/verilog.y | 13 +++--- 52 files changed, 470 insertions(+), 384 deletions(-) diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index b4205e0a1..981d705ae 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -317,12 +317,12 @@ private: "_Vpast_" + cvtToStr(m_modPastNum++) + "_" + cvtToStr(i), inp->dtypep()); m_modp->addStmtp(outvarp); - AstNode* assp = new AstAssignDly(nodep->fileline(), - new AstVarRef(nodep->fileline(), outvarp, true), inp); + AstNode* assp = new AstAssignDly( + nodep->fileline(), new AstVarRef(nodep->fileline(), outvarp, VAccess::WRITE), inp); alwaysp->addStmtp(assp); // if (debug() >= 9) assp->dumpTree(cout, "-ass: "); invarp = outvarp; - inp = new AstVarRef(nodep->fileline(), invarp, false); + inp = new AstVarRef(nodep->fileline(), invarp, VAccess::READ); } nodep->replaceWith(inp); } diff --git a/src/V3Ast.h b/src/V3Ast.h index 636f45df1..c7c44c5cb 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -123,6 +123,33 @@ inline std::ostream& operator<<(std::ostream& os, const VLifetime& rhs) { //###################################################################### +class VAccess { +public: + enum en : uint8_t { READ, WRITE }; + enum en m_e; + const char* ascii() const { + static const char* const names[] = {"RD", "WR"}; + return names[m_e]; + } + inline VAccess() + : m_e{READ} {} + // cppcheck-suppress noExplicitConstructor + inline VAccess(en _e) + : m_e{_e} {} + explicit inline VAccess(int _e) + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning + operator en() const { return m_e; } + VAccess invert() const { return (m_e == WRITE) ? VAccess(READ) : VAccess(WRITE); } + bool isRead() const { return m_e == READ; } + bool isWrite() const { return m_e == WRITE; } +}; +inline bool operator==(const VAccess& lhs, const VAccess& rhs) { return lhs.m_e == rhs.m_e; } +inline bool operator==(const VAccess& lhs, VAccess::en rhs) { return lhs.m_e == rhs; } +inline bool operator==(VAccess::en lhs, const VAccess& rhs) { return lhs == rhs.m_e; } +inline std::ostream& operator<<(std::ostream& os, const VAccess& rhs) { return os << rhs.ascii(); } + +//###################################################################### + class VSigning { public: enum en : uint8_t { @@ -2255,7 +2282,7 @@ public: class AstNodeVarRef : public AstNodeMath { // An AstVarRef or AstVarXRef private: - bool m_lvalue; // Left hand side assignment + VAccess m_access; // Left hand side assignment AstVar* m_varp; // [AfterLink] Pointer to variable itself AstVarScope* m_varScopep = nullptr; // Varscope for hierarchy AstNodeModule* m_packagep = nullptr; // Package hierarchy @@ -2264,15 +2291,15 @@ private: bool m_hierThis = false; // Hiername points to "this" function public: - AstNodeVarRef(AstType t, FileLine* fl, const string& name, bool lvalue) + AstNodeVarRef(AstType t, FileLine* fl, const string& name, const VAccess& access) : AstNodeMath{t, fl} - , m_lvalue{lvalue} + , m_access{access} , m_name{name} { this->varp(nullptr); } - AstNodeVarRef(AstType t, FileLine* fl, const string& name, AstVar* varp, bool lvalue) + AstNodeVarRef(AstType t, FileLine* fl, const string& name, AstVar* varp, const VAccess& access) : AstNodeMath{t, fl} - , m_lvalue{lvalue} + , m_access{access} , m_name{name} { // May have varp==nullptr this->varp(varp); @@ -2284,8 +2311,8 @@ public: virtual void cloneRelink() override; virtual string name() const override { return m_name; } // * = Var name virtual void name(const string& name) override { m_name = name; } - bool lvalue() const { return m_lvalue; } - void lvalue(bool lval) { m_lvalue = lval; } // Avoid using this; Set in constructor + VAccess access() const { return m_access; } + void access(const VAccess& flag) { m_access = flag; } // Avoid using this; Set in constructor AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable void varp(AstVar* varp); AstVarScope* varScopep() const { return m_varScopep; } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 8f140aa9e..e68988cf4 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1431,7 +1431,7 @@ void AstVarScope::dump(std::ostream& str) const { void AstVarXRef::dump(std::ostream& str) const { this->AstNode::dump(str); if (packagep()) { str << " pkg=" << nodeAddr(packagep()); } - if (lvalue()) { + if (access().isWrite()) { str << " [LV] => "; } else { str << " [RV] <- "; @@ -1449,7 +1449,7 @@ void AstVarXRef::dump(std::ostream& str) const { void AstVarRef::dump(std::ostream& str) const { this->AstNode::dump(str); if (packagep()) { str << " pkg=" << nodeAddr(packagep()); } - if (lvalue()) { + if (access().isWrite()) { str << " [LV] => "; } else { str << " [RV] <- "; diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index f4dd547ff..c3d4ba8f1 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1669,7 +1669,7 @@ class AstSel : public AstNodeTriop { // Multiple bit range extraction // Parents: math|stmt // Children: varref|arraysel, math, constant math - // Tempting to have an lvalue() style method here as LHS selects are quite + // Tempting to have an access() style method here as LHS selects are quite // different, but that doesn't play well with V3Inst and bidirects which don't know direction private: VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid @@ -2319,15 +2319,15 @@ public: class AstVarRef : public AstNodeVarRef { // A reference to a variable (lvalue or rvalue) public: - AstVarRef(FileLine* fl, const string& name, bool lvalue) - : ASTGEN_SUPER(fl, name, nullptr, lvalue) {} + AstVarRef(FileLine* fl, const string& name, const VAccess& access) + : ASTGEN_SUPER(fl, name, nullptr, access) {} // This form only allowed post-link because output/wire compression may // lead to deletion of AstVar's - AstVarRef(FileLine* fl, AstVar* varp, bool lvalue) - : ASTGEN_SUPER(fl, varp->name(), varp, lvalue) {} + AstVarRef(FileLine* fl, AstVar* varp, const VAccess& access) + : ASTGEN_SUPER(fl, varp->name(), varp, access) {} // This form only allowed post-link (see above) - AstVarRef(FileLine* fl, AstVarScope* varscp, bool lvalue) - : ASTGEN_SUPER(fl, varscp->varp()->name(), varscp->varp(), lvalue) { + AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access) + : ASTGEN_SUPER(fl, varscp->varp()->name(), varscp->varp(), access) { varScopep(varscp); } ASTNODE_NODE_FUNCS(VarRef) @@ -2340,10 +2340,10 @@ public: } inline bool same(const AstVarRef* samep) const { if (varScopep()) { - return (varScopep() == samep->varScopep() && lvalue() == samep->lvalue()); + return (varScopep() == samep->varScopep() && access() == samep->access()); } else { return (hiername() == samep->hiername() && varp()->name() == samep->varp()->name() - && lvalue() == samep->lvalue()); + && access() == samep->access()); } } inline bool sameNoLvalue(AstVarRef* samep) const { @@ -2354,7 +2354,7 @@ public: } } virtual int instrCount() const override { - return widthInstrs() * (lvalue() ? 1 : instrCountLd()); + return widthInstrs() * (access().isWrite() ? 1 : instrCountLd()); } virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } virtual string emitC() override { V3ERROR_NA_RETURN(""); } @@ -2368,11 +2368,11 @@ private: string m_dotted; // Dotted part of scope the name()'ed reference is under or "" string m_inlinedDots; // Dotted hierarchy flattened out public: - AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue) - : ASTGEN_SUPER(fl, name, nullptr, lvalue) + AstVarXRef(FileLine* fl, const string& name, const string& dotted, const VAccess& access) + : ASTGEN_SUPER(fl, name, nullptr, access) , m_dotted{dotted} {} - AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, bool lvalue) - : ASTGEN_SUPER(fl, varp->name(), varp, lvalue) + AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, const VAccess& access) + : ASTGEN_SUPER(fl, varp->name(), varp, access) , m_dotted{dotted} { dtypeFrom(varp); } diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index 4af93f4ec..9c1082689 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -275,7 +275,7 @@ private: processAndIterate(nodep); UASSERT_OBJ(!(v3Global.assertDTypesResolved() && nodep->brokeLhsMustBeLvalue() && VN_IS(nodep->lhsp(), NodeVarRef) - && !VN_CAST(nodep->lhsp(), NodeVarRef)->lvalue()), + && !VN_CAST(nodep->lhsp(), NodeVarRef)->access().isWrite()), nodep, "Assignment LHS is not an lvalue"); } virtual void visit(AstNode* nodep) override { diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index 55c60685e..94a0b1306 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -111,7 +111,7 @@ void V3CCtors::evalAsserts() { int lastWordWidth = varp->width() % storedWidth; if (lastWordWidth != 0) { // if (signal & CONST(upper_non_clean_mask)) { fail; } - AstNode* newp = new AstVarRef(varp->fileline(), varp, false); + AstNode* newp = new AstVarRef(varp->fileline(), varp, VAccess::READ); if (varp->isWide()) { newp = new AstWordSel( varp->fileline(), newp, @@ -151,8 +151,9 @@ void V3CCtors::cctorsAll() { for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) { if (AstVar* varp = VN_CAST(np, Var)) { if (!varp->isIfaceParent() && !varp->isIfaceRef() && !varp->noReset()) { - var_reset.add(new AstCReset(varp->fileline(), - new AstVarRef(varp->fileline(), varp, true))); + var_reset.add( + new AstCReset(varp->fileline(), + new AstVarRef(varp->fileline(), varp, VAccess::WRITE))); } } } diff --git a/src/V3Cast.cpp b/src/V3Cast.cpp index 66fb537c0..1f0fb7d86 100644 --- a/src/V3Cast.cpp +++ b/src/V3Cast.cpp @@ -154,9 +154,9 @@ private: } } virtual void visit(AstVarRef* nodep) override { - if (!nodep->lvalue() && !VN_IS(nodep->backp(), CCast) && VN_IS(nodep->backp(), NodeMath) - && !VN_IS(nodep->backp(), ArraySel) && nodep->backp()->width() - && castSize(nodep) != castSize(nodep->varp())) { + if (nodep->access().isRead() && !VN_IS(nodep->backp(), CCast) + && VN_IS(nodep->backp(), NodeMath) && !VN_IS(nodep->backp(), ArraySel) + && nodep->backp()->width() && castSize(nodep) != castSize(nodep->varp())) { // Cast vars to IData first, else below has upper bits wrongly set // CData x=3; out = (QData)(x<<30); insertCast(nodep, castSize(nodep)); diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp index 24f9703aa..72d4bc243 100644 --- a/src/V3Cdc.cpp +++ b/src/V3Cdc.cpp @@ -661,7 +661,7 @@ private: // We use weight of one for normal edges, // Weight of CDC_WEIGHT_ASYNC to indicate feeds async (for reporting) // When simplify we'll take the MAX weight - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1); if (m_inDly) { varvertexp->fromFlop(true); diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index 471d0d03c..922d0686c 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -199,9 +199,9 @@ public: m_newvscp = new AstVarScope(m_vscp->fileline(), m_statep->m_scopetopp, newvarp); m_statep->m_scopetopp->addVarp(m_newvscp); - m_varEqnp = new AstVarRef(m_vscp->fileline(), m_vscp, false); - m_newLvEqnp = new AstVarRef(m_vscp->fileline(), m_newvscp, true); - m_newRvEqnp = new AstVarRef(m_vscp->fileline(), m_newvscp, false); + m_varEqnp = new AstVarRef(m_vscp->fileline(), m_vscp, VAccess::READ); + m_newLvEqnp = new AstVarRef(m_vscp->fileline(), m_newvscp, VAccess::WRITE); + m_newRvEqnp = new AstVarRef(m_vscp->fileline(), m_newvscp, VAccess::READ); } iterate(vscp->dtypep()->skipRefp()); m_varEqnp->deleteTree(); diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index 378bf4245..1c39a0c9b 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -79,15 +79,15 @@ private: vscp->user1p(newvscp); m_scopep->addVarp(newvscp); // Add init - AstNode* fromp = new AstVarRef(newvarp->fileline(), vscp, false); + AstNode* fromp = new AstVarRef(newvarp->fileline(), vscp, VAccess::READ); if (v3Global.opt.xInitialEdge()) fromp = new AstNot(fromp->fileline(), fromp); AstNode* newinitp = new AstAssign( - vscp->fileline(), new AstVarRef(newvarp->fileline(), newvscp, true), fromp); + vscp->fileline(), new AstVarRef(newvarp->fileline(), newvscp, VAccess::WRITE), fromp); addToInitial(newinitp); // At bottom, assign them - AstAssign* finalp - = new AstAssign(vscp->fileline(), new AstVarRef(vscp->fileline(), newvscp, true), - new AstVarRef(vscp->fileline(), vscp, false)); + AstAssign* finalp = new AstAssign(vscp->fileline(), + new AstVarRef(vscp->fileline(), newvscp, VAccess::WRITE), + new AstVarRef(vscp->fileline(), vscp, VAccess::READ)); m_evalFuncp->addFinalsp(finalp); // UINFO(4, "New Last: " << newvscp << endl); @@ -112,25 +112,28 @@ private: AstVarScope* lastVscp = getCreateLastClk(clkvscp); newp = new AstAnd( nodep->fileline(), - new AstVarRef(nodep->fileline(), nodep->varrefp()->varScopep(), false), - new AstNot(nodep->fileline(), new AstVarRef(nodep->fileline(), lastVscp, false))); + new AstVarRef(nodep->fileline(), nodep->varrefp()->varScopep(), VAccess::READ), + new AstNot(nodep->fileline(), + new AstVarRef(nodep->fileline(), lastVscp, VAccess::READ))); } else if (nodep->edgeType() == VEdgeType::ET_NEGEDGE) { AstVarScope* lastVscp = getCreateLastClk(clkvscp); newp = new AstAnd( nodep->fileline(), new AstNot(nodep->fileline(), - new AstVarRef(nodep->fileline(), nodep->varrefp()->varScopep(), false)), - new AstVarRef(nodep->fileline(), lastVscp, false)); + new AstVarRef(nodep->fileline(), nodep->varrefp()->varScopep(), + VAccess::READ)), + new AstVarRef(nodep->fileline(), lastVscp, VAccess::READ)); } else if (nodep->edgeType() == VEdgeType::ET_BOTHEDGE) { AstVarScope* lastVscp = getCreateLastClk(clkvscp); newp = new AstXor( nodep->fileline(), - new AstVarRef(nodep->fileline(), nodep->varrefp()->varScopep(), false), - new AstVarRef(nodep->fileline(), lastVscp, false)); + new AstVarRef(nodep->fileline(), nodep->varrefp()->varScopep(), VAccess::READ), + new AstVarRef(nodep->fileline(), lastVscp, VAccess::READ)); } else if (nodep->edgeType() == VEdgeType::ET_HIGHEDGE) { - newp = new AstVarRef(nodep->fileline(), clkvscp, false); + newp = new AstVarRef(nodep->fileline(), clkvscp, VAccess::READ); } else if (nodep->edgeType() == VEdgeType::ET_LOWEDGE) { - newp = new AstNot(nodep->fileline(), new AstVarRef(nodep->fileline(), clkvscp, false)); + newp = new AstNot(nodep->fileline(), + new AstVarRef(nodep->fileline(), clkvscp, VAccess::READ)); } else { nodep->v3fatalSrc("Bad edge type"); } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index ef617c634..bfadcab72 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -314,7 +314,7 @@ private: // It was an expression, then got constified. In reality, the WordSel // must be wrapped in a Cond, that will be false. return (VN_IS(nodep->rhsp(), Const) && VN_IS(nodep->fromp(), NodeVarRef) - && !VN_CAST_CONST(nodep->fromp(), NodeVarRef)->lvalue() + && !VN_CAST_CONST(nodep->fromp(), NodeVarRef)->access().isWrite() && (static_cast(VN_CAST_CONST(nodep->rhsp(), Const)->toUInt()) >= VN_CAST(nodep->fromp(), NodeVarRef)->varp()->widthWords())); } @@ -1132,18 +1132,22 @@ private: VFlagLogicPacked(), msb2 - lsb2 + 1); m_modp->addStmtp(temp1p); m_modp->addStmtp(temp2p); - AstNodeAssign* asn1ap = VN_CAST( - nodep->cloneType(new AstVarRef(sel1p->fileline(), temp1p, true), sel1p), - NodeAssign); - AstNodeAssign* asn2ap = VN_CAST( - nodep->cloneType(new AstVarRef(sel2p->fileline(), temp2p, true), sel2p), - NodeAssign); - AstNodeAssign* asn1bp = VN_CAST( - nodep->cloneType(lc1p, new AstVarRef(sel1p->fileline(), temp1p, false)), - NodeAssign); - AstNodeAssign* asn2bp = VN_CAST( - nodep->cloneType(lc2p, new AstVarRef(sel2p->fileline(), temp2p, false)), - NodeAssign); + AstNodeAssign* asn1ap + = VN_CAST(nodep->cloneType( + new AstVarRef(sel1p->fileline(), temp1p, VAccess::WRITE), sel1p), + NodeAssign); + AstNodeAssign* asn2ap + = VN_CAST(nodep->cloneType( + new AstVarRef(sel2p->fileline(), temp2p, VAccess::WRITE), sel2p), + NodeAssign); + AstNodeAssign* asn1bp + = VN_CAST(nodep->cloneType( + lc1p, new AstVarRef(sel1p->fileline(), temp1p, VAccess::READ)), + NodeAssign); + AstNodeAssign* asn2bp + = VN_CAST(nodep->cloneType( + lc2p, new AstVarRef(sel2p->fileline(), temp2p, VAccess::READ)), + NodeAssign); asn1ap->dtypeFrom(temp1p); asn1bp->dtypeFrom(temp1p); asn2ap->dtypeFrom(temp2p); @@ -1601,7 +1605,7 @@ private: // if (debug()) valuep->dumpTree(cout, " visitvaref: "); iterateAndNextNull(nodep->varp()->valuep()); // May change nodep->varp()->valuep() AstNode* valuep = nodep->varp()->valuep(); - if (!nodep->lvalue() + if (!nodep->access().isWrite() && ((!m_params // Can reduce constant wires into equations && m_doNConst && v3Global.opt.oConst() diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index f371d4fa8..344d24d28 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -130,8 +130,8 @@ private: m_modp->addStmtp(varp); UINFO(5, "New coverage trace: " << varp << endl); AstAssign* assp = new AstAssign( - incp->fileline(), new AstVarRef(incp->fileline(), varp, true), - new AstAdd(incp->fileline(), new AstVarRef(incp->fileline(), varp, false), + incp->fileline(), new AstVarRef(incp->fileline(), varp, VAccess::WRITE), + new AstAdd(incp->fileline(), new AstVarRef(incp->fileline(), varp, VAccess::READ), new AstConst(incp->fileline(), AstConst::WidthedValue(), 32, 1))); incp->addNext(assp); } @@ -288,8 +288,9 @@ private: // This is necessarily an O(n^2) expansion, which is why // we limit coverage to signals with < 256 bits. - ToggleEnt newvec(string(""), new AstVarRef(nodep->fileline(), nodep, false), - new AstVarRef(nodep->fileline(), chgVarp, true)); + ToggleEnt newvec(string(""), + new AstVarRef(nodep->fileline(), nodep, VAccess::READ), + new AstVarRef(nodep->fileline(), chgVarp, VAccess::WRITE)); toggleVarRecurse(nodep->dtypeSkipRefp(), 0, newvec, nodep, chgVarp); newvec.cleanup(); } diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index 4ba1acb24..c042968f9 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -228,9 +228,10 @@ private: AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, dimp->width(), nullptr); AstAssign* bitassignp = new AstAssign( - nodep->fileline(), new AstVarRef(nodep->fileline(), bitvscp, true), dimp); + nodep->fileline(), new AstVarRef(nodep->fileline(), bitvscp, VAccess::WRITE), + dimp); nodep->addNextHere(bitassignp); - dimreadps.push_front(new AstVarRef(nodep->fileline(), bitvscp, false)); + dimreadps.push_front(new AstVarRef(nodep->fileline(), bitvscp, VAccess::READ)); } } // @@ -247,9 +248,10 @@ private: AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), bitvarname, lsbvaluep->width(), nullptr); AstAssign* bitassignp = new AstAssign( - nodep->fileline(), new AstVarRef(nodep->fileline(), bitvscp, true), lsbvaluep); + nodep->fileline(), new AstVarRef(nodep->fileline(), bitvscp, VAccess::WRITE), + lsbvaluep); nodep->addNextHere(bitassignp); - bitreadp = new AstVarRef(nodep->fileline(), bitvscp, false); + bitreadp = new AstVarRef(nodep->fileline(), bitvscp, VAccess::READ); } } // @@ -263,8 +265,8 @@ private: = (string("__Vdlyvval__") + oldvarp->shortName() + "__v" + cvtToStr(modVecNum)); AstVarScope* valvscp = createVarSc(varrefp->varScopep(), valvarname, 0, nodep->rhsp()->dtypep()); - newlhsp = new AstVarRef(nodep->fileline(), valvscp, true); - valreadp = new AstVarRef(nodep->fileline(), valvscp, false); + newlhsp = new AstVarRef(nodep->fileline(), valvscp, VAccess::WRITE); + valreadp = new AstVarRef(nodep->fileline(), valvscp, VAccess::READ); } // //=== Setting/not setting boolean: __Vdlyvset__ @@ -283,11 +285,11 @@ private: = (string("__Vdlyvset__") + oldvarp->shortName() + "__v" + cvtToStr(modVecNum)); setvscp = createVarSc(varrefp->varScopep(), setvarname, 1, nullptr); setinitp = new AstAssignPre(nodep->fileline(), - new AstVarRef(nodep->fileline(), setvscp, true), + new AstVarRef(nodep->fileline(), setvscp, VAccess::WRITE), new AstConst(nodep->fileline(), 0)); - AstAssign* setassignp - = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), setvscp, true), - new AstConst(nodep->fileline(), AstConst::LogicTrue())); + AstAssign* setassignp = new AstAssign( + nodep->fileline(), new AstVarRef(nodep->fileline(), setvscp, VAccess::WRITE), + new AstConst(nodep->fileline(), AstConst::LogicTrue())); nodep->addNextHere(setassignp); } if (m_nextDlyp) { // Tell next assigndly it can share the variable @@ -332,9 +334,9 @@ private: UASSERT_OBJ(postLogicp, nodep, "Delayed assignment misoptimized; prev var found w/o associated IF"); } else { - postLogicp - = new AstIf(nodep->fileline(), new AstVarRef(nodep->fileline(), setvscp, false), - nullptr, nullptr); + postLogicp = new AstIf(nodep->fileline(), + new AstVarRef(nodep->fileline(), setvscp, VAccess::READ), + nullptr, nullptr); UINFO(9, " Created " << postLogicp << endl); finalp->addBodysp(postLogicp); finalp->user3p(setvscp); // Remember IF's vset variable @@ -406,7 +408,7 @@ private: virtual void visit(AstVarRef* nodep) override { if (!nodep->user2Inc()) { // Not done yet - if (m_inDly && nodep->lvalue()) { + if (m_inDly && nodep->access().isWrite()) { UINFO(4, "AssignDlyVar: " << nodep << endl); markVarUsage(nodep->varScopep(), VU_DLY); UASSERT_OBJ(m_activep, nodep, "<= not under sensitivity block"); @@ -429,16 +431,19 @@ private: if (basicp && basicp->isEventValue()) { // Events go to zero on next timestep unless reactivated prep = new AstAssignPre( - nodep->fileline(), new AstVarRef(nodep->fileline(), dlyvscp, true), + nodep->fileline(), + new AstVarRef(nodep->fileline(), dlyvscp, VAccess::WRITE), new AstConst(nodep->fileline(), AstConst::LogicFalse())); } else { - prep = new AstAssignPre(nodep->fileline(), - new AstVarRef(nodep->fileline(), dlyvscp, true), - new AstVarRef(nodep->fileline(), oldvscp, false)); + prep = new AstAssignPre( + nodep->fileline(), + new AstVarRef(nodep->fileline(), dlyvscp, VAccess::WRITE), + new AstVarRef(nodep->fileline(), oldvscp, VAccess::READ)); } AstNodeAssign* postp = new AstAssignPost( - nodep->fileline(), new AstVarRef(nodep->fileline(), oldvscp, true), - new AstVarRef(nodep->fileline(), dlyvscp, false)); + nodep->fileline(), + new AstVarRef(nodep->fileline(), oldvscp, VAccess::WRITE), + new AstVarRef(nodep->fileline(), dlyvscp, VAccess::READ)); postp->lhsp()->user2(true); // Don't detect this assignment oldvscp->user1p(dlyvscp); // So we can find it later // Make new ACTIVE with identical sensitivity tree @@ -447,11 +452,11 @@ private: newactp->addStmtsp(prep); // Add to FRONT of statements newactp->addStmtsp(postp); } - AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true); + AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, VAccess::WRITE); newrefp->user2(true); // No reason to do it again nodep->replaceWith(newrefp); VL_DO_DANGLING(nodep->deleteTree(), nodep); - } else if (!m_inDly && nodep->lvalue()) { + } else if (!m_inDly && nodep->access().isWrite()) { // UINFO(9, "NBA " << nodep << endl); if (!m_inInitial) { UINFO(4, "AssignNDlyVar: " << nodep << endl); diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index d76a5cc11..0eee958f0 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -64,11 +64,11 @@ private: UASSERT_OBJ(m_funcp, nodep, "Deep expression not under a function"); m_funcp->addInitsp(varp); // Replace node tree with reference to var - AstVarRef* newp = new AstVarRef(nodep->fileline(), varp, false); + AstVarRef* newp = new AstVarRef(nodep->fileline(), varp, VAccess::READ); nodep->replaceWith(newp); // Put assignment before the referencing statement - AstAssign* assp = new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), varp, true), nodep); + AstAssign* assp = new AstAssign( + nodep->fileline(), new AstVarRef(nodep->fileline(), varp, VAccess::WRITE), nodep); AstNRelinker linker2; m_stmtp->unlinkFrBack(&linker2); assp->addNext(m_stmtp); diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index 007c8236e..9bbb522da 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -184,8 +184,9 @@ private: for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO() && !portp->isFuncReturn()) { - AstNode* newp - = new AstVarRef(portp->fileline(), portp, portp->isWritable()); + AstNode* newp = new AstVarRef(portp->fileline(), portp, + portp->isWritable() ? VAccess::WRITE + : VAccess::READ); argsp = argsp ? argsp->addNextNull(newp) : newp; } } diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index a1b9d4ed0..fb6bc7c43 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -94,7 +94,7 @@ private: void fixCloneLvalue(AstNode* nodep) { // In AstSel transforms, we call clone() on VarRefs that were lvalues, // but are now being used on the RHS of the assignment - if (VN_IS(nodep, VarRef)) VN_CAST(nodep, VarRef)->lvalue(false); + if (VN_IS(nodep, VarRef)) VN_CAST(nodep, VarRef)->access(VAccess::READ); // Iterate if (nodep->op1p()) fixCloneLvalue(nodep->op1p()); if (nodep->op2p()) fixCloneLvalue(nodep->op2p()); diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 085586bf5..95aed069a 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -220,7 +220,7 @@ private: if (nodep->varScopep()->varp()->isSc()) { clearSimple("SystemC sig"); // Don't want to eliminate the VL_ASSIGN_SI's } - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { if (m_lhsVarRef) clearSimple(">1 lhs varRefs"); m_lhsVarRef = nodep; } else { @@ -448,7 +448,7 @@ private: vvertexp->setIsClock(); // For SYNCASYNCNET varscp->user2(true); - } else if (m_activep && m_activep->hasClocked() && !nodep->lvalue()) { + } else if (m_activep && m_activep->hasClocked() && !nodep->access().isWrite()) { if (varscp->user2()) { if (!vvertexp->rstAsyncNodep()) vvertexp->rstAsyncNodep(nodep); } else { @@ -457,7 +457,7 @@ private: } // We use weight of one; if we ref the var more than once, when we simplify, // the weight will increase - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { new V3GraphEdge(&m_graph, m_logicVertexp, vvertexp, 1); } else { new V3GraphEdge(&m_graph, vvertexp, m_logicVertexp, 1); @@ -845,7 +845,7 @@ private: // It's possible we substitute into something that will be reduced more later, // however, as we never delete the top Always/initial statement, all should be well. m_didReplace = true; - UASSERT_OBJ(!nodep->lvalue(), nodep, + UASSERT_OBJ(!nodep->access().isWrite(), nodep, "Can't replace lvalue assignments with const var"); AstNode* substp = m_replaceTreep->cloneTree(false); UASSERT_OBJ( @@ -859,7 +859,8 @@ private: // to throw warnings that point to a PIN rather than where the pin us used. if (VN_IS(substp, VarRef)) substp->fileline(nodep->fileline()); // Make the substp an rvalue like nodep. This facilitates the hashing in dedupe. - if (AstNodeVarRef* varrefp = VN_CAST(substp, NodeVarRef)) varrefp->lvalue(false); + if (AstNodeVarRef* varrefp = VN_CAST(substp, NodeVarRef)) + varrefp->access(VAccess::READ); hashReplace(nodep, substp); nodep->replaceWith(substp); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -1514,7 +1515,7 @@ private: UINFO(9, "CLK DECOMP Connecting - " << assignp->lhsp() << endl); UINFO(9, " to - " << m_clk_vsp << endl); AstNode* rhsp = assignp->rhsp(); - rhsp->replaceWith(new AstVarRef(rhsp->fileline(), m_clk_vsp, false)); + rhsp->replaceWith(new AstVarRef(rhsp->fileline(), m_clk_vsp, VAccess::READ)); while (V3GraphEdge* edgep = lvertexp->inBeginp()) { VL_DO_DANGLING(edgep->unlinkDelete(), edgep); } diff --git a/src/V3GenClk.cpp b/src/V3GenClk.cpp index 60ba799df..729708b7e 100644 --- a/src/V3GenClk.cpp +++ b/src/V3GenClk.cpp @@ -67,9 +67,9 @@ private: m_topModp->addStmtp(newvarp); AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopetopp, newvarp); m_scopetopp->addVarp(newvscp); - AstAssign* asninitp - = new AstAssign(vscp->fileline(), new AstVarRef(vscp->fileline(), newvscp, true), - new AstVarRef(vscp->fileline(), vscp, false)); + AstAssign* asninitp = new AstAssign( + vscp->fileline(), new AstVarRef(vscp->fileline(), newvscp, VAccess::WRITE), + new AstVarRef(vscp->fileline(), vscp, VAccess::READ)); m_scopetopp->addFinalClkp(asninitp); // vscp->user2p(newvscp); @@ -98,7 +98,7 @@ private: UINFO(8, " VarActReplace " << nodep << endl); // Replace with the new variable AstVarScope* newvscp = genInpClk(vscp); - AstVarRef* newrefp = new AstVarRef(nodep->fileline(), newvscp, nodep->lvalue()); + AstVarRef* newrefp = new AstVarRef(nodep->fileline(), newvscp, nodep->access()); nodep->replaceWith(newrefp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } @@ -186,7 +186,7 @@ private: UINFO(8, " VarAct " << nodep << endl); vscp->user1(true); } - if (m_assignp && nodep->lvalue() && vscp->user1()) { + if (m_assignp && nodep->access().isWrite() && vscp->user1()) { // Variable was previously used as a clock, and is now being set // Thus a unordered generated clock... UINFO(8, " VarSetAct " << nodep << endl); diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 9a0c9af82..b42e14d4c 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -313,9 +313,9 @@ private: UASSERT_OBJ(exprconstp || exprvarrefp, nodep, "Unknown interconnect type; pinReconnectSimple should have cleared up"); if (exprconstp) { - m_modp->addStmtp(new AstAssignW(nodep->fileline(), - new AstVarRef(nodep->fileline(), nodep, true), - exprconstp->cloneTree(true))); + m_modp->addStmtp(new AstAssignW( + nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, VAccess::WRITE), + exprconstp->cloneTree(true))); } else if (nodep->user3()) { // Public variable at the lower module end - we need to make sure we propagate // the logic changes up and down; if we aliased, we might @@ -323,20 +323,22 @@ private: UINFO(9, "public pin assign: " << exprvarrefp << endl); UASSERT_OBJ(!nodep->isNonOutput(), nodep, "Outputs only - inputs use AssignAlias"); m_modp->addStmtp(new AstAssignW( - nodep->fileline(), new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true), - new AstVarRef(nodep->fileline(), nodep, false))); + nodep->fileline(), + new AstVarRef(nodep->fileline(), exprvarrefp->varp(), VAccess::WRITE), + new AstVarRef(nodep->fileline(), nodep, VAccess::READ))); } else if (nodep->isSigPublic() && VN_IS(nodep->dtypep(), UnpackArrayDType)) { // Public variable at this end and it is an unpacked array. We need to assign // instead of aliased, because otherwise it will pass V3Slice and invalid // code will be emitted. UINFO(9, "assign to public and unpacked: " << nodep << endl); m_modp->addStmtp(new AstAssignW( - nodep->fileline(), new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true), - new AstVarRef(nodep->fileline(), nodep, false))); + nodep->fileline(), + new AstVarRef(nodep->fileline(), exprvarrefp->varp(), VAccess::WRITE), + new AstVarRef(nodep->fileline(), nodep, VAccess::READ))); } else if (nodep->isIfaceRef()) { m_modp->addStmtp(new AstAssignVarScope( - nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, true), - new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false))); + nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, VAccess::WRITE), + new AstVarRef(nodep->fileline(), exprvarrefp->varp(), VAccess::READ))); AstNode* nodebp = exprvarrefp->varp(); nodep->fileline()->modifyStateInherit(nodebp->fileline()); nodebp->fileline()->modifyStateInherit(nodep->fileline()); @@ -344,8 +346,8 @@ private: // Do to inlining child's variable now within the same // module, so a AstVarRef not AstVarXRef below m_modp->addStmtp(new AstAssignAlias( - nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, true), - new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false))); + nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, VAccess::WRITE), + new AstVarRef(nodep->fileline(), exprvarrefp->varp(), VAccess::READ))); AstNode* nodebp = exprvarrefp->varp(); nodep->fileline()->modifyStateInherit(nodebp->fileline()); nodebp->fileline()->modifyStateInherit(nodep->fileline()); diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index 7919c547f..6c4c1922f 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -76,17 +76,17 @@ private: if (nodep->modVarp()->isInoutish()) { nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator"); } else if (nodep->modVarp()->isWritable()) { - AstNode* rhsp - = new AstVarXRef(exprp->fileline(), nodep->modVarp(), m_cellp->name(), false); + AstNode* rhsp = new AstVarXRef(exprp->fileline(), nodep->modVarp(), + m_cellp->name(), VAccess::READ); AstAssignW* assp = new AstAssignW(exprp->fileline(), exprp, rhsp); m_cellp->addNextHere(assp); } else if (nodep->modVarp()->isNonOutput()) { // Don't bother moving constants now, // we'll be pushing the const down to the cell soon enough. - AstNode* assp = new AstAssignW( - exprp->fileline(), - new AstVarXRef(exprp->fileline(), nodep->modVarp(), m_cellp->name(), true), - exprp); + AstNode* assp = new AstAssignW(exprp->fileline(), + new AstVarXRef(exprp->fileline(), nodep->modVarp(), + m_cellp->name(), VAccess::WRITE), + exprp); m_cellp->addNextHere(assp); if (debug() >= 9) assp->dumpTree(cout, " _new: "); } else if (nodep->modVarp()->isIfaceRef() @@ -96,8 +96,8 @@ private: IfaceRefDType))) { // Create an AstAssignVarScope for Vars to Cells so we can // link with their scope later - AstNode* lhsp - = new AstVarXRef(exprp->fileline(), nodep->modVarp(), m_cellp->name(), false); + AstNode* lhsp = new AstVarXRef(exprp->fileline(), nodep->modVarp(), + m_cellp->name(), VAccess::READ); const AstVarRef* refp = VN_CAST(exprp, VarRef); const AstVarXRef* xrefp = VN_CAST(exprp, VarXRef); UASSERT_OBJ(refp || xrefp, exprp, @@ -379,8 +379,9 @@ private: } string index = AstNode::encodeNumber(constp->toSInt()); AstVarRef* varrefp = VN_CAST(arrselp->lhsp(), VarRef); - AstVarXRef* newp = new AstVarXRef( - nodep->fileline(), varrefp->name() + "__BRA__" + index + "__KET__", "", true); + AstVarXRef* newp = new AstVarXRef(nodep->fileline(), + varrefp->name() + "__BRA__" + index + "__KET__", + "", VAccess::WRITE); newp->dtypep(nodep->modVarp()->dtypep()); newp->packagep(varrefp->packagep()); arrselp->addNextHere(newp); @@ -438,7 +439,8 @@ private: } if (!varrefp) { newp->exprp()->v3error("Unexpected connection to arrayed port"); } string newname = varrefp->name() + "__BRA__" + cvtToStr(i + offset) + "__KET__"; - AstVarXRef* newVarXRefp = new AstVarXRef(nodep->fileline(), newname, "", true); + AstVarXRef* newVarXRefp + = new AstVarXRef(nodep->fileline(), newname, "", VAccess::WRITE); newVarXRefp->varp(newp->modVarp()); newp->exprp()->unlinkFrBack()->deleteTree(); newp->exprp(newVarXRefp); @@ -553,18 +555,19 @@ public: " direct one-to-one connection (without any expression)"); } else if (pinVarp->isWritable()) { // See also V3Inst - AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false); + AstNode* 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, true)); + pinp->exprp(new AstVarRef(newvarp->fileline(), newvarp, VAccess::WRITE)); AstNode* 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 assignp = new AstAssignW(pinp->fileline(), - new AstVarRef(pinp->fileline(), newvarp, true), pinexprp); - pinp->exprp(new AstVarRef(pinexprp->fileline(), newvarp, false)); + new AstVarRef(pinp->fileline(), newvarp, VAccess::WRITE), + pinexprp); + pinp->exprp(new AstVarRef(pinexprp->fileline(), newvarp, VAccess::READ)); } if (assignp) cellp->addNextHere(assignp); // if (debug()) { pinp->dumpTree(cout, "- out:"); } diff --git a/src/V3Life.cpp b/src/V3Life.cpp index dff42a07e..aa8ca95ec 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -300,7 +300,7 @@ private: // AstVarScope* vscp = nodep->varScopep(); UASSERT_OBJ(vscp, nodep, "Scope not assigned"); - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { m_sideEffect = true; // $sscanf etc may have RHS vars that are lvalues m_lifep->complexAssign(vscp); } else { diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp index 65ee17693..c3ba15bbd 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -58,7 +58,7 @@ private: UASSERT_OBJ(vscp, nodep, "Scope not assigned"); if (AstVarScope* newvscp = reinterpret_cast(vscp->user4p())) { UINFO(9, " Replace " << nodep << " to " << newvscp << endl); - AstVarRef* newrefp = new AstVarRef(nodep->fileline(), newvscp, nodep->lvalue()); + AstVarRef* newrefp = new AstVarRef(nodep->fileline(), newvscp, nodep->access()); nodep->replaceWith(newrefp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } @@ -284,7 +284,7 @@ private: UASSERT_OBJ(vscp, nodep, "Scope not assigned"); LifeLocation loc(m_execMTaskp, ++m_sequence); - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { m_writes[vscp].insert(loc); } else { m_reads[vscp].insert(loc); diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 1ec6fc337..610e30f0b 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2132,7 +2132,7 @@ private: m_ds.m_dotPos = DP_SCOPE; UINFO(9, " cell -> iface varref " << foundp->nodep() << endl); AstNode* newp - = new AstVarRef(ifaceRefVarp->fileline(), ifaceRefVarp, false); + = new AstVarRef(ifaceRefVarp->fileline(), ifaceRefVarp, VAccess::READ); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } else if (VN_IS(cellp->modp(), NotFoundModule)) { @@ -2150,7 +2150,7 @@ private: m_ds.m_dotSymp = m_statep->getNodeSym(ifacerefp->ifaceViaCellp()); m_ds.m_dotPos = DP_SCOPE; ok = true; - AstNode* newp = new AstVarRef(nodep->fileline(), varp, false); + AstNode* newp = new AstVarRef(nodep->fileline(), varp, VAccess::READ); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } else if (allowVar) { @@ -2158,7 +2158,7 @@ private: if (m_ds.m_dotText != "") { AstVarXRef* refp = new AstVarXRef(nodep->fileline(), nodep->name(), m_ds.m_dotText, - false); // lvalue'ness computed later + VAccess::READ); // lvalue'ness computed later refp->varp(varp); if (varp->attrSplitVar()) { refp->v3warn( @@ -2188,8 +2188,9 @@ private: newp = refp; } } else { - AstVarRef* refp = new AstVarRef(nodep->fileline(), varp, - false); // lvalue'ness computed later + AstVarRef* refp + = new AstVarRef(nodep->fileline(), varp, + VAccess::READ); // lvalue'ness computed later refp->packagep(foundp->packagep()); newp = refp; } @@ -2224,7 +2225,7 @@ private: m_ds.m_dotPos = DP_SCOPE; ok = true; AstVar* varp = makeIfaceModportVar(nodep->fileline(), cellp, ifacep, modportp); - AstVarRef* refp = new AstVarRef(varp->fileline(), varp, false); + AstVarRef* refp = new AstVarRef(varp->fileline(), varp, VAccess::READ); nodep->replaceWith(refp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } @@ -2274,7 +2275,8 @@ private: if (checkImplicit) { // Create if implicit, and also if error (so only complain once) // Else if a scope is allowed, making a signal won't help error cascade - AstVarRef* newp = new AstVarRef(nodep->fileline(), nodep->name(), false); + AstVarRef* newp + = new AstVarRef(nodep->fileline(), nodep->name(), VAccess::READ); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); createImplicitVar(m_curSymp, newp, m_modp, m_modSymp, err); @@ -2293,7 +2295,7 @@ private: UINFO(9, " linkVarRef se" << cvtToHex(m_curSymp) << " n=" << nodep << endl); UASSERT_OBJ(m_curSymp, nodep, "nullptr lookup symbol table"); VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name()); - if (AstVar* varp = foundp ? foundToVarp(foundp, nodep, nodep->lvalue()) : nullptr) { + if (AstVar* varp = foundp ? foundToVarp(foundp, nodep, nodep->access()) : nullptr) { nodep->varp(varp); // Generally set by parse, but might be an import nodep->packagep(foundp->packagep()); @@ -2333,7 +2335,7 @@ private: okSymp); // Maybe nullptr if (!m_statep->forScopeCreation()) { VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot); - AstVar* varp = foundp ? foundToVarp(foundp, nodep, nodep->lvalue()) : nullptr; + AstVar* varp = foundp ? foundToVarp(foundp, nodep, nodep->access()) : nullptr; nodep->varp(varp); UINFO(7, " Resolved " << nodep << endl); // Also prints varp if (!nodep->varp()) { @@ -2349,7 +2351,7 @@ private: if (!m_statep->forPrearray() && !m_statep->forScopeCreation()) { if (VN_IS(nodep->dtypep(), IfaceRefDType)) { AstVarRef* newrefp - = new AstVarRef(nodep->fileline(), nodep->varp(), nodep->lvalue()); + = new AstVarRef(nodep->fileline(), nodep->varp(), nodep->access()); nodep->replaceWith(newrefp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } @@ -2373,7 +2375,7 @@ private: nodep->varp(vscp->varp()); nodep->varScopep(vscp); UINFO(7, " Resolved " << nodep << endl); // Also prints taskp - AstVarRef* newvscp = new AstVarRef(nodep->fileline(), vscp, nodep->lvalue()); + AstVarRef* newvscp = new AstVarRef(nodep->fileline(), vscp, nodep->access()); nodep->replaceWith(newvscp); VL_DO_DANGLING(nodep->deleteTree(), nodep); UINFO(9, " new " << newvscp << endl); // Also prints taskp diff --git a/src/V3LinkInc.cpp b/src/V3LinkInc.cpp index fdcdbebed..c7cf6298a 100644 --- a/src/V3LinkInc.cpp +++ b/src/V3LinkInc.cpp @@ -199,30 +199,33 @@ private: // Define what operation will we be doing AstNode* operp; if (VN_IS(nodep, PostSub) || VN_IS(nodep, PreSub)) { - operp = new AstSub(fl, new AstVarRef(fl, varrefp->varp(), false), newconstp); + operp = new AstSub(fl, new AstVarRef(fl, varrefp->varp(), VAccess::READ), newconstp); } else { - operp = new AstAdd(fl, new AstVarRef(fl, varrefp->varp(), false), newconstp); + operp = new AstAdd(fl, new AstVarRef(fl, varrefp->varp(), VAccess::READ), newconstp); } if (VN_IS(nodep, PreAdd) || VN_IS(nodep, PreSub)) { // PreAdd/PreSub operations // Immediately after declaration - increment it by one - m_insStmtp->addHereThisAsNext(new AstAssign(fl, new AstVarRef(fl, varp, true), operp)); + m_insStmtp->addHereThisAsNext( + new AstAssign(fl, new AstVarRef(fl, varp, VAccess::WRITE), operp)); // Immediately after incrementing - assign it to the original variable - m_insStmtp->addHereThisAsNext(new AstAssign( - fl, new AstVarRef(fl, varrefp->varp(), true), new AstVarRef(fl, varp, false))); + m_insStmtp->addHereThisAsNext( + new AstAssign(fl, new AstVarRef(fl, varrefp->varp(), VAccess::WRITE), + new AstVarRef(fl, varp, VAccess::READ))); } else { // PostAdd/PostSub operations // assign the original variable to the temporary one - m_insStmtp->addHereThisAsNext(new AstAssign( - fl, new AstVarRef(fl, varp, true), new AstVarRef(fl, varrefp->varp(), false))); + m_insStmtp->addHereThisAsNext( + new AstAssign(fl, new AstVarRef(fl, varp, VAccess::WRITE), + new AstVarRef(fl, varrefp->varp(), VAccess::READ))); // Increment the original variable by one m_insStmtp->addHereThisAsNext( - new AstAssign(fl, new AstVarRef(fl, varrefp->varp(), true), operp)); + new AstAssign(fl, new AstVarRef(fl, varrefp->varp(), VAccess::WRITE), operp)); } // Replace the node with the temporary - nodep->replaceWith(new AstVarRef(varrefp->fileline(), varp, true)); + nodep->replaceWith(new AstVarRef(varrefp->fileline(), varp, VAccess::WRITE)); VL_DO_DANGLING(nodep->deleteTree(), nodep); } virtual void visit(AstPreAdd* nodep) override { prepost_visit(nodep); } diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index 076ce57a4..0bccce54a 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -153,15 +153,15 @@ private: nodep->findSigned32DType()); varp->usedLoopIdx(true); m_modp->addStmtp(varp); - AstNode* initsp = new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), varp, true), countp); + AstNode* initsp = new AstAssign( + nodep->fileline(), new AstVarRef(nodep->fileline(), varp, VAccess::WRITE), countp); AstNode* decp = new AstAssign( - nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true), - new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false), + 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* zerosp = new AstConst(nodep->fileline(), AstConst::Signed32(), 0); - AstNode* condp - = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false), zerosp); + AstNode* condp = new AstGtS(nodep->fileline(), + new AstVarRef(nodep->fileline(), varp, VAccess::READ), zerosp); AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext(); AstNode* newp = new AstWhile(nodep->fileline(), condp, bodysp, decp); @@ -213,7 +213,7 @@ private: // Set output variable to return value nodep->addPrev(new AstAssign( nodep->fileline(), - new AstVarRef(nodep->fileline(), VN_CAST(funcp->fvarp(), Var), true), + new AstVarRef(nodep->fileline(), VN_CAST(funcp->fvarp(), Var), VAccess::WRITE), nodep->lhsp()->unlinkFrBackWithNext())); } // Jump to the end of the function call diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 7db59b71c..cdfdd11e8 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -45,9 +45,9 @@ private: // Result handing virtual void visit(AstNodeVarRef* nodep) override { // VarRef: LValue its reference - if (m_setRefLvalue) nodep->lvalue(true); + if (m_setRefLvalue) nodep->access(VAccess::WRITE); if (nodep->varp()) { - if (nodep->lvalue() && !m_ftaskp && nodep->varp()->isReadOnly()) { + if (nodep->access().isWrite() && !m_ftaskp && nodep->varp()->isReadOnly()) { nodep->v3warn(ASSIGNIN, "Assigning to input/const variable: " << nodep->prettyNameQ()); } @@ -60,7 +60,7 @@ private: if (nodep->modVarp() && nodep->modVarp()->isWritable()) { // When the varref's were created, we didn't know the I/O state // Now that we do, and it's from a output, we know it's a lvalue - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateChildren(nodep); m_setRefLvalue = false; } else { @@ -70,7 +70,7 @@ private: virtual void visit(AstNodeAssign* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->lhsp()); m_setRefLvalue = false; iterateAndNextNull(nodep->rhsp()); @@ -79,7 +79,7 @@ private: virtual void visit(AstFOpen* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); m_setRefLvalue = false; iterateAndNextNull(nodep->filenamep()); @@ -89,7 +89,7 @@ private: virtual void visit(AstFOpenMcd* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); m_setRefLvalue = false; iterateAndNextNull(nodep->filenamep()); @@ -98,14 +98,14 @@ private: virtual void visit(AstFClose* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); } } virtual void visit(AstFError* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); iterateAndNextNull(nodep->strp()); } @@ -113,21 +113,21 @@ private: virtual void visit(AstFFlush* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); } } virtual void visit(AstFGetC* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); } } virtual void visit(AstFGetS* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); iterateAndNextNull(nodep->strgp()); } @@ -135,7 +135,7 @@ private: virtual void visit(AstFRead* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->memp()); iterateAndNextNull(nodep->filep()); } @@ -143,7 +143,7 @@ private: virtual void visit(AstFScanF* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); iterateAndNextNull(nodep->exprsp()); } @@ -151,14 +151,14 @@ private: virtual void visit(AstFUngetC* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); } } virtual void visit(AstSScanF* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->exprsp()); } } @@ -170,7 +170,7 @@ private: virtual void visit(AstReadMem* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->memp()); m_setRefLvalue = false; iterateAndNextNull(nodep->filenamep()); @@ -183,14 +183,14 @@ private: { m_setRefLvalue = false; iterateAndNextNull(nodep->searchp()); - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->outp()); } } virtual void visit(AstSFormat* nodep) override { VL_RESTORER(m_setRefLvalue); { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->lhsp()); m_setRefLvalue = false; iterateAndNextNull(nodep->fmtp()); @@ -202,7 +202,7 @@ private: m_setRefLvalue = false; iterateAndNextNull(nodep->lhsp()); iterateAndNextNull(nodep->rhsp()); - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->thsp()); } } @@ -260,7 +260,7 @@ private: if (const AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO()) { if (portp->isWritable()) { - m_setRefLvalue = true; + m_setRefLvalue = VAccess::WRITE; iterate(pinp); m_setRefLvalue = false; } else { diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index 8b6a7d7e7..e59d87ffe 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -233,9 +233,10 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { varp->trace(false); } - AstPin* pinp - = new AstPin(oldvarp->fileline(), 0, varp->name(), - new AstVarRef(varp->fileline(), varp, oldvarp->isWritable())); + AstPin* pinp = new AstPin( + oldvarp->fileline(), 0, varp->name(), + new AstVarRef(varp->fileline(), varp, + oldvarp->isWritable() ? VAccess::WRITE : VAccess::READ)); // Skip length and width comp; we know it's a direct assignment pinp->modVarp(oldvarp); cellp->addPinsp(pinp); diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 9da01d844..09ebb7fb3 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -226,9 +226,9 @@ private: } else if (VN_IS(m_modp, Class)) { // 2. Class member init become initials (as might call functions) // later move into class constructor - nodep->addNextHere( - new AstInitial(fl, new AstAssign(fl, new AstVarRef(fl, nodep->name(), true), - nodep->valuep()->unlinkFrBack()))); + nodep->addNextHere(new AstInitial( + fl, new AstAssign(fl, new AstVarRef(fl, nodep->name(), VAccess::WRITE), + nodep->valuep()->unlinkFrBack()))); } else if (!m_ftaskp && nodep->isNonOutput()) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: Default value on module input: " << nodep->prettyNameQ()); @@ -239,11 +239,13 @@ private: FileLine* newfl = new FileLine(fl); newfl->warnOff(V3ErrorCode::PROCASSWIRE, true); nodep->addNextHere(new AstInitial( - newfl, new AstAssign(newfl, new AstVarRef(newfl, nodep->name(), true), - nodep->valuep()->unlinkFrBack()))); + newfl, + new AstAssign(newfl, new AstVarRef(newfl, nodep->name(), VAccess::WRITE), + nodep->valuep()->unlinkFrBack()))); } // 4. Under blocks, it's an initial value to be under an assign else { - nodep->addNextHere(new AstAssign(fl, new AstVarRef(fl, nodep->name(), true), + nodep->addNextHere(new AstAssign(fl, + new AstVarRef(fl, nodep->name(), VAccess::WRITE), nodep->valuep()->unlinkFrBack())); } } @@ -333,7 +335,8 @@ private: // lvalue is true, because we know we have a verilator public_flat_rw // but someday we may be more general bool lvalue = m_varp->isSigUserRWPublic(); - nodep->addStmtp(new AstVarRef(nodep->fileline(), m_varp, lvalue)); + nodep->addStmtp( + new AstVarRef(nodep->fileline(), m_varp, lvalue ? VAccess::WRITE : VAccess::READ)); } } @@ -445,7 +448,8 @@ private: new AstConst(fl, dimension)); AstNode* stmtsp = varp; // Assign left-dimension into the loop var: - stmtsp->addNext(new AstAssign(fl, new AstVarRef(fl, varp->name(), true), leftp)); + stmtsp->addNext( + new AstAssign(fl, new AstVarRef(fl, varp->name(), VAccess::WRITE), leftp)); // This will turn into a constant bool for static arrays AstNode* notemptyp = new AstGt(fl, sizep, new AstConst(fl, 0)); // This will turn into a bool constant, indicating whether @@ -454,14 +458,15 @@ private: AstNode* comparep = new AstCond( fl, countupp->cloneTree(true), // Left increments up to right - new AstLte(fl, new AstVarRef(fl, varp->name(), false), rightp->cloneTree(true)), + new AstLte(fl, new AstVarRef(fl, varp->name(), VAccess::READ), + rightp->cloneTree(true)), // Left decrements down to right - new AstGte(fl, new AstVarRef(fl, varp->name(), false), rightp)); + new AstGte(fl, new AstVarRef(fl, varp->name(), VAccess::READ), rightp)); // This will reduce to comparep for static arrays AstNode* condp = new AstAnd(fl, notemptyp, comparep); AstNode* incp = new AstAssign( - fl, new AstVarRef(fl, varp->name(), true), - new AstAdd(fl, new AstVarRef(fl, varp->name(), false), + fl, new AstVarRef(fl, varp->name(), VAccess::WRITE), + new AstAdd(fl, new AstVarRef(fl, varp->name(), VAccess::READ), new AstCond(fl, countupp, new AstConst(fl, 1), new AstConst(fl, -1)))); stmtsp->addNext(new AstWhile(fl, condp, newp, incp)); newp = new AstBegin(nodep->fileline(), "", stmtsp, false, true); diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index d81e1a6b4..bf158a20a 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -183,9 +183,10 @@ private: } addwherep->addNext(newvarp); - sensp->replaceWith(new AstVarRef(sensp->fileline(), newvarp, false)); + sensp->replaceWith(new AstVarRef(sensp->fileline(), newvarp, VAccess::READ)); AstAssignW* assignp = new AstAssignW( - sensp->fileline(), new AstVarRef(sensp->fileline(), newvarp, true), sensp); + sensp->fileline(), new AstVarRef(sensp->fileline(), newvarp, VAccess::WRITE), + sensp); addwherep->addNext(assignp); } } else { // Old V1995 sensitivity list; we'll probably mostly ignore @@ -490,7 +491,8 @@ private: varoutp = varp; // Tie off m_modp->addStmtp(new AstAssignW( - varp->fileline(), new AstVarRef(varp->fileline(), varp, true), + varp->fileline(), + new AstVarRef(varp->fileline(), varp, VAccess::WRITE), new AstConst(varp->fileline(), AstConst::LogicFalse()))); } else { varp->v3error("Only inputs and outputs are allowed in udp modules"); diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp index c9ee6b9f4..3192b074d 100644 --- a/src/V3Localize.cpp +++ b/src/V3Localize.cpp @@ -166,7 +166,7 @@ private: for (; nodep; nodep = nodep->nextp()) { if (VN_IS(nodep, NodeAssign)) { if (AstVarRef* varrefp = VN_CAST(VN_CAST(nodep, NodeAssign)->lhsp(), VarRef)) { - UASSERT_OBJ(varrefp->lvalue(), varrefp, "LHS assignment not lvalue"); + UASSERT_OBJ(varrefp->access().isWrite(), varrefp, "LHS assignment not lvalue"); if (!varrefp->varp()->user4p()) { UINFO(4, " FuncAsn " << varrefp << endl); varrefp->varp()->user4p(varrefp); diff --git a/src/V3MergeCond.cpp b/src/V3MergeCond.cpp index 114898b23..acdfe95b7 100644 --- a/src/V3MergeCond.cpp +++ b/src/V3MergeCond.cpp @@ -80,7 +80,7 @@ private: virtual void visit(AstVarRef* nodep) override { if (!m_mergeable) return; // Clear if it's an LValue referencing a marked variable - if (nodep->lvalue() && nodep->varp()->user1()) { + if (nodep->access().isWrite() && nodep->varp()->user1()) { clearMergeable(nodep, "might modify condition"); } } diff --git a/src/V3Order.cpp b/src/V3Order.cpp index b641e48e5..915f88ee2 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -1026,7 +1026,8 @@ private: UASSERT_OBJ(varscp, nodep, "Var didn't get varscoped in V3Scope.cpp"); if (m_inSenTree) { // Add CLOCK dependency... This is a root of the tree we'll trace - UASSERT_OBJ(!nodep->lvalue(), nodep, "How can a sensitivity be setting a var?"); + UASSERT_OBJ(!nodep->access().isWrite(), nodep, + "How can a sensitivity be setting a var?"); OrderVarVertex* varVxp = newVarUserVertex(varscp, WV_STD); varVxp->isClock(true); new OrderEdge(&m_graph, varVxp, m_activeSenVxp, WEIGHT_MEDIUM); @@ -1036,7 +1037,7 @@ private: // We don't want to add extra edges if the logic block has many usages of same var bool gen = false; bool con = false; - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { gen = !(varscp->user4() & VU_GEN); } else { con = !(varscp->user4() & VU_CON); diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 3e07a3de2..bc21b11f8 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -535,7 +535,7 @@ private: nodep->addNext(new AstInitial( nodep->fileline(), new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), nodep, true), + new AstVarRef(nodep->fileline(), nodep, VAccess::WRITE), nodep->valuep()->cloneTree(true)))); if (m_ftaskp) { // We put the initial in wrong place under a function. We diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index ae478171d..329631792 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -83,7 +83,7 @@ AstNode* V3ParseGrammar::argWrapList(AstNode* nodep) { AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, const string& name, int value) { return new AstAssignW( - fileline, new AstVarRef(fileline, name, true), + fileline, new AstVarRef(fileline, name, VAccess::WRITE), new AstConst(fileline, AstConst::StringToParse(), (value ? "'1" : "'0"))); } diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index 154e517ee..8402cdb60 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -58,7 +58,7 @@ private: } virtual void visit(AstVarRef* nodep) override { // it's LHS var is used so need a deep temporary - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { nodep->varp()->user4(true); } else { if (nodep->varp()->user4()) { @@ -173,11 +173,11 @@ private: AstVar* varp = getBlockTemp(nodep); if (noSubst) varp->noSubst(true); // Do not remove varrefs to this in V3Const // Replace node tree with reference to var - AstVarRef* newp = new AstVarRef(nodep->fileline(), varp, false); + AstVarRef* newp = new AstVarRef(nodep->fileline(), varp, VAccess::READ); linker.relink(newp); // Put assignment before the referencing statement - AstAssign* assp = new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), varp, true), nodep); + AstAssign* assp = new AstAssign( + nodep->fileline(), new AstVarRef(nodep->fileline(), varp, VAccess::WRITE), nodep); insertBeforeStmt(assp); if (debug() > 8) assp->dumpTree(cout, "deepou:"); nodep->user1(true); // Don't add another assignment diff --git a/src/V3Reloop.cpp b/src/V3Reloop.cpp index 7122b906c..f23423141 100644 --- a/src/V3Reloop.cpp +++ b/src/V3Reloop.cpp @@ -99,13 +99,13 @@ private: FileLine* fl = bodyp->fileline(); AstVar* itp = findCreateVarTemp(fl, m_mgCfuncp); - AstNode* initp = new AstAssign(fl, new AstVarRef(fl, itp, true), + AstNode* initp = new AstAssign(fl, new AstVarRef(fl, itp, VAccess::WRITE), new AstConst(fl, m_mgIndexLo)); - AstNode* condp - = new AstLte(fl, new AstVarRef(fl, itp, false), new AstConst(fl, m_mgIndexHi)); + AstNode* condp = new AstLte(fl, new AstVarRef(fl, itp, VAccess::READ), + new AstConst(fl, m_mgIndexHi)); AstNode* incp = new AstAssign( - fl, new AstVarRef(fl, itp, true), - new AstAdd(fl, new AstConst(fl, 1), new AstVarRef(fl, itp, false))); + fl, new AstVarRef(fl, itp, VAccess::WRITE), + new AstAdd(fl, new AstConst(fl, 1), new AstVarRef(fl, itp, VAccess::READ))); AstWhile* whilep = new AstWhile(fl, condp, nullptr, incp); initp->addNext(whilep); bodyp->replaceWith(initp); @@ -113,11 +113,11 @@ private: // Replace constant index with new loop index AstNode* lbitp = m_mgSelLp->bitp(); - lbitp->replaceWith(new AstVarRef(fl, itp, false)); + lbitp->replaceWith(new AstVarRef(fl, itp, VAccess::READ)); VL_DO_DANGLING(lbitp->deleteTree(), lbitp); if (m_mgSelRp) { // else constant and no replace AstNode* rbitp = m_mgSelRp->bitp(); - rbitp->replaceWith(new AstVarRef(fl, itp, false)); + rbitp->replaceWith(new AstVarRef(fl, itp, VAccess::READ)); VL_DO_DANGLING(rbitp->deleteTree(), lbitp); } if (debug() >= 9) initp->dumpTree(cout, "-new: "); diff --git a/src/V3Simulate.h b/src/V3Simulate.h index a2f1eb6f5..5d6b4ccf5 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -401,7 +401,7 @@ private: && !VN_IS(nodep->varp()->dtypeSkipRefp(), UnpackArrayDType) && !VN_IS(nodep->varp()->dtypeSkipRefp(), StructDType)) clearOptimizable(nodep, "Array references/not basic"); - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { if (m_inDlyAssign) { if (!(vscp->user1() & VU_LVDLY)) { vscp->user1(vscp->user1() | VU_LVDLY); @@ -433,7 +433,7 @@ private: } } if (!m_checkOnly && optimizable()) { // simulating - UASSERT_OBJ(!nodep->lvalue(), nodep, + UASSERT_OBJ(!nodep->access().isWrite(), nodep, "LHS varref should be handled in AstAssign visitor."); { // Return simulation value - copy by reference instead of value for speed diff --git a/src/V3Split.cpp b/src/V3Split.cpp index 69773c2b5..5fc44131a 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -383,7 +383,7 @@ protected: SplitVarStdVertex* vstdp = reinterpret_cast(vscp->user1p()); // SPEEDUP: We add duplicate edges, that should be fixed - if (m_inDly && nodep->lvalue()) { + if (m_inDly && nodep->access().isWrite()) { UINFO(4, " VARREFDLY: " << nodep << endl); // Delayed variable is different from non-delayed variable if (!vscp->user2p()) { @@ -398,7 +398,7 @@ protected: new SplitLVEdge(&m_graph, vpostp, vxp); } } else { // Nondelayed assignment - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { // Non-delay; need to maintain existing ordering // with all consumers of the signal UINFO(4, " VARREFLV: " << nodep << endl); diff --git a/src/V3SplitAs.cpp b/src/V3SplitAs.cpp index 793638187..ea7ec7a94 100644 --- a/src/V3SplitAs.cpp +++ b/src/V3SplitAs.cpp @@ -49,7 +49,7 @@ private: // METHODS virtual void visit(AstVarRef* nodep) override { - if (nodep->lvalue() && !m_splitVscp && nodep->varp()->attrIsolateAssign()) { + if (nodep->access().isWrite() && !m_splitVscp && nodep->varp()->attrIsolateAssign()) { m_splitVscp = nodep->varScopep(); } } @@ -76,7 +76,7 @@ private: // METHODS virtual void visit(AstVarRef* nodep) override { - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { if (nodep->varScopep() == m_splitVscp) { UINFO(6, " CL VAR " << nodep << endl); m_matches = true; diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index b7f308d47..0612174e4 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -239,7 +239,7 @@ class UnpackRef { int m_index; // for ArraySel int m_msb; // for SliceSel int m_lsb; // for SliceSel - bool m_lvalue; + VAccess m_access; bool m_ftask; // true if the reference is in function/task. false if in module. public: UnpackRef(AstNode* stmtp, AstVarRef* nodep, bool ftask) @@ -248,23 +248,24 @@ public: , m_index{-1} , m_msb{0} , m_lsb{1} - , m_lvalue{nodep->lvalue()} + , m_access{nodep->access()} , m_ftask{ftask} {} - UnpackRef(AstNode* stmtp, AstArraySel* nodep, int idx, bool lvalue, bool ftask) + UnpackRef(AstNode* stmtp, AstArraySel* nodep, int idx, const VAccess& access, bool ftask) : m_contextp{stmtp} , m_nodep{nodep} , m_index{idx} , m_msb{0} , m_lsb{1} - , m_lvalue{lvalue} + , m_access{access} , m_ftask{ftask} {} - UnpackRef(AstNode* stmtp, AstSliceSel* nodep, int msb, int lsb, bool lvalue, bool ftask) + UnpackRef(AstNode* stmtp, AstSliceSel* nodep, int msb, int lsb, const VAccess& access, + bool ftask) : m_contextp{stmtp} , m_nodep{nodep} , m_index{msb == lsb ? msb : -1} // Equivalent to ArraySel , m_msb{msb} , m_lsb{lsb} - , m_lvalue{lvalue} + , m_access{access} , m_ftask{ftask} {} AstNode* nodep() const { return m_nodep; } bool isSingleRef() const { @@ -275,7 +276,7 @@ public: return m_index; } AstNode* context() const { return m_contextp; } - bool lvalue() const { return m_lvalue; } + VAccess access() const { return m_access; } bool ftask() const { return m_ftask; } bool operator<(const UnpackRef& other) const { return AstNodeComparator()(m_nodep, other.m_nodep); @@ -308,11 +309,11 @@ public: } // Register the location where a variable is used. bool tryAdd(AstNode* context, AstVarRef* refp, AstArraySel* selp, int idx, bool ftask) { - return addCore(refp, UnpackRef(context, selp, idx, refp->lvalue(), ftask)); + return addCore(refp, UnpackRef(context, selp, idx, refp->access(), ftask)); } bool tryAdd(AstNode* context, AstVarRef* refp, AstSliceSel* selp, int msb, int lsb, bool ftask) { - return addCore(refp, UnpackRef(context, selp, msb, lsb, refp->lvalue(), ftask)); + return addCore(refp, UnpackRef(context, selp, msb, lsb, refp->access(), ftask)); } bool tryAdd(AstNode* context, AstVarRef* refp, bool ftask) { return addCore(refp, UnpackRef(context, refp, ftask)); @@ -434,8 +435,8 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { m_refsForPackedSplit[m_modp].add(varp); return varp; } - AstVarRef* newVarRef(FileLine* fl, AstVar* varp, bool lvalue) { - AstVarRef* refp = new AstVarRef(fl, varp, lvalue); + AstVarRef* newVarRef(FileLine* fl, AstVar* varp, const VAccess& access) { + AstVarRef* refp = new AstVarRef(fl, varp, access); UASSERT_OBJ(m_modp, refp, "Must not nullptr"); m_refsForPackedSplit[m_modp].add(refp); return refp; @@ -617,9 +618,11 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { = (context && VN_IS(context, NodeFTaskRef)) || (assignp && VN_IS(assignp, Assign)); for (int i = 0; i <= dtypep->msb() - dtypep->lsb(); ++i) { - AstNode* lhsp = newVarRef(nodep->fileline(), vars.at(start_idx + i), lvalue); - AstNode* rhsp = new AstArraySel(nodep->fileline(), - newVarRef(nodep->fileline(), varp, !lvalue), i); + AstNode* lhsp = newVarRef(nodep->fileline(), vars.at(start_idx + i), + lvalue ? VAccess::WRITE : VAccess::READ); + AstNode* rhsp = new AstArraySel( + nodep->fileline(), + newVarRef(nodep->fileline(), varp, !lvalue ? VAccess::WRITE : VAccess::READ), i); AstNode* refp = lhsp; UINFO(9, "Creating assign idx:" << i << " + " << start_idx << "\n"); if (!lvalue) std::swap(lhsp, rhsp); @@ -643,16 +646,18 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { UASSERT_OBJ(!m_contextp, m_contextp, "must be null"); setContextAndIterate(newassignp, refp); } - return newVarRef(nodep->fileline(), varp, lvalue); + return newVarRef(nodep->fileline(), varp, lvalue ? VAccess::WRITE : VAccess::READ); } void connectPort(AstVar* varp, std::vector& vars, AstNode* insertp) { UASSERT_OBJ(varp->isIO(), varp, "must be port"); insertp = insertp ? toInsertPoint(insertp) : nullptr; const bool lvalue = varp->direction().isWritable(); for (size_t i = 0; i < vars.size(); ++i) { - AstNode* nodes[] - = {new AstArraySel(varp->fileline(), newVarRef(varp->fileline(), varp, lvalue), i), - newVarRef(varp->fileline(), vars.at(i), !lvalue)}; + AstNode* nodes[] = { + new AstArraySel( + varp->fileline(), + newVarRef(varp->fileline(), varp, lvalue ? VAccess::WRITE : VAccess::READ), i), + newVarRef(varp->fileline(), vars.at(i), !lvalue ? VAccess::WRITE : VAccess::READ)}; AstNode* lhsp = nodes[lvalue ? 0 : 1]; AstNode* rhsp = nodes[lvalue ? 1 : 0]; AstNodeAssign* assignp = newAssign(varp->fileline(), lhsp, rhsp, varp); @@ -702,7 +707,7 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { AstNode* newp = nullptr; if (sit->isSingleRef()) { newp = newVarRef(sit->nodep()->fileline(), vars.at(sit->index()), - sit->lvalue()); + sit->access()); } else { AstVarRef* refp = VN_CAST(sit->nodep(), VarRef); AstUnpackArrayDType* adtypep; @@ -718,7 +723,7 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { lsb = adtypep->lsb(); } AstVarRef* newrefp = createTempVar(sit->context(), refp, adtypep, varp->name(), - vars, lsb, refp->lvalue(), sit->ftask()); + vars, lsb, refp->access(), sit->ftask()); newp = newrefp; refp->varp()->addNextHere(newrefp->varp()); UINFO(3, @@ -891,9 +896,9 @@ public: } explicit PackedVarRef(AstVar* varp) : m_basicp{varp->dtypep()->basicp()} {} - void append(const PackedVarRefEntry& e, bool lvalue) { + void append(const PackedVarRefEntry& e, const VAccess& access) { UASSERT(!m_dedupDone, "cannot add after dedup()"); - if (lvalue) + if (access.isWrite()) m_lhs.push_back(e); else m_rhs.push_back(e); @@ -981,7 +986,7 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { "variable in package must have been dropped beforehand."); const AstBasicDType* basicp = refit->second.basicp(); refit->second.append(PackedVarRefEntry(nodep, basicp->lsb(), varp->width()), - nodep->lvalue()); + nodep->access()); UINFO(5, varp->prettyName() << " Entire bit of [" << basicp->lsb() << ":+" << varp->width() << "] \n"); } @@ -1005,7 +1010,7 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { refit->second.append( PackedVarRefEntry(nodep, consts[0]->toSInt() + refit->second.basicp()->lsb(), consts[1]->toUInt()), - vrefp->lvalue()); + vrefp->access()); UINFO(5, varp->prettyName() << " [" << consts[0]->toSInt() << ":+" << consts[1]->toSInt() << "] lsb:" << refit->second.basicp()->lsb() << "\n"); @@ -1028,8 +1033,8 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { // Extract necessary bit range from a newly created variable to meet ref static AstNode* extractBits(const PackedVarRefEntry& ref, const SplitNewVar& var, - bool lvalue) { - AstVarRef* refp = new AstVarRef(ref.nodep()->fileline(), var.varp(), lvalue); + const VAccess access) { + AstVarRef* refp = new AstVarRef(ref.nodep()->fileline(), var.varp(), access); if (ref.lsb() <= var.lsb() && var.msb() <= ref.msb()) { // Use the entire bits return refp; } else { // Use slice @@ -1052,10 +1057,12 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { } const bool in = portp->isReadOnly(); for (size_t i = 0; i < vars.size(); ++i) { - AstNode* rhsp - = new AstSel(portp->fileline(), new AstVarRef(portp->fileline(), portp, !in), - vars[i].lsb(), vars[i].bitwidth()); - AstNode* lhsp = new AstVarRef(portp->fileline(), vars[i].varp(), in); + AstNode* rhsp = new AstSel( + portp->fileline(), + new AstVarRef(portp->fileline(), portp, !in ? VAccess::WRITE : VAccess::READ), + vars[i].lsb(), vars[i].bitwidth()); + AstNode* lhsp = new AstVarRef(portp->fileline(), vars[i].varp(), + in ? VAccess::WRITE : VAccess::READ); if (!in) std::swap(lhsp, rhsp); AstNodeAssign* assignp = newAssign(portp->fileline(), lhsp, rhsp, portp); if (insertp) { @@ -1121,12 +1128,12 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { if (AstSenItem* senitemp = refit->backSenItemp()) { AstNode* oldsenrefp = senitemp->sensp(); oldsenrefp->replaceWith( - new AstVarRef(senitemp->fileline(), varit->varp(), false)); + new AstVarRef(senitemp->fileline(), varit->varp(), VAccess::READ)); VL_DO_DANGLING(oldsenrefp->deleteTree(), oldsenrefp); prevp = senitemp; inSentitivityList = true; } else { - prevp = extractBits(*refit, *varit, lvalue); + prevp = extractBits(*refit, *varit, lvalue ? VAccess::WRITE : VAccess::READ); } for (int residue = refit->msb() - varit->msb(); residue > 0; residue -= varit->bitwidth()) { @@ -1135,10 +1142,11 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { if (AstSenItem* senitemp = VN_CAST(prevp, SenItem)) { prevp = new AstSenItem( senitemp->fileline(), senitemp->edgeType(), - new AstVarRef(senitemp->fileline(), varit->varp(), false)); + new AstVarRef(senitemp->fileline(), varit->varp(), VAccess::READ)); senitemp->addNextHere(prevp); } else { - AstNode* bitsp = extractBits(*refit, *varit, lvalue); + AstNode* bitsp + = extractBits(*refit, *varit, lvalue ? VAccess::WRITE : VAccess::READ); prevp = new AstConcat(refit->nodep()->fileline(), bitsp, prevp); } } @@ -1177,15 +1185,16 @@ class SplitPackedVarVisitor : public AstNVisitor, 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(), false); + AstNode* rhsp = new AstVarRef(vars.front().varp()->fileline(), vars.front().varp(), + VAccess::READ); for (size_t i = 1; i < vars.size(); ++i) { - rhsp = new AstConcat(varp->fileline(), - new AstVarRef(varp->fileline(), vars[i].varp(), false), - rhsp); + rhsp = new AstConcat( + varp->fileline(), + new AstVarRef(varp->fileline(), vars[i].varp(), VAccess::READ), rhsp); } - varp->addNextHere(newAssign( - varp->fileline(), new AstVarRef(varp->fileline(), varp, true), rhsp, varp)); + varp->addNextHere(newAssign(varp->fileline(), + new AstVarRef(varp->fileline(), varp, VAccess::WRITE), + rhsp, varp)); } else { // the original variable is not used anymore. VL_DO_DANGLING(varp->unlinkFrBack()->deleteTree(), varp); } diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index ac18e4d08..7b5752790 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -306,7 +306,7 @@ private: iterate(nodep->rhsp()); AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef); AstConst* constp = VN_CAST(nodep->rhsp(), Const); - if (varrefp && isSubstVar(varrefp->varp()) && !varrefp->lvalue() && constp) { + if (varrefp && isSubstVar(varrefp->varp()) && !varrefp->access().isWrite() && constp) { // Nicely formed lvalues handled in NodeAssign // Other lvalues handled as unknown mess in AstVarRef int word = constp->toUInt(); @@ -329,14 +329,14 @@ private: } virtual void visit(AstVarRef* nodep) override { // Any variable - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { m_assignStep++; nodep->varp()->user2(m_assignStep); UINFO(9, " ASSIGNstep u2=" << nodep->varp()->user2() << " " << nodep << endl); } if (isSubstVar(nodep->varp())) { SubstVarEntry* entryp = getEntryp(nodep); - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { UINFO(8, " ASSIGNcpx " << nodep << endl); entryp->assignComplex(); } else if (AstNode* substp = entryp->substWhole(nodep)) { diff --git a/src/V3Table.cpp b/src/V3Table.cpp index dc350a4d5..b91348489 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -154,7 +154,7 @@ public: // Called by TableSimulateVisitor on each unique varref encountered UINFO(9, " SimVARREF " << nodep << endl); AstVarScope* vscp = nodep->varScopep(); - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { m_outWidth += nodep->varp()->dtypeSkipRefp()->widthTotalBytes(); m_outVarps.push_back(vscp); } else { @@ -255,7 +255,7 @@ private: // First var in inVars becomes the LSB of the concat AstNode* concatp = nullptr; for (AstVarScope* invscp : m_inVarps) { - AstVarRef* refp = new AstVarRef(nodep->fileline(), invscp, false); + AstVarRef* refp = new AstVarRef(nodep->fileline(), invscp, VAccess::READ); if (concatp) { concatp = new AstConcat(nodep->fileline(), refp, concatp); } else { @@ -263,8 +263,9 @@ private: } } - AstNode* stmtsp = new AstAssign( - nodep->fileline(), new AstVarRef(nodep->fileline(), indexVscp, true), concatp); + AstNode* stmtsp + = new AstAssign(nodep->fileline(), + new AstVarRef(nodep->fileline(), indexVscp, VAccess::WRITE), concatp); return stmtsp; } @@ -372,10 +373,11 @@ private: // Set each output from array ref into our table int outnum = 0; for (AstVarScope* outvscp : m_outVarps) { - AstNode* alhsp = new AstVarRef(nodep->fileline(), outvscp, true); + AstNode* alhsp = new AstVarRef(nodep->fileline(), outvscp, VAccess::WRITE); AstNode* arhsp = new AstArraySel( - nodep->fileline(), new AstVarRef(nodep->fileline(), m_tableVarps[outnum], false), - new AstVarRef(nodep->fileline(), indexVscp, false)); + nodep->fileline(), + new AstVarRef(nodep->fileline(), m_tableVarps[outnum], VAccess::READ), + new AstVarRef(nodep->fileline(), indexVscp, VAccess::READ)); AstNode* outasnp = (m_assignDly ? static_cast(new AstAssignDly(nodep->fileline(), alhsp, arhsp)) @@ -389,9 +391,10 @@ private: outsetp = new AstIf( nodep->fileline(), new AstAnd(nodep->fileline(), - new AstArraySel(nodep->fileline(), - new AstVarRef(nodep->fileline(), chgVscp, false), - new AstVarRef(nodep->fileline(), indexVscp, false)), + new AstArraySel( + nodep->fileline(), + new AstVarRef(nodep->fileline(), chgVscp, VAccess::READ), + new AstVarRef(nodep->fileline(), indexVscp, VAccess::READ)), new AstConst(nodep->fileline(), outputChgMask)), outsetp, nullptr); } diff --git a/src/V3Task.cpp b/src/V3Task.cpp index f21ba9488..392641ba4 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -448,9 +448,9 @@ private: AstVarScope* tempvscp = createVarScope(portp, namePrefix + "__" + portp->shortName()); portp->user2p(tempvscp); - AstAssign* assp - = new AstAssign(pinp->fileline(), pinp, - new AstVarRef(tempvscp->fileline(), tempvscp, false)); + AstAssign* assp = new AstAssign( + pinp->fileline(), pinp, + new AstVarRef(tempvscp->fileline(), tempvscp, VAccess::READ)); assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block // Put assignment BEHIND of all other statements @@ -461,7 +461,8 @@ private: = createVarScope(portp, namePrefix + "__" + portp->shortName()); portp->user2p(inVscp); AstAssign* assp = new AstAssign( - pinp->fileline(), new AstVarRef(inVscp->fileline(), inVscp, true), pinp); + pinp->fileline(), + new AstVarRef(inVscp->fileline(), inVscp, VAccess::WRITE), pinp); assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block // Put assignment in FRONT of all other statements @@ -571,10 +572,10 @@ private: AstVarScope* newvscp = createVarScope(portp, namePrefix + "__" + portp->shortName()); portp->user2p(newvscp); - pinp->replaceWith(new AstVarRef(newvscp->fileline(), newvscp, true)); - AstAssign* assp - = new AstAssign(pinp->fileline(), pinp, - new AstVarRef(newvscp->fileline(), newvscp, false)); + pinp->replaceWith(new AstVarRef(newvscp->fileline(), newvscp, VAccess::WRITE)); + AstAssign* assp = new AstAssign( + pinp->fileline(), pinp, + new AstVarRef(newvscp->fileline(), newvscp, VAccess::READ)); assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block // Put assignment BEHIND of all other statements @@ -608,7 +609,7 @@ private: ccallp->addArgsp(exprp); } - if (outvscp) ccallp->addArgsp(new AstVarRef(refp->fileline(), outvscp, true)); + if (outvscp) ccallp->addArgsp(new AstVarRef(refp->fileline(), outvscp, VAccess::WRITE)); if (debug() >= 9) beginp->dumpTreeAndNext(cout, "-nitask: "); return beginp; @@ -661,7 +662,7 @@ private: bool useSetWSvlv = V3Task::dpiToInternalFrStmt(portp, frName, frstmt); if (useSetWSvlv) { AstNode* linesp = new AstText(portp->fileline(), frstmt); - linesp->addNext(new AstVarRef(portp->fileline(), portvscp, true)); + linesp->addNext(new AstVarRef(portp->fileline(), portvscp, VAccess::WRITE)); linesp->addNext(new AstText(portp->fileline(), "," + frName + ");")); return new AstCStmt(portp->fileline(), linesp); } @@ -675,7 +676,7 @@ private: } } AstNode* newp = new AstAssign( - portp->fileline(), new AstVarRef(portp->fileline(), portvscp, true), + portp->fileline(), new AstVarRef(portp->fileline(), portvscp, VAccess::WRITE), new AstSel(portp->fileline(), new AstCMath(portp->fileline(), frstmt, cwidth, false), 0, portp->width())); return newp; @@ -741,7 +742,8 @@ private: outvscp->varp()->protect(false); portp->protect(false); AstVarRef* refp - = new AstVarRef(portp->fileline(), outvscp, portp->isWritable()); + = new AstVarRef(portp->fileline(), outvscp, + portp->isWritable() ? VAccess::WRITE : VAccess::READ); argnodesp = argnodesp->addNextNull(refp); if (portp->isNonOutput()) { @@ -765,7 +767,8 @@ private: AstVarScope* outvscp = createFuncVar(dpip, portp->name() + "__Vcvt", portp); // No information exposure; is already visible in import/export func template outvscp->varp()->protect(false); - AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isWritable()); + AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, + portp->isWritable() ? VAccess::WRITE : VAccess::READ); argnodesp = argnodesp->addNextNull(refp); } @@ -1134,8 +1137,8 @@ private: // Return statement if (rtnvscp && nodep->taskPublic()) { - cfuncp->addFinalsp(new AstCReturn(rtnvscp->fileline(), - new AstVarRef(rtnvscp->fileline(), rtnvscp, false))); + cfuncp->addFinalsp(new AstCReturn( + rtnvscp->fileline(), new AstVarRef(rtnvscp->fileline(), rtnvscp, VAccess::READ))); } // Replace variable refs // Iteration requires a back, so put under temporary node @@ -1245,7 +1248,7 @@ private: visitp = insertBeforeStmt(nodep, beginp); } else if (!nodep->isStatement()) { UASSERT_OBJ(nodep->taskp()->isFunction(), nodep, "func reference to non-function"); - AstVarRef* outrefp = new AstVarRef(nodep->fileline(), outvscp, false); + AstVarRef* outrefp = new AstVarRef(nodep->fileline(), outvscp, VAccess::READ); nodep->replaceWith(outrefp); // Insert new statements visitp = insertBeforeStmt(nodep, beginp); diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index cb29a734e..3aeace7ab 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -419,13 +419,13 @@ private: graphSimplify(false); } - AstNode* selectActivity(FileLine* flp, uint32_t acode, bool lvalue) { - return new AstArraySel(flp, new AstVarRef(flp, m_activityVscp, lvalue), acode); + AstNode* selectActivity(FileLine* flp, uint32_t acode, const VAccess& access) { + return new AstArraySel(flp, new AstVarRef(flp, m_activityVscp, access), acode); } void addActivitySetter(AstNode* insertp, uint32_t code) { FileLine* const fl = insertp->fileline(); - AstAssign* const setterp = new AstAssign(fl, selectActivity(fl, code, true), + AstAssign* const setterp = new AstAssign(fl, selectActivity(fl, code, VAccess::WRITE), new AstConst(fl, AstConst::LogicTrue())); if (AstCCall* const callp = VN_CAST(insertp, CCall)) { callp->addNextHere(setterp); @@ -638,7 +638,7 @@ private: condp = new AstConst(flp, 1); // Always true, will be folded later } else { for (const uint32_t actCode : actSet) { - AstNode* const selp = selectActivity(flp, actCode, false); + AstNode* const selp = selectActivity(flp, actCode, VAccess::READ); condp = condp ? new AstOr(flp, condp, selp) : selp; } } @@ -651,7 +651,7 @@ private: // Add TraceInc node AstTraceDecl* const declp = vtxp->nodep(); - AstTraceInc* const incp = new AstTraceInc(declp->fileline(), declp, false); + AstTraceInc* const incp = new AstTraceInc(declp->fileline(), declp, VAccess::READ); ifp->addIfsp(incp); subStmts += EmitCBaseCounterVisitor(incp).count(); @@ -686,7 +686,7 @@ private: // Clear fine grained activity flags for (uint32_t i = 0; i < m_activityNumber; ++i) { - AstNode* const clrp = new AstAssign(fl, selectActivity(fl, i, true), + AstNode* const clrp = new AstAssign(fl, selectActivity(fl, i, VAccess::WRITE), new AstConst(fl, AstConst::LogicFalse())); cleanupFuncp->addStmtsp(clrp); } @@ -845,7 +845,7 @@ private: virtual void visit(AstVarRef* nodep) override { if (m_tracep) { UASSERT_OBJ(nodep->varScopep(), nodep, "No var scope?"); - UASSERT_OBJ(!nodep->lvalue(), nodep, "Lvalue in trace? Should be const."); + UASSERT_OBJ(!nodep->access().isWrite(), nodep, "Lvalue in trace? Should be const."); V3GraphVertex* varVtxp = nodep->varScopep()->user1u().toGraphVertex(); if (!varVtxp) { varVtxp = new TraceVarVertex(&m_graph, nodep->varScopep()); @@ -857,7 +857,7 @@ private: || nodep->varp()->isSigPublic()) { // Or ones user can change new V3GraphEdge(&m_graph, m_alwaysVtxp, traceVtxp, 1); } - } else if (m_funcp && m_finding && nodep->lvalue()) { + } else if (m_funcp && m_finding && nodep->access().isWrite()) { UASSERT_OBJ(nodep->varScopep(), nodep, "No var scope?"); V3GraphVertex* const funcVtxp = getCFuncVertexp(m_funcp); V3GraphVertex* const varVtxp = nodep->varScopep()->user1u().toGraphVertex(); diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 4157347a5..f8669c6bd 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -201,7 +201,7 @@ private: if (nodep->valuep()) { m_traValuep = nodep->valuep()->cloneTree(true); } else { - m_traValuep = new AstVarRef(nodep->fileline(), nodep, false); + m_traValuep = new AstVarRef(nodep->fileline(), nodep, VAccess::READ); } // Recurse into data type of the signal; the visitors will call addTraceDecl() iterate(varp->dtypep()->skipRefToEnump()); diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 7dda34b28..1bcf41c3f 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -168,7 +168,7 @@ private: for (V3GraphEdge* edgep = vtxp->inBeginp(); edgep; edgep = edgep->inNextp()) { TristateVertex* vvertexp = dynamic_cast(edgep->fromp()); if (const AstVarRef* refp = VN_CAST(vvertexp->nodep(), VarRef)) { - if (refp->lvalue() + if (refp->access().isWrite() // Doesn't hurt to not check if already set, but by doing so when we // print out the debug messages, we'll see this node at level 0 instead. && !vvertexp->isTristate()) { @@ -276,12 +276,12 @@ class TristatePinVisitor : public TristateBaseVisitor { bool m_lvalue; // Flip to be an LVALUE // VISITORS virtual void visit(AstVarRef* nodep) override { - if (m_lvalue && !nodep->lvalue()) { + if (m_lvalue && !nodep->access().isWrite()) { UINFO(9, " Flip-to-LValue " << nodep << endl); - nodep->lvalue(true); - } else if (!m_lvalue && nodep->lvalue()) { + nodep->access(VAccess::WRITE); + } else if (!m_lvalue && nodep->access().isWrite()) { UINFO(9, " Flip-to-RValue " << nodep << endl); - nodep->lvalue(false); + nodep->access(VAccess::READ); // Mark the ex-output as tristated UINFO(9, " setTristate-subpin " << nodep->varp() << endl); m_tgraph.setTristate(nodep->varp()); @@ -489,7 +489,7 @@ class TristateVisitor : public TristateBaseVisitor { UINFO(8, " Adding driver to var " << varp << endl); AstConst* constp = new AstConst(varp->fileline(), AstConst::WidthedValue(), varp->width(), 0); - AstVarRef* varrefp = new AstVarRef(varp->fileline(), varp, true); + AstVarRef* varrefp = new AstVarRef(varp->fileline(), varp, VAccess::WRITE); AstNode* newp = new AstAssignW(varp->fileline(), varrefp, constp); UINFO(9, " newoev " << newp << endl); varrefp->user1p(new AstConst(varp->fileline(), AstConst::WidthedValue(), @@ -577,24 +577,25 @@ class TristateVisitor : public TristateBaseVisitor { nodep->addStmtp(newenp); AstNode* enassp = new AstAssignW( - refp->fileline(), new AstVarRef(refp->fileline(), newenp, true), getEnp(refp)); + refp->fileline(), new AstVarRef(refp->fileline(), newenp, VAccess::WRITE), + getEnp(refp)); UINFO(9, " newass " << enassp << endl); nodep->addStmtp(enassp); // now append this driver to the driver logic. - AstNode* ref1p = new AstVarRef(refp->fileline(), newlhsp, false); - AstNode* ref2p = new AstVarRef(refp->fileline(), newenp, false); + AstNode* ref1p = new AstVarRef(refp->fileline(), newlhsp, VAccess::READ); + AstNode* ref2p = new AstVarRef(refp->fileline(), newenp, VAccess::READ); AstNode* andp = new AstAnd(refp->fileline(), ref1p, ref2p); // or this to the others orp = (!orp) ? andp : new AstOr(refp->fileline(), orp, andp); if (envarp) { - AstNode* ref3p = new AstVarRef(refp->fileline(), newenp, false); + AstNode* ref3p = new AstVarRef(refp->fileline(), newenp, VAccess::READ); enp = (!enp) ? ref3p : new AstOr(ref3p->fileline(), enp, ref3p); } - AstNode* tmp = new AstNot(newenp->fileline(), - new AstVarRef(newenp->fileline(), newenp, false)); + AstNode* tmp = new AstNot( + newenp->fileline(), new AstVarRef(newenp->fileline(), newenp, VAccess::READ)); undrivenp = ((!undrivenp) ? tmp : new AstAnd(refp->fileline(), tmp, undrivenp)); } if (!undrivenp) { // No drivers on the bus @@ -621,11 +622,12 @@ class TristateVisitor : public TristateBaseVisitor { } if (envarp) { nodep->addStmtp(new AstAssignW( - enp->fileline(), new AstVarRef(envarp->fileline(), envarp, true), enp)); + enp->fileline(), new AstVarRef(envarp->fileline(), envarp, VAccess::WRITE), + enp)); } // __out (child) or (parent) = drive-value expression - AstNode* assp = new AstAssignW(lhsp->fileline(), - new AstVarRef(lhsp->fileline(), lhsp, true), orp); + AstNode* assp = new AstAssignW( + lhsp->fileline(), new AstVarRef(lhsp->fileline(), lhsp, VAccess::WRITE), orp); assp->user2(U2_BOTH); // Don't process further; already resolved if (debug() >= 9) assp->dumpTree(cout, "-lhsp-eqn: "); nodep->addStmtp(assp); @@ -647,7 +649,7 @@ class TristateVisitor : public TristateBaseVisitor { // due to the pinReconnectSimple call in visit AstPin. // We can ignore the output override by making a temporary AstVar* varp = getCreateUnconnVarp(nodep, nodep->dtypep()); - AstNode* newp = new AstVarRef(nodep->fileline(), varp, true); + AstNode* newp = new AstVarRef(nodep->fileline(), varp, VAccess::WRITE); UINFO(9, " const->" << newp << endl); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -945,10 +947,12 @@ class TristateVisitor : public TristateBaseVisitor { ->num(); // visit(AstConst) already split into en/ones const V3Number& oneIfEnOne = constp->num(); AstVar* envarp = getCreateEnVarp(varrefp->varp()); - AstNode* newp = new AstLogAnd( - fl, new AstEq(fl, new AstConst(fl, oneIfEn), new AstVarRef(fl, envarp, false)), - // Keep the caseeq if there are X's present - new AstEqCase(fl, new AstConst(fl, oneIfEnOne), varrefp)); + AstNode* newp + = new AstLogAnd(fl, + new AstEq(fl, new AstConst(fl, oneIfEn), + new AstVarRef(fl, envarp, VAccess::READ)), + // Keep the caseeq if there are X's present + new AstEqCase(fl, new AstConst(fl, oneIfEnOne), varrefp)); if (neq) newp = new AstLogNot(fl, newp); UINFO(9, " newceq " << newp << endl); if (debug() >= 9) nodep->dumpTree(cout, "-caseeq-old: "); @@ -992,7 +996,7 @@ class TristateVisitor : public TristateBaseVisitor { nodep->v3warn(E_UNSUPPORTED, "Unsupported pullup/down (weak driver) construct."); } else { if (m_graphing) { - varrefp->lvalue(true); + varrefp->access(VAccess::WRITE); m_logicp = nodep; m_tgraph.setTristate(nodep); associateLogic(nodep, varrefp->varp()); @@ -1004,7 +1008,7 @@ class TristateVisitor : public TristateBaseVisitor { // current limitation of this implementation is that a pullup/down // gets applied to all bits of a bus and a bus cannot have drivers // in opposite directions on individual pins. - varrefp->lvalue(true); + varrefp->access(VAccess::WRITE); m_tgraph.didProcess(nodep); m_tgraph.didProcess(varrefp->varp()); setPullDirection(varrefp->varp(), nodep); @@ -1082,7 +1086,9 @@ class TristateVisitor : public TristateBaseVisitor { AstVar* ucVarp = getCreateUnconnVarp(nodep, nodep->modVarp()->dtypep()); nodep->exprp(new AstVarRef(nodep->fileline(), ucVarp, // We converted, so use declaration output state - nodep->modVarp()->declDirection().isWritable())); + nodep->modVarp()->declDirection().isWritable() + ? VAccess::WRITE + : VAccess::READ)); m_tgraph.setTristate(ucVarp); // We don't need a driver on the wire; the lack of one will default to tristate } else if (inDeclProcessing) { // Not an input that was a converted tristate @@ -1103,15 +1109,16 @@ class TristateVisitor : public TristateBaseVisitor { nodep->name() + "__en" + cvtToStr(m_unique++), VFlagBitPacked(), enModVarp->width()); UINFO(9, " newenv " << enVarp << endl); - AstPin* enpinp = new AstPin(nodep->fileline(), nodep->pinNum(), - enModVarp->name(), // should be {var}"__en" - new AstVarRef(nodep->fileline(), enVarp, true)); + AstPin* enpinp + = new AstPin(nodep->fileline(), nodep->pinNum(), + enModVarp->name(), // should be {var}"__en" + new AstVarRef(nodep->fileline(), enVarp, VAccess::WRITE)); enpinp->modVarp(enModVarp); UINFO(9, " newpin " << enpinp << endl); enpinp->user2(U2_BOTH); // don't iterate the pin later nodep->addNextHere(enpinp); m_modp->addStmtp(enVarp); - enrefp = new AstVarRef(nodep->fileline(), enVarp, false); + enrefp = new AstVarRef(nodep->fileline(), enVarp, VAccess::READ); UINFO(9, " newvrf " << enrefp << endl); if (debug() >= 9) enpinp->dumpTree(cout, "-pin-ena: "); } @@ -1215,7 +1222,7 @@ class TristateVisitor : public TristateBaseVisitor { virtual void visit(AstVarRef* nodep) override { UINFO(9, dbgState() << nodep << endl); if (m_graphing) { - if (nodep->lvalue()) { + if (nodep->access().isWrite()) { associateLogic(nodep, nodep->varp()); } else { associateLogic(nodep->varp(), nodep); @@ -1226,11 +1233,11 @@ class TristateVisitor : public TristateBaseVisitor { // Detect all var lhs drivers and adds them to the // VarMap so that after the walk through the module we can expand // any tristate logic on the driver. - if (nodep->lvalue() && m_tgraph.isTristate(nodep->varp())) { + if (nodep->access().isWrite() && m_tgraph.isTristate(nodep->varp())) { UINFO(9, " Ref-to-lvalue " << nodep << endl); m_tgraph.didProcess(nodep); mapInsertLhsVarRef(nodep); - } else if (!nodep->lvalue() + } else if (!nodep->access().isWrite() // Not already processed, nor varref from visit(AstPin) creation && !nodep->user1p() // Reference to another tristate variable @@ -1240,7 +1247,7 @@ class TristateVisitor : public TristateBaseVisitor { // Then propagate the enable from the original variable UINFO(9, " Ref-to-tri " << nodep << endl); AstVar* enVarp = getCreateEnVarp(nodep->varp()); - nodep->user1p(new AstVarRef(nodep->fileline(), enVarp, false)); + nodep->user1p(new AstVarRef(nodep->fileline(), enVarp, VAccess::READ)); } if (m_alhs) {} // NOP; user1() already passed down from assignment } @@ -1254,9 +1261,9 @@ class TristateVisitor : public TristateBaseVisitor { if (nodep->user2() & U2_GRAPHING) return; // Already processed nodep->user2(U2_GRAPHING); if (nodep->isPulldown() || nodep->isPullup()) { - AstNode* newp - = new AstPull(nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, true), - nodep->isPullup()); + AstNode* newp = new AstPull( + nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, VAccess::WRITE), + nodep->isPullup()); UINFO(9, " newpul " << newp << endl); nodep->addNextHere(newp); // We'll iterate on the new AstPull later diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 01890983f..c09336dcd 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -318,7 +318,7 @@ private: for (int usr = 1; usr < (m_alwaysCombp ? 3 : 2); ++usr) { UndrivenVarEntry* entryp = getEntryp(varrefp->varp(), usr); int lsb = constp->toUInt(); - if (m_inBBox || varrefp->lvalue()) { + if (m_inBBox || varrefp->access().isWrite()) { // Don't warn if already driven earlier as "a=0; if(a) a=1;" is fine. if (usr == 2 && m_alwaysCombp && entryp->isUsedNotDrivenBit(lsb, nodep->width())) { @@ -327,7 +327,7 @@ private: } entryp->drivenBit(lsb, nodep->width()); } - if (m_inBBox || !varrefp->lvalue()) entryp->usedBit(lsb, nodep->width()); + if (m_inBBox || !varrefp->access().isWrite()) entryp->usedBit(lsb, nodep->width()); } } else { // else other varrefs handled as unknown mess in AstVarRef @@ -336,7 +336,7 @@ private: } virtual void visit(AstNodeVarRef* nodep) override { // Any variable - if (nodep->lvalue() + if (nodep->access().isWrite() && !VN_IS(nodep, VarXRef)) { // Ignore interface variables and similar ugly items if (m_inProcAssign && !nodep->varp()->varType().isProcAssignable() && !nodep->varp()->isDeclTyped() // @@ -355,16 +355,16 @@ private: } for (int usr = 1; usr < (m_alwaysCombp ? 3 : 2); ++usr) { UndrivenVarEntry* entryp = getEntryp(nodep->varp(), usr); - bool fdrv = nodep->lvalue() + bool fdrv = nodep->access().isWrite() && nodep->varp()->attrFileDescr(); // FD's are also being read from - if (m_inBBox || nodep->lvalue()) { + if (m_inBBox || nodep->access().isWrite()) { if (usr == 2 && m_alwaysCombp && entryp->isUsedNotDrivenAny()) { UINFO(9, " Full bus. Entryp=" << cvtToHex(entryp) << endl); warnAlwCombOrder(nodep); } entryp->drivenWhole(); } - if (m_inBBox || !nodep->lvalue() || fdrv) entryp->usedWhole(); + if (m_inBBox || !nodep->access().isWrite() || fdrv) entryp->usedWhole(); } } diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 15e9a199b..160c161c3 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -118,14 +118,14 @@ private: m_modp->addStmtp(varp); AstNode* abovep = prep->backp(); // Grab above point before lose it w/ next replace - prep->replaceWith(new AstVarRef(fl, varp, true)); - AstIf* newp - = new AstIf(fl, condp, - (needDly ? static_cast( - new AstAssignDly(fl, prep, new AstVarRef(fl, varp, false))) - : static_cast( - new AstAssign(fl, prep, new AstVarRef(fl, varp, false)))), - nullptr); + prep->replaceWith(new AstVarRef(fl, varp, VAccess::WRITE)); + AstIf* newp = new AstIf( + fl, condp, + (needDly ? static_cast( + new AstAssignDly(fl, prep, new AstVarRef(fl, varp, VAccess::READ))) + : static_cast( + new AstAssign(fl, prep, new AstVarRef(fl, varp, VAccess::READ)))), + nullptr); newp->branchPred(VBranchPred::BP_LIKELY); if (debug() >= 9) newp->dumpTree(cout, " _new: "); abovep->addNextStmt(newp, abovep); @@ -281,12 +281,13 @@ private: ++m_statUnkVars; AstNRelinker replaceHandle; nodep->unlinkFrBack(&replaceHandle); - AstNodeVarRef* newref1p = new AstVarRef(nodep->fileline(), newvarp, false); + AstNodeVarRef* newref1p = new AstVarRef(nodep->fileline(), newvarp, VAccess::READ); replaceHandle.relink(newref1p); // Replace const with varref AstInitial* newinitp = new AstInitial( nodep->fileline(), new AstAssign( - nodep->fileline(), new AstVarRef(nodep->fileline(), newvarp, true), + nodep->fileline(), + new AstVarRef(nodep->fileline(), newvarp, VAccess::WRITE), new AstOr( nodep->fileline(), new AstConst(nodep->fileline(), numb1), new AstAnd(nodep->fileline(), new AstConst(nodep->fileline(), numbx), @@ -312,7 +313,7 @@ private: AstNode* basefromp = AstArraySel::baseFromp(nodep); bool lvalue = false; if (const AstNodeVarRef* varrefp = VN_CAST(basefromp, NodeVarRef)) { - lvalue = varrefp->lvalue(); + lvalue = varrefp->access().isWrite(); } // Find range of dtype we are selecting from // Similar code in V3Const::warnSelect @@ -360,7 +361,7 @@ private: AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp()); bool lvalue = false; if (const AstNodeVarRef* varrefp = VN_CAST(basefromp, NodeVarRef)) { - lvalue = varrefp->lvalue(); + lvalue = varrefp->access().isWrite(); } else if (VN_IS(basefromp, Const)) { // If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp } else { diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 968a23c30..a94de57ac 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -445,13 +445,13 @@ private: virtual void visit(AstVarRef* nodep) override { if (m_varModeCheck && nodep->varp() == m_forVarp && nodep->varScopep() == m_forVscp - && nodep->lvalue()) { + && nodep->access().isWrite()) { UINFO(8, " Itervar assigned to: " << nodep << endl); m_varAssignHit = true; } if (m_varModeReplace && nodep->varp() == m_forVarp && nodep->varScopep() == m_forVscp - && !nodep->lvalue()) { + && !nodep->access().isWrite()) { AstNode* newconstp = m_varValuep->cloneTree(false); nodep->replaceWith(newconstp); pushDeletep(nodep); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 081dcbd10..2e0245d12 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1356,7 +1356,7 @@ private: AstVar* varp = dimensionVarp(nodep->fromp()->dtypep(), nodep->attrType(), msbdim); AstNode* dimp = nodep->dimp()->unlinkFrBack(); - AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, false); + AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, VAccess::READ); varrefp->packagep(v3Global.rootp()->dollarUnitPkgAddp()); AstNode* newp = new AstArraySel(nodep->fileline(), varrefp, dimp); nodep->replaceWith(newp); @@ -1805,13 +1805,13 @@ private: // nodep->varp()->dumpTree(cout, " forvar "); } // Note genvar's are also entered as integers nodep->dtypeFrom(nodep->varp()); - if (VN_IS(nodep->backp(), NodeAssign) && nodep->lvalue()) { // On LHS + if (VN_IS(nodep->backp(), NodeAssign) && nodep->access().isWrite()) { // On LHS UASSERT_OBJ(nodep->dtypep(), nodep, "LHS var should be dtype completed"); } // if (debug() >= 9) nodep->dumpTree(cout, " VRout "); - if (nodep->lvalue() && nodep->varp()->direction() == VDirection::CONSTREF) { + if (nodep->access().isWrite() && nodep->varp()->direction() == VDirection::CONSTREF) { nodep->v3error("Assigning to const ref variable: " << nodep->prettyNameQ()); - } else if (nodep->lvalue() && nodep->varp()->isConst() && !m_paramsOnly + } else if (nodep->access().isWrite() && nodep->varp()->isConst() && !m_paramsOnly && (!m_ftaskp || !m_ftaskp->isConstructor()) && !VN_IS(m_procedurep, Initial)) { // Too loose, but need to allow our generated first assignment // Move this to a property of the AstInitial block @@ -2311,7 +2311,7 @@ private: } int selwidth = V3Number::log2b(msbdim) + 1; // Width to address a bit AstVar* varp = enumVarp(adtypep, attrType, (1ULL << selwidth) - 1); - AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, false); + AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, VAccess::READ); varrefp->packagep(v3Global.rootp()->dollarUnitPkgAddp()); AstNode* newp = new AstArraySel( nodep->fileline(), varrefp, @@ -2358,7 +2358,7 @@ private: newp->didWidth(true); } else if (nodep->name() == "delete") { // function void delete([input integer index]) methodOkArguments(nodep, 0, 1); - methodCallLValueRecurse(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); if (!nodep->pinsp()) { newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "clear", nullptr); @@ -2387,13 +2387,13 @@ private: VL_DANGLING(index_exprp); // May have been edited return VN_CAST(nodep->pinsp(), Arg)->exprp(); } - void methodCallLValueRecurse(AstMethodCall* nodep, AstNode* childp, bool lvalue) { + void methodCallLValueRecurse(AstMethodCall* nodep, AstNode* childp, const VAccess& access) { if (AstNodeVarRef* varrefp = VN_CAST(childp, NodeVarRef)) { - if (lvalue) varrefp->lvalue(true); + varrefp->access(access); } else if (AstMemberSel* ichildp = VN_CAST(childp, MemberSel)) { - methodCallLValueRecurse(nodep, ichildp->fromp(), lvalue); + methodCallLValueRecurse(nodep, ichildp->fromp(), access); } else if (AstNodeSel* ichildp = VN_CAST(childp, NodeSel)) { - methodCallLValueRecurse(nodep, ichildp->fromp(), lvalue); + methodCallLValueRecurse(nodep, ichildp->fromp(), access); } else { UINFO(1, " Related node: " << childp << endl); nodep->v3warn(E_UNSUPPORTED, "Unsupported: Non-variable on LHS of built-in method '" @@ -2404,7 +2404,7 @@ private: AstCMethodHard* newp = nullptr; if (nodep->name() == "at") { // Created internally for [] methodOkArguments(nodep, 1, 1); - methodCallLValueRecurse(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "at", nullptr); newp->dtypeFrom(adtypep->subDTypep()); @@ -2419,7 +2419,7 @@ private: newp->protect(false); } else if (nodep->name() == "delete") { // function void delete() methodOkArguments(nodep, 0, 0); - methodCallLValueRecurse(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "clear", nullptr); newp->makeStatement(); @@ -2437,7 +2437,7 @@ private: AstCMethodHard* newp = nullptr; if (nodep->name() == "at") { // Created internally for [] methodOkArguments(nodep, 1, 1); - methodCallLValueRecurse(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "at", nullptr); newp->dtypeFrom(adtypep->subDTypep()); @@ -2453,7 +2453,7 @@ private: newp->protect(false); } else if (nodep->name() == "delete") { // function void delete([input integer index]) methodOkArguments(nodep, 0, 1); - methodCallLValueRecurse(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); if (!nodep->pinsp()) { newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "clear", nullptr); @@ -2480,7 +2480,7 @@ private: } } else if (nodep->name() == "insert") { methodOkArguments(nodep, 2, 2); - methodCallLValueRecurse(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); AstNode* index_exprp = methodCallQueueIndexExpr(nodep); AstArg* argp = VN_CAST(nodep->pinsp()->nextp(), Arg); iterateCheckTyped(nodep, "insert value", argp->exprp(), adtypep->subDTypep(), BOTH); @@ -2501,7 +2501,7 @@ private: } } else if (nodep->name() == "pop_front" || nodep->name() == "pop_back") { methodOkArguments(nodep, 0, 0); - methodCallLValueRecurse(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), nodep->name(), nullptr); newp->dtypeFrom(adtypep->subDTypep()); @@ -2510,7 +2510,7 @@ private: if (!nodep->firstAbovep()) { newp->makeStatement(); } } else if (nodep->name() == "push_back" || nodep->name() == "push_front") { methodOkArguments(nodep, 1, 1); - methodCallLValueRecurse(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); AstArg* argp = VN_CAST(nodep->pinsp(), Arg); iterateCheckTyped(nodep, "push value", argp->exprp(), adtypep->subDTypep(), BOTH); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), @@ -2672,10 +2672,10 @@ private: AstNodeVarRef* fromp = VN_CAST(nodep->fromp()->unlinkFrBack(), VarRef); AstNode* rhsp = arg0p->exprp()->unlinkFrBack(); AstNode* thsp = arg1p->exprp()->unlinkFrBack(); - AstVarRef* varrefp = new AstVarRef(nodep->fileline(), fromp->varp(), false); + AstVarRef* varrefp = new AstVarRef(nodep->fileline(), fromp->varp(), VAccess::READ); AstNode* newp = new AstAssign(nodep->fileline(), fromp, new AstPutcN(nodep->fileline(), varrefp, rhsp, thsp)); - fromp->lvalue(true); + fromp->access(VAccess::WRITE); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } else if (nodep->name() == "getc") { @@ -5082,7 +5082,7 @@ private: AstNode* newp = new AstAssign( nodep->fileline(), fromp, new AstSFormatF(nodep->fileline(), format, false, argp->exprp()->unlinkFrBack())); - fromp->lvalue(true); + fromp->access(VAccess::WRITE); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index b6b248810..ce6cdcee8 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -280,7 +280,7 @@ private: "Unsupported: String array operation on non-variable"); } AstNode* newp; - if (varrefp && varrefp->lvalue()) { + if (varrefp && varrefp->access().isWrite()) { newp = new AstGetcRefN(nodep->fileline(), fromp, rhsp); } else { newp = new AstGetcN(nodep->fileline(), fromp, rhsp); diff --git a/src/verilog.y b/src/verilog.y index c9b2e8648..acc8dcc87 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -1932,7 +1932,7 @@ list_of_tf_variable_identifiers: // ==IEEE: list_of_tf_variable_identifie tf_variable_identifier: // IEEE: part of list_of_tf_variable_identifiers id variable_dimensionListE sigAttrListE exprEqE { $$ = VARDONEA($1,*$1, $2, $3); - if ($4) $$->addNext(new AstAssign($4->fileline(), new AstVarRef($1, *$1, true), $4)); } + if ($4) $$->addNext(new AstAssign($4->fileline(), new AstVarRef($1, *$1, VAccess::WRITE), $4)); } ; variable_declExpr: // IEEE: part of variable_decl_assignment - rhs of expr @@ -2432,7 +2432,8 @@ loop_generate_construct: // ==IEEE: loop_generate_construct genvar_initialization: // ==IEEE: genvar_initialization varRefBase '=' expr { $$ = new AstAssign($2,$1,$3); } - | yGENVAR genvar_identifierDecl '=' constExpr { $$ = $2; $2->addNext(new AstAssign($3,new AstVarRef($2->fileline(),$2,true), $4)); } + | yGENVAR genvar_identifierDecl '=' constExpr + { $$ = $2; $2->addNext(new AstAssign($3, new AstVarRef($2->fileline(), $2, VAccess::WRITE), $4)); } ; genvar_iteration: // ==IEEE: genvar_iteration @@ -2542,7 +2543,7 @@ netSigList: // IEEE: list_of_port_identifiers netSig: // IEEE: net_decl_assignment - one element from list_of_port_identifiers netId sigAttrListE { $$ = VARDONEA($1,*$1, nullptr, $2); } | netId sigAttrListE '=' expr { $$ = VARDONEA($1,*$1, nullptr, $2); - $$->addNext(new AstAssignW($3, new AstVarRef($1, *$1, true), $4)); } + $$->addNext(new AstAssignW($3, new AstVarRef($1, *$1, VAccess::WRITE), $4)); } | netId variable_dimensionList sigAttrListE { $$ = VARDONEA($1,*$1, $2, $3); } ; @@ -3386,12 +3387,12 @@ for_initializationItem: // IEEE: variable_assignment + for_variable_decl data_type idAny/*new*/ '=' expr { VARRESET_NONLIST(VAR); VARDTYPE($1); $$ = VARDONEA($2,*$2,nullptr,nullptr); - $$->addNext(new AstAssign($3, new AstVarRef($2, *$2, true), $4));} + $$->addNext(new AstAssign($3, new AstVarRef($2, *$2, VAccess::WRITE), $4)); } // // IEEE-2012: | yVAR data_type idAny/*new*/ '=' expr { VARRESET_NONLIST(VAR); VARDTYPE($2); $$ = VARDONEA($3,*$3,nullptr,nullptr); - $$->addNext(new AstAssign($4, new AstVarRef($3, *$3, true), $5));} + $$->addNext(new AstAssign($4, new AstVarRef($3, *$3, VAccess::WRITE), $5)); } // // IEEE: variable_assignment // // UNSUP variable_lvalue below | varRefBase '=' expr { $$ = new AstAssign($2, $1, $3); } @@ -4860,7 +4861,7 @@ idArrayedForeach: // IEEE: id + select (under foreach expression) // VarRef without any dots or vectorizaion varRefBase: - id { $$ = new AstVarRef($1,*$1,false);} + id { $$ = new AstVarRef($1, *$1, VAccess::READ); } ; // yaSTRING shouldn't be used directly, instead via an abstraction below