← Home Routing & Postroute Optimization
16 Routing & Postroute Optimization

Performing ECO Routing

Global routing, track assignment, detail routing, DRC convergence, SI and postroute optimization

Performing ECO Routing

By the time a block reaches signoff, the routing inside it represents an enormous amount of accumulated work: hundreds of thousands of nets carefully detail-routed, antenna-fixed, DRC-clean, and timing-closed. Then the inevitable happens. A late RTL fix lands, a hold buffer needs to be inserted, a scan chain gets re-stitched, or STA flags a single setup path that a bigger gate can rescue. The last thing you want to do is throw away a clean database and re-route the whole design from scratch. That is exactly the problem ECO routing solves. An Engineering Change Order (ECO) is a targeted, late-stage change to the netlist or placement. ECO routing is the discipline of connecting the new and modified cells while leaving everything else physically untouched. In the routing tool (and the router engine underneath it), the workhorse for this is

eco_route , supported by incremental modes of detail_route  and surgical use of remove_routes .

The mental model is simple: do the minimum amount of routing work required to make the design legal again, and protect every wire you already trust.

Technical diagram

Why Incremental, Not Full

The case for ECO routing is partly about runtime and partly about stability. A full auto_route on a large block can run for hours and, more importantly, will perturb routing everywhere. Even nets you never asked to change can shift to slightly different tracks because the global router re-solves the whole congestion picture. That perturbation is poison late in the flow: it invalidates your signoff DRC run, your extraction, your timing, and any manual fixes you carefully placed. Incremental ECO routing flips the priorities. Instead of optimizing the design as a whole, the tool identifies what actually changed, routes only those nets, and reuses the existing solution everywhere else. The result is a small, reviewable delta that you can verify quickly.

AspectFull Routing ( auto_route )ECO Routing ( eco_route )
ScopeEntire designOnly changed / unrouted / DRC-violating nets
Existing routesFree to rip up and reroutePreserved unless explicitly unfixed
RuntimeHours on large blocksMinutes, proportional to the change
Determinism vs.Re-perturbs everythingKeeps the rest of the database stable

signoff

Typical triggerFirst route, major floorplanLate netlist/placement ECO, timing/DRC
changepatch

How eco_route Behaves

eco_route  is purpose-built to touch only what needs touching. When invoked, it looks for nets that

are unrouted, partially routed, or carrying DRC violations, plus any nets connected to cells the ECO introduced or moved. It then performs global and detail routing on just that set, snapping into the existing track structure so new wires land cleanly next to old ones. Everything that is already legal and already fixed is left exactly as it was. A bare invocation handles the common "I added/changed some cells, go connect them" case:

# Connect newly added/modified cells and clean up any
# leftover opens or DRCs, leaving signoff-clean nets alone.
eco_route
# After it finishes, sanity-check what changed.
report_design -physical > eco_route.rpt
check_routes

The key behavioral difference from full routing is intent. auto_route assumes nothing is sacred and re-solves the whole problem. eco_route assumes almost everything is sacred and only disturbs the minimum. That assumption is what makes it safe to run after signoff DRC and extraction have already passed on the untouched portion of the block. It helps to understand how the engine decides what to work on. Internally, the ECO router builds a worklist by scanning for three conditions: nets with no routing or incomplete routing (the new connections the ECO demands), nets currently carrying DRC violations (geometry that became illegal because a cell moved next to it), and nets whose driver or load list changed since the last route (the modified connectivity). Anything not on that worklist is excluded from consideration entirely. This is why a tightly-scoped ECO finishes in minutes: the router never even loads the global congestion picture for the regions that did not change. The flip side is that eco_route will not opportunistically improve good-but-suboptimal routing the way a full reroute might. That is by design, predictability beats marginal quality once you are in signoff. You can constrain eco_route further when you know precisely which nets the ECO affects. Scoping to a net collection keeps the engine from even considering the rest of the design:

# Route only the nets touched by this ECO.
set eco_nets [get_nets {n_fix_buf_* scan_reconnect_*}]
eco_route -nets $eco_nets
# Confine work to a region around the inserted cells if the
# change is geographically localized (e.g., one hold-fix cluster).
eco_route -nets $eco_nets -bounding_box {1820.0 940.0 1960.0 1080.0}

Fixed vs. Unfixed Routes

The single most important concept in ECO routing is the route attribute that marks a wire as fixed. A fixed (or "user"/"locked") route is one the router treats as untouchable: it will route around it but will never rip it up or reroute it. An unfixed (sometimes called "auto" or "routed") wire is fair game for the engine to modify. This distinction is what protects your signoff-clean routing. Before running an ECO, the proven practice is to lock down everything that is good, so that the only wires eco_route is free to alter are the ones you genuinely want it to. The -route_types (or -route_type ) option appears on several commands and is how you select which class of routing you are talking about.

Route typeMeaningECO treatment
signalRegular signal net routingThe usual target of ECO changes
clockClock-net routingOften protected; reroute only deliberately
pg / power-groundRings, straps, railsAlmost always preserved
Fixed / userUser-locked, signoff-clean wiresNever modified by eco_route
Routed / autoTool-created, unlocked wiresEligible for ripup and reroute

