Placement & Clock Tree Synthesis
Placement decides where every cell physically lives, which fixes the length of every wire and therefore most of your timing. Then CTS does the thing the whole flow has been postponing: it turns the clock from a convenient fiction that arrives everywhere at once into a real network of thousands of buffers with real, unequal delay. Hold violations you have never seen before appear at exactly this moment, and they are supposed to.
4.1 Global, legal, detailed
Placement runs in three stages that solve genuinely different problems, and confusing them makes the logs unreadable.
Global placement optimises a proxy for wire length, almost always HPWL - the half-perimeter of the bounding box enclosing a net's pins. It is not the true routed length, but it is fast to compute and correlates well enough, and modern analytic placers solve for millions of cells by treating the problem as a system of springs.
The stage that most affects your timing report is the third one. After legalisation the tool finally knows real distances, so it can do timing-driven optimisation: resize a cell whose load turned out to be larger than synthesis assumed, insert a buffer on a net that turned out to be long, or swap in a lower-Vth cell on a critical path.
4.2 Congestion and density maps
Two different maps get called "the placement picture", and they answer different questions.
| Density map | Congestion map | |
|---|---|---|
| Shows | How much cell area sits in each region | Routing demand versus available tracks |
| Units | Per cent occupied | Overflow: needed tracks minus supplied tracks |
| Available | Right after global placement | After a trial global route |
| High values mean | Cells are packed here | The router will fail here |
| Fix | Effect | Cost |
|---|---|---|
Lower PL_TARGET_DENSITY |
Spreads everything; the blunt instrument that usually works | Longer wires everywhere, worse timing globally |
| Cell padding around high-pin-count cells | Targets the actual offenders | Needs you to know which cells they are |
| A soft blockage over the hot region | Forces the placer to spread just there | Manual, and it moves when the design changes |
| Restructure the RTL | The real fix for a crossbar or a huge mux | A front-end change, and a schedule conversation |
| Grow the core | Always works | Area, and a full flow re-run |
4.3 Why the clock is built last
Everything so far has treated the clock as ideal: it arrives at every flip-flop at exactly the same instant, with zero delay from the port. That is a deliberate fiction, and STA has been told to believe it.
The fiction is necessary because a clock tree cannot be built until you know where the sinks are. Before placement, a flip-flop has no coordinates, so there are no distances, so there is nothing to balance. CTS therefore has to come after placement - and its arrival changes the timing picture more than any other single step in the flow.
| Before CTS (ideal clock) | After CTS (propagated clock) | |
|---|---|---|
| Clock arrival | Identical everywhere, zero delay | Real, unequal, 0.5-2 ns of insertion delay |
| Skew | Zero, replaced by a lump of set_clock_uncertainty |
Computed per path from the real tree |
| Hold analysis | Nearly meaningless | The main event |
| Cell count | Your logic | Plus hundreds or thousands of clock buffers |
| Power | Underestimated | The clock tree is often 20-40% of total dynamic power |
# Before CTS: the clock is a promise. Uncertainty is a placeholder for
# the skew and jitter the tree does not have yet.
set_clock_uncertainty 0.25 [get_clocks clk]
# After CTS: analyse the tree that actually exists.
set_propagated_clock [all_clocks]
# And now uncertainty only has to cover what STA still cannot see --
# source jitter and a little modelling margin. The skew is measured.
set_clock_uncertainty -setup 0.10 [get_clocks clk]
set_clock_uncertainty -hold 0.05 [get_clocks clk]
# Running STA before this line and calling it sign-off is the single
# most common way to convince yourself a design is finished.
4.4 Building the clock tree
CTS starts from one root and thousands of sinks and must deliver an edge to all of them at nearly the same time, with a clean transition, without exceeding any buffer's load limit. It works bottom-up: cluster nearby sinks, drive each cluster with a buffer, then treat those buffers as the sinks of the next level, and repeat until one root remains.
clkbuf and clkinv cells, not ordinary
buffers. They are characterised for balanced rise and fall delay, because
an imbalance would distort duty cycle a little more at every level, and after six levels a
50% duty cycle can become 42% - which breaks anything using both edges. They also have
lower delay sensitivity to supply variation, which limits how much IR drop (Volume 03) can
turn into skew.
# Which cells CTS may use. Ordinary buffers are deliberately excluded.
set ::env(CTS_CLK_BUFFER_LIST) "sky130_fd_sc_hd__clkbuf_4 \
sky130_fd_sc_hd__clkbuf_8 \
sky130_fd_sc_hd__clkbuf_16"
set ::env(CTS_ROOT_BUFFER) "sky130_fd_sc_hd__clkbuf_16"
# Target skew, in nanoseconds. Asking for less than the tool can deliver
# just burns buffers and power for no benefit.
set ::env(CTS_TARGET_SKEW) 0.05
set ::env(CTS_TOLERANCE) 100
# Sink clustering: how many flops one leaf buffer may drive, and how far
# apart they may be. Tighter clustering = lower skew, more buffers.
set ::env(CTS_SINK_CLUSTERING_SIZE) 25
set ::env(CTS_SINK_CLUSTERING_MAX_DIAMETER) 50
4.5 Skew, insertion delay and useful skew
Two numbers describe a clock tree, and they are frequently confused.
Skew is signed, and the sign decides which check it helps:
| Case | Meaning | Setup | Hold |
|---|---|---|---|
| Positive skew | Capture clock arrives later than launch | Helps - more time for data | Hurts - the edge waits for a racing signal |
| Negative skew | Capture clock arrives earlier than launch | Hurts - less time for data | Helps |
| Zero skew | Simultaneous | Neutral | Neutral |
That table is why hold violations appear at CTS and not before. With an ideal clock, skew is zero and a short combinational path is fine. Give the capture flop a clock that arrives 60 ps early and that same short path now races the edge. The fix is to slow the data down - insert delay buffers - which is why post-CTS optimisation adds cells to paths that were never a problem.
Interview grilling - "Setup was clean before CTS. Now you have 4,000 hold violations. Panic?"
No - that is the expected shape of the flow, and saying so calmly is most of the answer.
- Why it happened. Before CTS the clock was ideal, so skew was zero and every short path passed trivially. CTS gave the clock real, unequal arrival times. Anywhere the capture flop's clock now arrives early, a short data path violates hold.
- Why it is not alarming. Hold is fixed by adding delay to the data path, and there is always somewhere to add it. Unlike setup, hold has no fundamental barrier - it costs area and a little power, not architecture.
- How to fix it. Post-CTS optimisation inserts delay cells automatically. Four thousand violations at a few picoseconds each is routine; four thousand at 500 ps each means the clock tree is badly unbalanced and should be rebuilt rather than patched.
- What would worry me instead. Setup degrading sharply after CTS. That
means insertion delay or skew is far worse than the
set_clock_uncertaintyplaceholder assumed - the estimate was wrong, and every pre-CTS decision was made against a target that did not exist.
The line that shows real experience: "I would check hold at the fast corner, not
typical. Hold failures are worst when cells are fastest, and a design that is hold-clean
at typical can still be broken at ff."
Volume 04 recap
| Concept | The one thing to remember |
|---|---|
| Global placement | Minimises HPWL. Overlaps allowed, rows ignored. |
| Detailed placement | Where timing-driven sizing and buffering actually happen. |
| Density vs congestion | Read the congestion map. Density is a proxy that misleads. |
| Ideal clock | A fiction held until CTS. Uncertainty is its placeholder. |
| CTS goal | Equal paths, not short paths. |
| Clock buffers | Balanced rise/fall, or duty cycle drifts down the tree. |
| Skew sign | Positive helps setup, hurts hold. Negative the reverse. |
| Post-CTS hold | Thousands of small violations is normal. Fix by adding delay. |