示例#1
0
    void processBlock(AstNode* nodep) {
	if (!nodep) return;	// Empty lists are ignorable
	// Pass the first node in a list of block items, we'll process them
	// Check there's >= 2 sub statements, else nothing to analyze
	// Save recursion state
	AstNode* firstp = nodep;   // We may reorder, and nodep is no longer first.
	void* oldBlockUser3 = nodep->user3p();   // May be overloaded in below loop, save it
	nodep->user3p(NULL);
	if (!nodep->firstAbovep()) nodep->v3fatalSrc("Node passed is in next list; should have processed all list at once");
	// Process it
	if (!nodep->nextp()) {
	    // Just one, so can't reorder.  Just look for more blocks/statements.
            iterate(nodep);
	} else {
	    UINFO(9,"  processBlock "<<nodep<<endl);
	    // Process block and followers
	    scanBlock(nodep);
	    if (m_noReorderWhy != "") {  // Jump or something nasty
		UINFO(9,"  NoReorderBlock because "<<m_noReorderWhy<<endl);
	    } else {
		// Reorder statements in this block
		cleanupBlockGraph(nodep);
		reorderBlock(nodep);
		// Delete old vertexes and edges only applying to this block
		while (firstp->backp()->nextp()==firstp) firstp = firstp->backp();  // Walk back to first in list
		for (AstNode* nextp=firstp; nextp; nextp=nextp->nextp()) {
		    SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p();
		    vvertexp->unlinkDelete(&m_graph);
		}
	    }
	}
	// Again, nodep may no longer be first.
	firstp->user3p(oldBlockUser3);
    }
示例#2
0
    virtual void visit(AstNode* nodep) {
        if (nodep->user3p()) {
            SplitLogicVertex* vertexp = (SplitLogicVertex*)(nodep->user3p());
            uint32_t color = vertexp->color();
            m_colors.insert(color);
            UINFO(8, "  SVL " << vertexp << " has color " << color << "\n");

            // Record that all containing ifs have this color.
            for (IfStack::const_iterator it = m_ifStack.begin();
                 it != m_ifStack.end(); ++it) {
                m_ifColors[*it].insert(color);
            }
        }
        iterateChildren(nodep);
    }
示例#3
0
    virtual void visit(AstNode* nodep) {
        // Anything that's not an if/else we assume is a leaf
        // (that is, something we won't split.) Don't visit further
        // into the leaf.
        //
        // A leaf might contain another if, for example a WHILE loop
        // could contain an if. We can't split WHILE loops, so we
        // won't split its nested if either. Just treat it as part
        // of the leaf; do not visit further; do not reach visit(AstNodeIf*)
        // for such an embedded if.

        // Each leaf must have a user3p
        if (!nodep->user3p()) nodep->v3fatalSrc("null user3p in V3Split leaf");

        // Clone the leaf into its new always block
        SplitLogicVertex* vxp = (SplitLogicVertex*)(nodep->user3p());
        uint32_t color = vxp->color();
        AstNode* clonedp = nodep->cloneTree(false);
        m_addAfter[color]->addNextHere(clonedp);
        m_addAfter[color] = clonedp;
    }
示例#4
0
    void reorderBlock(AstNode* nodep) {
	// Reorder statements in the completed graph

	// Map the rank numbers into nodes they associate with
        typedef std::multimap<uint32_t,AstNode*> RankNodeMap;
        RankNodeMap rankMap;
	int currOrder = 0;	// Existing sequence number of assignment
	for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) {
	    SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p();
	    rankMap.insert(make_pair(vvertexp->rank(), nextp));
	    nextp->user4(++currOrder);   // Record current ordering
	}

	// Is the current ordering OK?
	bool leaveAlone=true;
	int newOrder = 0;	// New sequence number of assignment
        for (RankNodeMap::const_iterator it = rankMap.begin();
             it != rankMap.end(); ++it) {
            AstNode* nextp = it->second;
            if (++newOrder != nextp->user4()) leaveAlone=false;
        }
	if (leaveAlone) {
	    UINFO(6,"   No changes\n");
	} else {
	    AstNRelinker replaceHandle;	// Where to add the list
            AstNode* newListp = NULL;
            for (RankNodeMap::const_iterator it = rankMap.begin(); it != rankMap.end(); ++it) {
                AstNode* nextp = it->second;
                UINFO(6, "   New order: "<<nextp<<endl);
                if (nextp == nodep) nodep->unlinkFrBack(&replaceHandle);
                else nextp->unlinkFrBack();
                if (newListp) newListp = newListp->addNext(nextp);
                else newListp = nextp;
            }
            replaceHandle.relink(newListp);
	} // leaveAlone
    }
