// VISITORS virtual void visit(AstNodeVarRef* nodep, AstNUser*) { nodep->iterateChildren(*this); // We only allow a LHS ref for the var being set, and a RHS ref for something else being read. if (nodep->varScopep()->varp()->isSc()) { clearSimple("SystemC sig"); // Don't want to eliminate the VL_ASSIGN_SI's } if (nodep->lvalue()) { if (m_lhsVarRef) clearSimple(">1 lhs varRefs"); m_lhsVarRef = nodep; } else { if (m_rhsVarRefs.size()>1) { AstNodeVarRef* lastRefp = m_rhsVarRefs.back(); if (0) { // Diable the multiple-input optimization clearSimple(">1 rhs varRefs"); } else { if (m_buffersOnly) clearSimple(">1 rhs varRefs"); if (!nodep->varScopep()->varp()->gateMultiInputOptimizable() // We didn't check multiInput on the first varref, so check it here || !lastRefp->varScopep()->varp()->gateMultiInputOptimizable()) { clearSimple("!gateMultiInputOptimizable"); } } } m_rhsVarRefs.push_back(nodep); } }
virtual void visit(AstNodeAssign* nodep, AstNUser*) { m_substTreep = nodep->rhsp(); if (!nodep->lhsp()->castNodeVarRef()) clearSimple("ASSIGN(non-VARREF)"); else nodep->iterateChildren(*this); // We don't push logic other then assignments/NOTs into SenItems // This avoids a mess in computing what exactly a POSEDGE is // V3Const cleans up any NOTs by flipping the edges for us if (m_buffersOnly && !(nodep->rhsp()->castVarRef() // Avoid making non-clocked logic into clocked, // as it slows down the verilator_sim_benchmark || (nodep->rhsp()->castNot() && nodep->rhsp()->castNot()->lhsp()->castVarRef() && nodep->rhsp()->castNot()->lhsp()->castVarRef()->varp()->isUsedClock()) )) { clearSimple("Not a buffer (goes to a clock)"); } }
//-------------------- // Default virtual void visit(AstNode* nodep, AstNUser*) { // *** Special iterator if (!m_isSimple) return; // Fastpath if (!(m_dedupe ? nodep->isGateDedupable() : nodep->isGateOptimizable()) || !nodep->isPure() || nodep->isBrancher()) { UINFO(5, "Non optimizable type: "<<nodep<<endl); clearSimple("Non optimizable type"); } else nodep->iterateChildren(*this); }
// CONSTUCTORS GateOkVisitor(AstNode* nodep, bool buffersOnly) { m_isSimple = true; m_substTreep = NULL; m_buffersOnly = buffersOnly; m_lhsVarRef = NULL; // Iterate nodep->accept(*this); // Check results if (!m_substTreep) { clearSimple("No assignment found\n"); } for (GateVarRefList::const_iterator it = rhsVarRefs().begin(); it != rhsVarRefs().end(); ++it) { if (m_lhsVarRef && m_lhsVarRef->varScopep() == (*it)->varScopep()) { clearSimple("Circular logic\n"); // Oh my, we'll get a UNOPTFLAT much later. } } if (debug()>=9 && !m_isSimple) { nodep->dumpTree(cout,"\tgate!Ok: "); } }