Esempio n. 1
0
    bool compareDfaOrigins(const DfaStates& nfasWithInput, DfaVertex* dfa2p) {
	// Return true if the NFA nodes both DFAs came from are the same list
	// Assume there are no duplicates in either input list or NFAs under dfa2
	nextStep();
	// Mark all input vertexes
	int num1s = 0;
	for (DfaStates::const_iterator nfaIt=nfasWithInput.begin(); nfaIt!=nfasWithInput.end(); ++nfaIt) {
	    DfaVertex* nfaStatep = *nfaIt;
	    nfaStatep->user(m_step);
	    num1s++;
	}
	if (!num1s) v3fatalSrc("DFA node construction that contains no NFA states");

	// Check comparison; must all be marked
	// (Check all in dfa2p were in dfa1p)
	int num2s = 0;
	for (V3GraphEdge* dfaEdgep = dfa2p->outBeginp(); dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) {
	    if (nfaState(dfaEdgep->top())) {
		if (dfaEdgep->top()->user() != m_step) return false;
		num2s++;
	    }
	}
	// If we saw all of the nodes, then they have the same number of hits
	// (Else something in dfa1p that wasn't in dfa2p)
	if (num1s != num2s) return false;
	// Match
	return true;
    }
Esempio n. 2
0
uint32_t V3GraphVertex::outHash() const {
    uint32_t hash=0;
    for (V3GraphEdge* edgep = this->outBeginp(); edgep; edgep=edgep->outNextp()) {
	hash += cvtToHash(edgep->top());
    }
    return hash;
}
Esempio n. 3
0
    void optimize_orphans() {
	// Remove states that don't come from start
	// Presumably the previous optimization orphaned them.

	// Vertex::m_user begin: 1 indicates on the work list, 2 processed
	// (Otherwise we might have nodes on the list twice, and reference after deleting them.)
	m_graphp->userClearVertices();

	DfaVertex* startp = graphp()->findStart();
	stack<V3GraphVertex*> workps;  workps.push(startp);

	// Mark all nodes connected to start
	while (!workps.empty()) {
	    V3GraphVertex* vertexp = workps.top(); workps.pop();
	    vertexp->user(2);  // Processed
	    // Add nodes from here to the work list
	    for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
		V3GraphVertex* tovertexp = edgep->top();
		if (!tovertexp->user()) {
		    workps.push(tovertexp);
		    tovertexp->user(1);
		}
	    }
	}

	// Delete all nodes not connected
	for (V3GraphVertex* nextp,*vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=nextp) {
	    nextp = vertexp->verticesNextp();
	    if (!vertexp->user()) {
		vertexp->unlinkDelete(m_graphp); vertexp=NULL;
	    }
	}
    }
Esempio n. 4
0
    // Returns only the result from the LAST vertex iterated over
    AstNUser* iterateInEdges(GateGraphBaseVisitor& v, AstNUser* vup=NULL) {
	AstNUser* retp = NULL;
	for (V3GraphEdge* edgep = inBeginp(); edgep; edgep = edgep->inNextp()) {
	    retp = dynamic_cast<GateEitherVertex*>(edgep->fromp())->accept(v, vup);
	}
	return retp;
    }
Esempio n. 5
0
    bool isDead(DfaVertex* vertexp) {
	// A state is dead if not accepting, and goes nowhere
	if (vertexp->accepting() || vertexp->start()) return false;
	for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
	    if (edgep->top() != vertexp) return false;
	}
	return true;
    }
