Skip to content

kIsaTable 数据段

本页中的每个偏移、值、地址和大小都逐字节精确读取自 libtpu-0.0.40-cp314 wheel 中的 libtpu.so(BuildID md5 89edbbe81c5b328a958fe628a9f2207d,未 stripped — 完整 C++ 符号)。所有地址都是虚拟地址;.rodata / .lrodata 按 1:1 映射(VA == file offset);.data.rel.ro 的 VA − file offset = 0x200000。其他 wheel 版本会不同。

摘要

"kIsaTable" 是对编译器 .rodata 中内置的逐代 ISA 编码描述符数据的惯用称呼,也就是编码器和解码器按 opcode 索引的 opcode/encoding 表。libtpu 中没有字面名为 kIsaTable 的符号。相反,逐代 ISA 编码这一角色被拆分到五类具体静态结构中,每一类都已定位、确定大小并部分解码:逐代 CodecMetadata 类(bundle 字节宽度、check byte、chunk 几何)、LLVM TPU 后端表(InstBitsTPUDescsTPUInstrName*、逐代 SchedModel 表)、逐代 kNoopBundleBytes NOP 模板、Ghostlite kLloOpcodeToGlcInstruction 翻译表,以及封装 codec metadata 的逐代 Encoder*/Decoder* 类。本页是这些段的地图:每个 blob 是什么、位于哪里、有多大,以及 encode/decode 路径如何索引它。

重实现者首先需要的架构事实是:编码数据不是一个按 (gen, opcode) 索引的单体表。LLVM-MC InstBits 数组跨代共享,但只为 Pufferfish BarnaCore HwMode 填充(每个 TensorCore 和 V5+ 行都是全零 — 见 InstBits Master DB);真正的 V5+ bundle 位由逐代 proto-bundle Encoder<gen> 类生成,其几何来自 CodecMetadata 注册表,而不是来自 InstBits。因此,“kIsaTable” 实际上是一个小型联合体:用于 bundle 几何的逐代 codec-metadata vtable 注册表、用于 MC 层 descriptor/name/sched 表的 LLVM TableGen .lrodata 区域、三个静态 NOP 模板,以及一个 Ghostlite 专用 opcode 翻译数组。

本页按成员记录这个联合体 — namespace/generation 映射、CodecMetadata 类及其逐代常量、带地址和大小的 LLVM 后端表清单、NOP 模板,以及 Ghostlite LLO→GLC 表 — 并说明编码器如何到达各成员。它是一个目录页:给出已确认的地址和大小,以及索引各 blob 的算法,而不是倾倒 181 KB 的 base bits。

对重实现而言,契约是:

  • generation → namespace → LLVM-target 映射(6 个 codename,3 个 HAL family,TpuVersion 0..5)— 每个 encoder/table 符号都按这套分类命名。
  • 逐代 CodecMetadata(7 个 virtual)是 bundle-geometry “kIsaTable”:BundleSizeBytes…ForHbmHasCheckByteForHbmBundleCheckByte…MaskBundleChunkSizeBundlesPerChunk,通过进程级注册表按 (TpuVersion, TpuSequencerType) keyed。
  • LLVM TPU 后端 .lrodataInstBits @ 0x3366d90TPUDescs @ 0x33bf650TPUInstrNameData/Indices、逐代 SchedModel SchedClasses/ProcResources)— MC 层 descriptor 联合体,按 opcode − 499 索引。
  • 逐代 kNoopBundleBytes(64 字节 V5+ NOP 模板),以及 pre-V5 gens 使用 kNeverExecute = 31 动态构造 NOP。
  • Ghostlite kLloOpcodeToGlcInstruction(258 项排序 (u16, u16) 数组 @ 0x4067dc8)— 唯一的静态逐代 LLO→ISA 翻译表;其他 gens 使用 switch 语句。
字面 kIsaTable 符号无 — 角色拆分到 5 类结构
GenerationsJellyfish / Dragonfish / Pufferfish / Viperfish / Ghostlite / 6acc60406 (TPU7x) (TpuVersion 0..5)
Codec 注册表CodecMetadataRegistry (absl::flat_hash_map<TpuVersion, pair<char*, CodecMetadata*>>, StaticMapBase singleton)
Codec 查找GetMetadataOrDie(TpuVersion) → 失败时 dies "Codec metadata not registered for TpuVersion"
MC base-bitsInstBits @ 0x3366d90 (0x2c460 B) / InstBits_BarnaCorePxcHwMode @ 0x33931f0
MC descriptorsTPUDescs @ 0x33bf650 (0x33590 B); TPUInstrNameData @ 0x33f2be0; TPUInstrNameIndices @ 0x3435d30
NOP 模板kNoopBundleBytes — vxc @ 0xb846d64, gxc::glc @ 0xb862ff4, gxc::gfc @ 0xb88580a (各 64 B)
Ghostlite xlatxla::ghostlite::kLloOpcodeToGlcInstruction @ 0x4067dc8 (0x408 B = 258 × 4)
置信度CONFIRMED(byte-anchored),除非某行另有说明

