The Signoff-Driven ECO Loop
By the time a design reaches the back end of the schedule, the question is no longer "is the architecture sound?" but "do the numbers we will actually be judged on say pass?" Those numbers do not come from the implementation tool's internal optimizer. They come from a signoff-grade static timing analysis (STA) run — one that reads full extracted parasitics, exercises every relevant corner and operating mode, and applies the most pessimistic, contractually-agreed analysis settings. This chapter is about a workflow that takes those authoritative results and turns them into surgical engineering change orders, then verifies the changes against the very same authoritative engine. We call it the signoff-driven ECO loop, and getting comfortable with it is the difference between a tapeout that converges and one that thrashes for weeks.
Why Signoff Is the Source of Truth
Every implementation tool carries its own timing engine. That engine is fast, incremental, and tightly coupled to placement and routing so it can guide optimization decisions in the inner loop. But "fast and tightly coupled" comes at a cost: it uses simplified delay models, approximate or partially-updated parasitics, a reduced set of corners, and sometimes looser crosstalk handling than the signoff engine. The result is that the two engines can — and routinely do — disagree.

The danger is a feedback mismatch. If you fix to the in-tool numbers, you may "close" a path the optimizer believes is clean while signoff still reports a violation. You re-run signoff, see the violation, push it back into the implementation tool, the optimizer again declares victory, and you bounce between the two engines indefinitely. This is the dreaded ping-pong. The cure is simple to state and demanding to practice: derive every late-stage ECO from signoff results, and confirm every fix against signoff results. The implementation tool becomes a means of applying changes, not the authority on whether they were needed.
| Aspect | In-tool optimizer estimate | Signoff-grade STA |
|---|---|---|
| Parasitics | Approximate / partially updated | Full extraction, post-route |
| Corner coverage | Reduced subset for speed | All sign-off corners |
| Crosstalk / noise | Often simplified | Full delay and noise analysis |
| Delay models | Fast, simplified | Most accurate available |
| Role in ECO loop | Apply the change | Decide and verify the change |
Anatomy of the Closed Loop
The loop has five repeating stages. Picture it as a cycle, not a line.

- 1. Run signoff STA. Read the netlist, the extracted parasitics, the timing constraints, and the library
data for every corner and mode. Produce the authoritative violation report.
- 2. Generate a fix list. From the violations, decide what to change: upsize a weak driver, insert a
buffer or pair of inverters to fix transition or fix a long net, swap a cell to a lower-threshold variant for speed, downsize or swap to a higher-threshold variant to recover hold margin or leakage, or request a localized reroute. Many signoff environments can emit these as a ready-to-apply change file.
- 3. Apply the change file in the implementation tool. The implementation tool reads the change file
and legally places, connects, and routes the new or modified cells without disturbing the rest of the design. This is the only step where the database physically changes.
- 4. Re-extract parasitics. The new cells and wires have new RC. You must re-extract — at minimum
incrementally — so the next STA sees reality, not the pre-ECO world.
- 5. Re-run signoff. Confirm the targeted violations are gone and, critically, that you created no new
ones. If clean, you are done; if not, the residual list feeds the next pass. A change file is just a sequence of generic ECO commands. Its great virtue is that it is text: reviewable, diff-able, version-controlled, and replayable. A representative fragment:
# --- ECO change file: setup recovery batch 03 ---
# Upsize a weak launch driver on a critical path
size_cell u_alu/u_add/g_2271 INVx1 INVx4
# Buffer a long, high-fanout net to fix transition + delay
create_buffer -lib_cell BUFx2 -net n_ctrl_bus[7] -name eco_buf_0031
# Swap to a faster threshold variant on the worst path
swap_cell u_alu/u_mul/g_8843 NAND2_HVT NAND2_LVT
# Hold fix on a fast min path (delay padding)
insert_delay_cell -after u_dp/g_551/Q -lib_cell DLYx1 -name eco_dly_0007
After applying, the implementation tool legalizes and routes only the affected region, then you reextract just the changed nets:
# Apply, legalize, route incrementally, then re-extract the touched nets
read_eco_changes ./eco/setup_recovery_batch_03.eco
place_eco_cells -legalize
route_eco -modified_nets_only
extract_parasitics -incremental -changed_nets_only
write_parasitics ./spef/post_eco_batch_03.spef.gz
A subtle point that trips up newcomers: the loop is closed through the implementation database but judged outside it. The change file is the bridge. Because it is a small, declarative artifact rather than a re-run of optimization, the implementation tool does the minimum work needed to realize it legally. The more of the design you let the tool re-touch, the more of the signoff picture you invalidate, and the more re-extraction and re-timing you owe. Every ECO is a trade between the benefit of the fix and the disturbance it creates; the best fixes buy the most slack for the least disturbance.
Why Late ECOs Must Be Physically Minimal
There is a second reason to keep late ECOs surgical beyond runtime: the design may already be through physical verification. If your block has passed layout-versus-schematic and design-rule checking, a sprawling ECO that shoves cells around can reopen DRC violations, disturb power-rail connections, or invalidate already-clean regions. A disciplined flow prefers fixes that fit into existing whitespace — buffers dropped into spare area, gate swaps that reuse the same footprint, spare-cell remapping in a metal-only ECO when base layers are frozen. The cost model is hierarchical: a samesize swap is cheapest, a same-footprint resize next, a new cell into existing whitespace next, and a fix that forces re-placement of a neighborhood is the most expensive. Reach for the cheapest fix that closes the path, and escalate only when you must.

