Skip to content

VectorStore Slot

本页中的每个 opcode 值、mask immediate、字段 shift/width 以及各代计数,都是从 libtpu-0.0.40-cp314 wheel(build-id 89edbbe81c5b328a958fe628a9f2207d)里的 libtpu.so 按字节精确读出的 — 来源包括每个 op 的 SparseCoreTecVectorStore<OpName>Opcode::Matches() 比较立即数、<OpName><Field>Field::GetConcatenatedValue() accessor shift,以及 SparseCoreTecVectorStoreEncoder::EncodeBitCopy destination-bit immediate。其他版本会不同。

摘要

VectorStoreTEC bundle 的七个 vector slot 之一 — 它把 VREG 写回每 tile SRAM(TILE_SPMEM)。不同于 scalar store,它不是一个带 address mode 的单一 op;它是一个编码二轴乘积的 6-bit opcode 字段,即 element-type × store-mode,opcode 值本身就是 dtype 与 mode 的选择。该 slot 是 SparseCore embedding-reduce datapath 的后半段:VectorLoad slot 从 TILE_SPMEM 拉取 gathered row 到 VREG,VectorExtended slot 对其 reduce,而 VectorStore 写回结果 — 并且关键的是,它能以 atomic scatter-add 形式写入,这是 embedding-table gradient accumulation 的构造块。若重新实现者把 VectorStore 建模为“把 vector store 到一个 address”,会得到一个无法表达该 slot 存在意义的操作:对 tile location 做 read-modify-add。

6acc60406(gfc)上的 opcode space 是 33 个 op,连续 0..32,从每个 op 的 Matches() predicate 逐字节读出(opcode = cmp_immediate >> 33,字段为 struct offset 0x30 处 8-byte word 的 bit 33 上 6-bit)。这 33 个值不是 flat list — 它们是一个矩阵的 cell,矩阵轴是四种 accumulate dtype(S32F32S16Bf16)和 store-mode lattice(plain overwrite · scatter-ADD · circular-buffer-windowed · post-update · per-element indexed · indexed fetch-and-add)。store-mode 不是由 mode sub-field decode,而是由 op 携带的 operand field 判定:+Cbreg = circular-buffer window,+Index = per-element scatter,+Dest = fetch-and-add return value,名称中的 Add = atomic accumulate 而不是 overwrite。本页记录 slot field map,枚举带逐字节 opcode 值的 33-entry type×mode matrix、per-mode operand field set、让 VectorExtended reduction 可以直接流入 store mux 的共享 VstSource fusion path,以及把 slot 从 15 个 op 增长到 33 个 op 的 Viperfish→Ghostlite generic-to-typed rename。

对重新实现而言,契约是:

  • opcode 就是 (element-type × store-mode) 乘积。 word 0x30 bit 33 处 6-bit 字段;opcode = Matches_cmp_immediate >> 33;gfc/glc 上连续 0..32。没有单独 dtype operand,也没有单独 mode operand — 二者都 baked into opcode value,排序先交织 {S32,F32},再是 {S16,Bf16}(dtype split),每组内部按 store-mode lattice 排列。
  • store-mode 由 operand-field SET decode,而不是 mode bit。 Plain {Source,BaseAddress,Offset,Stride,Mask};circular-buffer form 增加 +Cbreg(4-bit,→ 16 个 CBREGs);indexed scatter 增加 +Index(6-bit VREG);fetch-and-add return 增加 +Dest(word 0x28 处 6-bit VREG)。最密集 form(IndexedCircularBufferReturnValueAdd*)携带全部字段且无重叠。
  • Add 表示 atomic read-modify-add,不是 overwrite。 Plain TileSpmemStore/…Indexed/…CircularBuffer 覆盖 addressed word;每个 …Add{dt} form 都 accumulate 到现有 TILE_SPMEM location。这是 embedding-gradient accumulator;跨 HBM 的等价物是 Stream slot 的 SCATTER_FLOAT_ADD
  • 该 slot 与 VectorExtendedVstSource 共享 Source bit position。 二者都位于 word 0x30 >> 27 & 0x3f,因此 scan/reduce 结果可以直接驱动 store-source mux — reduced row 无需单独的 VectorStore-slot round-trip 即可写回。
SlotVectorStore — 64-byte TEC bundleTecVectorStore slot
Bundle base / opcode bitbase @328,opcode @353(absolute bundle bit;Source @347)
Opcode fieldword 0x30 bit 33 处 6-bit(gfc/glc);bit 31 处 4-bit(vfc)
Opcode → mnemonic source每个 op 的 SparseCoreTecVectorStore<Op>Opcode::Matches() immediate(>> 33
Op count (per gen)vfc 15 · glc 33 · gfc 33
Matrix axesdtype {S32,F32,S16,Bf16} × mode {plain · Add · CB · CB-PostUpdate · Indexed · IndexedReturnValue}
Data wordword 0x30(所有字段),但 Dest @ word 0x28 bit 52(仅 RVA form)
EncoderSparseCoreTecVectorStoreEncoder::Encode(gfc 0x1eccbe20
ConfidenceCONFIRMED(decompile / Matches-immediate 锚定),除非某行或 callout 另有说明

注意 — 本页负责 VectorStore opcode roster 与 field decode;64-byte bundle layout 在 TEC Engine 中。 bundle byte map、slot base(@328)、absolute opcode bit(@353)、encoder-dispatch model 以及 no-check-trailer rule 在那里记录,这里不重复。馈送该 slot 的 VectorExtended scan family 是 VectorExtended (VEX);load counterpart 是 VectorLoad


Slot Field Map {#the-slot-field-map}

目的

VectorStore slot 将一个 VREG(Source)写入 TILE_SPMEM,地址由 {BaseAddress, Offset, Stride}(或 CBREG window)构造,受 lane Mask 控制,可选地由 per-element Index VREG scatter,可选地 accumulate(Add),并可选地把 pre-add 值返回到 Dest VREG。每个 data field 都位于 struct offset 0x30 处的 8-byte word — 也就是持有 opcode 的同一个 word — 但 fetch-and-add 的 Dest 例外,它位于 word 0x28(load-Dest mux,见 §The Fetch-and-Add Return Path)。

Field Layout

已用 gfc plain TileSpmemStore field accessor(SparseCoreTecVectorStoreTileSpmemStore&lt;Field&gt;Field::GetConcatenatedValue)逐字节确认,每个都是单个 (word >> shift) & mask。opcode 与 data field 共享 word 0x30

text
VectorStore slot — word 0x30 (8 bytes) + Dest in word 0x28 (gfc)
 word0x30 bit: 2        8        13       17    20    23     27       33
              ┌────────┬────────┬────────┬─────┬─────┬──────┬────────┬────────┐
              │ Index  │ Mask   │ Stride │Offs.│Base │Cbreg │ Source │ Opcode │
              │ 6b     │ 5b     │ 4b     │ 3b  │ 3b  │ 4b   │ 6b     │ 6b     │
              │ @2     │ @8     │ @13    │ @17 │ @20 │ @23  │ @27    │ @33    │
              └────────┴────────┴────────┴─────┴─────┴──────┴────────┴────────┘
              Indexed* only      ◄──── address build ────►  CB* only  the VREG  the type×mode
                                                                       stored

 word0x28 bit 52:  Dest 6b   ── IndexedReturnValue* only (fetch-and-add return VREG; == VectorLoad Dest)
FieldWordShiftWidthPresent in modesAccessor (gfc)
Opcode0x30336全部(Matches predicate)
Source0x30276全部…StoreSourceField 0x1ecca3e0
Cbreg0x30234CircularBuffer*(→ 16 个 CBREGs…CbregField
BaseAddress0x30203全部(explicit base / CBREG base 的替代)…BaseAddressField
Offset0x30173全部(window 内 offset)…OffsetField
Stride0x30134全部(per-element address stride)…StrideField
Mask0x3085全部(lane predicate / vmask)…MaskField 0x1ecca460
Index0x3026Indexed*(per-element scatter VREG)…IndexField 0x1eccaf00
Dest0x28526IndexedReturnValue*(fetch-and-add return)…DestField 0x1eccb860

上面的 shift 来自 plain TileSpmemStore op-form,这是 canonical reference:它携带地址构造字段且没有 Cbreg/Index/Dest。最密集的 op-form IndexedCircularBufferReturnValueAddS32Source accessor 0x1eccb780Dest 0x1eccb860)在 word 0x30 中携带 {Source@27, Cbreg@23, BaseAddress@20, Offset@17, Stride@13, Mask@8, Index@2},在 word 0x28 中携带 Dest@52,并携带 Opcode@33 — 已验证无重叠、无空隙。{Source,BaseAddress,Offset,Stride,Mask} 位置与 Stream slot 的 scatter-add descriptor decode(Source @>>0x1b,Cbreg @>>0x17)匹配,交叉确认了地址构造字段顺序。

陷阱 — store-mode 不是 sub-field;它是 opcode 值加 operand-field SET。 没有 decoder 会读取“mode”bit 来选择 plain-vs-CB-vs-indexed。6-bit opcode 就是 mode(以及 dtype),给定 opcode 携带的 operand field 由它决定:CircularBuffer* opcode 读取 CbregIndexed* opcode 读取 IndexReturnValue* opcode 读取 Dest。重新实现者必须按 opcode 决定 field extraction,而不是寻找 orthogonal mode encoding — 它不存在。

特性 — fetch-and-add Dest 位于 word 0x28 的 load-Dest mux,而不是和其余 store 字段一样位于 word 0x30 IndexedReturnValueAdd* form 通过 VectorLoad slot 的 Dest 完全相同 bit position(word0x28 >> 52 & 0x3f)把 pre-add 值写入 VREG。所有 8 个 gfc ReturnValueAdd op 都已确认从 word 0x28 bit 52 读取 Dest。store 把 data 放在 word 0x30,因为它驱动 store mux;当它还要返回一个值时,它借用 load-Dest mux — 这就是 fetch-and-add 返回 pre-add 值的结构原因(它是 load-then-add)。见 §The Fetch-and-Add Return Path


33-Entry Type×Mode Scatter Matrix

opcode-recovery model

每个 store op-form 都是一个独立 C++ type SparseCoreTecVectorStore<OpName>Opcode,携带 Matches() const predicate:它从 decoded-instruction word 中 mask 出 opcode 字段,并与该 op 的 signature 比较。cmp immediate 就是 opcode(移位后):该字段是 struct offset 0x30 处 8-byte word 的 bit 33 上 6-bit(mask 0x7e00000000),所以 opcode = cmp_immediate >> 33。base op(TileSpmemStore,0)用 testb $0x7e, 0x34(%rdi); sete 测试(+0x34 处 byte 是 word 0x30 的 bits 32..39;mask 0x7e 隔离 6 个 opcode bit,全零即 op 0)。逐字节示例:

c
// SparseCoreTecVectorStoreTileSpmemStoreOpcode::Matches            (gfc 0x1ecc9f40)
return (*((uint8_t *)this + 52) & 0x7E) == 0;            // byte +0x34, opcode 0
// …TileSpmemStoreCircularBufferOpcode::Matches                     (gfc 0x1ecc9f60)
return (*((uint64_t *)this + 6) & 0x7E00000000) == 0x200000000;   // 0x2…>>33 = 1
// …TileSpmemStoreAddS32Opcode::Matches                             (gfc 0x1ecc9fa0)
return (*((uint64_t *)this + 6) & 0x7E00000000) == 0x600000000;   // 0x6…>>33 = 3
// …TileSpmemStoreAddF32Opcode::Matches                             (gfc 0x1ecca060)
return (*((uint64_t *)this + 6) & 0x7E00000000) == 0xC00000000;   // 0xc…>>33 = 6
// …IndexedCircularBufferReturnValueAddBf16Opcode::Matches          (gfc 0x1ecca340)
return (*((uint64_t *)this + 6) & 0x7E00000000) == 0x4000000000;  // 0x40…>>33 = 32

*((uint64_t*)this + 6) 是 byte offset 0x30 处的 word。已枚举并 decode 所有 33 个 gfc store-op Matches() immediate;得到的 opcode set 是连续 0..32,无空洞、无重复,且 opcode→mnemonic map 与下方矩阵逐行匹配。

两条轴

6-bit opcode 枚举一个(dtype × store-mode)grid 的 cell。排序不是 lexical — 它是 Ghostlite 引入的 dtype split(见 §VF→GF Evolution):先是 gen-stable base/indexed-plain op,再是交织的 {S32,F32} Add family,然后是 {S16,Bf16} Add family:

AxisValuesDecoded by
Element type(accumulate dtype)S32 · F32 · S16 · Bf16(仅 Add form;plain/indexed-plain 与 dtype 无关)opcode 值(无 dtype operand)
Store modeplain overwrite · scatter-Add · CircularBuffer(+Cbreg) · +PostUpdate(advance CBREG) · Indexed(+Index) · IndexedReturnValue(+Dest,fetch-and-add)opcode 值 + 它携带的 operand field

完整矩阵(gfc,33 个 op,逐字节确认)

opmnemonic (TileSpmem…)dtypestore modeextra fields
0Storeplain overwrite
1StoreCircularBufferplain, CB-windowedCbreg
2StoreCircularBufferPostUpdateplain, CB + advanceCbreg
3StoreAddS32S32scatter-ADD
4StoreCircularBufferAddS32S32scatter-ADD, CBCbreg
5StoreCircularBufferPostUpdateAddS32S32scatter-ADD, CB+advCbreg
6StoreAddF32F32scatter-ADD
7StoreCircularBufferAddF32F32scatter-ADD, CBCbreg
8StoreCircularBufferPostUpdateAddF32F32scatter-ADD, CB+advCbreg
9IndexedStoreindexed scatter(overwrite)Index
10StoreIndexedCircularBufferindexed scatter, CBIndex,Cbreg
11StoreIndexedAddS32S32indexed scatter-ADDIndex
12StoreIndexedCircularBufferAddS32S32indexed scatter-ADD, CBIndex,Cbreg
13StoreIndexedAddF32F32indexed scatter-ADDIndex
14StoreIndexedCircularBufferAddF32F32indexed scatter-ADD, CBIndex,Cbreg
15StoreIndexedReturnValueAddS32S32indexed fetch-and-addIndex,Dest
16StoreIndexedCircularBufferReturnValueAddS32S32indexed fetch-and-add, CBIndex,Cbreg,Dest
17StoreIndexedReturnValueAddF32F32indexed fetch-and-addIndex,Dest
18StoreIndexedCircularBufferReturnValueAddF32F32indexed fetch-and-add, CBIndex,Cbreg,Dest
19StoreAddS16S16scatter-ADD
20StoreCircularBufferAddS16S16scatter-ADD, CBCbreg
21StoreCircularBufferPostUpdateAddS16S16scatter-ADD, CB+advCbreg
22StoreAddBf16Bf16scatter-ADD
23StoreCircularBufferAddBf16Bf16scatter-ADD, CBCbreg
24StoreCircularBufferPostUpdateAddBf16Bf16scatter-ADD, CB+advCbreg
25StoreIndexedAddS16S16indexed scatter-ADDIndex
26StoreIndexedCircularBufferAddS16S16indexed scatter-ADD, CBIndex,Cbreg
27StoreIndexedAddBf16Bf16indexed scatter-ADDIndex
28StoreIndexedCircularBufferAddBf16Bf16indexed scatter-ADD, CBIndex,Cbreg
29StoreIndexedReturnValueAddS16S16indexed fetch-and-addIndex,Dest
30StoreIndexedCircularBufferReturnValueAddS16S16indexed fetch-and-add, CBIndex,Cbreg,Dest
31StoreIndexedReturnValueAddBf16Bf16indexed fetch-and-addIndex,Dest
32StoreIndexedCircularBufferReturnValueAddBf16Bf16indexed fetch-and-add, CBIndex,Cbreg,Dest

特性 — 矩阵是有意 sparse;并非每个 (dtype × mode) cell 都存在。 grid 本会预测的三个 cell 不存在,重新实现者不能合成它们:任何 Indexed form 都没有 PostUpdate(post-update 只与 non-indexed CB store 配对 — ops 2/5/8/21/24),S16/Bf16 IndexedReturnValueAdd 没有被删掉(它们存在,ops 29..32),但 non-indexed form 没有 fetch-and-addReturnValue 只与 Indexed 一起出现)。plain/indexed-plain overwrite(0,1,2,9,10)与 dtype 无关,因此没有 S32/F32/S16/Bf16 variant。33 个条目正是所有可达 cell;完整 Cartesian product 会更大。

陷阱 — dtype 是 opcode 的一部分,不是 operand。 StoreAddS32StoreAddBf16不同 opcode(3 vs 22),不是一个带 dtype operand 的 StoreAdd op。若重新实现者发出单一 add-store 加独立 dtype field,会与 opcode-encoded dtype 冲突并误 decode。accumulate width 由 opcode 值固定;Source VREG 携带该宽度的数据。


Store-Mode Roster

store-mode lattice 是第二条轴。每个 mode 都是对 TILE_SPMEM 的 read-modify-write 行为,按 §The Slot Field Map 所示,由 opcode 携带的 operand-field set decode:

ModeMarker in nameBehaviorExtra fieldEmbedding role
plain store(无 Add覆盖 addressed wordactivation / state write-back
scatter-ADDAdd对 location 做 atomic read-modify-addembedding-gradient accumulate
CircularBufferCircularBuffer通过 CBREG window 寻址(16 个 CBREG,4-bit selector)Cbregwindowed minibatch tile
+PostUpdate…PostUpdatestore 后推进 CBREG offsetCbreg无需单独 pointer bump 的 streaming tile write
IndexedIndexed从 VREG 读取 per-element scatter offsetIndexper-id gradient scatter
IndexedReturnValue…ReturnValueAddfetch-and-add:把 pre-add 值返回到 Dest VREGIndex,Destatomic accumulate,同时产出 old value

store mode 与 dtype 一起选择 opcode;opcode 选择 field set。mode lattice 与 VectorLoad slot 在读侧使用的 lattice 相同(plain / CircularBuffer / PostUpdate / Indexed),但去掉了只对写入有意义的 Add/ReturnValue accumulate 语义。

Add 语义 — atomic accumulate

名称中的 Add 是 overwrite 与 atomic read-modify-add 的区别。plain TileSpmemStore(op 0)用 Source 覆盖 addressed word;TileSpmemStoreAddF32(op 6)原子地计算 mem[addr] += Source。这是 Stream slot 所携带 cross-HBM atomic(STREAM_OPCODE_SCATTER_FLOAT_ADD)的 per-tile counterpart:embedding lookup 的 backward pass 会把每个 row 的 gradient accumulate 到 embedding table 中,在 tile 上该 accumulate 就是 VectorStore …Add{dt}

Circular-Buffer window 与 PostUpdate

CircularBuffer form 通过 16 个 CBREG 之一寻址(word 0x30 bit 23 处 4-bit Cbreg selector),而不是 explicit base — CBREG 持有 window base+offset,硬件在 window 内 wrap。…PostUpdate variant 会在 store 后推进 CBREG offset,因此把连续 tile stream 到 windowed buffer 的 loop 不需要单独 pointer-bump instruction。wrap arithmetic 是 CBREG hardware 的内在行为;store op 只携带 4-bit selector,从不携带 wrap bounds(它们位于 CBREG triple 中 — 见 CBREG)。

Indexed scatter

Indexed form 增加 6-bit Index VREG selector(@ word 0x30 bit 2),提供 per-element scatter offset:不再做单个 strided write,而是每个 lane 写入(或 accumulate 到)addr + Index[lane]。这是 embedding gradient 的 per-id scatter — gathered ids 反向索引 table,indexed scatter-add 将每个 row 的 gradient 写到其 row。indexed-plain form(9、10)scatter 一个 overwrite;indexed-Add form(11..14、25..28)scatter 一个 accumulate


Fetch-and-Add Return Path {#the-fetch-and-add-return-path}

目的

IndexedReturnValueAdd* family(8 个 op:{S32,F32,S16,Bf16} × {plain-indexed, CB-indexed},ops 15..18、29..32)是 fetch-and-add:它把 Source accumulate 到 mem[addr + Index],并把 add 之前存在的值返回到 Dest VREG。所有 8 个 gfc ReturnValueAdd op 都已确认从 word 0x28 bit 52 读取 Dest — 这与 VectorLoad slot 用于 load destination 的 bit position 完全相同。

为什么是 pre-add 值,以及为什么通常无关紧要

c
// fetch-and-add structural model — the Dest is the LOAD mux, so it captures pre-add
function FetchAndAddStore(slot):                  // e.g. TileSpmemStoreIndexedReturnValueAddF32 (op 17)
    addr  = BuildAddress(BaseAddress, Offset, Stride, Cbreg?)   // word0x30 fields
    addr += Index[lane]                            // per-element scatter (Index @ word0x30 bit2)
    old   = mem[addr]                              // read THROUGH the load-Dest mux (word0x28 bit52)
    Dest[lane] = old                               // return the PRE-add value
    mem[addr] = old + Source[lane]                 // atomic accumulate (word0x30 Source @bit27)

返回值是 pre-add,因为该 op 结构上是 load-then-add:Dest 通过 plain load 使用的同一个 mux 写入,lowering 目标是 LLVM intrinsic llvm.tpu.vst.msk.idx.ret.add.np(以及 .e4m3.np/.e5m2.np FP8 form;ret.add = return-then-add),而非普通 indexed scatter-add llvm.tpu.vst.[cb.]msk.idx.add。在 MLIR 层,fetch-and-add 是 VectorLoadStoreIdxAddOp(它 result type),相对的 VectorStoreIdxOp 没有 result。

注意 — vector 内 duplicate-index commit order 是 silicon,但 dedup path 让它无关紧要。 对于一个 vector 内并发 same-address fetch-and-add(真正重复 index),per-lane commit order 是硬件行为,不存在于 C++ 中。在 embedding path 中它不会触发:dedup pipeline(Sort → Uniquify → DuplicateCount)会在 scatter 前折叠重复 id,因此每个 unique row 正好被触碰一次,其 multiplicity 已折入 gradient。dedup 就是 correctness mechanism;fetch-and-add ordering 只对 raw、禁用 dedup 的 scatter 有意义(由 xla_tpu_enable_sparse_core_computation_deduplication gate 控制)。


VstSource Fusion {#the-vstsource-fusion}

VectorExtended slot — scan/sort/reduce engine — 携带一个 VstSource 字段,它位于 VectorStore slot 用于 Source 的完全相同 bit position:word 0x30 >> 27 & 0x3f。已在 gfc VectorExtended scan op 上逐字节确认(MinScanU32 VstSourceField 0x1eca7d80 读取 word0x30 >> 27 & 0x3f)— 与 gfc TileSpmemStore Source accessor(0x1ecca3e0)相同。

text
fused reduce → store (one TEC bundle, no VectorStore round-trip)
   VectorExtended slot          VectorStore slot
   (scan / segmented-scan)      (TileSpmemStore…Add{dt})
        │  result                     │
        └── VstSource @word0x30>>27 ───┘ Source @word0x30>>27   ◄── SAME bit position
            (the scan/reduce output drives the store-source mux directly)

由于 reduce output 与 store source 占据同一字段,VectorExtended reduction 可以直接驱动 store-source mux:reduced embedding row 无需中间 VectorStore-slot instruction 就能流入 TILE_SPMEM。结果也会经由 XRF → VectorResult path drain;两者并不互斥。这种 fusion 解释了为什么 embedding-reduce inner loop 所需 bundle 比朴素 load-scan-store sequence 更少 — scan 就是 store source。

特性 — VstSource 是一个命名 VectorStore resource 的 VectorExtended 字段。 重新实现者阅读 VectorExtended slot template 时会看到一个 6-bit 字段,其含义是“scan result 所馈送的 store source”,而不是 scan operand。它是两个 slot 之间的结构接口;把它当作普通 VEX operand 会错误建模 fused write-back。


VF→GF Generic-to-Typed Evolution {#the-vfgf-generic-to-typed-evolution}

计数增长

该 slot 从 Viperfish 的 15 个 op 增长到 Ghostlite 和 6acc60406 的 33 个 op;增长来自 dtype split 加一个新的 fetch-and-add family,而不是新的 addressing mode:

QuantityViperfish (vfc, v5)Ghostlite (glc, v6e)6acc60406 (gfc, TPU7x)
VectorStore op count153333
Opcode fieldword 0x30 bit 31 处 4-bitbit 33 处 6-bitbit 33 处 6-bit
dtype namingFloat/Integer(generic)S32/F32/S16/Bf16S32/F32/S16/Bf16
IndexedReturnValue(fetch-and-add)familyyesyes
Operand frame(Source/Base/Offset/Stride/Masksamesamesame

变化与不变

Viperfish 使用type-generic nameTileSpmemFloatStoreAddTileSpmemIntegerStoreAdd — 将所有 integer width 折叠进 Integer,所有 float width 折叠进 Float,并在 word 0x30 bit 31 使用 4-bit opcode field。Ghostlite 将每个 Float/Integer Add form 拆成四个 concrete dtype(S32/F32/S16/Bf16),添加整个 IndexedReturnValue fetch-and-add family(VF set 缺少的 8 个 op),并把 opcode field 加宽到 bit 33 处 6-bit 以容纳更大的 roster。低 opcode 在 rename 前后 gen-stable:VF TileSpmemIntegerStoreAdd = 3 ↔ GF StoreAddS32 = 3;VF TileSpmemFloatStoreAdd = 6 ↔ GF StoreAddF32 = 6;base/plain ops 0..2 完全相同。

text
VF 15-op roster (generic names) → GL/GF 33-op roster (typed)
  VF: TileSpmemStore                         (0)  ─┐ gen-stable
      TileSpmemStoreCircularBuffer           (1)   │ 0..2 identical
      TileSpmemStoreCircularBufferPostUpdate (2)  ─┘
      TileSpmemIntegerStoreAdd               (3)  → StoreAddS32        (3)   ┐ Integer →
      TileSpmemIntegerStoreAdd{CB,CB+adv}    (4,5)→ {S32 CB forms}            │ {S32,S16}
      TileSpmemFloatStoreAdd                 (6)  → StoreAddF32        (6)   ┐ Float →
      TileSpmemFloatStoreAdd{CB,CB+adv}      (7,8)→ {F32 CB forms}            │ {F32,Bf16}
      TileSpmemIndexedStore                  (9)  → IndexedStore       (9)
      TileSpmemIndexedStoreCircularBuffer    (10) → StoreIndexedCircularBuffer (10)
      TileSpmem{Integer,Float}IndexedStoreAdd[CB] (11..14)  → split into {S32,F32,S16,Bf16} indexed-Add
      (no fetch-and-add)                           → + IndexedReturnValueAdd family (8 new ops)

特性 — VF opcode field 比 GF 窄 1 bit 且低 2 bit。 Viperfish 将 opcode 打包在 bit 31 处 4 bit;Ghostlite/6acc60406 在 bit 33 处 6 bit。面向 Viperfish 的重新实现者必须 decode (word0x30 >> 31) & 0xf(并使用 Float/Integer generic name),而不是 GF 的 (word0x30 >> 33) & 0x3f。4-bit field 正好容纳 15 个 op(0..14);dtype split 和 fetch-and-add family 会溢出它,因此 GF 加宽了该字段 — 这与 VectorAlu opcode field 增长时的 4→6 / 7→8 width pressure 相同。


Embedding-Reduce Composition

VectorStore 是 SparseCore embedding-reduce datapath 的 stage 5;它是闭合 loop 的 slot。完整组合如下(其他 stage 由链接页面负责):

text
SparseCore embedding lookup + reduce — 5-stage TEC datapath
  1. GATHER   Stream IndirectStream          id list → HBM[base+id*stride] → TILE_SPMEM   (stream-gather-scatter)
  2. LOAD     VectorLoad TileSpmemLoad*       TILE_SPMEM rows → VREGs                       (vectorload-slot)
  3. REDUCE   VectorExtended SegmentedAddScan per-sample prefix sum / max / dedup            (vectorextended-vex)
  4. DRAIN    VectorResult EupResult/PopXrf*  XRF (extended-result FIFO) → VRF              (vector-opcode-enum)
  5. SCATTER  VectorStore …Add{dt}            atomic scatter-add the gradient INTO the row  ◄── THIS PAGE

forward sum-lookup 用 VectorExtended SegmentedAddScan reduce gathered rows,并写出 per-sample result;backward gradient 是写入 windowed tile 的 VectorStore …Add{dt} scatter-add(或直接写入 HBM 的 Stream SCATTER_FLOAT_ADD)。VstSource fusion 让 stage 3 直接馈送 stage 5 的 mux,dedup pipeline 先于 scatter,因此每个 unique row 只被触碰一次。当 gradient math 需要 old accumulator 时,IndexedReturnValueAdd fetch-and-add(stage 5)产出 pre-add 值。


Function Map

Symbol (gfc)AddressRole
…VectorStoreTileSpmemStoreOpcode::Matches0x1ecc9f40op 0 predicate(testb $0x7e,0x34)— base op
…VectorStoreTileSpmemStoreCircularBufferOpcode::Matches0x1ecc9f60op 1(cmp 0x200000000
…VectorStoreTileSpmemStoreAddS32Opcode::Matches0x1ecc9fa0op 3(cmp 0x600000000
…VectorStoreTileSpmemStoreAddF32Opcode::Matches0x1ecca060op 6(cmp 0xC00000000
…IndexedCircularBufferReturnValueAddBf16Opcode::Matches0x1ecca340op 32(cmp 0x4000000000)— 最密集 op
…TileSpmemStoreSourceField::GetConcatenatedValue0x1ecca3e0Source @ word 0x30 >> 27 & 0x3f
…TileSpmemStoreMaskField::GetConcatenatedValue0x1ecca460Mask @ word 0x30 >> 8 & 0x1f
…TileSpmemIndexedStoreIndexField::GetConcatenatedValue0x1eccaf00Index @ word 0x30 >> 2 & 0x3f
…IndexedCircularBufferReturnValueAddS32SourceField0x1eccb780最密集 form 的 Source(同样 @27)
…IndexedCircularBufferReturnValueAddS32DestField0x1eccb860Dest @ word 0x28 >> 52 & 0x3f(RVA fetch result)
SparseCoreTecVectorStoreEncoder::Encode0x1eccbe20slot encoder;opcode BitCopy(a3, 353, …, 6) @ bundle bit 353,Source BitCopy(…,347,…,6),slot base @328
…VectorExtendedMinScanU32VstSourceField0x1eca7d80VstSource @ word 0x30 >> 27 — fused store-source(== Source

跨代锚点:vfc VectorStore opcode field 是 word 0x30 bit 31 处 4-bit(base op 通过 movzwl 0x33CircularBuffer 通过 mask 0x780000000 cmp 0x80000000 → 1),使用 generic Float/Integer name;glc/gfc 是 bit 33 处 6-bit,并有四 dtype split。完整 per-gen count — vfc 15、glc 33、gfc 33 — 已通过 decompile 中 per-namespace Matches symbol enumeration 重新确认。

注意 — TensorCoreVectorStore* 是不同 engine,不计入 33-count。 0x1fa07dc0+ VectorStore symbol 属于 TensorCore datapath,不属于 SparseCore TEC。只有 SparseCoreTecVectorStore* type 计入此 slot 的 33-op roster;重新实现者 grep VectorStore 时必须过滤 SparseCoreTec prefix。


注意事项

  • Opcode-keyed field extraction。 decoder 必须先读 opcode,然后只在 opcode 是 CircularBuffer* / Indexed* / ReturnValue* form 时提取 {Cbreg, Index, Dest}。没有 orthogonal mode encoding;从 non-indexed op 读取 Index 会读到垃圾(那些 bit 持有 address-build field 的低端)。
  • dtype 在 opcode 中。 通过选择正确 opcode(AddS32 vs AddBf16)编码 accumulate width,绝不要用单独字段;Source VREG 以该宽度提供数据。
  • Viperfish 是窄的 generic form。 bit 31 处 4-bit opcode、Float/Integer name、没有 fetch-and-add。面向 VF 的重新实现 decode 4-bit field,且只有 15 个 op;dtype split 与 IndexedReturnValue family 仅 GL/GF 有。
  • fetch-and-add ordering 是 silicon(raw scatter 为 LOW)。 pre-add return value 已结构确认(Dest = load mux,.ret.add intrinsic);vector 内 duplicate-index commit order 不在 C++ 中,对 non-deduplicated scatter 在此未定义。对 embedding path 它无关紧要(dedup 会先折叠 duplicate),但启用 raw scatter 的重新实现者必须把 duplicate-index ordering 视为 unspecified。
  • 未映射(LOW/inferred)。 在 scatter-add 前将 DuplicateCount multiplicity 折入 gradient 的精确算术未 bit-trace(op set 和 result count 已确认;count×gradient fold 是 lowering body)。BaseAddress/Offset/Stride 相对 CBREG window 的 address-build 语义已 decode 为字段位置,但精确 wrap arithmetic 是 CBREG hardware 内在行为(见 CBREG)。

NameRelationship
SparseCoreTecVectorStoreEncoder::Encode (0x1eccbe20 gfc)slot encoder;在 bundle bit 353 写入 6-bit opcode(并在 bit 347 写入 Source
SparseCoreTecVectorStoreTileSpmemStore*Opcode::Matches定义矩阵 opcode 值的 33 个 per-op predicate
SparseCoreTecVectorLoad* (0x1ecb9a00+)load counterpart;共享 fetch-and-add 返回所经的 Dest mux(word 0x28 bit 52)
SparseCoreTecVectorExtended*::VstSource (0x1eca7d80 gfc)fused store-source field,bit position 与 Source 完全相同
SparseCoreStream SCATTER_FLOAT_ADDon-tile …Add{dt} 所镜像的 cross-HBM atomic accumulate

Cross-References

  • TEC (Vector) Engine — 负责 64-byte bundle、VectorStore slot base(@328)与 opcode bit(@353),以及 encoder-dispatch model。
  • VectorLoad Slot — load 侧镜像;共享 Dest mux 与 address-mode lattice(plain / CB / PostUpdate / Indexed)。
  • VectorExtended (VEX) — 通过共享 VstSource field 馈送本 slot 的 scan/sort/reduce slot;embedding pipeline 的 reduce stage。
  • TEC Vector Opcode EnumerationVectorAlu opcode roster 与本页复用的 opcode-recovery model;VectorResult XRF-drain slot。
  • Stream Gather/Scatter — on-tile scatter-add 所镜像的 cross-HBM SCATTER_FLOAT_ADD atomic;embedding pipeline 的 gather stage。
  • CBREGCbreg selector 所索引的 16-CBREG circular-buffer register triple;CB store mode 继承的 wrap arithmetic。
  • Dedup Multiplicity — precedes scatter-add 的 Sort→Uniquify→DuplicateCount 路径,使 fetch-and-add ordering 无关紧要。
  • SparseCore Overview — 三类 SC engine、per-gen presence,以及 TEC vector slot 所在位置。
  • Binary: extracted/libtpu-0.0.40-cp314-cp314-manylinux_2_31_x86_64/libtpu/libtpu.so(build-id 89edbbe81c5b328a958fe628a9f2207d
  • Index entry: Part IX — SparseCore & BarnaCore / SparseCore ISA — back to index