Payload:SparseCore Band
本页中的所有地址、宽度和
CHECK常量均适用于libtpu-0.0.40-cp314wheel(build-id89edbbe81c5b328a958fe628a9f2207d)中的libtpu.so。该二进制文件未被 strip —— 完整 C++ 符号仍然存在,且.textVMA 等于文件偏移。其他版本会有所不同。
摘要
SparseCore (SC) trace band 是设备端 profiler 观察 SparseCore 执行进度的唯一视图:每事件 payload 字段映射覆盖 SparseCore sequencer (SCS)、TensorE/TensorA compute tiles (TEC/TAC) 以及 SC stream gather/scatter engine 发出的 18 个硬件 trace 事件。SparseCore 是在 Viperfish/Ghostlite/6acc60406 系列上取代 BarnaCore 的 sparse-compute substrate;它的指令、任务、流和 tile 间消息都与其他所有 band 一样打包进同一个固定 16 字节 profiler packet,位于相同的 61-bit framing+header envelope 之后,并由匿名命名空间中的每芯片族、每事件 DecodeSc<Name>(string_view, bool*, TraceEntry*) 读出。
本页负责两件 codec page 有意不覆盖的内容:(1) 每事件 payload bit-decode —— bit 61 之后有序的 GetBits64 宽度序列、total-bit CHECK、packet count,以及带每字段宽度的命名 proto 字段 —— 对三个承载 SC 的家族 vfc (Viperfish)、glc (Ghostlite)、gfc (6acc60406) 做到字节精确;(2) on-wire-id → trace-point map —— 硬件为每个 SC 事件打上的 dense trace_point_id (108..133),它与 decoder 写入的 proto oneof field number 不同。SC band 位于只有通过较新 codec 的两级 dispatch 才能到达的高 id band;tracepoints-master-registry.md 负责完整的跨 band registry,本页负责 SC 子范围。
一个结构性事实贯穿全篇:SC trace band 只存在于带 SparseCore 的 silicon。pxc (Pufferfish, BarnaCore generation) 和 vlc (Viperfish-lite) 发出零个 Sc* proto message,并且有零个 DecodeSc* function。这些事件对 SCS sequencer、TEC/TAC tiles,以及 stream gather/scatter datapath 进行插桩;SyncFlagCoreType/DestCoreType 的 TEC_OR_SCS/TAC selector 是在线路上显露的 sequencer-type enum。
对重新实现而言,契约是:
- 18 个 SC 事件及其 wire shape —— 11 个
ScInstruction*、2 个ScTask*、3 个ScStream*、2 个ScMessage*—— 每个都按家族给出有序的 post-bit-61 宽度序列 + total-bitCHECK+ packet count。 - 命名 proto 字段映射 —— 哪个宽度是
scs_pc、tile_bitmap、tec_sync_stalls、stream_opcode、smem_address等,均经 descriptor 确认。 - SC selector enum value table ——
StreamOpcode、SyncFlagCoreType、TileLocal/OffTile MemoryType/StreamType、IndirectListType、DestCoreType、MsgType、Opcode—— 字节精确的命名值,包括每代StreamOpcode从 3 到 4 bit 的增长。 - on-wire-id → event map —— dense SC 子范围 (108..133),已证明不同于 proto oneof field,并从 high-id-band secondary jump table 恢复。
| 负责内容 | SC-band 每事件 payload field-bit map + SC on-wire-id table |
| Codec / framing | trace-entries-coder.md — 16-byte packet、2-bit framing、61-bit header、GetBits64/SkipBits primitives、CHECK mechanism |
| 承载 SC 的家族 | vfc (Viperfish)、glc (Ghostlite)、gfc (6acc60406) — 每个都有 18 个 DecodeSc* |
| 无 SC band | pxc (Pufferfish/BarnaCore)、vlc (Viperfish-lite) — 0 个 DecodeSc*、0 个 Sc* proto message |
| SC event count | 18 — 11 ScInstruction* + 2 ScTask* + 3 ScStream* + 2 ScMessage* |
| SC on-wire id range | 108..132 (vfc/glc)、108..133 (gfc — 一个 StatsCounter sample 将 ScMessage 上移 1) |
| vfc decoders | DecodeScInstructionCoreInterrupt @ 0xf60a8c0 … DecodeScMessageInboundInternalMessage @ 0xf60eb00 |
| glc decoders | 0xf63c760 … 0xf6409a0 |
| gfc decoders | 0xf6725a0 … 0xf676ae0 |
| Descriptor pool | trace_entries.proto FileDescriptorProto:vfc @ 0xbf06830、glc @ 0xbf41210、gfc @ 0xbf64c80(命名字段 + 嵌套 *Values enum) |
| Bit primitives | GetBits64NoInline @ 0x21073760、SkipBitsNoInline @ 0x21073580、mask_ @ 0xbe79440 |
读取 SC Payload — 通用形态
每个 SC decoder 都遵循通用 Decode<Name> 契约:先以 length > 15 gate,SkipBits(2) 越过 framing,运行每家族的 DecodeTraceHeader(59-bit id/block_id/timestamp,因此 framing+header = 61 bits),可选读取一个 TraceIdHeader,在 TraceEntry+0x28 处写入 dense oneof field,然后以每字段一个 GetBits64(n) 读取 typed payload,最后执行 CHECK(BitsDecoded() == K)。下面的宽度序列是 payload bits —— 即 bit 61 之后读取的内容(若存在 TraceIdHeader,则在其之后)。total-bit CHECK 覆盖整个 packet:CHECK = 61 + [TraceIdHeader] + Σ payload widths。
bit window of an SC packet
┌──────────┬───────────────────────────────┬──────────────────┬───────────────────────┐
│ framing │ TraceHeader (id/block/ts) │ TraceIdHeader? │ SC payload (this page)│
│ 2 bits │ 59 bits → bit 61 │ 38 bits (msg) │ Σ widths │
└──────────┴───────────────────────────────┴──────────────────┴───────────────────────┘
valid,started only ScMessage* per-event field set
```text
> **NOTE —** SC `TraceIdHeader` 是 `21,3,14`(= 38 bits),**不是** UHI/OCI/ICI band 的 `21,3,12`(= 36 bits)—— 这里的 `chip_id` 字段是 14 bits,与 vfc/glc/gfc header 中较新代的 14-bit `chip_id` 匹配。只有两个 `ScMessage*` 事件携带它;`ScInstruction*`/`ScTask*`/`ScStream*` 事件**没有** `TraceIdHeader`(core 由 59-bit header 中的 `trace_point_block_id` 隐含)。字节确认:`DecodeScMessageOutboundInternalMessage` @ `0xf60e6c0` 以 `GetBits64(21)`、`GetBits64(3)`、`GetBits64(14)` 开头。
两个 SC 事件(`ScTaskCommitOnSct`、`ScMessage*`)超过一个 16-byte packet,是 **2-packet** 事件。它们在 packet-1 边界携带一个*流中* `CHECK == 128`(`movq $0x20,0x8(%rbx)` 记录已消耗 32 bytes),并且还有最终 total-bit `CHECK`。跨越该 128-bit 边界的字段会被拆成两个 `GetBits64` 调用 —— `ScTaskCommitOnSct` 中的 `7,1,1,9` 组,以及 `ScMessage*` 中的 `4,1,1,10` 组(见每事件注记)。
> **GOTCHA —** 这些 straddle 组(`{7, 1, 1, 9}` 和 `{4, 1, 1, 10}`)内部的两个单 bit `GetBits64(1)` 调用**不是** boolean proto 字段 —— 它们是同一个 multi-bit 字段(`tec_sync_stalls` 7+9、`smem_address` 4+10)跨 packet 边界 straddle 的两半。把每个 `GetBits64` 一一映射到 proto 字段的重新实现会发明两个不存在的 bool,并拆分一个真实 counter。宽度片段和 `+0xNN` 目的 offset 已确认;每个片段在重组值中的确切 LSB 位置**未**制表(LOW —— 与 UHI/OCI straddle fields 相同的 open item)。
---
## SC_INSTRUCTION_* Band — Sequencer Control Events(11 个事件)
### 用途
SparseCore sequencer 的内部 control band —— TensorCore `TcsInternal*` band 的 SC 对应物。这 11 个事件在 SC sequencer primitive 执行时触发:core interrupt、trace marking,以及 fence/sync/barrier/sync-watch 的 start/stop 对。它们**没有** `TraceIdHeader`,并且**全部 11 个在每代共享同一种 wire shape** —— 它们只因*哪个* primitive 触发而不同(即只因 `trace_point_id` 和 oneof field 不同),payload layout 不变。
### 算法
```c
// DecodeScInstructionCoreInterrupt @0xf60a8c0 (vfc) — representative of all 11
function DecodeScInstruction<Prim>(view, started_out, entry):
if view.length <= 0xf: return error
BitDecoder dec(view); SkipBits(dec, 2); // framing
DecodeTraceHeader(entry, dec); // id/block/timestamp → bit 61
entry[+0x28] = <oneof field>; // vfc 75..85 / glc 67..77 / gfc 66..76
GetBits64(dec, 32, &data); // data (uint32)
GetBits64(dec, 1, &done); // done (bool)
GetBits64(dec, 6, &extra_id); // extra_id (uint32, 6-bit field)
GetBits64(dec, 13, &index); // index (uint32, 13-bit field)
GetBits64(dec, 14, &pc); // pc (uint32, 14-bit field)
CHECK(BitsDecoded() == 127); // movl $0x4b,0x28 stamps oneof 75
*bytes_consumed = 0x10;字段映射
Proto 字段(经 descriptor 确认,所有 11 个事件和全部 3 代都相同):data(uint32)、done(bool)、extra_id(uint32)、index(uint32)、pc(uint32)。
| 字段 | 宽度 | 含义 | 置信度 |
|---|---|---|---|
data | 32 | sequencer-primitive operand / payload word(例如 tracemark value、interrupt cause) | HIGH |
done | 1 | primitive-complete flag | HIGH |
extra_id | 6 | 每事件 correlation tag(SC band 的本地 “sub-id”) | HIGH |
index | 13 | primitive 目标的 sequencer slot / sync-flag index | MEDIUM |
pc | 14 | issue 时的 SCS program counter | HIGH |
每代宽度表
| 代 | payload widths(无 TraceIdHeader) | CHECK | pkts | oneof base |
|---|---|---|---|---|
| vfc | 32,1,6,13,14 | 127 | 1 | 75 |
| glc | 32,1,6,13,14 | 127 | 1 | 67 |
| gfc | 32,1,6,13,14 | 127 | 1 | 66 |
66 payload bits + 61 frame+header = 127。三个 SC generation 之间字节相同 —— 只有 oneof base 不同(wire shape 和 CHECK 不变)。这 11 个 primitive 按 oneof / on-wire-id 顺序为:CoreInterrupt, SetTracemark, TraceInstruction, SfenceStart, SfenceStop, SyncStart, SyncStop, BarrierStart, BarrierStop, SyncWatchStart, SyncWatchStop。
CONFIRMED (SC-1) —
DecodeScInstructionCoreInterrupt@0xf60a8c0反编译后正是SkipBits(2); DecodeTraceHeader; GetBits64(32); GetBits64(1); GetBits64(6); GetBits64(13); GetBits64(14); CHECK(==127),并带有movl $0x4b,0x28(= oneof field 75)。全部 11 个共享此 shape(vfc 上0xf60a8c0..0xf60bcc0,oneof 75..85)。
SC_TASK_* Band — Issue 和 Commit(2 个事件)
用途
SparseCore task 生命周期:task 从 SCS(SparseCore scalar sequencer)issued,随后在 SCT(SparseCore tile)上committed,并带有丰富的每引擎 stall accounting。ScTaskCommitOnSct 是主要的 SC progress record —— gather/scatter/sort/dedup throughput 通过它的 stall 和 word counter 读出。两者都不携带 TraceIdHeader。
ScTaskIssueFromScs — dispatch record
// DecodeScTaskIssueFromScs @0xf60bec0 (vfc)
function DecodeScTaskIssueFromScs(view, started_out, entry):
... SkipBits(2); DecodeTraceHeader; entry[+0x28] = 86; ... // glc 78 / gfc 77
GetBits64(dec, 13, &scs_pc); // SCS program counter
GetBits64(dec, 8, &tag); // task tag
GetBits64(dec, 14, &tec_pc); // TensorE-Compute engine PC
GetBits64(dec, 14, &tac_pc); // TensorA-Compute engine PC
GetBits64(dec, 16, &tile_bitmap); // SMEM-bitmap: which tiles the task spans
CHECK(BitsDecoded() == 126);
```text
| 字段 | 宽度 | 含义 | 置信度 |
|---|---|---|---|
| `scs_pc` | 13 | task issue 时的 SCS program counter | HIGH |
| `tag` | 8 | task correlation tag(与 `ScTaskCommitOnSct.tag` 匹配) | HIGH |
| `tec_pc` | 14 | [TEC](../sparsecore/tec-engine.md) program counter | HIGH |
| `tac_pc` | 14 | [TAC](../sparsecore/tac-engine.md) program counter | HIGH |
| `tile_bitmap` | 16 | SMEM-bitmap iteration field —— task 跨越的 tile 集合 | HIGH |
| 代 | widths | `CHECK` | pkts | oneof |
|---|---|---|---|---|
| vfc | `13,8,14,14,16` | 126 | 1 | 86 |
| glc | `13,8,14,14,16` | 126 | 1 | 78 |
| gfc | `13,8,14,14,16` | 126 | 1 | 77 |
65 payload bits + 61 = 126。各代字节相同。
### ScTaskCommitOnSct — progress record(在 gfc 上重构)
一个 2-packet 事件,在中途 packet-1 边界带 `CHECK == 128`。该 shape **在 gfc (6acc60406) 上重构**:分开的 TEC/TAC stall accounting 被折叠,并新增一个 load-store-unit hold-stall counter。
```c
// DecodeScTaskCommitOnSct @0xf60c0c0 (vfc) — 2-packet, mid CHECK 128, final CHECK 251
function DecodeScTaskCommitOnSct(view, started_out, entry):
... SkipBits(2); DecodeTraceHeader; entry[+0x28] = 87; ... // glc 79 / gfc 78
GetBits64(dec, 8, &tag); // task tag
GetBits64(dec, 4, &extra_id); // correlation sub-id
GetBits64(dec, 32, &total_cycles); // task wall cycles
GetBits64(dec, 16, &tec_ibuf_stalls);
GetBits64(dec, 7, &tec_sync_stalls_lo); // ── packet-boundary straddle ──
CHECK(BitsDecoded() == 128); // packet-1 boundary; movq $0x20 (32 B consumed)
GetBits64(dec, 1, &straddle_a); // (high half of tec_sync_stalls)
GetBits64(dec, 1, &straddle_b); // └ the 7+9 split spans the 16-byte boundary
GetBits64(dec, 9, &tec_sync_stalls_hi);
GetBits64(dec, 16, &tec_hold_stalls);
GetBits64(dec, 16, &tac_ibuf_stalls); // vfc/glc only
GetBits64(dec, 16, &tac_sync_stalls); // vfc/glc only
GetBits64(dec, 16, &tac_hold_stalls); // vfc/glc only
GetBits64(dec, 16, &num_spmem_words);
GetBits64(dec, 32, &num_hbm_words);
CHECK(BitsDecoded() == 251);| 字段 (vfc/glc) | 宽度 | 含义 | 置信度 |
|---|---|---|---|
tag | 8 | task tag(匹配 ScTaskIssueFromScs.tag) | HIGH |
extra_id | 4 | correlation sub-id | HIGH |
total_cycles | 32 | 设备周期中的 task duration | HIGH |
tec_ibuf_stalls | 16 | TEC instruction-buffer stall cycles | HIGH |
tec_sync_stalls | 7+9 (straddle) | TEC sync-flag wait cycles(跨 packet 边界) | HIGH |
tec_hold_stalls | 16 | TEC hold/backpressure stall cycles | HIGH |
tac_ibuf_stalls | 16 | TAC instruction-buffer stall cycles | HIGH |
tac_sync_stalls | 16 | TAC sync-flag wait cycles | HIGH |
tac_hold_stalls | 16 | TAC hold/backpressure stall cycles | HIGH |
num_spmem_words | 16 | task 的 SPMEM word throughput | HIGH |
num_hbm_words | 32 | task 的 HBM word throughput | HIGH |
| 代 | widths | mid CHECK | final CHECK | pkts | proto fields |
|---|---|---|---|---|---|
| vfc | 8,4,32,16,7,1,1,9,16,16,16,16,16,32 | 128 | 251 | 2 | 11 (TEC+TAC triples) |
| glc | 8,4,32,16,7,1,1,9,16,16,16,16,16,32 | 128 | 251 | 2 | 11 (identical) |
| gfc | 8,4,32,16,7,1,1,9,16,16,32,16 | 128 | 219 | 2 | 9 (TAC dropped, lsu_hold_stalls added) |
vfc/glc payload = 190 bits (251−61);gfc payload = 158 bits (219−61)。
CONFIRMED (SC-2) — gfc 重构是字节精确的。在
tec_sync_stalls的7,1,1,9straddle 之后,gfc 只读取16,16,32,16=tec_hold_stalls(16)、num_spmem_words(16)、num_hbm_words(32)、lsu_hold_stalls(16)—— 三个 TAC counter(tac_ibuf/sync/hold_stalls)消失,被单个lsu_hold_stalls(16)取代。读取自DecodeScTaskCommitOnSct@0xf673da0(gfc):midCHECK == 128,finalCHECK == 219。这是否是真正的 6acc60406 (v7x) microarch change(统一 SC tile 而不是分离 TEC/TAC),还是 profiler schema rev,尚未对 SC ISA 交叉检查(原因为 LOW;wire shape 为 CERTAIN)。
SC_STREAM_* Band — Gather/Scatter 和 Progress(3 个事件)
用途
SparseCore stream gather/scatter engine band。stream issue 事件携带 StreamOpcode(GATHER/SCATTER family)selector,加上 tile-local/off-tile memory 和 stream-type selector —— 它是 SC stream dispatch 的 on-wire image。两个 progress 事件(Xbar = crossbar lane,Cmn = memory-network lane)携带每次 progress 的 sync-flag bump。三者都不携带 TraceIdHeader。
ScStreamIssueFromCore — gather/scatter dispatch(在 glc/gfc 上变宽)
13 个 proto 字段,13 个宽度(每字段一个)。stream_opcode 宽度在较新代上从 3 增长到 4 bits,因为 StreamOpcode enum 增加了 half-width-accumulate 变体。
// DecodeScStreamIssueFromCore @0xf60c460 (vfc)
function DecodeScStreamIssueFromCore(view, started_out, entry):
... SkipBits(2); DecodeTraceHeader; entry[+0x28] = 88; ... // glc 80 / gfc 79
GetBits64(dec, 14, &pc);
GetBits64(dec, 6, &extra_id);
GetBits64(dec, 5, &sync_flag_id);
GetBits64(dec, 1, &sync_flag_core_type); // enum SyncFlagCoreType
GetBits64(dec, 3, &stream_opcode); // enum StreamOpcode (vfc 3-bit; glc/gfc 4-bit)
GetBits64(dec, 1, &tile_local_memory_type); // enum
GetBits64(dec, 3, &off_tile_memory_type); // enum
GetBits64(dec, 1, &tile_local_stream_type); // enum
GetBits64(dec, 2, &off_tile_stream_type); // enum
GetBits64(dec, 1, &set_done_bit); // bool
GetBits64(dec, 1, &sync_flag_count_type); // bool
GetBits64(dec, 1, &indirect_list_type); // enum
GetBits64(dec, 18, &length_in_4B); // uint32 (glc re-budgets to 17)
CHECK(BitsDecoded() == 118);
```text
| 字段 | vfc 宽度 | 含义 | 置信度 |
|---|---|---|---|
| `pc` | 14 | stream issue 时的 SC core PC | HIGH |
| `extra_id` | 6 | correlation sub-id | HIGH |
| `sync_flag_id` | 5 | stream 完成时发信号的 sync-flag | HIGH |
| `sync_flag_core_type` | 1 | target core class —— `TEC_OR_SCS`/`TAC` enum | HIGH |
| `stream_opcode` | 3 (vfc) / 4 (glc,gfc) | GATHER/SCATTER family —— 见 enum table | CERTAIN |
| `tile_local_memory_type` | 1 | `SMEM`/`TILESPMEM` enum | HIGH |
| `off_tile_memory_type` | 3 | `SPMEM`/`TILESPMEMN`/`HBM`/`HBM4B` enum | HIGH |
| `tile_local_stream_type` | 1 | `LINEAR`/`CIRCULARBUFFER` enum | HIGH |
| `off_tile_stream_type` | 2 | `LINEAR`/`STRIDED`/`INDIRECT`/`INDIRECTVREG` enum | HIGH |
| `set_done_bit` | 1 | 完成时设置 sync flag 的 done bit | HIGH |
| `sync_flag_count_type` | 1 | sync-flag bump 的 count-mode | MEDIUM |
| `indirect_list_type` | 1 | `WORD`/`ROW` indirection granularity enum | HIGH |
| `length_in_4B` | 18 (vfc,gfc) / 17 (glc) | 以 4-byte word 计的 stream length | HIGH |
| 代 | widths | `CHECK` | pkts | `stream_opcode` | `length_in_4B` |
|---|---|---|---|---|---|
| vfc | `14,6,5,1,3,1,3,1,2,1,1,1,18` | 118 | 1 | 3-bit (8 values) | 18 |
| glc | `14,6,5,1,4,1,3,1,2,1,1,1,17` | 118 | 1 | 4-bit (11 values) | 17 |
| gfc | `14,6,5,1,4,1,3,1,2,1,1,1,18` | 119 | 1 | 4-bit (11 values) | 18 |
> **CONFIRMED (SC-3) —** 每代 drift 是字节精确的。glc/gfc 为 `stream_opcode` 读取 `GetBits64(4)`,而 vfc 读取 `GetBits64(3)`(在 glc 的 `DecodeScStreamIssueFromCore` @ `0xf63e300` 验证)。glc 通过将 `length_in_4B` 从 18 收窄到 17 吸收额外 bit(保持 `CHECK == 118`);gfc 保持 `length_in_4B == 18`,并让总数增长到 `CHECK == 119`。导致变宽的 enum 增长见[下面的 enum table](#the-sparsecore-selector-enum-value-tables)。
### ScStreamProgressXbar / ScStreamProgressCmn — lane-progress events
wire shape 字节相同;**唯一**差异是 lane class —— `Xbar` 是 crossbar progress lane,`Cmn` 是 memory-network progress lane。
```c
// DecodeScStreamProgressXbar @0xf60c740 (vfc); DecodeScStreamProgressCmn @0xf60c940 identical shape
function DecodeScStreamProgress<Lane>(view, started_out, entry):
... SkipBits(2); DecodeTraceHeader; entry[+0x28] = 89/90; ...
GetBits64(dec, 6, &extra_id);
GetBits64(dec, 5, &sync_flag_id);
GetBits64(dec, 1, &sync_flag_core_type); // enum TEC_OR_SCS/TAC
GetBits64(dec, 32, &data);
GetBits64(dec, 1, &done);
CHECK(BitsDecoded() == 106);| 字段 | 宽度 | 含义 | 置信度 |
|---|---|---|---|
extra_id | 6 | correlation sub-id | HIGH |
sync_flag_id | 5 | 此 progress event bump 的 sync flag | HIGH |
sync_flag_core_type | 1 | TEC_OR_SCS/TAC enum | HIGH |
data | 32 | progress count / lane payload word | HIGH |
done | 1 | lane-drained flag | HIGH |
| 代 | widths | CHECK | pkts | oneof (Xbar / Cmn) |
|---|---|---|---|---|
| vfc | 6,5,1,32,1 | 106 | 1 | 89 / 90 |
| glc | 6,5,1,32,1 | 106 | 1 | 81 / 82 |
| gfc | 6,5,1,32,1 | 106 | 1 | 80 / 81 |
45 payload + 61 = 106。{sync_flag_id, sync_flag_core_type, done} 三元组是 stream 的每 progress sync-flag bump —— stream queue 使用的 producer/consumer occupancy signal。
SC_MESSAGE_* Band — Inter-Tile Internal Messages(2 个事件)
用途
SparseCore inter-tile / SCS↔SCT internal-message band:tile 之间的 queue-occupancy、sync-update 和 SMEM-update message。Outbound 和 Inbound 都携带 21,3,14(38-bit)TraceIdHeader,并且每代共享一种 wire shape。它们是唯一带 TraceIdHeader 的 SC 事件,且两者都是 2-packet 事件。
算法
// DecodeScMessageOutboundInternalMessage @0xf60e6c0 (vfc) — 2-packet, mid CHECK 128, final 176
function DecodeScMessage<Dir>InternalMessage(view, started_out, entry):
... SkipBits(2); DecodeTraceHeader; ... // bit 61
GetBits64(dec, 21, &transaction_id); // TraceIdHeader f1
GetBits64(dec, 3, &core_id); // TraceIdHeader f2 (3-bit enum)
GetBits64(dec, 14, &chip_id); // TraceIdHeader f3 (14-bit — note: not 12)
entry[+0x28] = 98; // glc 90 / gfc 90 (Inbound: vfc 99 / glc,gfc 91)
GetBits64(dec, 6, &extra_id);
GetBits64(dec, 5, &dest_tile_id);
GetBits64(dec, 1, &dest_core_type); // enum TEC_OR_SCS/TAC
GetBits64(dec, 13, &sync_flag_id);
GetBits64(dec, 4, &smem_address_lo); // ── packet-boundary straddle (4+10) ──
CHECK(BitsDecoded() == 128); // packet-1 boundary; movq $0x20 (32 B)
GetBits64(dec, 1, &straddle_a);
GetBits64(dec, 1, &straddle_b);
GetBits64(dec, 10, &smem_address_hi);
GetBits64(dec, 1, &msg_type); // enum SYNCUPDATE/SMEMUPDATE
GetBits64(dec, 2, &opcode); // enum WRITE/INC × NO_DONE/WITH_DONE
GetBits64(dec, 32, &data);
GetBits64(dec, 1, &done);
CHECK(BitsDecoded() == 176);
```text
| 字段 | 宽度 | 含义 | 置信度 |
|---|---|---|---|
| `trace_id_header` | 38 (`21,3,14`) | 每 transaction identity(`transaction_id`、`core_id`、`chip_id`) | CERTAIN |
| `extra_id` | 6 | correlation sub-id | HIGH |
| `dest_tile_id` | 5 | message 的 target tile | HIGH |
| `dest_core_type` | 1 | target core class —— `TEC_OR_SCS`/`TAC` enum | HIGH |
| `sync_flag_id` | 13 | message 更新的 sync flag | HIGH |
| `smem_address` | 4+10 (straddle) | SMEM target address(跨 packet 边界) | HIGH |
| `msg_type` | 1 | `SYNCUPDATE`/`SMEMUPDATE` enum | HIGH |
| `opcode` | 2 | `WRITE`/`INC` × `NO_DONE`/`WITH_DONE` enum | HIGH |
| `data` | 32 | message payload word | HIGH |
| `done` | 1 | done flag | HIGH |
| 代 | `TraceIdHeader` \| payload widths | mid `CHECK` | final `CHECK` | pkts | oneof (Out / In) |
|---|---|---|---|---|---|---|
| vfc | `21,3,14` \| `6,5,1,13,4,1,1,10,1,2,32,1` | 128 | 176 | 2 | 98 / 99 |
| glc | `21,3,14` \| `6,5,1,13,4,1,1,10,1,2,32,1` | 128 | 176 | 2 | 90 / 91 |
| gfc | `21,3,14` \| `6,5,1,13,4,1,1,10,1,2,32,1` | 128 | 176 | 2 | 90 / 91 |
payload 含 straddle = 115 bits;+ 61 = 176。三个 SC generation 之间字节相同。`dest_tile_id` + `dest_core_type` 选择 target tile 和 core;`msg_type` + `opcode` 是 message semantic。
---
## SparseCore Selector Enum Value Tables {#the-sparsecore-selector-enum-value-tables}
从 `trace_entries.proto` 中每个 SC message 的 `*Values` 嵌套 enum 字节精确读取(descriptor pool:vfc @ `0xbf06830`、glc @ `0xbf41210`、gfc @ `0xbf64c80`)。这些是上面解码出的 enum 字段的*命名*值。显示 vfc 值;glc/gfc 除 `StreamOpcodeValues` 外相同,后者在较新 generation 上增加 3 个值(和 1 bit)。
| Enum | 宽度 | 值 |
|---|---|---|
| `StreamOpcodeValues` (vfc) | 3-bit | `0=GATHER, 1=GATHERADDS32, 2=GATHERADDF32, 4=SCATTER, 5=SCATTERADDS32, 6=SCATTERADDF32, 7=RESERVED`(值 3 是空洞) |
| `StreamOpcodeValues` (glc/gfc) | 4-bit | 增加 `9=GATHERADDS16, 10=GATHERADDBF16, 13=SCATTERADDS16, 14=SCATTERADDBF16, 15=RESERVED` |
| `SyncFlagCoreTypeValues` | 1-bit | `0=TEC_OR_SCS, 1=TAC` |
| `TileLocalMemoryTypeValues` | 1-bit | `0=SMEM, 1=TILESPMEM` |
| `OffTileMemoryTypeValues` | 3-bit | `0=SPMEM, 1=TILESPMEMN, 2=HBM, 3=HBM4B` |
| `TileLocalStreamTypeValues` | 1-bit | `0=LINEAR, 1=CIRCULARBUFFER` |
| `OffTileStreamTypeValues` | 2-bit | `0=LINEAR, 1=STRIDED, 2=INDIRECT, 3=INDIRECTVREG` |
| `IndirectListTypeValues` | 1-bit | `0=WORD, 1=ROW` |
| `DestCoreTypeValues` | 1-bit | `0=TEC_OR_SCS, 1=TAC` |
| `MsgTypeValues` | 1-bit | `0=SYNCUPDATE, 1=SMEMUPDATE` |
| `OpcodeValues` | 2-bit | `0=WRITE_NO_DONE, 1=WRITE_WITH_DONE, 2=INC_NO_DONE, 3=INC_WITH_DONE` |
> **QUIRK —** `StreamOpcode` **不是** densely packed。GATHER family 占用 `0..2`,值 3 是空洞,SCATTER family 从 4 开始 —— 因此 gather/scatter 二分编码在高 bit 中,而不是连续范围。在 glc/gfc 上,half-width-accumulate 变体(`+S16`/`+BF16`)是 Ghostlite/6acc60406 上的 NEW,并插入 `9,10,13,14`,迫使字段变为 4 bits。假设 `0..n` 连续性的重新实现会把 SCATTER 错解为 reserved opcode。`SyncFlagCoreType`/`DestCoreType` 的 `TEC_OR_SCS`/`TAC` 分裂映射了 [SparseCore sequencer-type enum](../sparsecore/getsequencertype.md)。
---
## On-Wire-id → Trace-Point Map
codec 的[两级 dispatch](trace-entries-coder.md#the-dual-dispatch) 将 dense on-wire `trace_point_id` 空间拆成低 band(primary jump table)和高 band(primary overflow 后到达的 secondary jump table)。SC band 完全位于**高** band。on-wire id 是硬件打上的值,也是 decoder 索引的值;它与 handler 写入 `TraceEntry+0x28` 的 proto oneof field number **不同**。
> **QUIRK —** `ScInstructionCoreInterrupt` 的 on-wire id 是 **108**,但 proto oneof field 是 **75** (vfc)。dense on-wire id 空间(vfc 为 0..185 / glc 为 0..211 / gfc 为 0..206)是 *decode* key;dense oneof field 是 *encode* key。它们计数同一批事件,但索引不同 —— 捕获的 device-trace ring 打上 on-wire id,因此依赖 oneof field 驱动的 decoder 无法映射 raw stream。
### SC 子范围 — on-wire id → event → oneof(按 generation)
SC band 在高 band 中占据一段连续区间。on-wire id 在 **vfc/glc 间相同**(108..132);**gfc** 在 id 129 插入一个 `StatsCounterSampleIssuedFromScs`,将两个 `ScMessage*` 事件上移一位(到 132/133)。
| Event | on-wire id (vfc/glc) | vfc oneof | glc oneof | gfc oneof | gfc on-wire id |
|---|---|---|---|---|---|
| `ScInstructionCoreInterrupt` | 108 | 75 | 67 | 66 | 108 |
| `ScInstructionSetTracemark` | 109 | 76 | 68 | 67 | 109 |
| `ScInstructionTraceInstruction` | 110 | 77 | 69 | 68 | 110 |
| `ScInstructionSfenceStart` | 111 | 78 | 70 | 69 | 111 |
| `ScInstructionSfenceStop` | 112 | 79 | 71 | 70 | 112 |
| `ScInstructionSyncStart` | 113 | 80 | 72 | 71 | 113 |
| `ScInstructionSyncStop` | 114 | 81 | 73 | 72 | 114 |
| `ScInstructionBarrierStart` | 115 | 82 | 74 | 73 | 115 |
| `ScInstructionBarrierStop` | 116 | 83 | 75 | 74 | 116 |
| `ScInstructionSyncWatchStart` | 117 | 84 | 76 | 75 | 117 |
| `ScInstructionSyncWatchStop` | 118 | 85 | 77 | 76 | 118 |
| `ScTaskIssueFromScs` | 119 | 86 | 78 | 77 | 119 |
| `ScTaskCommitOnSct` | 120 | 87 | 79 | 78 | 120 |
| `ScStreamIssueFromCore` | 121 | 88 | 80 | 79 | 121 |
| `ScStreamProgressXbar` | 122 | 89 | 81 | 80 | 122 |
| `ScStreamProgressCmn` | 123 | 90 | 82 | 81 | 123 |
| `ScMessageOutboundInternalMessage` | 131 | 98 | 90 | 90 | 132 |
| `ScMessageInboundInternalMessage` | 132 | 99 | 91 | 91 | 133 |
`ScStreamProgressCmn` (123) 与 `ScMessageOutbound` (131) 之间的 7-id gap 由 **SC-issued OCI** descriptor/message events 填充 —— on-wire ids 124..130 = `OciDescriptorCommonIssuedBySc`、`OciDescriptorStride{Src,Dst,Steps}IssuedBySc`、`OciDescriptorAddressMiscIssuedFromSc`、`OciMessage{ReceivedBySc,SentBySc}`(SC 对自身 OCI traffic 的视图,由 [`payload-uhi-oci-ici-dma.md`](payload-uhi-oci-ici-dma.md) 负责)。gfc 还暴露 SparseCore PMU surface:`StatsCounterSampleIssuedFromScs` @ id 129,以及 `StatsCounterSampleIssuedFrom{Sctd,Sctc}` @ ids 134/135(SC TileData/TileCompute hardware perf-counter samples —— 仅 gfc)。
### 两级 dispatch 参数(到达 SC band 的路径)
```text
DecodeEntry(view):
read framing(2) + trace_point_id(8)
if id <= bound1: goto *primary_jt [id] // low band
else: id2 = id - rebase // high band
if id2 <= bound2: goto *secondary_jt [id2]
else: goto error| 代 | DecodeEntry | primary jt | bound1 | rebase | secondary jt | bound2 | SC sub-range |
|---|---|---|---|---|---|---|---|
| vfc | 0xf5f7080 | 0xab86ce8 | 0x5f (95) | −0x60 (96) | 0xab86e68 | 0x59 (89) | 108..132 |
| glc | 0xf6295c0 | 0xab875a8 | 0x62 (98) | −0x63 (99) | 0xab87734 | 0x70 (112) | 108..132 |
| gfc | 0xf65ffe0 | 0xab87f20 | 0x64 (100) | −0x6c (108) | 0xab880b4 | 0x62 (98) | 108..133 |
| vlc | 0xf5d6460 | 0xab86520 | 0x8f (143) | −0x90 (144) | 0xab86760 | 0x17 (23) | — (no SC) |
每个 secondary arm 都是相对于 secondary table base 的 rel32;arm 是 DecodeEntry 内部的 thunk,会写入 proto oneof tag 并 tail-call 匹配的 DecodeSc<Name>。codec page 负责 dispatch mechanism;本页负责它路由到的 SC 子范围。
CONFIRMED (SC-4) — 在 vfc
DecodeEntry@0xf5f7080中,decompiler 将两级 dispatch 渲染成嵌套 switch —— 外层switch以case 0x5f(primary)为边界,内层switch在case 0x60之后 rebase,并到达DecodeScInstructionCoreInterrupt。这就是早先 pxc reading(仅单表)标记为 “error label” 的 secondary table:在 vfc/vlc/glc/gfc 上,overflow target 是用于 high id band(SC/throttle/MGR/CMNUR)的第二个基于 id 重映射的 jump table。pxc 和 vlc 会到达 secondary table,但其中没有 SC arm —— pxc 改有 BarnaCoreBc_Fsm*band,vlc 只有VdqTransaction*和 MGR OCI。
此处未解码的内容
- straddle 字段的确切 uint64 重组 bit order ——
ScTaskCommitOnSct.tec_sync_stalls(7+9) 和ScMessage*.smem_address(4+10):宽度片段、+0xNN目的 offset,以及 packet-1 边界CHECK == 128均为 CERTAIN,但每个片段在重组值中占据的精确 LSB 位置未制表(LOW —— 与 UHI/OCI straddle fields 相同的 open item)。 - 下游 SC scalar → XStat/XEvent 映射 —— 哪个已解码 SC 字段(
num_spmem_words、tec_sync_stalls、tile_bitmap、stream_opcode)变成哪个 XStat,或被折叠进 SparseCore XEvent 名称,发生在SparseCoreOverlaySubscriber中,由trace-entry-to-xevent.md负责。 - gfc-only SC PMU sampling events(
StatsCounterSampleIssuedFrom{Scs,Sctd,Sctc}@ ids 129/134/135)和 SC-issued OCI descriptor sub-band(ids 124..130)—— 与 SC band 相邻,但不是DecodeSc*事件;它们的 payload 不在此处解码。 - gfc
ScTaskCommitOnSct重构的原因 —— wire shape(9 fields,CHECK == 219)为 CERTAIN;删除的 TAC counter 是否反映 unified-SC microarch change,还是 profiler schema rev,尚未对 SC ISA 交叉检查(LOW)。
相关组件
| 组件 | 关系 |
|---|---|
| TraceEntriesCoder | 这些 SC payload 所在的 codec —— 16-byte packet、61-bit envelope、GetBits64/CHECK、two-level dispatch |
| TracePoints Master Registry | 完整的跨 band wire-id ↔ oneof-field registry;本页只负责 SC 子范围 |
| Payload: UHI/OCI/ICI/DMA | 相邻 high-band events(SC-issued OCI ids 124..130),以及 SC band 变为 21,3,14 的 21,3,12 TraceIdHeader |
| Payload: vfc/vlc/gfc | SC payload 继承的每家族 header delta(6-bit block_id、45-bit timestamp、14-bit chip_id) |
| SCS Engine | 发出 ScTaskIssueFromScs 并运行 ScInstruction* primitive 的 sequencer |
| Stream Gather/Scatter | ScStream* 事件和 StreamOpcode enum 所插桩的 datapath |
交叉引用
- TraceEntriesCoder — 本页 payload 被读取时所在的 packet/framing/header/dispatch
- TracePoints Master Registry — SC 子范围所嵌入的 wire-id ↔ oneof-field 双 id 空间 registry
- Payload: UHI/OCI/ICI/DMA — 同一 high id band 中的相邻 band(以及 SC-issued OCI events)
- Payload: vfc/vlc/gfc — SC band 所基于的较新家族 header layout
- Payload: jxc Legacy — 没有 SC band 的独立
PerformanceTraceEntryschema - SCS Engine · TEC Engine · TAC Engine — 这些事件所插桩的 SparseCore sequencer 和 compute tiles
- Stream Gather/Scatter —
ScStream*band 和StreamOpcodeenum 描述的 gather/scatter engine - getSequencerType —
SyncFlagCoreType/DestCoreTypeselector 所映射的SCS/TAC/TECsequencer-type enum - Profiling and Telemetry Overview — 此 band 输入的 capture→encode→decode→xplane pipeline