Skip to content

Add multi-cut via support to pin access#9218

Open
Damonan wants to merge 6 commits intoThe-OpenROAD-Project:masterfrom
Damonan:add-multicut-basic-support
Open

Add multi-cut via support to pin access#9218
Damonan wants to merge 6 commits intoThe-OpenROAD-Project:masterfrom
Damonan:add-multicut-basic-support

Conversation

@Damonan
Copy link

@Damonan Damonan commented Jan 8, 2026

Problem

Pin access is currently hard-coded to using single-cut vias. I'm working with a PDK that has sufficiently large pins to require multi-cut vias. In addition, minimum cut violations are not handled properly.

MINIMUMCUT Types Targeted:

Type 1 - WIDTH only: If the metal rect is >WIDTH, the specified number of cuts is required
Type 2 - WIDTH and LENGTH+WITHIN: From LEFDEF, "this rule only checks the thin wire connected to a wide wire, and does not check the wire itself". If the metal rect is >WIDTH and >LENGTH then any other connected segments must use the specified number of cuts WITHIN the specified distance.

Key Modifications

src/drt/src/gc/FlexGC_impl.cpp - Update checkMinimumCut_main to correctly handle WIDTH/LENGTH MinimumCut constraints. Here's the basic algorithm:

  1. If the rect is <WIDTH or <LENGTH for the constraint, skip the constraint
  2. Search for all vias above/below in a box bloated by the constraint distance (WITHIN)
  3. For each via in the resulting list:
    a. If the via is inside the rect of interest and it is a WIDTH constraint, add it as a valid via, and continue
    b. If the via is inside the rect of interest and we're dealing with a LENGTH/WITHIN type constraint, skip it
    b. If the via is outside the rect of interest and we're dealing with LENGTH/WITHIN type, check the other pin rects to make sure the via is connected to the pin
  4. Check that the number of valid vias is either 0 (none attempted) or >= the number required by the constraint

TritonRoute(.h, .cpp, .i, .tcl) and global.h - Add two new router_cfg variables: VIA_MAX_CUT specifies the maximum number of cuts allowed. VIA_CANDIDATE_PER_CUT specifies how many cuts to use per cut type.
src/drt/src/pa/FlexPA_acc_point.cpp - Update filterViaAccess(...) to use VIA_MAX_CUT and VIA_CANDIDATE_PER_CUT to properly populate via_defs. genAPEnclosedBoundary(...) is updated similarly.
src/drt/src/db/obj/frAcces.h - Update getViaDef(s) functions to first check if hasVia for the requested numCut. If none exist, then search for a numCut that does have valid vias, and return the first one.

To-do, looking for some feedback

  1. Does VIA_MAX_CUT/VIA_CANDIDATE_PER_CUT fit in with the long-term vision? Would you prefer to move towards something more arbitrary. For example, what if the user wants a specific list of vias?
  2. Magic numbers are remaining in getViaDef(s) functions. I'm not sure what the best way to get VIA_MAX_CUT into that function is. An input might be too cumbersome. Perhaps it's best to give the frAccessPoint a max-cut variable on creation?

Test Cases:

Passes DRT regression, but only after modification. The MinimumCut constraint generator in the testbench did NOT assign any numCuts, so the constraint was invalid. Updated the constraint to have numCuts = 2, as it seems to be expected by the test case. This does suggest that MinimumCut test cases may need to be developed for robustness.

Copy link
Contributor

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

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 introduces valuable support for multi-cut vias in pin access, which is a significant enhancement for handling modern PDKs. The changes are well-structured, touching configuration, scripting interfaces, and core logic for via generation and rule checking. My review focuses on improving consistency in parameter defaults, removing hardcoded limits for better flexibility, and enhancing code readability. Overall, this is a solid contribution, and with a few refinements, it will be even better.

Comment on lines +119 to +121
} else {
set via_max_cut 1
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The default value for via_max_cut is set to 1 here, but it defaults to 2 in the C++ code (TritonRoute.h and global.h). This inconsistency could be confusing for users of the Tcl interface, as they might not get multi-cut vias by default. To ensure consistent behavior, I recommend aligning the Tcl default with the C++ default.

  } else {
    set via_max_cut 2
  }

