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
    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. 3
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. 4
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. 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
    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. 7
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. 8
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. 9
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. 10
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. 11
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. 12
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. 13
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. 14
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. 15
0
    // From *this, populate *mstp with the minimum spanning tree.
    // *mstp must be initially empty.
    void makeMinSpanningTree(TspGraphTmpl* mstp) {
        UASSERT(mstp->empty(), "Output graph must start empty");

        // Use Prim's algorithm to efficiently construct the MST.
        vl_unordered_set<Vertex*> visited_set;

        EdgeCmp cmp;
        typedef std::set<V3GraphEdge*, EdgeCmp&> PendingEdgeSet;
        // This is the set of pending edges from visited to unvisited
        // nodes.
        PendingEdgeSet pendingEdges(cmp);

        vluint32_t vertCount = 0;
        for (V3GraphVertex* vxp = verticesBeginp();
             vxp; vxp = vxp->verticesNextp()) {
            mstp->addVertex(castVertexp(vxp)->key());
            vertCount++;
        }

        // Choose an arbitrary start vertex and visit it;
        // all incident edges from this vertex go into a pending edge set.
        Vertex* start_vertexp = castVertexp(verticesBeginp());
        visited_set.insert(start_vertexp);
        for (V3GraphEdge* edgep = start_vertexp->outBeginp();
             edgep; edgep = edgep->outNextp()) {
            pendingEdges.insert(edgep);
        }

        // Repeatedly find the least costly edge in the pending set.
        // If it connects to an unvisited node, visit that node and update
        // the pending edge set. If it connects to an already visited node,
        // discard it and repeat again.
        unsigned edges_made = 0;
        while (!pendingEdges.empty()) {
            typename PendingEdgeSet::iterator firstIt = pendingEdges.begin();
            V3GraphEdge* bestEdgep = *firstIt;
            pendingEdges.erase(firstIt);

            // bestEdgep->fromp() should be already seen
            Vertex* from_vertexp = castVertexp(bestEdgep->fromp());
            UASSERT(visited_set.find(from_vertexp) != visited_set.end(), "Can't find vertex");

            // If the neighbor is not yet visited, visit it and add its edges
            // to the pending set.
            Vertex* neighborp = castVertexp(bestEdgep->top());
            if (visited_set.find(neighborp) == visited_set.end()) {
                int bestCost = bestEdgep->weight();
                UINFO(6, "bestCost = "<<bestCost
                      <<"  from "<<from_vertexp->key()
                      <<" to "<<neighborp->key()<<endl);

                // Create the edge in our output MST graph
                mstp->addEdge(from_vertexp->key(), neighborp->key(), bestCost);
                edges_made++;

                // Mark this vertex as visited
                visited_set.insert(neighborp);

                // Update the pending edges with new edges
                for (V3GraphEdge* edgep = neighborp->outBeginp();
                     edgep; edgep = edgep->outNextp()) {
                    pendingEdges.insert(edgep);
                }
            } else {
                UINFO(6, "Discarding edge to already-visited neighbor "
                      <<neighborp->key()<<endl);
            }
        }

        UASSERT(edges_made + 1 == vertCount, "Algorithm failed");
        UASSERT(visited_set.size() == vertCount, "Algorithm failed");
    }
Esempio n. 16
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");
    }
Esempio n. 17
0
    void findEulerTourRecurse(vl_unordered_set<unsigned>* markedEdgesp,
                              Vertex* startp,
                              std::vector<T_Key>* sortedOutp) {
        Vertex* cur_vertexp = startp;

        // Go on a random tour. Fun!
        std::vector<Vertex*> tour;
        do {
            UINFO(6, "Adding "<<cur_vertexp->key()<<" to tour.\n");
            tour.push_back(cur_vertexp);

            // Look for an arbitrary edge we've not yet marked
            for (V3GraphEdge* edgep = cur_vertexp->outBeginp();
                 edgep; edgep = edgep->outNextp()) {
                vluint32_t edgeId = edgep->user();
                if (markedEdgesp->end() == markedEdgesp->find(edgeId)) {
                    // This edge is not yet marked, so follow it.
                    markedEdgesp->insert(edgeId);
                    Vertex* neighborp = castVertexp(edgep->top());
                    UINFO(6, "following edge "<<edgeId
                          <<" from "<<cur_vertexp->key()
                          <<" to "<<neighborp->key()<<endl);
                    cur_vertexp = neighborp;
                    goto found;
                }
            }
            v3fatalSrc("No unmarked edges found in tour");
          found:
            ;
        } while (cur_vertexp != startp);
        UINFO(6, "stopped, got back to start of tour @ "<<cur_vertexp->key()<<endl);

        // Look for nodes on the tour that still have
        // un-marked edges. If we find one, recurse.
        for (typename std::vector<Vertex*>::iterator it = tour.begin();
             it != tour.end(); ++it) {
            Vertex* vxp = *it;
            bool recursed;
            do {
                recursed = false;
                // Look for an arbitrary edge at vxp we've not yet marked
                for (V3GraphEdge* edgep = vxp->outBeginp();
                     edgep; edgep = edgep->outNextp()) {
                    vluint32_t edgeId = edgep->user();
                    if (markedEdgesp->end() == markedEdgesp->find(edgeId)) {
                        UINFO(6, "Recursing.\n");
                        findEulerTourRecurse(markedEdgesp, vxp, sortedOutp);
                        recursed = true;
                        goto recursed;
                    }
                }
              recursed:
                ;
            } while (recursed);
            sortedOutp->push_back(vxp->key());
        }

        UINFO(6, "Tour was: ");
        for (typename std::vector<Vertex*>::iterator it = tour.begin();
             it != tour.end(); ++it) {
            Vertex* vxp = *it;
            UINFONL(6, " "<<vxp->key());
        }
        UINFONL(6, "\n");
    }
