mirror of
https://github.com/verilator/verilator.git
synced 2026-09-04 00:30:34 +02:00
Improve V3List user interface (#4996)
This commit is contained in:
+37
-33
@@ -53,36 +53,17 @@ struct GraphPCNode final {
|
||||
//######################################################################
|
||||
// GraphPathChecker implementation
|
||||
|
||||
GraphPathChecker::GraphPathChecker(const V3Graph* graphp, V3EdgeFuncP edgeFuncp)
|
||||
: GraphAlg<const V3Graph>{graphp, edgeFuncp} {
|
||||
for (V3GraphVertex* vxp = graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
|
||||
// Setup tracking structure for each node. If delete a vertex
|
||||
// there would be a leak, but ok as accept only const V3Graph*'s.
|
||||
vxp->userp(new GraphPCNode);
|
||||
}
|
||||
// Init critical paths in userp() for each vertex
|
||||
initHalfCriticalPaths(GraphWay::FORWARD, false);
|
||||
initHalfCriticalPaths(GraphWay::REVERSE, false);
|
||||
}
|
||||
|
||||
GraphPathChecker::~GraphPathChecker() {
|
||||
// Free every GraphPCNode
|
||||
for (V3GraphVertex* vxp = m_graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
|
||||
const GraphPCNode* const nodep = static_cast<GraphPCNode*>(vxp->userp());
|
||||
VL_DO_DANGLING(delete nodep, nodep);
|
||||
vxp->userp(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphPathChecker::initHalfCriticalPaths(GraphWay way, bool checkOnly) {
|
||||
template <GraphWay::en T_Way>
|
||||
void GraphPathChecker::initHalfCriticalPaths(bool checkOnly) {
|
||||
constexpr GraphWay way{T_Way};
|
||||
constexpr GraphWay rev = way.invert();
|
||||
GraphStreamUnordered order(m_graphp, way);
|
||||
const GraphWay rev = way.invert();
|
||||
while (const V3GraphVertex* const vertexp = order.nextp()) {
|
||||
unsigned critPathCost = 0;
|
||||
for (V3GraphEdge* edgep = vertexp->beginp(rev); edgep; edgep = edgep->nextp(rev)) {
|
||||
if (!m_edgeFuncp(edgep)) continue;
|
||||
for (const V3GraphEdge& edge : vertexp->edges<rev>()) {
|
||||
if (!m_edgeFuncp(&edge)) continue;
|
||||
|
||||
const V3GraphVertex* wrelativep = edgep->furtherp(rev);
|
||||
const V3GraphVertex* wrelativep = edge.furtherp<rev>();
|
||||
const GraphPCNode* const wrelUserp = static_cast<GraphPCNode*>(wrelativep->userp());
|
||||
critPathCost = std::max(critPathCost, wrelUserp->m_cp[way] + 1);
|
||||
}
|
||||
@@ -97,6 +78,30 @@ void GraphPathChecker::initHalfCriticalPaths(GraphWay way, bool checkOnly) {
|
||||
}
|
||||
}
|
||||
|
||||
template void GraphPathChecker::initHalfCriticalPaths<GraphWay::FORWARD>(bool);
|
||||
template void GraphPathChecker::initHalfCriticalPaths<GraphWay::REVERSE>(bool);
|
||||
|
||||
GraphPathChecker::GraphPathChecker(V3Graph* graphp, V3EdgeFuncP edgeFuncp)
|
||||
: GraphAlg<V3Graph>{graphp, edgeFuncp} {
|
||||
for (V3GraphVertex& vtx : graphp->vertices()) {
|
||||
// Setup tracking structure for each node. If delete a vertex
|
||||
// there would be a leak, but ok as accept only const V3Graph*'s.
|
||||
vtx.userp(new GraphPCNode);
|
||||
}
|
||||
// Init critical paths in userp() for each vertex
|
||||
initHalfCriticalPaths<GraphWay::FORWARD>(false);
|
||||
initHalfCriticalPaths<GraphWay::REVERSE>(false);
|
||||
}
|
||||
|
||||
GraphPathChecker::~GraphPathChecker() {
|
||||
// Free every GraphPCNode
|
||||
for (V3GraphVertex& vtx : m_graphp->vertices()) {
|
||||
const GraphPCNode* const nodep = static_cast<GraphPCNode*>(vtx.userp());
|
||||
VL_DO_DANGLING(delete nodep, nodep);
|
||||
vtx.userp(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphPathChecker::pathExistsInternal(const V3GraphVertex* ap, const V3GraphVertex* bp,
|
||||
unsigned* costp) {
|
||||
GraphPCNode* const auserp = static_cast<GraphPCNode*>(ap->userp());
|
||||
@@ -121,11 +126,11 @@ bool GraphPathChecker::pathExistsInternal(const V3GraphVertex* ap, const V3Graph
|
||||
|
||||
// Slow path; visit some extended family
|
||||
bool foundPath = false;
|
||||
for (V3GraphEdge* edgep = ap->outBeginp(); edgep && !foundPath; edgep = edgep->outNextp()) {
|
||||
if (!m_edgeFuncp(edgep)) continue;
|
||||
for (const V3GraphEdge& edge : ap->outEdges()) {
|
||||
if (!m_edgeFuncp(&edge)) continue;
|
||||
|
||||
unsigned childCost;
|
||||
if (pathExistsInternal(edgep->top(), bp, &childCost)) foundPath = true;
|
||||
if (pathExistsInternal(edge.top(), bp, &childCost)) foundPath = true;
|
||||
if (costp) *costp += childCost;
|
||||
}
|
||||
|
||||
@@ -141,10 +146,9 @@ bool GraphPathChecker::isTransitiveEdge(const V3GraphEdge* edgep) {
|
||||
const V3GraphVertex* fromp = edgep->fromp();
|
||||
const V3GraphVertex* top = edgep->top();
|
||||
incGeneration();
|
||||
for (const V3GraphEdge* fromOutp = fromp->outBeginp(); fromOutp;
|
||||
fromOutp = fromOutp->outNextp()) {
|
||||
if (fromOutp == edgep) continue;
|
||||
if (pathExistsInternal(fromOutp->top(), top)) return true;
|
||||
for (const V3GraphEdge& fromOut : fromp->outEdges()) {
|
||||
if (&fromOut == edgep) continue;
|
||||
if (pathExistsInternal(fromOut.top(), top)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user