Skip to content

Commit f9e2e01

Browse files
authored
Merge pull request #10229 from The-OpenROAD-Project-staging/multicore_congestion
grt: multicore congestion handling
2 parents c5dc64a + 2be8781 commit f9e2e01

20 files changed

Lines changed: 3540 additions & 366 deletions

src/OpenRoad.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,9 @@ void OpenRoad::setThreadCount(int threads, bool print_info)
668668

669669
// place limits on tools with threads
670670
sta_->setThreadCount(threads_);
671+
if (global_router_ != nullptr) {
672+
global_router_->setNumThreads(threads_);
673+
}
671674
}
672675

673676
void OpenRoad::setThreadCount(const char* threads, bool print_info)

src/grt/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ global_route
2626
[-critical_nets_percentage percent]
2727
[-skip_large_fanout_nets fanout]
2828
[-allow_congestion]
29+
[-snapshot_batched_width width]
2930
[-verbose]
3031
[-start_incremental]
3132
[-end_incremental]
@@ -52,6 +53,7 @@ global_route
5253
| `-use_cugr` | This flag run GRT using CUGR as the router solver. NOTE: this is not ready for production. |
5354
| `-resistance_aware` | This flag enables resistance-aware layer assignment and 3D routing. NOTE: this is not ready for production. |
5455
| `-infinite_cap` | Enables "infinite" gcell capacity for testing purpose. NOTE: this is not recommended for production flows. |
56+
| `-snapshot_batched_width` | Set the semantic width of snapshot-batched routing (max batches per wave). The default is `0`, preserving the non-batched behavior. Set a positive integer to enable batched routing; allowed values are integers `[1, MAX_INT]`. Execution width still follows `set_thread_count`. NOTE: this is not recommended for production flows; it is intended for exploration and research projects. |
5557

5658
### Set Routing Layers
5759

src/grt/include/grt/GlobalRouter.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,16 @@ class GlobalRouter
155155
void setGridOrigin(int x, int y);
156156
void setAllowCongestion(bool allow_congestion);
157157
void setResistanceAware(bool resistance_aware);
158+
void setSnapshotBatchedWidth(int snapshot_batched_width);
159+
int getSnapshotBatchedWidth() const;
160+
int getSnapshotBatchCount() const;
158161
void setMacroExtension(int macro_extension);
159162
void setUseCUGR(bool use_cugr) { use_cugr_ = use_cugr; };
160163
void setSkipLargeFanoutNets(int skip_large_fanout)
161164
{
162165
skip_large_fanout_ = skip_large_fanout;
163166
};
167+
void setNumThreads(int num_threads);
164168

165169
void setInfiniteCapacity(bool infinite_capacity);
166170

@@ -531,6 +535,8 @@ class GlobalRouter
531535
int congestion_report_iter_step_;
532536
bool allow_congestion_;
533537
bool resistance_aware_{false};
538+
int snapshot_batched_width_{0};
539+
int num_threads_;
534540
std::vector<int> vertical_capacities_;
535541
std::vector<int> horizontal_capacities_;
536542
int macro_extension_;

