Skip to content

drt: allow NDR auto-taper to be disabled per net#10805

Open
simi1505 wants to merge 6 commits into
The-OpenROAD-Project:masterfrom
simi1505:drt-disable-auto-taper-per-net
Open

drt: allow NDR auto-taper to be disabled per net#10805
simi1505 wants to merge 6 commits into
The-OpenROAD-Project:masterfrom
simi1505:drt-disable-auto-taper-per-net

Conversation

@simi1505

@simi1505 simi1505 commented Jul 4, 2026

Copy link
Copy Markdown

Summary

Adds runtime, per-net control over the detailed router's auto-tapering of non-default-rule (NDR) nets. By default, DRT tapers wide NDR wires down to minimum width near pin connections. Needed for digital pins, but unwanted for wide analog/pad traces that must keep full width all the way to the pin.

Previously the only control was the compile-time AUTO_TAPER_NDR_NETS global. This exposes it per net at runtime, no recompile required.

Addresses #9995 and #10032.

Changes

  • odb: new dbNet flag disable_auto_taper (disableAutoTaper() / setDisableAutoTaper()), with a schema-revision bump.
  • drt: honours the flag during pin access and maze routing (frNet::isAutoTaperDisabled, drNet::autoTaperEnabled).
  • Tcl: new command set_routing_disable_auto_taper (-net <name> | -all_clocks) [-disable] [-enable].
  • Adds regression test ndr_no_auto_taper.

Notes

  • Default behaviour is unchanged (auto-taper stays on for all nets).
  • The flag is subtractive: it can disable taper on a net, but never forces taper on when the global is off; -enable restores the default.
  • Continues the work in drt: allow auto-taper to be disabled per net (#9995) #10721, rebased onto current master with review fixes (schema revision, split include, ord::get_db_block).

Testing

Verified end-to-end via LibreLane on the IHP sg13g2 AMS chip template:

  • Top-level chip assembly: wide NDR analog/pad traces keep their full width all the way to the pins (previously tapered to minimum width at the pin).
  • Digital macro (counter): routes cleanly with no regression when the option is unused (the default path is behaviour-preserving).

Config comparison:

Companion LibreLane PR: librelane/librelane#978

@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.

Welcome to OpenROAD! Thanks for opening your first PR.
Before we review:

Please ensure:

  • CI passes
  • Code is properly formatted
  • Tests are included where applicable
    A maintainer will review shortly!

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

Signed-off-by: Simon Dorrer <simon.dorrer@jku.at>
@maliberty

Copy link
Copy Markdown
Member

I'm not sure what a "pad trace" refers to but dbSigType can be used to detect analog nets. Does that suffice or is a new bit really needed?

Comment thread src/OpenRoad.tcl Outdated
return false;
}

bool UniqueInsts::isNoAutoTaperNDRInst(frInst* inst) const

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.

I'm not sure about this one. Does that mean that, as soon as an instance is connected to a net with auto-taper disabled, that the entire instance has auto taper disabled?

Also, why not use isNDRInst(inst) instead of net->getNondefaultRule() as in the original code?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

isNDRInst(inst) only tells us whether the instance touches some NDR net. It reduces the per-terminal information to a single bool, so it can't tell us whether the same net is both NDR and has auto-taper suppressed.

Here I need that conjunction on one net. Take an instance with net A (NDR, taper enabled) and net B (auto-taper disabled, but no NDR): isNDRInst(inst) would be true (because of A) and "the instance has an auto-taper-disabled net" would also be true (because of B), yet no single net qualifies. So the instance should not be treated as no-auto-taper. Auto-taper only affects NDR nets, so the per-net flag is only meaningful when the same net also carries an NDR.

That's why the loop checks net->getNondefaultRule() && (!AUTO_TAPER_NDR_NETS || net->isAutoTaperDisabled()) together per terminal, rather than combining two instance-level predicates.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

However, the condition was duplicated. I've factored it into frNet::isAutoTaperSuppressed(bool auto_taper_enabled) and reused it at all three sites. Here in isNoAutoTaperNDRInst, and the two in FlexPA_acc_point. So the predicate now lives in one place. Behaviour is unchanged. See commit e638dd6

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

To your other question, "Does that mean that, as soon as an instance is connected to a net with auto-taper disabled, that the entire instance has auto taper disabled?":
Yes, for pin-access purposes, if an instance touches at least one NDR net whose auto-taper is suppressed, the whole instance gets its own unique class. That's intentional and matches the pre-existing behaviour: the line this replaced was if (!AUTO_TAPER_NDR_NETS && isNDRInst(inst)), which likewise classified the entire instance. Pin-access patterns are computed per unique-instance-class, so a no-taper NDR instance needs its own class to get access points computed against the untapered (full-width NDR) geometry. The actual tapering still happens per-net/per-pin during routing. This only affects how instances are grouped for pin access.

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.

