Add multi-cut via support to pin access#9218
Add multi-cut via support to pin access#9218Damonan wants to merge 6 commits intoThe-OpenROAD-Project:masterfrom
Conversation
There was a problem hiding this comment.
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.
| } else { | ||
| set via_max_cut 1 | ||
| } |
There was a problem hiding this comment.
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
}
| } else { | ||
| set via_max_cut 1 | ||
| } |
| for (int vi = 0; vi < 2; vi++) { | ||
| if (hasViaDef(vi+1, 0)) return viaDefs_[(vi+1) - 1]; | ||
| } |
There was a problem hiding this comment.
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.
| 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]; | |
| } |
| for (int vi = 0; vi < 2; vi++) { | ||
| if (hasViaDef(vi+1, 0)) return viaDefs_[(vi+1) - 1]; | ||
| } |
There was a problem hiding this comment.
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.
| 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]; | |
| } |
| for (int vi = 0; vi < 2; vi++) { | ||
| if (hasViaDef(vi+1, idx)) return viaDefs_[(vi+1) - 1][idx]; | ||
| } |
There was a problem hiding this comment.
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.
| 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]; | |
| } |
| 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; | ||
| } |
There was a problem hiding this comment.
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>
a25cf41 to
ae5b86b
Compare
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: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
TritonRoute(.h, .cpp, .i, .tcl)andglobal.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
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.