Placing & Legalizing ECO Cells
By the time an ECO reaches the placement stage, the difficult intellectual work of deciding what to change is already finished. Logic has been inserted, sized, or swapped, and the netlist now references cells that exist on paper but have no physical address on the die. The task of this chapter is purely spatial: every newly instantiated cell must be given a legal home on the floor without unsettling the layout that took weeks of effort to converge. This is the moment where ECO discipline is most easily lost, because placement tools are eager to be helpful and will happily relocate dozens of innocent neighbors to make room for one new buffer. Our job as engineers is to keep them on a short leash. The mental model to carry into this stage is minimal disturbance. The converged design is a settled ecosystem: timing closed, routing complete or nearly so, clock tree balanced. Each cell you move is a potential ripple that invalidates timing, breaks routes, or shifts the very paths you were trying to fix. A good ECO placement is one where, if you diffed the placement database before and after, you would see almost nothing change except the handful of cells you actually added. It helps to remember where in the overall flow this work sits. A pre-mask ECO arrives while the design is still malleable: base layers can change and sites can be created. A post-mask, metal-only ECO arrives after the transistor layers are frozen, and the placement question collapses into "which alreadyexisting cell can I borrow?" Knowing which regime you are in is the first decision, because it dictates every command that follows.

Why You Cannot Just "Place and Go"
In a greenfield placement, the engine is free to arrange the whole sea of cells to optimize wirelength and congestion globally. In an ECO, that freedom is precisely what you must surrender. The surrounding cells are load-bearing: their positions determine the timing of paths you have already signed off. If the placer treats your new cells as part of a fresh global problem, it may shuffle the neighborhood, and you will spend the next iteration chasing timing violations you created rather than the one you came to fix. There is also a routing dimension. Late ECOs often land on a design that is already routed. Moving a placed cell tears up the metal connected to it, forcing a reroute that may not find a clean path through congested channels. So ECO placement is constrained on two fronts at once: preserve neighbor positions to protect timing, and preserve existing routes to protect closure. The new cells must thread into the leftover space rather than carve out new territory.
Step One: Finding Room
Before placing anything, you survey the terrain. Standard-cell rows are built from a fixed grid of placement sites, and after the original placement some sites remain empty as whitespace. The question is whether enough contiguous, legal sites exist near the change region to host the new cells. "Near" matters enormously: a buffer inserted to fix a long net does no good if the only free site is on the other side of the block. A reporting command lets you query the availability and distribution of free sites around a coordinate or a given instance.
# Report free placement sites within a bounding box around the change region
report_eco_sites \
-region {1240.0 880.0 1310.0 940.0} \
-min_contiguous_width 6 \
-row_aware true \
-report_density true
The output tells you where the gaps are, how wide the largest contiguous runs are, and what the local placement density looks like. Density is the early warning system. If the region is already at, say, ninety-plus percent utilization, you know up front that there is little slack and that any insertion will likely require pushing neighbors. The table below shows the kind of summary worth extracting before committing to a placement strategy.
| Metric | Comfortable | Tight | Action if tight |
|---|---|---|---|
| Local density | < 75% | > 90% | Widen search radius; consider spare cells |
| Largest contiguous gap | >= cell width | < cell width | Plan to push neighbors or split insertion |
| Distance to nearest gap | < 5 rows | > 15 rows | Reassess fix location; net may worsen |
| Routing congestion overlay | low | high | Avoid; cell move will fail to reroute |
If the survey reveals no room near the fix, that is a signal to revisit the logic-level decision rather than to force a bad placement. Sometimes the right answer is to choose a different insertion point, or a smaller cell, before you ever touch the floor. It is worth widening the survey in stages rather than jumping straight to a large radius. Start with the rows immediately adjacent to the insertion point, because a cell placed there shortens the net you are repairing and minimizes the metal that needs rerouting. Only if that fails do you expand outward, and at each expansion you should ask whether the extra distance erodes the timing benefit you came to buy. A buffer placed fifteen rows away may add more interconnect delay than it removes, turning the fix into a non-fix. The survey is therefore not just a yes/no question about free space; it is a costdistance trade-off, and the engineer who treats it that way avoids the trap of "I found room" being mistaken for "I found good room."
Step Two: Incremental ECO Placement
With room located, you place only the new cells, instructing the engine to honor everything already there. The defining flag of ECO placement is the one that fixes existing instances, so the optimizer treats them as immovable obstacles rather than free variables. The placer's only degrees of freedom are the positions of the cells you just added, and its objective is to seat them well while keeping displacement of anything else at zero.
# Place only the newly added ECO instances, freezing the converged layout
place_eco_cells \
-cells [get_cells -hierarchical -filter "eco_status == new"] \
-honor_fixed_placement true \
-max_neighbor_displacement 0 \
-prefer_nearest_site true \
-timing_driven true
A few choices in that call deserve unpacking. Freezing fixed placement is what protects the neighborhood. Capping neighbor displacement at zero is the strict stance; in dense regions you may
have to relax it to a small bounded value, which we discuss under cautions. Preferring the nearest legal site keeps the new cell close to the net it serves, which preserves the timing benefit you were buying. Timing-driven placement, even at this tiny scale, helps the engine prefer the side of the gap that shortens the critical connection. The contrast between fresh and incremental placement is worth holding in mind explicitly.
| Aspect | Fresh placement | ECO placement |
|---|---|---|
| Scope | Entire block | Only new cells |
| Existing cells | Free to move | Fixed / honored |
| Primary objective | Global wirelength & congestion | Minimal local disturbance |
| Acceptable displacement | Large | Near zero |
| Routing assumption | Not yet routed | Often already routed |
| Risk profile | Self-contained | Ripple into closed timing |
Step Three: Legalization
Placement, even incremental placement, can leave cells in illegal positions: straddling the boundary between two sites, overlapping a neighbor by a fraction, or sitting off the row grid. Legalization is the cleanup pass that snaps every new cell onto a valid site, aligns it to a row, fixes its orientation, and resolves any overlaps, all while respecting placement blockages and keep-out regions. The cardinal rule for ECO legalization is keep it local. A global legalizer, asked to resolve one overlap, may cascade a wave of small shifts across an entire row to make everything fit, and that cascade is exactly the ripple we are trying to avoid. You want the legalizer scoped to the immediate area so it only touches what it must.
# Legalize only within a tight window around the inserted cells
legalize_placement \
-cells [get_cells -hierarchical -filter "eco_status == new"] \
-scope local \
-bounding_box {1230.0 870.0 1320.0 950.0} \
-respect_blockages true \
-allow_neighbor_shift false \
-snap_to_site true
When allow_neighbor_shift is false and there genuinely is no legal site, legalization will fail rather than silently disturb the layout, and a clean failure is far better than a quiet ripple. That failure tells you to go back to the room-finding step. Respecting blockages is non-negotiable: routing blockages, hard macros, and reserved channels exist for reasons that are invisible at the placement view but very real at signoff.
There are subtleties in legalization that catch newcomers. Cell orientation matters: a row has a fixed orientation, and a cell placed into it must be flipped or mirrored to match so that its power rail aligns with the row's rail. A legalizer that snaps position but not orientation produces a cell that looks placed yet shorts power to ground. Multi-row (double-height or taller) cells add another wrinkle, because they must span an even or specific set of rows with consistent rail polarity, and the contiguous gap they need is correspondingly larger and rarer. Finally, well-tap and tap-cell spacing rules can be violated when a new cell displaces filler that was holding a tap in place; a careful flow re-inserts taps and fillers in the disturbed window after legalization so the well-tie design rules stay satisfied.