Esempio n. 6
0
    // Populate *outp with a minimal perfect matching of *this.
    // *outp must be initially empty.
    void perfectMatching(const std::vector<T_Key>& oddKeys,
                         TspGraphTmpl* outp) {
        UASSERT(outp->empty(), "Output graph must start empty");

        std::list<Vertex*> odds = keysToVertexList(oddKeys);
        vl_unordered_set<Vertex*> unmatchedOdds;
        typedef typename std::list<Vertex*>::iterator VertexListIt;
        for (VertexListIt it = odds.begin(); it != odds.end(); ++it) {
            outp->addVertex((*it)->key());
            unmatchedOdds.insert(*it);
        }

        UASSERT(odds.size() % 2 == 0, "number of odd-order nodes should be even");

        // TODO: The true Chrisofides algorithm calls for minimum-weight
        // perfect matching. Instead, we have a simple greedy algorithm
        // which might get close to the minimum, maybe, with luck?
        //
        // TODO: Revisit this. It's possible to compute the true minimum in
        // N*N*log(N) time using variants of the Blossom algorithm.
        // Implementing Blossom looks hard, maybe we can use an existing
        // open source implementation -- for example the "LEMON" library
        // which has a TSP solver.

        // -----

        // Reuse the comparator from Prim's routine. The logic is the same
        // here.  Note that the two V3GraphEdge's representing a single
        // bidir edge will collide in the pendingEdges set here, but this
        // is OK, we'll ignore the direction on the edge anyway.
        EdgeCmp cmp;
        typedef std::set<V3GraphEdge*, EdgeCmp&> PendingEdgeSet;
        PendingEdgeSet pendingEdges(cmp);

        for (VertexListIt it = odds.begin(); it != odds.end(); ++it) {
            for (V3GraphEdge* edgep = (*it)->outBeginp();
                 edgep; edgep = edgep->outNextp()) {
                pendingEdges.insert(edgep);
            }
        }

        // Iterate over all edges, in order from low to high cost.
        // For any edge whose ends are both odd-order vertices which
        // haven't been matched yet, match them.
        for (typename PendingEdgeSet::iterator it = pendingEdges.begin();
             it != pendingEdges.end(); ++it) {
            Vertex* fromp = castVertexp((*it)->fromp());
            Vertex* top = castVertexp((*it)->top());
            if ((unmatchedOdds.find(fromp) != unmatchedOdds.end())
                && (unmatchedOdds.find(top) != unmatchedOdds.end())) {
                outp->addEdge(fromp->key(), top->key(), (*it)->weight());
                unmatchedOdds.erase(fromp);
                unmatchedOdds.erase(top);
            }
        }
        UASSERT(unmatchedOdds.empty(), "Algorithm should have processed all vertices");
    }
Esempio n. 7
0
    void nafgMarkRecurse(V3GraphVertex* vertexp, uint32_t generation) {
	// Backwards mark user() on the path we recurse
	//UINFO(9," nafgMark: v "<<(void*)(vertexp)<<" "<<vertexp->name()<<endl);
	for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
	    //UINFO(9," nafgMark: "<<(void*)(edgep)<<" "<<edgep->name()<<endl);
	    edgep->user(generation);
	    nafgMarkRecurse(edgep->fromp(), generation);
	}
    }
Esempio n. 8
0
void V3Graph::userClearEdges() {
    // Clear user() in all of tree
    for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
	for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
	    edgep->user(0);
	    edgep->userp(NULL);	 // Its a union, but might be different size than user()
	}
    }
}
Esempio n. 9
0
void GateVisitor::consumedMarkRecurse(GateEitherVertex* vertexp) {
    if (vertexp->user()) return;	// Already marked
    vertexp->user(true);
    if (!vertexp->consumed()) vertexp->setConsumed("propagated");
    // Walk sources and mark them too
    for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
	GateEitherVertex* eFromVertexp = (GateEitherVertex*)edgep->fromp();
	consumedMarkRecurse(eFromVertexp);
    }
}
Esempio n. 10
0
uint32_t V3GraphVertex::inHash() const {
    // We want the same hash ignoring the order of edges.
    // So we need an associative operator, like XOR.
    // However with XOR multiple edges to the same source will cancel out,
    // so we use ADD.  (Generally call this only after removing duplicates though)
    uint32_t hash=0;
    for (V3GraphEdge* edgep = this->inBeginp(); edgep; edgep=edgep->inNextp()) {
	hash += cvtToHash(edgep->fromp());
    }
    return hash;
}
Esempio n. 11
0
 void dumpGraph(std::ostream& os, const string& nameComment) const {
     // UINFO(0) as controlled by caller
     os<<"At "<<nameComment<<", dumping graph. Keys:\n";
     for (V3GraphVertex* vxp = verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
         Vertex* tspvp = castVertexp(vxp);
         os<<" "<<tspvp->key()<<endl;
         for (V3GraphEdge* edgep = tspvp->outBeginp(); edgep; edgep = edgep->outNextp()) {
             Vertex* neighborp = castVertexp(edgep->top());
             os<<"   has edge "<<edgep->user()<<" to "<<neighborp->key()<<endl;
         }
     }
 }
Esempio n. 12
0
void V3GraphVertex::rerouteEdges(V3Graph* graphp) {
    // Make new edges for each from/to pair
    for (V3GraphEdge* iedgep = inBeginp(); iedgep; iedgep=iedgep->inNextp()) {
	for (V3GraphEdge* oedgep = outBeginp(); oedgep; oedgep=oedgep->outNextp()) {
	    new V3GraphEdge (graphp, iedgep->fromp(), oedgep->top(),
			     min(iedgep->weight(),oedgep->weight()),
			     iedgep->cutable() && oedgep->cutable());
	}
    }
    // Remove old edges
    unlinkEdges(graphp);
}
Esempio n. 13
0
 std::vector<T_Key> getOddDegreeKeys() const {
     std::vector<T_Key> result;
     for (V3GraphVertex* vxp = verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
         Vertex* tspvp = castVertexp(vxp);
         vluint32_t degree = 0;
         for (V3GraphEdge* edgep = vxp->outBeginp(); edgep; edgep = edgep->outNextp()) {
             degree++;
         }
         if (degree & 1) {
             result.push_back(tspvp->key());
         }
     }
     return result;
 }
Esempio n. 14
0
void V3Graph::dump(ostream& os) {
    // This generates a file used by graphviz, http://www.graphviz.org
    os<<" Graph:\n";
    // Print vertices
    for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
	os<<"\tNode: "<<vertexp->name();
	if (vertexp->color()) os<<"  color="<<vertexp->color();
	os<<endl;
	// Print edges
	for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep=edgep->inNextp()) {
	    dumpEdge (os, vertexp, edgep);
	}
	for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
	    dumpEdge (os, vertexp, edgep);
	}
    }
}
Esempio n. 15
0
    AstNode* nafgCreateRecurse(V3GraphVertex* vertexp, uint32_t generation) {
	// Forewards follow user() marked previously and build tree
	AstNode* nodep = NULL;
	// OR across all edges found at this level
	//UINFO(9," nafgEnter: v "<<(void*)(vertexp)<<" "<<vertexp->name()<<endl);
	for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
	    if (edgep->user() == generation) {
		GaterEdge* cedgep = static_cast<GaterEdge*>(edgep);
		AstNode* eqnp = NULL;
		//UINFO(9," nafgFollow: "<<(void*)(edgep)<<" "<<edgep->name()<<endl);
		if (dynamic_cast<GaterHeadVertex*>(edgep->fromp())) {
		    // Just OR in all lower terms
		    eqnp = nafgCreateRecurse(edgep->top(), generation);
		} else if (GaterIfVertex* cVxp = dynamic_cast<GaterIfVertex*>(edgep->fromp())) {
		    // Edges from IFs represent a real IF branch in the equation tree
		    //UINFO(9,"  ifver "<<(void*)(edgep)<<" cc"<<edgep->dotColor()<<endl);
		    eqnp = cVxp->nodep()->condp()->cloneTree(true);
		    if (eqnp && cedgep->ifelseFalse()) {
			eqnp = new AstNot(eqnp->fileline(),eqnp);
		    }
		    // We need to AND this term onto whatever was found below it
		    AstNode* belowp = nafgCreateRecurse(edgep->top(), generation);
		    if (belowp) eqnp = new AstAnd(eqnp->fileline(),eqnp,belowp);
		}
		// Top level we could choose to make multiple gaters, or ORs under the gater
		// Right now we'll put OR lower down and let other optimizations deal
		if (nodep) nodep = new AstOr(eqnp->fileline(),nodep,eqnp);
		else nodep = eqnp;
		//if (debug()>=9) nodep->dumpTree(cout,"      followExpr: ");
	    }
	}
	//UINFO(9," nafgExit:  "<<(void*)(vertexp)<<" "<<vertexp->name()<<endl);
	return nodep;
    }
Esempio n. 16
0
 void pruneDepsOnInputs() {
     for (V3GraphVertex* vertexp = m_graph.verticesBeginp();
          vertexp; vertexp=vertexp->verticesNextp()) {
         if (!vertexp->outBeginp()
             && dynamic_cast<SplitVarStdVertex*>(vertexp)) {
             if (debug() >= 9) {
                 SplitVarStdVertex* stdp = (SplitVarStdVertex*)(vertexp);
                 UINFO(0, "Will prune deps on var "<<stdp->nodep()<<endl);
                 stdp->nodep()->dumpTree(cout, "- ");
             }
             for (V3GraphEdge* edgep = vertexp->inBeginp();
                  edgep; edgep=edgep->inNextp()) {
                 SplitEdge* oedgep = dynamic_cast<SplitEdge*>(edgep);
                 oedgep->setIgnoreThisStep();
             }
         }
     }
 }
