V5+ EmitX 绝对位位置
本页所有地址均适用于
libtpu-0.0.40-cp314wheel 中的libtpu.so(libtpu-0.0.40-cp314-cp314-manylinux_2_31_x86_64/libtpu/libtpu.so,BuildID89edbbe81c5b328a958fe628a9f2207d,781,691,048 B,未 strip,.textVA == 文件偏移)。其他构建会不同。
摘要
Jellyfish(v2)和 Pufferfish(v4)用单个整体式编码器构造 bundle,即 EncoderJf::EncodeBundleInternal(0x1e86c7c0)和 EncoderPfTensorCore::EncodeBundleInternal(0x1e8c5c40);它们接收一个 Bundle 对象并内联打包每个槽。本构建中的每个 V5+ 代(Viperfish/vxc+vfc、Ghostlite/glc、6acc60406/gfc)都完全放弃了该模型。任何 V5+ codec 都不存在 EncodeBundleInternal。bundle 改由两阶段链路生成:上游由 xla::tpu::sparse_core::isa_emitter::EmitX proto-template 填充带类型的 proto 子消息并设置 present bit;下游由逐槽 <Slot>Encoder::Encode codec 读取该 proto,并通过一个通用的按位打包器 BitCopy(dst, dst_bit, src, src_bit, nbits)(0x1fa0a900)把每个字段写到扁平 bundle 字节缓冲区中的固定绝对位位置。本页汇总 sequencer、immediate 和 predicate 槽的这些绝对位位置;各代 bundle 页面会把这些内容委托到本页。
结构性后果是:LLVM-MC InstBits 表在标准 LLVM 后端中保存每条指令的固定 opcode 位,而在每个 V5+ 代中它在磁盘上全为零。静态表中没有固定指令位;整个 bundle 布局是一张扁平的 (absolute-bit, width) 三元组列表,分布在约两百个逐 op 的 BitCopy helper 中,并由单个 EncodeBundle dispatcher 编排。每槽 BitCopy 偏移集合就是该代实际的 kIsaTable。重新实现者若寻找静态 InstBits 数组,或寻找 EncoderVf::EncodeBundleInternal,都不会找到。
本页按两个编码阶段组织,然后按槽组织。开头的 BitCopy 和 EmitImmediate 小节确立基本原语及其 proto-field 约定;immediate、sequencer 和 predicate 小节给出各代的绝对 (dst_bit, width) 映射;MXU/result/EUP 小节汇总 compute-slot 位置;最后的逐 (slot, gen) 表是 Viperfish、Ghostlite 和 6acc60406 bundle 页面引用 deferred 字段时使用的单一参考。
对重新实现而言,契约如下:
- 两阶段链路:
EmitXproto 填充(阶段 1)→<Slot>Encoder::EncodeBitCopy(阶段 2)。没有整体式EncodeBundleInternal。 BitCopy(dst, dst_bit, src, src_bit, nbits)调用约定,以及位精确、LSB-first 语义。EmitImmediateproto 槽映射(一个值落入 6 个 immediate 槽中的哪一个,以及它的 present bit)。- 对 32 字节 SCS bundle 和 64 字节 TC bundle,逐代给出 sequencer(branch/call/LCC)判别符、dest/x-target sreg 和 predication 字段的绝对 (dst_bit, width)。
- 每代绝对位差异:Viperfish 基线 → Ghostlite TC +3 位平移 → 6acc60406(自己的布局,专用双 predicate 槽,2 位逐槽选择器)。
| 通用打包器 | BitCopy(void* dst, int dst_bit, const void* src, int src_bit, int nbits) @ 0x1fa0a900(mangled _Z7BitCopyPviPKvii) |
| 调用约定 | dst=rdi,dst_bit=esi,src=rdx,src_bit=ecx,nbits=r8d(System V);按位粒度,LSB-first |
| 阶段 1 发射器命名空间 | xla::tpu::sparse_core::isa_emitter::EmitX<…>(EmitImmediate、EmitBranchOp、EmitCallOp、EmitPredicationToSlot) |
| 阶段 2 codec 命名空间 | asic_sw::deepsea::{vxc,vxc::vfc,gxc::glc,gxc::gfc}::isa::<Slot>Encoder::Encode |
| 编排器 | EncodeBundle 0x1e838cc0(6acc60406 codec;TC worker 0x1d371540),EncoderGlTensorCore::EncodeBundle 0x1d331d00(Ghostlite) |
| SCS bundle | 32 B / 256 bit;branch/call offset(imm slot 0)位于 bit 67,所有 V5+ 代相同 |
| TC bundle | 64 B / 512 bit;branch/call offset(imm slot 0)位于 bit 430(vxc)/ 433(glc)/ 423(gfc) |
InstBits 表 | 0x3366d90,对每个 V5+ 代均全零,无重定位 |
两阶段编码链路
目的
把指令含义(带类型的 proto 子消息,与代无关)和位放在哪里(逐代 BitCopy 偏移映射)分离。阶段 1 在前半发射器中运行,为每个占用槽产生带已填充子消息的 *Bundle proto。阶段 2 在 codec 中运行,把该 proto 序列化为 wire bundle。这个拆分解释了为什么同一个 LLO op 在 Viperfish、Ghostlite 和 6acc60406 上会编码成三种不同位布局,而前端发射器逻辑无需改变,只有 codec 的偏移字面量不同。
入口点
LLO MCInst
└─ isa_emitter::EmitX<Slot, OpKind> ── Stage 1: populate proto sub-message
│ sets present bit, writes operand fields
▼
<gen> proto bundle (SparseCoreScsBundle / TensorCoreBundle / …)
│
EncodeBundle 0x1e838cc0 (dispatch on TpuSequencerType)
├─ case 0 → TensorCoreCodecBase<…> → TC worker 0x1d371540
├─ case 3 → SparseCoreScsCodecBase<…> → EncoderBase::EncodeBundle
└─ case 5 → SparseCoreTecCodecBase<…> → EncoderBase::EncodeBundle
│ walk per-slot Encoders in template-arg order
▼
<Slot>Encoder::Encode ── Stage 2: BitCopy fields → bundle bytes
└─ BitCopy(buf, dst_bit, &field, 0, width) 0x1fa0a900
```text
### 算法
阶段 1 的 immediate 填充由 demangled 的 `isa_emitter::EmitImmediate<glc::isa::SparseCoreImmediates>` 函数体(`0x139f7060`)确认:
```c
function EmitImmediate(slot_index, value, immediates_msg): // 0x139f7060
if value >= 0x100000: // llvm::isUInt<20> RET_CHECK
return Error("isa_emitter_base.h:587") // (signed 20-bit offsets are pre-masked)
switch slot_index: // jump on slot 0..5
case 0: field = msg+0x18; present = 0x01; break // imm_0()
case 1: field = msg+0x1c; present = 0x02; break // imm_1()
case 2: field = msg+0x20; present = 0x04; break // imm_2()
case 3: field = msg+0x24; present = 0x08; break // imm_3()
case 4: field = msg+0x28; present = 0x10; break // imm_4()
case 5: field = msg+0x2c; present = 0x20; break // imm_5()
default: return Error("Invalid immediate: <n>")
if (msg+0x10 & present) && *field != value: // RET_CHECK: re-set must match
return Error("imm_N() == value")
*field = value
msg+0x10 |= present // set present bit at msg+0x10
return Ok阶段 2 中,逐槽编码器读取每个已填充的子消息,并发出一串 BitCopy 调用。编码器主体是在 proto opcode 判别符上的 switch,该判别符在 Viperfish/Ghostlite 标量编码器和 gfc TC sequencer 中位于 proto+0x50,在 gfc SCS sequencer 和 gfc predicates 编码器中位于 proto+0x58(gfc proto 有更宽的 header);每个 arm 是一个 op 家族的字段布局。通用形状(来自 immediates 编码器)如下:
function <Slot>Encoder::Encode(this, proto, out_buf):
scratch[0] = proto.imm_0 // stage value into 8-byte scratch
BitCopy(out_buf, ABS_BIT_0, scratch, 0, WIDTH_0) // place WIDTH_0 bits at ABS_BIT_0
scratch[0] = proto.imm_1
BitCopy(out_buf, ABS_BIT_1, scratch, 0, WIDTH_1)
... // one BitCopy per field
return Ok
```text
> **NOTE —** `EmitImmediate` **不知道**绝对位。它只选择六个 proto 字段之一并设置 present bit。绝对位完全由阶段 2 的编码器 `BitCopy` 字面量决定。这就是为什么同一个逻辑 immediate slot 0 在 SCS 中位于 bit 67,而在 TC 中位于 bit 430 的原因:proto 字段相同,编码器不同。
---
## BitCopy:通用打包器
### 目的
一个函数负责打包每个 V5+ bundle 的每个字段。不存在按类型划分的序列化器;每个 `<Slot>Encoder::Encode` 都是一张扁平的 `BitCopy` 调用列表。恢复任意槽的布局,等价于读取命名编码器中每个 `BitCopy` 调用前的 `(dst_bit, nbits)` 立即数对。
### 调用约定和语义
`BitCopy` 是 `_Z7BitCopyPviPKvii`,即 `BitCopy(void* dst, int dst_bit, const void* src, int src_bit, int nbits)`。在 System V 下,参数进入 `rdi`、`esi`、`rdx`、`ecx`、`r8d`。反编译函数体(`0x1fa0a900`)确认了位精确、LSB-first 行为:
```c
function BitCopy(dst, dst_bit, src, src_bit, nbits): // 0x1fa0a900
if nbits == 0: return // early-out, then vzeroupper
dst_byte = dst_bit / 8 // = dst_bit >> 3
dst_off = dst_bit & 7 // bit-in-byte
src_byte = src_bit / 8
src_off = src_bit & 7
// copy nbits from src starting at (src_byte, src_off) into dst at (dst_byte, dst_off),
// LSB-first, preserving the surrounding bits of any straddled dst byte
// (vectorized inner loop when the run is >= 24 bits; scalar head/tail otherwise)函数体完全按上述方式计算 dst_bit / 8 和 dst_bit & 7,对前导/尾随的部分字节做掩码,使相邻字段不受影响,并对 24 位及以上的连续区间使用 AVX 内循环。bit 0 是 bundle 缓冲区 byte 0 的 LSB。
QUIRK — 由于每个字段都是独立
BitCopy到共享缓冲区,字段顺序对正确性无关紧要,只要窗口不重叠。编码器会先写 predication header,再分派逐 op 逻辑,但重新实现可以按任意顺序发出调用。重叠本身是设计允许的:在 6acc60406 SCS 上,3 位 predicate selector 和 4 位 dual-predicate index 都从 bit 187 开始(见 Predicate Slot)。
因此,每个具体的 mov esi,<dst_bit>; mov r8d,<width>; call BitCopy 都可以直接读作“把 width 位放到绝对 bit dst_bit”。下面所有位置都从命名编码器中的这些立即数恢复而来。
Immediate 槽映射
目的
branch/call/sync 目标偏移和所有其他 immediate 都位于 immediate 槽中,而不是位于任何 opcode 字段中。分支的 20 位有符号目标偏移是 immediate slot 0;sequencer 槽中的 opcode 判别符只区分 absolute/relative/call。本页就是各代 bundle 页面委托说明这些位置的归宿。
SCS Bundle(32 B / 256 bit)
SparseCoreImmediatesEncoder::Encode 读取 proto 字段 a2[6]..a2[11](proto +0x18..+0x2c,即 imm_0..imm_5),并以 20 位宽度对每个字段执行 BitCopy。三代均逐字节相同:
| imm slot | proto 字段 | dst_bit(hex) | dst_bit(dec) | 宽度 |
|---|---|---|---|---|
| 0(branch/call offset) | +0x18 | 0x43 | 67 | 20 |
| 1 | +0x1c | 0x2f | 47 | 20 |
| 2 | +0x20 | 0x1b | 27 | 20 |
| 3 | +0x24 | 0x07 | 7 | 20 |
| 4 | +0x28 | 0xd7 | 215 | 20 |
| 5 | +0x2c | 0xc3 | 195 | 20 |
编码器地址:vfc 0x1ee75ee0,glc 0x1eb563c0,gfc 0x1ecd1760。slot 4 和 5(bits 215/195)出现在完整的 SparseCoreImmediatesEncoder 中;SCS branch/call 路径只使用 slots 0..3。第二个类 SparseCoreScalarImmediatesEncoder(gfc 0x1eb5bd20)只在同样的 bits 67/47/27/7 打包 slots 0..3,它是 gfc SCS codec template 命名的编码器。gfc SCS codec template(在 EncodeBundle 0x1e838cc0 case 3 SparseCoreScsCodecBase<…> 参数列表中确认)选择 SparseCoreScalarImmediatesEncoder,因此 0x1eb5bd20 是 SCS 分支路径实际调用的函数;完整的 SparseCoreImmediatesEncoder::Encode(slots 0..5,bits 215/195)位于 0x1ecd1760。branch/call offset(imm slot 0 = bit 67)在两个编码器之间相同。
NOTE —
EncodeBundle0x1e838cc0专门是 6acc60406 codec dispatcher:其defaultarm 报告 "EncodeBundle not implemented for sequencer type",三个有效 case 构造gfc::isa::{TensorCore,SparseCoreScs,SparseCoreTec}CodecBase<…>。Ghostlite 有自己的EncoderGlTensorCore::EncodeBundle(0x1d331d00)。slot-walk 机制在 v5+ 中共享,但 dispatcher 符号是代特定的。
TensorCore Bundle(64 B / 512 bit)
TensorCoreImmediatesEncoder::Encode 读取 imm_0..imm_5(proto +0x18..+0x2c),并以 20 位宽度对每个字段执行 BitCopy。逐代位位置由编码器 BitCopy 字面量逐字确认:
| imm slot | proto 字段 | vxc (VF) | glc (GL) | gfc (GF) | 宽度 |
|---|---|---|---|---|---|
| 0(branch/call offset) | +0x18 | 430 (0x1ae) | 433 (0x1b1) | 423 (0x1a7) | 20 |
| 1 | +0x1c | 410 | 413 | 403 | 20 |
| 2 | +0x20 | 390 | 393 | 383 | 20 |
| 3 | +0x24 | 370 | 373 | 363 | 20 |
| 4 | +0x28 | 350 | 353 | 343 | 20 |
| 5 | +0x2c | 330 | 333 | 323 | 20 |
编码器地址:vxc 0x1eebee40,glc 0x1f20d520,gfc 0x1f86de20。
逐代差异是核心事实:Ghostlite = Viperfish + 3 位(TC scalar/sequencer/immediate 区域整体 +3,为 7→8 位 opcode 扩宽腾出空间),而 6acc60406 = Viperfish − 7 位(immediate block 下移,为其上方更宽的 scalar/predicate 区域腾出空间;在 gfc 上该区域包含 bits 496..505 的专用 dual-predicate 槽)。
GOTCHA —
EmitImmediate中的 immediate slot index 是逻辑索引,不是固定 bit。slot 0 在 SCS 中是 bit 67,但在 TC 中是 bit 430/433/423。重新实现若为 "immediate slot 0" 硬编码一个 bit,会破坏每个跨 engine 分支。应根据 (engine, generation) 对解析 bit,而不是只看 slot index。
Sequencer 槽映射
目的
sequencer 槽(ScalarAlu0)承载 branch/call 判别符、call return-address(dest)sreg、branch-by-register x-target sreg 和 predication header。branch/call 目标偏移不在这里,而是在 immediate slot 0。sequencer 槽是各代 bundle 页面委托到本页的位置;尤其是 TC sequencer 无法从 InstBits 中提取,因为 InstBits 为空。
判别符模型
每个 ScalarAlu0 op 写一个 opcode-HIGH 字段(宽度 6,family)和一个 opcode-LOW 字段(宽度 5,寻址判别符)。对所有 branch/call control op,opcode-HIGH = 0;标量 ALU compute op 则把自身 opcode 放在 opcode-HIGH 中(例如 CompareIntegerEq = 0x1e)。opcode-LOW 判别符值在 SCS 和 TC、所有 V5+ 代中一致:
| opcode-LOW | Op | 额外字段 |
|---|---|---|
| 4 | BranchAbsolute | offset → imm slot 0 |
| 5 | BranchRelative | offset → imm slot 0 |
| 6 | CallAbsolute | offset → imm slot 0;dest(link)sreg → dest 字段 |
| 7 | CallRelative | offset → imm slot 0;dest(link)sreg → dest 字段 |
| 4(使用 family 字段) | BranchSreg | x-target sreg → x-target 字段 |
| 0x18 (24) | BranchRelativeRotatingPreg | rotating-preg index → 专用字段(仅 gfc SCS) |
绝对、相对和调用的分支偏移范围均为有符号 20 位(−0x80000..+0x7FFFF);abs/rel 区别纯粹是判别符值。return 不是专用 op,它是读取 link sreg 的 BranchSreg。
SCS Sequencer(SparseCoreScalarAlu0Encoder::Encode)
编码器写入通用 predication header,然后分派 jmp *jt[proto+0x50](上界 0x56 = 86 项)到逐 op helper。由 glc 0x1e9d2140 和 BranchAbsolute helper 0x1e9d67c0 确认;Viperfish(vfc encoder 0x1ee82ce0,BranchAbsolute helper 0x1ee873c0)逐字节相同。
| 字段 | dst_bit | hex | 宽度 | 来源 / 写入者 |
|---|---|---|---|---|
| predication reg index | 187 | 0xbb | 4 | proto +0x20,主编码器 |
| predication inversion | 191 | 0xbf | 1 | proto +0x18(byte),主编码器 |
| opcode-HIGH / family | 181 | 0xb5 | 6 | 逐 op helper(branch/call 为 =0) |
| opcode-LOW / discriminator | 176 | 0xb0 | 5 | 逐 op helper(4/5/6/7/0x18) |
| x-target / 2nd operand | 170(gfc)/ 176(vfc/glc) | 0xaa / 0xb0 | 6 / 5 | BranchSreg/aux(gfc 0x1eb6dd40,vfc 0x1ee87480) |
| call dest(return-addr)sreg | 165 | 0xa5 | 5 | CallAbsolute/CallRelative |
rotating-preg index(gfc) | 165 | 0xa5 | 4 | BranchRelativeRotatingPreg |
在 6acc60406(gfc encoder 0x1eb693c0)上,SCS predication 变窄:bit 187(0xbb)处 3 位 selector + bit 190(0xbe)处 inversion,与同样从 bit 187 开始的 4 位 dual-predicate index + bit 191 处 inversion 重叠。gfc BranchRelativeRotatingPreg helper(0x1eb6b9c0)在 bit 176(w5)写判别符 24,在 bit 181(w6)写 opcode-HIGH 0,在 bit 165(w4)写 rotating-preg index,并在 bit 170 写 6 位 aux。
TC Sequencer(TensorCoreScalarAlu0Encoder::Encode)
该槽无法由 InstBits 容纳。由 vxc 0x1eecb900(及 helper 0x1eecf960)、glc 0x1f219b40(及 helper 0x1f21da40)和 gfc 0x1f87b420 确认。
| 字段 | vxc (VF) | glc (GL) | gfc (GF) |
|---|---|---|---|
| predication reg index | bit 499 w4 | bit 502 w4 | —(2 位 selector) |
| predication inversion | bit 503 w1 | bit 506 w1 | — |
| predication 2-bit selector | — | — | bit 489 w2 |
| opcode-HIGH / family | bit 493 w6 | bit 496 w6 | bit 483 w6 |
| opcode-LOW / discriminator | bit 488 w5 | bit 491 w5 | bit 478 w5 |
| x-target / 2nd operand | bit 482 w6 | bit 485 w6 | bit 472 w6 |
| call dest(return-addr)sreg | bit 477 w5 | bit 480 w5 | bit 467 w5 |
Ghostlite 将整个 TC scalar/sequencer 区域在 Viperfish 基础上上移 +3 位,与 TC immediate block 的 +3 位平移(433 vs 430)同步;整个 TC scalar/sequencer/immediate block 作为一个刚性窗口平移,以吸收 7→8 位 opcode 扩宽(glc::isa::TensorCoreScalarAlu0Encoder::Encode 0x1f219b40 及其 BranchAbsolute helper 0x1f21da40:predicate reg @ 502 而非 499,inversion @ 506 而非 503,opcode-HIGH @ 496 而非 493,opcode-LOW @ 491 而非 488,x-target aux @ 485 而非 482,call dest @ 480 而非 477)。SCS sequencer 没有平移,glc 在那里与 vxc 逐字节相同(0x1e9d2140);见 Ghostlite Bundle。6acc60406 的 TC scalar 槽最宽:它在 bit 472 增加 6 位 operand,并将逐槽 predication 缩小为 bit 489 处的 2 位 selector,而实际的 16 寄存器 predicate 池移到了专用的 TensorCorePredicates 槽。
NOTE — TC
vxcx-target 跨两个不同字段。bit 488(w5)是 opcode-LOW 判别符(与BranchSregx-target 值共享);secondary-operand / LCC-read aux 字段则是 bit 482(0x1da)处的独立 6 位字段,由vxc编码器主体(0x1eecb900)确认。BranchSreg会用 x() sreg 覆盖判别符窗口,但 LCC read 同时使用 bit 488 的 5 位判别符和 bit 482 的 6 位 aux。
Predicate 槽映射 {#predicate-slot-map}
目的
确定每个 V5+ bundle 槽内 predicate 字段的确切字节偏移,即此前 predicate-field 分析留下的空白位置(当时称其“受 InstBits 控制”,而 InstBits 为空)。Viperfish/Ghostlite 的逐槽方案和 6acc60406 的专用 dual-predicate 槽模型不同。
Viperfish / Ghostlite:逐槽 4+1 字段
每个已填充的 functional 槽都携带自己的 predicate:4 位寄存器索引加 1 位 inversion(encodePredicateOperand 布局的 2 位扩展是该字段高端,在非 rotating 代码中为 0)。在 scalar 槽顶部:
| 槽 | reg index | inversion | 编码器 |
|---|---|---|---|
TC ScalarAlu0(vxc) | bit 499 w4 | bit 503 w1 | 0x1eecb900 |
TC ScalarAlu0(glc) | bit 502 w4 | bit 506 w1 | 0x1f219b40 |
SCS ScalarAlu0(glc/vfc) | bit 187 w4 | bit 191 w1 | 0x1e9d2140 / 0x1ee82ce0 |
6acc60406:专用 Dual-Predicate 槽
TensorCorePredicatesEncoder::Encode(gfc 0x1f86e500)把两个每 bundle predicate 写入 64 字节 TC bundle 的最顶部;随后每个 functional 槽只携带 2 位 selector,在 {pred_0, pred_1, always, never} 中选择:
| 字段 | dst_bit | hex | 宽度 | proto src |
|---|---|---|---|---|
| pred_0 reg | 501 | 0x1f5 | 4 | msg word |
| pred_0 inversion | 505 | 0x1f9 | 1 | msg +0x20(byte) |
| pred_1 reg | 496 | 0x1f0 | 4 | msg word |
| pred_1 inversion | 500 | 0x1f4 | 1 | msg +0x21(byte) |
16 寄存器 predicate 池(PredicationSlot 枚举 0..15)被编码进 pred_0/pred_1;逐槽 2 位 selector 对该池建立索引。"predication overflow — both predicate slots already taken" 条件正是 bits 496..505 中这两个 4 位 (reg, inversion) 条目已满的状态。2 位 selector 的具体值到 {pred_0,pred_1,always,never} 的映射尚未解码(selector 自己的跳转表未遍历);selector 字段偏移已确认(值语义 LOW confidence)。
Compute 槽:MXU、Result、EUP
目的
MXU matmul/push/latch(VectorExtended)、matres/EUP pop(VectorResult)和 transcendental push(VALU slot 3)都来自同一套 <Slot>Encoder::Encode + BitCopy 机制。它们在 MXU Slot、VPU Slot 和 EUP/Transcendental Slot 中完整记录;绝对位位置在这里汇总。
MXU VectorExtended 槽
两个 MXU 槽(VectorExtended0、VectorExtended1),每个物理矩阵单元一个。这两个槽共享 source-vreg(systolic-feed)区域,但在 6acc60406 上,opcode/control 区域相差一个 25 位槽步长。opcode 字段跨代从 7 位扩宽到 8 位,与 VALU 槽一致。由 gfc MatrixMultiplyBf16 0x1f99a920 确认:
| 字段 | vxc | glc | gfc VEx0 | gfc VEx1 |
|---|---|---|---|---|
| MXU-id(unit)[proto +0x1c] | bit 64 w4 | bit 66 w4 | bit 70 w2 | bit 45 w2 |
| opcode-HIGH | bit 57 w7 | bit 58 w8 | bit 62 w8 | bit 37 w8 |
| data-format sub-disc | bit 51 w4 | bit 52 w4 | bit 57 w4 | bit 32 w4 |
| done-gains/latch flag | bit 55 w2 | bit 56 w1 | bit 61 w1 | bit 36 w1 |
| control(3 位) | bit 48 w3 | bit 49 w3 | bit 54 w3 | bit 29 w3 |
| primary operand | bit 180 w6 | bit 183 w6 | bit 47 w7 | bit 22 w7 |
src vregs(8 × 6 位,gfc) | — | — | 156/276/287/243/254/210/221/177 | (相同) |
| opcode bound(#ops) | 0x66 (103) | 0x70 (113) | 0x54 (85) | 0x54 (85) |
编码器地址:vxc 0x1efa0f60,glc 0x1f32fd00,gfc VEx0 0x1f996940 / VEx1 0x1f9d3800。weight latch 是 LoadMatrixRegister{Gmr,Lmr}{Msra,Msrb}(gfc 上 opcode-HIGH 0x37,0x1f9a04a0);moving-operand push 是 PushMatrix{fmt}(opcode-HIGH 0xe)。8 个 source-vreg 字段在 VEx0 和 VEx1 之间逐字节相同,这一编码事实表明两个 MXU 从同一组 vector read port 取数。
VectorResult 槽(matres pop / EUP pop)
VectorResult0Encoder::Encode 读取 result-type 判别符(proto +0x1c),分派 jmp *jt[proto+0x50],设置逐 result-type 子消息 present tag,然后在公共尾部用 BitCopy 写 dest vreg。由 gfc 0x1fa01820 确认:
| 字段 | vxc | glc | gfc |
|---|---|---|---|
| result-type discriminator | bit 24 w4 | bit 24 w4 | bit 20 w2 |
| dest vreg | bit 14 w6 | bit 14 w6 | bit 11 w6 |
| PopMxu accum-mode/format | (按 +0x1c) | (按 +0x1c) | bit 323 w8 |
| result-opcode bound | 0x8 (9) | 0x8 (9) | 0x7 (8) |
matres-pop opcode 在所有代上都是 6(PopMxuResult),EUP-pop opcode 都是 7(PopEupResult)。Ghostlite 增加了 PopAddMxu01Result(融合 matres+accumulate,K>128 多 pass);Viperfish 增加了 PopCcrfResult(scalar/CRF pop)。result 槽自身的 predication 字段访问器是 TensorCoreVectorResult1PredicationField::GetConcatenatedValue(gfc 0x1fa02520);其确切 bit 未单独遍历(相邻的 result-mode/format 字段 bits 17..21 已解码)。
EUP / Transcendental Push:VALU Slot 3
在所有 V5+ 代上,transcendental push 都是 VALU slot-3(Alu3)op,而不是 VectorExtended op;这一点由 EUP helper 只存在于 Alu3 集合中确认。VALU opcode 字段选择 EUP-push 家族(值 0x0);5 位 EUP-function selector 选择具体 transcendental。由 gfc F32Tanh 0x1f96ae40 确认:
| 字段 | vxc | glc | gfc |
|---|---|---|---|
| VALU opcode(EUP-push family = 0x0) | bit 197 w7 | bit 194 w8 | bit 194 w8 |
| EUP-function selector | bit 186 w5 | bit 183 w5 | bit 183 w5 |
| src vreg | (slot-3) | bit 188 w6 | bit 188 w6 |
gfc 5 位 function selector 值映射(VALU op = 0x0,selector @ bit 183)由逐 helper 确认:
| function | F32 selector | Bf16 selector |
|---|---|---|
Erf | 0x0e | 0x0f |
ReciprocalSqrt | 0x10 | 0x0c |
PowTwo (2^x) | 0x11 | 0x19 |
LogTwo (log2) | 0x12 | 0x1a |
Tanh | 0x13 | 0x1b |
ShiftedSigmoid | 0x14 | 0x1c |
Reciprocal | 0x15 | 0x1d |
Sinq (sin) | 0x17 | 0x1e |
Cosq (cos) | 0x18 | 0x1f |
push-pop 协议是位精确的:bundle N 中的 PUSH 是上述 VALU slot-3 op;bundle N+k 中的 POP 是 result-opcode 7(PopEupResult)的 VectorResult op,dest vreg 位于 bit 11(gfc)。XLU 是 single-issue,因此只有 VALU slot 3 能发起 EUP push。
逐 (Slot, Generation) 绝对位位置表
这是各代 bundle 页面引用的汇总参考。所有位置均为 bit <n> w<width>;bit 0 = byte 0 的 LSB。
SCS Bundle(32 B / 256 bit)
| slot / 字段 | vfc (VF) | glc (GL) | gfc (GF) |
|---|---|---|---|
| branch/call offset(imm 0) | 67 w20 | 67 w20 | 67 w20 |
| imm slot 1 | 47 w20 | 47 w20 | 47 w20 |
| imm slot 2 | 27 w20 | 27 w20 | 27 w20 |
| imm slot 3 | 7 w20 | 7 w20 | 7 w20 |
| seq opcode-HIGH | 181 w6 | 181 w6 | 181 w6 |
| seq opcode-LOW(discriminator) | 176 w5 | 176 w5 | 176 w5 |
| seq x-target / 2nd operand | 176 w5 | 176 w5 | 170 w6 |
| seq call dest sreg | 165 w5 | 165 w5 | 165 w5 |
| seq predicate reg | 187 w4 | 187 w4 | 187 w3(selector)/ w4(dual) |
| seq predicate inversion | 191 w1 | 191 w1 | 190 w1 |
| rotating-preg index | — | — | 165 w4 |
TensorCore Bundle(64 B / 512 bit)
| slot / 字段 | vxc (VF) | glc (GL) | gfc (GF) |
|---|---|---|---|
| branch/call offset(imm 0) | 430 w20 | 433 w20 | 423 w20 |
| imm slots 1..5 | 410/390/370/350/330 | 413/393/373/353/333 | 403/383/363/343/323 |
| seq opcode-HIGH | 493 w6 | 496 w6 | 483 w6 |
| seq opcode-LOW(discriminator) | 488 w5 | 491 w5 | 478 w5 |
| seq x-target / 2nd operand(aux) | 482 w6 | 485 w6 | 472 w6 |
| seq call dest sreg | 477 w5 | 480 w5 | 467 w5 |
| seq per-slot predicate | reg 499 w4 + inv 503 w1 | reg 502 w4 + inv 506 w1 | 2-bit selector @ 489 |
| dual predicate pred_0 | — | — | reg 501 w4 + inv 505 w1 |
| dual predicate pred_1 | — | — | reg 496 w4 + inv 500 w1 |
| MXU opcode-HIGH(VEx0) | 57 w7 | 58 w8 | 62 w8 |
| MXU data-format sub-disc | 51 w4 | 52 w4 | 57 w4 |
| MXU-id(unit) | 64 w4 | 66 w4 | 70 w2 |
| VectorResult discriminator | 24 w4 | 24 w4 | 20 w2 |
| VectorResult dest vreg | 14 w6 | 14 w6 | 11 w6 |
| EUP-push VALU opcode(Alu3) | 197 w7 | 194 w8 | 194 w8 |
| EUP-function selector | 186 w5 | 183 w5 | 183 w5 |
逐代差异一句话概括:Ghostlite 将整个 TC scalar/sequencer/immediate 窗口上移 +3 位(immediate slot 0 bit 430 → 433;sequencer opcode-HIGH 493 → 496),作为一个刚性块吸收 7→8 位 opcode 扩宽;6acc60406 将 TC immediate block 下移 −7 位(bit 430 → 423),并把 scalar/sequencer 区域下移,为 bits 496..505 的专用 dual-predicate 槽和 bit 472 处更宽的 scalar operand 腾出空间。
Delay-Slot 和 Loop 说明
标准 LLVM-MC 思维模型预期会被编码的两个字段,在 V5+ 上不是 bundle 内位字段:
- Delay-slot count。 没有任何 V5+ branch/call helper(Ghostlite、Viperfish 或 6acc60406)会发出
delay_slotsBitCopy。branch/call helper 只写{opcode-HIGH, opcode-LOW, offset (imm 0), dest}。delay-slot count 是 bundle-packer pad count(在分支之后追加的空 bundle),由 packer 上的 LLVM-MC verifier bound(delay_slots <= 5)门控,而不是编码后的槽字段。 - Hardware-loop length。 V5+ 没有 hardware-loop setup 槽位字段。loop 是 LCC 硬件计数器读取(
ReadRegisterLccLow/High,sequencer-slot opcode 位于 bit 181 + dst 位于 bit 176)馈入条件BranchRelative。所谓“loop counter”是寄存器,而不是编码后的 loop-length 字段。
GOTCHA — 重新实现如果在 bundle 内分配 3 位 delay-slot 字段(像
BarnaCore风格 v4 布局那样),会让后续每个字段都失步。在 V5+ 上,分支的 dest 字段之后的下一批 bit 属于下一个槽,而不是 delay count。
交叉引用
- IsaEmitter Registry:生成本页所序列化 proto 的
isa_emitter::EmitX模板家族和逐代 codec 注册 - Viperfish 64B Bundle:
vxc/vfc槽映射;sequencer/immediate/predicate 位置引用本页 - Ghostlite Bundle:
glc槽映射和 +3 位 TC 平移 - 6acc60406 Bundle:
gfc槽映射、专用 dual-predicate 槽和 2 位逐槽 selector - MC-Emitter:馈入阶段 1
EmitX的 MCInst 流 - Record Format:编码后 bundle 字节周围的磁盘 record framing
- Sequencer Slot:映射到本页判别符值的 branch/call/LCC op 语义
- Predicate Slot:本页确定其绝对偏移的 predication 模型
- MXU Slot / VPU Slot / EUP/Transcendental Slot:汇总的 MXU/result/EUP 位置所对应的 compute-slot 语义
- InstBits Master DB:确认这些位位于 emitter 路径中的全零 V5+
InstBits表