The Metal-Only Case: Mapping to Spares
Some ECOs must be implemented without changing the placement at all, typically because only the upper metal and via masks can be re-spun. Base layers, where the transistors and the standard-cell rows live, are frozen. You cannot create a new placement site because you cannot fabricate a new transistor. In this regime the new logic must be realized using cells that already exist on the die: the spare cells (and tie/filler equivalents) that a prudent flow scatters across the floor precisely for this purpose. Mapping to spares is a binding problem rather than a placement problem. The synthesized ECO logic is matched, function by function, onto nearby spare instances of compatible type, and the connections are made entirely in metal.
# Bind new ECO logic onto pre-placed spare cells using metal-only routing
map_to_spares \
-new_cells [get_cells -hierarchical -filter "eco_status == new"] \
-spare_pool [get_cells -filter "is_spare == true"] \
-max_bind_distance 40.0 \
-match_function true \
-metal_only true
The practical constraints here are sobering and worth internalizing for interviews. You can only implement functions for which a matching spare type exists nearby; if your ECO needs a complex gate and only inverters and two-input NANDs are spare, you must decompose the logic into what is
available. The spare must be close enough that metal routing can reach it without absurd detours, hence the bind-distance cap. And because nothing on the base layers moves, there is no legalization step at all in the pure metal-only flow, which is exactly what makes it cheap to fabricate.
Hooking Up the Supplies
A placed cell is electrically dead until its power and ground pins connect to the rails. In most standardcell architectures, abutting a cell onto a legal row automatically aligns its primary power and ground pins with the row's rails, so a correctly legalized cell often inherits its supply by geometry alone. But you must verify this, and you must handle the cases that do not happen for free: multi-height cells, cells needing a secondary or switched supply, always-on cells inside a power-gated region, or level shifters and isolation cells that straddle voltage domains.
# Connect primary and secondary supplies for the newly placed cells
connect_supply \
-cells [get_cells -hierarchical -filter "eco_status == new"] \
-primary_power VDD \
-primary_ground VSS \
-secondary_power {VDDG when_in_switchable_domain} \
-infer_from_row true \
-check_connectivity true
For spare-cell ECOs the supply story is usually simpler, because the spare was placed and powered in the original flow, but you should still confirm that a previously unused spare is genuinely tied into the rails rather than left floating. A floating supply on an active cell is the kind of defect that passes every timing check and fails on silicon. A related subtlety is the unused-input and unused-output handling for spare cells. A spare that was previously tied off (its inputs strapped to a constant so it drew no spurious power) must have those tieoffs released and rewired when it is recruited into active logic. Forgetting this leaves an input pin fighting between a tie constant and the new driver, or leaves it floating, both of which produce unpredictable behavior. The supply-connection step is therefore not only about the power and ground rails; it is the moment to confirm that every signal pin of every newly active cell, spare or freshly placed, has exactly one well-defined driver and a clean tie-off only where intended.
Cautions and Pitfalls
The recurring theme of every caution here is the ripple. The pitfalls below are the ones that turn a onecell fix into a multi-day re-closure.
- Density hotspots. Inserting into a region already near full utilization forces the engine to push neighbors to make room. Each pushed cell moves, each move perturbs timing, and the perturbation can be larger than the violation you set out to fix. Always read local density before placing.
- Cell pushing and cascades. Allowing even a small neighbor displacement can chain: cell A shifts to seat your buffer, which nudges B, which nudges C. Keep displacement bounded and scoped, and prefer failing over rippling when the box is full.
- Route damage. On an already-routed design, every moved cell tears its connected metal. If the reroute cannot find a clean path through congestion, you trade a timing violation for a routing violation. Overlay congestion on your site survey before committing.
- Blockage violations. New cells dropped onto reserved channels or over macro keep-outs will pass a casual placement glance and fail signoff. Legalization must respect blockages, and you must verify it did.
- Forgotten supplies. Multi-height and secondary-supply cells do not always inherit power by abutment. An unconnected rail is invisible to timing and fatal in fabrication. After every ECO placement and legalization pass, run a placement legality check scoped to the change region and confirm three things: every new cell is on-grid and overlap-free, no neighbor moved beyond your allowed bound, and every new cell's supplies are connected. Only then is the placement ready to hand off to routing.