Comment on lines +349 to +351
} else {
set via_max_cut 1
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Similar to the detailed_route command, the default value for via_max_cut here is 1, which is inconsistent with the C++ default of 2. For consistency and to ensure multi-cut vias are enabled by default, this should be updated.

  } else {
    set via_max_cut 2
  }

Comment on lines +110 to +112
for (int vi = 0; vi < 2; vi++) {
if (hasViaDef(vi+1, 0)) return viaDefs_[(vi+1) - 1];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The hardcoded limit of 2 in this loop restricts via searching to 1-cut and 2-cut vias, even if more are available. As you noted in the PR description, this should be parameterized. I suggest adding a max_cut_ member to frAccessPoint, which can be initialized from router_cfg_->VIA_MAX_CUT when an frAccessPoint is created. This would make the via selection logic more flexible and future-proof. You would also need to update the creation site of frAccessPoint to set this new member.

Suggested change
for (int vi = 0; vi < 2; vi++) {
if (hasViaDef(vi+1, 0)) return viaDefs_[(vi+1) - 1];
}
for (int vi = 1; vi <= max_cut_; vi++) {
if (hasViaDef(vi, 0)) return viaDefs_[vi - 1];
}

Comment on lines +124 to +126
for (int vi = 0; vi < 2; vi++) {
if (hasViaDef(vi+1, 0)) return viaDefs_[(vi+1) - 1];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The hardcoded limit of 2 in this loop restricts via searching to 1-cut and 2-cut vias. This should be parameterized to allow for vias with more cuts, consistent with the VIA_MAX_CUT setting.

Suggested change
for (int vi = 0; vi < 2; vi++) {
if (hasViaDef(vi+1, 0)) return viaDefs_[(vi+1) - 1];
}
for (int vi = 1; vi <= max_cut_; vi++) {
if (hasViaDef(vi, 0)) return viaDefs_[vi - 1];
}

Comment on lines +156 to +158
for (int vi = 0; vi < 2; vi++) {
if (hasViaDef(vi+1, idx)) return viaDefs_[(vi+1) - 1][idx];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The hardcoded limit of 2 in this loop restricts via searching to 1-cut and 2-cut vias. This should be parameterized to allow for vias with more cuts, consistent with the VIA_MAX_CUT setting.

Suggested change
for (int vi = 0; vi < 2; vi++) {
if (hasViaDef(vi+1, idx)) return viaDefs_[(vi+1) - 1][idx];
}
for (int vi = 1; vi <= max_cut_; vi++) {
if (hasViaDef(vi, idx)) return viaDefs_[vi - 1][idx];
}

Comment on lines +904 to +908
for (const auto& [tup, via_def] : via_set) {
via_defs.emplace_back(via_defs.size(), via_def);
if (via_defs.size() >= router_cfg_->VIA_CANDIDATE_PER_CUT*(groups_used+1) && !deep_search)
break;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This loop condition is a bit difficult to reason about as it depends on the total number of vias collected so far. To improve readability and make it easier to verify its correctness, consider using a local counter for each cut group, similar to the logic in genAPEnclosedBoundary.

      int vias_added_this_group = 0;
      for (const auto& [tup, via_def] : via_set) {
        via_defs.emplace_back(via_defs.size(), via_def);
        vias_added_this_group++;
	    if (vias_added_this_group >= router_cfg_->VIA_CANDIDATE_PER_CUT && !deep_search) {
	      break;
        }
	  }

…; Pass pin rectangles to determine if via is part of the pin easily

Signed-off-by: Damon Anderson <damon@h3dgamma.com>
Signed-off-by: Damon Anderson <damon@h3dgamma.com>
…e first valid via

Signed-off-by: Damon Anderson <damon@h3dgamma.com>
…vide user interface to max_cut choice

Signed-off-by: Damon Anderson <damon@h3dgamma.com>
Signed-off-by: Damon Anderson <damon@h3dgamma.com>
…t; May need to include more test cases for robustness

Signed-off-by: Damon Anderson <damon@h3dgamma.com>
@Damonan Damonan force-pushed the add-multicut-basic-support branch from a25cf41 to ae5b86b Compare January 9, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant