@@ -436,39 +436,47 @@ sta::Slack RepairTargetCollector::getPathSlackByIndex(
436436 const sta::Pin* endpoint_pin,
437437 int path_index)
438438{
439+ // Worst path only: pure read via vertexWorstSlackPath, no findPathEnds /
440+ // ExceptionTo. All shipping callers pass 0; findPathEnds path below is k>1.
441+ if (path_index == 0 ) {
442+ sta::Path* path = worstSlackPathForPin (endpoint_pin);
443+ return path ? path->slack (search_) : static_cast <sta::Slack>(sta::INF );
444+ }
445+
439446 // Create ExceptionTo for this endpoint
440447 sta::PinSet* to_pins = new sta::PinSet (network_);
441448 to_pins->insert (endpoint_pin);
442- sta::ExceptionTo* to = sdc_ ->makeExceptionTo (to_pins,
449+ sta::ExceptionTo* to = sta_ ->makeExceptionTo (to_pins,
443450 nullptr ,
444451 nullptr ,
445452 sta::RiseFallBoth::riseFall (),
446- sta::RiseFallBoth::riseFall ());
453+ sta::RiseFallBoth::riseFall (),
454+ sdc_);
447455
448456 // Find paths to the endpoint - request only up to path_index+1 paths
449457 sta::StringSeq group_names;
450458 int num_paths_needed = path_index + 1 ;
451459 sta::PathEndSeq path_ends
452- = search_ ->findPathEnds (nullptr , // from
453- nullptr , // thrus
454- to, // to
455- false , // unconstrained
456- sta_->scenes (), // scene
457- sta::MinMaxAll::all (), // min_max
458- num_paths_needed, // group_path_count
459- num_paths_needed, // endpoint_path_count
460- false , // unique_pins
461- false , // unique_edges
462- -sta::INF , // slack_min
463- sta::INF , // slack_max
464- true , // sort_by_slack
465- group_names, // group_names
466- true ,
467- false ,
468- true ,
469- true ,
470- true ,
471- true ); // checks
460+ = sta_ ->findPathEnds (nullptr , // from
461+ nullptr , // thrus
462+ to, // to
463+ false , // unconstrained
464+ sta_->scenes (), // scene
465+ sta::MinMaxAll::all (), // min_max
466+ num_paths_needed, // group_path_count
467+ num_paths_needed, // endpoint_path_count
468+ false , // unique_pins
469+ false , // unique_edges
470+ -sta::INF , // slack_min
471+ sta::INF , // slack_max
472+ true , // sort_by_slack
473+ group_names, // group_names
474+ true ,
475+ false ,
476+ true ,
477+ true ,
478+ true ,
479+ true ); // checks
472480
473481 // Return the slack of the requested path index
474482 if (std::cmp_less (path_index, path_ends.size ())) {
@@ -919,6 +927,13 @@ void RepairTargetCollector::collectExpandedPathDriverPins(
919927 }
920928}
921929
930+ sta::Path* RepairTargetCollector::worstSlackPathForPin (
931+ const sta::Pin* endpoint_pin) const
932+ {
933+ sta::Vertex* endpoint = graph_->pinLoadVertex (endpoint_pin);
934+ return endpoint ? findWorstSlackPath (endpoint) : nullptr ;
935+ }
936+
922937std::vector<Target> RepairTargetCollector::collectPathDriverTargets (
923938 sta::Path* path,
924939 const sta::Slack path_slack) const
@@ -1138,74 +1153,69 @@ set<const sta::Pin*> RepairTargetCollector::collectPinsByPathEndpoint(
11381153 // Create a set to remove duplciates
11391154 set<const sta::Pin*> viol_pins;
11401155
1141- // This uses the old method for a single path at a time
1142- /* if (paths_per_endpoint == 1) {
1143- Vertex* end = graph_->pinDrvrVertex(endpoint_pin);
1144- Path* end_path = sta_->vertexWorstSlackPath(end, max_);
1145- PathExpanded expanded(end_path, sta_);
1146- if (expanded.size() > 1) {
1147- const int path_length = expanded.size();
1148- const int start_index = expanded.startIndex();
1149- for (int i = start_index; i < path_length; i++) {
1150- const Path* path = expanded.path(i);
1151- const Pin* path_pin = path->pin(sta_);
1152- Vertex* path_vertex = path->vertex(sta_);
1153- if (!path_vertex->isDriver(network_)
1154- || network_->isTopLevelPort(path_pin)) {
1155- continue;
1156- }
1157- viol_pins.insert(path_pin);
1158- debugPrint(logger_,
1159- RSZ,
1160- "violator_collector",
1161- 3,
1162- " - Pin: {}",
1163- network_->pathName(path_pin));
1164- }
1156+ // Worst path only: pure read via vertexWorstSlackPath, no findPathEnds /
1157+ // ExceptionTo. All shipping callers pass 1; findPathEnds path below is k>1.
1158+ if (paths_per_endpoint == 1 ) {
1159+ sta::Path* path = worstSlackPathForPin (endpoint_pin);
1160+ if (path == nullptr || path->slack (search_) > 0.0 ) {
11651161 return viol_pins;
11661162 }
1167- } else {
1168- // FIXME later
1163+ sta::PathExpanded expanded (path, sta_);
1164+ for (size_t i = 0 ; i < expanded.size (); i++) {
1165+ const sta::Pin* pin = expanded.path (i)->pin (graph_);
1166+ if (!network_->direction (pin)->isOutput () || network_->isTopLevelPort (pin)
1167+ || sta_->isClock (pin, sta_->cmdMode ())) {
1168+ continue ;
1169+ }
1170+ viol_pins.insert (pin);
1171+ }
1172+ // A latch-through path starts at latch Q in OpenSTA; expand the latch D
1173+ // fanin paths as well, matching the k>1 branch below.
1174+ visitLatchFaninSegments (
1175+ expanded, sta_, [&](const sta::Path*, sta::PathExpanded& d_expanded) {
1176+ collectExpandedPathDriverPins (d_expanded, viol_pins);
1177+ return false ;
1178+ });
11691179 return viol_pins;
11701180 }
1171- */
11721181
1173- // This code does not behave properly for single path case. At some points it
1174- // does not match the above vertexWorstSlackPath method. It seems to be
1175- // related to the use of the ExceptionTo object.
1182+ // The k>1 path below does not behave properly for the single path case: at
1183+ // some points it does not match the vertexWorstSlackPath fast path above. It
1184+ // seems to be related to the use of the ExceptionTo object.
11761185 // 1. Define the single endpoint for the path search.
11771186 sta::PinSet* to_pins = new sta::PinSet (network_);
11781187 to_pins->insert (endpoint_pin);
11791188 // The ExceptionTo object will be owned and deleted by the SDC.
1180- sta::ExceptionTo* to = sdc_ ->makeExceptionTo (to_pins,
1189+ sta::ExceptionTo* to = sta_ ->makeExceptionTo (to_pins,
11811190 nullptr ,
11821191 nullptr ,
11831192 sta::RiseFallBoth::riseFall (),
1184- sta::RiseFallBoth::riseFall ());
1193+ sta::RiseFallBoth::riseFall (),
1194+ sdc_);
11851195
11861196 // 2. Find paths to the endpoint.
11871197 sta::StringSeq group_names;
11881198 sta::PathEndSeq path_ends
1189- = search_ ->findPathEnds (nullptr , // from
1190- nullptr , // thrus
1191- to, // to
1192- false , // unconstrained
1193- sta_->scenes (), // scene
1194- sta::MinMaxAll::all (), // min_max
1195- paths_per_endpoint, // group_path_count
1196- paths_per_endpoint, // endpoint_path_count
1197- false , // unique_pins
1198- false , // unique_edges
1199- -sta::INF , // slack_min
1200- sta::INF , // slack_max
1201- true , // sort_by_slack
1202- group_names, // group_names
1203- true ,
1204- false ,
1205- true ,
1206- true ,
1207- true ,
1208- true ); // checks
1199+ = sta_ ->findPathEnds (nullptr , // from
1200+ nullptr , // thrus
1201+ to, // to
1202+ false , // unconstrained
1203+ sta_->scenes (), // scene
1204+ sta::MinMaxAll::all (), // min_max
1205+ paths_per_endpoint, // group_path_count
1206+ paths_per_endpoint, // endpoint_path_count
1207+ false , // unique_pins
1208+ false , // unique_edges
1209+ -sta::INF , // slack_min
1210+ sta::INF , // slack_max
1211+ true , // sort_by_slack
1212+ group_names, // group_names
1213+ true ,
1214+ false ,
1215+ true ,
1216+ true ,
1217+ true ,
1218+ true ); // checks
12091219
12101220 int path_num = 1 ;
12111221 for (const sta::PathEnd* path_end : path_ends) {
0 commit comments