The Concurrent Placement Flow, Step by Step
In the previous chapter we contrasted the philosophy of concurrent placement against the older staged approach of "freeze the floorplan, then place the logic." This chapter is the practical heart of that idea. We will walk the integrated flow from cold start to clean handoff, pausing at each stage to explain what the engine is actually doing, what objective it is chasing, and what you should look at before you let it move on. By the end you should be able to read an intermediate placement, recognize when it is healthy, and know which knob to reach for when it is not. Think of this chapter as the script you would narrate while sitting next to a junior engineer watching the run. Interviewers love this exact framing: "Walk me through your mixed-placement flow." A crisp, ordered answer signals that you have actually driven these runs.
The Shape of the Flow
At the highest level, a concurrent macro-plus-standard-cell placement run has six movements. They are not rigid walls; the engine blurs them internally, and optimization can revisit earlier decisions. But conceptually they are distinct enough to reason about and to checkpoint.
- 1. Ingest the design: netlist, technology and cell libraries, physical abstracts, and timing constraints.
- 2. Coarse global placement of macros and standard cells together, optimizing for spread and
connectivity.
- 3. Macro location refinement: snap macros to legal sites, choose orientations, honor keep-outs and
halos.
- 4. Standard-cell legalization: remove overlaps, align cells to rows and sites.
- 5. Optimization hooks: timing- and congestion-driven improvement passes.
- 6. Handoff: a clean, legal, analyzable database for clock tree synthesis and routing.

The single most important thing to internalize is that stages 2 and 3 happen with knowledge of each other. The macros do not get parked first and then have cells stuffed around them. Macros and cells enter the same global optimization, and the macro positions you eventually freeze are positions the cells helped choose. A second thing to internalize is that the stage boundaries are checkpoints, not commitments. Every reporting step exists so you can inspect a partial result and decide whether to continue, adjust a knob and re-run, or step all the way back. A flow you cannot inspect mid-stream is a flow you cannot debug. Treat the reports as the steering wheel: they keep the run pointed at a routable, timing-clean result instead of discovering hours later that the first global arrangement was doomed.
Stage 1: Ingest and Sanity
Before any placement math runs, the engine assembles a consistent picture of the design. It needs the logical netlist, the physical views of every cell and macro (footprint, pin locations, blockage layers), the technology rules (row height, site grid, routing layers), and the timing environment (clocks, I/O delays, exceptions). The die area, core area, and any pre-existing constraints such as placement blockages, regions, or bounds are read in here too. This stage produces no placement, but it produces the constraints every later stage obeys. A surprising fraction of bad runs trace back to a defect here: a missing physical view, a stale constraint file, an undersized core. The cheapest debugging you will ever do is confirming that what you loaded is what you meant to load.
# Stage 1: assemble the design and confirm the inputs are sane
read_netlist ./design/top.v
read_libraries ./libs/std_cells.lib ./libs/macros.lib
read_physical ./libs/std_cells.lef ./libs/macros.lef
read_constraints ./constraints/top.sdc
report_design_summary ;# instance counts, macro count, utilization estimate
check_library_bindings ;# every instance has a physical view
If report_design_summary shows a target utilization above roughly the high-seventies percent once macros are counted, pause. A tight core forces macros and cells to fight for the same area, and the rest of the flow will be an exercise in damage control. Fixing area now is free; fixing it after legalization is not. It is worth being explicit about what each input contributes. The netlist defines connectivity, the spring system the placer pulls on. The physical views define footprints, pin locations, and blockages, on which legality and routability depend. The technology rules define the row and site grid every legal position must land on. The timing constraints define which paths matter, so the timing driver knows where to spend effort. Load macros without physical views and legality becomes meaningless; load stale constraints and the timing driver optimizes for paths that no longer exist. Confirming every input before placement is the cheapest insurance in the flow.
Stage 2: Coarse Global Placement
This is where concurrent placement earns its name. The engine treats every movable object, large macros and tiny standard cells alike, as a point with mass and connections, and it spreads them across the core while pulling connected objects together. There is no legality yet: cells overlap, macros sit on fractional coordinates, and that is fine. The goal is a global arrangement that captures the design's natural topology. The classic mental model is a force system. Connectivity acts like springs pulling related logic into clusters; a spreading force pushes objects apart so they do not collapse into a single pile. Modern engines layer an analytical density model on top so that area is distributed smoothly rather than piling up in hotspots. The output is a low-overlap, connectivity-respecting cloud of objects, with macros already gravitating toward sensible neighborhoods near the logic that drives them.
# Stage 2: concurrent global placement of macros + cells
run_mixed_placement \
-mode global \
-effort high \
-macro_handling concurrent \
-density_target 0.70
report_placement -stage global -metrics {overlap density spread}
Here the run is already balancing three competing drivers at once. It is worth being precise about what each one wants, because their tension is the whole game.
| Driver | Pulls toward | Left unchecked, causes |
|---|---|---|
| Wirelength | Connected objects packed tightly together | Local congestion, macro pile-ups |
| Congestion | Objects spread out, routing resources balanced | Longer nets, worse timing |
| Timing | Critical-path endpoints placed close, slack-aware spreading | Distorted layout around a few paths |
No single driver wins. Wirelength wants everything compressed into a knot; congestion wants everything fanned out; timing wants the few paths that matter held tight even at the cost of the average. The engine's job is to find the operating point where each is "good enough," weighted by the priorities you set. When an interviewer asks "what does the placer optimize?", the strong answer is not "wirelength," it is "a weighted balance of wirelength, congestion, and timing, simultaneously, and here is what each one trades away."