A typical protect-then-route sequence looks like this. You first promote all existing signal routing to fixed status, then deliberately unfix only the nets the ECO needs, then route:

# 1. Lock everything currently routed so it becomes signoff-protected.
set_route_attributes -nets [get_nets *] -fixed true
# 2. Selectively release just the ECO nets so they can be reworked.
set eco_nets [get_nets {n_fix_buf_* old_path_critical_*}]
set_route_attributes -nets $eco_nets -fixed false
# 3. ECO-route only the unfixed nets; fixed wires are honored.
eco_route -nets $eco_nets
# 4. (Optional) re-lock the result so a later ECO doesn't disturb it.
set_route_attributes -nets $eco_nets -fixed true

When a change is genuinely incompatible with the old wiring, you reach for remove_routes with an explicit -route_types filter so you delete only the class you intend to. This is far safer than a blanket unroute:

# Remove only the unfixed signal routing on these nets, keeping
# any fixed/locked wires and all PG and clock routing intact.
remove_routes -nets [get_nets {legacy_mux_sel_*}] \
-route_types {signal} \
-ignore_fixed_nets false
# Now let the engine reconnect them from scratch within the delta.
eco_route -nets [get_nets {legacy_mux_sel_*}]

The -ignore_fixed_nets false flag is the safety belt: it tells remove_routes to respect the fixed attribute and refuse to delete locked wires. Flip it to true only when you consciously want to blow away protected routing. A subtle point that trips people up: locking every net before an ECO is the conservative default, but it can also box the router in. If the new connection genuinely needs a track that an adjacent fixed wire is sitting on, and that fixed wire could legally shift over by one track, the router cannot take advantage of that because you forbade it. The practical compromise is to lock the broad population but leave the immediate neighbors of the ECO region unfixed, so the engine has a little room to maneuver near the change while the bulk of the block stays frozen. Choosing that protection boundary well is part of the craft of clean ECO routing.

Fixed (locked) Unfixed (reroutable)

Figure 16.2 Two columns of nets. Left column "Fixed (locked)" shown as solid bold wires with a padlock icon,

untouched. Right column "Unfixed" shown as dashed wires being ripped up and re-drawn by eco_route. PG and clock layers shown greyed/protected across both.

Incremental Detail Routing

eco_route  already includes a detail-routing phase, but there are situations where you want to invoke

detail routing directly and incrementally, for example after manually editing a few wires, or to scrub residual DRCs introduced by the ECO without re-globaling anything. That is what detail_route - incremental is for. In incremental mode the detail router does not start over. It examines the current routing, finds violations and unconnected segments, and fixes them in place while preserving valid geometry. It is the right tool when global routing is already fine and you only need clean detail-level legalization on the affected area.

# Clean up residual DRCs after an ECO without touching good geometry.
detail_route -incremental true
# Restrict the incremental pass to the nets/region you disturbed
# so the runtime and the delta stay small.
detail_route -incremental true \
-nets [get_nets {n_fix_buf_* legacy_mux_sel_*}]
# Loop detail routing a couple of times if a stubborn cluster of
# DRCs needs more than one pass to settle.
for {set i 0} {$i < 3} {incr i} {
detail_route -incremental true
if {[sizeof_collection [get_drc_errors]] == 0} { break }
}

The discipline here is the same as everywhere in ECO work: restrict the scope. An unscoped detail_route may legalize the whole design and, while it will not gratuitously reroute, it still costs runtime and re-examines wires you would rather leave certified. Naming the nets or supplying a bounding box keeps the work proportional to the change.

Functional vs. Metal-Only ECO

At a high level, ECOs come in two flavors, and they place very different demands on routing. A functional ECO changes the logic. New cells are instantiated, gates are swapped for different functions, connectivity changes. Because new instances need placement, functional ECOs may require spare-cell legalization or incremental placement before routing, and the routing delta can be larger and more spread out. The flow is: implement the logic change, legalize placement of the new/ moved cells, then eco_route the affected nets. A metal-only ECO is constrained to change nothing below the metal layers. The base layers (diffusion, poly, contacts) are frozen because the masks for them are already committed or expensive to spin. The fix must be realized purely by rewiring existing spare cells or gate-array fillers and changing metal connections. Metal-only ECOs are common very late in the project when only the upper-layer masks can still change. Routing here is even more conservative: you are rewiring within a fixed cell population, and remove_routes -route_types {signal} followed by a tightly scoped

eco_route  is the typical motion.
Functional ECOMetal-only ECO
Logic changesYes, freelyYes, but realized via spare/filler cells
Base layersMay changeFrozen
Placement stepOften needed (legalize new cells)None; reuse existing cell sites
Routing scopeCan be broaderTightly localized, metal layers only
Typical timingMid-to-late ECO cyclesVery late; minimal mask cost

