mirror of
https://github.com/verilator/verilator.git
synced 2025-05-02 13:36:55 +00:00
Internals: Create VAccess class. No functional change intended.
This commit is contained in:
parent
cc134b38ee
commit
1899a875a4
@ -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);
|
||||
}
|
||||
|
41
src/V3Ast.h
41
src/V3Ast.h
@ -123,6 +123,33 @@ inline std::ostream& operator<<(std::ostream& os, const VLifetime& rhs) {
|
||||
|
||||
//######################################################################
|
||||
|
||||
class VAccess {
|
||||
public:
|
||||
enum en : uint8_t { READ, WRITE };
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* const names[] = {"RD", "WR"};
|
||||
return names[m_e];
|
||||
}
|
||||
inline VAccess()
|
||||
: m_e{READ} {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline VAccess(en _e)
|
||||
: m_e{_e} {}
|
||||
explicit inline VAccess(int _e)
|
||||
: m_e(static_cast<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; }
|
||||
|
@ -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] <- ";
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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,17 +1132,21 @@ 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),
|
||||
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, true), sel2p),
|
||||
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, false)),
|
||||
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, false)),
|
||||
AstNodeAssign* asn2bp
|
||||
= VN_CAST(nodep->cloneType(
|
||||
lc2p, new AstVarRef(sel2p->fileline(), temp2p, VAccess::READ)),
|
||||
NodeAssign);
|
||||
asn1ap->dtypeFrom(temp1p);
|
||||
asn1bp->dtypeFrom(temp1p);
|
||||
@ -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()
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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,10 +285,10 @@ 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),
|
||||
AstAssign* setassignp = new AstAssign(
|
||||
nodep->fileline(), new AstVarRef(nodep->fileline(), setvscp, VAccess::WRITE),
|
||||
new AstConst(nodep->fileline(), AstConst::LogicTrue()));
|
||||
nodep->addNextHere(setassignp);
|
||||
}
|
||||
@ -332,8 +334,8 @@ 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),
|
||||
postLogicp = new AstIf(nodep->fileline(),
|
||||
new AstVarRef(nodep->fileline(), setvscp, VAccess::READ),
|
||||
nullptr, nullptr);
|
||||
UINFO(9, " Created " << postLogicp << endl);
|
||||
finalp->addBodysp(postLogicp);
|
||||
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -313,8 +313,8 @@ 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),
|
||||
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
|
||||
@ -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());
|
||||
|
@ -76,16 +76,16 @@ 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),
|
||||
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: ");
|
||||
@ -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:"); }
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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); }
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -226,8 +226,8 @@ 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->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: "
|
||||
@ -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),
|
||||
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);
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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")));
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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: ");
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
@ -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,8 +947,10 @@ 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)),
|
||||
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);
|
||||
@ -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(),
|
||||
AstPin* enpinp
|
||||
= new AstPin(nodep->fileline(), nodep->pinNum(),
|
||||
enModVarp->name(), // should be {var}"__en"
|
||||
new AstVarRef(nodep->fileline(), enVarp, true));
|
||||
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,8 +1261,8 @@ 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),
|
||||
AstNode* newp = new AstPull(
|
||||
nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, VAccess::WRITE),
|
||||
nodep->isPullup());
|
||||
UINFO(9, " newpul " << newp << endl);
|
||||
nodep->addNextHere(newp);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,13 +118,13 @@ 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,
|
||||
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, false)))
|
||||
new AstAssignDly(fl, prep, new AstVarRef(fl, varp, VAccess::READ)))
|
||||
: static_cast<AstNode*>(
|
||||
new AstAssign(fl, prep, new AstVarRef(fl, varp, false)))),
|
||||
new AstAssign(fl, prep, new AstVarRef(fl, varp, VAccess::READ)))),
|
||||
nullptr);
|
||||
newp->branchPred(VBranchPred::BP_LIKELY);
|
||||
if (debug() >= 9) newp->dumpTree(cout, " _new: ");
|
||||
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user