@@ -253,6 +253,11 @@ static bool is_better_quality_routing(const vtr::vector<ClusterNetId,t_traceback
253
253
const WirelengthInfo& wirelength_info,
254
254
std::shared_ptr<const SetupHoldTimingInfo> timing_info);
255
255
256
+ static bool early_reconvergence_exit_heuristic (const t_router_opts& router_opts,
257
+ int itry_since_last_convergence,
258
+ std::shared_ptr<const SetupHoldTimingInfo> timing_info,
259
+ const RoutingMetrics& best_routing_metrics);
260
+
256
261
/* *********************** Subroutine definitions *****************************/
257
262
bool try_timing_driven_route (t_router_opts router_opts,
258
263
vtr::vector_map<ClusterNetId, float *> &net_delay,
@@ -357,6 +362,7 @@ bool try_timing_driven_route(t_router_opts router_opts,
357
362
float prev_iter_cumm_time = 0 ;
358
363
vtr::Timer iteration_timer;
359
364
int num_net_bounding_boxes_updated = 0 ;
365
+ int itry_since_last_convergence = -1 ;
360
366
for (itry = 1 ; itry <= router_opts.max_router_iterations ; ++itry) {
361
367
362
368
RouterStats router_iteration_stats;
@@ -381,6 +387,10 @@ bool try_timing_driven_route(t_router_opts router_opts,
381
387
route_timing_info = make_constant_timing_info (0 .);
382
388
}
383
389
390
+ if (itry_since_last_convergence >= 0 ) {
391
+ ++itry_since_last_convergence;
392
+ }
393
+
384
394
/*
385
395
* Route each net
386
396
*/
@@ -499,20 +509,33 @@ bool try_timing_driven_route(t_router_opts router_opts,
499
509
}
500
510
501
511
// Decrease pres_fac so that criticl connections will take more direct routes
502
- pres_fac = router_opts.initial_pres_fac ;
512
+ // Note that we use first_iter_pres_fac here (typically zero), and switch to
513
+ // use initial_pres_fac on the next iteration.
514
+ pres_fac = router_opts.first_iter_pres_fac ;
503
515
504
516
// Reduce timing tolerances to re-route more delay-suboptimal signals
505
- connections_inf.set_connection_criticality_tolerance (0.8 );
517
+ connections_inf.set_connection_criticality_tolerance (0.7 );
506
518
connections_inf.set_connection_delay_tolerance (1.01 );
507
519
508
520
++legal_convergence_count;
521
+ itry_since_last_convergence = 0 ;
509
522
510
523
VTR_ASSERT (routing_is_successful);
511
524
}
512
525
513
- // Have we converged the maximum number of times, or did not make any changes?
526
+ if (itry_since_last_convergence == 1 ) {
527
+ // We used first_iter_pres_fac when we started routing again
528
+ // after the first routing convergence. Since that is often zero,
529
+ // we want to set pres_fac to a reasonable (i.e. typically non-zero)
530
+ // value afterwards -- so it grows when multiplied by pres_fac_mult
531
+ pres_fac = router_opts.initial_pres_fac ;
532
+ }
533
+
534
+ // Have we converged the maximum number of times, did not make any changes, or does it seem
535
+ // unlikely additional convergences will improve QoR?
514
536
if (legal_convergence_count >= router_opts.max_convergence_count
515
- || router_iteration_stats.connections_routed == 0 ) {
537
+ || router_iteration_stats.connections_routed == 0
538
+ || early_reconvergence_exit_heuristic (router_opts, itry_since_last_convergence, timing_info, best_routing_metrics)) {
516
539
break ; // Done routing
517
540
}
518
541
@@ -526,7 +549,7 @@ bool try_timing_driven_route(t_router_opts router_opts,
526
549
527
550
// Estimate at what iteration we will converge to a legal routing
528
551
if (overuse_info.overused_nodes () > ROUTING_PREDICTOR_MIN_ABSOLUTE_OVERUSE_THRESHOLD) {
529
- // Only abort if we have a significant number of overused resources
552
+ // Only consider aborting if we have a significant number of overused resources
530
553
531
554
if (!std::isnan (est_success_iteration) && est_success_iteration > abort_iteration_threshold) {
532
555
VTR_LOG (" Routing aborted, the predicted iteration for a successful route (%.1f) is too high.\n " , est_success_iteration);
@@ -2516,3 +2539,26 @@ static bool is_better_quality_routing(const vtr::vector<ClusterNetId,t_traceback
2516
2539
// Finally, wirelength tie breaker
2517
2540
return wirelength_info.used_wirelength () < best_routing_metrics.used_wirelength ;
2518
2541
}
2542
+
2543
+ static bool early_reconvergence_exit_heuristic (const t_router_opts& router_opts,
2544
+ int itry_since_last_convergence,
2545
+ std::shared_ptr<const SetupHoldTimingInfo> timing_info,
2546
+ const RoutingMetrics& best_routing_metrics) {
2547
+ // Give-up on reconvergent routing if the CPD improvement after the
2548
+ // first iteration since convergence is small, compared to the best
2549
+ // CPD seen so far
2550
+ if (itry_since_last_convergence == 1 ) {
2551
+ float cpd_ratio = timing_info->setup_worst_negative_slack () / best_routing_metrics.sWNS ;
2552
+
2553
+ // Give up if we see less than a 1% CPD improvement,
2554
+ // after reducing pres_fac. Typically larger initial
2555
+ // improvements are needed to see an actual improvement
2556
+ // in final legal routing quality.
2557
+ if (cpd_ratio >= router_opts.reconvergence_cpd_threshold ) {
2558
+ VTR_LOG (" Giving up routing since additional routing convergences seem unlikely to improve quality (CPD ratio: %g)\n " , cpd_ratio);
2559
+ return true ; // Potential CPD improvement is small, don't spend run-time trying to improve it
2560
+ }
2561
+ }
2562
+
2563
+ return false ; // Don't give up
2564
+ }
0 commit comments