Multiple Corners and Modes at Once
A real design is never a single timing picture. It is a matrix: several process/voltage/temperature corners crossed with several functional and test modes (functional, scan-shift, scan-capture, lowpower, and so on). The corner that limits setup is typically slow-process / low-voltage / a particular temperature; the corner that limits hold is typically fast-process / high-voltage. They pull in opposite directions.

This is where naive ECOs cause regressions. Add a buffer to fix a slow-corner setup violation, and you have just added delay that may help hold at the fast corner — fine. But upsize a driver to win setup, and the sharper edge it produces can break hold at the fast corner, or worsen a transition-driven noise problem in another mode. Fixing one corner while breaking another is the single most common way an ECO loop loses ground. The discipline that prevents it is multi-corner, multi-mode (MCMM) aware fixing. Two practices matter:
- Generate fixes against the merged view, not one corner. A good signoff flow evaluates a candidate change across all active corners/modes before committing it, choosing a fix that is net-
positive everywhere or at worst neutral. Setup fixes should be screened for hold impact; hold fixes should be screened for setup and leakage impact.
- Order the work. Conventional practice is to close setup first across all corners, let the design settle, and then close hold last. Hold fixes (adding delay) rarely hurt setup, so doing them last avoids re-opening setup. Doing it the other way around invites churn.
# Fix setup across all corners, but require no hold degradation anywherefix_eco_timing \-type setup \-corners {slow_low_volt slow_high_temp typical} \-modes {func scan_capture} \-prevent_hold_degradation true \-output ./eco/setup_recovery_batch_03.eco# Later, after setup is stable, close hold last across the fast cornersfix_eco_timing \-type hold \-corners {fast_high_volt fast_low_temp} \-modes {func scan_shift scan_capture} \-prevent_setup_degradation true \-output ./eco/hold_closure_batch_07.ecoFix action Helps Risks breaking Best closed Upsize driver Setup (slow Hold (fast corner), area, During setup phase corner) power Insert buffer on long net Setup, transition Hold if over-applied During setup phase Insert delay cell Hold (fast corner) Setup if mis-placed Last, after setup stable Swap to faster Vt Setup Hold, leakage During setup phase Swap to slower Vt / Hold, leakage Setup After setup stable downsize
Incremental Signoff: Pay Only for What You Changed
A full signoff run across a large block and a dozen scenarios can take hours. If every ECO batch demanded a full re-extraction and a full STA from scratch, the loop would crawl. The escape is incremental signoff: re-do only the work that the change could have affected. Concretely, incremental signoff exploits the fact that an ECO touches a small, localized set of cells and nets. Re-extraction is restricted to the modified nets and their immediate neighbors (neighbors matter because coupling capacitance — and therefore crosstalk delay and noise — depends on what is routed nearby). Timing is then re-propagated only forward and backward from the changed points, reusing cached arrival and required times everywhere the change cannot reach.

Two cautions keep incremental signoff honest:
- Coupling has a radius. A change to one net can alter the crosstalk seen by a physically adjacent but logically unrelated net. Incremental extraction must include those physical neighbors, or you will miss a noise-induced regression. Trust the flow's neighbor logic, but periodically validate with a full run.
- Schedule periodic full runs. Incremental updates accumulate small approximations. A common rhythm is to fix in incremental batches for speed, then do a clean, full signoff at milestones (end of setup phase, end of hold phase, pre-tapeout) as the gate of record. The incremental runs get you there fast; the full run is what you sign.
# Incremental signoff after an ECO batchread_design -netlist ./netlist/post_eco_batch_03.vread_parasitics -incremental ./spef/post_eco_batch_03.spef.gzupdate_timing -incrementalreport_timing -delay setup -slack_lesser_than 0 \-corners all -modes all -nworst 200 \-output ./reports/sta_setup_batch_03.rptreport_noise -changed_nets_only -output ./reports/noise_batch_03.rpt
Discipline: Small Batches, Tracked, Re-Verified
The loop converges when it is run with discipline and diverges when it is not. Three habits separate the two. Small batches. It is tempting to dump hundreds of fixes into one giant change file. Resist it. A small batch — tens of changes, not hundreds — keeps the cause-and-effect chain legible. When a regression appears, you know which handful of edits to suspect. Large batches make every regression a mystery and turn debugging into bisection. Track every change. Each batch should be a named, version-controlled change file with a one-line intent ("setup recovery, ALU multiply path, slow corner"). Keep the before/after worst-negative-slack
and total-negative-slack for each batch. This running log is your evidence of convergence and your map back out if a batch makes things worse.
| Batch | Intent | WNS before | WNS after | New violations | Status |
|---|---|---|---|---|---|
| 01 | Setup, control fanout | -212 ps | -98 ps | 0 | kept |
| 02 | Setup, ALU add path | -98 ps | -41 ps | 0 | kept |
| 03 | Setup, ALU mul path | -41 ps | -6 ps | 2 hold | reworked |
| 03b | Setup mul, hold-aware | -41 ps | -4 ps | 0 | kept |
| 07 | Hold closure, fast corner | +0 ps | +0 ps | 0 | kept |
Re-verify, always. A fix is not done when it is applied; it is done when signoff — with re-extracted parasitics — confirms it across all corners and modes and shows no new violations. Treat "applied" and "verified" as different states. The most expensive bugs are the ones where someone declared a path closed on the strength of the implementation tool's optimistic estimate and skipped the confirming signoff run.

Run this way — authoritative input, surgical batches, MCMM-aware fixes, incremental speed punctuated by full-run gates, and relentless re-verification — and the loop tightens predictably toward a clean, signable result.
Interview Q&A
separate signoff STA at all? The optimizer's timing engine is built for speed inside the place-androute inner loop, so it uses approximate parasitics, a reduced corner set, and simplified delay and noise models. Signoff STA uses full post-route extraction, all corners and modes, and the most accurate models — and that is the result the design will be judged on. If you close to the optimizer's numbers, signoff can still fail, and you bounce between the two engines forever. Closing directly on signoff numbers breaks that ping-pong.
how do you guard against it? A bigger driver produces a faster, sharper edge, which can shorten min-path delay and break hold at the fast corner — and it can worsen crosstalk on neighboring nets. The guard is MCMM-aware fixing: evaluate the candidate change across every corner and mode before committing, and require that setup fixes do not degrade hold (and vice versa). Procedurally, close setup first across all corners, let it settle, then close hold last with delay cells, since hold fixes rarely re-open setup.
extracts only the modified nets plus their physical neighbors, and re-propagates timing only through the fan-in/fan-out cones the change can reach, reusing cached results elsewhere. It bites you if the neighbor radius for coupling is too small — a change can alter crosstalk on a physically adjacent but logically unrelated net, producing a noise or delay regression that a too-narrow incremental update misses. Mitigate by trusting the neighbor logic but scheduling periodic full runs at milestones as the real gate.
Because debugging cost dominates. A small batch keeps cause and effect legible: when a regression shows up, you know which few edits to suspect and can rework or drop just that batch. A giant batch turns every new violation into a bisection problem and makes it hard to attribute regressions, so the loop actually slows down despite "fewer" iterations. Small, named, tracked batches with before/after slack logged give you both convergence evidence and a clean undo path.
Key Takeaways
- The authoritative late-stage timing and noise picture comes from signoff-grade STA with full parasitics and all corners/modes — derive ECOs from that, not from in-tool estimates.
- Closing on signoff numbers eliminates the engine-to-engine ping-pong that wastes schedule.
- The closed loop is: run signoff STA, generate a fix list, apply the change file in the implementation tool, re-extract parasitics, re-run signoff, repeat until clean.
- Fixes must be MCMM-aware: screen every change across all corners and modes so you never fix one corner while breaking another; close setup first, hold last.
- Incremental signoff re-extracts and re-times only what the change touched (including physical neighbors for coupling), with periodic full runs as the gate of record.
- Discipline wins: small named batches, every change tracked with before/after slack, and every fix re-verified against signoff before it is considered closed.
ChipBuddy
← Home
Comments
Leave a Reply