Routing Critical Nets
Routing Critical Nets
Most of the wires on a chip are perfectly happy to be routed by the bulk router with whatever default rules the technology hands them. A small fraction are not. These are the nets that decide whether the design closes timing, whether it survives signal-integrity sign-off, and whether the power grid stays inside its electromigration budget. Treating those nets like everyone else is one of the most common reasons a block ping-pongs between routing and ECO for weeks. The skill that separates a competent route engineer from a great one is knowing which nets deserve special handling, what kind of handling each needs, and how to apply it without burning so many tracks that the rest of the design suffocates. This chapter is about that judgment and the machinery behind it: nondefault routing rules, grouped routing, timing- and crosstalk-driven detail routing, and the discipline of pre-routing and freezing the nets you cannot afford to let the router second-guess.
What Makes a Net "Critical"
A net earns the "critical" label for one of three structural reasons, and it helps to keep them separate in your head because the fix is different for each. The first is timing criticality. A net sits on a path with little or no slack. Anything that adds delay, extra vias, a detour around congestion, a thin wire with high resistance, makes the violation worse. For these nets you want short, direct, low-resistance topologies and you want the router to understand the timing cost of its choices while it works.
The second is signal-integrity sensitivity. Some nets are aggressors, some are victims, and some are both. A high-slew clock-like net injects crosstalk into its neighbors; a slow, high-impedance victim net is easily corrupted by an aggressor running alongside it. The remedy here is physical separation, shielding, or spacing rules, not necessarily a faster wire. The third is high current. Power, ground, and certain heavily loaded or fast-switching signal nets carry enough current to raise electromigration and IR-drop concerns. The fix is metal cross-section: wider wires, more vias in parallel, sometimes multiple metal layers stapled together. Routing Flow
| Global | Track | Detail | Postroute |
|---|---|---|---|
| Route | Assignment | Route | Opt |
Figure 10.1 Three columns labeled Timing-critical, SI-sensitive, High-current, each showing the characteristic net
and its preferred remedy Why route these first or specially? Because routing is a resource auction. Whoever routes first gets the cleanest, shortest, lowest-layer tracks. If you let the bulk router consume the good real estate around a critical net, the only paths left for that net later are detours and via stacks, exactly what it cannot tolerate. Reserving resources up front for the nets that matter is almost always cheaper than repairing them afterward.
| Criticality type | Dominant concern | Typical remedy | Cost paid |
|---|---|---|---|
| Timing | Net delay, detours, | Short topology, timing-driven route, vias | Tracks, runtime wider wire |
| Signal integrity | Crosstalk delay/ | Shielding, spacing, layer assignment noise | 2–3x track area for shields |
| High current (EM/ | Metal reliability | Wide wire, multi-via, multi-layer | Significant track area |
IR)
Nondefault Routing Rules
The mechanism the routing tool gives you for "route this net differently" is the nondefault routing rule (NDR). You define a rule once, naming the wire widths, spacings, and via requirements per layer, then attach it to the nets that should obey it. The default rule is the minimum-DRC geometry; an NDR is anything more generous. A timing or EM net usually wants width. Doubling a wire's width roughly halves its resistance, cutting RC delay and improving current-carrying capacity. An SI net usually wants spacing, pushing neighbors away reduces coupling capacitance and the crosstalk that rides on it.
# A 2x-width, 2x-spacing rule for timing/EM-critical nets,
# defined on the routing layers we actually want to use.
define_routing_rule NDR_2W2S \
-widths {M3 0.10 M4 0.10 M5 0.14 M6 0.14} \
-spacings {M3 0.10 M4 0.10 M5 0.14 M6 0.14} \
-default_reference_rule
# A spacing-only rule for noise-sensitive victims:
# keep the wire at default width but force extra clearance.
define_routing_rule NDR_WIDE_SPACE \
-spacings {M3 0.14 M4 0.14 M5 0.18 M6 0.18} \
-via_cuts {VIA34 2 VIA45 2} \
-default_reference_rule
The -via_cuts clause is easy to overlook and important: a wide low-resistance wire feeding through a single minimum via reintroduces all the resistance you just removed and creates an EM hot spot at the cut. Forcing two cuts (a redundant or "double" via) keeps the via from being the bottleneck. Once the rule exists you bind it to nets with apply_routing_rule . You can target an explicit collection, a pattern, or the output of a timing query.
# Attach the 2W2S rule to an explicit list of critical signal nets.
apply_routing_rule -rule NDR_2W2S \
[get_nets {dsp_core/mac_out[*] ctrl/req_grant}]
# Attach the spacing rule to the worst aggressors found by analysis.
set crit_nets [get_nets -filter "max_slew > 0.18"]
apply_routing_rule -rule NDR_WIDE_SPACE $crit_nets
# Clocks usually carry their own rule from CTS; confirm before
# overriding so you don't undo the clock tree's intent.
report_routing_rules -nets [get_nets clk*]
A practical caution: NDRs are not free, and they are not always helpful. A 2x-width rule on a net buried in a congested region can make routing fail outright because the router cannot find two adjacent tracks. Reserve aggressive rules for the genuinely critical handful, and use a "taper" mindset, the wide rule on the long, exposed stretches and default geometry at pin access where width only causes DRCs.
Grouping Nets with route_net_group
Defining a rule says how a net should be routed. It says nothing about when. To control ordering, to route a chosen set of nets ahead of, or in isolation from, the bulk, you use route_net_group.
route_net_group routes only the collection you hand it, leaving everything else untouched. This is the command behind the "route the critical nets first, then route the rest" methodology. By running it before the global bulk route, the critical nets claim their tracks while the canvas is still empty, then the bulk router fills in around them.
# Step 1: route the critical set first, with their NDRs already attached.
set_tool_option -name detail.timing_driven -value true
set_tool_option -name detail.force_max_number_iterations -value 40
route_net_group -nets $crit_nets
# Step 2: once happy, route everything else. The critical nets are
# already on the canvas and the bulk router treats them as blockages.
auto_route
There are two common reasons to group beyond pure ordering. One is separation of concerns: bus nets that must stay matched, or differential pairs, can be grouped and routed together so the router balances them as a set rather than one at a time. The other is iterative refinement: after a first full route, you can pull out just the failing critical nets, rip them up, and re-route only that group with tighter options, without disturbing the thousands of clean nets around them.
| Approach | When it runs | What it touches | Best for |
|---|---|---|---|
| route_net_group (pre-bulk) | Before auto_route | Only the listed nets | Reserving tracks for critical nets |
| route_net_group (post- | After full route | Only the listed bulk) | Targeted re-route of failers nets |
| auto_route | Main pass | All signal nets | Bulk of the design |
Routing Flow
| Global | Track | Detail | Postroute |
|---|---|---|---|
| Route | Assignment | Route | Opt |
Figure 10.2 Timeline showing route_net_group on critical set, then auto_route filling around the pre-placed critical
wires
Timing-Driven and Crosstalk-Driven Routing
The router does not have to be blind to timing or noise. the routing tool's detail and global routers can be put into modes where they actively weigh delay and coupling alongside the usual wirelength-andDRC objective. This is controlled through the route.* tool options. Timing-driven routing lets the router spend extra wirelength or layer changes to improve a critical path, and conversely lets it relax non-critical nets to free up resources. It works from the timing graph, so it needs a reasonable timing setup (clocks defined, constraints loaded) to be meaningful.
# Enable timing-driven behavior in both global and detail route.
set_tool_option -name global.timing_driven -value true
set_tool_option -name detail.timing_driven -value true
# Let the router prefer upper, faster layers for critical nets.
set_tool_option -name detail.timing_driven_effort -value high
Crosstalk-driven routing is the SI counterpart. The router estimates coupling between adjacent nets and rearranges or spaces them to keep noise and crosstalk-induced delay under control. Spacingaware routing combined with shielding handles the worst victims; the option set below tells detail route to treat crosstalk as a first-class cost.
# Turn on crosstalk awareness during detail routing.
set_tool_option -name detail.crosstalk_driven -value true
set_tool_option -name detail.crosstalk_driven_effort -value high
# Reduce coupling by encouraging the router to space hot nets.
set_tool_option -name detail.reduce_crosstalk_by_spacing -value true
Shielding is the heavier hammer for SI. A shielded net runs with grounded (or power) wires on one or both sides, which gives the coupling capacitance somewhere quiet to terminate instead of into a neighboring signal. You request it as part of the routing rule or through a dedicated shielding flow; the trade-off is that every shielded net consumes the tracks of its shields too, so it is reserved for clocks and the most sensitive analog-adjacent or high-speed signals. A subtlety worth stating in an interview: timing-driven and crosstalk-driven modes increase runtime and can, paradoxically, hurt overall convergence if turned to maximum effort on a congested block. They are scalpels, not defaults. Turn them up where the slack histogram or the noise report says you must, and leave them moderate elsewhere.
Pre-Routing, Protecting, and Freezing
The most reliable way to guarantee a net gets the route you want is to route it deliberately and then forbid the router from touching it again. This is the pre-route and freeze pattern, and it is standard practice for clocks, top-level critical signals, and anything you have hand-tuned. The workflow is: route the critical nets (with their NDRs, via route_net_group ), verify them, then mark them so subsequent routing passes treat them as fixed obstacles rather than candidates for ripup.
# Pre-route the protected set with their rules already bound.
route_net_group -nets $crit_nets
# Freeze them: the bulk router now sees their wires as blockages
# and will not rip them up or reroute them.
set_attribute [get_nets $crit_nets] route_state user_route
set_dont_touch [get_nets $crit_nets] true
# Now route the rest of the design around the frozen wires.
auto_route
# After bulk routing, you can selectively release a net if you
# decide it needs to participate in a later optimization pass.
set_dont_touch [get_nets dsp_core/mac_out[3]] false
Freezing buys you predictability at the cost of flexibility. A frozen critical net cannot benefit from the bulk router discovering a better global solution, and if you froze a net into a poor topology you have locked in the mistake. So the discipline is: only freeze after you have confirmed the pre-route is actually good, by checking DRCs, timing on those paths, and crosstalk on the victims. Freezing a bad route is worse than not freezing at all. Protecting is the lighter-weight cousin. Rather than a hard dont_touch , you can let the router rip up and reroute a critical net but keep its NDR and timing weight attached, so even when it moves it stays wide, spaced, and timing-aware. This is the right choice mid-flow when you still want the optimizer's help but want it constrained.
Trade-offs: Resources Versus Timing and SI
Every technique in this chapter spends routing resources to buy timing or signal-integrity margin, and the budget is finite. The art is matching the spend to the payoff. A 2x-width rule on a long net might recover 30–40 ps of delay but consumes a neighboring track for the entire run. Shielding a clock might cut crosstalk delta-delay dramatically but costs two extra tracks per shielded segment, and on a wide clock distribution that adds up to real area. Routing the critical group first guarantees clean tracks for the nets that matter, but if the group is too large, you have effectively pre-congested the block and made the bulk route harder. The failure modes at each extreme are instructive. Spend too little, and you ship a design that limps through timing closure and fails noise sign-off late, when fixes are expensive. Spend too much, and you create congestion hotspots, DRC pileups, and a route that will not converge at all, trading a timing problem you could have ECO'd for a routability problem you cannot.
| Lever | Buys you | Costs you | Apply when |
|---|---|---|---|
| Wider NDR | Lower R, less delay, EM | One+ adjacent track per headroom | Long timing/EM nets net |
| Spacing NDR | Lower coupling, less noise | Track area beside the net | SI victims |
| Shielding | Strong crosstalk isolation | 2 tracks per segment | Clocks, top SI nets |
| Route-first grouping | Clean tracks for criticals | Tighter bulk routability | Small, vital net set |
| Timing/XT-driven | Smarter router decisions | Runtime, possible churn mode | Targeted, by effort level |
The healthy default is a small, well-chosen critical list, moderate NDRs applied with judgment, timingand crosstalk-driven modes enabled at moderate effort, and freezing reserved for nets you have verified. Escalate effort only where the reports demand it.

Interview Q&A
width NDR on it? Not blindly. In a congested region a wide rule may make the net unroutable because two adjacent tracks aren't available, which turns a timing violation into a DRC or open. I'd first check whether the delay is dominated by resistance (where width helps) or by detour length and vias (where it doesn't). If width is the right lever, I'd apply it as a tapered rule, wide on the long exposed segments, default at pin access, and possibly relieve the congestion first with placement or layer promotion so the wide wire actually fits.
would you use each together? An NDR ( define_routing_rule plus apply_routing_rule ) controls how a net is built, its width, spacing, and via rules. route_net_group controls when and in what isolation a set of nets is routed. They're orthogonal and usually combined: you bind the NDR to
your critical nets, then route_net_group them before auto_route so they claim clean tracks while honoring the wide/spaced geometry, after which the bulk router fills in around them.
verified pre-route) guarantees the bulk router can't rip up or detour a net you've carefully built, which is essential for clocks and hand-tuned signals. The danger is locking in a bad topology: a frozen net can't benefit from a better global solution the router might find, so you only freeze after confirming the preroute passes DRC, timing, and crosstalk. Freezing a poor route is worse than leaving it editable.
High-effort crosstalk- and timing-driven modes increase runtime and can hurt convergence on an already-congested block by inducing churn. They're scalpels applied where the noise and slack reports say you need them. The sensible posture is moderate effort globally, with high effort targeted at the specific victims and critical paths that analysis flags, plus shielding reserved for the handful of nets that truly require isolation.
Key Takeaways
- A net is "critical" for one of three structural reasons, tight timing, SI sensitivity, or high current, and each calls for a different remedy: short low-R topology, spacing/shielding, or wide multi-via metal.
- Route critical nets first because routing is a resource auction; the earliest router gets the cleanest, shortest tracks, and reserving them up front is cheaper than repairing detours later.
- Use
define_routing_ruleplusapply_routing_ruleto control how a net is built (width, spacing, via cuts), androute_net_groupto control when and how isolated a set is routed. - Enable timing-driven and crosstalk-driven routing through
route.*.timing_drivenandroute.*.crosstalk_driven, but treat high effort as a targeted scalpel, not a global default. - Pre-route, verify, then freeze (
dont_touch) the nets you cannot let the router second-guess, but never freeze a route you haven't confirmed is good. - Every technique spends tracks to buy timing or SI margin; keep the critical list small, apply moderate rules by default, and escalate only where the reports demand it, the far end of the resource curve is a routability cliff.
ChipBuddy
← Home
Comments
Leave a Reply