Post-route STA is the timing analysis of the finished layout: real cells at their final sizes, a real clock tree, and parasitics extracted from the routed wires. It is the timing that sign-off is based on, and it is usually different from what synthesis reported. This article follows the worst slack of the 16x16 multiplier through every stage of the flow, explains what changes at each one, and shows how the same layout times at the slow, typical and fast corners.

8 min read | Intermediate

What You'll Learn

  • Explain what changes in the timing model from synthesis to post-route
  • Follow the worst slack of a design through the flow and explain each change
  • Read a post-route timing path with propagated clocks and extracted parasitics
  • Analyse one layout at several corners and see which corner limits setup and hold

What Changes Between Synthesis and Sign-Off

ItemAfter synthesisAfter routing
WiresNone, or a wire-load modelExtracted resistance and capacitance of each routed net, with coupling
CellsAs mapped, many at size 1Resized, with buffers and repair changes
ClockIdeal: every flip-flop gets the edge at the same timePropagated through the real clock tree, with latency and skew
CornersUsually one librarySeveral corners, each with its own worst case

Every row moves the slack, in either direction. Wires and the clock tree add delay; repair removes some; a different corner changes all cell delays at once.

One Design Through the Flow

The multiplier was run at a 6 ns clock with the per-layer RC values of OpenROAD-flow-scripts, with the worst slack reported after every step:

StageParasiticsClockWorst setup slackTotal negative slack
After synthesisnoneideal-2.29 ns-15.4 ns
After global placementplacement estimateideal-3.72 ns-34.4 ns
After CTS and timing repairplacement estimateideal-1.04 ns-4.8 ns
Same, clock propagatedplacement estimatepropagated-1.04 ns-4.8 ns
After global routingglobal-route estimatepropagated-1.53 ns-8.7 ns
After detailed routing, extractedOpenRCXpropagated-1.07 ns-4.8 ns
  • Placement adds the wires. The first estimate of wire capacitance costs 1.4 ns on the worst path and doubles the total negative slack.
  • Repair recovers it. After CTS, repair_timing upsizes 91 cells and inserts 53 buffers, which brings the worst slack to -1.04 ns, better than synthesis predicted, because synthesis left many cells at size 1.
  • The clock tree changed nothing here. The tree is balanced, so launch and capture flip-flops see almost the same latency, and propagating the clock moved the slack by less than 0.01 ns. On an unbalanced tree it would not, as Post-CTS Optimization shows.
  • The global-route estimate is pessimistic. It overstates short nets, as measured in Parasitics After Routing, and the slack drops to -1.53 ns.
  • Extraction gives the real answer: -1.07 ns, 0.46 ns better than the last estimate.

Two lessons follow. The synthesis slack is a warning, not a prediction: the final number was 1.2 ns better. And every estimate along the way had its own error, so only the extracted result should be used to decide whether a design is done.

Quick Check

Q: Propagating the clock after CTS did not change the worst slack. Does that mean the clock tree adds no delay?

Show Answer

No. The tree adds about 0.33 ns of latency to every flip-flop. A setup check compares the launch and capture clock arrivals, so equal latency on both sides cancels out. Only the difference, the skew, changes the slack, and on this balanced tree the skew was below 0.01 ns.

Reading the Post-Route Path

The worst path after extraction, shortened:

     Cap     Slew    Delay     Time   Description
                     0.000    0.000   clock clk (rise edge)
   0.088    0.105    0.161    0.161 ^ clkbuf_0_clk/X (sky130_fd_sc_hd__clkbuf_16)
   0.033    0.054    0.165    0.326 ^ clkbuf_3_1__f_clk/X (sky130_fd_sc_hd__clkbuf_16)
            0.054    0.001    0.327 ^ _2419_/CLK (sky130_fd_sc_hd__dfxtp_4)
   0.029    0.093    0.384    0.710 ^ _2419_/Q (sky130_fd_sc_hd__dfxtp_4)
   0.089    0.152    0.188    0.898 ^ rebuffer4/X (sky130_fd_sc_hd__probec_p_8)
   ...
   0.003    0.088    0.470    7.274 v _2395_/X (sky130_fd_sc_hd__or4_1)
            0.088    0.000    7.274 v _2415_/D (sky130_fd_sc_hd__dfxtp_1)
                              7.274   data arrival time

                     6.000    6.000   clock clk (rise edge)
   0.034    0.054    0.166    6.327 ^ clkbuf_3_6__f_clk/X (sky130_fd_sc_hd__clkbuf_16)
            0.054    0.002    6.329 ^ _2415_/CLK (sky130_fd_sc_hd__dfxtp_1)
                    -0.127    6.201   library setup time
                              6.201   data required time
                             -1.073   slack (VIOLATED)
  • The clock passes two levels of the tree, a root buffer and a leaf buffer, and reaches both flip-flops after about 0.33 ns.
  • The Cap column is the extracted load each cell drives, wire plus pins. The repair buffer rebuffer4 drives 89 fF, the operand's fanout; most other stages drive 3 to 13 fF. That buffer is a probec_p_8, a probe buffer with shapes on met5 meant for test pads, not for logic; production flows keep such cells away from repair with set_dont_use, as OpenROAD-flow-scripts does for sky130.
  • Small differences in the clock arrival at the two flip-flops (0.327 and 0.329 ns) are the skew of this path, 2 ps.

