|
353 | 353 | .Lasd\@: |
354 | 354 | .endm |
355 | 355 |
|
| 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 | + |
356 | 391 | // ============================================================================================ |
357 | 392 | // KERNEL |
358 | 393 | // ============================================================================================ |
@@ -501,6 +536,26 @@ occ_kernel: |
501 | 536 | // A7 advance gate: free resident A/B only when ALL G rowblks are computed+flushed |
502 | 537 | .Lclaimer_wait_done: |
503 | 538 | 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 |
504 | 559 | lds_get s44, ROWBLK_DONE_OFF // (a) all G rowblks computed + flushed |
505 | 560 | s_cmp_lt_u32 s44, G |
506 | 561 | s_cbranch_scc1 .Lclaimer_wait_done |
|
0 commit comments