virtual void visit(AstSel* nodep, AstNUser*) { AstVarRef* varrefp = nodep->fromp()->castVarRef(); AstConst* constp = nodep->lsbp()->castConst(); if (varrefp && constp && !constp->num().isFourState()) { UndrivenVarEntry* entryp = getEntryp (varrefp->varp()); int lsb = constp->toUInt(); if (m_markBoth || varrefp->lvalue()) entryp->drivenBit(lsb, nodep->width()); if (m_markBoth || !varrefp->lvalue()) entryp->usedBit(lsb, nodep->width()); } else { // else other varrefs handled as unknown mess in AstVarRef nodep->iterateChildren(*this); } }
virtual void visit(AstSel* nodep, AstNUser*) { AstVarRef* varrefp = nodep->fromp()->castVarRef(); AstConst* constp = nodep->lsbp()->castConst(); if (varrefp && constp && !constp->num().isFourState()) { for (int usr=1; usr<(m_alwaysp?3:2); ++usr) { UndrivenVarEntry* entryp = getEntryp (varrefp->varp(), usr); int lsb = constp->toUInt(); if (m_markBoth || varrefp->lvalue()) { // Don't warn if already driven earlier as "a=0; if(a) a=1;" is fine. if (usr==2 && m_alwaysp && entryp->isUsedNotDrivenBit(lsb, nodep->width())) { UINFO(9," Select. Entryp="<<(void*)entryp<<endl); warnAlwCombOrder(varrefp); } entryp->drivenBit(lsb, nodep->width()); } if (m_markBoth || !varrefp->lvalue()) entryp->usedBit(lsb, nodep->width()); } } else { // else other varrefs handled as unknown mess in AstVarRef nodep->iterateChildren(*this); } }
virtual void visit(AstNodeAssign* nodep) { if (!m_cfuncp) return; // Left select WordSel or ArraySel AstNodeSel* lselp = VN_CAST(nodep->lhsp(), NodeSel); if (!lselp) { mergeEnd(); return; } // Not ever merged // Of a constant index AstConst* lbitp = VN_CAST(lselp->bitp(), Const); if (!lbitp) { mergeEnd(); return; } uint32_t index = lbitp->toUInt(); // Of variable AstNodeVarRef* lvarrefp = VN_CAST(lselp->fromp(), NodeVarRef); if (!lvarrefp) { mergeEnd(); return; } // RHS is a constant or a select AstConst* rconstp = VN_CAST(nodep->rhsp(), Const); AstNodeSel* rselp = VN_CAST(nodep->rhsp(), NodeSel); AstNodeVarRef* rvarrefp = NULL; if (rconstp) { // Ok } else { if (!rselp) { mergeEnd(); return; } AstConst* rbitp = VN_CAST(rselp->bitp(), Const); rvarrefp = VN_CAST(rselp->fromp(), NodeVarRef); if (!rbitp || rbitp->toUInt() != index || !rvarrefp || lvarrefp->varp() == rvarrefp->varp()) { mergeEnd(); return; } } if (m_mgSelLp) { // Old merge if (m_mgCfuncp == m_cfuncp && m_mgNextp == nodep && m_mgSelLp->same(lselp) && m_mgVarrefLp->same(lvarrefp) && (m_mgConstRp ? (rconstp && m_mgConstRp->same(rconstp)) : (rselp && m_mgSelRp->same(rselp) && m_mgVarrefRp->same(rvarrefp))) && (index == m_mgIndexLo-1 || index == m_mgIndexHi+1)) { // Sequentially next to last assign; continue merge if (index == m_mgIndexLo-1) m_mgIndexLo = index; else if (index == m_mgIndexHi+1) m_mgIndexHi = index; UINFO(9, "Continue merge i="<<index <<" "<<m_mgIndexHi<<":"<<m_mgIndexLo<<" "<<nodep<<endl); m_mgAssignps.push_back(nodep); m_mgNextp = nodep->nextp(); return; } else { // This assign doesn't merge with previous assign, // but should start a new merge mergeEnd(); } } // Merge start m_mgAssignps.push_back(nodep); m_mgCfuncp = m_cfuncp; m_mgNextp = nodep->nextp(); m_mgSelLp = lselp; m_mgSelRp = rselp; m_mgVarrefLp = lvarrefp; m_mgVarrefRp = rvarrefp; m_mgConstRp = rconstp; m_mgIndexLo = index; m_mgIndexHi = index; UINFO(9, "Start merge i="<<index<<" "<<nodep<<endl); }