Esempio n. 1
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. 2
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. 3
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);
			}
		    }
		}
	    }
	}
    }
}
Esempio n. 4
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. 5
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");
    }