CHAPTER FOURTEEN
Timing Budgeting: A Slice of the Period Is Not Signoff
By the end of this chapter you will be able to point at a clock waveform and name the launch edge, the capture edge, the period, the teaching taxes, and the remaining window. You will split that window among the rooms, lighten rooms into timing abstracts, run a virtual rehearsal called estimate_timing, read the artificial corner named estimated_corner, write files you can source, and treat a returned 1 as a heartbeat, not as a closed path.
Why this chapter matters in a real project
Think of a chip as a city of rooms. Power is already in the streets from Chapter 10. The data bus already has a map from Chapter 11. The clock already has a coarse spine from Chapter 12. The doors already sit on the walls from Chapter 13. What the city still lacks is an agreed split of one clock tick. Draw that tick as a waveform. A rising edge launches a flip-flop in CPU_CLUSTER. The next rising edge, 625 ps later, must capture the data in NPU_CORE. That is 1.60 GHz. It is not infinite. Uncertainty and setup eat the two ends of the wave. The green window that remains is what leftover glue, the CPU room, and the NPU room must share.
Sit with Nimbus-8 the morning after Chapter 13. The leftover channel is still 2.091 mm² = 2,091,000 µm². The 128-bit bus still has a map through that leftover. Clock pins still sit where you put them. The doors you placed stay. Today you do not move furniture. Today you split the remaining tick.
If you skip this chapter, two expensive things happen. Either every room is told it may use the whole 625 ps, and the leftover glue has nothing left, or you copy a nearby latency of 5 ns onto a 625 ps clock and invent eight ticks of fiction. Multiply instantiated block, then MIB: two copies of the same drawing. On Nimbus-8 those copies are u_npu_core_0 and u_npu_core_1, sharing NPU_CORE. The first instance you add for budgeting is the master. Its clocks win for the shared drawing.
One more thing, because it will happen to you. You will type estimate_timing. It will return 1. You will type compute_budget_constraints. It will return 1. That means the command finished. It does not mean the remaining 550 ps was split fairly. It does not mean estimated_corner is a library corner you tape out. It does not mean a budget file exists on disk. Those are other commands.
Prerequisites
Chapter 13, because pins are already placed and budgeting is done on rooms whose doors already sit. Chapter 12, because clock pins stay fixed and the spine is a prior, not a second CTS. Chapter 11, because leftover glue already has a bus map. Chapter 10, because M4 and M5 still carry the 20 µm power mesh. Chapter 9, because blocks are shaped. Chapter 8, because a module is a name and a block is a physical room — budgets sit on rooms, not on names. Chapter 5, because plan.budget.bbt_fixed_delay was named there and is cooked here, not re-taught from scratch. Chapter 3, because split constraints already made separate top-level and block-level SDC and UPF files. Budgeting needs those separate files. Mapping keyword this chapter is BUDGET.
The library is nimbus8.dlib. The top is NIMBUS8. Teaching pin, port, clock, and net names in this book are stand-ins. Query them with get_pins, get_ports, get_clocks, and get_nets. Brace Tcl indexes.
How to read the numbers and the notation in this chapter
Read this table slowly. Every later command uses these words. If a word here is still fog, stop and read the row again before you type Tcl.
| You will see | Read it as | What you need to know |
|---|---|---|
| waveform | high and low over time | The picture of the tick. Query the real create_clock wave. Do not invent duty. |
| launch edge | rising tick that starts the walk | The CPU flop starts here. Time zero on the teaching wave. |
| capture edge | next rising tick that must catch the data | 625 ps later on clk_cpu. |
| period | launch to capture | 1 / 1.60 GHz = 0.625 ns = 625 ps. Not a budget. |
| teaching taxes | uncertainty + setup | 45 ps after launch, 30 ps before capture. Estimates. |
| remaining window | what rooms must share | 625 − 45 − 30 = 550 ps = 0.550 ns. A pie is only a nickname for this band. |
| budget | a promised slice of the window | Teaching split: 150 CPU / 190 leftover / 210 NPU. Not a measured delay. |
| virtual clock | the same waveform, no netlist source | What write_budgets uses with set_input_delay / set_output_delay. |
| VIPO | virtual in-place optimisation | estimate_timing. A rehearsal. The saved netlist stays. |
estimated_corner | an artificial corner | Worst-of-corners tape measure. Not SS 0.72 V. |
| timing abstract | a light room | create_abstract -estimate_timing. Pins already sit. |
| budget shell | a stand-in of I/O timing | Early exploration. Not a tapeout block. |
mapping keyword BUDGET | which file the tool sources | Chapter 3 used SDC / UPF. Chapter 12 used CTS_CONSTRAINT. |
| quiet success | return 1 | The command finished. Taste is report_timing and report_budget. |
Learning objectives
After this chapter you will be able to:
- Point at launch, capture, period, uncertainty, setup, and the remaining 550 ps window on a
clk_cpuwaveform, and refuse a nearby 5 ns latency example. - Merge pin changes if needed, then create timing abstracts with
create_abstract -estimate_timing. - Run
estimate_timing, read return 1 as a heartbeat, and tastereport_timing -corners estimated_corner. - Name the obsolete
compute_budget_constraints -estimate_timingswitch and useplan.budget.estimate_timing_modeinstead. - Set a manual pin slice with
set_pin_budget_constraints, then compute and report. - Write budgets with
write_budgets, source them after split constraints, and putBUDGETin the mapfile. - Say what a budget shell is for, and say out loud that it is not tapeout.
- Pick up
plan.budget.bbt_fixed_delayfrom Chapter 5 without re-teaching black boxes. - Leave implementation for later. This chapter ends with promises you can source, not with
place_opt.
The beginner’s mental model
A waveform is not a measured path
Hold a square wave. A rising edge launches. The next rising edge captures. The time between them is the period. You agree those two edges before anyone routes a metal. A budget is a coloured band between those edges: this much for the CPU room, this much for leftover glue, this much for the NPU room. Later, in signoff, you overlay the real data edge on the same clock. That overlay is the weighing scale. This chapter only paints the bands.
People sometimes call the remaining window a pie. That nickname is fine after you can point at the wave. It is not a replacement for the wave. A nearby example writes a clock latency of 5. That is 5 ns = 5,000 ps if the unit is nanoseconds. On this waveform the whole period is 625 ps. Five nanoseconds is eight ticks of fiction. You do not copy it. You query get_clocks. You label every teaching band an estimate.
The precise engineering model
The database already has shaped blocks, a leftover channel, a compiled power grid, a bus map, a clock spine, and placed pins. Timing budgeting adds promised delays on the boundary of those rooms. You typically lighten the rooms into timing abstracts. You run virtual in-place optimisation. You may write a manual slice on a pin you refuse to leave to the tool. You compute. You report. You write files. You source those files after the split-constraint files from Chapter 3, not instead of them.
The nearby flow picture still writes compute_budget_constraints -estimate_timing. The command page says that switch, and -no_estimate_timing, are obsolete and will be removed. New Tcl in this book runs estimate_timing yourself, sets plan.budget.estimate_timing_mode, then computes without the dead flag. Confirm with man.
The practical loop is kind to beginners. Abstracts. Estimate. Taste the artificial corner. Name the rooms. Optional manual slice. Compute. Taste the budget. Write. Source after split. Four small walks are easier to debug than one giant one.
Concepts built from first principles
Part 1 — Read the waveform first
Do not start with a command. Start with the picture the command is trying to split. If you cannot point at a launch edge, a capture edge, a tax, and a remaining window on a sketch, the Tcl will only hide the fog.
Launch, capture, period
A waveform is high and low over time. For teaching we draw clk_cpu as a square wave. The launch edge is the rising tick that starts the walk. The capture edge is the next rising tick that must catch the data. The period is the time between those two edges. For clk_cpu that is 1 / 1.60 GHz = 0.625 ns = 625 ps.
Query with get_clocks. Query the real create_clock waveform. This book’s square wave is a teaching drawing with half the tick high. Do not invent the duty on a netlist that already named it.
Taxes sit on the ends of the tick
The capture flop needs the data to sit still for a while before its clock edge. That wait is setup. This book uses 30 ps. The two clocks might not be exactly where the drawing says. That fuzz is uncertainty. This book uses 45 ps after launch. They are estimates. They are not signoff derates.
Paint those two taxes on the wave. What is left in the middle is the remaining window: 625 − 45 − 30 = 550 ps = 0.550 ns. Required time, in this picture, is capture minus setup minus uncertainty. A budget is a promised slice of that remaining window. People call it a pie after they can point at the green band. The pie is not a second physics.
The walk sits on the same wave
Launch flip-flop inside CPU, leftover glue in the channel, capture flip-flop inside NPU. Put those three slices on the remaining window: 150 ps inside CPU_CLUSTER, 190 ps leftover, 210 ps inside NPU_CORE. 150 + 190 + 210 = 550. Say both units: 0.190 ns = 190 ps.
The budget files you write later constrain boundary paths: input delay, output delay, and a virtual clock that copies this waveform. They do not rewrite every gate inside the room as a full SDC of the sofa.
Do not confuse these
| This | Is not this | Repair |
|---|---|---|
| Launch edge | Capture edge | Launch starts the walk. Capture must catch it, 625 ps later. |
| Period 625 ps | Remaining window 550 ps | Taxes ate 45 + 30. The walk uses the green band. |
| Budget 190 ps | Measured data arrival | A promised band on the wave. Signoff still overlays gold. |
| Virtual clock | The netlist clock port | Same waveform, no source. What a budget file uses. |
estimate_timing | CTS / place_opt | Virtual. Annotations. The saved netlist stays. |
estimated_corner | A library corner | Keeps the later gold edge. Do not tape it out. |
| Timing abstract | Placement abstract | This chapter wants timing. Chapter 8 owned placement abstracts. |
| Budget file | Split SDC from Chapter 3 | Source split first, then budget. Keyword BUDGET. |
| Budget shell | Implemented block | A stand-in for exploration. Not tapeout. |
| Return 1 | A closed path | Heartbeat. Taste with report_timing and report_budget. |
compute_budget_constraints? You will split a number you cannot point at on a wave. The command will run. The picture in your head will be a measured delay. The database will hold a promise. That gap is how quiet success gets shipped.A budget is a promised band on a clock waveform, between launch and capture, after uncertainty and setup have eaten the ends.
On Nimbus-8, clk_cpu is still 1.60 GHz = 625 ps. After 45 ps of uncertainty and 30 ps of setup, 550 ps remains as the green window. The teaching split of that window is 150 ps inside CPU_CLUSTER, 190 ps leftover glue, and 210 ps inside NPU_CORE. Say 0.190 ns = 190 ps out loud so a nearby 5 ns example cannot hide.
What you type next is not yet compute_budget_constraints. You still need light rooms and a virtual rehearsal. What you must not confuse this with is signoff slack, CTS, or a gold data edge you have not measured.
Part 2 — estimated_corner is an artificial corner
estimate_timing creates a new corner named estimated_corner. It is artificial. Draw two gold data edges on the same clock wave. Corner A arrives at 420 ps. Corner B arrives at 520 ps. The artificial corner keeps the later edge on this path, and it keeps the later edge of the other path from the other corner. If corner A is slow on path 1 and corner B is slow on path 2, the mode paired with estimated_corner keeps both.
Taste with report_timing -modes [all_modes] -corners estimated_corner. The paths carry extra letters. A lowercase e means the value came from estimate_timing. A or a means the value came from create_abstract -estimate_timing. S means SPEF or SDF. An asterisk * means you overrode the value with set_annotated_delay. The Analysis column may say Size: None, Buff: Short net, or that three buffers were added in the rehearsal. Those buffers are virtual. They are not a netlist edit you would tape out. They may move the gold edge on this drawing. They do not change the saved netlist.
Budgets are then generated for all corners, modes, and scenarios, including the estimated ones. Do not ship estimated_corner as if it were SS 0.72 V. It is a planning tape measure.
estimated_corner is a tape measure the tool invented. It is not a library corner, and an e on a timing line is not a cell you placed.
You create it by running estimate_timing. You read it with report_timing -modes [all_modes] -corners estimated_corner. If you later override a delay with set_annotated_delay -corners estimated_corner, the letter becomes *. Take the override back with remove_annotated_delay on the same arc.
What you must not do is treat a green path on that corner as signoff, or forget that budgets generated after this rehearsal still have to be written to disk before any block can source them.
Part 3 — Timing abstracts are light rooms
A timing abstract is a smaller, more efficient copy of a room, useful for generating budgets. Pins are already placed. You do not re-place the sofa before you lighten the inside. If you placed those pins on an abstract, you must first merge_abstract so the doors copy into the full design view. Then source the block’s split top.tcl once, to apply internal constraints. Then, in the nearby cook, add_feedthrough_buffers (plural). Then create_abstract -estimate_timing.
That last command runs virtual timing optimisation on the interface logic and annotates the abstract with the result. You may omit -estimate_timing if you already ran the virtual step earlier. On multiple levels of physical hierarchy, only the lowest rooms become abstracts. Intermediate parents stay design views.
Black boxes get their own abstracts after load_block_constraints -type SDC. Do not pretend a black box was virtually optimised. Query report_abstracts for leaf-cell count, compression, and which modes and corners the abstract actually holds. Before abstracts that carry estimated_corner, set abstract.enable_improvements_for_budgeting true. Read it back with report_app_options.
| Switch | What it does | Teaching note |
|---|---|---|
-estimate_timing | Runs virtual optimisation on interface logic and stores the result in the abstract. | This chapter’s default for rooms that will be budgeted. |
-placement | No timing. Physical data for top-level placement. | Chapter 8’s flavour. Not today’s cook. |
-timing_level | none | boundary | compact | full_interface | Less detail, less memory. none is deprecated. |
-blocks | Named block designs, not the current block alone. | Reference names in the nearby cook. Mutex with -all_blocks. |
-all_blocks | Every eligible child. | Mutex with -blocks. |
-force_recreate | Rebuild even if an abstract exists. | Only with -blocks or -all_blocks. Alone, the current block always rebuilds. |
-host_options | Distributed processing. | Plural switch. Confirm the host-option object with man. |
-target_use | implementation | planning | Planning is this book’s job. |
# Teaching stand-ins. Query instances first
icc2_shell> open_block nimbus8.dlib:CPU_CLUSTER.design
icc2_shell> merge_abstract
icc2_shell> source split/CPU_CLUSTER/top.tcl
icc2_shell> add_feedthrough_buffers
icc2_shell> create_abstract -estimate_timing
icc2_shell> save_lib
icc2_shell> report_abstracts
The nearby cook passes reference names to create_abstract -blocks — the drawing, not a copy. set_budget_options -add_blocks and write_budgets -blocks take instance paths. A nearby incremental example writes U1. Confirm with man. New Tcl uses {CPU_CLUSTER NPU_CORE ISP} on the abstract, and u_cpu_cluster / u_npu_core_0 on the budget commands.
add_feedthrough_buffers (plural). The estimate_timing command page writes that a bad child view may run add_feedthrough_buffer (singular) and then create_abstract -estimate_timing, and that this can change the child’s netlist. Name both spellings. Confirm with man. Prefer legal child views so the tool does not “help” you by editing a room you thought was read-only.A timing abstract is a lighter copy of a room whose pins already sit. You merge doors first if they were placed on an abstract, then you lighten the inside.
On multiple levels of physical hierarchy, only the lowest rooms become abstracts. Intermediate parents stay design views. Black boxes are loaded with load_block_constraints -type SDC and are not pretended to be virtually optimised. Compression is a report from report_abstracts, not a feeling from a screenshot.
What you type is create_abstract -estimate_timing after the merge and the split top.tcl. What you must not do is rebuild placement inside the room “just in case”, or steal Chapter 8’s placement abstract and hope it carries estimated_corner.
Part 4 — Virtual in-place optimisation is a rehearsal
estimate_timing pretends to remove repeaters, build repeater trees, and size cells. The simulated effects are stored as annotations on estimated_corner. The saved netlist stays the saved netlist — unless a child view was illegal and the tool opened it to buffer feedthroughs, as the previous trap said.
It optimises top-level logic whether or not a block is editable. Editable rooms and boundary nets that cross editable or read-only rooms are in scope. Cells or nets completely inside a non-editable block are avoided. If you defined unified topology constraints on a net, those constraints steer the delay; query estimated_analysis on a pin to see whether they were used. If they were not defined, the tool uses ordinary buffering to estimate.
Open the top. Set the constraint mapping file from Chapter 3. Source the top-level split top.tcl (or the full-chip SDC in a full-netlist flow). Then run estimate_timing. Return 1 is a heartbeat. Taste is the timing report on estimated_corner.
| Switch | What it does | Teaching note |
|---|---|---|
| (none) | Full virtual optimisation of the current design. | Creates estimated_corner. Return 1 is a heartbeat. |
-pins | Incremental. Only paths through those pins or ports. | Needs a previous full run. Otherwise there is nothing to keep. |
-nets | Incremental. Only those nets. | Same prior: a full run first. |
-host_options | Distributed processing. | Plural. Or set plan.estimate_timing.enable_multi_threading true and read it back. |
# Top-level rehearsal. Mapping file is the Chapter 3 prior
icc2_shell> open_block nimbus8.dlib:NIMBUS8
icc2_shell> set_constraint_mapping_file split/mapfile
icc2_shell> source split/NIMBUS8/top.tcl
icc2_shell> set_app_options -name abstract.enable_improvements_for_budgeting \
-value true
icc2_shell> estimate_timing
icc2_shell> report_timing -modes [all_modes] -corners estimated_corner
Acceptable child views: a design view, or a timing abstract that already carries child-level estimate_timing data. If a child is the wrong view, the tool may open it, run the singular feedthrough-buffer step, build a timing abstract, retarget the instance, and continue. That reference-view change happens unless set_editability -value false is set on the child. App options under plan.estimate_timing.abstract* steer that inner buffering. Read them with report_app_options plan.estimate_timing.abstract*. Do not invent defaults.
estimate_timing is a rehearsal that writes annotations on estimated_corner. Return 1 means the rehearsal finished, not that the remaining 550 ps is closed.
Run it at the top after the mapping file and the split top-level constraints. Taste with report_timing -corners estimated_corner. An e is estimated. A * is a delay you annotated by hand. Child views must already be a design view or a timing abstract with child-level estimate data, or the tool may change a child’s netlist while “helping”.
What you must not confuse this with is place_opt, clock_opt, or CTS. Those still wait. A nearby log that says “Virtually optimized 903 out of 13,637 cells” is a rehearsal count, not a placed netlist.
Part 5 — Constraining the estimate: layers, clips, and partial routes
You can still steer the rehearsal. set_net_estimation_rule names which layers the estimate may use for RC. Then you attach the rule to nets with set_attribute ... estimate_timing_net_rule. A nearby example uses M7 horizontal and M8 vertical. On Nimbus-8 the teaching bus from Chapter 11 is M3 horizontal and M6 vertical. Query get_layers. Do not copy M7/M8 onto a library that never had them.
# Teaching layers. Query get_layers before you copy
icc2_shell> set_net_estimation_rule -parameter layer \
-horizontal_value M3 -vertical_value M6 rule_bus
icc2_shell> set_attribute -objects [get_nets -of_objects \
[get_bundles cpu_npu_data]] \
-name estimate_timing_net_rule -value rule_bus
Layer promotion on critical nets is plan.estimate_timing.optimize_layers true. That also allows promotion inside create_abstract -estimate_timing. When it is on, the global router runs in floorplan mode during the estimate. Mesh layers M4 and M5 still belong to Chapter 10. You do not promote the teaching bus onto the mesh because the metal looks fat.
Maximum net delay and maximum cell delay are plan.estimate_timing.maximum_net_delay and plan.estimate_timing.maximum_cell_delay. A nearby example sets both to 1.0. If the unit is nanoseconds, that is 1,000 ps on a 625 ps clock — larger than the whole tick. Do not copy 1.0 onto clk_cpu. If you clip at all, pick a slice you can defend, for example 0.150 ns = 150 ps, and label it an estimate. After the run, pins whose delay was replaced have is_et_delay_clipped==true.
icc2_shell> get_pins -of_objects [get_cells *] \
-filter is_et_delay_clipped==true
Partial routes are ignored by default. Set plan.estimate_timing.honor_routes true if you want existing global or detail segments kept and only the missing bits estimated. Read the option back. Do not assert a default from memory.
The rehearsal can be steered: layers, a clip, and whether partial routes count. None of those settings is a licence to copy 1.0 onto a 625 ps clock.
Teaching bus layers stay M3 horizontal and M6 vertical unless get_layers says otherwise. A nearby M7/M8 example is someone else’s stack. A nearby 1.0 clip is 1,000 ps if the unit is nanoseconds. Query is_et_delay_clipped after you clip, so you know which pins were replaced by the ceiling.
Default behaviour ignores partial routes. Turn plan.estimate_timing.honor_routes true only when you mean the routes you already have. Read every app option back with report_app_options.
Part 6 — Incremental estimate_timing needs a full run first
By default each full run throws away previous annotations and recalculates. To update only a walk, pass -pins or -nets. Other annotations from the last full run stay. If you skip the full run, incremental has nothing to keep.
If you moved cells on the critical path, recreate abstracts for the rooms you touched: create_abstract -estimate_timing -force_recreate -blocks .... Then incremental-estimate the pin or net on that walk. A nearby log says the full chip virtually optimised 903 of 13,637 cells; the incremental walk virtually optimised 36 of 2,093. That difference is the point of incremental, not a QoR number you would ship.
icc2_shell> estimate_timing
icc2_shell> report_timing -corners estimated_corner
# After you moved cells on that walk, rebuild that room’s abstract
icc2_shell> create_abstract -estimate_timing -force_recreate \
-blocks {CPU_CLUSTER}
icc2_shell> estimate_timing -pins [get_pins \
{u_cpu_cluster/cpu_npu_data_reg_0_/Q}]
Teaching pin names are stand-ins. Query get_pins. Brace Tcl indexes.
Incremental -pins or -nets updates one walk and keeps the rest. It is not the first command of the day.
A full estimate_timing wipes previous annotations. That is why you run full once, taste, move what you must, rebuild abstracts for rooms you touched with -force_recreate, then incremental-estimate the walk. -force_recreate only works with -blocks or -all_blocks.
What you must not do is treat “36 of 2,093 cells” as a closed path, or mix set_annotated_delay on estimated_corner with a full rerun and then wonder why the asterisk vanished. A full run without -pins replaces the annotations. Incremental is how you keep the rest of the chip.
Part 7 — Manual budget constraints are promises you said out loud
Automatic compute still creates pin and boundary constraints for every hierarchical pin. Manual is how you override a slice you refuse to leave to the tool. You can combine them: write the manual slice, then compute.
Pin constraints: set_pin_budget_constraints. How much of a path through a door stays inside. The textbook is -internal_percent 40 on a pin such as u0_0/rstn — 40 percent inside the room, 60 percent outside. On Nimbus-8 you would query the actual pin. Percent and delay forms are mutually exclusive on the same call. -internal_percent is equivalent to -input -internal -to_percent.
| Switch | What it does | Teaching note |
|---|---|---|
-internal_percent | Percent of the path kept inside the pin’s block. | Sets -internal for you. Remainder stays outside. |
-from_percent / -to_percent | Percent before / after the pin. | Mutex with other percent and delay forms. |
-from_delay / -to_delay / -internal_delay | Absolute delay, in input time units. | Same mutex. Query the unit. Do not copy 5. |
-inputs / -outputs | Restrict to input or output pins. | Plural on this command. Compute uses singular. Name both. |
-late_boundary / -early_boundary | Attach a named boundary constraint. | Create the boundary object first. |
-frozen | Keep this slice; compute must not rewrite it. | Feedthrough reports later show FROM_FROZEN / TO_FROZEN. |
-same_as_mib | Copies share the slice. | NPU copies share NPU_CORE. |
-all_pins | -all | pin list | Scope. | Query pins. Do not invent u0_0/rstn on Nimbus-8. |
# Teaching stand-in. Query get_pins first
icc2_shell> set_pin_budget_constraints \
[get_pins {u_cpu_cluster/cpu_npu_data[0]}] \
-internal_percent 40
Boundary constraints: set_boundary_budget_constraints. Driving cell and load. Then attach with -late_boundary / -early_boundary on the pin command. Latency constraints: set_latency_budget_constraints. Early and late clock latency. A nearby example uses -early_latency 5 -late_latency 5 on a clock named clk. If the unit is nanoseconds, that is 5,000 ps. Teaching latency, if you set one at all, is a small slice of 625 ps — for example 0.080 ns = 80 ps — labelled an estimate. Query get_clocks.
A manual slice is a promise you said out loud. Percent and delay forms cannot share one call, and a nearby latency of 5 is not a Nimbus-8 number.
-internal_percent 40 keeps 40 percent of the path inside the room. The rest stays in leftover glue and the other room. Create named driving cells and loads with set_boundary_budget_constraints, then attach them. Latency, if you set it, is a small slice of the period you queried, not 5 ns on a 625 ps clock.
This command’s scope switches are -inputs and -outputs (plural). compute_budget_constraints uses -input and -output (singular). Mixing the families is a syntax error. Confirm with man. Automatic compute still fills every other hierarchical pin. Manual is the override, not a replacement for compute unless you truly meant to write every door by hand.
Part 8 — Naming rooms and computing the split
set_budget_options -add_blocks names the instances that will receive a budget. When a multiply instantiated block appears in the list, the instance given first is the master. Its clocks and their characteristics are used for the generated budget. On Nimbus-8, if both NPU copies are in the list, put the master you intend first. -reset clears budget constraints and options from set_budget_options, the pin / latency / boundary commands, and compute_budget_constraints.
| Switch | What it does | Teaching note |
|---|---|---|
-add_blocks | Declare instances that get a budget. | Must pass instance paths. First MIB instance is master. |
-remove_blocks | Drop instances, or -all. | They no longer receive write_budgets output. |
-reset | Clear budget constraints and options. | A broom, not a compute. |
-adjust_latency | prects | target | actual | Default if never set: prects, honest early in the flow. |
Then compute_budget_constraints splits the remaining window on the wave. If you specify none of -setup_delay, -boundary, or -latency_targets, the tool behaves as -setup_delay -boundary. -latency_targets must be paired with -balance. Values are actual (match current latencies) or estimated (match predicted trunk latency — clock trunk planning from Chapter 12 must already have been run).
compute_budget_constraints -estimate_timing. The command page says -estimate_timing and -no_estimate_timing are obsolete. Use plan.budget.estimate_timing_mode and run estimate_timing yourself. If the mode is on and estimated_corner is missing, the tool may run estimate_timing as a side effect. Prefer to run it yourself and read it. A nearby table caption also misspells the command as compute_budget_contraints (missing an s). The command is compute_budget_constraints. Confirm with man.| Switch | What it does | Teaching note |
|---|---|---|
-setup_delay | Compute setup delay budgets. | Default pair with -boundary if you say nothing. |
-boundary | Compute boundary (drive / load) budgets. | Same default pair. |
-latency_targets | actual | estimated | Must pair with -balance. Estimated needs Chapter 12 trunks. |
-pins | Only those pins. | Further restrict with -input / -output (singular). |
-input / -output | Only block inputs or outputs. | A nearby table writes -inputs / -outputs. New Tcl uses the command page: singular. Confirm with man. |
-unspecified | Only pins with no delay budget yet. | Useful on a second pass. |
-feedthrough | Only feedthrough paths. | A visit from input of a room to output of the same room. |
-slack | Only paths whose budget slack is worse than the value. | Budget slack is actual delay versus budgeted delay. |
-default | Ignore current plan.budget.* settings. | Same honesty as write_budgets -default. |
-host_options | Distributed processing. | Plural. Not Chapter 12’s CTP family. |
icc2_shell> set_app_options -name plan.budget.estimate_timing_mode -value true
icc2_shell> set_budget_options -add_blocks [get_cells \
{u_cpu_cluster u_npu_core_0 u_npu_core_1}]
icc2_shell> compute_budget_constraints -setup_delay -boundary
Read plan.budget.estimate_timing_mode back. Do not invent a default. u_npu_core_0 listed first is the MIB master. plan.budget.bbt_fixed_delay is the Chapter 5 thread: when a black-box delay was measured, leave the option so the budgeter maintains it; when the delay was a guess, set it false so the budgeter may adjust, and take the tightened number to the block owner. Do not re-open Chapter 5’s black-box cook. Just decide, here, which way the option faces on the rooms that are still boxes.
Name the rooms first. Compute second. The obsolete -estimate_timing flag on compute is not new Tcl, even when a nearby flow still types it.
Set plan.budget.estimate_timing_mode, then compute_budget_constraints -setup_delay -boundary without the dead switch. If you specify nothing, you still get setup and boundary. -latency_targets without -balance is incomplete. MIB: the first instance in -add_blocks is the master.
A nearby table writes -inputs on compute. The command page writes -input. New Tcl follows the command page and names the conflict. Confirm with man. Return 1 is still a heartbeat. The taste is the next part.
Part 9 — report_budget is the taste
compute_budget_constraints finished. Taste is report_budget. If you computed in estimate-timing mode, the report may open with ABS-240: the budget is based on estimated_corner delays. That is information, not a pass. Read it as “this window was cut with the tape measure, not with the weighing scale.”
| Switch | What it does | Teaching note |
|---|---|---|
-blocks | List rooms selected by set_budget_options. | First check: did you add the instances you think you added? |
-html | One HTML file, current mode. | Can be huge. Extension .html. |
-html_dir | Split HTML plus index.html. | All active modes. Kinder to the browser. |
-through | Worst-slack path through that pin, with segment percents. | S = slack-ish split, D = delay, B = budget in the nearby printout. |
-warning_pins | Impossible constraints, missing budgets, pins with no paths. | Pair with -verbose for the reason column. |
-feedthroughs | Visit pins, frozen flags, Manhattan, budget versus delay. | CSV needs -csv and a .csv filename. |
-latency | Clocks crossing block boundaries. | Median latency and fanout, grouped into clock groups. |
-default | Ignore current plan.budget.*. | Same honesty as compute / write -default. |
icc2_shell> report_budget -blocks
icc2_shell> report_budget -html_dir budget_html
icc2_shell> report_budget -warning_pins -verbose > warning_pins.txt
icc2_shell> report_budget -through [get_pins \
{u_cpu_cluster/cpu_npu_data[0]}]
Warning-pin reasons you will actually see: clock_pin (the pin is on a clock network), false_path (every path through it is a false path), unclocked_endpoint, unconstrained_input_port. A bidirectional pin is expected to have at least one input delay and one output delay; a missing direction with no path in that direction shows up here. That is a constraint gap, not a router bug.
| You see | It means | What you do |
|---|---|---|
| ABS-240 | Budget is based on estimated_corner delays. | Expected after VIPO-mode compute. Do not call it signoff. |
clock_pin | The pin is part of a clock network. | Do not expect a data-path budget through it. |
false_path | Exceptions cover every path through the pin. | Confirm the exception was meant. |
unclocked_endpoint | The named pin has no clock. | Fix the clock, not the leftover channel. |
unconstrained_input_port | That top port has no constraint. | Look at the port. Do not rerun compute first. |
| Return 1, empty taste | Quiet success. | -warning_pins -verbose before you write files. |
report_budget is the taste. ABS-240 tells you the window was cut with estimated_corner, which is information, not a pass sticker.
Start with -blocks so you know which rooms were actually declared. Then -warning_pins -verbose so missing paths have a reason, not a shrug. Then -through on a door you care about so you can see the percent inside versus outside. HTML is a browser report; -html_dir splits it so the browser does not choke.
What you must not do is write files because compute returned 1. Warning pins that are clock pins are expected. Warning pins that are unconstrained input ports are a Chapter 3 leftover, not a leftover-channel geometry problem.
Part 10 — write_budgets writes files you can source
A computed budget is not a written budget. write_budgets writes a directory (default ./budgets) with one folder per reference, a top.tcl that sources mode and corner files, and a mapfile whose keyword is BUDGET. Those files put this same clock waveform onto a virtual clock — a clock with the waveform and no source in the netlist — then hang set_input_delay and set_output_delay off its edges. Budgets apply to boundary paths, not to internal combinational segments. Whenever you write a new budget, you must source that block’s top.tcl again. A new file overwrites the old boundary constraints.
Source order is not a style. Source split constraints first, then the budget. Budget is not a replacement for Chapter 3.
| Switch | What it does | Teaching note |
|---|---|---|
-blocks | Only named instances. | They must already be in -add_blocks. Else it is an error. |
-top | Write a budget for the top. | Top always gets a full budget. |
-output | Directory name. | Default ./budgets. |
-force | Overwrite an existing directory. | Without it, a second write refuses the folder. |
-shell_subblocks | Write budget shells for those references. | Forces a full budget on the parent. Not tapeout. |
-full_budget_blocks | Full, not incremental, for those modules. | Or set plan.budget.all_full_budgets and read it back. |
-default | Ignore current plan.budget.*. | Pair mentally with compute -default. |
-format | dc | icc2 | This book’s cook is icc2 unless you said otherwise. |
write_budgets -all_blocks. The command page this chapter sat with lists -blocks, -top, -shell_subblocks, and friends, not -all_blocks (-all_blocks is on create_abstract). New Tcl writes the instances you already declared with -blocks, or confirms -all_blocks with man write_budgets on your release. Do not invent the switch from a table caption.icc2_shell> write_budgets -blocks [get_cells \
{u_cpu_cluster u_npu_core_0 u_npu_core_1}] \
-force -output budgets
# Later, inside a block. Split first, then budget
icc2_shell> set_constraint_mapping_file split/mapfile
icc2_shell> source split/CPU_CLUSTER/top.tcl
icc2_shell> set_constraint_mapping_file budgets/mapfile
icc2_shell> source budgets/CPU_CLUSTER/top.tcl
set_constraint_mapping_file without -reset appends. That rule is still true from Chapter 12. If you meant to replace the map, say -reset. Optional: update_constraint_mapping_file -remove_blocks before you source. App options that change what is written: plan.budget.all_design_subblocks, all_full_budgets, allow_top_only_exceptions, hold_buffer_margin, pessimistic_driving_cells, write_hold_budgets. Read them back. Do not invent defaults.
A computed budget lives in the session. A written budget is a directory you can source, and you source it after Chapter 3’s split files, not instead of them.
Default folder is ./budgets. Each reference gets top.tcl, mode files, and corner files. The mapfile keyword is BUDGET. -force overwrites. Instances you never passed to -add_blocks are an error on -blocks. A new source overwrites previous boundary constraints for that block.
What you must not do is treat CTS_CONSTRAINT or SDC as this chapter’s keyword, or append a second mapfile and wonder why both families of files are still in play. Without -reset, mapping appends. Confirm with man.
Part 11 — A budget shell is a stand-in, not tapeout
A budget shell is a macro-like representation of the I/O timing and physical interface of a room. The parent can explore while the child is still a promise. Paths that used to walk into the child become budgeted paths to the shell ports. write_budgets -shell_subblocks takes reference names and forces a full budget on the parent. Incremental budgets are not allowed on that parent.
For final chip production to generate a tapeout database, do not use the budget-shell flow. Use implemented blocks, starting from RTL. That sentence is the nearby note, said out loud so a shell cannot hide as a finished chip.
By default the shell keeps PG pins and multivoltage Liberty attributes (voltage map, related power and ground, isolation, level-shifter ranges, and friends). Set mv.hierarchical.include_pg_in_budget_shell false only if you mean to drop them. Read it back. After the shell: reset, reload UPF for top and shells separately, commit_upf, then source the shell timing files. The nearby cook also names a shell environment variable, SYNOPSYS_LC_ROOT, as a prior for Liberty Compiler when writing shells. Name it. Do not invent a path.
# References, not a feeling. Query get_cells / ref_name first icc2_shell> set_budget_options -add_blocks [get_cells \ {u_cpu_cluster u_npu_core_0}] icc2_shell> compute_budget_constraints -setup_delay -boundary \ -latency_targets actual -balance true # Optional: freeze a percent slice after compute icc2_shell> set_pin_budget_constraints -internal_percent 40 -all icc2_shell> write_budgets -shell_subblocks {CPU_CLUSTER NPU_CORE} \ -output budget_shell
A nearby script writes get_cells "B_cell" "C_cell" as two arguments. Teaching Tcl passes one list: [get_cells {u_cpu_cluster u_npu_core_0}]. Confirm with man.
A budget shell is a stand-in of I/O timing so the parent can explore. It is not a tapeout block, and the nearby note says so in one sentence.
-shell_subblocks takes reference names and forces a full budget on the parent. Reload UPF for top and shells, commit, then source the shell timing files. SYNOPSYS_LC_ROOT is a named prior for Liberty Compiler. Do not invent the path in this book.
What you must not do is ship a shell as the production database, or mix an incremental budget on a parent that already owns a shell child. Default shells keep PG and multivoltage attributes. Turn that off only when you mean it, and read the option back.
Part 12 — Mapping, MIB, and the black-box delay
Three mapping keywords now live in this book. Chapter 3: SDC and UPF. Chapter 12: CTS_CONSTRAINT. This chapter: BUDGET. set_constraint_mapping_file without -reset appends. Read the mapfile. Do not hope.
MIB: two copies, one drawing. The first instance in -add_blocks is the master. Its clocks win. Pin slices you want shared use -same_as_mib on set_pin_budget_constraints. Copies are still u_npu_core_0 and u_npu_core_1, sharing NPU_CORE.
Black-box delay: plan.budget.bbt_fixed_delay was named in Chapter 5. This is the cook it sits in. If the black-box number was measured, keep the tool from “improving” it. If it was a guess, set the option false and take the tightened figure to the owner. Read it back. Do not re-teach black boxes here.
To run the same abstract script on several rooms, run_block_script still exists from earlier chapters. Parallel work is a host-options object, not a feeling.
Mapping appends unless you reset. MIB clocks follow the first instance you added. The black-box delay option is decided here, not re-derived from Chapter 5.
Source split files, then budget files. Keyword BUDGET is not CTS_CONSTRAINT. If both NPU copies are budgeted, say which instance is master by putting it first in -add_blocks.
What you must not do is leave plan.budget.bbt_fixed_delay untouched “because Chapter 5 already mentioned it” without saying, on this chip, whether each remaining box was measured or guessed. The option is a decision, not a souvenir.
Inputs, outputs, and readiness
| Kind | Object | Honesty rule |
|---|---|---|
| Input | Split top and block SDC / UPF | Chapter 3. Budgeting needs separate files. |
| Input | Shaped blocks, leftover channel | Channel 2.091 mm² = 2,091,000 µm². |
| Input | Compiled PG mesh | M4/M5 still 20 µm. Not estimate layers you steal. |
| Input | Bus map and clock spine | Chapters 11 and 12. Clock pins stay fixed. |
| Input | Placed pins | Chapter 13. Merge if they were placed on an abstract. |
| Input | Queried clocks, pins, nets, layers | Stand-ins in this book are not a netlist. |
| Output | Timing abstracts with estimate data | Lowest hierarchy only, if MPH. |
| Output | Annotations on estimated_corner | Artificial. Taste, then compute. |
| Output | ./budgets/<ref>/top.tcl and a BUDGET mapfile | Source after split. Boundary paths only. |
| Not output | A finished CTS tree or place_opt | Implementation still waits. |
| Not output | A tapeout shell | A budget shell is exploration. |
Preflight: split files exist; pins placed and merged if needed; clock pins still fixed; rooms named; clk_cpu period said out loud as 625 ps; remaining window said out loud as 550 ps on the wave; MIB master said out loud; plan.budget.bbt_fixed_delay decided for any remaining box.
Guided tool workflow
| Step | You do | Command |
|---|---|---|
| 1 | Confirm split files and mapping. | set_constraint_mapping_file split/mapfile |
| 2 | Merge pin changes if pins were placed on an abstract. | merge_abstract |
| 3 | Lighten lowest rooms. | create_abstract -estimate_timing |
| 4 | Virtual rehearsal at the top. | estimate_timing |
| 5 | Taste the artificial corner. | report_timing -corners estimated_corner |
| 6 | Name rooms. MIB master first. | set_budget_options -add_blocks |
| 7 | Optional manual slice. | set_pin_budget_constraints |
| 8 | Split the remaining window. No obsolete flag. | compute_budget_constraints -setup_delay -boundary |
| 9 | Taste. | report_budget -warning_pins -verbose |
| 10 | Write, then source after split. | write_budgets -force |
Validation gates: report_abstracts shows timing abstracts with compression you can point at; estimated_corner exists and was read; ABS-240 is expected or explained; warning pins are owned; mapfile contains BUDGET; leftover still 2.091 mm²; teaching split still labelled an estimate.
One continuous worked example
Nimbus-8. Library nimbus8.dlib. Top NIMBUS8. Leftover 2.091 mm² = 2,091,000 µm². clk_cpu 1.60 GHz = 625 ps. Remaining window 550 ps on the wave. Teaching split 190 leftover / 150 CPU / 210 NPU. Pins already placed. Clock pins already fixed.
# Teaching stand-ins. Query before you copy
icc2_shell> open_block nimbus8.dlib:NIMBUS8
icc2_shell> set_constraint_mapping_file split/mapfile
icc2_shell> source split/NIMBUS8/top.tcl
icc2_shell> set_app_options -name abstract.enable_improvements_for_budgeting \
-value true
icc2_shell> report_app_options abstract.enable_improvements_for_budgeting
icc2_shell> create_abstract -estimate_timing -blocks \
{CPU_CLUSTER NPU_CORE ISP}
icc2_shell> report_abstracts
icc2_shell> estimate_timing
icc2_shell> report_timing -modes [all_modes] -corners estimated_corner
icc2_shell> set_app_options -name plan.budget.estimate_timing_mode -value true
icc2_shell> report_app_options plan.budget.estimate_timing_mode
icc2_shell> set_budget_options -add_blocks [get_cells \
{u_cpu_cluster u_npu_core_0 u_npu_core_1}]
icc2_shell> set_pin_budget_constraints \
[get_pins {u_cpu_cluster/cpu_npu_data[0]}] \
-internal_percent 40
icc2_shell> compute_budget_constraints -setup_delay -boundary
icc2_shell> report_budget -warning_pins -verbose > warning_pins.txt
icc2_shell> write_budgets -blocks [get_cells \
{u_cpu_cluster u_npu_core_0 u_npu_core_1}] \
-force -output budgets
Read return 1 as a heartbeat. Read ABS-240 as “cut with the tape measure.” If the NPU copies disagree about clocks, you listed the wrong instance first, or you budgeted only one copy and hoped the drawing would invent the other promise.
Later, inside CPU_CLUSTER: source split/CPU_CLUSTER/top.tcl, then budgets/CPU_CLUSTER/top.tcl. Mapping keyword BUDGET. Without -reset, a second set_constraint_mapping_file appends.
Failure modes and debugging
| What you see | What it usually is | What you do |
|---|---|---|
| Latency 5 on a 625 ps clock | A nearby example copied as nanoseconds. | Query units and get_clocks. Teaching latency is a small slice, labelled estimate. |
| Clip 1.0, period 0.625 | Nearby maximum_net_delay 1.0 if the unit is ns. | Do not copy 1.0. Query is_et_delay_clipped. |
compute_budget_constraints -estimate_timing warned or vanished | Obsolete switch. | plan.budget.estimate_timing_mode. Confirm with man. |
-inputs rejected on compute | Nearby table used the plural. | Type -input. Pin-constraint command is the one with -inputs. |
write_budgets -all_blocks rejected | Nearby table, not the command page this chapter sat with. | Write -blocks of declared instances. Confirm with man. |
| Child netlist changed during estimate | Illegal child view. Singular feedthrough-buffer step inside estimate. | Legal views first. Read plan.estimate_timing.abstract*. |
Incremental -pins did nothing useful | No prior full run. | Full estimate_timing first. |
| Second mapfile, both families still live | Append without -reset. | Same muscle as Chapter 12. Say -reset if you meant replace. |
Warning pin unconstrained_input_port | Chapter 3 gap, not a leftover-channel bug. | Look at the port. Do not recompute first. |
| Shell treated as tapeout | Exploration stand-in shipped. | Implemented blocks from RTL. The nearby note forbids the shell for production. |
| Return 1, no files on disk | Quiet success: compute is not write. | write_budgets -force, then source after split. |
| Black-box path fails with nowhere to look | plan.budget.bbt_fixed_delay left true on a guess. | Chapter 5 decision, cooked here. Set false if it was a guess; take the number to the owner. |
Hands-on mini lab — Aldebaran-4
Aldebaran-4 has a core that is a square 900 µm = 0.900 mm on each side, so an area of 0.810 mm² = 810,000 µm². Two blocks, one leftover strip between them. One clock at 1.00 GHz = 1,000 ps. Teaching taxes 50 ps uncertainty and 30 ps setup, so the remaining window is 920 ps. No MIB. Pins already placed. Split files already exist.
- Query clocks, pins, and layers. Do not invent names from this page.
- Create timing abstracts with
create_abstract -estimate_timing. Readreport_abstracts. - Run
estimate_timing. Read return 1 as a heartbeat. Tastereport_timing -corners estimated_corner. - Set
plan.budget.estimate_timing_modeand read it back. Do not type the obsolete compute flag. - Add both block instances with
set_budget_options -add_blocks. Put a 40 percent internal slice on one queried data pin. - Compute with
-setup_delay -boundary. Tastereport_budget -warning_pins -verbose. Write with-force.
You are done when the remaining 920 ps is a window you can point at on a square wave, estimated_corner was read, warning pins are owned or empty, and budgets/<ref>/top.tcl exists to source after split. Label every number an estimate. Do not copy a 5 ns latency onto a 1,000 ps clock.
Interview preparation
1. What is a timing budget, in one honest sentence?
A budget is a promised band on a clock waveform, between launch and capture, after uncertainty and setup. It is not a measured delay, and it is not signoff.
Draw clk_cpu. Launch at t = 0. Capture 625 ps later. Taxes: 45 ps after launch, 30 ps before capture. The green window is 550 ps. Teaching split: 150 CPU / 190 leftover / 210 NPU.
An estimate is a gold data edge on estimated_corner. A budget file copies this waveform onto a virtual clock and hangs input and output delays off the edges. Mixing any two is how a later report becomes a mystery.
Query get_clocks. A nearby latency of 5 ns is eight of these waves stacked if you copy it blindly.
2. estimate_timing returned 1. Is the path closed?
No. Return 1 is a heartbeat. The taste is report_timing on estimated_corner, then report_budget after you compute.
The command finished a rehearsal. It stored annotations on an artificial corner. It did not finish CTS. It did not write a budget directory.
Letters on the timing report: e is estimated, * is a delay you annotated by hand, A/a came from create_abstract -estimate_timing.
Quiet success is how a screenshot ships. Same muscle as Chapter 12 and Chapter 13.
3. What is estimated_corner?
An artificial corner that gathers the worst delays from several real corners. It is a tape measure, not a library PVT you tape out.
If corner A is slow on path 1 and corner B is slow on path 2, the mode paired with estimated_corner keeps both. Budgets generated afterwards still cover all corners, modes, and scenarios.
Create it with estimate_timing. Read it with report_timing -modes [all_modes] -corners estimated_corner.
Do not ship it as SS 0.72 V. Do not skip the report because the rehearsal returned 1.
4. Why create a timing abstract before you budget?
So the tool can split the remaining tick on a lighter room whose pins already sit, without dragging every sofa into the top-level estimate.
create_abstract -estimate_timing runs virtual optimisation on interface logic and stores the result. Pins are already placed. Merge first if they were placed on an abstract.
On multiple levels of physical hierarchy, only the lowest rooms become abstracts. Intermediate parents stay design views. Black boxes load SDC and are not pretended to be virtually optimised.
Compression is a number from report_abstracts, not a feeling.
5. In what order do you source split constraints and budgets?
Split first, then budget. A budget file is not a replacement for Chapter 3. The mapping keyword this chapter is BUDGET.
Whenever you write a new budget, source that block’s top.tcl again. The new file overwrites previous boundary constraints.
set_constraint_mapping_file without -reset appends. Chapter 12 already taught that. It is still true.
CTS_CONSTRAINT was the clock-trunk keyword. Do not put it on a budget line.
6. A nearby flow types compute_budget_constraints -estimate_timing. What do you type instead?
Set plan.budget.estimate_timing_mode, run estimate_timing yourself, then compute without that flag. The command page says the switch is obsolete.
If the mode is on and estimated_corner is missing, the tool may run estimate_timing as a side effect. Prefer to run it yourself and read the report.
A nearby table caption also misspells the command as compute_budget_contraints. The command has two s characters in constraints.
Interviewers listen for the conflict, not for a silent copy of the flow picture. Confirm with man.
7. Why must -pins on estimate_timing follow a full run?
Incremental mode updates only the named walk and keeps other annotations from the previous full run. Without that run, there is nothing to keep.
A full run wipes previous annotations and recalculates. That is why you do not use -pins as the first command of the day.
If you moved cells, recreate abstracts for those rooms with -force_recreate (only with -blocks or -all_blocks), then incremental-estimate the walk.
A nearby log’s “36 of 2,093 cells” is a rehearsal count, not QoR.
8. set_pin_budget_constraints -inputs versus compute_budget_constraints -input. Which is right?
Both, on their own pages. The pin-constraint command uses plural -inputs / -outputs. Compute uses singular -input / -output. A nearby compute table uses the plural. New Tcl follows each command page.
Mixing the families is a syntax error. Confirm with man on the command you are typing, not on the command you typed yesterday.
The same muscle as Chapter 13’s -side versus -sides: name the conflict, pick the syntax list, do not invent a third token.
Percent and delay forms on the pin command are mutex. -internal_percent 40 is the textbook inside-the-room slice.
9. What does ABS-240 mean after report_budget?
The budget is based on estimated_corner delays. That is expected after a VIPO-mode compute. It is not a signoff sticker.
Read it as “this window was cut with the tape measure.” Then still run -warning_pins -verbose so missing paths have a reason.
clock_pin is expected on clock network pins. unconstrained_input_port is a Chapter 3 gap. Do not repair it by moving leftover geometry.
Return 1 from compute is still a heartbeat. ABS-240 is a sentence, not a pass.
10. write_budgets -all_blocks from a nearby table. Defend the next line.
The command page this chapter sat with lists -blocks, -top, and -shell_subblocks, not -all_blocks. Write the instances you already passed to -add_blocks, or confirm -all_blocks with man on your release.
-all_blocks is real on create_abstract. Copying it onto write_budgets because a table said so is how a caption becomes a syntax error.
Instances that were never declared with set_budget_options -add_blocks are an error on write_budgets -blocks.
A weak recovery is “I’ll try -all.” A strong recovery is to quote both sources and run man write_budgets.
11. estimate_timing changed a child’s netlist. You thought the room was read-only. What happened?
The child view was not acceptable. The command may open the design view, run add_feedthrough_buffer (singular), then create_abstract -estimate_timing, and retarget the instance. That can change the netlist unless editability is false.
Acceptable children: a design view, or a timing abstract that already carries child-level estimate data. Prefer those, so the tool does not “help.”
The flow cook writes add_feedthrough_buffers (plural). The estimate page writes the singular. Name both. App options live under plan.estimate_timing.abstract*. Read them back.
This is not CTS. It is a side effect of an illegal view. Repair the view, then rerun.
12. A colleague pastes -early_latency 5 -late_latency 5 onto clk_cpu. What do you say?
If the unit is nanoseconds, 5 ns is 5,000 ps. clk_cpu’s period is 625 ps. That is eight ticks of fiction. Query the unit and get_clocks. Teaching latency is a small slice, labelled an estimate.
The same trap as Chapter 12’s nearby -delay 20. A number without a unit you queried is not a Nimbus-8 number.
If you set latency at all, 0.080 ns = 80 ps is a slice you can defend on a 625 ps clock. Label it an estimate. Do not tape it out.
compute_budget_constraints -latency_targets actual -balance true is the automatic family. Manual 5 is not “more precise.” It is a copied example.
13. Both NPU copies share NPU_CORE. After write_budgets the clocks disagree. What did you skip?
The first instance in set_budget_options -add_blocks is the MIB master. Its clocks win for the shared drawing. Copies do not invent a second clock story.
Name the instances: u_npu_core_0 and u_npu_core_1. Put the master you intend first. Pin slices you want shared use -same_as_mib.
This is the same MIB honesty as Chapter 13’s matching doors, now on promised delays rather than metal shapes.
Do not budget only one copy and hope the drawing writes the other folder.
14. You sourced budgets/CPU_CLUSTER/top.tcl and the internal SDC exceptions vanished. Why?
You sourced the budget without the split file, or you treated budget as a replacement for Chapter 3. Budgets apply to boundary paths. Internal constraints live in the split top.tcl.
Correct order: mapping for split, source split top.tcl, mapping for budgets (reset if you meant replace), source budget top.tcl.
A new budget source overwrites previous boundary constraints. It should not be asked to carry the whole internal SDC.
Keyword BUDGET in the mapfile is how the tool finds that file. It is not how it finds Chapter 3.
15. Someone wants a budget shell for tapeout next week. What do you say?
No. A budget shell is a stand-in for top-level exploration. Final chip production uses implemented blocks starting from RTL. The nearby note says that out loud.
write_budgets -shell_subblocks takes reference names and forces a full budget on the parent. Reload UPF, commit, then source the shell timing files. That is exploration.
SYNOPSYS_LC_ROOT is a named prior for Liberty Compiler when writing shells. Do not invent a path in an interview. Name the variable.
Breadth is knowing the shell exists. Recklessness is shipping it as the database.
16. Pins are done. Budgets are written. Someone asks you to run place_opt in the same script. What do you say?
This chapter ends with promises you sourced. Implementation still waits. Mixing place_opt into a budget cook hides both plots.
What you can say, cleanly: leftover still 2.091 mm²; M4/M5 still mesh; clock pins still fixed; doors still sit; remaining window 550 ps split 190 leftover / 150 CPU / 210 NPU, labelled estimate; BUDGET mapfile written; warning pins owned.
The design-planning cook that this book sat with ends at budgeting. The next work is implementation, not a fifteenth planning verb invented in the same session.
Breadth is naming that boundary. Recklessness is pasting place_opt into a session whose budget files you have not sourced.
Chapter close
Sign-off checklist for this planning stage
- You can point at launch, capture, period, uncertainty, setup, and the remaining 550 ps window on a
clk_cpuwaveform. - Clocks, pins, nets, and layers were queried, not invented.
clk_cpuwas said as 1.60 GHz = 625 ps. Remaining window was said as 550 ps on the waveform. Teaching split 190 leftover / 150 CPU / 210 NPU was labelled an estimate.- Pins from Chapter 13 were already placed. Clock pins from Chapter 12 stayed fixed.
- Abstracts used
create_abstract -estimate_timing. MPH kept intermediate parents as design views. estimate_timingreturn 1 was followed byreport_timing -corners estimated_corner.- The obsolete compute flag was refused.
plan.budget.estimate_timing_modewas read back. report_budget -warning_pinswas read. ABS-240 was treated as information.write_budgetswrote files. They were sourced after split. Mapfile keyword isBUDGET.- A budget shell, if used, was not called tapeout.
plan.budget.bbt_fixed_delaywas decided for any remaining box. - Implementation was not mixed into this script.
Key-concept flashcards
The whole tick. clk_cpu is 625 ps. Not a budget.
Launch, then capture. 625 ps. Taxes 45 + 30. Window 550 ps.
A promised band on that window. Not a measured delay. Not signoff.
Artificial tape measure. An e is estimated. A * is yours.
estimate_timing is a rehearsal. Return 1 is a heartbeat.
Light room, pins already sit. Lowest hierarchy only, if MPH.
compute -estimate_timing is retired. Use the app option.
BUDGET this chapter. Appends without -reset.
Compute is not write. Source after split.
Stand-in for exploration. Not tapeout.
First instance in -add_blocks. Its clocks win.
Promises are written. Implementation still waits.
Compact glossary
| Term | Meaning as used in this book |
|---|---|
| Launch edge | Rising tick that starts the walk. Time zero on the teaching wave. |
| Capture edge | Next rising tick that must catch the data. 625 ps later on clk_cpu. |
| Remaining window | Period minus teaching taxes. 550 ps on clk_cpu. A pie is only a nickname for this band. |
| Budget | A promised band on that window, written as boundary delays on a virtual clock. |
| Virtual clock | The same waveform, no netlist source. What write_budgets uses. |
| Budget shell | A stand-in of I/O timing for parent exploration. Not tapeout. |
| BUDGET | Mapping-file keyword for this chapter’s files. |
estimated_corner | Artificial corner created by estimate_timing. |
| Remaining tick / pie | Period minus teaching taxes. 550 ps on clk_cpu. |
| Timing abstract | A lighter room with interface timing, pins already placed. |
| VIPO | Virtual in-place optimisation: estimate_timing. |
| Budget slack | How much actual delay sits under the promised delay. |
| MIB master | First instance in -add_blocks. Its clocks characterise the drawing. |
| Quiet success | Return 1. Taste is the report, then the written file. |
Five-question self-check
Antares-2 has a core that is a square 1,100 µm = 1.100 mm on each side, so an area of 1.21 mm² = 1,210,000 µm². Two copies of one reference. One clock at 800 MHz = 1,250 ps. Teaching taxes 45 ps + 30 ps, so the remaining window is 1,175 ps. Pins already placed. Split files already exist.
- A colleague draws a 625 ps
clk_cpuwave and paints the whole tick green for the NPU room. What two taxes did they skip, and what remaining window should they have painted? - You run
estimate_timing -pinsas the first command of the day. Why is that incomplete, and what do you run first? - You type
compute_budget_constraints -inputsand the tool rejects it. Why, and which other command uses the plural? - After write, Antares-2’s two copies disagree about clock latency in the budget files. Which
set_budget_optionsrule did you skip? - A colleague asks to tape out the budget shell you just wrote for Antares-2. What do you say, and which nearby prohibition do you quote?
Answers.
1. They skipped 45 ps of uncertainty after launch and 30 ps of setup before capture. The remaining window on Nimbus-8’s clk_cpu is 550 ps, not 625 ps. (Antares-2’s own remaining window would be 1,175 ps.)
2. Incremental -pins needs a previous full run so other annotations have somewhere to stay. Run full estimate_timing first, taste estimated_corner, then incremental.
3. Compute’s command page uses singular -input / -output. A nearby table uses the plural. The plural lives on set_pin_budget_constraints -inputs. Do not mix the families. Confirm with man.
4. The first instance in set_budget_options -add_blocks is the MIB master. Its clocks are used for the generated budget. Name both copies and put the intended master first.
5. No. A budget shell is a stand-in for exploration. Final chip production uses implemented blocks starting from RTL. That is the nearby prohibition, said out loud.
Why implementation follows, and this chapter stops
The leftover channel now has a bus map, a clock spine, a set of doors you checked, and a set of promised slices you can source. The mesh still holds power. The remaining 550 ps on clk_cpu is split on paper as 190 leftover / 150 CPU / 210 NPU, labelled an estimate. What the chip still lacks is the implementation that turns those promises into placed cells, a real clock tree, and a path you would weigh. That work is not a tail on write_budgets. This chapter ends with budgets. The next session, after you have reviewed this one, begins at implementation — not at a fifteenth planning verb invented in the same cook.