In both cases the routing imperative is identical: preserve signoff-clean wiring everywhere except the small zone you must change, and prove that the change did not break anything around it. The metalonly constraint deserves one extra caution. Because you cannot add base layers, you are entirely dependent on the spare-cell distribution that was sprinkled into the floorplan earlier. If the nearest usable spare cell of the right type is far from where the fix is needed, the metal rewire can grow long, picking up routing detour, RC delay, and even fresh DRC pressure. This is why mature flows seed spare cells generously and evenly: the quality of a late metal-only ECO is largely decided long before the ECO itself, by how well the spares were placed.

Verifying the Delta

ECO routing is only finished when you have demonstrated that the delta is clean and that the rest of the design is still as clean as it was. Because you preserved the untouched routing, you can scope verification to what changed rather than re-running full-chip checks blindly, though a final full signoff pass is still mandatory before tapeout. The verification trio is DRC, LVS/connectivity, and timing:

# 1. Geometric DRC on the affected region/nets.
check_routes
report_design -physical
# scope incremental DRC to the ECO bounding box where possible
# 2. Connectivity / LVS-style checks: no new opens or shorts.
check_routes -open_nets -short_nets
# 3. Timing on the delta: confirm the ECO closed its target path
# and introduced no new violators nearby.
update_timing
report_timing -delay_type max -nworst 10
report_qor

Practical guidance for the verification step:

  • Diff the violator lists before and after. A correct ECO removes the violations it targeted and adds none. New violations near the ECO site mean the change perturbed a neighbor and you need another incremental pass.
  • Re-extract and re-time the affected nets. Even a metal-only rewire changes coupling and RC, so timing on the modified paths must be re-confirmed, not assumed.
  • Confirm fixed wires really were preserved. A quick check that the fixed-net count and geometry are unchanged outside the ECO region proves you did not accidentally disturb signoff routing.
  • Always close with a full signoff DRC/LVS run before tapeout. Scoped checks accelerate the iteration loop, but the final sign-off must cover the whole block.
Technical diagram

Interview Q&A

Q
Why use eco_route instead of just re-running auto_route after a late netlist change?

auto_route re-solves the entire routing problem and will perturb wires across the whole design, even nets you never touched, because the global router re-balances congestion globally. That invalidates your signoff DRC, extraction, timing, and any manual fixes, and it costs hours of runtime. eco_route touches only the nets that are unrouted, violating, or attached to the ECO's new/moved cells, snapping new wiring into the existing track structure and leaving everything else byte-for-byte the same. You get a small, reviewable delta and a stable database.

Q
How do you protect signoff-clean routing during an ECO?

You mark the good routing as fixed before routing. Using set_route_attributes -fixed true on all existing nets promotes them to locked status, then you selectively unfix only the ECO nets with -fixed false . The router routes around fixed wires and never rips them up. When you must delete wiring, you use remove_routes -route_types {signal} -ignore_fixed_nets false , which restricts the deletion to a specific route class and refuses to remove locked wires. The combination guarantees

eco_route  can only alter the nets you explicitly released.
Q
What is the difference between a functional ECO and a metal-only ECO from a routing

standpoint? A functional ECO changes the logic, so it may add or move cells, which usually requires an incremental placement/legalization step before routing, and the routing delta can be larger and more dispersed. A metal-only ECO freezes the base layers (poly, diffusion, contacts) because those masks are committed, so the fix must be realized by rewiring existing spare or filler cells using only metal changes. Metal-only routing is therefore tightly localized to upper metal layers and more conservative, typically a scoped remove_routes of signal wiring followed by a narrow eco_route .

Q
After an ECO route, how do you verify the change without re-checking the entire block

every iteration? You scope verification to the delta during iteration and save the full-chip pass for the end. Run

check_routes  (including -open_nets -short_nets ) on the affected region for geometric and

connectivity correctness, re-extract and update_timing then report_timing on the modified paths to confirm the target violation closed and no neighbor was disturbed, and diff the violator lists before and after, a clean ECO removes its targets and adds nothing. Also confirm fixed nets outside the ECO zone are unchanged. Then, before tapeout, you still run a complete signoff DRC/LVS over the whole design.

Key Takeaways

  • ECO routing exists to absorb late netlist or placement changes with a minimal, reviewable routing delta instead of a destabilizing full reroute.
  • eco_route touches only unrouted, violating, or ECO-affected nets and reuses the existing solution everywhere else; scope it with -nets and -bounding_box to keep the change small.
  • The fixed vs. unfixed route distinction is the core protection mechanism. Lock signoff-clean wires with set_route_attributes -fixed true , release only the ECO nets, and use remove_routes - route_types {...} -ignore_fixed_nets false to delete surgically.
  • detail_route -incremental true cleans residual DRCs in place without re-globaling, ideal for scrubbing the affected area after the ECO.
  • Functional ECOs may need placement legalization and a broader routing delta; metal-only ECOs freeze base layers and rewire spare cells on metal only, demanding the most conservative routing.
  • Verify the delta with DRC, LVS/connectivity, and re-timed paths every iteration, then always finish with a full signoff DRC/LVS run before tapeout.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Replying to