A dashboard is a photograph; tapeout is a date. The trend turns weekly photographs into a slope, and the slope says whether the remaining reds burn down before the signoff-complete date or whether the plan is fiction. Integrators who cannot read the slope discover the slip the week it happens. This lesson computes the slope on NanoSoC teaching data and states the call rule. Its one job is the prediction; the meeting that hears it is the next topic.
Plot open violations per discipline per week and fit a least-squares line over the last four weeks: its slope is the burn-down rate. Divide the remaining opens by the rate for the weeks to zero, then compare against the signoff-complete date with a one-week margin, because the last violations are always the hardest. A flat line with nonzero opens is not stability, it is a stall, and the script below labels it as one instead of failing: either the owners are fixing without closing the reports, or the fixes are not landing. A slope that depends on waivers rather than fixes is refinancing, not progress: the opens fall because excuses rose, and the escape topic prices that trade. Weeks here are project weeks counted from day 0: day 150 is week 22, and the signoff-complete date is week 26. Violations fixed between the design freeze and week 26 are post-freeze changes and carry the gates of the ECO topic.
# Burn-down by least-squares slope over the last four weeks.
# Counts are illustrative; weeks 18 to 22, so the last point is day 150.
WEEK = 22
SIGNOFF_WEEK = 26 # signoff-complete date (day 182)
MARGIN = 1
opens = {"timing": [6, 4, 3, 2, 1], "physical": [14, 11, 9, 7, 5],
"crossings": [6, 4, 4, 3, 2], "verification": [11, 9, 7, 6, 4],
"connectivity": [3, 3, 3, 3, 3]}
def burn(ys):
recent = ys[-4:]
xs = range(len(recent))
xm = sum(xs) / len(recent)
ym = sum(recent) / len(recent)
num = sum((x - xm) * (y - ym) for x, y in zip(xs, recent))
den = sum((x - xm) ** 2 for x in xs)
return -num / den # opens removed per week
def call(ys):
rate = burn(ys)
if rate <= 0:
return "stalled"
weeks_to_zero = ys[-1] / rate
ok = WEEK + weeks_to_zero + MARGIN <= SIGNOFF_WEEK
return "on track" if ok else "slipping"
assert abs(burn(opens["timing"]) - 1.0) < 1e-9
assert abs(burn(opens["physical"]) - 2.0) < 1e-9
assert abs(burn(opens["crossings"]) - 0.7) < 1e-9
assert abs(burn(opens["verification"]) - 1.6) < 1e-9
calls = {d: call(ys) for d, ys in opens.items()}
assert calls == {"timing": "on track", "physical": "on track",
"crossings": "on track", "verification": "on track",
"connectivity": "stalled"}, calls
# a slow burn-down must be called slipping: 1 open per week from 9
assert call([14, 12, 11, 10, 9]) == "slipping"
print("PASS: four disciplines on track for week 26, connectivity stalled")The trend page shows four weeks minimum, per discipline, with fixes and waivers plotted separately.
Any stalled or waiver-driven slope is annotated with its cause before the review, not discovered in it; the stalled connectivity line above is the case to chase first.
The call, on track or slipping, is written above the plot with the weeks-to-zero arithmetic attached.
When the slope flatters, split it: re-plot with waivers removed and watch whether fixes alone still reach zero. When a discipline stalls two weeks running, walk its open list with the owner: the usual causes are one hard violation blocking ten trivial ones, or fixes landing in a branch the checker never sees. Both are visible in the manifest once you look.
# not-run: the call rule, NanoSoC teaching values
weeks to zero = opens now / least-squares burn-down per week over last 4 weeks
stalled = burn-down rate zero or negative: say so, do not compute a date
on track = zero date + 1 week margin is on or before signoff-complete week 26
slipping = anything else; the review hears the new date, not hopeNo: the drop is refinancing through waivers, not progress. Re-plot fixes-only; if that slope misses the signoff-complete date, the date moved even though the photograph looks better.