diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index 6ed60261..3de4710d 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -698,19 +698,30 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex, load_slews_prev = loadSlews(load_pin_index_map); findDriverDelays(vertex, arc_delay_calc, load_pin_index_map); if (network_->direction(pin)->isInternal()) - enqueueTimingChecksEdges(vertex); - // Enqueue adjacent vertices even if the load slews did not - // change when non-incremental to stride past annotations. - if (!delays_exist_ - || loadSlewsChanged(load_slews_prev, load_pin_index_map)) - iter_->enqueueFanout(vertex); + enqueueCheckEdges(vertex); + graph_->visitFanouts(vertex, search_non_latch_pred_, + [this, &load_slews_prev, &load_pin_index_map] + (Vertex *fanout) { + // Enqueue adjacent vertices even if the load slew + // did not change when non-incremental to stride + // past annotations. + if (!delays_exist_ + || loadSlewChanged(fanout, load_slews_prev, + load_pin_index_map)) { + iter_->enqueue(fanout); + fanout->setBfsPredecessorChanged(true); + } + }); } else if (vertex->isLoad(network_)) { // Load vertex. // Includes top level bidirect load vertex with wire edge to bidirect driver. - enqueueTimingChecksEdges(vertex); - // Enqueue driver vertices from this input load. - iter_->enqueueFanout(vertex); + enqueueCheckEdges(vertex); + graph_->visitFanouts(vertex, search_non_latch_pred_, + [this] (Vertex *fanout) { + iter_->enqueue(fanout); + fanout->setBfsPredecessorChanged(true); + }); } } @@ -730,24 +741,25 @@ GraphDelayCalc::loadSlews(LoadPinIndexMap &load_pin_index_map) } bool -GraphDelayCalc::loadSlewsChanged(DrvrLoadSlews &load_slews_prev, - LoadPinIndexMap &load_pin_index_map) +GraphDelayCalc::loadSlewChanged(Vertex *load_vertex, + DrvrLoadSlews &load_slews_prev, + LoadPinIndexMap &load_pin_index_map) { + if (load_slews_prev.empty()) + return true; + size_t index = load_pin_index_map[load_vertex->pin()]; + SlewSeq &slews_prev = load_slews_prev[index];; size_t slew_count = graph_->slewCount(); - for (auto const [pin, index] : load_pin_index_map) { - Vertex *load_vertex = graph_->pinLoadVertex(pin); - SlewSeq &slews_prev = load_slews_prev[index];; - for (size_t i = 0; i < slew_count; i++) { - const Slew slew = graph_->slew(load_vertex, i); - if (!delayEqual(slew, slews_prev[i], this)) - return true; - } + for (size_t i = 0; i < slew_count; i++) { + const Slew slew = graph_->slew(load_vertex, i); + if (!delayEqual(slew, slews_prev[i], this)) + return true; } return false; } void -GraphDelayCalc::enqueueTimingChecksEdges(Vertex *vertex) +GraphDelayCalc::enqueueCheckEdges(Vertex *vertex) { if (vertex->hasChecks()) { VertexInEdgeIterator edge_iter(vertex, graph_); @@ -1173,10 +1185,10 @@ GraphDelayCalc::annotateDelaysSlews(Edge *edge, dcalc_result.drvrSlew(), scene, min_max); if (!edge->role()->isLatchDtoQ()) { Vertex *drvr_vertex = edge->to(graph_); - delay_changed |= annotateLoadDelays(drvr_vertex, arc->toEdge()->asRiseFall(), - dcalc_result, - load_pin_index_map, delay_zero, true, - scene, min_max); + annotateLoadDelays(drvr_vertex, arc->toEdge()->asRiseFall(), + dcalc_result, + load_pin_index_map, delay_zero, true, + scene, min_max); } return delay_changed; } @@ -1231,7 +1243,7 @@ GraphDelayCalc::annotateDelaySlew(Edge *edge, // Annotate wire arc delays and load pin slews. // extra_delay is additional wire delay to add to delay returned // by the delay calculator. -bool +void GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex, const RiseFall *drvr_rf, ArcDcalcResult &dcalc_result, @@ -1242,7 +1254,6 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex, const MinMax *min_max) { DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max); - bool changed = false; VertexOutEdgeIterator edge_iter(drvr_vertex, graph_); while (edge_iter.hasNext()) { Edge *wire_edge = edge_iter.next(); @@ -1257,20 +1268,17 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex, load_vertex->to_string(this), delayAsString(wire_delay, this), delayAsString(load_slew, this)); - bool load_changed = false; if (!load_vertex->slewAnnotated(drvr_rf, min_max)) { if (drvr_vertex->slewAnnotated(drvr_rf, min_max)) { // Copy the driver slew to the load if it is annotated. const Slew drvr_slew = graph_->slew(drvr_vertex, drvr_rf, ap_index); graph_->setSlew(load_vertex, drvr_rf, ap_index, drvr_slew); - load_changed = true; } else { const Slew slew = graph_->slew(load_vertex, drvr_rf, ap_index); if (!merge || delayGreater(load_slew, slew, min_max, this)) { graph_->setSlew(load_vertex, drvr_rf, ap_index, load_slew); - load_changed = true; } } } @@ -1283,15 +1291,12 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex, if (!merge || delayGreater(wire_delay_extra, delay, min_max, this)) { graph_->setWireArcDelay(wire_edge, drvr_rf, ap_index, wire_delay_extra); - load_changed = true; + if (observer_) + observer_->delayChangedTo(load_vertex); } } - if (load_changed && observer_) - observer_->delayChangedTo(load_vertex); - changed |= load_changed; } } - return changed; } LoadPinIndexMap diff --git a/graph/Graph.cc b/graph/Graph.cc index 93f52be1..2e7f4e64 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -1053,6 +1053,7 @@ Vertex::init(Pin *pin, has_downstream_clk_pin_ = false; visited1_ = false; visited2_ = false; + bfs_predecessor_changed_ = false; has_sim_value_ = false; level_ = 0; slew_annotated_ = false; @@ -1281,6 +1282,12 @@ Vertex::setBfsInQueue(BfsIndex index, bfs_in_queue_ &= ~(1 << static_cast(index)); } +void +Vertex::setBfsPredecessorChanged(bool changed) +{ + bfs_predecessor_changed_ = changed; +} + //////////////////////////////////////////////////////////////// // // Edge diff --git a/include/sta/Graph.hh b/include/sta/Graph.hh index ed96f633..1d22708f 100644 --- a/include/sta/Graph.hh +++ b/include/sta/Graph.hh @@ -289,6 +289,8 @@ public: void setHasDownstreamClkPin(bool has_clk_pin); [[nodiscard]] bool bfsInQueue(BfsIndex index) const; void setBfsInQueue(BfsIndex index, bool value); + bool bfsPredecessorChanged() const { return bfs_predecessor_changed_; } + void setBfsPredecessorChanged(bool changed); [[nodiscard]] bool isRegClk() const { return is_reg_clk_; } // Has sim value in some mode. [[nodiscard]] bool hasSimValue() const { return has_sim_value_; } @@ -336,6 +338,7 @@ protected: unsigned int has_downstream_clk_pin_:1; unsigned int visited1_:1; unsigned int visited2_:1; + unsigned int bfs_predecessor_changed_:1; unsigned int has_sim_value_:1; int level_:Graph::vertex_level_bits; // 24 unsigned int slew_annotated_:slew_annotated_bits; // 4 diff --git a/include/sta/GraphDelayCalc.hh b/include/sta/GraphDelayCalc.hh index 46e1c37b..e8dc919d 100644 --- a/include/sta/GraphDelayCalc.hh +++ b/include/sta/GraphDelayCalc.hh @@ -234,9 +234,10 @@ protected: void findVertexDelay(Vertex *vertex, ArcDelayCalc *arc_delay_calc); DrvrLoadSlews loadSlews(LoadPinIndexMap &load_pin_index_map); - bool loadSlewsChanged(DrvrLoadSlews &load_slews_prev, - LoadPinIndexMap &load_pin_index_map); - void enqueueTimingChecksEdges(Vertex *vertex); + void enqueueCheckEdges(Vertex *vertex); + bool loadSlewChanged(Vertex *load_vertex, + DrvrLoadSlews &load_slews_prev, + LoadPinIndexMap &load_pin_index_map); bool annotateDelaysSlews(Edge *edge, const TimingArc *arc, ArcDcalcResult &dcalc_result, @@ -250,7 +251,7 @@ protected: const Slew &gate_slew, const Scene *scene, const MinMax *min_max); - bool annotateLoadDelays(Vertex *drvr_vertex, + void annotateLoadDelays(Vertex *drvr_vertex, const RiseFall *drvr_rf, ArcDcalcResult &dcalc_result, LoadPinIndexMap &load_pin_index_map,