Skip to content

Refactor TA files and format and document TA support files.#9677

Closed
alokkumardalei-wq wants to merge 4 commits into
The-OpenROAD-Project:masterfrom
alokkumardalei-wq:drt_refactor_ta
Closed

Refactor TA files and format and document TA support files.#9677
alokkumardalei-wq wants to merge 4 commits into
The-OpenROAD-Project:masterfrom
alokkumardalei-wq:drt_refactor_ta

Conversation

@alokkumardalei-wq

@alokkumardalei-wq alokkumardalei-wq commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

What I have resolve with this PR?

Fixes #5614 .
I have:

  • Refactored TA initialization and assignment logic into smaller helpers to reduce complexity.
  • Cleaned up TA support code for readability and Google-style C++ consistency.
  • No intended functional change.

What got resolved?

  • TA init/assign refactor in FlexTA_init.cpp and FlexTA_assign.cpp.
  • Readability/style cleanup in TA support files:

FlexTA.cpp

FlexTA_end.cpp

FlexTA_graphics.cpp

FlexTA_rq.cpp

  • FlexTA.h updated only for private helper declarations required by the refactor.

Validation

bazel build //src/drt:drt

Expected output:

INFO: Invocation ID: e7872132-7f52-49ff-99f5-a2d068795b26
Computing main repo mapping: 
Loading: 
Loading: 0 packages loaded
Analyzing: target //src/drt:drt (0 packages loaded, 0 targets configured)
Analyzing: target //src/drt:drt (0 packages loaded, 0 targets configured)

INFO: Analyzed target //src/drt:drt (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //src/drt:drt up-to-date:
  bazel-bin/src/drt/libdrt.a
INFO: Elapsed time: 0.483s, Critical Path: 0.23s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
bazel test //src/drt/test:ta_ap_aligned-tcl_test //src/drt/test:ta_pin_aligned-tcl_test --test_output=errors

Expected output:

INFO: Invocation ID: 2e1a3c4f-bfff-4255-a163-37cabec69363
Computing main repo mapping: 
Loading: 
Loading: 0 packages loaded
Analyzing: 2 targets (0 packages loaded, 0 targets configured)
Analyzing: 2 targets (0 packages loaded, 0 targets configured)

DEBUG: /Users/alokkumardalei/Desktop/open-road/OpenROAD/bazel/notification.bzl:11:14: 
================================================================================
  NOTIFICATION: Use --config=opt to build with LTO (Link Time Optimization)
                and get better performance at the expense of longer build time.
================================================================================
INFO: Analyzed 2 targets (0 packages loaded, 1293 targets configured).
[2,658 / 6,476] checking cached actions
[6,476 / 6,478] 1 / 2 tests; checking cached actions
INFO: Found 2 test targets...
INFO: Elapsed time: 5.022s, Critical Path: 1.98s
INFO: 1 process: 6144 action cache hit, 1 internal.
INFO: Build completed successfully, 1 total action
//src/drt/test:ta_ap_aligned-tcl_test                           (cached) PASSED in 1.9s
//src/drt/test:ta_pin_aligned-tcl_test                          (cached) PASSED in 1.9s

Executed 0 out of 2 tests: 2 tests pass.
bazel test //src/drt/test:obstruction-tcl_test //src/drt/test:top_level_term-tcl_test //src/drt/test:via_access_layer-tcl_test --test_output=errors

Expected output:

INFO: Invocation ID: 25b71343-b821-4ae3-9af9-ed248524dd33
Computing main repo mapping: 
Loading: 
Loading: 0 packages loaded
Analyzing: 3 targets (0 packages loaded, 0 targets configured)
Analyzing: 3 targets (0 packages loaded, 0 targets configured)

INFO: Analyzed 3 targets (0 packages loaded, 6 targets configured).
INFO: Found 3 test targets...
INFO: Elapsed time: 0.429s, Critical Path: 0.22s
INFO: 1 process: 18 action cache hit, 1 internal.
INFO: Build completed successfully, 1 total action
//src/drt/test:obstruction-tcl_test                             (cached) PASSED in 0.4s
//src/drt/test:top_level_term-tcl_test                          (cached) PASSED in 0.4s
//src/drt/test:via_access_layer-tcl_test                        (cached) PASSED in 0.5s

