@@ -91,7 +91,8 @@ const char* RepairTargetCollector::getEnumString(ViolatorSortType sort_type)
9191void RepairTargetCollector::printViolators (int numPrint = 0 ) const
9292{
9393 if (violating_pins_.empty ()) {
94- logger_->info (RSZ , 8 , " No violating pins found." );
94+ debugPrint (
95+ logger_, RSZ , " violator_collector" , 1 , " No violating pins found." );
9596 return ;
9697 }
9798
@@ -812,9 +813,9 @@ void RepairTargetCollector::collectViolatingEndpoints()
812813
813814 const sta::VertexSet& endpoints = sta_->endpoints ();
814815 for (sta::Vertex* endpoint : endpoints) {
815- const sta::Slack endpoint_slack = sta_->slack (endpoint, max_);
816- if (sta::fuzzyLess (endpoint_slack , slack_margin_)) {
817- violating_endpoints_.emplace_back (endpoint->pin (), endpoint_slack );
816+ const sta::Slack slack = sta_->slack (endpoint, max_);
817+ if (sta::fuzzyLess (slack , slack_margin_)) {
818+ violating_endpoints_.emplace_back (endpoint->pin (), slack );
818819 }
819820 }
820821
@@ -877,6 +878,47 @@ sta::Path* RepairTargetCollector::findWorstSlackPath(
877878 return sta_->vertexWorstSlackPath (endpoint, max_);
878879}
879880
881+ void RepairTargetCollector::collectExpandedPathDriverTargets (
882+ const sta::Path* endpoint_path,
883+ const sta::PathExpanded& expanded,
884+ const sta::Slack path_slack,
885+ std::vector<Target>& targets) const
886+ {
887+ const int start_index = static_cast <int >(expanded.startIndex ());
888+ const int path_count = static_cast <int >(expanded.size ());
889+ for (int index = start_index; index < path_count; ++index) {
890+ const sta::Path* driver_path = expanded.path (index);
891+ sta::Vertex* vertex = driver_path->vertex (sta_);
892+ sta::Pin* pin = driver_path->pin (sta_);
893+ if (vertex == nullptr || pin == nullptr || !vertex->isDriver (network_)
894+ || network_->isTopLevelPort (pin)) {
895+ continue ;
896+ }
897+
898+ targets.push_back (makePathDriverTarget (
899+ endpoint_path, expanded, index, path_slack, *resizer_));
900+ }
901+ }
902+
903+ void RepairTargetCollector::collectExpandedPathDriverPins (
904+ const sta::PathExpanded& expanded,
905+ set<const sta::Pin*>& pins) const
906+ {
907+ const int start_index = static_cast <int >(expanded.startIndex ());
908+ const int path_count = static_cast <int >(expanded.size ());
909+ for (int index = start_index; index < path_count; ++index) {
910+ const sta::Path* driver_path = expanded.path (index);
911+ sta::Vertex* vertex = driver_path->vertex (sta_);
912+ const sta::Pin* pin = driver_path->pin (sta_);
913+ if (vertex == nullptr || pin == nullptr || !vertex->isDriver (network_)
914+ || network_->isTopLevelPort (pin)
915+ || sta_->isClock (pin, sta_->cmdMode ())) {
916+ continue ;
917+ }
918+ pins.insert (pin);
919+ }
920+ }
921+
880922std::vector<Target> RepairTargetCollector::collectPathDriverTargets (
881923 sta::Path* path,
882924 const sta::Slack path_slack) const
@@ -888,18 +930,19 @@ std::vector<Target> RepairTargetCollector::collectPathDriverTargets(
888930
889931 sta::PathExpanded expanded (path, sta_);
890932 targets.reserve (expanded.size ());
891- for (int index = expanded.startIndex (); index < expanded.size (); ++index) {
892- const sta::Path* driver_path = expanded.path (index);
893- sta::Vertex* vertex = driver_path->vertex (sta_);
894- sta::Pin* pin = driver_path->pin (sta_);
895- if (vertex == nullptr || pin == nullptr || !vertex->isDriver (network_)
896- || network_->isTopLevelPort (pin)) {
897- continue ;
898- }
899-
900- targets.push_back (
901- makePathDriverTarget (path, expanded, index, path_slack, *resizer_));
902- }
933+ collectExpandedPathDriverTargets (path, expanded, path_slack, targets);
934+
935+ // A latch-through path starts at latch Q in OpenSTA, with each latch D path
936+ // stored as side context. Expand those D paths separately so repair_timing
937+ // can optimize the logic that consumed the borrowed time.
938+ visitLatchFaninSegments (
939+ expanded,
940+ sta_,
941+ [&](const sta::Path* d_path, sta::PathExpanded& d_expanded) {
942+ collectExpandedPathDriverTargets (
943+ d_path, d_expanded, path_slack, targets);
944+ return false ;
945+ });
903946
904947 return targets;
905948}
@@ -1218,6 +1261,21 @@ set<const sta::Pin*> RepairTargetCollector::collectPinsByPathEndpoint(
12181261 }
12191262 }
12201263 }
1264+
1265+ const size_t old_size = viol_pins.size ();
1266+ visitLatchFaninSegments (
1267+ expanded, sta_, [&](const sta::Path*, sta::PathExpanded& d_expanded) {
1268+ collectExpandedPathDriverPins (d_expanded, viol_pins);
1269+ return false ;
1270+ });
1271+ if (viol_pins.size () > old_size) {
1272+ debugPrint (logger_,
1273+ RSZ ,
1274+ " violator_collector" ,
1275+ 4 ,
1276+ " Added {} latch D fanin pins from latch-through path" ,
1277+ viol_pins.size () - old_size);
1278+ }
12211279 debugPrint (logger_, RSZ , " violator_collector" , 5 , " \n " );
12221280 }
12231281
@@ -2206,7 +2264,6 @@ void RepairTargetCollector::setToEndpoint(int index)
22062264 current_endpoint_index_ = index;
22072265 const auto & end_slack_pair = violating_endpoints_[current_endpoint_index_];
22082266 current_endpoint_ = graph_->pinLoadVertex (end_slack_pair.first );
2209- current_end_original_slack_ = end_slack_pair.second ;
22102267}
22112268
22122269void RepairTargetCollector::setToStartpoint (int index)
@@ -2215,7 +2272,6 @@ void RepairTargetCollector::setToStartpoint(int index)
22152272 const auto & start_slack_pair
22162273 = violating_startpoints_[current_startpoint_index_];
22172274 current_startpoint_ = graph_->pinLoadVertex (start_slack_pair.first );
2218- // Note: For startpoints, we don't use current_end_original_slack_
22192275}
22202276
22212277void RepairTargetCollector::advanceToNextEndpoint ()
0 commit comments