Esempio n. 17
0
    uint32_t hashDfaOrigins(DfaVertex* dfaStatep) {
	// Find the NFA states this dfa came from,
	// Record a checksum, so we can search for it later by the list of nfa nodes.
	// The order of the nodes is not deterministic; the hash thus must not depend on order of edges
	uint32_t hash = 0;
	// Foreach NFA state (this DFA state was formed from)
	if (debug()) nextStep();
	for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) {
	    if (nfaState(dfaEdgep->top())) {
		DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top());
		hash ^= hashVertex(nfaStatep);
		if (debug()) {
		    if (nfaStatep->user()==m_step) v3fatalSrc("DFA state points to duplicate NFA state.");
		    nfaStatep->user(m_step);
		}
	    }
	}
	return hash;
    }
Esempio n. 18
0
    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;
    }
Esempio n. 19
0
void V3Graph::clear() {
    // Empty it of all points, as if making a new object
    // Delete the old edges
    for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
	for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; /*BELOW*/) {
	    V3GraphEdge* nextp = edgep->outNextp();
	    delete edgep;
	    edgep = nextp;
	}
	vertexp->outUnlink();
    }
    // Delete the old vertices
    for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; /*BELOW*/) {
	V3GraphVertex* nextp = vertexp->verticesNextp();
	delete vertexp;
	vertexp = nextp;
    }
    verticesUnlink();
}
Esempio n. 20
0
int GaterVertex::sortCmp(const V3GraphVertex* rhsp) const {
    const GaterVertex* crhsp = static_cast<const GaterVertex*>(rhsp);
    // We really only care about ordering Var's together, but...
    // First put same type together
    if (typeNum() < crhsp->typeNum()) return -1;
    if (typeNum() > crhsp->typeNum()) return 1;
    // If variable, group by same input fanin
    // (know they're the same type based on above compare)
    if (dynamic_cast<const GaterVarVertex*>(this)) {
	// We've already sorted by edges, so just see if same tree
	// If this gets too slow, we could compute a hash up front
	V3GraphEdge* lEdgep = this->inBeginp();
	V3GraphEdge* rEdgep = rhsp->inBeginp();
	while (lEdgep && rEdgep) {
	    const GaterEdge* clEdgep = static_cast<const GaterEdge*>(lEdgep);
	    const GaterEdge* crEdgep = static_cast<const GaterEdge*>(rEdgep);
	    if (lEdgep->fromp()->rank() < rEdgep->fromp()->rank()) return -1;
	    if (lEdgep->fromp()->rank() > rEdgep->fromp()->rank()) return 1;
	    if (clEdgep->ifelse() < crEdgep->ifelse()) return -1;
	    if (clEdgep->ifelse() > crEdgep->ifelse()) return 1;
	    lEdgep = lEdgep->inNextp();
	    rEdgep = rEdgep->inNextp();
	}
	if (!lEdgep && !rEdgep) return 0;
	return lEdgep ? -1 : 1;
    }
    // Finally by rank of this vertex
    if (rank() < rhsp->rank()) return -1;
    if (rank() > rhsp->rank()) return 1;
    return 0;
}
Esempio n. 21
0
    void optimize_no_outbound() {
	// Non-accepting states with no outbound transitions may be
	// deleted.  Then, any arcs feeding those states, and perhaps those
	// states...

	// Vertex::m_user begin: 1 indicates on the work list
	// (Otherwise we might have nodes on the list twice, and reference after deleting them.)
	m_graphp->userClearVertices();

	// Find all dead vertexes
	stack<DfaVertex*> workps;
	for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
	    if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
		workps.push(vvertexp);
		vertexp->user(1);
	    } else {
		// If ever remove this, need dyn cast below
		v3fatalSrc("Non DfaVertex in dfa graph");
	    }
	}

	// While deadness... Delete and find new dead nodes.
	while (!workps.empty()) {
	    DfaVertex* vertexp = workps.top(); workps.pop();
	    vertexp->user(0);
	    if (isDead(vertexp)) {
		// Add nodes that go here to the work list
		for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep=edgep->inNextp()) {
		    DfaVertex* fromvertexp = static_cast<DfaVertex*>(edgep->fromp());
		    if (fromvertexp != vertexp
			&& !fromvertexp->user()) {
			workps.push(static_cast<DfaVertex*>(fromvertexp));
			fromvertexp->user(1);
		    }
		}
		// Transitions to this state removed by the unlink function
		vertexp->unlinkDelete(m_graphp); vertexp=NULL;
	    }
	}
    }
Esempio n. 22
0
bool GateVisitor::elimLogicOkOutputs(GateLogicVertex* consumeVertexp, const GateOkVisitor& okVisitor) {
    // Return true if can optimize
    // Return false if the consuming logic has an output signal that the replacement logic has as an input
    typedef set<AstVarScope*> VarScopeSet;
    // Use map to find duplicates between two lists
    VarScopeSet varscopes;
    // Replacement logic usually has shorter input list, so faster to build list based on it
    const GateVarRefList& rhsVarRefs = okVisitor.rhsVarRefs();
    for (GateVarRefList::const_iterator it = rhsVarRefs.begin();
	 it != rhsVarRefs.end(); ++it) {
	AstVarScope* vscp = (*it)->varScopep();
	if (varscopes.find(vscp) == varscopes.end()) varscopes.insert(vscp);
    }
    for (V3GraphEdge* edgep = consumeVertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
	GateVarVertex* consVVertexp = dynamic_cast<GateVarVertex*>(edgep->top());
	AstVarScope* vscp = consVVertexp->varScp();
	if (varscopes.find(vscp) != varscopes.end()) {
	    UINFO(9,"    Block-unopt, insertion generates input vscp "<<vscp<<endl);
	    return false;
	}
    }
    return true;
}
Esempio n. 23
0
void V3GraphVertex::unlinkEdges(V3Graph* graphp) {
    for (V3GraphEdge* edgep = outBeginp(); edgep; /*BELOW*/) {
	V3GraphEdge* nextp = edgep->outNextp();
	edgep->unlinkDelete();
	edgep = nextp;
    }
    for (V3GraphEdge* edgep = inBeginp(); edgep; /*BELOW*/) {
	V3GraphEdge* nextp = edgep->inNextp();
	edgep->unlinkDelete();
	edgep = nextp;
    }
}
Esempio n. 24
0
    void findNfasWithInput(DfaVertex* dfaStatep, DfaInput input,
			   DfaStates& nfasWithInput) {
	// Return all NFA states, with the given input transition from
	// the nfa states a given dfa state was constructed from.
	nextStep();
	nfasWithInput.clear();	// NFAs with given input

	// Foreach NFA state (this DFA state was formed from)
	for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) {
	    if (nfaState(dfaEdgep->top())) {
		DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top());
		// Foreach input transition (on this nfaStatep)
		for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
		    DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
		    if (cNfaEdgep->input() == input) {
			DfaVertex* nextStatep = static_cast<DfaVertex*>(cNfaEdgep->top());
			if (unseenNfaThisStep(nextStatep)) {  // Not processed?
			    nfasWithInput.push_back(nextStatep);
			    nextStatep->user(m_step);
			    UINFO(9,"      Reachable "<<nextStatep<<endl);
			}
		    }
		}
	    }
	}

	// Expand the nfasWithInput list to include epsilon states reachable by those on nfasWithInput
	for (DfaStates::iterator nfaIt=nfasWithInput.begin(); nfaIt!=nfasWithInput.end(); ++nfaIt) {
	    DfaVertex* nfaStatep = *nfaIt;
	    // Foreach epsilon-reachable (on this nfaStatep)
	    for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
		DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
		if (cNfaEdgep->epsilon()) {
		    DfaVertex* nextStatep = static_cast<DfaVertex*>(cNfaEdgep->top());
		    if (unseenNfaThisStep(nextStatep)) {  // Not processed?
			nfasWithInput.push_back(nextStatep);
			nextStatep->user(m_step);
			UINFO(9,"      Epsilon Reachable "<<nextStatep<<endl);
		    }
		}
	    }
	}
    }
Esempio n. 25
0
    void simplifyIfElseRecurse(V3GraphVertex* vertexp) {
	// From bottom-up, propagate duplicate IF/ELSE branches to grandparent
	for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
	    simplifyIfElseRecurse(edgep->top());
	}
	//UINFO(9,"IERecurse "<<vertexp<<endl);
	if (dynamic_cast<GaterIfVertex*>(vertexp)) {
	    // Clear indications
	    for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
		edgep->top()->user(VU_NONE);
	    }
	    // Mark nodes on to/from side
	    for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
		V3GraphVertex* toVxp = edgep->top();
		GaterEdge* cedgep = static_cast<GaterEdge*>(edgep);
		// We may mark this twice in one pass - if so it's duplicated; no worries
		if (cedgep->ifelseTrue()) toVxp->user(toVxp->user() | VU_IF);
		if (cedgep->ifelseFalse()) toVxp->user(toVxp->user() | VU_ELSE);
		//UINFO(9,"  mark "<<edgep<<" "<<toVxp<<endl);
	    }
	    // Any with both IF & ELSE mark get removal mark, and new parent edge
	    for (V3GraphEdge* nextp,* edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
		nextp = edgep->outNextp();  // We may edit the list
		V3GraphVertex* toVxp = edgep->top();
		//UINFO(9," to "<<toVxp->user()<<" "<<toVxp<<endl);
		if ((toVxp->user() & VU_IF) && (toVxp->user() & VU_ELSE)) {
		    edgep->unlinkDelete(); edgep = NULL;
		    if (!(toVxp->user() & VU_MADE)) {   // Make an edge only once
			toVxp->user(toVxp->user() | VU_MADE);
			GaterEdge* inedgep = static_cast<GaterEdge*>(vertexp->inBeginp());
			V3GraphVertex* grandparent = inedgep->fromp();
			new GaterEdge(&m_graph, grandparent, toVxp, inedgep->ifelse());
		    }
		}
	    }
	}
    }
Esempio n. 26
0
 void combineGraph(const TspGraphTmpl& g) {
     vl_unordered_set<vluint32_t> edges_done;
     for (V3GraphVertex* vxp = g.verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
         Vertex* fromp = castVertexp(vxp);
         for (V3GraphEdge* edgep = fromp->outBeginp(); edgep; edgep = edgep->outNextp()) {
             Vertex* top = castVertexp(edgep->top());
             if (edges_done.find(edgep->user()) == edges_done.end()) {
                 addEdge(fromp->key(), top->key(), edgep->weight());
                 edges_done.insert(edgep->user());
             }
         }
     }
 }
Esempio n. 27
0
    void simplifyGrandRecurse(V3GraphVertex* vertexp, uint32_t depth) {
	// From top-down delete any vars that grandparents source
	// IE    A -> B -> C -> VAR
	//         \----------^
	//UINFO(9,"GRecurse "<<depth<<" "<<vertexp<<endl);
	// Mark all variables to be swept
	for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
	    nextp = edgep->outNextp();  // We may edit the list
	    if (GaterVarVertex* toVxp = dynamic_cast<GaterVarVertex*>(edgep->top())) {
		if (toVxp->user() && toVxp->user() < depth) {
		    // A recursion "above" us marked it,
		    // Remove this edge, it's redundant with the upper edge
		    edgep->unlinkDelete(); edgep=NULL;
		} else {
		    GaterEdge* cedgep = static_cast<GaterEdge*>(edgep);
		    if (cedgep->ifelseBoth()) {
			toVxp->user(depth);
		    }
		}
	    }
	}
	// Recurse
	for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
	    simplifyGrandRecurse(edgep->top(), depth+1);
	}
	// Clean our marks
	for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
	    V3GraphVertex* toVxp = edgep->top();
	    if (toVxp->user() && toVxp->user() < depth) {  // A recursion "above" us marked it; don't mess with it
	    } else {
		toVxp->user(0);  // We marked it originally, so unmark now
	    }
	}
	// Delete any If nodes with no children
	// Last, as want bottom-up cleanup
	for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
	    nextp = edgep->outNextp();  // We may edit the list
	    if (GaterIfVertex* toVxp = dynamic_cast<GaterIfVertex*>(edgep->top())) {
		if (!toVxp->outBeginp()) {
		    if (!nextp || nextp->top() != edgep->top()) {  // Else next would disappear; we'll do it next loop
			toVxp->unlinkDelete(&m_graph); toVxp=NULL; edgep=NULL;
		    }
		}
	    }
	}
    }
Esempio n. 28
0
    void colorAlwaysGraph() {
        // Color the graph to indicate subsets, each of which
        // we can split into its own always block.
        m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue);

        // Some vars are primary inputs to the always block; prune
        // edges on those vars. Reasoning: if two statements both depend
        // on primary input A, it's ok to split these statements. Whereas
        // if they both depend on locally-generated variable B, the statements
        // must be kept together.
        SplitEdge::incrementStep();
        pruneDepsOnInputs();

        // For any 'if' node whose deps have all been pruned
        // (meaning, its conditional expression only looks at primary
        // inputs) prune all edges that depend on the 'if'.
        for (V3GraphVertex* vertexp = m_graph.verticesBeginp();
             vertexp; vertexp=vertexp->verticesNextp()) {
            SplitLogicVertex* logicp = dynamic_cast<SplitLogicVertex*>(vertexp);
            if (!logicp) continue;

            AstNodeIf* ifNodep = VN_CAST(logicp->nodep(), NodeIf);
            if (!ifNodep) continue;

            bool pruneMe = true;
            for (V3GraphEdge* edgep = logicp->outBeginp();
                 edgep; edgep = edgep->outNextp()) {
                SplitEdge* oedgep = dynamic_cast<SplitEdge*>(edgep);
                if (!oedgep->ignoreThisStep()) {
                    // This if conditional depends on something we can't
                    // prune -- a variable generated in the current block.
                    pruneMe = false;

                    // When we can't prune dependencies on the conditional,
                    // give a hint about why...
                    if (debug() >= 9) {
                        V3GraphVertex* vxp = oedgep->top();
                        SplitNodeVertex* nvxp = dynamic_cast<SplitNodeVertex*>(vxp);
                        UINFO(0, "Cannot prune if-node due to edge "<<oedgep<<
                              " pointing to node "<<nvxp->nodep()<<endl);
                        nvxp->nodep()->dumpTree(cout, "- ");
                    }

                    break;
                }
            }

            if (!pruneMe) continue;

            // This if can be split; prune dependencies on it.
            for (V3GraphEdge* edgep = logicp->inBeginp();
                 edgep; edgep = edgep->inNextp()) {
                SplitEdge* oedgep = dynamic_cast<SplitEdge*>(edgep);
                oedgep->setIgnoreThisStep();
            }
        }

        if (debug()>=9) {
            m_graph.dumpDotFilePrefixed("splitg_nodup", false);
        }

        // Weak coloring to determine what needs to remain grouped
        // in a single always. This follows all edges excluding:
        //  - those we pruned above
        //  - PostEdges, which are done later
        m_graph.weaklyConnected(&SplitEdge::followScoreboard);
    }
Esempio n. 29
0
    void cleanupBlockGraph(AstNode* nodep) {
	// Transform the graph into what we need
	UINFO(5, "ReorderBlock "<<nodep<<endl);
	m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue);

	if (debug()>=9) {
            m_graph.dumpDotFilePrefixed("reorderg_nodup", false);
	    //m_graph.dump(); cout<<endl;
	}

	// Mark all the logic for this step
	// Vertex::m_user begin: true indicates logic for this step
	m_graph.userClearVertices();
	for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) {
	    SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p();
	    vvertexp->user(true);
	}

	// If a var vertex has only inputs, it's a input-only node,
	// and can be ignored for coloring **this block only**
        SplitEdge::incrementStep();
        pruneDepsOnInputs();

        // For reordering this single block only, mark all logic
        // vertexes not involved with this step as unimportant
        for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
            if (SplitLogicVertex* vvertexp = dynamic_cast<SplitLogicVertex*>(vertexp)) {
                if (!vvertexp->user()) {
                    for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep=edgep->inNextp()) {
                        SplitEdge* oedgep = dynamic_cast<SplitEdge*>(edgep);
                        oedgep->setIgnoreThisStep();
                    }
                    for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
                        SplitEdge* oedgep = dynamic_cast<SplitEdge*>(edgep);
                        oedgep->setIgnoreThisStep();
                    }
                }
            }
        }

	// Weak coloring to determine what needs to remain in order
	// This follows all step-relevant edges excluding PostEdges, which are done later
	m_graph.weaklyConnected(&SplitEdge::followScoreboard);

	// Add hard orderings between all nodes of same color, in the order they appeared
        vl_unordered_map<uint32_t, SplitLogicVertex*> lastOfColor;
	for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) {
	    SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p();
            uint32_t color = vvertexp->color();
	    if (!color) nextp->v3fatalSrc("No node color assigned");
	    if (lastOfColor[color]) {
		new SplitStrictEdge(&m_graph, lastOfColor[color], vvertexp);
	    }
	    lastOfColor[color] = vvertexp;
	}

	// And a real ordering to get the statements into something reasonable
	// We don't care if there's cutable violations here...
	// Non-cutable violations should be impossible; as those edges are program-order
	if (debug()>=9) m_graph.dumpDotFilePrefixed((string)"splitg_preo", false);
	m_graph.acyclic(&SplitEdge::followCyclic);
	m_graph.rank(&SplitEdge::followCyclic);  // Or order(), but that's more expensive
	if (debug()>=9) m_graph.dumpDotFilePrefixed((string)"splitg_opt", false);
    }