Generation 和 Namespace 映射

每个表和编码器符号都按三轴分类命名:codename、HAL family 和内部 C++ namespace。该映射从符号 demangling 和嵌入的 codec_metadata_<gen>.cc 源路径锚点恢复而来。

CodenameTpuVersionFamily内部 namespaceLLVM subtarget
Jellyfish0JXCplatforms_deepsea::jellyfish::isaTPUSubtarget (base)
Dragonfish1JXC(共享 JellyfishCodecMetadatabase
Pufferfish2PXCasic_sw::deepsea::pxc::isabase + TPUBcSubtarget
Viperfish3VXCasic_sw::deepsea::vxc::isaTPUVfcSubtarget
Ghostlite4VXC=GXCasic_sw::deepsea::gxc::glc::isaTPUGlcSubtarget
6acc60406 (TPU7x)5VXC=GXCasic_sw::deepsea::gxc::gfc::isaTPUGfcSubtarget

SparseCore 子 namespace(vxc::vfc::isagxc::glc::isa::sparsecoregxc::gfc::isa::sparsecore)和 Pufferfish BarnaCore(pxc::pfc::isa)带有自己的编码器。(TpuVersion, TpuSequencerType) pair 是进入 codec metadata 的完整 key — 一颗芯片有若干 sequencer type,bundle 宽度不同(见 Bundle Model)。八个 TpuSequencerType 值是 TC=0, BCS=1, BCAH=2, SCS=3, TAC=4, TEC=5, SCv0=6, SCv0AH=7;逐代 presence matrix 记录在 Bundle Model

NOTE — v5 generation 在二进制中只以 codename 6acc60406 出现(tpu::TpuVersion::k6acc60406 enumerator、TPU_VERSION_6acc60406xla_target_6acc60406,以及 .../target/6acc60406/ 源路径);营销名 "Trillium" 和 "Ironwood" 在 libtpu.so 中出现 0 次。本页使用二进制 codename,并在首次出现时注释为 (TPU7x)

Ghostlite (glc) 和 6acc60406 (gfc) 都属于 GXC family,因此它们的符号共享 gxc:: 前缀。表中可见的一个结构差异是:存在 SparseCoreTacGL* SchedModel,但没有 SparseCoreTacGF* — 6acc60406 没有 TAC sequencer(由下方符号缺失确认)。


CodecMetadata — Bundle-Geometry “kIsaTable”

最接近逐代 kIsaTable 的东西是 CodecMetadata 类:每代一个 subclass,派生自抽象基类 platforms_deepsea::jellyfish::isa::codec_metadata::CodecMetadata,暴露七个按 TpuSequencerType keyed 的 virtual。vtable 布局固定(由 BundleSizeBytes thunk 解引用 *((vtable) + N) 确认):

vtable slotvirtual含义
+16BundleSizeBytes(seq)线上形式(DMA form)每个 bundle 的字节数
+24BundleSizeBytesForHbm(seq)存在 HBM 中每个 bundle 的字节数(可能添加 check byte)
+32HasCheckByteForHbm(seq)HBM form 是否追加 check byte?
+40BundleCheckByte(seq)期望的 check-byte 值(普遍为 0x55
+48BundleCheckByteMask(seq)compare 前的 mask(普遍为 0xFF
+56BundleChunkSize(seq)线上 chunk 大小,单位字节
+64BundlesPerChunk(seq)每个 chunk 的 bundle 数

注册表和查找

逐代实例被放入进程级 CodecMetadataRegistry — 一个通过 util_registration::StaticMapBase singleton 构建一次的 absl::flat_hash_map<tpu::TpuVersion, pair<char const*, CodecMetadata const*>>。四个全局构造函数注册四个 codec 类;GetMetadataOrDie(TpuVersion) (@ 0x1ecf6f60) 以 map 为 key 查找,miss 时以 "Codec metadata not registered for TpuVersion: " dies。自由函数 dispatch wrapper(codec_metadata::BundleSizeBytes(TpuVersion, TpuSequencerType) @ 0x1ecf7180,以及六个 sibling @ 0x1ecf71a0…0x1ecf7240)调用 GetMetadataOrDie,然后索引解析出的实例的 vtable:

c
// codec_metadata::BundleSizeBytes(TpuVersion v, TpuSequencerType t)  @ 0x1ecf7180  (dispatch)
md = GetMetadataOrDie(v);          // flat_hash_map lookup; LogFatal on miss
return md->vtable[+16](t);          // virtual BundleSizeBytes(t) on the per-gen class
```text

| registering ctor | registers |
|---|---|
| `_GLOBAL__sub_I_codec_metadata_jellyfish.cc` @ `0x213673e0` | JF=0 **and** DF=1 (same instance) |
| `_GLOBAL__sub_I_codec_metadata_pufferfish.cc` @ `0x21367470` | PF=2 |
| `_GLOBAL__sub_I_codec_metadata_viperfish.cc` @ `0x213674c0` | VF=3 |
| `_GLOBAL__sub_I_codec_metadata_ghostlite.cc` @ `0x21367510` | GL=4 |

Jellyfish 注册**两个** key(01)到*同一个* `JellyfishCodecMetadata` 实例 — Dragonfish (v1) 复用 Jellyfish (v0) codec。没有 `_GLOBAL__sub_I_codec_metadata_6acc60406` 构造函数:6acc60406 没有注册 codec metadata,因此 `GetMetadataOrDie(5, …)` 会 fatal abort。6acc60406 bundle 几何只通过 `gxc::gfc::isa` 中 type-erased 的 `EncoderBase<>` 模板 vtable 到达(它们通过自己的 `vtable[+48]` forward `BundleSizeBytes`),绝不经由注册表。

### 逐代常量

直接从 `BundleSizeBytes` virtual 反编译得到 — `(seq, return)` 分支是精确的:

```c
// JellyfishCodecMetadata::BundleSizeBytes  @ 0x1ecf7460
if (seq == 0) return 41;               // TensorCore
if (seq == 1) return 16;               // BarnaCoreAddressHandler
LogFatal("Unhandled component");       // codec_metadata_jellyfish.cc:19

// ViperfishCodecMetadata::BundleSizeBytes  @ 0x1ee71320
if (seq != 0) LogFatal("Unhandled component");  // codec_metadata_viperfish.cc:20
return 64;                             // TensorCore
Gen (seq=TC)BundleSizeBytescheck bytechunkbundles/chunkmetadata @
Jellyfish / Dragonfish410x5512830x1ecf7460…
Pufferfish510x555110x1ecf7ac0…
Viperfish640x556410x1ee71320…
Ghostlite640x550x1eeb7640…
6acc6040664(template; no registry)(no class)

…ForHbm virtual 在 Pufferfish/Ghostlite 上对 seq=0 会 fatal abort(它们的 TensorCore HBM 路径直接走 EncoderPfTensorCore / EncoderGlTensorCore,而不是这个 metadata);Jellyfish 的 …ForHbm 返回 42(41 + 1 check byte)。逐代完整几何 — 包括 HBM +1 check byte 和 Jellyfish 的 (n/3)*128 + (n%3)*43 chunk 布局 — 见 Bundle Model


LLVM TPU 后端表

编译器在 libtpu 中嵌入了完整的 LLVM TPU 后端,其 TableGen 生成的表位于一个连续的 .lrodata 区域(另有少数在 .data.rel.ro 中)。这些是 MC 层 descriptor 联合体 — 逐 opcode 编码位、descriptor、mnemonic、寄存器编码和逐代调度模型。它们按 opcode − 499 索引(前 499 个 opcode 是 MC pseudos)。

SymbolAddressSizePurpose
…getBinaryCodeForInstr::InstBits0x3366d900x2c460 (181344 B = 5667 × 32)base bits,TensorCore mode(全零)
…InstBits_BarnaCorePxcHwMode0x33931f00x2c460BarnaCore variant(704 个填充行)
llvm::TPUDescs0x33bf6500x33590逐 opcode MCInstrDesc(operand type、flag)
llvm::TPUStages0x343bd900x7c8pipeline-stage 表
llvm::TPUInstrNameData0x33f2be00x4314cmnemonic 字符串池(约 270 KB)
llvm::TPUInstrNameIndices0x3435d300x6058opcode → NameData 中的字节偏移
llvm::TPURegDesc0x343e7b00x5358register descriptors
llvm::TPURegStrings0x343cde00x19c9register name strings
llvm::TPURegEncodingTable0x34469b00x6f2reg# → HW encoding (889 × u16)
llvm::TPURegClassInfos0x334ea600x800register-class metadata
llvm::TPUFeatureKV0x219345500x480SubtargetFeature KV(约 48 × 24 B)
llvm::TPUSubTypeKV0x21934ca00x3f0subtype/CPU KV(约 42 × 24 B)

InstBits 是该联合体的 LLVM-MC 切片;它在 InstBits Master DB 中完整记录,包括其反直觉的全零默认表(TensorCore 和 V5+ 行不携带任何 bits — 这些 bundle 由 proto-bundle Encoder<gen> 路径编码,而不是由 getBinaryCodeForInstr 编码)。索引算术((opcode − 499) × 32 字节、5667 行、239-bit APInt)见 239-Bit Record Format。names JSON 确认 TPU InstBits 符号与 AArch64/AMDGPU/ARM/R600/PPC InstBits 并列 — 二进制嵌入了多个 LLVM target,TPU 这个才是相关成员。

逐代 SchedModel 表

每个非 TensorCore sequencer 都有一个 SchedClasses 表(每个 0x79a = 1946 B)和一个 ProcResources 表(每个 MCProcResourceDesc entry 为 per-cycle resource bitmask,16 B)。这些符号集合就是逐代 sequencer 清单:

Sequencer × genSchedClasses @ProcResources @ / size
BarnaCore (PF)0x34476300x21935740 / 0xa0 (10 PR)
SCS — 6acc60406 (GF)0x34483500x219357e0 / 0x320 (50 PR)
SCS — Ghostlite (GL)0x34490700x21935b00 / 0x300 (48 PR)
SCS — Viperfish (VF)0x3449d900x21935e00 / 0x2a0 (42 PR)
TAC — Ghostlite (GL)0x344a5300x219360a0 / 0x300
TAC — Viperfish (VF)0x344acd00x219363a0 / 0x2a0
TEC — 6acc60406 (GF)0x344b4700x21936640 / 0x320
TEC — Ghostlite (GL)0x344bc100x21936960 / 0x300
TEC — Viperfish (VF)0x344c3b00x21936c60 / 0x2a0

ProcResources 字节大小单调增长 — VF 0x2a0(42 units)、GL 0x300(48)、GF 0x320(50)— 因此 6acc60406 比 Viperfish 多 8 个 functional units。names table 中没有 SparseCoreTacGF* 符号,这是 6acc60406 没有 TAC sequencer 的字节级证据(它的 SparseCore 只有 SCS + TEC)。每个 TPUVfcSubtarget / TPUGlcSubtarget / TPUGfcSubtarget 都按 gen override getFifoDepthgetVyEncodingsgetSyEncodings


NOP Bundle 模板

V5+ generations 在 .rodata 中携带一个静态 64 字节 NOP-bundle 模板;pre-V5 gens 动态构造 NOP。这些模板是 empty-bundle 的 ground truth — NOP 用 kNeverExecute = 31 (0x1F) 填充每个 slot 的 predicate 字段,因此 decoder 能 round-trip 一个 absent slot。

Symbol ((anonymous namespace)::kNoopBundleBytes)AddressSizebyte 63encoding style
asic_sw::deepsea::vxc::isa0xb846d6464 B0x55每个 slot predicate 为 0x1F << shift
asic_sw::deepsea::gxc::glc::isa0xb862ff464 B0x53更紧凑的 shift base(e0 01c0 03
asic_sw::deepsea::gxc::gfc::isa0xb88580a64 B0x50全零 body(zero-default slots)

Viperfish 模板的非零 pattern(00 3c00 0f00 f000 78)是将 0x1F 移到每个 slot 的 predicate bit offset,byte 63 = 0x55 check byte。Ghostlite 使用不同的(更紧凑的)shift base,因此其 slot bit layout 不同(byte 63 = 0x53,不是字面 check byte — 高位携带最后一个 slot 的 predicate,与 check field OR 在一起)。6acc60406 的模板除 byte 63 = 0x50 外全为零 — 6acc60406 安排 slot 时让全零表示“present but inactive”,而不是“active with an always-false predicate”。Jellyfish 和 Pufferfish 没有 kNoopBundleBytes 静态量;它们的 EncodeBundleInternal 将 buffer zero-init,并在运行时把 kNeverExecute = 31 patch 到每个 predicate 字段中。kNeverExecute = 31 / kAlwaysExecute = 15 / kPredicateRegisterCount = 15 常量(0xb834cf4…0xb834cff)确认 Jellyfish predicate 字段为 5 bit。见 Bundle Model §Empty-Slot


Ghostlite LLO → GLC 翻译表

xla::ghostlite::kLloOpcodeToGlcInstruction0x4067dc80x408 B)是 xla:: namespace 中唯一的逐代静态 LLO→ISA 翻译表:一个 258 项排序数组,元素为 (uint16_t llo_opcode, uint16_t glc_instruction) pair,按 llo_opcode 二分搜索。

c
// xla::ghostlite::kLloOpcodeToGlcInstruction  @ 0x4067dc8  (258 × 4 B, sorted ascending)
struct { uint16_t llo_opcode; uint16_t glc_instruction; } entries[258];
// e.g. {9, 118}, {10, 474}, {11, 474}, {13, 70}, ... {424, 23}, {425, 26}, {426, 25}
```text

- LLO opcode 覆盖是稀疏的:`9..426`(所用约 418 范围中的 258 个)。
- GLC instruction 范围是 `0..475`。
- 该映射是**多对一** — 例如 LLO `10` 和 `11` 都映射到 GLC `474`;LLO `37` 和 `39` 都映射到 GLC `0` — 因此 GLC opcodes 比 LLO IR opcodes 粒度更粗。

为什么只有 Ghostlite 是静态数组:Jellyfish、Pufferfish、Viperfish 和 6acc60406 都把 LLO→ISA 映射实现为 **switch 语句**(例如 `xla::jellyfish::LloOpcodeToIsaScalarOpcode` @ `0x140bc1e0`,一个 162-case switch)。Ghostlite 的 GLC 映射足够宽(>200 entries),因此优先使用排序数组二分搜索而不是 switch。反向 LLO 方向是未命名的 `LloOpcodeToProto` 表 @ `0x344cb4c`(`462 × u32`);LLO opcode 编号本身(proto `1..499` → internal `0..461`)在 `ProtoToLloOpcode`(`0x14420040`)中重建。

---

## 这些段不包含什么

这个联合体诚实地说明了自身边界:

- **完整的逐 opcode TensorCore / V5+ 编码位。** `InstBits` 对这些 opcode 全为零(没有 `.rela.dyn`,已证明);真实 bits 来自逐代 `Encoder<gen>::EncodeBundleInternal` + `<Slot>Encoder::Encode` `BitCopy` 调用,其位置是逐代 slot ladders([Immediate Slot](slot-immediate.md)、逐代 bundle 页面)。*5667-case MC encoder switch 和内部逐 slot encoder 方法没有穷举 — 太大,无法手工枚举;未遍历的 V5+ slot encoders 为 MEDIUM。)*
- **来自注册表的 6acc60406 codec 常量。** 6acc60406 没有注册 `CodecMetadata`;此处的 64 字节几何读取自 `kNoopBundleBytes` 大小和 `EncoderBase` 模板,而不是注册表条目。*6acc60406 check byte 为 HIGH,而非 CONFIRMED。)*
- **GLC instruction mnemonics。** `kLloOpcodeToGlcInstruction` ID(`0..475`)已解码,但其名称需要在 Ghostlite HwMode 下交叉解码 `TPUInstrNameData` — 此处未做。
- **逐代 `TPUFeatureKV` / `TPUSubTypeKV` 内容。** 已定位并确定大小(约 48 features、约 42 subtargets),但未枚举单个 feature/CPU 字符串。

---

## 交叉引用

- [Bundle Model](bundle-model-overview.md) — `(TpuVersion, TpuSequencerType)` codec-metadata dispatch、逐代 bundle 宽度和 empty-slot `kNeverExecute` 约定。
- [InstBits Master DB](instbits-master-db.md) — `InstBits` base-bits 数据库(该联合体的 LLVM-MC 成员)、其全零默认表,以及 BarnaCore class field maps。
- [239-Bit Record Format](record-format.md) — `InstBits`/`TPUDescs` 表输入的 MC `APInt` record,以及 `opcode − 499` 索引。
- [MC-Emitter](mc-emitter.md) — `getBinaryCodeForInstr`,索引 `InstBits` 和 `TPUDescs` 的 consumer。
- [Immediate Slot](slot-immediate.md) — V5+ proto-bundle 编码器写入的逐代 immediate-slot ladders(`InstBits` **包含的 bits)。
- [TPUMCImm / SyImm32](tpumcimm-syimm32.md) — 通过相同后端表携带的 MC immediate operand。