A budget that is never re-measured is not a budget. The spreadsheet says 0.040 mm2 for the fabric; synthesis reports 0.044 (10% over); the floorplan needs 0.048 with buffering (20% over). None of these is wrong — each measures a different thing — but without a handoff discipline the three numbers drift and the overrun is discovered at tapeout. Budgets move in stages, and each stage re-measures the same rows with a sharper tool.
There are four stages, with four owners. Estimation assigns each block a budget from the ledger before RTL exists; the integrator owns this. Synthesis measures gate area against the budget per partition; the block owner explains any excess. Floorplanning adds real buffering, spacing and macro halos; the layout owner re-reports the same rows. Signoff closes them: any row still over budget needs a waiver with a compensating saving elsewhere, or a budget change through governance. The rule that holds it together: the row names and the units never change between stages, only the measurement sharpens.
Stage | Measures | Owner | If over budget |
|---|---|---|---|
Estimation | Spreadsheet per block | Integrator | Cut scope or grow the die budget now |
Synthesis | Gate area per partition | Block owner | Re-synthesise, restructure, or trade with a neighbour |
Floorplan | Placed area with buffers and halos | Layout owner | Re-floorplan or request a budget change |
Signoff | Final routed area | Integrator | Waiver with compensation, or change the budget |
The fabric synthesises at 0.044 mm2 and needs 0.048 mm2 once the floorplan adds buffering, against its 0.040 budget: 0.008 over after floorplanning. The SBR measures 0.008 against its 0.010: 0.002 under. Rebalancing moves 0.002 of slack from the SBR to the fabric and draws 0.006 from the area headroom (0.285 becomes 0.279), or the fabric owner restructures instead. The same story is told on the change-process and burn-down pages. The script below runs the ledger arithmetic through both stages and fails if the cover does not equal the overrun.
budgets = {"xbar": 0.040, "sbr": 0.010, "dma": 0.012}
synth = {"xbar": 0.044, "sbr": 0.008, "dma": 0.012}
placed = {"xbar": 0.048, "sbr": 0.008, "dma": 0.012}
over_synth = {b: round(synth[b] - budgets[b], 3) for b in budgets}
over = {b: round(placed[b] - budgets[b], 3) for b in budgets}
assert over_synth["xbar"] == 0.004 and over["xbar"] == 0.008, (over_synth, over)
assert over == {"xbar": 0.008, "sbr": -0.002, "dma": 0.000}, over
# Rebalance: move SBR slack to the fabric; remainder is drawn from headroom.
transfer = min(over["xbar"], -over["sbr"])
assert transfer == 0.002
headroom_draw = round(over["xbar"] - transfer, 3)
assert headroom_draw == 0.006
headroom = 0.285
after = round(headroom - headroom_draw, 3)
assert after == 0.279, after
# The books balance: cover equals overrun, nothing is left unexplained.
assert round(transfer + headroom_draw - over["xbar"], 9) == 0
print(f"PASS: xbar +0.008 covered by sbr trade 0.002 + headroom draw {headroom_draw:.3f}; headroom {headroom} -> {after}")One ledger with the same row names at every stage; no renamed or split rows between synthesis and layout.
Each overrun names its cover: a trade, a restructuring, or a governed budget change.
The headroom draw-down is cumulative and visible, not reset each month.
Diff the row names between stages before diffing the numbers: a renamed row hides an overrun better than any rounding. Then check units — library area in square microns versus the ledger in square millimetres has caused at least one false alarm per project. A sudden 1,000,000x overrun (square microns read as square millimetres) is a units bug, not a design bug.
The overhead line deserves its own re-estimate after the first trial route: congestion around the SRAM macros and the bridge crossings is where NanoSoC's 12% is won or lost. If the trial route reports 15%, the ledger moves to 15% that week and every row's headroom shrinks accordingly; waiting for final route to admit it compresses the response into the worst moment. The integrator's habit is simple: re-measure overhead at every stage gate and publish which rows the new number endangers.
Because the ledger is compared stage to stage. A renamed row breaks the comparison and lets an overrun hide as a new entry with no history.