mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Improve V3List user interface (#4996)
This commit is contained in:
+65
-82
@@ -42,19 +42,15 @@ class GraphRemoveRedundant final : GraphAlg<> {
|
||||
const bool m_sumWeights; ///< Sum, rather then maximize weights
|
||||
private:
|
||||
void main() {
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
vertexIterate(vertexp);
|
||||
}
|
||||
for (V3GraphVertex& vertex : m_graphp->vertices()) vertexIterate(&vertex);
|
||||
}
|
||||
void vertexIterate(V3GraphVertex* vertexp) {
|
||||
// Clear marks
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
edgep->top()->userp(nullptr);
|
||||
}
|
||||
for (V3GraphEdge& edge : vertexp->outEdges()) edge.top()->userp(nullptr);
|
||||
|
||||
// Mark edges and detect duplications
|
||||
for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
|
||||
nextp = edgep->outNextp();
|
||||
|
||||
for (V3GraphEdge* const edgep : vertexp->outEdges().unlinkable()) {
|
||||
if (followEdge(edgep)) {
|
||||
V3GraphVertex* outVertexp = edgep->top();
|
||||
V3GraphEdge* prevEdgep = static_cast<V3GraphEdge*>(outVertexp->userp());
|
||||
@@ -112,15 +108,15 @@ public:
|
||||
: GraphAlg<>(graphp, nullptr) {}
|
||||
void go() {
|
||||
GraphPathChecker checker{m_graphp};
|
||||
for (V3GraphVertex* vxp = m_graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
|
||||
for (V3GraphVertex& vtx : m_graphp->vertices()) {
|
||||
V3GraphEdge* deletep = nullptr;
|
||||
for (V3GraphEdge* edgep = vxp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
for (V3GraphEdge& edge : vtx.outEdges()) {
|
||||
if (deletep) VL_DO_CLEAR(deletep->unlinkDelete(), deletep = nullptr);
|
||||
// It should be safe to modify the graph, despite using
|
||||
// the GraphPathChecker, as none of the modifications will
|
||||
// change what can be reached from what, nor should they
|
||||
// change the rank or CP of any node.
|
||||
if (checker.isTransitiveEdge(edgep)) deletep = edgep;
|
||||
if (checker.isTransitiveEdge(&edge)) deletep = &edge;
|
||||
}
|
||||
if (deletep) VL_DO_DANGLING(deletep->unlinkDelete(), deletep);
|
||||
}
|
||||
@@ -143,10 +139,9 @@ class GraphAlgWeakly final : GraphAlg<> {
|
||||
m_graphp->clearColors();
|
||||
// Color graph
|
||||
uint32_t currentColor = 0;
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
for (V3GraphVertex& vertex : m_graphp->vertices()) {
|
||||
currentColor++;
|
||||
vertexIterate(vertexp, currentColor);
|
||||
vertexIterate(&vertex, currentColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,11 +150,11 @@ class GraphAlgWeakly final : GraphAlg<> {
|
||||
// then visit each of its edges, giving them the same color
|
||||
if (vertexp->color()) return; // Already colored it
|
||||
vertexp->color(currentColor);
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
if (followEdge(edgep)) vertexIterate(edgep->top(), currentColor);
|
||||
for (V3GraphEdge& edge : vertexp->outEdges()) {
|
||||
if (followEdge(&edge)) vertexIterate(edge.top(), currentColor);
|
||||
}
|
||||
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||
if (followEdge(edgep)) vertexIterate(edgep->fromp(), currentColor);
|
||||
for (V3GraphEdge& edge : vertexp->inEdges()) {
|
||||
if (followEdge(&edge)) vertexIterate(edge.fromp(), currentColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,33 +187,30 @@ class GraphAlgStrongly final : GraphAlg<> {
|
||||
// Vertex::color // Output subtree number (fully processed)
|
||||
|
||||
// Clear info
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
vertexp->color(0);
|
||||
vertexp->user(0);
|
||||
for (V3GraphVertex& vertex : m_graphp->vertices()) {
|
||||
vertex.color(0);
|
||||
vertex.user(0);
|
||||
}
|
||||
// Color graph
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
if (!vertexp->user()) {
|
||||
for (V3GraphVertex& vertex : m_graphp->vertices()) {
|
||||
if (!vertex.user()) {
|
||||
m_currentDfs++;
|
||||
vertexIterate(vertexp);
|
||||
vertexIterate(&vertex);
|
||||
}
|
||||
}
|
||||
// If there's a single vertex of a color, it doesn't need a subgraph
|
||||
// This simplifies the consumer's code, and reduces graph debugging clutter
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
for (V3GraphVertex& vertex : m_graphp->vertices()) {
|
||||
bool onecolor = true;
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
if (followEdge(edgep)) {
|
||||
if (vertexp->color() == edgep->top()->color()) {
|
||||
for (V3GraphEdge& edge : vertex.outEdges()) {
|
||||
if (followEdge(&edge)) {
|
||||
if (vertex.color() == edge.top()->color()) {
|
||||
onecolor = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (onecolor) vertexp->color(0);
|
||||
if (onecolor) vertex.color(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,9 +218,9 @@ class GraphAlgStrongly final : GraphAlg<> {
|
||||
const uint32_t thisDfsNum = m_currentDfs++;
|
||||
vertexp->user(thisDfsNum);
|
||||
vertexp->color(0);
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
if (followEdge(edgep)) {
|
||||
V3GraphVertex* top = edgep->top();
|
||||
for (V3GraphEdge& edge : vertexp->outEdges()) {
|
||||
if (followEdge(&edge)) {
|
||||
V3GraphVertex* top = edge.top();
|
||||
if (!top->user()) { // Dest not computed yet
|
||||
vertexIterate(top);
|
||||
}
|
||||
@@ -273,15 +265,13 @@ class GraphAlgRank final : GraphAlg<> {
|
||||
// Rank each vertex, ignoring cutable edges
|
||||
// Vertex::m_user begin: 1 indicates processing, 2 indicates completed
|
||||
// Clear existing ranks
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
vertexp->rank(0);
|
||||
vertexp->user(0);
|
||||
for (V3GraphVertex& vertex : m_graphp->vertices()) {
|
||||
vertex.rank(0);
|
||||
vertex.user(0);
|
||||
}
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
if (!vertexp->user()) { //
|
||||
vertexIterate(vertexp, 1);
|
||||
for (V3GraphVertex& vertex : m_graphp->vertices()) {
|
||||
if (!vertex.user()) { //
|
||||
vertexIterate(&vertex, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,10 +288,8 @@ class GraphAlgRank final : GraphAlg<> {
|
||||
if (vertexp->rank() >= currentRank) return; // Already processed it
|
||||
vertexp->user(1);
|
||||
vertexp->rank(currentRank);
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
if (followEdge(edgep)) {
|
||||
vertexIterate(edgep->top(), currentRank + vertexp->rankAdder());
|
||||
}
|
||||
for (V3GraphEdge& edge : vertexp->outEdges()) {
|
||||
if (followEdge(&edge)) vertexIterate(edge.top(), currentRank + vertexp->rankAdder());
|
||||
}
|
||||
vertexp->user(2);
|
||||
}
|
||||
@@ -353,8 +341,8 @@ class GraphAlgRLoops final : GraphAlg<> {
|
||||
}
|
||||
if (vertexp->user() == 2) return; // Already processed it
|
||||
vertexp->user(1);
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
if (followEdge(edgep)) vertexIterate(edgep->top(), currentRank);
|
||||
for (V3GraphEdge& edge : vertexp->outEdges()) {
|
||||
if (followEdge(&edge)) vertexIterate(edge.top(), currentRank);
|
||||
}
|
||||
vertexp->user(2);
|
||||
}
|
||||
@@ -387,13 +375,13 @@ class GraphAlgSubtrees final : GraphAlg<> {
|
||||
newVertexp = vertexp->clone(m_loopGraphp);
|
||||
vertexp->userp(newVertexp);
|
||||
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
if (followEdge(edgep)) {
|
||||
V3GraphEdge* newEdgep = static_cast<V3GraphEdge*>(edgep->userp());
|
||||
for (V3GraphEdge& edge : vertexp->outEdges()) {
|
||||
if (followEdge(&edge)) {
|
||||
V3GraphEdge* newEdgep = static_cast<V3GraphEdge*>(edge.userp());
|
||||
if (!newEdgep) {
|
||||
V3GraphVertex* newTop = vertexIterateAll(edgep->top());
|
||||
newEdgep = edgep->clone(m_loopGraphp, newVertexp, newTop);
|
||||
edgep->userp(newEdgep);
|
||||
V3GraphVertex* newTop = vertexIterateAll(edge.top());
|
||||
newEdgep = edge.clone(m_loopGraphp, newVertexp, newTop);
|
||||
edge.userp(newEdgep);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -438,30 +426,25 @@ struct GraphSortEdgeCmp final {
|
||||
void V3Graph::sortVertices() {
|
||||
// Sort list of vertices by rank, then fanout
|
||||
std::vector<V3GraphVertex*> vertices;
|
||||
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) {
|
||||
vertices.push_back(vertexp);
|
||||
}
|
||||
for (V3GraphVertex& vertex : m_vertices) vertices.push_back(&vertex);
|
||||
std::stable_sort(vertices.begin(), vertices.end(), GraphSortVertexCmp());
|
||||
this->verticesUnlink();
|
||||
for (V3GraphVertex* ip : vertices) ip->verticesPushBack(this);
|
||||
// Re-insert in sorted order
|
||||
for (V3GraphVertex* const ip : vertices) {
|
||||
m_vertices.unlink(ip);
|
||||
m_vertices.linkBack(ip);
|
||||
}
|
||||
}
|
||||
|
||||
void V3Graph::sortEdges() {
|
||||
// Sort edges by rank then fanout of node they point to
|
||||
std::vector<V3GraphEdge*> edges;
|
||||
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) {
|
||||
for (V3GraphVertex& vertex : vertices()) {
|
||||
// Make a vector
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
edges.push_back(edgep);
|
||||
}
|
||||
for (V3GraphEdge& edge : vertex.outEdges()) edges.push_back(&edge);
|
||||
// Sort
|
||||
std::stable_sort(edges.begin(), edges.end(), GraphSortEdgeCmp());
|
||||
|
||||
// Relink edges in specified order
|
||||
// We know the vector contains all of the edges that were
|
||||
// there originally (didn't delete or add)
|
||||
vertexp->outUnlink();
|
||||
for (V3GraphEdge* edgep : edges) edgep->outPushBack();
|
||||
for (V3GraphEdge* const edgep : edges) edgep->relinkFromp(&vertex);
|
||||
// Prep for next
|
||||
edges.clear();
|
||||
}
|
||||
@@ -487,8 +470,8 @@ void V3Graph::orderPreRanked() {
|
||||
// Compute fanouts
|
||||
// Vertex::m_user begin: 1 indicates processing, 2 indicates completed
|
||||
userClearVertices();
|
||||
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) {
|
||||
if (!vertexp->user()) orderDFSIterate(vertexp);
|
||||
for (V3GraphVertex& vertex : vertices()) {
|
||||
if (!vertex.user()) orderDFSIterate(&vertex);
|
||||
}
|
||||
|
||||
// Sort list of vertices by rank, then fanout. Fanout is a bit of a
|
||||
@@ -506,12 +489,12 @@ double V3Graph::orderDFSIterate(V3GraphVertex* vertexp) {
|
||||
UASSERT_OBJ(vertexp->user() != 1, vertexp, "Loop found, backward edges should be dead");
|
||||
vertexp->user(1);
|
||||
double fanout = 0;
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
if (edgep->weight()) fanout += orderDFSIterate(edgep->m_top);
|
||||
for (V3GraphEdge& edge : vertexp->outEdges()) {
|
||||
if (edge.weight()) fanout += orderDFSIterate(edge.top());
|
||||
}
|
||||
// Just count inbound edges
|
||||
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||
if (edgep->weight()) ++fanout;
|
||||
for (V3GraphEdge& edge : vertexp->inEdges()) {
|
||||
if (edge.weight()) ++fanout;
|
||||
}
|
||||
vertexp->fanout(fanout);
|
||||
vertexp->user(2);
|
||||
@@ -524,12 +507,12 @@ double V3Graph::orderDFSIterate(V3GraphVertex* vertexp) {
|
||||
|
||||
class GraphAlgParallelismReport final {
|
||||
// MEMBERS
|
||||
const V3Graph& m_graph; // The graph
|
||||
V3Graph& m_graph; // The graph
|
||||
const std::function<uint64_t(const V3GraphVertex*)> m_vertexCost; // vertex cost function
|
||||
V3Graph::ParallelismReport m_report; // The result report
|
||||
|
||||
// CONSTRUCTORS
|
||||
explicit GraphAlgParallelismReport(const V3Graph& graph,
|
||||
explicit GraphAlgParallelismReport(V3Graph& graph,
|
||||
std::function<uint64_t(const V3GraphVertex*)> vertexCost)
|
||||
: m_graph{graph}
|
||||
, m_vertexCost{vertexCost} {
|
||||
@@ -540,13 +523,13 @@ class GraphAlgParallelismReport final {
|
||||
for (const V3GraphVertex* vertexp; (vertexp = serialize.nextp());) {
|
||||
++m_report.m_vertexCount;
|
||||
uint64_t cpCostToHere = 0;
|
||||
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||
for (const V3GraphEdge& edge : vertexp->inEdges()) {
|
||||
++m_report.m_edgeCount;
|
||||
// For each upstream item, add its critical path cost to
|
||||
// the cost of this edge, to form a new candidate critical
|
||||
// path cost to the current node. Whichever is largest is
|
||||
// the critical path to reach the start of this node.
|
||||
cpCostToHere = std::max(cpCostToHere, critPaths[edgep->fromp()]);
|
||||
cpCostToHere = std::max(cpCostToHere, critPaths[edge.fromp()]);
|
||||
}
|
||||
// Include the cost of the current vertex in the critical
|
||||
// path, so it represents the critical path to the end of
|
||||
@@ -564,12 +547,12 @@ class GraphAlgParallelismReport final {
|
||||
|
||||
public:
|
||||
static V3Graph::ParallelismReport
|
||||
apply(const V3Graph& graph, std::function<uint32_t(const V3GraphVertex*)> vertexCost) {
|
||||
apply(V3Graph& graph, std::function<uint32_t(const V3GraphVertex*)> vertexCost) {
|
||||
return GraphAlgParallelismReport(graph, vertexCost).m_report;
|
||||
}
|
||||
};
|
||||
|
||||
V3Graph::ParallelismReport
|
||||
V3Graph::parallelismReport(std::function<uint64_t(const V3GraphVertex*)> vertexCost) const {
|
||||
V3Graph::parallelismReport(std::function<uint64_t(const V3GraphVertex*)> vertexCost) {
|
||||
return GraphAlgParallelismReport::apply(*this, vertexCost);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user