Esempio n. 18
0
void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) {
    // This generates a file used by graphviz, http://www.graphviz.org
    // "hardcoded" parameters:
    const auto_ptr<ofstream> logp (V3File::new_ofstream(filename));
    if (logp->fail()) v3fatalSrc("Can't write "<<filename);

    // Header
    *logp<<"digraph v3graph {\n";
    *logp<<"\tgraph\t[label=\""<<filename<<"\",\n";
    *logp<<"\t\t labelloc=t, labeljust=l,\n";
    *logp<<"\t\t //size="<<"\"7.5,10\","<<"\n";
    *logp<<"\t\t rankdir="<<dotRankDir()<<"];\n";

    // List of all possible subgraphs
    typedef multimap<string,V3GraphVertex*> SubgraphMmap;
    SubgraphMmap subgraphs;
    for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
	string vertexSubgraph = (colorAsSubgraph && vertexp->color()) ? cvtToStr(vertexp->color()) : "";
	subgraphs.insert(make_pair(vertexSubgraph, vertexp));
    }

    // We use a map here, as we don't want to corrupt anything (userp) in the graph,
    // and we don't care if this is slow.
    map<V3GraphVertex*,int>  numMap;

    // Print vertices
    int n=0;
    string subgr;
    for (SubgraphMmap::iterator it = subgraphs.begin(); it!=subgraphs.end(); ++it) {
	string vertexSubgraph = it->first;
	V3GraphVertex* vertexp = it->second;
	numMap[vertexp] = n;
	if (subgr != vertexSubgraph) {
	    if (subgr!="") *logp<<"\t};\n";
	    subgr = vertexSubgraph;
	    if (subgr!="") *logp<<"\tsubgraph cluster_"<<subgr<<" {\n";
	}
	if (subgr!="") *logp<<"\t";
	*logp<<"\tn"<<vertexp->dotName()<<(n++)
	     <<"\t[fontsize=8 "
	     <<"label=\""<<(vertexp->name()!="" ? vertexp->name() : "\\N");
	if (vertexp->rank()) *logp<<" r"<<vertexp->rank();
	if (vertexp->fanout()) *logp<<" f"<<vertexp->fanout();
	if (vertexp->color()) *logp<<"\\n c"<<vertexp->color();
	*logp<<"\"";
	*logp<<", color="<<vertexp->dotColor();
	if (vertexp->dotStyle()!="") *logp<<", style="<<vertexp->dotStyle();
	if (vertexp->dotShape()!="") *logp<<", shape="<<vertexp->dotShape();
	*logp<<"];\n";
    }
    if (subgr!="") *logp<<"\t};\n";

    // Print edges
    for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
	for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
	    if (edgep->weight()) {
		int fromVnum = numMap[edgep->fromp()];
		int toVnum   = numMap[edgep->top()];
		*logp<<"\tn"<<edgep->fromp()->dotName()<<fromVnum
		     <<" -> n"<<edgep->top()->dotName()<<toVnum
		     <<" ["
		    //<<"fontsize=8 label=\""<<(edgep->name()!="" ? edgep->name() : "\\E")<<"\""
		     <<"fontsize=8 label=\""<<(edgep->dotLabel()!="" ? edgep->dotLabel() : "")<<"\""
		     <<" weight="<<edgep->weight()
		     <<" color="<<edgep->dotColor();
		if (edgep->dotStyle()!="") *logp<<" style="<<edgep->dotStyle();
		//if (edgep->cutable()) { *logp<<",constraint=false"; }    // to rank without following edges
		*logp<<"];\n";
	    }
	}
    }
    // Vertex::m_user end, now unused

    // Trailer
    *logp << "}\n";
    logp->close();

    cout << "dot -Tpdf -o ~/a.pdf "<<filename<<endl;
}
Esempio n. 19
0
void GateVisitor::optimizeSignals(bool allowMultiIn) {
    for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
	if (GateVarVertex* vvertexp = dynamic_cast<GateVarVertex*>(itp)) {
	    if (vvertexp->inEmpty()) {
		vvertexp->clearReducibleAndDedupable("inEmpty");	// Can't deal with no sources
		if (!vvertexp->isTop()		// Ok if top inputs are driverless
		    && !vvertexp->varScp()->varp()->valuep()
		    && !vvertexp->varScp()->varp()->isSigPublic()) {
		    UINFO(4, "No drivers "<<vvertexp->varScp()<<endl);
		    if (0) {
			// If we warned here after constant propagation, what the user considered
			// reasonable logic may have disappeared.  Issuing a warning would
			// thus be confusing.  V3Undriven now handles this.
			vvertexp->varScp()->varp()->v3warn(UNDRIVEN,"Signal has no drivers "
							   <<vvertexp->scopep()->prettyName()<<"."
							   <<vvertexp->varScp()->varp()->prettyName());
		    }
		}
	    }
	    else if (!vvertexp->inSize1()) {
		vvertexp->clearReducibleAndDedupable("size!1");	// Can't deal with more than one src
	    }
	    // Reduce it?
	    if (!vvertexp->reducible()) {
		UINFO(8, "SigNotRed "<<vvertexp->name()<<endl);
	    } else {
		UINFO(8, "Sig "<<vvertexp->name()<<endl);
		GateLogicVertex* logicVertexp = dynamic_cast<GateLogicVertex*>
		    (vvertexp->inBeginp()->fromp());
		UINFO(8, "  From "<<logicVertexp->name()<<endl);
		AstNode* logicp = logicVertexp->nodep();
		if (logicVertexp->reducible()) {
		    // Can we eliminate?
		    GateOkVisitor okVisitor(logicp, vvertexp->isClock(), false);
		    bool multiInputs = okVisitor.rhsVarRefs().size() > 1;
		    // Was it ok?
		    bool doit = okVisitor.isSimple();
		    if (doit && multiInputs) {
			if (!allowMultiIn) doit = false;
			// Doit if one input, or not used, or used only once, ignoring traces
			int n=0;
			for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
			    GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
			    if (!consumeVertexp->slow()) { // Not tracing or other slow path junk
				if (edgep->top()->outBeginp()) {  // Destination is itself used
				    n += edgep->weight();
				}
			    }
			    if (n>1) {
				doit = false;
				break;
			    }
			}
		    }
		    // Process it
		    if (!doit) {
			if (allowMultiIn && (debug()>=9)) {
			    UINFO(9, "Not ok simp"<<okVisitor.isSimple()<<" mi"<<multiInputs
				  <<" ob"<<vvertexp->outBeginp()<<" on"<<(vvertexp->outBeginp()?vvertexp->outBeginp()->outNextp():0)
				  <<" "<<vvertexp->name()
				  <<endl);
			    for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
				GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
				UINFO(9, "    edge "<<edgep<<" to: "<<consumeVertexp->nodep()<<endl);
			    }
			    for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
				GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->fromp());
				UINFO(9, "    edge "<<edgep<<" from: "<<consumeVertexp->nodep()<<endl);
			    }
			}
		    }
		    else {
			AstNode* substp = okVisitor.substTree();
			if (debug()>=5) logicp->dumpTree(cout,"\telimVar:  ");
			if (debug()>=5) substp->dumpTree(cout,"\t  subst:  ");
			++m_statSigs;
			bool removedAllUsages = true;
			for (V3GraphEdge* edgep = vvertexp->outBeginp();
			     edgep; ) {
			    GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
			    AstNode* consumerp = consumeVertexp->nodep();
			    if (!elimLogicOkOutputs(consumeVertexp, okVisitor/*ref*/)) {
				// Cannot optimize this replacement
				removedAllUsages = false;
				edgep = edgep->outNextp();
			    } else {
				optimizeElimVar(vvertexp->varScp(), substp, consumerp);
				// If the new replacement referred to a signal,
				// Correct the graph to point to this new generating variable
				const GateVarRefList& rhsVarRefs = okVisitor.rhsVarRefs();
				for (GateVarRefList::const_iterator it = rhsVarRefs.begin();
				     it != rhsVarRefs.end(); ++it) {
				    AstVarScope* newvarscp = (*it)->varScopep();
				    UINFO(9,"         Point-to-new vertex "<<newvarscp<<endl);
				    GateVarVertex* varvertexp = makeVarVertex(newvarscp);
				    new V3GraphEdge(&m_graph, varvertexp, consumeVertexp, 1);
				    // Propagate clock attribute onto generating node
				    varvertexp->propagateAttrClocksFrom(vvertexp);
				}
				// Remove the edge
				edgep->unlinkDelete(); VL_DANGLING(edgep);
				++m_statRefs;
				edgep = vvertexp->outBeginp();
			    }
			}
			if (removedAllUsages) {
			    // Remove input links
			    while (V3GraphEdge* edgep = vvertexp->inBeginp()) {
				edgep->unlinkDelete(); VL_DANGLING(edgep);
			    }
			    // Clone tree so we remember it for tracing, and keep the pointer
			    // to the "ALWAYS" part of the tree as part of this statement
			    // That way if a later signal optimization that retained a pointer to the always
			    // can optimize it further
			    logicp->unlinkFrBack();
			    vvertexp->varScp()->valuep(logicp);
			    logicp = NULL;
			    // Mark the vertex so we don't mark it as being unconsumed in the next step
			    vvertexp->user(true);
			    logicVertexp->user(true);
			}
		    }
		}
	    }
	}
    }
}