From 1c6ab172e2870bee72127e330c1380e79199a8b7 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Wed, 17 Jun 2026 19:54:36 -0700 Subject: [PATCH] eval latches out of bfs Signed-off-by: James Cherry --- include/sta/Search.hh | 6 +-- search/PathEnum.cc | 10 +++++ search/Search.cc | 92 +++++++++++++++++-------------------------- 3 files changed, 49 insertions(+), 59 deletions(-) diff --git a/include/sta/Search.hh b/include/sta/Search.hh index d6db126e..364e6dfb 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -75,6 +75,8 @@ using ExceptionPathSeq = std::vector; class Search : public StaState { public: + bool postpone_latch_outputs_{false}; + Search(StaState *sta); ~Search() override; void copyState(const StaState *sta) override; @@ -530,9 +532,6 @@ protected: const MinMax *min_max) const; void seedRequireds(); void seedInvalidRequireds(); - [[nodiscard]] bool havePendingLatchOutputs(); - void clearPendingLatchOutputs(); - void enqueuePendingLatchOutputs(); void findFilteredArrivals(bool thru_latches); void findArrivalsSeed(); void seedFilterStarts(); @@ -669,7 +668,6 @@ protected: std::mutex filtered_arrivals_lock_; bool found_downstream_clk_pins_{false}; - bool postpone_latch_outputs_{false}; std::vector enum_paths_; VisitPathEnds *visit_path_ends_; diff --git a/search/PathEnum.cc b/search/PathEnum.cc index 7abd4a80..3be9e114 100644 --- a/search/PathEnum.cc +++ b/search/PathEnum.cc @@ -356,7 +356,9 @@ PathEnumFaninVisitor::visitFaninPathsThru(Path *before_div, prev_vertex_ = prev_vertex; visited_fanins_.clear(); unique_edge_divs_.clear(); + search_->postpone_latch_outputs_ = false; visitFaninPaths(before_div_->vertex(this)); + search_->postpone_latch_outputs_ = true; if (unique_edges_) { for (auto [vertex_edge, div] : unique_edge_divs_) @@ -422,6 +424,14 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *, Arrival & /* to_arrival */, const MinMax *) { + debugPrint(debug_, "path_enum", 3, "visit fanin {} -> {} {} {}", + from_path->to_string(this), + to_vertex->to_string(this), to_rf->shortName(), + delayAsString( + search_->deratedDelay( + from_vertex, arc, edge, false, from_path->minMax(this), + from_path->dcalcAnalysisPtIndex(this), from_path->sdc(this)), + this)); // These paths fanin to before_div_ so we know to_vertex matches. if ((!unique_pins_ || from_vertex != prev_vertex_) && (!unique_edges_ || from_vertex != prev_vertex_ diff --git a/search/Search.cc b/search/Search.cc index 22fe70b0..d943d3fc 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -326,7 +326,7 @@ Search::clear() deletePathGroups(); deletePaths(); deleteTags(); - clearPendingLatchOutputs(); + pending_latch_outputs_.clear(); pending_clk_endpoints_.clear(); deleteFilter(); found_downstream_clk_pins_ = false; @@ -644,18 +644,26 @@ Search::findFilteredArrivals(bool thru_latches) // Search always_to_endpoint to search from exisiting arrivals at // fanin startpoints to reach -thru/-to endpoints. arrival_visitor_->init(true, false, eval_pred_); - // Iterate until data arrivals at all latches stop changing. - postpone_latch_outputs_ = true; enqueuePendingClkFanouts(); - for (int pass = 1; pass == 1 || (thru_latches && havePendingLatchOutputs()); + postpone_latch_outputs_ = true; + bool have_pending_latch_outputs = false; + // Iterate until data arrivals at all latches stop changing. + for (int pass = 1; + pass == 1 || (thru_latches && have_pending_latch_outputs); pass++) { - if (thru_latches) - enqueuePendingLatchOutputs(); debugPrint(debug_, "search", 1, "find arrivals pass {}", pass); + int arrival_count = arrival_iter_->visitParallel(max_level, arrival_visitor_); - deleteTagsPrev(); debugPrint(debug_, "search", 1, "found {} arrivals", arrival_count); + + have_pending_latch_outputs = !pending_latch_outputs_.empty(); postpone_latch_outputs_ = false; + for (Vertex *latch_vertex : pending_latch_outputs_) + arrival_visitor_->visit(latch_vertex); + pending_latch_outputs_.clear(); + postpone_latch_outputs_ = true; + + deleteTagsPrev(); } arrivals_exist_ = true; } @@ -983,41 +991,23 @@ Search::findAllArrivals(bool thru_latches, if (!clks_only) enqueuePendingClkFanouts(); arrival_visitor_->init(false, clks_only, eval_pred_); - // Iterate until data arrivals at all latches stop changing. postpone_latch_outputs_ = true; - for (int pass = 1; pass == 1 || (thru_latches && havePendingLatchOutputs()); + bool have_pending_latch_outputs = false; + // Iterate until data arrivals at all latches stop changing. + for (int pass = 1; pass == 1 || (thru_latches && have_pending_latch_outputs); pass++) { - enqueuePendingLatchOutputs(); debugPrint(debug_, "search", 1, "find arrivals pass {}", pass); findArrivals1(levelize_->maxLevel()); - if (pass > 2) - postpone_latch_outputs_ = false; + + have_pending_latch_outputs = !pending_latch_outputs_.empty(); + postpone_latch_outputs_ = false; + for (Vertex *latch_vertex : pending_latch_outputs_) + arrival_visitor_->visit(latch_vertex); + pending_latch_outputs_.clear(); + postpone_latch_outputs_ = true; } } -bool -Search::havePendingLatchOutputs() -{ - return !pending_latch_outputs_.empty(); -} - -void -Search::clearPendingLatchOutputs() -{ - pending_latch_outputs_.clear(); -} - -void -Search::enqueuePendingLatchOutputs() -{ - for (Vertex *latch_vertex : pending_latch_outputs_) { - debugPrint(debug_, "search", 2, "enqueue latch output {}", - latch_vertex->to_string(this)); - arrival_iter_->enqueue(latch_vertex); - } - clearPendingLatchOutputs(); -} - void Search::enqueuePendingClkFanouts() { @@ -1148,6 +1138,17 @@ ArrivalVisitor::visit(Vertex *vertex) { debugPrint(debug_, "search", 2, "find arrivals {}", vertex->to_string(this)); + + if (search_->postponeLatchOutputs()) { + VertexInEdgeIterator edge_iter(vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + if (edge->role()->isLatchDtoQ()) { + search_->enqueueLatchOutput(edge->to(graph_)); + return; + } + } + } Pin *pin = vertex->pin(); tag_bldr_->init(vertex); has_fanin_one_ = graph_->hasFaninOne(vertex); @@ -2139,26 +2140,7 @@ PathVisitor::visitFromPath(const Pin *from_pin, } else if (edge->role() == TimingRole::latchDtoQ()) { if (min_max == MinMax::max() && clk) { - bool postponed = false; - if (search_->postponeLatchOutputs()) { - const Path *from_clk_path = from_clk_info->crprClkPath(this); - if (from_clk_path) { - Vertex *d_clk_vertex = from_clk_path->vertex(this); - Level d_clk_level = d_clk_vertex->level(); - Level q_level = to_vertex->level(); - if (d_clk_level >= q_level) { - // Crpr clk path on latch data input is required to find Q - // arrival. If the data clk path level is >= Q level the - // crpr clk path prev_path pointers are not complete. - debugPrint(debug_, "search", 3, "postponed latch eval {} {} -> {} {}", - d_clk_level, d_clk_vertex->to_string(this), - edge->to_string(this), q_level); - postponed = true; - search_->enqueueLatchOutput(to_vertex); - } - } - } - if (!postponed) { + if (!search_->postponeLatchOutputs()) { arc_delay = search_->deratedDelay(from_vertex, arc, edge, false, min_max, dcalc_ap, sdc); latches_->latchOutArrival(from_path, arc, edge, to_tag, arc_delay,