Skip to content

Ghostlite 束

本页中的每个偏移、数值和地址都按字节精确读取自 libtpu-0.0.40-cp314 wheel 中的 libtpu.so(BuildID md5 89edbbe81c5b328a958fe628a9f2207d)。其他版本会有所不同。

摘要

Ghostlite(TpuVersion::kGhostlite = 4,外部名称 "TPU v6 lite" / v6e)是此构建中第二新的 TensorCore 代际,也是 GXC family具名的一半。它的 ISA 位于 asic_sw::deepsea::gxc::glc(通用加载核)子命名空间,并且与其 6acc60406 / gfc 兄弟不同,它的每一层都具有完整的符号名:一个 TpuCodecGhostlite 编解码器(CreateTpuCodecGhostlite @ 0x1e83bce0,vtable 0x21d35c00)、一个 GhostliteCodecMetadata、具名的 ghostlite::isa::EncoderGl{TensorCore,SparseCoreScs,SparseCoreTac,SparseCoreTec} worker、一个 GlcCycleTable 成本模型,以及专用的 GetGhostliteInstruction opcode→cost-row 重映射。

Ghostlite TensorCore 束是一个 64 字节(512 位)VLIW 发射字,宽度与 Viperfish6acc60406 相同,这由 GhostliteCodecMetadata::BundleSizeBytes @ 0x1eeb7640 返回 0x40 以及 EncoderGlTensorCore::BundleSizeBytes @ 0x1d332540 确认。使它成为独立线格式的并不是宽度,而是槽位位布局:相对于 Viperfish,Ghostlite 将每个 opcode 字段从 7 位扩宽到 8 位,并将 TensorCore 标量/定序器/立即数区域在缓冲区中统一向高位移动 +3 位;相对于 6acc60406,它保留每槽 4+1 位谓词(没有专用双谓词槽),并保留完整的 8-dtype MXU(四种浮点 + 四种整数),而 gfc 去掉了整数。本页以可重新实现的精度记录 glc 布局:带绝对字节/位偏移的完整槽位图、它与 Viperfish 的差异(GetGhostliteInstruction opcode→GhPerf 行重映射、GL 专用 iar 类跳转表分支、MXU 收缩深度输入),以及 GL 专用的 EmitX/EncodeGl* 模板。

与每个 V5+ 代际一样,Ghostlite 束字节完全由 proto-bundle <Slot>Encoder::Encode 编解码器产生,默认 LLVM-MC InstBits 表对这一代全为零。每个编码器读取其类型化的 glc::isa proto 子消息,并调用通用位打包器 BitCopy(dst, dst_bit, src, src_bit, nbits) @ 0x1fa0a900,将每个字段放在 64 字节缓冲区中的固定绝对位。调度器 EncoderGlTensorCore::EncodeBundle @ 0x1d331d00 按模板实参顺序遍历各槽编码器;glc 命名空间中的编码器集合就是该代际有效的 kIsaTable。关于模型背景(什么是束、无 scoreboard 的 VLIW 契约、空槽 kNeverExecute 约定),见 束模型

对于重新实现,契约是:

  • 64 字节宽度,以及它通过具名 TpuCodecGhostlite 编解码器(TpuCodec::Create 的 case 4)选择,并带有具名 GhostliteCodecMetadata 和具名 EncoderGl* worker。
  • glc 槽位偏移:每个功能槽都是 512 位缓冲区中的连续位窗口,由 BitCopy 从类型化 proto 子消息填充,在槽位高端带有每槽 4 位谓词寄存器索引 + 1 位反转,其下方是 opcode 判别符。
  • 与 Viperfish 的两个差异:(1)MXU 和 VALU 槽中的 opcode 字段从 7 位扩宽到 8 位;(2)TensorCore 标量/定序器/立即数区域位于高 +3 位处(例如 TC 分支偏移在 bit 433,而不是 Viperfish 的 430)。
  • 与 6acc60406 的两个差异:(1)Ghostlite 保留每槽 4+1 位谓词(没有 TensorCorePredicates 双谓词槽);(2)Ghostlite 保留8-dtype 整数+浮点 MXU,以及专用的 PopAddMxu01Result 融合累加结果操作。
  • 解码侧反向过程:glc::isa::...Decoder::Decode 通过逐字段 GetConcatenatedValue 访问器和逐 dtype 的 Opcode::Matches 掩码谓词读回字节。
TpuVersionkGhostlite = 4(外部 "TPU v6 lite" / v6e);见 代号矩阵
子核 ISAasic_sw::deepsea::gxc::glc::isa(通用加载核);见 GXC 家族
束宽度64 B / 512 bitGhostliteCodecMetadata::BundleSizeBytes @ 0x1eeb7640 return 0x40
编解码器具名TpuCodecGhostlite(vtable 0x21d35c00);CreateTpuCodecGhostlite @ 0x1e83bce0
编码调度器EncoderGlTensorCore::EncodeBundle @ 0x1d331d00TpuCodecGhostlite::EncodeBundle @ 0x1e83c780
位打包器BitCopy(dst, dst_bit, src, src_bit, nbits) @ 0x1fa0a900(LSB-first,按位粒度)
成本重映射GetGhostliteInstruction @ 0x1c8b1740(LloOpcode → GhPerf::Instruction);GlcCycleTable @ 0x1c89e7e0
MXU dtype 集{F32, If8, Bf16, Bf8}(浮点)+ {U8, S8, U4, S4}(整数)— 共 8 种
谓词模型每槽 4 位寄存器索引 + 1 位反转(无专用谓词槽)

具名编解码器和 EncoderGl* Worker

Ghostlite 是此构建中最后一个被实体化为完整具名 C++ 编解码器的代际。TpuCodec::Create0x1e835fa0)是一个 switch(TpuVersion),其 case 4 调用解混淆后的 CreateTpuCodecGhostlite0x1e83bce0),安装具名 vtable tpu::TpuCodecGhostlite @ 0x21d35c00。(它的 gfc 兄弟,即 case 5,是唯一的匿名编解码器;见 6acc60406 束。)

TpuCodecGhostlite::EncodeBundle0x1e83c780)按 TpuSequencerType 分派到四个具名编码器 worker 之一,它们都在 ghostlite::isa 命名空间中,并且都绑定到 gxc::glc::isa proto 类型:

text
ghostlite::isa::EncoderGlTensorCore      @ 0x1d331d00   (EncodeBundle)   ; TensorCore sequencer
ghostlite::isa::EncoderGlSparseCoreScs                                    ; SparseCore scalar sub-bundle
ghostlite::isa::EncoderGlSparseCoreTac                                    ; SparseCore tile-access core
ghostlite::isa::EncoderGlSparseCoreTec                                    ; SparseCore tensor-engine core
```text

`EncodeProgram<ghostlite::isa::EncoderGlTensorCore, gxc::glc::isa::TensorCoreProgram>` 实例化(`0x1e83cca0`)证明了这种绑定:`EncoderGl*` 模板名携带代号(`Gl`),但它的 proto 实参是 `asic_sw::deepsea::gxc::glc::isa::TensorCoreProgram`,即*加载*核 ISA。单个工厂 `CreateEncoderGlGf`(`0x1e831020`)从共享的 `TpuSequencerProgramProto` 构造 Ghostlite 和 6acc60406 定序器编码器;`glc` 与 `gfc` 的拆分体现在模板实参中,而不是叶子层。

> **注意 — `glc` 是 Ghostlite 子核,不是 6acc60406 的子核。** 一个命名陷阱:`glc` 看起来与 `gfc` 相邻,但 [GXC 家族](../targets/gxc-family.md) 明确给出 **Ghostlite (v4) = `glc`**(通用加载核)以及 **6acc60406 (v5) = `gfc`**(通用取指核)。本页中每个 `glc::*` 符号都属于 Ghostlite 代际。该代际的外部名称是 **"TPU v6 lite"**(v6e);不要把 `glc` 理解为 "TPU7x" — 那是 `gfc` / 6acc60406 代际。

宽度被两处字节锚定。TensorCore 定序器的 `GhostliteCodecMetadata::BundleSizeBytes` @ `0x1eeb7640` 是一个两指令叶函数:

```text
0x1eeb7644:  mov eax, 0x40      ; 64
0x1eeb7649:  ret

EncoderGlTensorCore::BundleSizeBytes @ 0x1d332540 通过其 codec-metadata 指针返回同样的 64。因此 Ghostlite TensorCore 束是 64 字节,这确认了 束模型 的说法:v5e / v6e / v7x 都共享 64 字节发射字,只在槽位布局上不同。


编码路径

编码路径是通用的两阶段 V5+ 链:

text
LLO op ──(EmitX, proto population)──▶ glc proto sub-message (present-bit + fields)
glc proto sub-message ──(<Slot>Encoder::Encode, BitCopy)──▶ absolute bit window in 64-B buffer
```text

`EncoderGlTensorCore::EncodeBundle` @ `0x1d331d00` 是调度器:它按模板实参顺序对共享 64 字节缓冲区调用每个槽的 `glc::isa::...Encoder::Encode`。每次字段写入都是一次 `BitCopy(buffer, dst_bit, &field, 0, width)` 调用,目标为 `0x1fa0a900` — 按位粒度、**LSB-first**(bit 0 是 byte 0 的最低有效位,这是 [束模型](bundle-model-overview.md#abstract) 中说明的通用 v5+ 约定;编码路径中没有任何 MSB-first 排列),其中 `dst_bit` 是束中的绝对位(byte = `dst_bit >> 3`,字节内位 = `dst_bit & 7`)。下表给出每个字段的 `(dst_bit, width)` 三元组,每项都由具名编码器中 `BitCopy` 调用之前的字面量 `mov esi,<dst_bit>` / `mov r8d,<width>` 立即数验证。

---

## 槽位图 — 绝对位偏移(64 字节 / 512 位缓冲区)

束划分为标准 V5+ 槽类。下表是合并后的 Ghostlite(`glc`)槽位图;bit 0 是 byte 0 的 LSB。每项都锚定到写入它的具名 `glc::isa::...Encoder::Encode` 以及固定偏移的 `BitCopy` 立即数。

| 槽位 / 字段 | dst_bit(十进制) | hex | 宽度 | 编码器(`glc::isa`)@ |
|---|---:|---|---:|---|
| **定序器**每槽 pred 寄存器索引 | 502 | 0x1f6 | 4 | `TensorCoreScalarAlu0Encoder::Encode` @ `0x1f219b40` |
| seq pred 反转 | 506 | 0x1fa | 1 | (same) |
| seq opcode-HIGH / family | 496 | 0x1f0 | 6 | (same; branch helpers @ `0x1f21da40`+) |
| seq opcode-LOW / discriminator | 491 | 0x1eb | 5 | (same) |
| **立即数**槽 0(branch/call/sync offset) | 433 | 0x1b1 | 20 | `TensorCoreImmediatesEncoder::Encode` @ `0x1f20d520` |
| imm 槽 1 | 413 | 0x19d | 20 | (same) |
| imm 槽 2 | 393 | 0x189 | 20 | (same) |
| imm 槽 3 | 373 | 0x175 | 20 | (same) |
| imm 槽 4 | 353 | 0x161 | 20 | (same) |
| imm 槽 5 | 333 | 0x14d | 20 | (same) |
| **VALU 槽 0** opcode | 302 | 0x12e | 7 | `TensorCoreVectorAlu0Encoder` |
| VALU0 predicate(4 位寄存器) | 309 | 0x135 | 4 | (same) |
| **MXU VEx0** opcode-HIGH | 58 | 0x3a | 8 | `TensorCoreVectorExtended0Encoder::Encode` @ `0x1f32fd00` |
| VEx0 data-format sub-disc | 52 | 0x34 | 4 | (same) |
| VEx0 MXU-id(单元) | 66 | 0x42 | 4 | (same) |
| VEx0 control(matpush 目标) | 49 | 0x31 | 3 | `…MatrixMultiplyBf16` @ `0x1f333ce0` |
| VEx0 done-gains / latch 标志 | 56 | 0x38 | 1 | (same) |
| VEx0 systolic 源 vreg #1(proto +0x20) | 160 | 0xa0 | 6 | (same) |
| VEx0 systolic 源 vregs #2..#8(proto +0x24..+0x3c) | 285/296/251/262/217/228/183 | — | 每个 6 | (same) |
| **EUP push**(VALU 槽 3)VALU-opcode | 200 | 0xc8 | 7 | `…VectorAlu3F32Tanh` @ `0x1f2f4f40`(family) |
| EUP 函数选择器 | 189 | 0xbd | 5 | (same) |
| EUP push 源 vreg | 194 | 0xc2 | 6 | (same) |
| **结果槽** result-type discriminator | 24 | 0x18 | 4 | `TensorCoreVectorResult0Encoder::Encode` @ `0x1f3bc160` |
| result 目标 vreg | 14 | 0x0e | 6 | (same) |

> **注意 — 八个 MXU source-vreg 偏移不是单调的。** 所有八个 MXU systolic source-vreg 字段(proto `+0x20..+0x3c`)都由 `MatrixMultiplyBf16` @ `0x1f333ce0` 写入,按 proto 字段顺序落在 bits **160 / 285 / 296 / 251 / 262 / 217 / 228 / 183**(每个 w6)— 这些偏移在缓冲区中是*非单调*的(160 然后跳到 285,再下降,最后字段 +0x3c 落在 183)。对应的 `gfc` 池记录在 [6acc60406 页面](bundle-gf.md#slot-map--absolute-bit-offsets-64-byte--512-bit-buffer)。

---

## 与 Viperfish 的差异 — `+3` 移位和 7→8 Opcode 扩宽

Ghostlite 在逐字段层面是一个经过两种系统变换的 Viperfish 束。二者都能在二进制中作为 `vxc` 与 `glc` 编码器之间的常量偏移看到。

### 变换 1 — TensorCore 标量/定序器/立即数区域上移 +3 位

TensorCore *标量*区域中的每个字段(定序器 opcode、谓词、立即数槽)在 Ghostlite 上都正好比 Viperfish 高 **+3 位**。这是统一且内部一致的:

| 字段 | Viperfish (`vxc`) | Ghostlite (`glc`) | Δ |
|---|---:|---:|---:|
| TC imm 槽 0(分支偏移) | bit 430 (0x1ae) | bit 433 (0x1b1) | +3 |
| TC imm 槽 1..5 | 410/390/370/350/330 | 413/393/373/353/333 | +3 |
| TC seq opcode-HIGH / family | bit 493 (0x1ed) | bit 496 (0x1f0) | +3 |
| TC seq opcode-LOW discriminator | bit 488 (0x1e8) | bit 491 (0x1eb) | +3 |
| TC seq predicate 寄存器索引 | bit 499 (0x1f3) | bit 502 (0x1f6) | +3 |
| TC seq predicate 反转 | bit 503 (0x1f7) | bit 506 (0x1fa) | +3 |

这些位置直接读取自 `glc::isa::TensorCoreScalarAlu0Encoder::Encode`(`0x1f219b40`)及其分支 helper `EncodeTensorCoreScalarAlu0BranchAbsolute`(`0x1f21da40`)。Ghostlite TC 标量区域统一位于 Viperfish 上方 **+3 位**,与 TC 立即数槽 +3(433 vs 430)匹配:整个 TC 标量/定序器/立即数块作为一个刚性窗口平移。SparseCore SCS 定序器*没有*移位 — 其中 `glc` 与 `vxc` 按字节相同(见下文)。

相比之下,**SparseCore SCS** 定序器在两代之间按字节相同,+3 移位是仅 TensorCore 有的现象:

```text
glc SparseCoreScalarAlu0Encoder::Encode @ 0x1e9d2140:
  predication reg index  -> bit 187 (0xbb) w4   ; = vxc
  predication inversion  -> bit 191 (0xbf) w1   ; = vxc
  opcode-HIGH / family   -> bit 181 (0xb5) w6   ; = vxc
  opcode-LOW disc        -> bit 176 (0xb0) w5   ; = vxc
glc SCS imm slot 0 (branch offset) -> bit 67 (0x43) w20   ; = vxc (SparseCoreImmediatesEncoder @ 0x1eb563c0)

变换 2 — opcode 字段从 7 位扩宽到 8 位

MXU 和 VALU opcode 字段在 Ghostlite 上增加一位。Viperfish MXU VectorExtended opcode 是 bit 57 处的 7 位字段;Ghostlite 的是 bit 58 处的 8 位字段。这对应同一代际对之间 VALU 槽 opcode 的扩宽(Viperfish VALU0 opcode 为 bit 299 处 7 位;Ghostlite 为 bit 302 处 7 位 — 注意 VALU0 opcode 在 glc 上仍保持 7 位,只在 gfc 上变为 8 位)。

MXU VectorExtended 字段Viperfish (vxc)Ghostlite (glc)
opcode-HIGHbit 57 w7bit 58 w8
data-format sub-discbit 51 w4bit 52 w4
MXU-id(单元)bit 64 w4bit 66 w4
opcode 边界(cmp0x66(103 ops)0x70(113 ops)

更宽的 opcode 和更大的跳转表边界(113 vs 103)就是 Ghostlite 的 MXU 槽在相同 64 字节字中编码额外操作的方式。


GetGhostliteInstruction Opcode→行重映射(成本模型)

Ghostlite 是此构建中唯一带有具名专用 LloOpcode→成本行转换器的代际:xla::ghostlite::(anonymous namespace)::GetGhostliteInstruction @ 0x1c8b1740。它将 LloOpcode(0..0x1cc)映射到 GhPerf::Instruction 索引(0..0x1db)— 一个独立且更稠密的枚举,GlcCycleTable 成本网格以它为索引。这就是 LLO opcode 不是成本表行的原因。

反编译后的机制:

text
GetGhostliteInstruction(LloValue*)  @ 0x1c8b1740:
  1. opcode = WORD[value]                                       ; movzx ecx,WORD[rbx]
  2. binary search a SORTED 258-entry table @ 0x4067dc8         ; mov edi,0x102 (=258)
     (key = LloOpcode WORD, value = GhPerf::Instruction WORD)   ; lower_bound; on hit, return value
  3. miss -> lea edx,[opcode-1]; cmp edx,0xa5; jump table @ 0xb43b34c (166 entries)
       data-format / mode-dependent arms compute the row from a secondary key:
         Latch* opcodes   -> LloInstruction::latch_mode()        @ 0x1d4e7500
         Matmul* opcodes  -> LloInstruction::matmul_data_format() @ 0x1d4e8440
         Transpose 0xa6   -> LloInstruction::vxpose_mode()        @ 0x1d4e7440 (2nd jt @ 0xb43b5e4)
         iar-class ops    -> LloInstruction::iar()                @ 0x1d4e7120   (FIVE arms)
  4. any opcode neither in the table nor a special arm -> absl::LogMessageFatal (latency_table_gl.cc:761)
```text

`kLloOpcodeToGlcInstruction` 二分查找表 @ `0x4067dc8`(258 项,锚定于 [GXC 家族](../targets/gxc-family.md#compiler-target-and-cost-model-binding))是字面 LloOpcode→GhPerf 映射;该重映射覆盖有效 Ghostlite opcode 集上的所有情况,否则中止。

### GL 专用 iar 类跳转表分支

该重映射中最具 Ghostlite 特征的方面是 **iar 类**(index-address-register)处理。`0xb43b34c` 跳转表中五个不同分支用于 iar 类 LLO opcode,它们通过 `LloInstruction::iar()` @ `0x1d4e7120` 根据指令的 IAR 操作数计算 GhPerf 行,而不是只根据 opcode。`glc::isa` 操作数变体集确认 IAR 操作数类是 Ghostlite 标量槽的一等字段:`FormatSlot<glc::isa::TensorCoreScalarAlu>` 助记符变体携带 `IarNumber` strong-int alternative,与 `Sreg`/`Vreg`/`Preg` 并列。matmul/latch/transpose 分支以 `matmul_data_format` / `latch_mode` / `vxpose_mode` 为键,这些也是 MXU 延迟表使用的同一组修饰键,因此成本行选择和 MXU 保留都以数据格式为枢轴。

> **注意 — 共享 GhPerf 行。** 重映射会把多个 LloOpcode 折叠到一个 GhPerf 行:例如全部 14 个 HBM-DMA opcode 映射到一行,全部 14 个 VMEM/SMEM-DMA opcode 映射到另一行,因此成本模型用单个网格行给整个 DMA 方向族定价。`GhPerf::Instruction` 枚举在 Ghostlite 和 6acc60406 之间代际不变;每代差异只在网格行数(Ghostlite 为 476)。默认延迟哨兵是 `0xffffffff` = −1(有符号),在 `LatencyBetween` 的 signed-max 中被结构性支配,因此永远不会作为成本浮现。完整成本模型细节见 [MXU 延迟:GL](../cost/mxu-latency-gl.md)。

---

## MXU 槽 — 8 种 Dtype 和收缩深度输入

Ghostlite MXU 槽由两个 `VectorExtended` 槽(VEx0、VEx1)组成,每个物理 MXU 一个,分别是通过槽编码器跳转表分派到逐操作 helper 的 `BitCopy` 打包字段。该槽编码密集 matmul 步骤、移动操作数 push(matpush)以及权重 latch。

### Dtype 集:浮点 + 整数(共 8 种)

Ghostlite 支持**八种** matmul/push dtype,`PushMatrix*` helper 名册的符号统计是决定性证据:

| 代际 | PushMatrix / MatrixMultiply dtype 集 |
|---|---|
| **Ghostlite (`glc`)** | `F32`, `If8`, `Bf16`, `Bf8`(浮点)+ `U8`, `S8`, `U4`, `S4`(整数)— **8** |
| 6acc60406 (`gfc`) | `F32`, `E4m3`, `Bf16`, `E5m2`(4,只有浮点) |

Ghostlite 将其两种 FP8 格式命名为 `If8` / `Bf8`(相对于 6acc60406 明确的 `E4m3` / `E5m2`),并且关键的是,它保留了 `gfc` 完全去掉的四种整数 matmul dtype。解码侧把 dtype 读作 4 元素类别内的 2 位子序号 `@ bit 54`,类别由 bit 60 处的 latch opcode 选择(14 = 浮点类别 `{F32=0, If8=1, Bf16=2, Bf8=3}`,15 = 整数类别 `{U8=0, S8=1, U4=2, S4=3}`)。

### MXU 槽位图

```text
glc MatrixMultiplyBf16 @ 0x1f333ce0 (VEx0):
  opcode-HIGH (literal 0x1)  -> bit 58 (0x3a) w8   ; BitCopy(buf, 58, &1, 0, 8)
  data-format (literal 0x1)  -> bit 52 (0x34) w4   ; bf16 = 1 (push-format enum)
  control (matpush target)   -> bit 49 (0x31) w3
  done-gains / latch flag    -> bit 56 (0x38) w1
  MXU-id (unit)              -> bit 66 (0x42) w4   ; written by VectorExtended0Encoder
                                                   ;   dispatcher @ 0x1f32fd00, not the leaf
  8 systolic src vregs       -> bits 160/285/296/251/262/217/228/183 (w6 each)
    (proto +0x20..+0x3c, in proto-field order; offsets non-monotone in the buffer)

MXU 使用一个 8-vreg systolic 操作数输入(proto +0x20..+0x3c 源 vreg 字段,全为 6 位),由两个 MXU 共享 — 这就是收缩深度输入:256×256 systolic array 每周期从共享向量读端口输入一个操作数列,八个源 vreg 字段把收缩维度流入阵列。权重 latch 是 LoadMatrixRegister{Gmr,Lmr}{Msra,Msrb}[Bf16Conversion] opcode 族(LoadMatrixRegisterGmrMsra @ 0x1f33f140,opcode-HIGH @ bit 58 w8 — 与 matmul 相同的统一 8 位 opcode 区域,4 位子判别符 @ bit 52);移动操作数 push 是 PushMatrix<fmt>[Masked]PushMatrixBf16 @ 0x1f33fe00,opcode-HIGH 0xe=14 @ bit 60 w6,sub @ bit 58 w2,dtype @ bit 54 w2,3 位 MatpushTarget MSRA/MSRB 控制)。K>128 多轮累加在 Ghostlite 上有专用结果 op(下文 PopAddMxu01Result),而不是单独的 VaddF32


结果槽和 PopAddMxu01Result

结果槽(TensorCoreVectorResult0Encoder::Encode @ 0x1f3bc160)将 MXU 结果 FIFO 和 EUP 超越函数 FIFO 读入 vreg。Ghostlite 保持 Viperfish 形状的结果槽偏移(没有 gfc 下移),并携带一个 6acc60406 缺少的结果子消息:

text
glc TensorCoreVectorResult0Encoder::Encode @ 0x1f3bc160:
  result-type discriminator -> bit 24 (0x18) w4   ; always written (proto +0x1c)
  dest vreg                 -> bit 14 (0x0e) w6
  switch on proto oneof tag (a2+0x50); cmp bound 0x8 (cases 0,5,6,7,8):
    tag 5 = PopEupResult        -> writes sub-disc 0 @ bit 20 w4
    tag 6 = PopMxuResult        -> writes sub-disc 2 @ bit 21 w3 (matres pop)
    tag 7 = PopAddMxu01Result   -> writes sub-disc 1 @ bit 20 w4 (GL-only fused accumulate)
    tag 8 = TransposeResult     -> writes sub-disc 4 @ bit 21 w3
```text

| 结果槽轴 | Viperfish (`vxc`) | Ghostlite (`glc`) | 6acc60406 (`gfc`) |
|---|---:|---:|---:|
| result-type discriminator | bit 24 w4 | bit 24 w4 | bit 20 w2 |
| 目标 vreg | bit 14 w6 | bit 14 w6 | bit 11 w6 |
| result-opcode 边界 | 0x8 (9) | 0x8 (9) | 0x7 (8) |
| 融合累加 op | `PopCcrfResult`(标量) | **`PopAddMxu01Result`** | (none) |

上面的 tag→op 配对读取自 `TensorCoreVectorResult0Encoder::Encode`(`0x1f3bc160`):`switch` 作用于 `a2+0x50` 处的 proto oneof tag,而每个分支引用的 default-instance global 固定了 op(tag 5 → `PopEupResult`,tag 6 → `PopMxuResult`,tag 7 → `PopAddMxu01Result`,tag 8 → `TransposeResult`)。融合累加 `PopAddMxu01Result`(tag 7)仅属于 GL。

`PopAddMxu01Result`(在 `glc::isa` 命名空间中引用为 `TensorCoreVectorResult_PopAddMxu01Result_globals_`,即 tag-7 分支回退到的 proto default-instance)是多轮(K>128)matmul 路径的结果内 matres-add 累加,是 Ghostlite 专用融合。Viperfish 使用标量 `PopCcrfResult`,6acc60406 使用单独的 VALU `VaddF32`,而 Ghostlite 将累加折叠到结果 pop 本身。

---

## EUP / 超越函数 Push(VALU 槽 3)

超越函数 push 是 VALU **槽 3** op(`Alu3`),不是 MXU op — 单发射 XLU 只从 VALU 槽 3 取源。Ghostlite 携带完整的超越函数名册:`glc::isa` 有 `F32`/`Bf16` × `{Tanh, Erf, Sinq, Cosq, Reciprocal, ReciprocalSqrt, …}` 的具名 `Alu3` helper,以及一个通用 `EupPush`(`0x1f2f5180`)。

```text
glc EncodeTensorCoreVectorAlu3F32Tanh @ 0x1f2f4f40:
  VALU opcode (EUP-push family) -> bit 200 (0xc8) w7   ; mov esi,0xc8 ; mov r8d,0x7
  EUP function selector         -> bit 189 (0xbd) w5   ; mov esi,0xbd ; mov r8d,0x5
  EUP push src vreg             -> bit 194 (0xc2) w6   ; mov esi,0xc2 ; mov r8d,0x6

注意 — Ghostlite 的 VALU opcode 是 7 位(与 Viperfish 相同);只有 6acc60406 将其扩宽到 8 位。因此 Ghostlite EUP-push 字段位于 6acc60406 偏移上方 +6 位:VALU-opcode @ bit 200 w7(对比 gfc bit 194 w8)、函数选择器 @ bit 189 w5(对比 183)、源 vreg @ bit 194 w6(对比 188),依据 glc::isa::…VectorAlu3F32Tanh0x1f2f4f40)。

5 位函数选择器值(F32Tanh0x13)在编码时来自函数 helper 的静态 proto default-instance(例如 TensorCoreVectorAlu_F32Tanh_globals_ @ 0x2243f290),而不是 helper 中的字面量,因此逐函数选择器值携带与代际不变 GhPerf 超越函数集相同的枚举:

函数F32 选择器Bf16 选择器
Erf0x0e (14)0x0f (15)
ReciprocalSqrt0x10 (16)0x0c (12)
PowTwo (2^x)0x11 (17)0x19 (25)
LogTwo (log2)0x12 (18)0x1a (26)
Tanh0x13 (19)0x1b (27)
ShiftedSigmoid0x14 (20)0x1c (28)
Reciprocal0x15 (21)0x1d (29)
Sinq (sin)0x17 (23)0x1e (30)
Cosq (cos)0x18 (24)0x1f (31)

push-pop 协议:束 N 发射带函数选择器的 VALU3 op;束 N+k 发射结果槽 PopEupResult(opcode 7),目标 vreg 位于 bit 14。逐函数选择器值读取自 .data globals,它们的逐函数序号遵循代际不变的 GhPerf 超越函数枚举,而不是逐 helper 字面量。


GL 专用的 EmitX 模板

编码链的第 1 阶段,即 proto 填充,通过 EmitX 模板族运行。GL 专用实例化绑定到 gxc::glc::isa proto 类型,并在对应的 EncodeGl* 槽编码器用 BitCopy 写入字段之前设置 present bit:

  • EmitBranchOp / EmitCallOp — signed-20-bit 范围检查(lea 0x80000(%rsi); cmp 0x100000; jae fail),设置 scalar-ALU present bit,通过 EmitImmediate 将偏移写入立即数槽 0。glc TC 分支 helper(EncodeTensorCoreScalarAlu0BranchAbsolute @ 0x1f21da40BranchRelative @ 0x1f21daa0CallAbsolute @ 0x1f21db80BranchSreg @ 0x1f21db00)在 opcode-LOW bit 491 w5 处写判别符(4 = BranchAbsolute,5 = BranchRelative,6 = CallAbsolute,7 = CallRelative),并在 bit 496 w6 处写 opcode-HIGH 0。
  • EmitImmediate<TensorCoreImmediates> — 对槽索引(0..5)执行跳转表分派并将值写入逐槽 proto 字段;随后 glc TensorCoreImmediatesEncoder::Encode @ 0x1f20d520 将每个字段 BitCopy 到其束位(槽 0 @ 433,槽 1..5 @ 413/393/373/353/333,均为 w20)。
  • EmitPredicationToSlot<…glc::isa::TensorCoreScalarAlu> — 将谓词方向 + 寄存器号写入槽 proto;槽编码器在 TC 定序器上将 4 位寄存器索引 BitCopy 到 bit 502,将 1 位反转写到 bit 506(或在 SCS 定序器上写到 187 / 191)。
  • EncodeProgram<EncoderGlTensorCore, glc::isa::TensorCoreProgram> @ 0x1e83cca0 — 程序级 driver,遍历每个束并调用 EncoderGlTensorCore::EncodeBundle

判别符值映射(与所有 V5+ 代际共享):

Op
4BranchAbsolute
5BranchRelative
6CallAbsolute
7CallRelative

任何 V5+ 代际都没有束内 delay-slot 字段;分支 delay-slot 计数是束打包器的填充计数(分支后附加的空束),不是编码槽位。硬件循环同样不是编码字段 — 它是在定序器 opcode 处读取 LCC 寄存器,从而驱动条件 BranchRelative


示例 — Ghostlite 束中的 bf16 vmatmul + vtanh.f32

在新 512 位缓冲区中编码 MXU 0 上的 bf16 matmul(VectorExtended 槽 0,非谓词化)和一个 tanh.f32 超越函数:

text
EncoderGlTensorCore::EncodeBundle @ 0x1d331d00 walks each slot encoder.

VectorExtended0Encoder::Encode (the MatrixMultiplyBf16 helper @ 0x1f333ce0):
  MXU-id (0)            -> bit 66 (w4)
  opcode-HIGH (0x1)     -> bit 58 (w8)
  data-format (bf16=1)  -> bit 52 (w4)
  control               -> bit 49 (w3) ; done-gains -> bit 56 (w1)
  8 systolic src vregs  -> bits 160/285/296/251/262/217/228/183 (w6 each)

VectorResult0Encoder::Encode (PopMxuResult, result-opcode 6):
  result-type disc      -> bit 24 (w4)
  dest vreg             -> bit 14 (w6)

VectorAlu3 F32Tanh (EUP push @ 0x1f2f4f40):
  VALU-opcode (EUP)      -> bit 200 (w7)
  function selector (0x13)-> bit 189 (w5)
  push src vreg          -> bit 194 (w6)
  ... one+ bundles later: PopEupResult (result-opcode 7), dest vreg -> bit 14 (w6)
```text

空槽保持在填充任何槽之前写入束头的 `kNeverExecute` 谓词戳(见 [束模型](bundle-model-overview.md#empty-slot-and-nop-convention));已填充槽的 4 位谓词寄存器索引用真实 `PredicationSlot` 覆盖默认值。

---

## 交叉引用

- [Viperfish 64B 束](bundle-vf-64b.md) — 本页比较的 `vxc`(v5e)兄弟:7 位 MXU opcode,TC 标量区域低 3 位(分支偏移在 430),使用 `PopCcrfResult` 而不是 `PopAddMxu01Result`。
- [6acc60406 束](bundle-gf.md) — `gfc`(v5 / TPU7x)兄弟:匿名编解码器、8 位 VALU opcode、专用双谓词槽、只有浮点的 4-dtype MXU、结果槽位于 bits 11/20。
- [束模型](bundle-model-overview.md) — VLIW 发射字模型、64 字节宽度家族、空槽 `kNeverExecute` 约定。
- [GXC 家族](../targets/gxc-family.md) — 为什么 Ghostlite = `glc`(通用加载核)、具名编解码器/`EncoderGl*` 名册,以及 `GetGhostliteInstruction` / `GlcCycleTable` 编译器绑定。
- [MXU 延迟:GL](../cost/mxu-latency-gl.md) — `GlcCycleTable` 逐格式 MXU 延迟/保留矩阵,以及 `GetGhostliteInstruction` 重映射馈入的 `GhPerf::Instruction` 成本网格。