Margin starts full and only shrinks: each overrun spends a little, each replan spends a lot, and nothing restores it except descoping. A project that plots margin monthly sees trouble quarters ahead; one that re-baselines it quarterly sees nothing until tapeout. NanoSoC's headroom of 0.285 mm2 and illustrative power margin show the shape on numbers small enough to check by hand.
Pick one margin per budget — area headroom, power band, bandwidth headroom on the tightest link — and plot remaining margin against time with two trigger lines. The watch line (half spent) starts monthly review of the spending rows. The act line (three-quarters spent) freezes new scope and forces covers for every further draw. Never re-baseline silently: declaring fresh margin because the old chart looks bad wipes the project's memory of every decision. A larger die budget is allowed, but only as a change-board entry that keeps the old chart and starts a new segment with its reason; an equal descoping entry is another allowed way to restore margin. A single large draw can jump over the watch line straight onto the act line, so project the chart before approving a reservation, not after.
# not-run: NanoSoC area margin burn-down, teaching values
Start: headroom 0.285 mm2 (budget 0.940 minus core 0.655).
Month 2: fabric overrun draws 0.006 -> remaining 0.279 (2.1% spent).
Month 4: hypothetical 128 KB RAM reserved (not in the NanoSoC map): 0.200 mm2
of blocks, 0.224 mm2 with the 12% overhead -> remaining 0.055 (80.7% spent).
The watch line (50%) and the act line (75%) both fire this month.
Month 5: second DMA 0.020 mm2, 0.0224 mm2 with overhead -> remaining 0.0326
(88.6% spent).
Verdict: scope freezes in month 4; anything larger than the second DMA needs
descoping or a change-board entry that starts a new chart segment.The script runs the burn-down, fires the trigger lines at the right months, and rejects a re-baseline.
start, budget = 0.285, 0.940
overhead = 1.12
draws = [(2, "fabric overrun", 0.006),
(4, "hypothetical 128 KB RAM reserved, with overhead", 0.200 * overhead),
(5, "second DMA, with overhead", 0.020 * overhead)]
remaining, first = start, {}
history = [(0, start, "start")]
for month, why, amount in draws:
assert why # every draw names its cause
remaining = round(remaining - amount, 4)
spent = (start - remaining) / start
if spent >= 0.50 and "watch" not in first:
first["watch"] = month
if spent >= 0.75 and "act" not in first:
first["act"] = month
history.append((month, remaining, "draw"))
# The lines fire in the right month: not before month 4 (2.1% spent at month 2).
assert first == {"watch": 4, "act": 4}, first
assert abs(remaining - 0.0326) < 0.0005, remaining
# Project before approving: the 0.224 reservation would jump both lines at once.
def projected(rem, amount):
return (start - (rem - amount)) / start
assert projected(0.279, 0.224) >= 0.75
assert projected(0.279, 0.112) < 0.50 # a 64 KB reservation alone would not
# No silent re-baseline: margin may rise only through a board-segment entry.
def valid(h):
return all(b[1] <= a[1] or b[2] == "board-segment" for a, b in zip(h, h[1:]))
assert valid(history)
assert not valid(history + [(6, 0.285, "draw")]) # silent reset is caught
assert valid(history + [(6, 0.100, "board-segment")])
print(f"PASS: margin {start} -> {remaining:.4f}; watch and act both fire in month {first['act']}; no silent re-baseline")One burn-down chart per budget, updated on the same cadence, with trigger lines drawn.
Every draw names its cause: overrun, growth reservation, or scope addition.
No silent re-baselining: a restored or larger budget appears only as a descoping entry or a change-board entry that keeps the old chart and starts a new segment with its reason.
Check the arithmetic before the story: remaining must equal start minus the sum of draws, and a chart that does not add up is hiding a draw. Then check the dates: a draw recorded months late means the review cadence slipped, and the next miss will also arrive late.
Keep one chart per budget, not one chart for the project: area headroom burns when estimates sharpen, power margin burns when activity assumptions change, and bandwidth headroom burns when use cases are added. The three rarely move together, and a single blended chart hides which budget is actually binding. The review reads the tightest chart first and spends its time there; the comfortable charts get a glance and a nod.
Because the chart is the project's memory of spending. Resetting it hides past decisions without undoing them; the die still carries every draw. A larger budget is allowed only as a change-board entry that keeps the old chart and starts a new segment with its reason, or as a descoping of equal size.