示例#5
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);
    }
示例#6
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);
    }
示例#7
0
    void reorderBlock(AstNode* nodep) {
	// Reorder statements in the completed graph
	AstAlways* splitAlwaysp = nodep->backp()->castAlways();

	// Map the rank numbers into nodes they associate with
	typedef multimap<uint32_t,AstNode*> RankNodeMap;
	typedef map<uint32_t,RankNodeMap> ColorRankMap;
	ColorRankMap colorRankMap;
	uint32_t firstColor = 0;  bool multiColors = false;
	int currOrder = 0;	// Existing sequence number of assignment
	for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) {
	    SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p();
	    if (!splitAlwaysp) vvertexp->splitColor(1);  // All blocks remain as-is
	    RankNodeMap& rankMap = colorRankMap[vvertexp->splitColor()];
	    rankMap.insert(make_pair(vvertexp->rank(), nextp));
	    if (firstColor && firstColor != vvertexp->splitColor()) multiColors = true;
	    firstColor = vvertexp->splitColor();
	    nextp->user4(++currOrder);   // Record current ordering
	}
	// If there was only one color, we don't need multiple always blocks
	if (!multiColors) splitAlwaysp = NULL;

	// Is the current ordering OK?
	bool leaveAlone=true;
	if (splitAlwaysp) leaveAlone=false;
	int newOrder = 0;	// New sequence number of assignment
	for (ColorRankMap::iterator colorIt = colorRankMap.begin(); colorIt != colorRankMap.end(); ++colorIt) {
	    RankNodeMap& rankMap = colorIt->second;
	    for (RankNodeMap::iterator it = rankMap.begin(); it != rankMap.end(); ++it) {
		AstNode* nextp = it->second;
		if (++newOrder != nextp->user4()) leaveAlone=false;
	    }
	}
	if (leaveAlone) {
	    UINFO(6,"   No changes\n");
	} else {
	    AstNRelinker replaceHandle;	// Where to add the list
	    AstNode* addAfterp = splitAlwaysp;

	    for (ColorRankMap::iterator colorIt = colorRankMap.begin(); colorIt != colorRankMap.end(); ++colorIt) {
		uint32_t color = colorIt->first;
		RankNodeMap& rankMap = colorIt->second;
		AstNode* newListp = NULL;
		for (RankNodeMap::iterator it = rankMap.begin(); it != rankMap.end(); ++it) {
		    AstNode* nextp = it->second;
		    UINFO(6, "    Color="<<color<<"  New order: "<<nextp<<endl);
		    if (nextp == nodep && !splitAlwaysp) nodep->unlinkFrBack(&replaceHandle);
		    else nextp->unlinkFrBack();
		    newListp = newListp->addNext(nextp);
		}
		if (splitAlwaysp) {
		    ++m_statSplits;
		    AstAlways* alwaysp = new AstAlways(newListp->fileline(), VAlwaysKwd::ALWAYS, NULL, NULL);
		    addAfterp->addNextHere(alwaysp);  addAfterp=alwaysp;
		    alwaysp->addStmtp(newListp);
		} else {
		    // Just reordering
		    replaceHandle.relink(newListp);
		}
	    }
	    if (splitAlwaysp) {
		pushDeletep(splitAlwaysp->unlinkFrBack());
	    }
	} // leaveAlone
    }