TAC 引擎
本页中的每个地址、位偏移以及按代际划分的存在性声明,都是从
libtpu-0.0.40-cp314wheel(BuildID md589edbbe81c5b328a958fe628a9f2207d)里的libtpu.so按字节精确读取的,来源包括反混淆后的 C++ 符号表、嵌入的 proto 描述符字符串,以及反编译得到的逐槽Encoder::Encode函数体。其他版本会有所不同。
摘要
TAC,即 Tile Access Core,TpuSequencerType = 4,是 SparseCore 的 SCS / TAC / TEC 三引擎组合中的第三个成员。尽管它的 bundle 很宽,但能力范围最窄。SCS 是标量控制定序器,TEC 是宽向量引擎,而 TAC 是一个纯地址计算 + tile-fetch DMA 发起器:它接收一串 embedding 索引(由 SCS 产生,或由另一个 SC 的 stream 槽产生),并发出 gather DMA,把 embedding 行从 HBM/SPMEM 拉到每个 tile 的工作 SRAM(TILE_SPMEM)中,随后 TEC 在这些数据上计算。它有自己的定序器线程,包括分支、halt、delay、整数/地址算术、比较、谓词生成、用于地址暂存的 SMEM load/store、sync/atomic 协调以及一个 stream 槽,但没有 FPU 向量路径、没有向量 ALU、没有向量 load/store、没有 scan/sort/uniquify。在 embedding 流水线中,它位于“我需要哪些行”和“这些行现在已经在 tile SRAM 中”之间。
关于 TAC,最重要的事实是它并非存在于每一代。SparseCore 首次出现在 Viperfish(TPU v5p)上,采用 SCS+TAC+TEC 三引擎拆分;Ghostlite(TPU v6e)保留全部三个引擎;6acc60406 代(TPU v7x)完全移除了 TAC,把它的 tile-fetch 发起职责折叠进 SCS+TEC 组合中(SCS 计算 gather 地址,TEC 自己的 stream 槽发起 DMA)。这是直接的二进制读数,不是推断:6acc60406(gxc.gfc)命名空间中有零个 SparseCoreTac* 符号,也有零个 SparseCoreTac* 反编译函数;相比之下,Viperfish(vxc.vfc)和 Ghostlite(gxc.glc)各有约 930–950 个。为 6acc60406 目标发出 TAC 程序的重实现,会产生 codec 无法编码的东西。
TAC bundle 是 64 字节(512 位)的 VLIW word,物理宽度与 TEC bundle 相同,但它复用了 SCS bundle 的低位区域槽布局,并让高 320 位保持未写入。它把宽度花在许多并发的标量风格地址操作上,而不是向量计算上。本页记录该引擎的 codec/template 身份、64 字节 bundle 及其槽基地址的字节/位偏移(从每个逐槽 Encoder::Encode 内部的 BitCopy 目标立即数恢复)、它执行的操作清单(即 SCS 标量/stream 集合,并限制为地址子集),以及按代际划分的存在性和确认 6acc60406 = 0 的反编译计数。
对重实现而言,契约是:
- TAC 是
TpuSequencerType = 4,并且是独立的 codec。 它由SparseCoreTacCodecBase<…, TpuSequencerType=4>(LN3tpu16TpuSequencerTypeE4Etemplate 字面量)编码,只存在于vxc.vfc和gxc.glc下。dispatcher 会把同一个absl::Span<uchar>缓冲区交给每个逐槽 encoder,所以每个槽都写入绝对 bundle 位偏移。 - 64 字节 bundle 只使用 bits 3..191,也就是 SCS 低位区域(4×20 位立即数、vector-scalar bridge、scalar-misc 槽、两个 scalar-ALU lane,以及 Dma/Stream oneof-of-lane),另加 Stream 槽写入的两个 header 控制位(@3/3 和 @6/1)。512 位 bundle 的高 320 位不承载任何内容;TAC 没有向量槽需要填充。
- 操作集合是 SCS 标量 + stream 集合,而不是单独的 enum。 TAC 复用
SparseCoreScalarAlu/SparseCoreScalarMisc/SparseCoreStreamproto-enum 空间;合法性在 emit 期间由SparseCoreTacScalarAlu{0,1}Encoder/SparseCoreTacStreamEncoder类内部限制。不存在可枚举的SparseCoreTacScalarAluproto enum。 - 按代际存在性是契约的一部分。 Viperfish(v5p)和 Ghostlite(v6e)提供 TAC;
6acc60406(v7x)没有。应把这编码为强 codec-family 测试,而不是 flag。
| 引擎 | TAC — Tile Access Core(地址计算 + tile-fetch DMA 发起器) |
| 定序器 enum | tpu::TpuSequencerType = 4 (TPU_SEQUENCER_TYPE_SPARSE_CORE_TILE_ACCESS_CORE_SEQUENCER) |
| Codec 根 | SparseCoreTacCodecBase<…, TpuSequencerType=4>(位于 asic_sw::deepsea::{vxc.vfc, gxc.glc}::isa) |
| Bundle 大小 | 64 字节 / 512 位(BundleSizeBytes → codec-metadata vtable 槽 6)— 没有 check trailer |
| 活动区域 | bits 3..191(SCS 低位区域;Stream 槽还会写 header bits @3/3 和 @6/1);bits 192..511 未写入 |
| 槽清单 | 4×20 位立即数 · vector-scalar bridge · ScalarMisc · TacScalarAlu1 · TacScalarAlu0 · Dma / TacStream(lane 的 oneof) |
| 操作集合 | SCS SparseCoreScalarAlu / SparseCoreScalarMisc / SparseCoreStream enum,地址子集 |
| 计算路径 | 无 — 没有向量 ALU、没有向量 load/store、没有 scan/sort/uniquify |
| 存在于 | Viperfish / v5p (vxc.vfc) · Ghostlite / v6e (gxc.glc) — 不存在于 6acc60406 / v7x (gxc.gfc) |
| 置信度 | CONFIRMED(反编译 / BitCopy 立即数锚定),除非某行或标注另有说明 |
Codec 和定序器身份
用途
TAC 与 SCS 和 TEC 一样,由其 codec 上作为非类型模板参数携带的 tpu::TpuSequencerType 值选择。操作级别没有任何东西命名引擎;引擎分配由包围的 outlined function 上标记的 sc.sequencer 字符串属性("access")决定(见 Region → Sequencer Outliner),而下游读回的 codec template enum(4)会选择此 codec。
入口点
TpuSequencerType = 4 (TILE_ACCESS_CORE_SEQUENCER)
└─ SparseCoreTacCodecBase<SparseCoreTacBundle, TacScalarSubBundle,
SparseCoreTacScalarAlu0{Decoder,Encoder},
SparseCoreTacScalarAlu1{Decoder,Encoder},
SparseCoreScalarMisc{Decoder,Encoder},
SparseCoreTacStream{Decoder,Encoder},
SparseCoreDma{Decoder,Encoder},
SparseCoreVectorScalar{Encoder,Decoder},
SparseCoreScalarImmediates{Decoder,Encoder},
…, SparseCoreTacProgram, TpuSequencerType=4>
├─ Encoder<…>::EncodeBundle ── alloc 64 B, memset 0, dispatch each slot encoder
│ └─ each <Slot>Encoder::Encode(this, Message, absl::Span<uchar> buf) ── SAME buf to all
│ └─ BitCopy(dst=buf, esi=dst_bitoff, src, src_bitoff, r8d=nbits) ── LE bit packer
└─ Encoder<…>::BundleSizeBytes ── codec_metadata.vtable[+0x30]() → 64
```text
### Codec 模板参数列表
被混淆的 `SparseCoreTacCodecBase` 模板名本身就是 sub-bundle 清单;该 codec 精确枚举它必须驱动的槽 {Encoder,Decoder} 对。它从反混淆符号恢复而来(`…ELN3tpu16TpuSequencerTypeE4EE…` 后缀固定了整数字面量 `4` = TAC 定序器类型 enum 值):
| 槽 {Enc,Dec} 类 | 角色 | 它消费的 op-enum |
|---|---|---|
| `TacScalarSubBundle` | 两个标量 lane 的 wrapper |(结构性)|
| `SparseCoreTacScalarAlu0` | 标量/地址 ALU lane 0(TAC 变体) | `SparseCoreScalarAlu` |
| `SparseCoreTacScalarAlu1` | 标量/地址 ALU lane 1(TAC 变体) | `SparseCoreScalarAlu` |
| `SparseCoreScalarMisc` | scalar misc / sync / atomic 槽(与 SCS 共享) | `SparseCoreScalarMisc` |
| `SparseCoreTacStream` | stream 槽,即 tile-fetch DMA 发起器(TAC 变体) | `SparseCoreStream` |
| `SparseCoreDma` | DMA 发起槽(与 SCS 共享) | `SparseCoreDma` |
| `SparseCoreVectorScalar` | scalar→vector 值桥接槽(共享) | `SparseCoreVectorScalar` |
| `SparseCoreScalarImmediates` | 4× immediate-value 槽(共享) | `SparseCoreImmediates` |
> **NOTE — TAC 不声明任何向量槽。** 将此列表与 [TEC](tec-engine.md) codec 对比,后者还携带 `SparseCoreTecVectorAlu0/1/2`、`…VectorLoad`、`…VectorStore`、`…VectorExtended` 和 `…VectorResult`。TAC 模板中*没有*这些槽。该引擎在结构上是第二个带 stream 槽的标量定序器;它唯一“宽”的属性是 64 字节 bundle,而这个宽度承载的是许多并发的标量地址操作,不是向量计算。
### Bundle 大小 — `BundleSizeBytes`
`Encoder<…>::BundleSizeBytes` 读取 codec metadata 的槽 6(`vtable[+0x30]`)。对于 Viperfish(`EncoderVfSparseCoreTac::BundleSizeBytes` @ `0x1d2eebe0`),它尾调用 `codec_metadata.vtable[+48]()`;metadata 函数体证明了该值:
```c
function ViperfishCodecMetadata_BundleSizeBytesForHbm(this, seq): // 0x1ee71380
result = 32 // seq == 3 (SCS)
if seq != 3:
result = 64 // TAC or TEC
if (seq & 0xFFFFFFFE) != 4: // seq not in {4,5} → FATAL
LOG(FATAL) << "Unhandled component" // codec_metadata_viperfish.cc:31
return result(seq & 0xFFFFFFFE) != 4 掩码是按字节精确的来源:它只允许 seq ∈ {4, 5}(TAC、TEC)进入 64 字节分支,并让 seq == 3(SCS)进入 32 字节分支;其他任何值都是 fatal。因此 TAC(seq 4)= 64 字节,与 TEC 相同,不同于 32 字节的 SCS。与所有 SC bundle 一样,这里没有 0x55 check trailer(全零 bundle 表示“所有槽 inactive”)。
QUIRK — TAC 是唯一一个 64 字节宽但不承载计算的 SC 引擎。 如果重实现者从“它是不是 64 字节 bundle?”来确定缓冲区大小,就会因为假定存在并不存在的向量能力而过度配置 tile-fetch 程序。这个宽度用于标量地址操作并行性,也就是在一个 cycle 中执行多个独立的 index/stride/offset 计算并发起 DMA,而不是用于 64 字节 TEC bundle 所使用的向量槽。
TAC Bundle 槽基址图
用途
每个 TAC 槽 encoder 都从 dispatcher 接收同一个输出缓冲区 span,因此每个 BitCopy(dst, esi, …) 都写入一个绝对 bundle 位偏移。所以每个字段的目标位基址和宽度,就是每次 call BitCopy 之前的 mov esi,IMM / mov r8d,IMM 对。下图从 Ghostlite(gxc.glc)逐槽 encoder 恢复;Viperfish(vxc.vfc)按字节相同。Bundle = 64 字节 / 512 位;活动区域是 SCS 低位区域(标量/立即数栈位于 bits 7..191,Stream 槽另外写入两个 header 控制位 @3/3 和 @6/1),并且 bits 192..511 未写入。
槽图
| 槽 | base | end | width | opcode bit | 内部模板 |
|---|---|---|---|---|---|
| (header) | 0 | 6 | 7 | — | bundle prefix — 只有 Stream 槽在这里写入(@3/3、@6/1);其他槽让其保持零 |
ScalarImmediates | 7 | 86 | 80 | — | 4 × 20-bit(@7、@27、@47、@67) |
VectorScalar | 87 | 110 | 24 | — | scalar→vector bridge |
ScalarMisc | 111 | 137 | 27 | 127 | 27 位标量模板 |
TacScalarAlu1 (lane 1) | 138 | 164 | 27 | 154 | 27 位标量模板 |
TacScalarAlu0 (lane 0) | 165 | 191 | 27 | 181 | 27 位标量模板 |
Dma (oneof of lane) | 87 | 191 | — | 181 / 154 | 标量 opcode + payload @87..142 |
TacStream (oneof of lane) | 3 | 191 | — | 181 / 154 | 标量 opcode + payload @99..162,另有 header bits @3/3 和 @6/1 |
| (reserved / pad) | 192 | 511 | 320 | — | 未写入 — 无向量路径 |
三个标量槽(Misc @111、Alu1 @138、Alu0 @165)在 vector-scalar bridge 上方以 27 位间隔堆叠,与 SCS bundle 完全相同。这就是同一个低位区域布局:TacScalarAlu0 opcode @181、TacScalarAlu1 @154、ScalarMisc @127,与 SCS 的位位置相同。DMA 和 TacStream 槽不是单独的物理区域:它们是标量 lane 的 oneof alternatives(该 lane 承载 ALU op 或 Misc op 或 Dma op 或 Stream op),所以 Dma/Stream op 会把它的 opcode 写入标量 lane 的 opcode 字段(lane 0 为 @181,lane 1 为 @154),并借用较低的 bundle payload 来放置多字 descriptor。
27 位标量模板
每个标量槽的内部布局(slot-relative)如下,按位精确来自 TacScalarAlu0 @165;TacScalarAlu1 @138 和 ScalarMisc @111 的布局相同,只是整体 −27:
| 字段 | offset | width | 含义 |
|---|---|---|---|
| operand x0 | +0 | 5 | 标量寄存器选择器 |
| ScalarY | +5 | 6 | 标量寄存器或立即数选择器 |
| operand x1 | +11 | 5 | 标量寄存器选择器 |
| OPCODE | +16 | 6 | ≤ 64 个标量 op |
| normal_predication | +22 | 3 | SparsecoreNormalPredication |
| rotate_predication | +22 | 4 | is_rotate 时重叠(16-entry ring) |
| predication_inversion | +25 | 1 | |
| is_rotate_predication | +26 | 1 |
反编译交叉检查 — BitCopy 立即数
TacScalarAlu0Encoder::Encode(Ghostlite @ 0x1ea17e40)接收一个 SparseCoreScalarAlu message 和 bundle span;它的前导代码及各形式的 BitCopy 调用固定了每个偏移:
function TacScalarAlu0Encoder_Encode(this, msg /*SparseCoreScalarAlu*/, buf): // 0x1ea17e40
BitCopy(buf, 187, &msg[+32], 0, 4) // rotate_predication header @187/4 (= slot-base 165 +22)
BitCopy(buf, 191, &msg[+24], 0, 1) // is_rotate / inversion bit @191/1 (= +26)
switch (msg.opcode /* [+80] = the SCS ScalarAlu proto-enum TAG, not the wire opcode */):
case 0: return 1 // NoInstruction — leave slot empty
case 6: BitCopy(buf, 181, 0, 6) // 6-bit HW OPCODE @181 := 0 (tag 6 → wire op 0)
BitCopy(buf, 176, 0, 5) … // operand x1 / sub-selector region @176/5 (= +11)
case 7: BitCopy(buf, 181, 0, 6) // 6-bit HW OPCODE @181 := 0 (tag 7 = Delay)
BitCopy(buf, 176, 3, 5) // sub-selector := 3
BitCopy(buf, 165, …, 11) … // operand x0 / ScalarY @165 (= slot base)
case 8: BitCopy(buf, 181, 0,6); BitCopy(buf,176,8,5); BitCopy(buf,165,1,5) // tag 8 = SetTag
BitCopy(buf, 170, …, 6) … // ScalarY @170/6 (= +5)
… case 0x0A..0x5B: tail-call EncodeSparseCoreTacScalarAlu0<Op>(buf) // ~70 named proto tags
default: return MakeErrorImpl("Cannot find matching encoder for instruction: …")
```text
`TacScalarAlu1Encoder::Encode`(@ `0x1ea2a7a0`)是同一函数体下移一个 lane:OPCODE @154/6,operand-x1 区域 @149/5,槽基址 @138,谓词 header @160/4 + @164/1。`TacStreamEncoder::Encode`(@ `0x1ea338e0`)写入 OPCODE @181/6,并把它的 descriptor 分布在 bits 99..162(off-tile/indirect operand @105/5、@110/1、@104/1、@99/5;sync/list controls @154/1、@155/1、@156/1、@157/3、@160/1、@161/1;stream-opcode mirror @162/6),使用同样的 @187/4 + @191/1 谓词 header,并且作为 TAC 槽中唯一的例外,它还写入两个 **header 控制位 @3/3 和 @6/1**(在反编译中由 `BitCopy(a3, 3, …, 0, 3)` 和 `BitCopy(a3, 6, …, 0, 1)` 验证)。这些 header 位是 TAC 中 bit 87 以下唯一的写入;其他每个槽都从 bit 87 或更高处开始。
> **CONFIRMED — 没有 TAC 槽 encoder 写入 192 或更高的 bit。** 扫描 `TacScalarAlu0`(@1ea17e40)、`TacScalarAlu1`(@1ea2a7a0)、`TacStream`(@1ea338e0)以及共享的 `SparseCoreDmaEncoder`(@1ea09b40)里的 `BitCopy` 目标立即数后,任何 TAC 槽写入的最高目标位是 **191**(标量 lane 0 的 is-rotate 位),最低是 **3**(Stream 槽的 header 控制字段)。512 位 TAC bundle 的高 320 位是纯 padding,这是 TAC 没有向量路径并且只复用 SCS 低位区域加两个 stream-header 位的直接字节级证据。
>
> **GOTCHA — 槽 opcode 是共享的,槽含义按引擎决定。** `TacScalarAlu0` 的 opcode @181 占据与 SCS `ScalarAlu0` 的 opcode @181 *相同*的位字段,并且两者消费*相同*的 `SparseCoreScalarAlu` proto enum。重实现者无法仅从 bundle 位判断 SCS-vs-TAC;引擎由包围函数上的 `sc.sequencer` 属性(`"scs"` vs `"access"`)固定,并读回以选择 codec。bundle 与引擎无关;codec 选择不是。
---
## 操作清单
### 用途
TAC 执行 SCS 标量指令集的地址和控制子集,以及 stream 槽;它的全部职责就是计算 gather 地址并发起 tile-fetch DMA。它不携带单独的 opcode enum;它复用 SCS 的 `SparseCoreScalarAlu`、`SparseCoreScalarMisc` 和 `SparseCoreStream` proto-enum 空间,并在 emit 时由 `SparseCoreTac*Encoder` 类限制合法性。
### 操作类别
以下类别来自 `TacScalarAlu0Encoder::Encode` switch(`SparseCoreScalarAlu` proto-enum tags 0x06..0x5B,位于 `msg[+80]`)以及共享的 `SparseCoreScalarMisc` / `SparseCoreStream` / `SparseCoreDma` encoder。这些是 TAC 变体接受的 SCS 标量/stream op。下面括号中的十六进制值是 **proto-enum tag**(switch 判别值),不是发往 bundle bits @181 的 6 位 wire opcode;逐 op 的 `Encode<Op>` helper 会把每个 tag 重新编码为 6 位 OPCODE 字段外加 @176 的 sub-selector,因此多个 proto tag 可以共享 wire opcode `0`(例如上面的 tags 6/7/8):
| 类别 | 在 TAC 中? | 代表性 op(来自 encoder switch) |
|---|:---:|---|
| 控制流和分支 | Y | `BranchAbsolute` (0x4B), `BranchRelative` (0x4C), `BranchSreg` (0x4D), `BranchAbsoluteClearIbuf` (0x5B), `CallAbsolute/Relative/Sreg` (0x4E–0x50), `Delay` (0x07), `Halt` |
| 整数 / 地址 ALU(32 位) | Y | `IntegerAdd` (0x12), `IntegerSubtractYX` (0x14), `Multiply32BitIntegers` (0x52), `DivideWithRemainder*` (0x54–0x56), `BitwiseAnd/Or/Xor` (0x16–0x18), shifts (0x19–0x1C), `CountLeadingZeros` (0x22) |
| 比较 / 条件 | Y | `CompareInteger{Eq,Ne}` (0x2D–0x2E), `CompareSignedInteger*` (0x2F–0x32), `CompareUnsignedInteger*` (0x33–0x36), `CarryOutFromIntegerUnsigned` (0x37) |
| 谓词 | Y | `PredicateOr` (0x38) |
| 寄存器文件读取 | Y | `ReadRegisterSparseCoreId` (0x41), `ReadRegisterTileid` (0x42), `ReadRegisterTaskBitmap` (0x43), `ReadRegister{Gtc,Lcc}*`, `ReadRegisterTag/Tracemark`, `ReadRegisterDifDepthRegister` (0x45) |
| SMEM load/store(地址暂存) | Y | `ScalarLoadSmem*` / `ScalarStore*Smem*` / `ScalarLoadCircularBuffer`(共享 SCS 集合) |
| 可编程资源 | Y | `SetPrefetchDepth` (0x47), `SetIndirectFilterValue` (0x48) |
| Stack / pop | Y | `PopDrf` (0x3A), `PopRcmf` (0x3B) |
| Fence / sync | Y | `ScalarFence` (0x3C), `ScalarFenceScmf` (0x3D), `ScalarFenceStream{Spmem,Hbm}` (0x3E–0x3F), `ScalarFenceSelect` (0x40) |
| Misc / sync / atomic(ScalarMisc 槽) | Y | sync-flag + atomic-remote/tile 家族(`SparseCoreScalarMisc` enum,opcode @127) |
| **Stream — TAC 的主要工作** | Y | `TacStream`: `IndirectStream`, `IndirectVregStream`, `LinearStream`, `StridedStream` → tile-fetch DMA |
| DMA 发起 | Y | `SparseCoreDma`: `SimpleDma`, `SingleStridedDma`, `GeneralDma`(opcode @181) |
| 标量浮点 | partial | `MaxOfTwoFloatingPointValues` (0x1D), `MinOfTwoFloatingPointValues` (0x1E), `CompareFloatingPoint*` (0x25–0x2A), `FloatingPointMultiply` (0x51), `Convert{Int32ToFloat32,Float32ToInt32}` (0x10–0x11), `IsInfOrNan` (0x2B) 出现在 switch 中 |
| 向量 ALU / load / store / scan / sort | **N** | 没有对应槽 — codec 模板不携带向量 encoder |
> **NOTE — TAC 有标量 float op,但没有向量计算路径。** 反编译的 `TacScalarAlu0Encoder::Encode` switch 包含标量浮点 opcode case:float min/max(0x1D/0x1E)、float compare(0x25–0x2A)、`FloatingPointMultiply`(0x51)以及 int↔float convert(0x10/0x11),编码方式与整数 ALU op 相同。精确表述是:TAC **没有*向量* FPU,也没有向量计算路径**(没有 `VectorAlu`/`VectorLoad`/`VectorStore`/`VectorExtended` 槽)。硬件是否执行这些标量 float 形式,还是 encoder enum 只是接受它们,尚未确定(MEDIUM);每个*向量*槽都不存在这一点是字节精确的(CONFIRMED)。
### Tile-Fetch 角色
TacStream 槽是该引擎的操作核心。前向 embedding 流水线运行方式是:SCS 调度 tile-fetch 程序并计算 gather descriptor;**TAC 发起 stream-gather DMA** `HBM[table_base + index_i · row_stride] → TILE_SPMEM`;TEC 对驻留的 tile 执行 vector-load 并运行逐样本 reduction。TAC 是 SCS 定序器与 TEC 向量核心之间的专用地址处理器 + DMA 发起器,在架构上类似于 Pufferfish BarnaCore address-handler 相对 BarnaCore 的角色(见 [BarnaCore Overview](../barnacore/overview.md))。`STREAM_OPCODE_*` 集合和 gather/scatter descriptor 格式归 [Stream Gather/Scatter](stream-gather-scatter.md) 所有;TAC 与 SCS 共享的 scalar/misc opcode 清单归 [Scalar Opcode Enum](scalar-opcode-enum.md) 所有。
---
## 按代际存在性
### 用途
重实现者关于 TAC 必须编码的最重要事实,是*它何时存在*。SparseCore 是 v5+ 特性;在携带 SC 的代际中,TAC 存在于 Viperfish(v5p)和 Ghostlite(v6e),并在 `6acc60406`(v7x)上被移除。判别器是 codec class family;每个代号 family namespace 下是否存在 `SparseCoreTacCodecBase`,是直接的二进制读数。
### 清单表
| Gen | Codename | Family ns | TAC present | Tile-fetch issuer | Notes |
|---|---|:---:|:---:|---|---|
| TPU v5p | Viperfish | `vxc.vfc` | **Y** | TAC stream | 第一代三引擎拆分 |
| TPU v6e | Ghostlite | `gxc.glc` | **Y** | TAC stream | 完整 SCS+TAC+TEC |
| TPU v7x | `6acc60406` | `gxc.gfc` | **–** | TEC stream | **TAC removed** — 折叠进 SCS+TEC |
| earlier | Jellyfish / Dragonfish / Pufferfish | `jxc` / `pxc.pfc` | – |(无 SparseCore)| BarnaCore 时代 |
### 反编译交叉检查 — `6acc60406` TAC = 0
该清单直接对反编译函数集合和符号表确认。两个独立计数中,`6acc60406` 列均为零:
| 指标 | Viperfish (`vxc.vfc`) | Ghostlite (`gxc.glc`) | `6acc60406` (`gxc.gfc`) |
|---|---:|---:|---:|
| 反混淆后的 `<ns>::isa::SparseCoreTac*` 符号(`nm -C`) | 838 | 860 | **0** |
| 文件名中名为 `SparseCoreTac*` 的反编译函数 | 932 | 952 | **0** |
`gfc`(`6acc60406`)命名空间中有**零个** `SparseCoreTac*` 反编译函数和零个 `SparseCoreTac*` 符号,而 Viperfish 和 Ghostlite 各有约 840–950 个(两种计数方式不同,是因为单个反编译函数文件可以多次携带该符号,而 `nm` 计数按符号计算)。不存在 `gxc.gfc` `SparseCoreTacCodecBase` 类,不存在 `SparseCoreTacScalarAlu*Encoder`,不存在 `SparseCoreTacStreamEncoder`,也不存在 `SparseCoreTacProgram` proto。对应的 `SparseCoreTacGFSchedModelSchedClasses` LLVM 表也不存在;只有 `SparseCoreTacVF*`/`SparseCoreTacGL*` sched model,而 SCS 和 TEC 都携带 `VF`/`GL`/`GF` 三元组。TAC 已从 `6acc60406` 硅片中完全消失。
> **CONFIRMED — `6acc60406` 将 3 引擎流水线压缩为 2 个。** 在 Viperfish/Ghostlite 上,路径是 SCS → TAC(tile-fetch DMA)→ TEC(compute)。在 `6acc60406` 上,TAC 消失:TEC 自己的 stream 槽(`IndirectStream` / `IndirectVregStream` / `LinearStream` / `StridedStream`)吸收地址生成 + DMA 发起职责,SCS 计算 gather 地址(由 TEC 通过 `tile_wait_scs_smem` 消费),而新的 SCS op `BranchRelativeRotatingPreg` / `SetRotatingPredicateRegister` 以及 TEC 的 `TileSpmemLoadCircularBufferPostUpdate` 支持内层循环 tile-fetch dispatch,此前它需要 TAC 的单独定序器。结果是单个 SCS↔TEC 边界、更低硅面积以及更低延迟的 tile-fetch,代价是 TEC bundle 更重,因为它现在同时发起计算和 DMA。
### Outliner — “access” 函数来自哪里
引擎分配是字符串属性,不是 op 上的数值 enum。`TileTaskOutliningPass` 遍历每个 `sc_tpu.tile_task` op,把 body outline 成一个 `func.func`,并标记 `sc.sequencer`。在 `6acc60406` 上,它只为 tile body 标记 `"execute"`(TEC),并为包围的控制程序标记 `"scs"`;没有 `"access"`。在 Viperfish/Ghostlite 上,同一个按 Target 参数化的 pass 会额外生成 `"access"`(TAC)函数。`"access"` 值字符串以及把它映射到 `TpuSequencerType=4` 的读回谓词都位于 outliner 中;在携带 TAC 的代际上,精确的逐 op Access-vs-Execute 拆分规则没有被穷尽位追踪(`GetTransferKind` 的 `kStream`/`kDma` 结果以及 op 数据依赖会输入该规则)。见 [Region → Sequencer Outliner](region-to-sequencer-outliner.md) 和 [getSequencerType](getsequencertype.md)。
> **QUIRK — C++ `TpuSequencerType` enum 在 codec 和 geometry 之间共享;只有 *proto* enum 不同。** 本页和 SC-ISA 页面使用 C++ `TpuSequencerType` 编号 `{3 = SCS, 4 = TAC, 5 = TEC}`(codec 模板中携带的字面量;`…E4E` = TAC,已在混淆后的 `SparseCoreTacCodecBase` 符号中验证)。硬件 geometry descriptor [`SparseCoreTarget`](architecture.md#the-sparsecoretarget-map-target0x948) 由 `tpu::TpuCoreParts` 支撑,它是一个 `EnumMap<TpuSequencerType, Sequencer, 6>`(6-slot array,`TpuCoreParts` ctor @ `0x20b29e40`),并按这个**相同** C++ enum 索引 core-parts:[architecture page](architecture.md) 把逐芯片 tile 数读作 `SequencerCount(seq-type 5 = TEC)`,与 codec 编号一致。因此重实现者可以统一用 `{3,4,5}` 进行 codec 选择*和* `TpuCoreParts` 查找。唯一的 off-by-one 是 **protobuf** enum `TpuSequencerTypeProto`(`{4 = SCS, 5 = TAC, 6 = TEC}`,其中 `INVALID=0`),`TpuSequencerTypeFromProto` 在任何内存内使用之前都会执行 subtract-one 转换为 C++ enum;见 [getSequencerType](getsequencertype.md)。
---
## 相关组件
| 名称 | 关系 |
|---|---|
| `SparseCoreTacCodecBase<…, TpuSequencerType=4>` | TAC codec — 驱动每个 TAC 槽 encoder(仅 VF/GL) |
| `TacScalarAlu0Encoder::Encode` (`0x1ea17e40` glc) | 标量 lane-0 槽 encoder;opcode @181,`BitCopy` 立即数来源 |
| `TacStreamEncoder::Encode` (`0x1ea338e0` glc) | tile-fetch DMA 发起器槽 encoder;opcode @181,payload @99..162 |
| `ViperfishCodecMetadata::BundleSizeBytesForHbm` (`0x1ee71380`) | 证明 TAC(seq 4)= 64 字节 |
| `TileTaskOutliningPass` | 在 VF/GL outlined function 上标记 `sc.sequencer = "access"`(TAC) |
| `SparseCoreScalarMiscEncoder` (`0x1ea46f00` glc) / `SparseCoreDmaEncoder` (`0x1ea09b40` glc) | TAC 与 SCS 按字节相同共享的槽 |
## 交叉引用
- [SparseCore Overview](overview.md) — Part IX 的导航入口;引擎名称、按代际存在性和数据路径。
- [SparseCore Hardware Architecture](architecture.md) — engine→core 布局、四层内存模型和 geometry-descriptor enum 偏移。
- [SCS (Scalar) Engine](scs-engine.md) — 标量控制定序器;TAC 复用其低位区域 bundle 布局。
- [TEC (Vector) Engine](tec-engine.md) — 宽向量引擎,消费 TAC 拉取的 tile,并在 `6acc60406` 上吸收 TAC 的角色。
- [Per-Engine Bundle Slot-Base Map](bundle-slot-base-map.md) — 完整的 SCS/TAC/TEC 槽基址分区,本页从中抽取 TAC 列。
- [Region → Sequencer Outliner](region-to-sequencer-outliner.md) — 标记 `sc.sequencer = "access"` 以把函数分配给 TAC 的 pass。
- [getSequencerType](getsequencertype.md) — SCS/TAC/TEC 引擎选择 accessor 和 `TpuSequencerType` enum。
- [Scalar Opcode Enum](scalar-opcode-enum.md) — `SparseCoreScalarAlu` / `SparseCoreScalarMisc` 清单;TAC 将其限制到地址子集。
- [Stream Gather/Scatter](stream-gather-scatter.md) — `STREAM_OPCODE_*` 集合和 TacStream 发出的 gather/scatter descriptor。
- [SC Backend Pipeline](sc-backend-pipeline.md) — SC-MLO offload pass pipeline,用于 outline 并 lower 每引擎 bundle stream。
- [SC EmitX Dispatcher](sc-emitx-dispatcher.md) — seq3/seq4/seq5 → EmitX jump table,路由到每引擎 codec。
- [BarnaCore Overview](../barnacore/overview.md) — 已退役的 embedding accelerator;TAC 映射其 address-handler。
- **二进制:** `extracted/libtpu-0.0.40-cp314-cp314-manylinux_2_31_x86_64/libtpu/libtpu.so`(build-id `89edbbe81c5b328a958fe628a9f2207d`)
- **索引条目:** Part IX — SparseCore & BarnaCore / SparseCore engines — [返回索引](../index.md)