From b32eed9a849381172a5d3208cc7798a8a11c4c9b Mon Sep 17 00:00:00 2001 From: James Cherry Date: Thu, 15 May 2025 17:21:39 -0700 Subject: [PATCH] Fix levelize crash when vertices enqueued in arrival/required iterators Signed-off-by: James Cherry --- include/sta/Search.hh | 1 + search/Levelize.cc | 27 ++++++++++++++++++++++----- search/Levelize.hh | 3 +++ search/Search.cc | 20 ++++++++++++++++++-- search/Sta.cc | 9 ++++++++- 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/include/sta/Search.hh b/include/sta/Search.hh index cd2dd9e7..780ef60a 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -359,6 +359,7 @@ public: void reportArrivals(Vertex *vertex) const; Slack wnsSlack(Vertex *vertex, PathAPIndex path_ap_index); + void levelsChangedBefore(); void levelChangedBefore(Vertex *vertex); void seedInputArrival(const Pin *pin, Vertex *vertex, diff --git a/search/Levelize.cc b/search/Levelize.cc index 9bfdacde..79f54066 100644 --- a/search/Levelize.cc +++ b/search/Levelize.cc @@ -122,6 +122,8 @@ Levelize::levelize() Stats stats(debug_, report_); debugPrint(debug_, "levelize", 1, "levelize"); clear(); + if (observer_) + observer_->levelsChangedBefore(); VertexIterator vertex_iter(graph_); while (vertex_iter.hasNext()) { @@ -545,6 +547,19 @@ Levelize::ensureLatchLevels() latch_d_to_q_edges_.clear(); } +void +Levelize::setLevel(Vertex *vertex, + Level level) +{ + debugPrint(debug_, "levelize", 2, "set level %s %d", + vertex->to_string(this).c_str(), + level); + vertex->setLevel(level); + max_level_ = max(level, max_level_); + if (level >= Graph::vertex_level_max) + criticalError(616, "maximum logic level exceeded"); +} + void Levelize::invalid() { @@ -597,6 +612,8 @@ Levelize::deleteEdgeBefore(Edge *edge) { if (levelized_ && loop_edges_.hasKey(edge)) { + debugPrint(debug_, "levelize", 2, "delete loop edge %s", + edge->to_string(this).c_str()); disabled_loop_edges_.erase(edge); // Relevelize if a loop edge is removed. Incremental levelization // fails because the DFS path will be missing. @@ -621,7 +638,7 @@ Levelize::relevelize() vertex->to_string(this).c_str()); if (search_pred_.searchFrom(vertex)) { if (isRoot(vertex)) { - setLevel(vertex, 0); + setLevelIncr(vertex, 0); roots_->insert(vertex); } VertexSet visited(graph_); @@ -645,7 +662,7 @@ Levelize::visit(Vertex *vertex, EdgeSeq &path) { Pin *from_pin = vertex->pin(); - setLevel(vertex, level); + setLevelIncr(vertex, level); level += level_space; visited.insert(vertex); path_vertices.insert(vertex); @@ -691,8 +708,8 @@ Levelize::isDisabledLoop(Edge *edge) const } void -Levelize::setLevel(Vertex *vertex, - Level level) +Levelize::setLevelIncr(Vertex *vertex, + Level level) { debugPrint(debug_, "levelize", 2, "set level %s %d", vertex->to_string(this).c_str(), @@ -704,7 +721,7 @@ Levelize::setLevel(Vertex *vertex, } max_level_ = max(level, max_level_); if (level >= Graph::vertex_level_max) - criticalError(616, "maximum logic level exceeded"); + criticalError(617, "maximum logic level exceeded"); } //////////////////////////////////////////////////////////////// diff --git a/search/Levelize.hh b/search/Levelize.hh index a1a9a383..28a34603 100644 --- a/search/Levelize.hh +++ b/search/Levelize.hh @@ -96,6 +96,8 @@ protected: EdgeSeq &path); void setLevel(Vertex *vertex, Level level); + void setLevelIncr(Vertex *vertex, + Level level); void clearLoopEdges(); void deleteLoops(); void reportPath(EdgeSeq &path) const; @@ -135,6 +137,7 @@ class LevelizeObserver public: LevelizeObserver() {} virtual ~LevelizeObserver() {} + virtual void levelsChangedBefore() = 0; virtual void levelChangedBefore(Vertex *vertex) = 0; }; diff --git a/search/Search.cc b/search/Search.cc index 85370049..a18e436f 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -795,14 +795,30 @@ Search::arrivalInvalid(Vertex *vertex) } } +// Move any pending arrival/requireds to invalid before relevelization. +void +Search::levelsChangedBefore() +{ + if (arrivals_exist_) { + while (arrival_iter_->hasNext()) { + Vertex *vertex = arrival_iter_->next(); + arrivalInvalid(vertex); + } + while (required_iter_->hasNext()) { + Vertex *vertex = required_iter_->next(); + requiredInvalid(vertex); + } + } +} + void Search::levelChangedBefore(Vertex *vertex) { if (arrivals_exist_) { arrival_iter_->remove(vertex); required_iter_->remove(vertex); - search_->arrivalInvalid(vertex); - search_->requiredInvalid(vertex); + arrivalInvalid(vertex); + requiredInvalid(vertex); } } diff --git a/search/Sta.cc b/search/Sta.cc index 4bf71fca..4a42db38 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -210,7 +210,8 @@ class StaLevelizeObserver : public LevelizeObserver { public: StaLevelizeObserver(Search *search); - virtual void levelChangedBefore(Vertex *vertex); + void levelsChangedBefore() override; + void levelChangedBefore(Vertex *vertex) override; private: Search *search_; @@ -221,6 +222,12 @@ StaLevelizeObserver::StaLevelizeObserver(Search *search) : { } +void +StaLevelizeObserver::levelsChangedBefore() +{ + search_->levelsChangedBefore(); +} + void StaLevelizeObserver::levelChangedBefore(Vertex *vertex) {