Alright. So as long as you can have instances with both non-NDR nets and NDR nets connected to them, it with tapering individually enabled, this should be fine.

simi1505 added 2 commits July 4, 2026 10:50
Address review: the double negative ("disable" in the command name plus -disable/-enable flags) was confusing. Rename to `set_routing_auto_taper` and require exactly one of -enable/-disable (no default), so it reads as a direct on/off switch. Behavior and the odb flag (`disable_auto_taper`) are unchanged.
…essed`

Address review from @mole99: the 'NDR net whose auto-taper is suppressed' predicate
was duplicated inline in three places (FlexPA_unique once, FlexPA_acc_point
twice). Extract it into `frNet::isAutoTaperSuppressed(bool auto_taper_enabled)`
and reuse it. Behavior-preserving.
@simi1505

simi1505 commented Jul 4, 2026

Copy link
Copy Markdown
Author

I'm not sure what a "pad trace" refers to but dbSigType can be used to detect analog nets. Does that suffice or is a new bit really needed?

Good question. I asked Claude to help me with this. This is his thinking summarized. What do you say?

Let me clarify "pad trace" first. In top-level chip assembly (padframe / chip integration), the wide NDR connections from I/O pads to the core (or pad-to-pad), must keep their full NDR width all the way to the pad/pin rather than taper. These are typically SIGNAL-type nets with an assigned NDR, not marked ANALOG.

I looked at using dbSigType, but I don't think it covers the cases here:
It's orthogonal to signal type. "Don't taper / keep full NDR width" is a routing directive, not a classification. The nets that need it are usually SIGNAL (pad/assembly/high-current), and conversely not every analog net wants no-taper.
Flows don't set ANALOG for these nets. They're selected by NDR assignment (e.g. LibreLane's DRT_ASSIGN_NDR by name regex) and remain SIGNAL. Keying off ANALOG would require flows to additionally classify nets as analog in odb, which they don't do today (including the top-level case in #10032).
It can't express per-net choice among NDR nets. The regression test keeps 2 of 6 NDR clock nets untapered while the rest still taper. sigType is too coarse for that.
On the cost: this doesn't grow dbNet. It reuses the existing free unused2 bit, so the only overhead is the schema-revision bump. I modelled it after dbNet::dont_touch (a per-net routing directive stored as a flag), which felt like the closest precedent.

@simi1505

simi1505 commented Jul 4, 2026

Copy link
Copy Markdown
Author

@mole99 @maliberty I tried to answer your review as well as possible. If you are not happy with this solution, we can further discuss it at FSiC in two days. Just let me know. However, we really would appreciate this feature. Especially for the HeiChips 2026 in the first week of August, we would need this feature. Thanks!

simi1505 added 3 commits July 4, 2026 14:16
Address review: the double negative ("disable" in the command name plus -disable/-enable flags) was confusing. Rename to `set_routing_auto_taper` and require exactly one of -enable/-disable (no default), so it reads as a direct on/off switch. Behavior and the odb flag (`disable_auto_taper`) are unchanged.

Signed-off-by: Simon Dorrer <simon.dorrer@jku.at>
…essed`

Address review from @mole99: the 'NDR net whose auto-taper is suppressed' predicate
was duplicated inline in three places (FlexPA_unique once, FlexPA_acc_point
twice). Extract it into `frNet::isAutoTaperSuppressed(bool auto_taper_enabled)`
and reuse it. Behavior-preserving.

Signed-off-by: Simon Dorrer <simon.dorrer@jku.at>
@maliberty maliberty requested a review from osamahammad21 July 5, 2026 04:38
Comment thread src/OpenRoad.tcl
}
}

sta::define_cmd_args "set_routing_auto_taper" \

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Add documentation to the odb/README

Comment thread src/OpenRoad.tcl
Comment on lines +309 to +314
if { !([info exists keys(-net)] ^ [info exists flags(-all_clocks)]) } {
utl::error ORD 1016 "Either -net or -all_clocks need to be defined."
}
if { [info exists flags(-enable)] == [info exists flags(-disable)] } {
utl::error ORD 1017 "Exactly one of -enable or -disable must be specified."
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why use two different idioms and different words (Either vs Exactly one) for the same one-hot style check?

Comment thread src/OpenRoad.tcl
# nets without recompiling. Use -enable to restore the default behavior.
proc set_routing_auto_taper { args } {
sta::parse_key_args "set_routing_auto_taper" args \
keys {-net} flags {-all_clocks -enable -disable}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The -enable flag is unused

Comment thread src/odb/include/odb/db.h
Comment on lines +2522 to +2524
bool disableAutoTaper();

void setDisableAutoTaper(bool disable_auto_taper);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Using positive names avoids double negatives like setDisableAutoTaper(false) which just means setAutoTaper() [using bool enable=true arg]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants