|
| 1 | +# Optional S2G destination completion and local visibility |
| 2 | + |
| 3 | +This branch extends the source-only group implementation at `b1593b3d2`. It |
| 4 | +does not change what `vx_dxa_wait_group_read<N>()` guarantees. Enable the new |
| 5 | +path with `VX_CFG_EXT_DXA_FULL_ENABLE`; it defaults off. Full wait is a separate |
| 6 | +instruction, `vx_dxa_wait_group<N>()` (custom DXA funct3=4, five-bit immediate). |
| 7 | + |
| 8 | +## Supported contract |
| 9 | + |
| 10 | +* Groups remain warp-owned, with independent ordered queues for each warp. |
| 11 | +* READ waits for source consumption, permitting SMEM reuse before destination |
| 12 | + writes finish. It does not invalidate a cache or imply destination visibility. |
| 13 | +* FULL waits for the older committed groups to reach the configured WB L2 |
| 14 | + commit point, then invalidates the issuing socket's WT L1 and waits for its |
| 15 | + acknowledgement. The newest N groups and the uncommitted open group remain |
| 16 | + excluded from the destination wait. |
| 17 | +* This first implementation requires enabled write-through L1, one physical |
| 18 | + D-cache per socket, write-back L2, and no L3. Unsupported configurations fail |
| 19 | + assertions. It neither discards dirty L1 data nor claims global coherence. |
| 20 | + The DXA store path reaches L2 directly; the optional generic WT ACK relay |
| 21 | + does not support an opted-in store racing an older same-line fill and asserts |
| 22 | + on that case. It is not used by this full-wait path. |
| 23 | +* A consuming warp on another socket needs its own refresh and explicit |
| 24 | + inter-warp/CTA synchronization. A full wait is not a CTA barrier. Concurrent |
| 25 | + unsynchronized accesses to an excluded or open group's destination are races. |
| 26 | + |
| 27 | +## Data and completion paths |
| 28 | + |
| 29 | +``` |
| 30 | + {core, wid, gid} |
| 31 | +warp ISSUE ──► source + destination rings ──► fixed-mapped DXA worker |
| 32 | + │ │ |
| 33 | + │ stable LMEM source capture |
| 34 | + │ │ |
| 35 | + ◄──── SOURCE_CONSUMED ────────┤ |
| 36 | + │ │ |
| 37 | + │ strsp-marked store requests |
| 38 | + │ ▼ |
| 39 | + │ WB L2 array commit |
| 40 | + │ │ |
| 41 | + │ one ACK per request beat |
| 42 | + ◄──── DESTINATION_COMPLETE ──┘ |
| 43 | + │ |
| 44 | +FULL<N> parks warp; destination depth <= N |
| 45 | + │ |
| 46 | + ▼ |
| 47 | + zero-byte local-invalidate command |
| 48 | + │ |
| 49 | + ▼ |
| 50 | + local WT L1 ingress serialization |
| 51 | + drain older requests / MSHRs / old fills |
| 52 | + invalidate clean tags; no lower-level invalidation |
| 53 | + │ |
| 54 | + ▼ |
| 55 | + tagged invalidate ACK ──► unlock issuing warp |
| 56 | +``` |
| 57 | + |
| 58 | +`VX_dxa_store_ack` wraps either existing S2G data engine. It does not send the |
| 59 | +data through LSU. The worker retains one high-level operation until its write |
| 60 | +ACK count drains. It may have `VX_CFG_DXA_S2G_WRITE_CREDITS` requests outstanding |
| 61 | +(default 16); ACK order within this operation is irrelevant to the count. The |
| 62 | +cache transport must deliver exactly one ACK for every opted-in write. The |
| 63 | +wrapper forwards SOURCE_CONSUMED independently and emits exactly one later |
| 64 | +DESTINATION_COMPLETE. No per-packet warp/group bookkeeping is added to L2. |
| 65 | + |
| 66 | +The L2 ACK is enqueued atomically with the actual array write, including |
| 67 | +write-miss fill/replay and byte-mask merge. Accepting a write into an upstream |
| 68 | +queue is not sufficient. Zero-length and wholly out-of-bounds operations still |
| 69 | +produce one event in each domain, with zero memory writes. |
| 70 | + |
| 71 | +## Why two retirement fronts are necessary |
| 72 | + |
| 73 | +``` |
| 74 | + source pending destination pending |
| 75 | +issue G0 1 1 |
| 76 | +commit G0 1 1 |
| 77 | +source capture G0 0 1 |
| 78 | +wait.read<0> PASS 1 |
| 79 | +overwrite SMEM safe 1 |
| 80 | +L2 ACK drain G0 0 0 |
| 81 | +wait.full<0> refresh L1 -> ACK -> PASS |
| 82 | +``` |
| 83 | + |
| 84 | +Two direct-indexed instances of the existing small per-warp ring track the |
| 85 | +source and destination domains. Both see the same accepted ISSUE and COMMIT; |
| 86 | +their tails and open group identities match, but their retirement heads may |
| 87 | +differ. An issue succeeds only when both have room. Thus a source-complete row |
| 88 | +cannot be recycled while its old destination identity is live. This is |
| 89 | +deliberately conservative; an independently sized destination pool is future |
| 90 | +work, not hidden in this patch. |
| 91 | + |
| 92 | +For every live row, destination pending is at least source pending. Every |
| 93 | +DESTINATION_COMPLETE follows acceptance of that operation's SOURCE_CONSUMED |
| 94 | +event. Assertions check these invariants. Existing exact-once transport and |
| 95 | +owner drain before warp reuse avoid the need for new generation tags. A reset |
| 96 | +must reset/flush both transport and trackers; individual warp kill cannot |
| 97 | +silently recycle an outstanding identity. |
| 98 | + |
| 99 | +The depth and pending bounds stay configurable (`VX_CFG_DXA_GROUP_DEPTH=8`, |
| 100 | +`VX_CFG_DXA_GROUP_MAX_PENDING=8`). Counts denote currently outstanding |
| 101 | +operations, not historical issues. Because the destination count drains later, |
| 102 | +enabling FULL may impose stronger issue backpressure than a source-only build. |
| 103 | +Commit closes an already reserved row, never allocating a new row. |
| 104 | + |
| 105 | +## Invalidation transport |
| 106 | + |
| 107 | +The endpoint injects `{rw=1, byteen=0, local_inval=1, tag=wid}` through a |
| 108 | +two-input arbiter on local L1 request port zero. One extra route bit keeps its |
| 109 | +ACK separate from LSU responses. Other L1 ports still operate normally until |
| 110 | +the cache takes the invalidate lock. Each endpoint allows one invalidate in |
| 111 | +flight and remembers other ready full waiters. Only the matching ACK unlocks |
| 112 | +the corresponding warp; SFU is not occupied while it waits. |
| 113 | + |
| 114 | +The cache consumes this control request locally. Its ordinary flush machinery |
| 115 | +drains older bank ingress and outstanding fills before clearing tags, preventing |
| 116 | +an old refill from restoring stale data afterward. It returns an explicit ACK |
| 117 | +without issuing a dummy read or zero-byte write downstream. Unrelated clean |
| 118 | +lines may be evicted: this loses hit rate, not architectural data. Dirty-cache |
| 119 | +support would require a different drain/writeback policy and is not enabled. |
| 120 | + |
| 121 | +## Validation and limitations |
| 122 | + |
| 123 | +* `hw/unittest/cache_strsp`: real WB array ACK timing, miss replay, byte masks. |
| 124 | +* `hw/unittest/cache_strsp_hier`: opted-in ACK transport through WT to WB. |
| 125 | +* `hw/unittest/cache_wt_invalidate`: actual cache data; stale primed line, |
| 126 | + outstanding old fill, unrelated clean data, standalone ACK/backpressure. |
| 127 | +* `tests/unittest/cache_visibility`: matching SimX lifecycle/cache checks. |
| 128 | +* `hw/unittest/dxa_s2g`: serial and pipelined workers, delayed/reordered ACKs, |
| 129 | + source poisoning, credit bounds, partial/OOB/zero-length transfers. |
| 130 | +* `hw/unittest/dxa_full_wait`: independent source/destination heads, retained |
| 131 | + group identities on wrap, full thresholds 0/1/2, parked waiters and ACK-gated |
| 132 | + wakeup. |
| 133 | +* `tests/regression/dxa_s2g_full_wait`: one and two issuer modes; each group has |
| 134 | + a 512-byte tile plus 32-byte vector, old destination priming, source poisoning |
| 135 | + after READ, FULL followed by same-kernel reload, unrelated data and canaries. |
| 136 | + |
| 137 | +SimX's functional LSU accesses can bypass cached data. Its integrated PASS |
| 138 | +therefore validates lifecycle/control, not by itself stale-L1 data visibility. |
| 139 | +Real RTL cache tests and the whole RTL regression must be reported separately. |
| 140 | +No performance, ASIC area, FPGA, or cross-socket coherence claim is made here. |
| 141 | + |
| 142 | +## Reproduction |
| 143 | + |
| 144 | +Configure out of tree with the installed Vortex toolchain; the regression |
| 145 | +Makefile supplies DXA, S2G, groups, full wait and L2 flags consistently to the |
| 146 | +kernel, runtime and model. Example commands from the configured build: |
| 147 | + |
| 148 | +```bash |
| 149 | +make -C tests/regression/dxa_s2g_full_wait -j8 THREADS=8 run-simx |
| 150 | +make -C tests/regression/dxa_s2g_full_wait -j8 THREADS=8 run-rtlsim |
| 151 | +make -C hw/unittest/dxa_full_wait THREADS=8 run |
| 152 | +make -C hw/unittest/cache_strsp THREADS=8 run |
| 153 | +make -C hw/unittest/cache_strsp_hier THREADS=8 run |
| 154 | +make -C hw/unittest/cache_wt_invalidate THREADS=8 run |
| 155 | +make -C tests/unittest/cache_visibility -j8 run |
| 156 | +``` |
| 157 | + |
| 158 | +Use a fresh build directory for each cache latency variant |
| 159 | +(`PARAMS=-GLATENCY=4` or `6` on `cache_strsp`) and for serial/pipelined worker |
| 160 | +variants. Full serial worker flags are DXA/GROUP/S2G/FULL/L2; the pipelined |
| 161 | +variant additionally defines `VX_CFG_DXA_S2G_PIPELINED` and |
| 162 | +`VX_CFG_DXA_S2G_PIPE_MULTI_READ`. Debug builds (`DEBUG=4`) report source and |
| 163 | +destination completion separately, plus full-wait invalidate/wakeup events. |
| 164 | +The regression defaults to four warps of four lanes, one core/socket. Both one |
| 165 | +issuer and two issuer modes run; each issuer commits four heterogeneous groups. |
| 166 | + |
| 167 | +Negative control: keep all destination ACK tracking, replace endpoint |
| 168 | +`full_unlock` with `destination_unlock`, and stop scheduling cache invalidate |
| 169 | +requests in an isolated source/build copy. The unchanged kernel then reports |
| 170 | +544 mismatches in its one-issuer mode (all 4 x 136 payload words); the real |
| 171 | +implementation reports zero. This demonstrates a cache-visibility benefit, |
| 172 | +not a speedup. Never ship the negative-control modification. |
| 173 | + |
| 174 | +Checkpoint limitation: default-off L2 `vecadd_v1 -n64` passes in RTL, but the |
| 175 | +newer queue-based `vecadd -n64` and `async_barrier -n16` time out at CP sequence |
| 176 | +26 (target 27) in the tested tool environment. No untouched-baseline comparison |
| 177 | +has established whether those failures predate this branch. They remain open; |
| 178 | +the successful full-wait tests must not be presented as an all-regressions-green |
| 179 | +release. The existing plain `hw/unittest/cache` executable is an empty harness, |
| 180 | +so its successful elaboration is not counted as functional validation. |
0 commit comments