src/grt/src/GlobalRouter.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ GlobalRouter::GlobalRouter(utl::Logger* logger,
8787
adjustment_(0.0),
8888
congestion_report_iter_step_(0),
8989
allow_congestion_(false),
90+
num_threads_(1),
9091
macro_extension_(0),
9192
initialized_(false),
9293
total_diodes_count_(0),
@@ -110,6 +111,28 @@ GlobalRouter::GlobalRouter(utl::Logger* logger,
110111
cugr_ = new CUGR(db_, logger_, service_registry_, stt_builder_, sta_);
111112
}
112113

114+
void GlobalRouter::setNumThreads(int num_threads)
115+
{
116+
num_threads_ = num_threads;
117+
fastroute_->setNumThreads(num_threads_);
118+
}
119+
120+
void GlobalRouter::setSnapshotBatchedWidth(int snapshot_batched_width)
121+
{
122+
snapshot_batched_width_ = snapshot_batched_width;
123+
fastroute_->setSnapshotBatchedWidth(snapshot_batched_width_);
124+
}
125+
126+
int GlobalRouter::getSnapshotBatchedWidth() const
127+
{
128+
return fastroute_->getSnapshotBatchedWidth();
129+
}
130+
131+
int GlobalRouter::getSnapshotBatchCount() const
132+
{
133+
return fastroute_->getSnapshotBatchCount();
134+
}
135+
113136
void GlobalRouter::initGui(
114137
gui::HeatMapSourceHandle routing_congestion_data_source,
115138
gui::HeatMapSourceHandle routing_congestion_data_source_rudy)
@@ -2327,6 +2350,7 @@ void GlobalRouter::configFastRoute()
23272350
fastroute_->setOverflowIterations(congestion_iterations_);
23282351
fastroute_->setCongestionReportIterStep(congestion_report_iter_step_);
23292352
fastroute_->setResistanceAware(resistance_aware_);
2353+
fastroute_->setSnapshotBatchedWidth(snapshot_batched_width_);
23302354

23312355
if (congestion_file_name_ != nullptr) {
23322356
fastroute_->setCongestionReportFile(congestion_file_name_);
@@ -3848,9 +3872,17 @@ int GlobalRouter::computeNetWirelength(odb::dbNet* db_net)
38483872

38493873
void GlobalRouter::computeWirelength()
38503874
{
3875+
std::vector<odb::dbNet*> routed_nets;
3876+
routed_nets.reserve(routes_.size());
3877+
for (const auto& [db_net, route] : routes_) {
3878+
routed_nets.push_back(db_net);
3879+
}
3880+
38513881
int64_t total_wirelength = 0;
3852-
for (auto& net_route : routes_) {
3853-
total_wirelength += computeNetWirelength(net_route.first);
3882+
#pragma omp parallel for num_threads(num_threads_) \
3883+
reduction(+ : total_wirelength)
3884+
for (int i = 0; i < static_cast<int>(routed_nets.size()); i++) {
3885+
total_wirelength += computeNetWirelength(routed_nets[i]);
38543886
}
38553887
logger_->metric("global_route__wirelength",
38563888
total_wirelength / block_->getDefUnits());

src/grt/src/GlobalRouter.i

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,24 @@ set_resistance_aware(bool resistance_aware)
110110
getGlobalRouter()->setResistanceAware(resistance_aware);
111111
}
112112

113+
void
114+
set_snapshot_batched_width(int snapshot_batched_width)
115+
{
116+
getGlobalRouter()->setSnapshotBatchedWidth(snapshot_batched_width);
117+
}
118+
119+
int
120+
get_snapshot_batched_width()
121+
{
122+
return getGlobalRouter()->getSnapshotBatchedWidth();
123+
}
124+
125+
int
126+
get_snapshot_batch_count()
127+
{
128+
return getGlobalRouter()->getSnapshotBatchCount();
129+
}
130+
113131
void
114132
set_critical_nets_percentage(float criticalNetsPercentage)
115133
{
@@ -178,6 +196,8 @@ void end_incremental()
178196
void
179197
global_route()
180198
{
199+
const int num_threads = ord::OpenRoad::openRoad()->getThreadCount();
200+
getGlobalRouter()->setNumThreads(num_threads);
181201
getGlobalRouter()->globalRoute(true);
182202
}
183203

src/grt/src/GlobalRouter.tcl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ sta::define_cmd_args "global_route" {[-guide_file out_file] \
148148
[-critical_nets_percentage percent] \
149149
[-skip_large_fanout_nets fanout] \
150150
[-allow_congestion] \
151+
[-snapshot_batched_width width] \
151152
[-verbose] \
152153
[-start_incremental] \
153154
[-end_incremental] \
@@ -159,8 +160,8 @@ sta::define_cmd_args "global_route" {[-guide_file out_file] \
159160
proc global_route { args } {
160161
sta::parse_key_args "global_route" args \
161162
keys {-guide_file -congestion_iterations -congestion_report_file \
162-
-grid_origin -critical_nets_percentage -congestion_report_iter_step\
163-
-skip_large_fanout_nets
163+
-grid_origin -critical_nets_percentage -congestion_report_iter_step \
164+
-skip_large_fanout_nets -snapshot_batched_width
164165
} \
165166
flags {-allow_congestion -resistance_aware -infinite_cap -verbose -start_incremental \
166167
-end_incremental -use_cugr}
@@ -229,6 +230,15 @@ proc global_route { args } {
229230
set resistance_aware [info exists flags(-resistance_aware)]
230231
grt::set_resistance_aware $resistance_aware
231232

233+
if { [info exists keys(-snapshot_batched_width)] } {
234+
set snapshot_batched_width $keys(-snapshot_batched_width)
235+
sta::check_positive_integer "-snapshot_batched_width" \
236+
$snapshot_batched_width
237+
} else {
238+
set snapshot_batched_width 0
239+
}
240+
grt::set_snapshot_batched_width $snapshot_batched_width
241+
232242
set infinite_cap [info exists flags(-infinite_cap)]
233243
grt::set_infinite_cap $infinite_cap
234244

src/grt/src/fastroute/include/FastRoute.h

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ class FastRouteCore
169169
NetRouteMap run();
170170
int totalOverflow() const { return total_overflow_; }
171171
bool has2Doverflow() const { return has_2D_overflow_; }
172+
int getSnapshotBatchCount() const { return snapshot_batch_count_; }
172173
void getBlockage(odb::dbTechLayer* layer,
173174
int x,
174175
int y,
@@ -244,6 +245,12 @@ class FastRouteCore
244245
void setCongestionReportFile(const char* congestion_file_name);
245246
void setGridMax(int x_max, int y_max);
246247
void setDetourPenalty(int penalty);
248+
void setNumThreads(int num_threads) { num_threads_ = num_threads; }
249+
void setSnapshotBatchedWidth(int snapshot_batched_width)
250+
{
251+
snapshot_batched_width_ = snapshot_batched_width;
252+
}
253+
int getSnapshotBatchedWidth() const { return snapshot_batched_width_; }
247254
void getCongestionNets(std::set<odb::dbNet*>& congestion_nets);
248255
void computeCongestionInformation();
249256
std::vector<int> getOriginalResources();
@@ -326,6 +333,24 @@ class FastRouteCore
326333
int L,
327334
const CostParams& cost_params,
328335
float& slack_th);
336+
void mazeRouteMSMDSequential(int iter,
337+
int expand,
338+
int ripup_threshold,
339+
int maze_edge_threshold,
340+
bool ordering,
341+
int via,
342+
int L,
343+
const CostParams& cost_params,
344+
float& slack_th);
345+
bool runSnapshotBatchedMazeRoute(int iter,
346+
int expand,
347+
int ripup_threshold,
348+
int maze_edge_threshold,
349+
bool ordering,
350+
int via,
351+
int L,
352+
const CostParams& cost_params,
353+
float& slack_th);
329354
void convertToMazeroute();
330355
int getOverflow2D(int* maxOverflow);
331356
int getOverflow2Dmaze(int* maxOverflow, int* tUsage);
@@ -621,6 +646,47 @@ class FastRouteCore
621646
void copyBR();
622647
void copyRS();
623648
void freeRR();
649+
std::vector<int> getMazeRouteNetOrder(bool ordering, float& slack_th);
650+
bool hasNonSoftNdrNets() const;
651+
int resolveSnapshotExecutionThreads(int work_items) const;
652+
int resolveSnapshotWaveSize(int available_batch_count) const;
653+
int resolveSnapshotBaseBatchSize(int net_count) const;
654+
bool useSnapshotBatchRouting(int net_count) const;
655+
int resolveSnapshotBatchIterationLimit(int net_count) const;
656+
bool useSnapshotBatchRoutingForIteration(int iter, int net_count) const;
657+
int resolveSnapshotNetsForBatch(int iter, int net_count) const;
658+
std::unique_ptr<FastRouteCore> buildSnapshotBatchWorker() const;
659+
void syncSnapshotBatchWorker(const FastRouteCore& snapshot,
660+
const std::vector<int>& batch_net_ids);
661+
void applySnapshotBatchRoute(int net_id, StTree&& sttree);
662+
void updatePlanarNetUsage(const StTree& sttree, FrNet* net, int edge_cost);
663+
void resetSnapshotBatchStats();
664+
665+
// Timing data collected during run(), reported via reportRunMetrics().
666+
struct RunTimings
667+
{
668+
double total = 0.0;
669+
double initial_rsmt = 0.0;
670+
double route_l = 0.0;
671+
double congestion_rsmt = 0.0;
672+
double new_route_l = 0.0;
673+
double spiral = 0.0;
674+
double route_z = 0.0;
675+
double monotonic = 0.0;
676+
double overflow_iterations = 0.0;
677+
double finalization = 0.0;
678+
};
679+
void reportRunMetrics(const RunTimings& timings,
680+
int num_vias,
681+
int final_length);
682+
683+
// Returns true if the overflow loop should break due to snapshot
684+
// convergence patience being exhausted.
685+
bool checkSnapshotConvergence(int past_cong,
686+
int& bmfl,
687+
int& bwcnt,
688+
int iter,
689+
int snapshot_batch_count_before);
624690
int edgeShift(stt::Tree& t, int net);
625691
int edgeShiftNew(stt::Tree& t, int net);
626692

@@ -635,6 +701,23 @@ class FastRouteCore
635701
static const int BIG_INT = 1e9; // big integer used as infinity
636702
static const int HCOST = 5000;
637703

704+
// Snapshot-batched routing constants.
705+
// Nets are partitioned into batches and routed in parallel waves against
706+
// a frozen graph snapshot. The user-supplied snapshot_batched_width_
707+
// controls the maximum batches per wave (independent of thread count) and
708+
// gates the minimum routable net count (2 * width) needed to attempt
709+
// batching.
710+
//
711+
// kSnapshotLowOverflowForSerialCleanup /
712+
// kSnapshotLowMaxOverflowForSerialCleanup:
713+
// overflow thresholds below which batching is disabled for the run,
714+
// because the design is already near-converged.
715+
// kSnapshotCleanupPatience: how many non-improving iterations to tolerate
716+
// in the snapshot cleanup phase before breaking.
717+
static constexpr int kSnapshotLowOverflowForSerialCleanup = 1500;
718+
static constexpr int kSnapshotLowMaxOverflowForSerialCleanup = 32;
719+
static constexpr int kSnapshotCleanupPatience = 12;
720+
638721
int max_degree_;
639722
std::vector<int> cap_per_layer_;
640723
std::vector<int> usage_per_layer_;
@@ -647,6 +730,12 @@ class FastRouteCore
647730
std::string congestion_file_name_;
648731
std::vector<odb::dbTechLayerDir> layer_directions_;
649732
std::vector<odb::dbTechLayer*> db_layers_;
733+
int num_threads_;
734+
// When false, nets_ contains borrowed pointers from a parent
735+
// FastRouteCore (snapshot-batch workers). Workers must not outlive
736+
// the parent's nets_ lifetime.
737+
bool owns_nets_;
738+
int snapshot_batched_width_;
650739
int x_range_;
651740
int y_range_;
652741

@@ -746,6 +835,15 @@ class FastRouteCore
746835

747836
std::vector<int> net_ids_;
748837

838+
// Maze 2D variables
839+
std::vector<bool> pop_heap2_2D_;
840+
std::vector<double*> src_heap_2D_;
841+
std::vector<double*> dest_heap_2D_;
842+
multi_array<double, 2> d1_2D_;
843+
multi_array<double, 2> d2_2D_;
844+
std::vector<bool> visited_2D_;
845+
std::vector<int> queue_2D_;
846+
749847
// Maze 3D variables
750848
multi_array<Direction, 3> directions_3D_;
751849
multi_array<int, 3> corr_edge_3D_;
@@ -756,6 +854,15 @@ class FastRouteCore
756854
multi_array<int, 3> d1_3D_;
757855
multi_array<int, 3> d2_3D_;
758856
multi_array<int, 3> path_len_3D_;
857+
double snapshot_batch_sync_time_ = 0.0;
858+
double snapshot_batch_route_time_ = 0.0;
859+
double snapshot_batch_apply_time_ = 0.0;
860+
int snapshot_batch_count_ = 0;
861+
int snapshot_batch_net_count_ = 0;
862+
int snapshot_batch_wave_count_ = 0;
863+
bool snapshot_batch_disabled_for_run_ = false;
864+
bool snapshot_cleanup_active_ = false;
865+
bool has_non_soft_ndr_nets_ = false;
759866
int detour_penalty_;
760867
};
761868

src/grt/src/fastroute/include/Graph2D.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class Graph2D
5555
void init(int x_grid, int y_grid, int num_layers, utl::Logger* logger);
5656
void InitEstUsage();
5757
void InitLastUsage(int upType);
58+
void copyRoutingStateFrom(const Graph2D& other, bool include_ndr_state);
5859
void clear();
5960
void clearUsed();
6061
bool hasEdges() const;

0 commit comments

Comments
 (0)