diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 79efa9f69..151c5a438 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -108,6 +108,7 @@ private: bool m_doGenerate; // Postpone width checking inside generate AstNodeModule* m_modp; // Current module AstNode* m_scopep; // Current scope + AstAttrOf* m_attrp; // Current attribute // METHODS static int debug() { @@ -1209,11 +1210,17 @@ private: nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL; } + virtual void visit(AstAttrOf* nodep, AstNUser*) { + AstAttrOf* oldAttr = m_attrp; + m_attrp = nodep; + nodep->iterateChildren(*this); + m_attrp = oldAttr; + } virtual void visit(AstVarRef* nodep, AstNUser*) { nodep->iterateChildren(*this); if (!nodep->varp()) nodep->v3fatalSrc("Not linked"); bool did=false; - if (m_doV && nodep->varp()->hasSimpleInit() && !nodep->backp()->castAttrOf()) { + if (m_doV && nodep->varp()->hasSimpleInit() && !m_attrp) { //if (debug()) nodep->varp()->valuep()->dumpTree(cout," visitvaref: "); nodep->varp()->valuep()->iterateAndNext(*this); if (operandConst(nodep->varp()->valuep()) @@ -2006,6 +2013,7 @@ public: m_wremove = true; // Overridden in visitors m_modp = NULL; m_scopep = NULL; + m_attrp = NULL; // switch (pmode) { case PROC_PARAMS: m_doV = true; m_doNConst = true; m_params = true; m_required = true; break; diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index c3f991630..8fe1b2acc 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -51,6 +51,7 @@ private: AstVarScope* m_forVscp; // Iterator variable scope (NULL for generate pass) AstConst* m_varValuep; // Current value of loop AstNode* m_ignoreIncp; // Increment node to ignore + AstAttrOf* m_attrp; // Current attribute bool m_varModeCheck; // Just checking RHS assignments bool m_varModeReplace; // Replacing varrefs bool m_varAssignHit; // Assign var hit @@ -383,6 +384,12 @@ private: nodep->v3error("V3Begin should have removed standard FORs"); } } + virtual void visit(AstAttrOf* nodep, AstNUser*) { + AstAttrOf* oldAttr = m_attrp; + m_attrp = nodep; + nodep->iterateChildren(*this); + m_attrp = oldAttr; + } virtual void visit(AstVarRef* nodep, AstNUser*) { if (m_varModeCheck @@ -396,7 +403,7 @@ private: && nodep->varp() == m_forVarp && nodep->varScopep() == m_forVscp && !nodep->lvalue() - && !nodep->backp()->castAttrOf()) { // Most likely under a select + && !m_attrp) { // Most likely under a select AstNode* newconstp = m_varValuep->cloneTree(false); nodep->replaceWith(newconstp); pushDeletep(nodep); @@ -423,6 +430,7 @@ public: m_varModeReplace = false; m_generate = generate; m_beginName = beginName; + m_attrp = NULL; // nodep->accept(*this); } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 9dedf9453..224bf2e5b 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -521,20 +521,24 @@ private: virtual void visit(AstSelBit* nodep, AstNUser* vup) { // Just a quick check as after V3Param these nodes instead are AstSel's + nodep->attrp()->iterateAndNext(*this,WidthVP(0,0,FINAL).p()); AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; } nodep->v3fatalSrc("AstSelBit should disappear after widthSel"); } virtual void visit(AstSelExtract* nodep, AstNUser* vup) { // Just a quick check as after V3Param these nodes instead are AstSel's + nodep->attrp()->iterateAndNext(*this,WidthVP(0,0,FINAL).p()); AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; } nodep->v3fatalSrc("AstSelExtract should disappear after widthSel"); } virtual void visit(AstSelPlus* nodep, AstNUser* vup) { + nodep->attrp()->iterateAndNext(*this,WidthVP(0,0,FINAL).p()); AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; } nodep->v3fatalSrc("AstSelPlus should disappear after widthSel"); } virtual void visit(AstSelMinus* nodep, AstNUser* vup) { + nodep->attrp()->iterateAndNext(*this,WidthVP(0,0,FINAL).p()); AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp!=nodep) { nodep=NULL; selp->iterate(*this,vup); return; } nodep->v3fatalSrc("AstSelMinus should disappear after widthSel"); } @@ -631,8 +635,11 @@ private: if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression"); V3Number num (nodep->fileline(), 32, nodep->fromp()->width()); nodep->replaceWith(new AstConst(nodep->fileline(), num)); nodep->deleteTree(); nodep=NULL; + } else if (nodep->attrType()==AstAttrType::VAR_BASE) { + // Soon to be handled in V3LinkWidth SEL generation } else { // Everything else resolved earlier nodep->dtypeSetLogicSized(32,1,AstNumeric::UNSIGNED); // Approximation, unsized 32 + UINFO(1,"Missing ATTR type case node: "<v3fatalSrc("Missing ATTR type case"); } }