The Φ (timing) and Δ (capability) judgments from 02 §1: events, temporal capabilities, guarded feedback, and the separation of the three notions of time. Principles in force: P-2 (cost visible), P-5 (schedules are witnesses, not compiler artifacts).
issue(op) < complete(op), commit after execute). Stable under all optimization.complete(op) = issue(op) + 3 @ CoreClock). Changed by retiming/scheduling passes, which must preserve the architectural order.Measured, Estimated).There is no single Latency type. A retiming pass changes layer 2 while a preserved layer-1 relation is its correctness condition (07 §4).
Named symbolic events (accept(r), issue(op), produce(x), flush(e), reset_release(d)) with constraints between them; value types carry event indices: At<T, E>, During<T, [E1, E2)>. Absolute stage numbers are sugar for events. Rationale from research: both Filament (intervals relative to events) and Anvil (contracts over abstract time points) demonstrate relative events compose where absolute stages don't.
A physical unit is not consumed by use; its availability over time is. The core object:
| 1 | Capability<Resource, Availability> // e.g. WritePort<DCache, [Execute+2, Execute+3)> |
Uses claim intervals; the checker proves non-overlap against the resource's capacity. Latency and initiation interval are distinct: Unit<Latency<4>, II<1>> legally has four results in flight — inexpressible in a consumed-once model, natural here.
Committed scope: static intervals (Filament-lineage). With delays and offsets static (possibly comptime-parametric), non-overlap collapses to linear integer inequalities — Filament's checker needs no general solver and checks all its benchmarks in under a second; the parametric case (Lilac) discharges symbolic obligations via Z3 in seconds. Both are proven-practical territory. Concretely committed:
Committed scope: conditional use. Conditional uses of one unit generate a Tier-2 disjointness obligation — in general cardinality form: at most capacity − (unconditional claims) of the guards may be simultaneously true, of which the pairwise is_add(op) ∧ is_addr_calc(op) = false is the two-claim special case (probe-sharpened wording, probes/interval-caps/). This is deliberately more than Filament (which is path-insensitive: shared invocations charge worst-case spans on one event) and is grounded in PDL, whose path-sensitive abstract interpretation over branch conditions, discharged by Z3, handles exactly the conditional-reserve case. The checker only generates obligations; it never schedules (OP-4) — the probe demonstrated the line concretely: the check is a pure function over the design, repairs are suggestion values (move / replicate / guard), and the two tiers exchange exactly one artifact type in one direction. Two probe-found details the one-line rule understates, both resolved in wave 2 (probes/interval-caps/, oracle-validated against brute-force unrolled simulation over 3×lcm cycles, 2000 random designs, zero disagreement):
[G+i, G+j) occupies residues {(i..j) mod II} in ℤ/II, and conflict-freedom is capacity-checking at every residue — solver-free and finite because of the length ≤ II wellformedness rule, which is load-bearing independently: an overlong claim must be rejected even when capacity would absorb the occupancy (occupancy counting alone provably misses that case).Exhausted maps to the standard obligation outcome. Measured headroom: 500 invocations check in ~114 µs.Guard inference validated (wave 2, probes/guard-inference/, SUPPORTS-SETTLED). One analysis walk yields both per-use guards and D-069 narrowing facts — provably two projections of one normal form — and its inferred guards are value-identical to the wave-1 hand-written ones, feeding the interval checker unchanged. The structural safety property: inference failure always weakens the guard, which makes the cardinality obligation strictly harder — degradation is safe by direction, so narrow! is a precision mechanism, never a soundness one. Completeness boundary: 9/12 natural patterns infer exactly (anything testing operands against constants/variants, through let-bound aliases — the dominant decode-dispatch shape); only genuine dataflow (var-vs-var, arithmetic-derived tests, mutation, computed scrutinees) needs narrow!, so users encounter it at dataflow boundaries, not per-branch. Mutation between test and use drops the stale conjunct and flags it — a guard never lies. Two implementation notes carried forward: the obligation guard language needs bounded-int atoms (an exact n ≤ 7 guard is otherwise untranslatable; discharge stays solver-free via representative values), and guard emission wants SSA form first. Syntax-phase recommendation: operand immutability by default deletes the stale-guard class outright.
Dynamic latency (D-034) — via protocols, not intervals. Variable-latency interaction (cache misses, arbitration) is typed at component boundaries through protocol contracts and outstanding-count refinements (04), not through the interval checker. Anvil shows event patterns with dynamic durations can be typed (event-graph interval containment), but it's a 2025 prototype that loses to Filament on static pipelines (~2× power on a pipelined ALU) — evidence that dynamic-event typing is not yet a free lunch. North star below.
The single strongest lesson from the Bluespec lineage: never make cycle-level behavior an artifact of opaque compiler analysis. BSV's ORAAT semantics underdetermines cycle behavior; users demonstrably "code at the compiler," and conflict resolution degrades to stringly descending_urgency pragmas. Kôika's fix (user-visible schedule) and Filament's (schedule in interface types) both work; Strata's committed form:
| 1 | Algorithm<A> → Scheduled<A, S> → Implemented<A, S, I> |
S is a schedule witness — produced by the designer, by search, or by an agent, but always inspectable, diffable, and checkable against A's architectural event order. The optimizer replaces S freely under the equivalence-class rules; it never invents unstated cycle semantics. Arbitration among conflicting resource users is likewise first-class (arbitrate { policy, guarantees, liveness } — 04 §6), never a compiler-chosen urgency order.
A register is delay : (init: T, next: Signal<T>) → Later<Clock, Signal<T>>; feedback is legal only through Later. An unguarded combinational cycle fails compositionally — a component's feedback port demands Later<_, T> in its signature, so safety is known without opening bodies (critical for agent composition). The post-elaboration graph check remains as a backstop.
Committed: single-clock later per domain. Research status is honest here: full clocked type theory exists only inside proof assistants (Guarded Cubical Agda); no programming language ships it. But the unary case — later = "next cycle in this domain" — is far simpler, and the comparison point is Clash, where a register-free feedback loop type-checks and manifests as simulation divergence or a synthesis-time combinational loop. Typing causality is a genuine, claimable improvement over the state of practice. Multi-clock guarded quantification (∀κ) is DEFERRED; cross-domain feedback must pass through a typed CDC bridge (04 §7), which sidesteps the multi-clock modality entirely in committed scope.
Calculus-mandated rule (wave 2, probes/core-calculus/ — a found-and-fixed unsoundness): the feedback rule requires FIX-ω — usage inside a feedback body is ω-promoted, because feedback re-executes every cycle and the naive rule let a 1-graded value be spent once per cycle, a bug neither QTT nor guarded recursion alone can express. The corollary is load-bearing and pleasant: ω-graded periodic capabilities (initiation intervals) remain usable in feedback — II is precisely how linearity reconciles with per-cycle reuse.
Queue capacity is linear tokens, not an integer annotation: enqueue consumes FreeSlot ⊗ Payload → OccupiedSlot<Id>; dequeue returns the slot. Gives no-overflow/no-underflow/no-lost-entry/one-response-per-request as conservation laws the checker tracks structurally. Surface stays ordinary (queue.reserve()?); tokens are the elaborated semantics. Under speculation, conservation is per-epoch — granted(E) = live(E) + retired(E) + reclaimed(E) — which is exactly the squash-contract form of 05 §3. Credit protocols (tokens exchanged across an interface) live in 04 §4.
e ▷ #N | ω) and lifetimes/loans in the event-graph style, once the static-pipeline regression is understood. Entry criterion: expresses a non-blocking cache's response contract without worst-case padding, checked in seconds, without losing Filament-class results on static pipelines. (OP-8)requires placement_distance(rf) <= D) — obligations for the physical flow, never type equality.