-
Notifications
You must be signed in to change notification settings - Fork 767
DRT: Add guide-based tiles flow and improve stubborn-tiles iteration control #9198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
feadfd8
3377bc8
51c7aa7
4387587
4128bf3
450fd46
9c57b8c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -608,7 +608,7 @@ std::unique_ptr<FlexDRWorker> FlexDR::createWorker(const int x_offset, | |
| namespace { | ||
| void printIteration(utl::Logger* logger, | ||
| const int iter, | ||
| const bool stubborn_flow) | ||
| const std::string& flow_name) | ||
| { | ||
| std::string suffix; | ||
| if (iter == 1 || (iter > 20 && iter % 10 == 1)) { | ||
|
|
@@ -620,12 +620,7 @@ void printIteration(utl::Logger* logger, | |
| } else { | ||
| suffix = "th"; | ||
| } | ||
| logger->info(DRT, | ||
| 195, | ||
| "Start {}{} {} iteration.", | ||
| iter, | ||
| suffix, | ||
| stubborn_flow ? "stubborn tiles" : "optimization"); | ||
| logger->info(DRT, 195, "Start {}{} {} iteration.", iter, suffix, flow_name); | ||
| } | ||
|
|
||
| void printIterationProgress(utl::Logger* logger, | ||
|
|
@@ -1063,23 +1058,15 @@ std::vector<std::vector<int>> getWorkerBatchesBoxes( | |
| return {}; | ||
| } | ||
| std::vector<odb::Rect> boxes_max; | ||
| boxes_max.resize(expanded_boxes.size()); | ||
| int id = 0; | ||
| for (auto& boxes : expanded_boxes) { | ||
| bool first = true; | ||
| for (auto& box : boxes) { | ||
| auto min_idx = box.ll(); | ||
| auto max_idx = box.ur(); | ||
| odb::Rect rect(design->getTopBlock()->getGCellBox(min_idx).ll(), | ||
| design->getTopBlock()->getGCellBox(max_idx).ur()); | ||
| boxes_max[id].mergeInit(); | ||
| for (auto rect : boxes) { | ||
| rect.bloat(bloating_dist, rect); | ||
| if (first) { | ||
| boxes_max.emplace_back(rect); | ||
| first = false; | ||
| continue; | ||
| } | ||
| boxes_max[id].merge(rect); | ||
| } | ||
| id++; | ||
| ++id; | ||
| } | ||
| std::vector<std::vector<int>> batches; | ||
| batches.push_back({0}); | ||
|
|
@@ -1114,15 +1101,37 @@ void FlexDR::stubbornTilesFlow(const SearchRepairArgs& args, | |
| if (graphics_) { | ||
| graphics_->startIter(iter_, router_cfg_); | ||
| } | ||
| control_.skip_till_changed = false; | ||
| control_.tried_guide_flow = false; | ||
| std::vector<odb::Rect> drv_boxes; | ||
| for (const auto& marker : getDesign()->getTopBlock()->getMarkers()) { | ||
| auto box = marker->getBBox(); | ||
| drv_boxes.push_back(getDRVBBox(box)); | ||
| } | ||
| auto merged_boxes = stub_tiles::mergeBoxes(drv_boxes); | ||
| auto expanded_boxes = stub_tiles::expandBoxes(merged_boxes); | ||
|
|
||
| // Convert gcell indices to actual coordinates | ||
| std::vector<std::set<odb::Rect>> expanded_boxes_coords; | ||
| expanded_boxes_coords.reserve(expanded_boxes.size()); | ||
| std::ranges::transform( | ||
| expanded_boxes, | ||
| std::back_inserter(expanded_boxes_coords), | ||
| [this](const auto& box_set) { | ||
| std::set<odb::Rect> coord_set; | ||
| std::ranges::transform( | ||
| box_set, | ||
| std::inserter(coord_set, coord_set.end()), | ||
| [this](const auto& gcell_box) { | ||
| return odb::Rect( | ||
| getDesign()->getTopBlock()->getGCellBox(gcell_box.ll()).ll(), | ||
| getDesign()->getTopBlock()->getGCellBox(gcell_box.ur()).ur()); | ||
| }); | ||
| return coord_set; | ||
| }); | ||
|
|
||
| auto route_boxes_batches = stub_tiles::getWorkerBatchesBoxes( | ||
| getDesign(), expanded_boxes, router_cfg_->MTSAFEDIST); | ||
| getDesign(), expanded_boxes_coords, router_cfg_->MTSAFEDIST); | ||
| std::vector<frUInt4> drc_costs | ||
| = {args.workerDRCCost, args.workerDRCCost / 2, args.workerDRCCost * 2}; | ||
| std::vector<frUInt4> marker_costs = {args.workerMarkerCost, | ||
|
|
@@ -1134,12 +1143,7 @@ void FlexDR::stubbornTilesFlow(const SearchRepairArgs& args, | |
| for (int batch_id = 0; batch_id < route_boxes_batches.size(); batch_id++) { | ||
| auto& batch = route_boxes_batches[batch_id]; | ||
| for (const auto worker_id : batch) { | ||
| for (auto gcell_box : expanded_boxes[worker_id]) { | ||
| auto min_idx = gcell_box.ll(); | ||
| auto max_idx = gcell_box.ur(); | ||
| odb::Rect route_box( | ||
| getDesign()->getTopBlock()->getGCellBox(min_idx).ll(), | ||
| getDesign()->getTopBlock()->getGCellBox(max_idx).ur()); | ||
| for (const auto& route_box : expanded_boxes_coords[worker_id]) { | ||
| for (auto drc_cost : drc_costs) { | ||
| for (auto marker_cost : marker_costs) { | ||
| auto worker_args = args; | ||
|
|
@@ -1181,6 +1185,88 @@ void FlexDR::stubbornTilesFlow(const SearchRepairArgs& args, | |
| } | ||
| } | ||
|
|
||
| void FlexDR::guideTilesFlow(const SearchRepairArgs& args, | ||
| IterationProgress& iter_prog) | ||
| { | ||
| if (graphics_) { | ||
| graphics_->startIter(iter_, router_cfg_); | ||
| } | ||
| control_.tried_guide_flow = true; | ||
| std::vector<odb::Rect> workers; | ||
| for (const auto& marker : getDesign()->getTopBlock()->getMarkers()) { | ||
| for (auto src : marker->getSrcs()) { | ||
| if (src->typeId() == frcNet) { | ||
| auto net = static_cast<frNet*>(src); | ||
| if (net->getOrigGuides().empty()) { | ||
| continue; | ||
| } | ||
| for (const auto& guide : net->getOrigGuides()) { | ||
| if (!guide.getBBox().intersects(marker->getBBox())) { | ||
| continue; | ||
| } | ||
| workers.push_back(guide.getBBox()); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| if (workers.empty()) { | ||
| iter_prog.total_num_workers = 1; | ||
| iter_prog.cnt_done_workers = 1; | ||
| return; | ||
| } | ||
|
|
||
| for (auto itr1 = workers.begin(); itr1 != workers.end(); ++itr1) { | ||
| for (auto itr2 = itr1 + 1; itr2 != workers.end(); ++itr2) { | ||
| if (itr1->getDir() == itr2->getDir() && itr1->intersects(*itr2)) { | ||
| itr1->merge(*itr2); | ||
| workers.erase(itr2); | ||
| itr2 = itr1; | ||
| } | ||
| } | ||
| } | ||
|
Comment on lines
+1218
to
+1226
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The nested loop for merging worker rectangles is functionally correct, but its implementation using A for (auto itr1 = workers.begin(); itr1 != workers.end(); ++itr1) {
restart_inner_loop:
for (auto itr2 = itr1 + 1; itr2 != workers.end(); ++itr2) {
if (itr1->getDir() == itr2->getDir() && itr1->intersects(*itr2)) {
itr1->merge(*itr2);
workers.erase(itr2);
goto restart_inner_loop;
}
}
} |
||
| std::vector<std::set<odb::Rect>> boxes_set; | ||
| boxes_set.reserve(workers.size()); | ||
| for (auto& worker : workers) { | ||
| boxes_set.push_back({worker}); | ||
| } | ||
| auto route_boxes_batches = stub_tiles::getWorkerBatchesBoxes( | ||
| getDesign(), boxes_set, router_cfg_->MTSAFEDIST); | ||
| std::vector<std::vector<std::unique_ptr<FlexDRWorker>>> workers_batches( | ||
| route_boxes_batches.size()); | ||
| iter_prog.total_num_workers = 0; | ||
| for (int batch_id = 0; batch_id < route_boxes_batches.size(); batch_id++) { | ||
| auto& batch = route_boxes_batches[batch_id]; | ||
| for (const auto worker_id : batch) { | ||
| for (auto route_box : boxes_set[worker_id]) { | ||
| workers_batches[batch_id].emplace_back( | ||
| createWorker(0, 0, args, route_box)); | ||
| workers_batches[batch_id].back()->setWorkerId(worker_id); | ||
| iter_prog.total_num_workers++; | ||
| } | ||
| } | ||
| } | ||
| bool changed = false; | ||
| omp_set_num_threads(router_cfg_->MAX_THREADS); | ||
| for (auto& batch : workers_batches) { | ||
| processWorkersBatch(batch, iter_prog); | ||
| std::map<int, FlexDRWorker*> | ||
| worker_best_result; // holds the best worker in results | ||
| for (auto& worker : batch) { | ||
| const int worker_id = worker->getWorkerId(); | ||
| if (worker_best_result.find(worker_id) == worker_best_result.end() | ||
| || worker->getBestNumMarkers() | ||
| < worker_best_result[worker_id]->getBestNumMarkers()) { | ||
| worker_best_result[worker_id] = worker.get(); | ||
| } | ||
| } | ||
| for (auto [_, worker] : worker_best_result) { | ||
| changed | ||
| |= (worker->end(getDesign()) | ||
| && worker->getBestNumMarkers() != worker->getInitNumMarkers()); | ||
| } | ||
| batch.clear(); | ||
| } | ||
| } | ||
| void FlexDR::optimizationFlow(const SearchRepairArgs& args, | ||
| IterationProgress& iter_prog) | ||
| { | ||
|
|
@@ -1275,11 +1361,28 @@ void FlexDR::searchRepair(const SearchRepairArgs& args) | |
| const bool stubborn_flow = num_drvs <= 11 && ripupMode != RipUpMode::ALL | ||
| && ripupMode != RipUpMode::INCR | ||
| && !control_.fixing_max_spacing; | ||
| const bool skip_stubborn_flow | ||
| = stubborn_flow && control_.skip_till_changed | ||
| && args.isEqualIgnoringSizeAndOffset(control_.last_args); | ||
| const bool guides_flow = skip_stubborn_flow && !control_.tried_guide_flow; | ||
|
|
||
| if (router_cfg_->VERBOSE > 0) { | ||
| printIteration(logger_, iter_, stubborn_flow); | ||
| std::string flow_name; | ||
| if (guides_flow) { | ||
| flow_name = "guides tiles"; | ||
| } else if (stubborn_flow) { | ||
| flow_name = "stubborn tiles"; | ||
| } else { | ||
| flow_name = "optimization"; | ||
| } | ||
| printIteration(logger_, iter_, flow_name); | ||
| } | ||
| if (stubborn_flow) { | ||
| stubbornTilesFlow(args, iter_prog); | ||
| if (guides_flow) { | ||
| guideTilesFlow(args, iter_prog); | ||
| } else if (stubborn_flow) { | ||
| if (!skip_stubborn_flow) { | ||
| stubbornTilesFlow(args, iter_prog); | ||
| } | ||
| } else { | ||
| optimizationFlow(args, iter_prog); | ||
| } | ||
|
|
@@ -1890,14 +1993,14 @@ int FlexDR::main() | |
| } | ||
| } | ||
| if (control_.skip_till_changed | ||
| && args.isEqualIgnoringSizeAndOffset(control_.last_args)) { | ||
| && args.isEqualIgnoringSizeAndOffset(control_.last_args) | ||
| && control_.tried_guide_flow) { | ||
| if (router_cfg_->VERBOSE > 0) { | ||
| logger_->info(DRT, 200, "Skipping iteration {}", iter_); | ||
| } | ||
| ++iter_; | ||
| continue; | ||
| } | ||
| control_.skip_till_changed = false; | ||
| searchRepair(args); | ||
| if (getDesign()->getTopBlock()->getNumMarkers() == 0) { | ||
| break; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be
itr1oritr1+1as in the loop initialization?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be
itr1. Once the loop finishes an iteration and goes back to the for statement, the increment step will advance it toitr1+1.