mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
DFG: Remove topological sort
Cyclic components are now extracted separately, so there is no functional reason to have to do a topological sort (previously we used it to detect cyclic graphs). Removing it to gain some speed.
This commit is contained in:
@@ -46,77 +46,6 @@ void DfgGraph::addGraph(DfgGraph& other) {
|
||||
});
|
||||
}
|
||||
|
||||
bool DfgGraph::sortTopologically(bool reverse) {
|
||||
// Vertices in reverse topological order
|
||||
std::vector<DfgVertex*> order;
|
||||
|
||||
// Markings for algorithm
|
||||
enum class Mark : uint8_t { Scheduled, OnPath, Finished };
|
||||
std::unordered_map<DfgVertex*, Mark> marks;
|
||||
|
||||
// Stack of nodes in depth first search. The second element of the pair is true if the vertex
|
||||
// is on the current DFS path, and false if it's only scheduled for visitation.
|
||||
std::vector<std::pair<DfgVertex*, bool>> stack;
|
||||
|
||||
// Schedule vertex for visitation
|
||||
const auto scheudle = [&](DfgVertex& vtx) {
|
||||
// Nothing to do if already finished
|
||||
if (marks.emplace(&vtx, Mark::Scheduled).first->second == Mark::Finished) return;
|
||||
// Otherwise scheule for visitation
|
||||
stack.emplace_back(&vtx, false);
|
||||
};
|
||||
|
||||
// For each vertex (direct loop, so we can return early)
|
||||
for (DfgVertex* vtxp = m_vertices.begin(); vtxp; vtxp = vtxp->m_verticesEnt.nextp()) {
|
||||
// Initiate DFS from this vertex
|
||||
scheudle(*vtxp);
|
||||
while (!stack.empty()) {
|
||||
// Pick up stack top
|
||||
const auto pair = stack.back();
|
||||
stack.pop_back();
|
||||
DfgVertex* const currp = pair.first;
|
||||
const bool onPath = pair.second;
|
||||
Mark& mark = marks.at(currp);
|
||||
|
||||
if (onPath) { // Popped node on path
|
||||
// Mark it as done
|
||||
UASSERT_OBJ(mark == Mark::OnPath, currp, "DFS got lost");
|
||||
mark = Mark::Finished;
|
||||
// Add to order
|
||||
order.push_back(currp);
|
||||
} else { // Otherwise node was scheduled for visitation, so visit it
|
||||
// If already finished, then nothing to do
|
||||
if (mark == Mark::Finished) continue;
|
||||
// If already on path, then not a DAG
|
||||
if (mark == Mark::OnPath) return false;
|
||||
// Push to path and mark as such
|
||||
mark = Mark::OnPath;
|
||||
stack.emplace_back(currp, true);
|
||||
// Schedule children
|
||||
currp->forEachSink(scheudle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move given vertex to end of vertex list
|
||||
const auto reinsert = [this](DfgVertex& vtx) {
|
||||
// Remove from current location
|
||||
removeVertex(vtx);
|
||||
// 'addVertex' appends to the end of the vertex list, so can do this in one loop
|
||||
addVertex(vtx);
|
||||
};
|
||||
|
||||
// Remember 'order' is in reverse topological order
|
||||
if (!reverse) {
|
||||
for (DfgVertex* vtxp : vlstd::reverse_view(order)) reinsert(*vtxp);
|
||||
} else {
|
||||
for (DfgVertex* vtxp : order) reinsert(*vtxp);
|
||||
}
|
||||
|
||||
// Done
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<DfgGraph>> DfgGraph::splitIntoComponents(std::string label) {
|
||||
size_t componentNumber = 0;
|
||||
std::unordered_map<const DfgVertex*, unsigned> vertex2component;
|
||||
|
||||
Reference in New Issue
Block a user