One Layout, Three Corners

A corner is a combination of process, voltage and temperature, each with its own Liberty file. sky130 provides, among others, a slow corner (ss, 1.60 V, 100 °C), a typical one (tt, 1.80 V, 25 °C) and a fast one (ff, 1.95 V, -40 °C), described in PVT Corners. Sign-off checks the same layout at all of them. In OpenROAD the corners are defined before the libraries are read, and every analysis can then report each corner:

define_corners tt ss ff
read_liberty -corner tt sky130_fd_sc_hd__tt_025C_1v80.lib
read_liberty -corner ss sky130_fd_sc_hd__ss_100C_1v60.lib
read_liberty -corner ff sky130_fd_sc_hd__ff_n40C_1v95.lib
...
foreach c {tt ss ff} { read_spef -corner $c layout.spef }
report_checks -path_delay max -scenes ss -format slack_only

In this OpenROAD version a corner is reported as a scene, so the report commands take -scenes. The multiplier at a 10 ns clock, with all three corners defined from the start, after routing and extraction:

CornerWorst setup slackWorst hold slack
ss (slow)-3.87 ns+1.32 ns
tt (typical)+2.92 ns+0.70 ns
ff (fast)+5.60 ns+0.42 ns
  • Setup is limited at the slow corner. At ss every cell is slower, and the worst path arrives at 14.12 ns against 10.25 ns required. The same path family that fails at 6 ns typical fails at 10 ns slow.
  • Hold is limited at the fast corner. At ff the short paths are fastest, and the worst hold path, a flip-flop through two gates to the next flip-flop, has the least margin: +0.42 ns.
  • The corners also change the flow. Because every step saw all three corners, repair_timing worked to rescue the slow corner and upsized 123 cells and inserted 62 buffers. The cell area ended 13.6 % larger than in the same run with the typical corner only (11,811 against 10,399 um2), and the typical slack ended at +2.92 ns instead of +0.12 ns.

The slow corner still fails by 3.87 ns: at 1.60 V and 100 °C, this multiplier needs a clock period of roughly 14 ns, or a pipelined design. A design meant to work at the slow corner must be closed there, and the cost shows up in area and power at the other corners.

Quick Check

Q: The hold slack is largest at the slow corner (+1.32 ns) and smallest at the fast one (+0.42 ns). Why does the corner affect hold the opposite way to setup?

Show Answer

A hold check fails when data arrives too early, a setup check when it arrives too late. At the fast corner every cell switches sooner, so data paths get shorter in time and come closer to violating hold, while setup gains margin. At the slow corner the opposite happens. That is why setup is checked at ss and hold at ff. Variation between cells within one corner adds derates on top, as in On-Chip Variation, Derates and Sign-Off Corners.

Running It in ChipVerify Lab

Run Place and Route on the multiplier and open the post-route STA section: it shows the critical path with propagated clocks and extracted parasitics, at the corner chosen for synthesis. Running the panel at a different corner synthesizes and places the design again for that library, which gives a different layout, not the same layout at another corner.

With PRO, the multi-corner option times the same routed layout at ss, tt and ff after routing. It does not change the repair, which still works at the synthesis corner. For the multiplier at 10 ns, repaired for the typical corner only, it reports a worst setup slack of -10.06 ns at ss and a worst hold slack of +0.63 ns at ff: far from the -3.87 ns above, where every step of the flow saw all three corners.

Multi-corner analysis in sign-off is covered in the STA tutorial article MCMM Analysis.

Common Mistakes

Mistake #1: Taking the synthesis slack as the final answer

The multiplier went from -2.29 ns after synthesis through -3.72 ns to -1.07 ns at the end. The synthesis report shows whether a design is far off, not its final timing.

Mistake #2: Signing off at one corner

Setup is limited at the slow corner and hold at the fast corner. A design that passes at typical can fail at either.

Mistake #3: Reading post-route timing from estimated parasitics

Every estimate in the flow had a different error. Extract the routed layout before judging the timing.

Practice Exercise

Challenge: Where Did the Slack Go?

From the stage table: the worst slack was -2.29 ns after synthesis, -3.72 ns after global placement, -1.04 ns after repair and -1.07 ns after extraction. How much did the wire estimate cost at placement, how much did repair gain, and how much did extraction differ from the repaired estimate?

Hint

Take the differences between consecutive stages.

Solution

Placement wires: -3.72 - (-2.29) = -1.43 ns. Repair: -1.04 - (-3.72) = +2.68 ns. Extraction versus the repaired placement estimate: -1.07 - (-1.04) = -0.03 ns. The large swings come from adding wires and from repair; the final extracted slack happened to land close to the post-repair estimate, even though the global-route estimate in between was 0.5 ns more pessimistic.

Open the ready-made example in the lab, synthesize it and run Place and Route.

Summary

  • Post-route STA uses resized cells, propagated clocks and extracted parasitics, at several corners.
  • On the multiplier at 6 ns the slack went -2.29 (synthesis), -3.72 (placement), -1.04 (repair), -1.53 (global-route estimate) and -1.07 ns (extracted).
  • The balanced clock tree added latency but no skew worth measuring, so propagating it did not change the slack.
  • The same layout at three corners: setup is limited at ss (-3.87 ns at 10 ns), hold at ff (+0.42 ns); closing all corners costs area.
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5