diff --git a/include/sta/ExceptionPath.hh b/include/sta/ExceptionPath.hh index e0337c5b..53a99355 100644 --- a/include/sta/ExceptionPath.hh +++ b/include/sta/ExceptionPath.hh @@ -439,6 +439,9 @@ public: bool matches(const Pin *pin, const RiseFall *end_rf) const; bool matches(const Clock *clk) const; + bool matches(const Pin *pin, + const RiseFall *end_rf, + const Network *network) const; bool matchesFilter(const Pin *pin, const ClockEdge *clk_edge, const RiseFall *end_rf, diff --git a/include/sta/Sdc.hh b/include/sta/Sdc.hh index 40ab885b..5012e192 100644 --- a/include/sta/Sdc.hh +++ b/include/sta/Sdc.hh @@ -976,6 +976,10 @@ public: const MinMax *min_max, bool match_min_max_exactly, bool require_to_pin) const; + bool isCompleteTo(ExceptionState *state, + const Pin *pin, + const RiseFall *rf, + const MinMax *min_max) const; bool isPathDelayInternalStartpoint(const Pin *pin) const; PinSet *pathDelayInternalStartpoints() const; bool isPathDelayInternalEndpoint(const Pin *pin) const; diff --git a/sdc/ExceptionPath.cc b/sdc/ExceptionPath.cc index e4cb251b..abc0cc9f 100644 --- a/sdc/ExceptionPath.cc +++ b/sdc/ExceptionPath.cc @@ -1465,6 +1465,23 @@ ExceptionTo::matches(const Pin *pin, && end_rf_->matches(end_rf)); } +bool +ExceptionTo::matches(const Pin *pin, + const RiseFall *end_rf, + const Network *network) const +{ + return (pins_ + && pins_->hasKey(const_cast(pin)) + && rf_->matches(end_rf) + && end_rf_->matches(end_rf)) + || (insts_ + && insts_->hasKey(network->instance(pin)) + && (network->direction(pin)->isAnyInput() + || network->direction(pin)->isInternal()) + && rf_->matches(end_rf) + && end_rf_->matches(end_rf)); +} + bool ExceptionTo::matches(const Pin *pin, const RiseFall *end_rf) const diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index d97f1790..94075c28 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -5620,6 +5620,20 @@ Sdc::isCompleteTo(ExceptionState *state, min_max, match_min_max_exactly, require_to_pin); } +bool +Sdc::isCompleteTo(ExceptionState *state, + const Pin *pin, + const RiseFall *rf, + const MinMax *min_max) const +{ + ExceptionPath *exception = state->exception(); + ExceptionTo *to = exception->to(); + return state->nextThru() == nullptr + && to + && exception->matches(min_max, true) + && to->matches(pin, rf, network_); +} + //////////////////////////////////////////////////////////////// Wireload * diff --git a/search/Search.cc b/search/Search.cc index 047de99b..101156c2 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -1134,11 +1134,9 @@ ArrivalVisitor::visit(Vertex *vertex) && network->isLatchData(pin)) search->enqueueLatchDataOutputs(vertex); } - if ((!search->arrivalsAtEndpointsExist() - || always_to_endpoints_ - || arrivals_changed) - && (network->isRegClkPin(pin) - || !sdc->isPathDelayInternalEndpoint(pin))) + if (!search->arrivalsAtEndpointsExist() + || always_to_endpoints_ + || arrivals_changed) search->arrivalIterator()->enqueueAdjacentVertices(vertex, adj_pred_); if (arrivals_changed) { debugPrint(debug, "search", 4, "arrival changed"); @@ -2033,27 +2031,22 @@ PathVisitor::visitEdge(const Pin *from_pin, VertexPathIterator from_iter(from_vertex, search); while (from_iter.hasNext()) { PathVertex *from_path = from_iter.next(); - Tag *from_tag = from_path->tag(sta_); - // Only propagate seeded paths from segment startpoint. - if (!search->isSegmentStart(from_pin) - || from_tag->isSegmentStart()) { - PathAnalysisPt *path_ap = from_path->pathAnalysisPt(sta_); - const MinMax *min_max = path_ap->pathMinMax(); - const RiseFall *from_rf = from_path->transition(sta_); - // Do not propagate paths from a clock source unless they are - // defined on the from pin. - if (!search->pathPropagatedToClkSrc(from_pin, from_path)) { - TimingArc *arc1, *arc2; - arc_set->arcsFrom(from_rf, arc1, arc2); - if (!visitArc(from_pin, from_vertex, from_rf, from_path, - edge, arc1, to_pin, to_vertex, - min_max, path_ap)) - return false; - if (!visitArc(from_pin, from_vertex, from_rf, from_path, - edge, arc2, to_pin, to_vertex, - min_max, path_ap)) - return false; - } + PathAnalysisPt *path_ap = from_path->pathAnalysisPt(sta_); + const MinMax *min_max = path_ap->pathMinMax(); + const RiseFall *from_rf = from_path->transition(sta_); + // Do not propagate paths from a clock source unless they are + // defined on the from pin. + if (!search->pathPropagatedToClkSrc(from_pin, from_path)) { + TimingArc *arc1, *arc2; + arc_set->arcsFrom(from_rf, arc1, arc2); + if (!visitArc(from_pin, from_vertex, from_rf, from_path, + edge, arc1, to_pin, to_vertex, + min_max, path_ap)) + return false; + if (!visitArc(from_pin, from_vertex, from_rf, from_path, + edge, arc2, to_pin, to_vertex, + min_max, path_ap)) + return false; } } } @@ -2565,6 +2558,10 @@ Search::mutateTag(Tag *from_tag, // Don't propagate a completed false path -thru unless it is a // clock (which ignores exceptions). return nullptr; + // Don't propagate path delay tags past the -to pin. + if (exception->isPathDelay() + && sdc_->isCompleteTo(state, from_pin, from_rf, min_max)) + return nullptr; if (state->matchesNextThru(from_pin,to_pin,to_rf,min_max,network_)) { // Found a -thru that we've been waiting for. if (state->nextState()->isComplete()