Esempio n. 30
0
    void main() {
	UINFO(5,"Dfa to Nfa conversion...\n");
	// Vertex::color() begin: 1 indicates vertex on DFA graph, 0=NFA graph
	m_graphp->clearColors();
	// Vertex::m_user begin: # indicates processed this m_step number
	m_graphp->userClearVertices();

	if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_nfa");

	// Find NFA start
	DfaVertex* nfaStartp = graphp()->findStart();

	// Create new DFA State (start state) from the NFA states
	DfaVertex* dfaStartp = newDfaVertex(nfaStartp);

	DfaStates dfaUnprocps;		// Unprocessed DFA nodes
	dfaUnprocps.push_back(dfaStartp);

	UINFO(5,"Starting state conversion...\n");
	// Form DFA starting state from epsilon closure of NFA start
	nextStep();
	DfaStates workps; workps.push_back(nfaStartp);

	while (!workps.empty()) {  // While work
	    DfaVertex* nfaStatep = workps.back(); workps.pop_back();
	    //UINFO(9," Processing "<<nfaStatep<<endl);
	    nfaStatep->user(m_step);	// Mark as processed
	    // Add a edge so we can find NFAs from a given DFA.
	    // The NFA will never see this edge, because we only look at TO edges.
	    new DfaEdge(graphp(), dfaStartp, nfaStatep, DfaEdge::NA());
	    // Find epsilon closure of this nfa node, and destinations to work list
	    for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
		DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
		DfaVertex* nfaStatep = static_cast<DfaVertex*>(nfaEdgep->top());
		//UINFO(9,"   Consider "<<nfaEdgep->top()<<" EP "<<cNfaEdgep->epsilon()<<endl);
		if (cNfaEdgep->epsilon()
		    && unseenNfaThisStep(nfaStatep)) {  // Not processed?
		    workps.push_back(nfaStatep);
		}
	    }
	}
	if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_start");
	insertDfaOrigins(dfaStartp);

	int i=0;
	UINFO(5,"Main state conversion...\n");
	while (!dfaUnprocps.empty()) {
	    DfaVertex* dfaStatep = dfaUnprocps.back(); dfaUnprocps.pop_back();
	    UINFO(9,"  On dfaState "<<dfaStatep<<endl);

	    // From this dfaState, what corresponding nfaStates have what inputs?
	    set<DfaInput> inputs;
	    // Foreach NFA state (this DFA state was formed from)
	    for (V3GraphEdge* dfaEdgep = dfaStatep->outBeginp(); dfaEdgep; dfaEdgep=dfaEdgep->outNextp()) {
		if (nfaState(dfaEdgep->top())) {
		    DfaVertex* nfaStatep = static_cast<DfaVertex*>(dfaEdgep->top());
		    // Foreach input on this nfaStatep
		    for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
			DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
			if (!cNfaEdgep->epsilon()) {
			    if (inputs.find(cNfaEdgep->input()) == inputs.end()) {
				inputs.insert(cNfaEdgep->input());
				UINFO(9,"    Input to "<<dfaStatep<<" is "<<(void*)(cNfaEdgep->input())<<" via "<<nfaStatep<<endl);
			    }
			}
		    }
		}
	    }

	    // Foreach input state (NFA inputs of this DFA state)
	    for (set<DfaInput>::const_iterator inIt=inputs.begin(); inIt!=inputs.end(); ++inIt) {
		DfaInput input = *inIt;
		UINFO(9,"    ==="<<++i<<"=======================\n");
		UINFO(9,"    On input "<<(void*)(input)<<endl);

		// Find all states reachable for given input
		DfaStates nfasWithInput;
		findNfasWithInput(dfaStatep, input, nfasWithInput/*ref*/);

		// nfasWithInput now maps to the DFA we want a transition to.
		// Does a DFA already exist with this, and only this subset of NFA's?
		DfaVertex* toDfaStatep = findDfaOrigins(nfasWithInput);
		if (!toDfaStatep) {
		    // Doesn't exist, make new dfa state corresponding to this one,
		    toDfaStatep = newDfaVertex();
		    dfaUnprocps.push_back(toDfaStatep);  // Add to process list
		    // Track what nfa's point to it.
		    for (DfaStates::const_iterator nfaIt=nfasWithInput.begin(); nfaIt!=nfasWithInput.end(); ++nfaIt) {
			UINFO(9,"          NewContainsNfa "<<*nfaIt<<endl);
			new DfaEdge (graphp(), toDfaStatep, *nfaIt, DfaEdge::NA());
			if ((*nfaIt)->accepting()) toDfaStatep->accepting(true);
		    }
		    insertDfaOrigins(toDfaStatep);
		}
		// Add input transition
		new DfaEdge (graphp(), dfaStatep, toDfaStatep, input);

		if (debug()>=6) m_graphp->dumpDotFilePrefixed("step");
	    }
	}

	// Remove old NFA states
	UINFO(5,"Removing NFA states...\n");
	if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_withnfa");
	for (V3GraphVertex* nextp,*vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=nextp) {
	    nextp = vertexp->verticesNextp();
	    if (nfaState(vertexp)) {
		vertexp->unlinkDelete(m_graphp); vertexp=NULL;
	    }
	}

	UINFO(5,"Done.\n");
	if (debug()>=6) m_graphp->dumpDotFilePrefixed("dfa_done");
    }