Internals: Create VAccess class. No functional change intended.

This commit is contained in:
Wilson Snyder 2020-09-07 17:09:25 -04:00
parent cc134b38ee
commit 1899a875a4
52 changed files with 470 additions and 384 deletions

View File

@ -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);
}

View File

@ -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<en>(_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; }

View File

@ -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] <- ";

View File

@ -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);
}

View File

@ -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 {

View File

@ -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)));
}
}
}

View File

@ -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));

View File

@ -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);

View File

@ -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();

View File

@ -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");
}

View File

@ -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<int>(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()

View File

@ -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();
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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());

View File

@ -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);
}

View File

@ -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);

View File

@ -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());

View File

@ -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:"); }

View File

@ -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 {

View File

@ -58,7 +58,7 @@ private:
UASSERT_OBJ(vscp, nodep, "Scope not assigned");
if (AstVarScope* newvscp = reinterpret_cast<AstVarScope*>(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);

View File

@ -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

View File

@ -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); }

View File

@ -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

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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");
}
}

View File

@ -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);

View File

@ -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

View File

@ -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")));
}

View File

@ -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

View File

@ -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: ");

View File

@ -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

View File

@ -383,7 +383,7 @@ protected:
SplitVarStdVertex* vstdp = reinterpret_cast<SplitVarStdVertex*>(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);

View File

@ -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;

View File

@ -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<AstVar*>& 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);
}

View File

@ -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)) {

View File

@ -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<AstNode*>(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);
}

View File

@ -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);

View File

@ -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();

View File

@ -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());

View File

@ -168,7 +168,7 @@ private:
for (V3GraphEdge* edgep = vtxp->inBeginp(); edgep; edgep = edgep->inNextp()) {
TristateVertex* vvertexp = dynamic_cast<TristateVertex*>(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 <in> (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

View File

@ -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();
}
}

View File

@ -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<AstNode*>(
new AstAssignDly(fl, prep, new AstVarRef(fl, varp, false)))
: static_cast<AstNode*>(
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<AstNode*>(
new AstAssignDly(fl, prep, new AstVarRef(fl, varp, VAccess::READ)))
: static_cast<AstNode*>(
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 {

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -1932,7 +1932,7 @@ list_of_tf_variable_identifiers<nodep>: // ==IEEE: list_of_tf_variable_identifie
tf_variable_identifier<varp>: // IEEE: part of list_of_tf_variable_identifiers
id variable_dimensionListE sigAttrListE exprEqE
{ $$ = VARDONEA($<fl>1,*$1, $2, $3);
if ($4) $$->addNext(new AstAssign($4->fileline(), new AstVarRef($<fl>1, *$1, true), $4)); }
if ($4) $$->addNext(new AstAssign($4->fileline(), new AstVarRef($<fl>1, *$1, VAccess::WRITE), $4)); }
;
variable_declExpr<nodep>: // IEEE: part of variable_decl_assignment - rhs of expr
@ -2432,7 +2432,8 @@ loop_generate_construct<nodep>: // ==IEEE: loop_generate_construct
genvar_initialization<nodep>: // ==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<nodep>: // ==IEEE: genvar_iteration
@ -2542,7 +2543,7 @@ netSigList<varp>: // IEEE: list_of_port_identifiers
netSig<varp>: // IEEE: net_decl_assignment - one element from list_of_port_identifiers
netId sigAttrListE { $$ = VARDONEA($<fl>1,*$1, nullptr, $2); }
| netId sigAttrListE '=' expr { $$ = VARDONEA($<fl>1,*$1, nullptr, $2);
$$->addNext(new AstAssignW($3, new AstVarRef($<fl>1, *$1, true), $4)); }
$$->addNext(new AstAssignW($3, new AstVarRef($<fl>1, *$1, VAccess::WRITE), $4)); }
| netId variable_dimensionList sigAttrListE { $$ = VARDONEA($<fl>1,*$1, $2, $3); }
;
@ -3386,12 +3387,12 @@ for_initializationItem<nodep>: // IEEE: variable_assignment + for_variable_decl
data_type idAny/*new*/ '=' expr
{ VARRESET_NONLIST(VAR); VARDTYPE($1);
$$ = VARDONEA($<fl>2,*$2,nullptr,nullptr);
$$->addNext(new AstAssign($3, new AstVarRef($<fl>2, *$2, true), $4));}
$$->addNext(new AstAssign($3, new AstVarRef($<fl>2, *$2, VAccess::WRITE), $4)); }
// // IEEE-2012:
| yVAR data_type idAny/*new*/ '=' expr
{ VARRESET_NONLIST(VAR); VARDTYPE($2);
$$ = VARDONEA($<fl>3,*$3,nullptr,nullptr);
$$->addNext(new AstAssign($4, new AstVarRef($<fl>3, *$3, true), $5));}
$$->addNext(new AstAssign($4, new AstVarRef($<fl>3, *$3, VAccess::WRITE), $5)); }
// // IEEE: variable_assignment
// // UNSUP variable_lvalue below
| varRefBase '=' expr { $$ = new AstAssign($2, $1, $3); }
@ -4860,7 +4861,7 @@ idArrayedForeach<nodep>: // IEEE: id + select (under foreach expression)
// VarRef without any dots or vectorizaion
varRefBase<varrefp>:
id { $$ = new AstVarRef($<fl>1,*$1,false);}
id { $$ = new AstVarRef($<fl>1, *$1, VAccess::READ); }
;
// yaSTRING shouldn't be used directly, instead via an abstraction below