// 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 AstNUser* visit(GateVarVertex *vvertexp, AstNUser*) { // Check that we haven't been here before if (vvertexp->varScp()->user2()) return NULL; vvertexp->varScp()->user2(true); AstNodeVarRef* dupVarRefp = (AstNodeVarRef*) vvertexp->iterateInEdges(*this, (AstNUser*) vvertexp); if (dupVarRefp && vvertexp->inSize1()) { V3GraphEdge* edgep = vvertexp->inBeginp(); GateLogicVertex* lvertexp = (GateLogicVertex*)edgep->fromp(); if (!vvertexp->dedupable()) vvertexp->varScp()->v3fatalSrc("GateLogicVertex* visit should have returned NULL if consumer var vertex is not dedupable."); GateOkVisitor okVisitor(lvertexp->nodep(), false, true); if (okVisitor.isSimple()) { AstVarScope* dupVarScopep = dupVarRefp->varScopep(); GateVarVertex* dupVvertexp = (GateVarVertex*) (dupVarScopep->user1p()); UINFO(4,"replacing " << vvertexp << " with " << dupVvertexp << endl); ++m_numDeduped; // Replace all of this varvertex's consumers with dupVarRefp for (V3GraphEdge* outedgep = vvertexp->outBeginp();outedgep;) { GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(outedgep->top()); AstNode* consumerp = consumeVertexp->nodep(); GateElimVisitor elimVisitor(consumerp,vvertexp->varScp(),dupVarRefp); outedgep = outedgep->relinkFromp(dupVvertexp); } // Propogate attributes dupVvertexp->propagateAttrClocksFrom(vvertexp); // Remove inputs links while (V3GraphEdge* inedgep = vvertexp->inBeginp()) { inedgep->unlinkDelete(); VL_DANGLING(inedgep); } // replaceAssigns() does the deleteTree on lvertexNodep in a later step AstNode* lvertexNodep = lvertexp->nodep(); lvertexNodep->unlinkFrBack(); vvertexp->varScp()->valuep(lvertexNodep); lvertexNodep = NULL; vvertexp->user(true); lvertexp->user(true); } } return NULL; }
// 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: "); } }