Roadmap — Post-Phase-0 work scheduling
Status: Active. ADR 0008 accepted 2026-05-02. ADR 0007 still pending.
This document orders the work captured in those two ADRs alongside the in-flight tail of Phase 0. It is a scheduling doc, not a design doc — design lives in the ADRs and in docs/timing-model-extensions.md / docs/why-jacquard.md.
Where things stand (2026-05-02)
- Phase 0 (
phase-0-ir-and-oracle.md): WS1–WS5 + WS2.2 + WS2.4 all landed. WS2.4 multi-corner shipped 2026-05-02 across four commits (5822343consumer,530bb36builder,59fde04producer, plus the integration test). Open items: sky130-based corpus entries (gated on a CI sky130-Liberty install strategy) and peripheral wiring for I²C/SPI when a fuller mcu_soc fixture lands. - OpenTimer spike (
spikes/opentimer-sky130.md): resolved 2026-05-01 — Superseded. Q1 (Liberty parse) passed cleanly on SKY130; Q2 (arrival computation) failed on the canonical OpenSTA-bundled GCD example after eight input-pipeline workarounds (bus ports, OpenROAD-emitted SPEF, modern TCL, tap cells). Per the spike's decision matrix, ADR 0003 is now Superseded (commitd002bde). OpenSTA out-of-process is committed as Jacquard's sole STA path —opensta-to-iris the canonical preprocessor; no in-process reference STA is planned. A future ADR may revisit libreda-sta or an in-house walker if an in-process reference is wanted later, but not on this roadmap. - Pillar B Stages 1+2 (per
adr/0007): landed.ClockArrivalIR table +opensta-to-irTcl emission in commitc403cc8;DFFConstraint.clock_arrival_ps+ skew-aware fold-in inbuild_timing_constraint_bufferin6767c3e. Closed Pillar B's main accuracy lever ahead of this roadmap's original Phase 2 schedule. - ADR 0006 amended 2026-05-02: subprocess invocation of user-installed OpenSTA from the shipped runtime is now permitted (no linking, no bundling). Phase 3 (native Rust SDF→IR) is no longer release-gating — see § Phase 3 below. New release-hardening workstream WS-RH.1 (OpenSTA detection + version check) is required before first release; see § Release hardening.
- ADRs 0007 / 0008: ADR 0008 accepted 2026-05-02; ADR 0007 still pending review.
Phase boundaries
The phase numbering established by Phase 0 and ADR 0006 continues:
| Phase | Topic | Trigger |
|---|---|---|
| 0 | Timing IR + OpenSTA preprocessor | In flight, near close |
| 1 | Structured timing output (ADR 0008 required items) + Phase 0 carryover | ADR 0008 accepted ✓ |
| 2 | Timing model fidelity Pillar C Tier 1 + Pillar B Stage 3 if needed (ADR 0007) | Phase 1 lands; ADR 0007 accepted |
| RH | Release hardening (OpenSTA detection + version check, see § Release hardening) | WS-RH.1 shipped ✓; no other items currently scoped |
| 3 | Native Rust SDF→IR parser (ADR 0006) | Deferred indefinitely — no longer release-gating per amended ADR 0006. Picks up when bandwidth allows or commercial demand appears. |
| 4+ | Pillar A Stage 1 (static IDM); Pillar C Tier 2; ADR 0008 optional outputs | Demand-driven; not committed |
Parked (require new ADR to revive): in-process reference STA (ADR 0003 superseded), Pillar A Stage 2 (dynamic δ(T)), Pillar A Stage 3 (sub-cycle ticks), NoC-aware partitioning hints (Pillar C Tier 3).
Phase 1 — Structured timing output and Phase 0 wrap-up
Entry criteria:
- ADR 0008 accepted.
- Phase 0 exit criteria met (per
phase-0-ir-and-oracle.md).
OpenTimer integration was originally Phase 1's centrepiece (former WS-P1.1) but was retired when the spike Superseded ADR 0003. With OpenSTA-out-of-process as the sole STA path, Phase 1 is now anchored on user-visible output rather than a second STA tool.
Workstreams (parallel where independent):
WS-P1.1 — Structured timing output (ADR 0008 required items)
The four required items from ADR 0008. Single workstream because they share infrastructure.
- WS-P1.1.a — Symbolic violation messages. Shipped 2026-05-02 in commit
0432d9a. NewWordSymbolMapinsrc/flatten.rsbuilt once at sim startup;process_eventsgained an optional resolver closure;sim_metalthreads it through. Setup/hold violation messages now name DFFs astop/cpu/regs[7][bit 22] [word=42]instead of bareword 42. CUDA/HIP sim paths don't currently route runtime violations throughprocess_events(separate plumbing gap, not blocked on this format change). - WS-P1.1.b —
--timing-report <path.json>. Shipped 2026-05-02 in commit58a7a04. Newsrc/timing_report.rsmodule with serde-derivedTimingReport(schema_version 1.0.0);process_eventstakes aReportingCtxbundling the optional resolver + violation observer (signature back to 5 args);sim_metalbuilds the report end-to-end. Sample fixture attests/timing_ir/sample_reports/two_violations.json; schema documented indocs/timing-violations.md. WS-P1.1.d's worst-slack ranking is included (top-10 per kind from violation events). Caveats: closest-to-violation tracking in non-violating runs needs GPU near-miss instrumentation (deferred); violations array is unbounded (opt-in cap is the natural follow-up); CUDA/HIP/cosim paths don't route runtime violations throughprocess_eventsyet. - WS-P1.1.c —
--timing-summarytext output. Shipped 2026-05-02 in commit44e70a0. NewTimingReport::format_summary()formatter;--timing-summaryCLI flag;TimingReportConfigrefactored to support either / both / neither output. Text writes to stdout. Deferred from ADR 0008's wishlist: "corner" (metadata struct doesn't carry it yet) and "margin percentage" (derivable from existing fields). Both are documented in code as known gaps. - WS-P1.1.d — Per-DFF worst-slack ranking. Partially shipped in
58a7a04alongside WS-P1.1.b: top-10 per kind from observed violation events. Remaining: closest-to-violation tracking when no violation occurred — needs GPU near-miss instrumentation, deferred to a separate workstream.
Total ~2 weeks.
WS-P1.2 — Phase 0 follow-ups (carryover)
Tail of Phase 0 work that didn't gate WS3 completion. Listed for completeness.
WS2.4: multi-corner CLI flag inShipped 2026-05-02 (commitsopensta-to-ir.5822343/530bb36/59fde04).- WS4: corpus + runner + regen helper + CI hookup shipped 2026-05-02 with the seed entry
aigpdk_dff_chain(covers all four IR record types). One follow-up: add sky130-based corpus entries (inv_chain_pnr, mcu_soc subset) once a CI sky130-Liberty install strategy is decided. - Peripheral wiring for I²C/SPI when a fuller mcu_soc fixture lands.
(WS5 — parser-success assertions on the Liberty parser path and on opensta-to-ir — was already shipped; see phase-0-ir-and-oracle.md § WS5.)
These are not gated by any new ADR; pick them up as bandwidth allows.
Exit criteria for Phase 1:
- ✅ Symbolic violation messages live; old state-word-index format gone (commit
0432d9a). - ✅
--timing-reportJSON shipping; sample fixture attests/timing_ir/sample_reports/two_violations.json(commit58a7a04). - ✅
--timing-summaryavailable (commit44e70a0). - ✅ Worst-slack ranking included in both report and summary (top-10 from violations; non-violating-run tracking still requires GPU near-miss instrumentation, separate workstream).
- ✅
why-jacquard.mdupdated; old "Output interface" section now describes the shipped surface, "Still on the wishlist" carries the deferred items.
Phase 1 closed. Phase 2 entry now blocked only on ADR 0007 acceptance.
Phase 2 — Timing model fidelity
Entry criteria:
- Phase 1 exit criteria met.
- ADR 0007 accepted.
Pillar B Stages 1 and 2 (per-DFF clock arrival in the IR + setup/hold fold-in) landed early, in commits c403cc8 and 6767c3e — directly on top of the OpenSTA-out-of-process producer rather than the OpenTimer integration originally planned. Phase 2 is therefore anchored on Pillar C Tier 1 (per-receiver wire delay), with Pillar B Stage 3 only if measurement justifies it.
Workstreams (parallel where independent):
WS-P2.1 — Pillar C Tier 1: Per-receiver wire delay (ADR 0007)
Key wire delay per (src_aigpin, dst_aigpin) edge.
- WS-P2.1.a — Edge-attributed wire delay. Rewrite of
src/flatten.rs:1850-1872to key wire delay per fanout; fold into source-side gate_delay per fanout target. ~3–5 days. - WS-P2.1.b — Rise/fall preservation. Carry per-edge rise/fall through the consumer; honour both in
PackedDelayaccumulation. ~1–2 days, after WS-P2.1.a. - WS-P2.1.c — Validation. Long-route corpus addition; tolerance ≤±3% on long-wire paths.
Total ~1 week.
WS-P2.2 — Pillar B Stage 3: Bucketed per-DFF constraint packing (conditional)
Stages 1+2 collapsed all DFFs in a 32-bit state word to min(setup), min(hold) after folding the per-DFF clock arrival in. For most current designs the per-word collapse pessimism is small relative to clock period; for designs running close to the period boundary, splitting each word into clock-arrival buckets eliminates the collapse loss without disturbing the partitioner. See Stage 3 in docs/timing-model-extensions.md Part B.
Land only if Stage 1+2 measurement on a representative design shows the per-word collapse materially over-reports violations; otherwise defer indefinitely. Effort if pursued: ~3–5 days, touches src/flatten.rs:1722-1761 and the kernel's constraint indexing.
WS-P2.3 — Output adjustments for fidelity work
Small touch-ups to ensure Phase 1 outputs continue to work as model fidelity changes. JSON report fields, summary metrics, etc. Folded into WS-P2.1 / WS-P2.2 PRs as needed.
Exit criteria for Phase 2:
- Per-receiver wire delay landed; long-route paths reported within ≤±3% of CVC.
timing-model-extensions.mdParts B and C marked Implemented with cross-references to landed code (Part B already updated post-Stage-1+2).timing-validation.mdupdated with per-pillar tolerances.- No regression on existing corpus.
Phase 3 — Native Rust SDF→IR parser
Deferred indefinitely as of 2026-05-02 per amended ADR 0006. No longer release-gating: shipped Jacquard binaries may subprocess user-installed OpenSTA via opensta-to-ir, provided OpenSTA is not bundled and not linked. The user-facing capability gap is "OpenSTA must be on PATH for jacquard sim input.sdf," surfaced by WS-RH.1 below with a clear error message.
Reasons to revive:
- A downstream commercial integrator's legal team rejects subprocess-of-GPL-tool even with no bundling/linking.
- OpenSTA dialect coverage gaps appear that are easier to fix in our own parser than via
opensta-to-irpost-processing. - Bandwidth opens up and the team wants the zero-runtime-dependency story for its own ergonomics.
Effort estimate (unchanged from the original ADR 0006 framing): grammar-based (nom / pest), validated against OpenSTA on the WS4 corpus per ADR 0001. Probably 2–3 weeks of focused work. Not scheduled.
Release hardening
Pre-first-release work that became necessary when ADR 0006 § Amendment relaxed the no-runtime-subprocess rule. These are blockers for first release, not for any specific Phase.
WS-RH.1 — OpenSTA detection + version check
Status: Shipped 2026-05-02 in commit c9c393b. All scope items below are landed; this entry is preserved as a brief reference. Test coverage: 9 unit tests for the version parser + 6 integration tests for the locator across the missing / too-old / newer-than-tested / unparseable / failing-probe paths.
Why: With the shipped runtime now allowed to subprocess opensta-to-ir, a user invoking jacquard sim input.sdf on a machine without OpenSTA — or with an untested OpenSTA version — must get an actionable error rather than silent timing-data loss. Pre-WS-RH.1, missing OpenSTA only emitted a warn! and the simulation proceeded with no timing information loaded. That was acceptable during development but shipped as a UX bug.
Scope:
- Promote missing-OpenSTA from warning to hard error when
--sdfis provided. Today's silent-fallback behaviour is fine for--liberty-only runs but wrong when SDF was explicitly requested. Error message must name the env var (JACQUARD_OPENSTA_BIN), the PATH lookup, and link to install instructions. ~0.5 day. - Pin a tested OpenSTA version range. Record the version we test against in
vendor/opensta/(already pinned via submodule per ADR 0005) and surface that as aMIN_TESTED_OPENSTA_VERSION/MAX_TESTED_OPENSTA_VERSIONconstant incrates/opensta-to-ir/src/opensta.rs. Need to choose a version-detection mechanism — OpenSTA's-versionflag output format is the obvious target; check whether it's stable across the versions we care about. ~0.5 day. - Version probe at first invocation. On first call to
find_opensta()per process, run<binary> -version, parse the version, and:- If older than min-tested → hard error with remediation message ("rebuild via
scripts/build-opensta.shor upgrade your system OpenSTA"). - If newer than max-tested → warn but proceed ("untested OpenSTA version vN.M; please report any timing discrepancies").
- Cache the result for the rest of the process. ~1 day.
- If older than min-tested → hard error with remediation message ("rebuild via
- Document the dependency in
docs/usage.md. Single section: required tooling, install paths, version range, whatjacquard simdoes and doesn't need OpenSTA for. ~0.5 day. - Test coverage: unit tests for the version-string parser (with sample
-versionoutputs from the pinned version and a synthetic too-old version); an integration test that pointsJACQUARD_OPENSTA_BINat a stub script and confirms the error path. ~0.5 day. - Stale-framing cleanup (folded in here per 2026-05-02 decision rather than spun out separately):
- Reword
INTERIM per ADR 0006/Pre-release onlymarkers in source:src/sim/setup.rs:176,228,286,src/bin/jacquard.rs:187,src/sim/cosim_metal.rs:2053,src/testbench.rs:255-257. Replace with "subprocess wrapper per ADR 0006 § Amendment" or similar — these paths are no longer interim. - Update
docs/plans/phase-0-ir-and-oracle.mdlines 152, 161, 172 — drop "tagged for pre-release removal" framing; the subprocess wrapper is now the shipping mechanism, not a temporary bridge. - Audit
docs/plans/ws3-delete-sdf-parser.mdfor the same stale framing and update. - ~0.5 day total for the cleanup.
- Reword
Total: ~3.5 days. Single PR, owned by whoever picks up release prep.
Open question: does OpenSTA emit a stable -version string, or do we need to scrape git describe from a build-time-recorded commit? If -version is unreliable, fall back to recording the submodule commit at crates/opensta-to-ir build time and comparing — this is cheaper than version-string sniffing and avoids the "user has a custom build" problem.
Phase 4+ — Demand-driven
Items below land when (a) a real use case appears that demands them, and (b) bandwidth is available. Each gets its own ADR amendment / new ADR before scheduling, since the cost is non-trivial.
Pillar A Stage 1 (static IDM)
Cheapest δ(T) entry point. Lands only after Pillars B and C confirm the wire/skew baseline is correct — characterisation work done before that risks chasing wire-delay error masquerading as δ(T) error.
Effort: 1–2 day spike to validate value, then ~1 week implementation, plus per-cell SPICE characterisation effort (long-pole risk).
Pillar C Tier 2 (inter-partition wire delay)
Required for many-core/NoC designs at advanced processes. Lands when a representative such design appears in the test corpus and Tier 1 measurement shows it is needed.
Effort: ~2–3 weeks, touches src/sim/cosim_metal.rs shuffle pipeline.
ADR 0008 optional outputs
Items 5–7 from ADR 0008: arrival histograms, STA cross-reference, path-back-trace. Demand-driven prioritisation.
Pillar C Tier 3 (NoC-aware partitioning hints)
Optional optimisation that makes Tier 2 cheap on tile-decomposed designs. Lands only if Tier 2 lands and partitioning quality on tile designs proves measurably suboptimal.
Risks and walk-back
- Pillar measurement shows smaller-than-expected gain. Each pillar's later stages are deferred or abandoned per ADR 0007's walk-back clause. Pillar B Stage 3 is explicitly conditional on this signal.
- JSON report schema design wastes time in bikeshedding. Mitigation: ship v1 quickly, additive-only changes thereafter, breaking changes require explicit ADR-level decision.
- OpenSTA upstream regressions. With OpenSTA as the sole STA path, an upstream behaviour change reaches us through
opensta-to-ir's output. Mitigation: pin OpenSTA in CI (per ADR 0001) and rely on the regression corpus to surface drift. - CRPR pessimism on tight designs. Stage 1+2 fold-in treats launch=0; a design with very heterogeneous launch arrivals will see pessimism on paths whose launch DFF also has a long clock path. Stage 3 is the lever if this matters; otherwise live with it.
Cross-references
../adr/0007-timing-model-fidelity-roadmap.md— Pillar definitions for Phase 2.../adr/0008-structured-timing-output.md— Output items for Phase 1.../adr/0001-opensta-as-oracle.md— OpenSTA out-of-process commitment (post-ADR-0003 supersedure).../adr/0003-opentimer-primary-sta.md— Superseded. Spike fail outcome documented in../spikes/opentimer-sky130.md.../adr/0006-sdf-preprocessing-model.md— Phase 3.../why-jacquard.md— User-facing positioning that this roadmap delivers.../timing-model-extensions.md— Technical analysis underlying ADR 0007.../timing-validation.md— Validation tolerances each phase updates.phase-0-ir-and-oracle.md— Predecessor roadmap (current Phase 0 status lives there per workstream).../spikes/opentimer-sky130.md— Spike outcome (Superseded).