Interview Q&A
optimizes the whole block globally and is free to move every cell. On a converged design that freedom is destructive: moving cells shifts the timing of already-closed paths and tears up existing routes. ECO placement fixes all existing instances and places only the new cells, so the converged layout is preserved and disturbance is minimized.
must you use spare cells? A regular ECO can change base layers, so new cells get fresh placement sites and full legalization. A metal-only ECO freezes the base layers because only upper-metal and via masks are re-spun, so no new transistors or sites can be created. The new logic must be bound onto
pre-existing spare cells using metal-only connections. You use spares whenever the re-spin is restricted to metal, typically for late, low-cost fixes after the base masks are committed.
widen the site search to see if acceptable room exists slightly farther out without harming the net you are fixing. If not, reconsider the fix itself: choose a different insertion point, a smaller cell, or decompose the logic. Forcing the insertion would push neighbors, ripple timing, and likely damage existing routes. If the design is metal-only or the area is truly frozen, map onto a nearby spare instead. The wrong answer is to relax displacement limits and let the placer cascade.
checks do you run? Run a local legality check: confirm the cell is snapped on-grid, correctly oriented, and overlap-free; confirm it sits on no blockage or macro keep-out; confirm no neighbor moved beyond the allowed bound; and confirm its power and ground pins, including any secondary or switched supply, are actually connected. A cell can be timing-clean yet illegally placed or floating on its supply, defects that surface only at signoff or in silicon.
Key Takeaways
- ECO placement is governed by one principle: minimal disturbance to the converged layout. Place only the new cells and freeze everything else.
- Always survey the terrain first with a site/density report; local density and routing congestion determine whether an insertion is feasible before you attempt it.
- Use incremental placement that honors fixed instances and caps neighbor displacement, then legalize locally so cleanup does not cascade across rows.
- When base layers are frozen, implement the change by mapping logic onto nearby spare cells with metal-only connections; this is a binding problem, not a placement one.
- Verify supplies and legality after every pass. Abutment often connects rails automatically, but multi-height, secondary, and always-on cells need explicit attention, and a clean failure beats a silent ripple.
ChipBuddy
← Home
Comments
Leave a Reply