Executed 0 out of 3 tests: 3 tests pass.
bazel test //src/drt/test:gc_unittest --test_output=errors

Expected output:

INFO: Invocation ID: bbceebf3-c928-4522-bf70-066aadb14fed
Computing main repo mapping: 
Loading: 
Loading: 0 packages loaded
Analyzing: target //src/drt/test:gc_unittest (0 packages loaded, 0 targets configured)
Analyzing: target //src/drt/test:gc_unittest (0 packages loaded, 0 targets configured)

INFO: Analyzed target //src/drt/test:gc_unittest (0 packages loaded, 3324 targets configured).
INFO: Found 1 test target...
Target //src/drt/test:gc_unittest up-to-date:
  bazel-bin/src/drt/test/gc_unittest
INFO: Elapsed time: 1.008s, Critical Path: 0.31s
INFO: 1 process: 1541 action cache hit, 1 internal.
INFO: Build completed successfully, 1 total action
//src/drt/test:gc_unittest                                      (cached) PASSED in 0.6s

Executed 0 out of 1 test: 1 test passes.
There were tests whose specified size is too big. Use the --test_verbose_timeout_warnings command line option to see which ones these are.

ispd tests:

bazel test //src/drt/test:ispd18_sample-tcl_test --test_output=errors

Run this command.

Expected output before (refactor):

Differences found at line 58.
      + ROUTED Metal2 ( 92200 73530 ) ( * 77710 )
      + ROUTED Metal2 ( 92200 73530 ) ( * 78470 )
Exitcode:  0
INFO: Build completed, 1 test FAILED
Executed 1 out of 1 test: 1 fails locally.

Expected output after (refactor):

bazel test //src/drt/test:ispd18_sample-tcl_test --test_output=errors
Differences found at line 58.
      + ROUTED Metal2 ( 92200 73530 ) ( * 77710 )
      + ROUTED Metal2 ( 92200 73530 ) ( * 78470 )
Exitcode:  0
INFO: Build completed, 1 test FAILED
Executed 1 out of 1 test: 1 fails locally.

We found that in both the cases the output is same and it's failing.
Why??
These ispd tests are failing because the test framework does a strict text diff against golden DEF files and therefore it is showing same output in both the cases.

@alokkumardalei-wq alokkumardalei-wq marked this pull request as draft March 6, 2026 16:31
@alokkumardalei-wq alokkumardalei-wq marked this pull request as ready for review March 6, 2026 16:31

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a significant refactoring of the track assignment (TA) logic. It successfully breaks down large, complex functions into smaller, more manageable helpers, which greatly improves code readability and maintainability. The changes also enforce a consistent coding style, such as using snake_case for variable names.

I've found a critical issue where the program terminates with exit(1) on an error, which should be replaced with proper exception handling. Additionally, there are a couple of medium-severity issues related to inconsistent logging (including the use of magic numbers for message IDs) and container usage that should be addressed to further improve code quality.

Overall, this is a valuable refactoring effort.

Comment on lines +1200 to 1210
if (best_track_idx == -1) {
auto* guide = iroute->getGuide();
const odb::Rect box = guide->getBBox();
std::cout << "Error: assignIroute_bestTrack select no track for "
<< guide->getNet()->getName() << " @(" << box.xMin() / dbu << ", "
<< box.yMin() / dbu << ") (" << box.xMax() / dbu << ", "
<< box.yMax() / dbu << " "
<< getDesign()->getTech()->getLayer(lNum)->getName()
<< " idx1/2=" << idx1 << "/" << idx2 << '\n';
<< getDesign()->getTech()->getLayer(layer_num)->getName()
<< " idx_1/2=" << idx_1 << "/" << idx_2 << '\n';
exit(1);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Calling exit(1) is not a good practice for error handling within a library function as it abruptly terminates the entire application. It's better to log the error using logger_->error and then throw an exception (e.g., std::runtime_error or a custom exception like utl::DRTException) to allow the caller to handle the error gracefully. Additionally, the 0 used as a message ID in the suggested logger_->error call is a magic number and should be replaced with a named constant for better maintainability and clarity, as per the guideline on tunable parameters.

  if (best_track_idx == -1) {
    auto* guide = iroute->getGuide();
    const odb::Rect box = guide->getBBox();
    logger_->error(DRT,
                   0,  // A suitable message ID should be used.
                   "assignIroute_bestTrack could not select a track for net {} "
                   "in box ({}, {}) ({}, {}) on layer {} with track indices "
                   "({}, {}).",
                   guide->getNet()->getName(),
                   box.xMin() / dbu,
                   box.yMin() / dbu,
                   box.xMax() / dbu,
                   box.yMax() / dbu,
                   getDesign()->getTech()->getLayer(layer_num)->getName(),
                   idx_1,
                   idx_2);
    throw std::runtime_error("Track assignment failed.");
  }
References
  1. Define tunable parameters as named constants instead of using hardcoded magic numbers.

Comment thread src/drt/src/ta/FlexTA.cpp Outdated
}
workers.back().push_back(std::move(uworker));
worker_batches.back().push_back(std::move(worker_uptr));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with the horizontal case (which uses emplace_back), it would be better to use emplace_back here as well.

Suggested change
worker_batches.back().push_back(std::move(worker_uptr));
worker_batches.back().emplace_back(std::move(worker_uptr));

Comment thread src/drt/src/ta/FlexTA_assign.cpp Outdated
Comment on lines 374 to 376
std::cout
<< "Warning: via layer connected to non-routing layer, skipped in "
"modMinSpacingCostVia\n";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Warnings should be logged using the logger_ object for consistency, rather than printing directly to std::cout. This allows for better control over log verbosity and output streams. Please use a suitable message ID instead of 0. This 0 is a magic number and should be replaced with a named constant for better maintainability and clarity, as per the guideline on tunable parameters.

    logger_->warn(DRT, 0, "Via layer connected to non-routing layer, skipped in modMinSpacingCostVia.");
References
  1. Define tunable parameters as named constants instead of using hardcoded magic numbers.

Comment thread src/drt/src/ta/FlexTA_assign.cpp Outdated
Comment on lines +473 to +475
std::cout
<< "Warning: via layer connected to non-routing layer, skipped in "
"modMinSpacingCostVia\n";
"modCutSpacingCost\n";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Warnings should be logged using the logger_ object for consistency, rather than printing directly to std::cout. This allows for better control over log verbosity and output streams. Please use a suitable message ID instead of 0. This 0 is a magic number and should be replaced with a named constant for better maintainability and clarity, as per the guideline on tunable parameters.

    logger_->warn(DRT, 0, "Via layer connected to non-routing layer, skipped in modCutSpacingCost.");
References
  1. Define tunable parameters as named constants instead of using hardcoded magic numbers.

@maliberty

Copy link
Copy Markdown
Member

@osamahammad21 please suggest additional validation (eg ispd)

Refactor track-assignment internals to reduce complexity while keeping behavior unchanged.

- split TA init/assign logic into focused helpers
- simplify cut-spacing and best-track selection control flow
- clean up TA support files for readability and consistent Google-style C++ formatting

Closes The-OpenROAD-Project#5614.

Signed-off-by: alokkumardalei-wq <alokkumardalei2@gmail.com>
@alokkumardalei-wq alokkumardalei-wq changed the title Drt refactor ta Refactor TA fles and format and document TA support fles. Mar 6, 2026
@alokkumardalei-wq alokkumardalei-wq changed the title Refactor TA fles and format and document TA support fles. Refactor TA files and format and document TA support fles. Mar 6, 2026
@alokkumardalei-wq alokkumardalei-wq changed the title Refactor TA files and format and document TA support fles. Refactor TA files and format and document TA support files. Mar 6, 2026
@alokkumardalei-wq

Copy link
Copy Markdown
Contributor Author

Thanks @maliberty for pointing this out. It's right that just the bazel build test would not suffice to validate the working, we need more tests like for example ispd tests and other tests. But you can see ispd tests are failing as because test framework does a strict text diff against golden DEF files and the generated DEF has two extra ROUTED Metal2. I you want I can try to fix this by manually updating MANUAL_FOR_BAZEL_TESTS in BUILD with adding these cases.

@maliberty

Copy link
Copy Markdown
Member

In general refactoring is not expected to change the results. Please investigate why there are differences in the DEF

@alokkumardalei-wq

Copy link
Copy Markdown
Contributor Author

Hello @maliberty do you mean the After and Before outputs are ok of ispd test and I don't need to change anything and provide concrete evidence why there differences in DEF or anything else??

@maliberty

Copy link
Copy Markdown
Member

Refactoring to me means to reorganize code without functional change. If the results change then it isn't a refactoring or you have a bug in your refactoring.

@alokkumardalei-wq

alokkumardalei-wq commented Mar 8, 2026

Copy link
Copy Markdown
Contributor Author

Hello @maliberty
You are absolutely right about refactoring
but actually there is no logical issue or bug in our
refactored code becuase I have ran the
ispd tests in both my branch where the refactored
codes resides and the master branch , in the both the cases it was failing.
Then spent some time why this is so, I think there is issue
with ispd18_sample.defok file currently it is expecting
77710 track for net1230 but we ran the test it is
going for 78470 track instead of track 77710 don't know this is so may
be due to some upstream updation and
our old .defok file is not updated . Actually I don't have any idea about this .

57:     - net1230 ( inst7234 Y ) ( inst5195 C0 ) + USE SIGNAL
58:       + ROUTED Metal2 ( 92200 73530 ) ( * 77710 )
59:       NEW Metal3 ( 92200 77710 ) ( 95800 * )
60:       NEW Metal2 ( 95800 77710 ) ( * 83790 )
61:       NEW Metal1 ( 92200 73530 ) VIA12_1C_V
62:       NEW Metal2 ( 92200 77710 ) VIA23_1C
63:       NEW Metal2 ( 95800 77710 ) VIA23_1C
64:       NEW Metal1 ( 95800 83790 ) VIA12_1C_V ;

You can clearly see here now also our ispd18_sample.defok file have old 77710 track but tests picking up new 78470 track and due this mismatch it is causing error both in master branch and my drt_refactor_ta branch .

May be I am foolish but I guess there is no error in my PR for the issue and it the issue from upstream itself ,if would like to allow me to update the .defok file I will definitely do that.

Please let me know If I am correct about and proceed with further process.

Again thank you so much for your time and would be happy receive your feedback further.

@alokkumardalei-wq

Copy link
Copy Markdown
Contributor Author

@maliberty

Copy link
Copy Markdown
Member

@alokkumardalei-wq

alokkumardalei-wq commented Mar 9, 2026

Copy link
Copy Markdown
Contributor Author

@maliberty Thank you for checking the CI!
Maybe I am wrong about this but
I had spend some time and investigated the
DEF differences thoroughly and found that this
is actually an environment-specific
non-determinism issue (macOS ARM64 vs Linux x86_64),
and not from the refactoring ,as

I am developing locally on a macOS ARM64 machine. I ran a definitive test to prove this:

  1. I fully reverted all 7 TA files (FlexTA.cpp, FlexTA_assign.cpp, etc.) to the raw origin/master code.
  2. I ran bazel clean and I ran
    bazel test //src/drt:ispd18_sample-tcl_test
    to force a complete rebuild of the tracker
    from scratch using only the original, untouched OpenROAD code.
  3. The ispd18_sample-tcl_test still fails locally
    on raw master, producing the exact same
    78470 track instead of the expected 77710 from ispd18_sample.defok.

Then I researched and found that OpenRod
jenkins servers runs on linux.
Therefore I tested the same thing on my linux machine too.

But on my Linux system CI, both tracks likely tie in,
and the tie is broken to select 77710.
On macOS ARM64, the exact same un-refactored
and master code breaks the tie and selects 78470.

Because our refactored code produces the exact
identical 78470 output as the original master code
on this machine, the refactoring itself is 1
00% logically equivalent and bug-free. The CI passes on Linux
because the CI environment reproduces the 77710 tie-break.
Let me know what additional steps you'd
like me to take, but the refactoring doesn't actually alter anything .

Thank you so much for your time and looking forward for further feedback.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

Comment thread src/drt/src/ta/FlexTA.h
frLayerNum& layer_num,
int& idx1,
int& idx2);
int assignIroute_bestTrack(taPin* iroute,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function 'drt::FlexTAWorker::assignIroute_bestTrack' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]

  int assignIroute_bestTrack(taPin* iroute,
      ^
Additional context

src/drt/src/ta/FlexTA_assign.cpp:1105: the definition seen here

int FlexTAWorker::assignIroute_bestTrack(taPin* iroute,
                  ^

src/drt/src/ta/FlexTA.h:403: differing parameters are named here: ('idx1', 'idx2'), in definition: ('idx_1', 'idx_2')

  int assignIroute_bestTrack(taPin* iroute,
      ^

Comment thread src/drt/src/ta/FlexTA_assign.cpp Outdated
}
const auto& track_locs = getTrackLocs(layer_num);
int start_track_idx = static_cast<int>(
std::lower_bound(track_locs.begin(), track_locs.end(), pin_coord)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: use a ranges version of this algorithm [modernize-use-ranges]

Suggested change
std::lower_bound(track_locs.begin(), track_locs.end(), pin_coord)
std::ranges::lower_bound(track_locs,, pin_coord)

&& getTech()->getLayer(layer_num - 2)->getType()
== dbTechLayerType::ROUTING) {
auto cut_layer = getTech()->getLayer(layer_num - 1);
auto via = std::make_unique<frVia>(cut_layer->getDefaultViaDef());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "drt::frVia" is directly included [misc-include-cleaner]

src/drt/src/ta/FlexTA_init.cpp:20:

- #include "db/taObj/taFig.h"
+ #include "db/obj/frVia.h"
+ #include "db/taObj/taFig.h"

- Use std::ranges::lower_bound in FlexTA_assign.cpp to fix modernize-use-ranges warning
- Fix inconsistent parameter names between definition and declaration for assignIroute algorithms
- Add missing frVia.h include in FlexTA_init.cpp

Signed-off-by: alokkumardalei-wq <alokkumardalei2@gmail.com>
Signed-off-by: Alok Kumar Dalei <alokkumardalei2@gmail.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

}
const auto& track_locs = getTrackLocs(layer_num);
int start_track_idx = static_cast<int>(
std::ranges::lower_bound(track_locs, pin_coord) - track_locs.begin());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "std::ranges::lower_bound" is directly included [misc-include-cleaner]

src/drt/src/ta/FlexTA_assign.cpp:3:

- #include <algorithm>
+ #include <bits/ranges_algo.h>
+ #include <algorithm>

trackNum++;
for (auto& tp : getDesign()->getTopBlock()->getTrackPatterns(layer_num)) {
if ((getDir() == dbTechLayerDir::HORIZONTAL
&& tp->isHorizontal() == false)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: redundant boolean literal supplied to boolean operator [readability-simplify-boolean-expr]

Suggested change
&& tp->isHorizontal() == false)
&& !tp->isHorizontal())

if ((getDir() == dbTechLayerDir::HORIZONTAL
&& tp->isHorizontal() == false)
|| (getDir() == dbTechLayerDir::VERTICAL
&& tp->isHorizontal() == true)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: redundant boolean literal supplied to boolean operator [readability-simplify-boolean-expr]

Suggested change
&& tp->isHorizontal() == true)) {
&& tp->isHorizontal())) {

@osamahammad21

Copy link
Copy Markdown
Member

@alokkumardalei-wq
Hi Alok, thanks for your effort on this.

Refactoring PRs tend to become very large and difficult to review if they’re not properly split. For context, the PA refactor was broken down into around 10 separate PRs.

To make this reviewable, please divide this into smaller, focused PRs. Each PR should contain only one type of change, for example:

  • Variable renaming only
  • Function renaming only
  • Moving a single function (no other changes)
  • Logic changes for a single code path only
  • Formatting / style changes only (no semantic impact)
  • Dead code removal only
  • Comment / documentation updates only
  • Type updates, const-correctness

The goal is to keep each PR atomic and easy to review independently.

Signed-off-by: Alok Kumar Dalei <alokkumardalei2@gmail.com>
@alokkumardalei-wq

Copy link
Copy Markdown
Contributor Author

Thank you @osamahammad21 for the feedback , I will definitely divide this into small PRs and will notify you very soon
Thank you!

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 21 days if no further activity occurs. Remove the Stale label or comment to keep it open.

@github-actions github-actions Bot added the Stale A stale PR or issue subject to automated closure. label May 25, 2026
@github-actions github-actions Bot closed this Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Stale A stale PR or issue subject to automated closure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DRT Refactor ta

3 participants