Skip to content

Commit c714001

Browse files
kmbandyclaude
andcommitted
feat(dsws): Phase-B consume-point sensing (read-only)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0132aDSBLwusCJ4KzHQTnvdu
1 parent 3f62cb5 commit c714001

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

ggml/src/ggml-cuda/aiter-integration/rdna4_fp8_gemm/spike/dvgpr_occ/occ_kernel_dsws.s

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,41 @@
353353
.Lasd\@:
354354
.endm
355355

356+
// ============================================================================================
357+
// Phase-B (DSWS2_CONV) consume-point ring-occupancy sensor -- Task 3, READ-ONLY (actuation is Task 5).
358+
// Mirrors the coop occ_a/occ_b sensor (occ = producer - consumer, sampled where the value is
359+
// CONSUMED, not at the segment boundary). The claimer's A7 wait-done spin runs CONCURRENTLY with the
360+
// compute drain, so it observes the ring mid-flight; at the segment boundary the resident region has
361+
// fully drained and occ would read a stuck ~0 (permanent false-starvation) -- exactly what SPEC warns.
362+
//
363+
// COUNTER IDENTITIES (confirmed against the live claim/consume sites -- see report):
364+
// producer = the STORE-completion counters the compute wave actually gates on:
365+
// A-ring: AROW_DONE_OFF (A rowblks resident, monotonic in [0,G]; lds_inc @ ASTAGE)
366+
// B-ring: BFRAG_DONE_OFF (B frags resident, monotonic in [0,FN]; lds_inc @ BSTAGE)
367+
// NOT the *_NEXT claim counters: AROW_NEXT/BFRAG_NEXT overshoot the ring depth by the role
368+
// terminal-bails (G+NAFEED / FN+NBFEED), which would break the occ <= depth bound.
369+
// consumer = ROWBLK_NEXT_OFF, the compute rowblk-claim clock (consume progress through the super-tile:
370+
// each claimed rowblk r consumes A(r) and re-reads all FN shared B frags).
371+
// min-clamp: cons is clamped to prod before the subtract so the u32 result cannot underflow when the
372+
// consume clock outruns a shallower ring (G=6 > FN=4 -> ROWBLK_NEXT can exceed BFRAG_DONE).
373+
// INVARIANT preserved: occ_A in [0,G], occ_B in [0,FN] (nonnegative, bounded by ring depth).
374+
//
375+
// REGISTER DISCIPLINE (brick-critical; this path is reachable pre-grow -- a >v15 vector temp is
376+
// OOR-poison under dyn-VGPR, SPEC S4): scalars <= s65 only (s60/s61 scratch; callers pass dst in
377+
// [s62,s65]); the only vector temps are inside lds_get, which uses v11/v14 (INTERIOR to the launch
378+
// 16-VGPR block) -- NO >v15 temp is introduced here.
379+
.if DSWS2_CONV
380+
.macro occ_sample dst_a, dst_b // out: \dst_a=occ_A in [0,G], \dst_b=occ_B in [0,FN]; clob s60,s61
381+
lds_get \dst_a, AROW_DONE_OFF // prod_a: A rowblks resident (store-completion)
382+
lds_get \dst_b, BFRAG_DONE_OFF // prod_b: B frags resident (store-completion)
383+
lds_get s60, ROWBLK_NEXT_OFF // cons : compute rowblk-claim consume clock
384+
s_min_u32 s61, s60, \dst_a // cons_a = min(clock, prod_a) (clamp -> no u32 underflow)
385+
s_sub_u32 \dst_a, \dst_a, s61 // occ_A = prod_a - cons_a in [0,G]
386+
s_min_u32 s61, s60, \dst_b // cons_b = min(clock, prod_b)
387+
s_sub_u32 \dst_b, \dst_b, s61 // occ_B = prod_b - cons_b in [0,FN]
388+
.endm
389+
.endif
390+
356391
// ============================================================================================
357392
// KERNEL
358393
// ============================================================================================
@@ -501,6 +536,26 @@ occ_kernel:
501536
// A7 advance gate: free resident A/B only when ALL G rowblks are computed+flushed
502537
.Lclaimer_wait_done:
503538
s_sleep SLEEPN
539+
.if DSWS2_CONV
540+
.if DIAG
541+
// Phase-B DIAG probe (Task 3): wid 0 samples the LIVE ring occupancy (compute is mid-drain here)
542+
// and publishes the last-sampled occ_A/occ_B so a GPU run can confirm the sensor OSCILLATES
543+
// rather than reading a stuck 0. Written every wait-done spin -> a live poller observes it vary.
544+
// Spare word-indexed slots occ[26]/occ[27] -> byte offsets 104/108 (well clear of the
545+
// byte-indexed control words occ[0]/occ[20]/occ[24]). READ-ONLY sensing, NO actuation.
546+
occ_sample s62, s63
547+
v_cmp_eq_u32 vcc_lo, 0, v2
548+
s_mov_b32 s16, exec_lo
549+
s_and_b32 exec_lo, exec_lo, vcc_lo
550+
s_cbranch_execz .Locc_diag_skip
551+
v_mov_b32 v14, s62 // occ_A (v14 <= v15: pre-grow safe)
552+
v_mov_b32 v15, s63 // occ_B
553+
global_store_b32 v4, v14, s[0:1] offset:104 scope:SCOPE_DEV // occ[26] = last occ_A
554+
global_store_b32 v4, v15, s[0:1] offset:108 scope:SCOPE_DEV // occ[27] = last occ_B
555+
.Locc_diag_skip:
556+
s_mov_b32 exec_lo, s16
557+
.endif
558+
.endif
504559
lds_get s44, ROWBLK_DONE_OFF // (a) all G rowblks computed + flushed
505560
s_cmp_lt_u32 s44, G
506561
s_cbranch_scc1 .Lclaimer_wait_done

0 commit comments

Comments
 (0)