The presence of macros makes this balance harder than in a cells-only placement, and that is precisely why the concurrent approach exists. A large macro displaces a great deal of area, carries many pins that all need routing escape, and once placed becomes an obstacle the cells must flow around. Pull macros purely by wirelength and you cluster them into unroutable knots; ignore their pins and you leave channels too narrow to escape. The concurrent engine reasons about macros and cells in the same density and connectivity model, so the macro positions it favors leave room for both the cells and the routing. One nuance worth carrying into an interview: the weights are not fixed across the run. Early global placement leans on spreading and wirelength to establish a sane topology; later passes shift weight toward timing and congestion as the picture firms up. You choose a schedule of priorities that evolves as the placement matures, not one static set.
Stage 3: Macro Location Refinement
Coming out of global placement, macros are in roughly the right neighborhoods but on illegal coordinates and possibly with arbitrary orientations. Refinement turns those soft suggestions into hard, manufacturable placements. The engine snaps each macro to a legal location on the placement grid, selects an orientation that aligns pins toward their drivers and respects flip rules, enforces keep-out halos so standard cells cannot crowd macro edges, and opens routing channels between adjacent macros. This is also where macro-specific physical etiquette is applied: pushing macros toward the core periphery when that suits the architecture, aligning data-path macros into orderly arrays, and reserving channel width for the pins that must escape. Once you accept this stage, the macros are effectively frozen for the rest of the run.
# Stage 3: legalize and finalize macro placement
refine_macros \
-snap_to_grid true \
-orientation auto \
-halo 4 \
-min_channel 6 \
-push_to_periphery soft
report_macros -checks {legality halo channel orientation overlap}
The check after this stage is non-negotiable. Confirm zero macro overlaps, zero halo violations, and that every macro channel is wide enough to route. A single macro that snapped on top of a keep-out region, or two macros pressed together with no channel between them, will silently poison routing many hours later. Catch it here.
Stage 4: Standard-Cell Legalization
With macros fixed, the standard-cell cloud is still overlapping and off-grid. Legalization resolves this by sliding cells onto legal rows and sites, removing every overlap while perturbing positions as little as possible. The guiding principle is minimum displacement: the global placement was a good solution, so legalization should respect it and only nudge cells the small distances needed to make them legal.
# Stage 4: legalize standard cells with minimum displacement
legalize -objects std_cells -strategy min_displacement
report_placement -stage legalized -metrics {displacement density overlap}
A healthy legalization shows small average displacement and no remaining overlaps. Large displacement is a warning: it means cells had nowhere nearby to go, usually because local density was too high or a region was over-constrained. Large displacement quietly undoes the wirelength and timing work from global placement, so treat a big number here as a signal to revisit density or utilization rather than something to accept.
Stage 5: Optimization Hooks
Legalization makes the placement valid; optimization makes it good. With cells on legal sites, the engine can now run accurate-enough analysis and improve the result without breaking legality. Timingdriven passes pull critical endpoints closer, may resize or buffer along hot paths, and bias placement toward slack recovery. Congestion-driven passes spread cells in routing hotspots, sometimes trading a little wirelength to relieve a jam. These passes are incremental: they perturb, re-check, and keep what helps.
# Stage 5: timing- and congestion-driven incremental optimization
optimize_placement -objective timing -effort medium
optimize_placement -objective congestion -effort medium
report_timing -summary
report_congestion -map overflow
This is the stage where the three-driver balance becomes visible as a decision, not just an internal weighting. If timing improves but congestion overflow climbs, you have pushed too hard on timing. If congestion clears but slack erodes, the reverse. You are looking for both reports to land in acceptable territory at the same time, and the iteration mindset below is how you get there. To make the stages concrete and reviewable at a glance, the following table pairs each stage with its objective, its output, and the one check that tells you whether it succeeded. This is the kind of mental model worth committing to memory before an interview; it lets you answer "what happens at each step and how do you know it worked?" without hesitation.
| Stage | Objective | Output | Check |
|---|---|---|---|
| Ingest | Assemble a consistent design | Loaded netlist, views, constraints | Bindings complete, utilization sane |
| Global | Spread + connectivity, three- | Low-overlap object cloud placement | Even density, no hotspots driver balance |
| Macro | Legal, oriented, channeled refinement | Frozen macro positions macros | Zero overlap, halos, channels OK |
| Cell | Overlap-free, row-aligned cells legalization | Legal standard-cell placement | Small displacement, no overlaps |
| Optimization | Improve timing and congestion | Improved legal placement | Slack and overflow both acceptable |
| Handoff | Stable foundation for CTS/route | Verified placement | Full legality, no surprises |
database
Stage 6: Handoff
The flow ends by producing a placement database that downstream stages consume unchanged. Clock tree synthesis and routing should never need to re-place macros or relegalize cells. A clean handoff means: macros legal and frozen, standard cells legal, no overlaps, congestion within the routability budget, timing with no surprising violations, and all physical constraints still honored. If a later stage has to undo placement decisions, the handoff was not clean, and the concurrent flow's main promise, a stable physical foundation, was not kept.
# Stage 6: verify and export a clean database
report_placement -stage final -metrics {legality density congestion timing}
verify_placement -checks {overlap legality halo channel}
write_design ./out/top_placed.db
Concurrent vs Staged: What Actually Changes
It is worth stating crisply what "concurrent" buys you, since this is a favorite interview probe. In a staged flow, macros are placed first, by hand or by a dedicated step, using only an estimate of where the logic will land. The logic is then placed into the leftover area. The risk is obvious: the macro placement is a guess made before the placer has any real information, and a bad guess becomes a fixed constraint everyone else must live with.
| Aspect | Staged (floorplan then place) | Concurrent (mixed) |
|---|---|---|
| Macro information | Estimated, placed before logic | Informed by real cell distribution |
| Iteration cost | High; macro changes ripple manually | Lower; engine re-balances together |
| Channel sizing | Pre-decided, often guessed | Emerges from actual cell demand |
| Risk profile | Early mistakes locked in | Mistakes surface inside one optimization |
| Best fit | Few macros, well-understood dataflow | Many macros, complex connectivity |
Concurrent placement does not eliminate judgment; it moves the judgment to a point where the engine has data to back it. You still review and you still iterate, but you iterate on a layout that the macros and cells negotiated together. A fair interview follow-up is "then why does the staged approach still exist?" It is perfectly reasonable when the macro story is simple: a design with two or three macros whose dataflow you understand can be placed by hand with nothing lost. The concurrent approach earns its keep as macro count and connectivity complexity rise, where plausible arrangements explode beyond what intuition can search and a single guessed-wrong macro position taxes every downstream metric. Knowing when each fits is as much the answer as knowing how each works.
Reading Intermediate Results and Deciding to Iterate
The flow above reads like a one-way street. In practice it is a loop, and the skill is knowing when to take the loop. After each reporting checkpoint, ask three questions: Is the density spread even, or are there hotspots? Are the macros sitting where the connectivity wants them, or marooned in a corner pulling long nets? Is timing trending the right way, or did a stage make it worse? The reflex you want is to iterate early and cheaply. A density hotspot seen after global placement costs almost nothing to fix by adjusting the density target and re-running. The same hotspot discovered after legalization and optimization costs hours. Cheap checkpoints exist precisely so you can fail fast.

A practical iteration rule: if a problem is global in nature (overall congestion, uneven spread, macros in the wrong neighborhoods), step back to global placement and change the high-level knob. If a problem is local (one congested corner, a handful of timing paths), prefer an incremental optimization pass over a full re-run. Re-running global placement to fix a local issue throws away good work everywhere else.
Pitfalls During the Run and Quick Responses
Three failure modes recur often enough that you should be able to name them and their fixes on sight. Macro pile-ups. Wirelength pressure pulls several macros into a tight cluster, leaving no room for the channels their pins need. The cluster looks efficient by wirelength but is unroutable. Quick response: increase the minimum channel constraint, add spacing or guidance between the offending macros, and slightly lower the density target so the engine stops compressing them. Channel starvation. Macros are individually legal but the gaps between them are too narrow to carry the routing they must. This is the subtle cousin of a pile-up; nothing overlaps, yet routing will choke. Quick response: enforce a larger minimum channel width during macro refinement and re-check the congestion map specifically along macro edges, not just the core average. Halo violations. Standard cells creep into the keep-out region around a macro, either because the halo was too small or because local density pushed cells inward during legalization. Quick response:
widen the halo, confirm the keep-out is honored after legalization (not just after refinement), and if cells keep intruding, relieve the surrounding density that is forcing them in.
| Pitfall | Symptom in reports | First response |
|---|---|---|
| Macro pile-up | Macros clustered, no channels | Raise min-channel, lower density target |
| Channel starvation | Edge congestion, narrow gaps | Enforce wider channels, recheck edge map |
| Halo violation | Cells inside keep-out | Widen halo, relieve local density |
The common thread is that all three are visible at a checkpoint before routing, and all three are cheap to fix if caught at the macro-refinement or legalization stage. The expensive version of every one of these is discovering it during routing.
Interview Q&A
views, and constraints. Run concurrent global placement of macros and standard cells together, optimizing a balance of wirelength, congestion, and timing. Refine and legalize the macros, snapping them to grid with proper orientation, halos, and channels. Legalize the standard cells with minimum displacement. Run timing- and congestion-driven optimization. Then verify and hand off a clean, legal database that clock tree synthesis and routing consume unchanged. The defining feature is that macros and cells are placed in the same optimization, not one after the other.
balance of three drivers simultaneously. Wirelength pulls connected logic tightly together, which left alone creates congestion. Congestion pushes objects apart for routability, which left alone lengthens nets and hurts timing. Timing holds critical paths close even at the average's expense, which left alone distorts the layout. The placer finds the operating point where all three are acceptable under your chosen weights, rather than maximizing any one.
refinement: zero macro overlaps, zero halo violations, and adequate channel width on every macro. Macros freeze after this stage, so any defect here becomes a fixed constraint that silently breaks routing hours later. It is the last cheap moment to catch a macro problem.
had no nearby legal sites, almost always from excessive local density or an over-constrained region. Large displacement undoes the wirelength and timing benefit of global placement, so I treat it as a signal to step back, lower the density target or relieve the crowded region, and re-run, rather than accepting a legal-but-degraded result.
Key Takeaways
- The concurrent flow has six movements: ingest, global placement, macro refinement, cell legalization, optimization, and handoff. Stages 2 and 3 share information, which is what "concurrent" means.
- Global placement balances wirelength, congestion, and timing at once. Know what each driver pulls toward and what it sacrifices.
- Macro refinement is the make-or-break checkpoint, because macros freeze there. Verify legality, halos, and channels before proceeding.
- Legalize standard cells with minimum displacement; large displacement is a warning to revisit density, not a result to accept.
- Iterate cheaply: fix global problems by re-running global placement, fix local problems with incremental optimization.
- The classic run-time pitfalls, macro pile-ups, channel starvation, and halo violations, are all visible at a checkpoint before routing and cheap to fix there, expensive to fix later.
ChipBuddy
← Home
Comments
Leave a Reply