diff --git a/include/sta/Search.hh b/include/sta/Search.hh index 364e6dfb..8122752e 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -75,8 +75,6 @@ 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; @@ -408,7 +406,6 @@ public: void checkPrevPaths() const; void deletePaths(Vertex *vertex); void deleteTagGroup(TagGroup *group); - bool postponeLatchOutputs() const { return postpone_latch_outputs_; } void saveEnumPath(Path *path); bool isSrchRoot(Vertex *vertex, const Mode *mode) const; @@ -710,7 +707,8 @@ public: bool make_tag_cache, const StaState *sta); ~PathVisitor() override; - virtual void visitFaninPaths(Vertex *to_vertex); + virtual void visitFaninPaths(Vertex *to_vertex, + bool with_latch_edges); virtual void visitFanoutPaths(Vertex *from_vertex); // Return false to stop visiting. virtual bool visitFromToPath(const Pin *from_pin, @@ -777,6 +775,8 @@ public: SearchPred *pred); void copyState(const StaState *sta) override; void visit(Vertex *vertex) override; + void visit(Vertex *vertex, + bool with_latch_edges); VertexVisitor *copy() const override; // Return false to stop visiting. bool visitFromToPath(const Pin *from_pin, diff --git a/search/Genclks.cc b/search/Genclks.cc index 851a601a..acf801b7 100644 --- a/search/Genclks.cc +++ b/search/Genclks.cc @@ -748,7 +748,7 @@ GenclkSrcArrivalVisitor::visit(Vertex *vertex) tag_bldr_->init(vertex); has_fanin_one_ = graph_->hasFaninOne(vertex); genclks_->copyGenClkSrcPaths(vertex, tag_bldr_); - visitFaninPaths(vertex); + visitFaninPaths(vertex, true); // Propagate beyond the clock tree to reach generated clk roots. insert_iter_->enqueueAdjacentVertices(vertex, &srch_pred_, mode_); search_->setVertexArrivals(vertex, tag_bldr_); diff --git a/search/PathEnum.cc b/search/PathEnum.cc index 3be9e114..e433c703 100644 --- a/search/PathEnum.cc +++ b/search/PathEnum.cc @@ -356,9 +356,7 @@ 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; + visitFaninPaths(before_div_->vertex(this), true); if (unique_edges_) { for (auto [vertex_edge, div] : unique_edge_divs_) diff --git a/search/Search.cc b/search/Search.cc index d943d3fc..08829669 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -645,7 +645,6 @@ Search::findFilteredArrivals(bool thru_latches) // fanin startpoints to reach -thru/-to endpoints. arrival_visitor_->init(true, false, eval_pred_); enqueuePendingClkFanouts(); - postpone_latch_outputs_ = true; bool have_pending_latch_outputs = false; // Iterate until data arrivals at all latches stop changing. for (int pass = 1; @@ -657,11 +656,9 @@ Search::findFilteredArrivals(bool thru_latches) 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); + for (Vertex *latch_output : pending_latch_outputs_) + arrival_visitor_->visit(latch_output, true); pending_latch_outputs_.clear(); - postpone_latch_outputs_ = true; deleteTagsPrev(); } @@ -991,20 +988,19 @@ Search::findAllArrivals(bool thru_latches, if (!clks_only) enqueuePendingClkFanouts(); arrival_visitor_->init(false, clks_only, eval_pred_); - 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); + for (int pass = 1; + pass == 1 || (thru_latches && have_pending_latch_outputs); pass++) { debugPrint(debug_, "search", 1, "find arrivals pass {}", pass); + findArrivals1(levelize_->maxLevel()); have_pending_latch_outputs = !pending_latch_outputs_.empty(); - postpone_latch_outputs_ = false; - for (Vertex *latch_vertex : pending_latch_outputs_) - arrival_visitor_->visit(latch_vertex); + for (Vertex *latch_output : pending_latch_outputs_) + arrival_visitor_->visit(latch_output, true); pending_latch_outputs_.clear(); - postpone_latch_outputs_ = true; } } @@ -1135,27 +1131,32 @@ ArrivalVisitor::setAlwaysToEndpoints(bool to_endpoints) void ArrivalVisitor::visit(Vertex *vertex) +{ + VertexInEdgeIterator edge_iter(vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + if (edge->role()->isLatchDtoQ()) { + search_->enqueueLatchOutput(vertex); + return; + } + } + visit(vertex, false); +} + +void +ArrivalVisitor::visit(Vertex *vertex, + bool with_latch_edges) { 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); if (crpr_active_ && !has_fanin_one_) tag_bldr_no_crpr_->init(vertex); - visitFaninPaths(vertex); + visitFaninPaths(vertex, with_latch_edges); if (crpr_active_ && search_->crprPathPruningEnabled() // No crpr for ideal clocks. @@ -1949,12 +1950,16 @@ PathVisitor::~PathVisitor() } void -PathVisitor::visitFaninPaths(Vertex *to_vertex) +PathVisitor::visitFaninPaths(Vertex *to_vertex, + bool with_latch_edges) { VertexInEdgeIterator edge_iter(to_vertex, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - if (!edge->role()->isTimingCheck()) { + const TimingRole *role = edge->role(); + if (!(role->isTimingCheck() + || (role == TimingRole::latchDtoQ() + && !with_latch_edges))) { Vertex *from_vertex = edge->from(graph_); const Pin *from_pin = from_vertex->pin(); const Pin *to_pin = to_vertex->pin(); @@ -2140,14 +2145,12 @@ PathVisitor::visitFromPath(const Pin *from_pin, } else if (edge->role() == TimingRole::latchDtoQ()) { if (min_max == MinMax::max() && clk) { - 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, - to_arrival); - if (to_tag) - to_tag = search_->thruTag(to_tag, edge, to_rf, tag_cache_); - } + arc_delay = search_->deratedDelay(from_vertex, arc, edge, false, min_max, + dcalc_ap, sdc); + latches_->latchOutArrival(from_path, arc, edge, to_tag, arc_delay, + to_arrival); + if (to_tag) + to_tag = search_->thruTag(to_tag, edge, to_rf, tag_cache_); } } else if (from_tag->isClock()) {