Fat Pointers (AS7/8/9)
本页中的每个地址、偏移和值都逐字节精确地读取自
libtpu-0.0.40-cp314wheel 中的libtpu.so(构建libtpu_lts_20260413_b_RC00,BuildID md589edbbe81c5b328a958fe628a9f2207d)。其他版本会不同。
摘要
本页记录 SparseCore (SC) 指针表示,以及 libtpu.so 中并存的两套指针编号方案:TPU DataLayout 中声明的 AS7/AS8/AS9 “胖指针”保留区,以及后端实际使用的 SparseCore 地址空间 ID 表。首要结论是一个负面结论,并且对重新实现至关重要:160/128/192 位的 AS7/8/9 胖指针是继承来的 AMDGPU 样板,没有任何 TPU 或 SparseCore op 会构造它们。 它们原样出现在 TPU data-layout 字符串中,是因为 TPU TargetMachine 共享 LLVM 的 AMDGPU buffer-fat-pointer ABI 片段,而且二进制里甚至带着 AMDGPU 针对它们的诊断信息;但在整个 SC MLIR-lowering、SC IR-emitter 和 jellyfish LLO-emitter 中,传给 LLVMPointerType::get / PointerType::get 的地址空间只有 0x00 以及 0xC9..0xE1 / 0x1F5 / 0x1F6 这个 SparseCore 区间。这两个编号空间完全不相交。
需要丢弃的心智模型,是来自 AMDGPU 的读者会自然带来的那一个:SparseCore 地址是一个 160 位结构,把 {descriptor, core/chip, offset} 打包进 AS7 胖指针的位中。事实并非如此。SparseCore 指针至多是一个 64 位 LLVM 指针,其寄存器内值携带 32 位 word offset:0xCA/0xC9/0xCB/0xCC 地址空间不在 DataLayout 的 p 列表中,所以它们采用默认的 p:64:64 表示,而在它们之间重新打标签的 addrspacecast 会降低为类型为 MVT::i32 的保值 SDNode。AS7 保留区看起来应当携带的路由信息,也就是哪个 core/chip、哪个 tile,实际上作为独立 SSA 操作数传递:跨芯片 remote cast 使用 destination-id 操作数,on-tile TEC cast 使用 tpu_tileid 操作数。
本页分三部分。第一,AS7/8/9 胖指针保留区,包括三种格式是什么、AMDGPU ABI 为它们定义的逐字段位布局,以及 TPU 构建只是死继承这些内容的字节证据。第二,SparseCore 地址空间 ID 表,包括跨三个数值区间的 20 个带描述 ID、每个 ID 的后备内存池和 on-tile/off-tile 语义,它们从三个互逆的 switch/table 函数恢复而来。第三,实际的 SparseCore 指针表示,包括 64 位/32 位 word-offset 模型、为什么 tile 和 core 路由是操作数而不是指针位,以及一个指针的地址空间整数如何流经 lowering。MLIR MemorySpaceCast 到 llvm.addrspacecast 的转换见 addrspacecast ISel;on-tile 的 2 操作数 tile-id cast lowering 见 Tile-ID Cast;本页负责的是表示和 AS-id 表。
对重新实现而言,契约是:
- 不要实现 AS7/8/9 构造器。 没有 SparseCore op 会物化 160/128/192 位指针。该保留区在此构建中是死的;如果重新实现从
DataLayout的p7/p8/p9条目出发,会去寻找一个并不存在的构造器。 - SparseCore 指针是 64 位 LLVM ptr(默认表示),携带 32 位 word-offset 值。 地址空间编号应从
{0, 201..225, 501, 502}分配,绝不要从{7, 8, 9}分配。这两个范围必须保持不相交。 - 精确复现 AS-id 表。 ID → 人类可读描述 →
MemorySpace枚举 → 池名称 → on/off-tile,包括六个保留空洞(206,207,209,210,221,222)、两个无池的 "Any" 别名超集(211 SflagAny,225 SflagAnySynctile),以及两个存活但无描述的 ID(215 simem,220 mar),这些都从AddressSpaceDescription/AddressSpaceToMemorySpace/MemorySpaceToAddressSpace恢复而来。 - 将 tile 和 core 路由作为操作数携带,而不是作为指针位。 TEC 和 TAC tile-id cast 是 2 操作数
{base, tileId}(二者都声明NOperands<2>);SCS/TC/plain cast 是 1 操作数{base}(OneOperand)。判别依据是 sequencer 的操作数元数,而不是指针。
| TPU DataLayout | 单一实例 @ 0x973de15,由 Triple::computeDataLayout (0x1DAF4380) 发出 |
| AS7/8/9 片段 | p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32 … ni:7:8:9(AMDGPU ABI,原样) |
| TPU/SC 代码中的 AS7/8/9 构造器 | 无 — 任何 SC/jellyfish 区段中都没有 …PointerType::get(7/8/9) |
| SC address-space 方案 | 0x00 + 0xC9..0xE1 + 0x1F5/0x1F6(与 {7,8,9} 不相交) |
| AS-id 描述 switch | LlvmTpuDialect::AddressSpaceDescription (0x135462C0) — 基数 201,跨度 24,另有 ID 0 / 501 / 502 分支 |
| ID → MemorySpace | AddressSpaceToMemorySpace (0x14B78800);反向 MemorySpaceToAddressSpace (0x14B78780,表 0xAF36CE8,掩码 0x3FFF7F) |
| On-tile 分类器 | IsOffTileMemory (0x13D7AC00) = (ms & ~0x10) != 2 — 仅 MS 2 / 18 为 on-tile |
| SC pointer 寄存器内值 | MVT::i32 32 位 word offset(re-tag 保值;LowerADDRSPACECAST @ 0x13B70592) |
| Tile/core 路由 | 独立 SSA 操作数(tpu_tileid i32 / destination-id),绝不是指针位 |
AS7/8/9 胖指针保留区
目的
TPU TargetMachine 从 llvm::Triple::computeDataLayout (0x1DAF4380) 的 TPU 分支构建它的 DataLayout,该分支生成位于 0x973DE15 的字符串单一实例。这个字符串大部分是常规内容,即 64 位默认指针、32 位 p2/p3/p5/p6、64 位 p1/p4,但它还携带了三个并非 TPU 原生的高位指针类别:
e-m:e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-
p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-
i64:64- … -n32:64-S32-A5-G1-ni:7:8:9
```text
`p7:160:256:256:32 / p8:128:128:128:48 / p9:192:256:256:32 / ni:7:8:9` 片段与 LLVM 的 **AMDGPU** target `DataLayout` 逐字节相同。在 AMDGPU 中,这三个空间属于 *buffer fat pointer* 家族:AS7 是 buffer fat pointer(128 位 `V#` resource descriptor 加 32 位 offset = 160 位),AS8 是裸 buffer resource("V#",128 位,48 位 index,即 "45-bit num_records" 诊断所指),AS9 是 buffer strided pointer(192 位)。`ni:7:8:9` 标记声明三者都是**非整数型**:它们不能通过 `ptrtoint`/`inttoptr` 与整数互转,原因正是它们的位是结构化 descriptor,而不是平坦地址。
这个片段之所以存在于 TPU layout 中,原因是来源:TPU 后端构建在同一个带有 AMDGPU 的 LLVM 中,buffer-fat-pointer lowering 机制也被编译进来。二进制携带 AMDGPU pass `AMDGPULowerBufferFatPointers` (`0x11999BA0`) 及其诊断信息的原文:`"global variables with a buffer fat pointer address space (7) are not supported"` 和 `"Use buffer resource pointers (address space 8) instead"` 都出现在该 pass 的函数体中。**这些内容都不能从 SparseCore codegen 到达。** 它们是死保留区,重新实现者可以忽略,但必须知道它们的存在,以免把它误认为 SC 指针模型。
### 三种格式
下面的逐字段布局是 AMDGPU ABI 对每个空间的定义;TPU 构建原样继承。`DataLayout` 四元组是以位为单位的 `size:abi-align:pref-align:index-width`。
| AS | `p` 条目 | 大小 | Index 宽度 | AMDGPU 角色 | 字段布局 (AMDGPU ABI) |
|---|---|---|---|---|---|
| 7 | `p7:160:256:256:32` | 160 bit | 32 bit | buffer **fat pointer** | 128-bit buffer resource (`V#`) + 32-bit offset |
| 8 | `p8:128:128:128:48` | 128 bit | 48 bit | buffer **resource** ("V#") | 128-bit descriptor; 48-bit index ⇒ "45-bit num_records" |
| 9 | `p9:192:256:256:32` | 192 bit | 32 bit | buffer **strided pointer** | 128-bit `V#` + 32-bit index + 32-bit stride |
> **GOTCHA —** 这三行描述的是 AS7/8/9 **如果**被构造出来,其位*会*表示什么。在 `libtpu` 0.0.40 中它们从未被构造。宽度和字段布局是逐字节相同的 AMDGPU ABI,二进制也带有匹配的 AMDGPU 诊断;TPU 构建把它们当作惰性保留区,任何位置都没有 TPU 构造器(见下一节)。不要把它们实现为 SparseCore 指针格式。
### 负面结论 — 没有 TPU 构造器
“没有 TPU op 构建 AS7/8/9 指针”这个断言是指令级负面结论。在这个代码库中物化 MLIR/LLVM 指针类型的方式,是调用 `LLVMPointerType::get(ctx, AS)` (`0x1746EB40`) 或 `PointerType::get(ctx, AS)` (`0x1DA72640`),并在调用前立即把地址空间字面量放入 `esi`/`edx`。扫描三个相关代码区段中的每一个此类调用点,即 SC MLIR-lowering 区段(`0x13500000..0x135D0000`)、SC IR-emitter 区段(`0x13800000..0x13E00000`)以及 jellyfish LLO-emitter 区段(`0x1D400000..0x1D800000`),地址空间参数**只会**出现在 `{0x00, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xD3}` 中。`7`、`8` 或 `9` 的出现次数为**零**。AMDGPU buffer-fat-pointer 诊断和 `ni:7:8:9` 标记解析到 `AMDGPULowerBufferFatPointers` 与通用 LLVM pass,而非任何 TPU 专用内容。
SparseCore 后端*确实*构建的唯一结构化指针聚合体是 `CircularBufferDescriptor`,这是一个 2 元素 LLVM struct `{CbReg, MemRefDescriptor}`,用 `mlir::StructBuilder` 组装;其中 `CbReg` 半边是一个作为 128 位 opaque CBREG 句柄复用的 `LLVMPPCFP128Type` 单例。它是由 SC CBREG 寄存器文件支撑的一等 struct 值,**不是**胖地址空间中的指针,也不触碰 AS7/8/9 保留区。(CBREG 窗口本身是下表中的 `0x1F5`/`0x1F6` 地址空间区段。)
> **NOTE — 保留区不是 TPU 结构化指针。** 很容易把 AS7/8/9 保留区解读成跨 core 寻址的 `{core/chip, space, offset}` 打包。字节证据否定了这一点:没有构造器,格式是死的 AMDGPU 样板,而 cross-core / cross-tile 路由走独立 SSA 操作数,即 remote cast 的 destination-id 操作数和 on-tile cast 的 `tpu_tileid` 操作数,绝不是指针位。
---
## SparseCore 地址空间 ID 表
### 目的
SparseCore 指针携带一个**数值地址空间 ID**,这个 ID,而不是任何指针位字段,命名该指针指向哪个物理内存池,以及它是在 tile 上可达,还是需要 DMA/stream/sync 才能到达。ID 空间通过三种相互一致的方式恢复:`AddressSpaceDescription` switch 将 ID 映射到人类可读字符串,`AddressSpaceToMemorySpace` 将 ID 映射到 `MemorySpace` 枚举,`MemorySpaceToAddressSpace` 是精确反函数。三者在 ID 上完全一致。`MemorySpace` 枚举是规范的 SparseCore 内存池枚举(22 个值,从 1 开始,值 8 是未使用空洞);其池名称来自 `stringifyMemorySpace`。
### 入口点
```text
LlvmTpuDialect::AddressSpaceDescription(int) (0x135462C0) ── ID → human string (the authority below)
├─ base 201, jump-table span 24 (IDs 201..225)
└─ explicit arms for ID 0, 501, 502; reserved IDs fall through to "Unknown"
AddressSpaceToMemorySpace(uint) (0x14B78800) ── ID → MemorySpace enum (IDs 201..224)
MemorySpaceToAddressSpace(MemorySpace) (0x14B78780) ── MemorySpace → ID (reverse table 0xAF36CE8, mask 0x3FFF7F)
stringifyMemorySpace(MemorySpace) (0x14B78240) ── MemorySpace → pool name
IsOffTileMemory(MemorySpace) (0x13D7AC00) ── (ms & ~0x10) != 2 → on-tile gate
GetAnyTypeFromAddressSpace(int) (0x1357B400) ── concrete ID → "Any" may-alias superset三个区段
20 个带描述的 ID 落在三个数值区段中,它们从 AddressSpaceDescription switch 逐字节恢复:
- ID 0 — 继承的基底
Smem(标量内存,MemorySpace 1)。这是唯一与常规 LLVM default-AS 区域重叠的 SC ID;switch 的default分支只会对0返回"Smem"。 - IDs 201..225 — SparseCore 专用区段(基数
0xC9)。25 个槽位中,17 个命名后备池,2 个(211,225)命名无池的别名组,6 个(206,207,209,210,221,222)是既无池也无描述的保留空洞。另有两个(215/220)携带存活的MemorySpace(simem,mar)但没有描述字符串,所以AddressSpaceDescription会在它们上 fall through。 - IDs 501, 502 — 两个 circular-buffer 空间(
0x1F5/0x1F6),处于独立高位区段,支撑 CBREG 窗口。
AddressSpaceDescription 的函数体足够小,可以精确确认:对于 ID > 500,它返回 "TileSpmem Circular Buffer" (501) 或 "Smem Circular Buffer" (502);对于 201..225,它切换到下面的名称;无描述 ID(206,207,209,210,215,220,221,222)return 当前结果 "Unknown";而 default 分支对 ID 0 返回 "Smem"。
完整表
MS# 是 MemorySpace 枚举值(从 1 开始;0 = 没有规范池,即别名组)。tile? 是 IsOffTileMemory == false,只有 MS 2 和 MS 18 为 true。
| ID | hex | 描述 | MS# | 池 | tile? | 备注 |
|---|---|---|---|---|---|---|
| 0 | 0x00 | Smem | 1 | smem | off | 基础 TPU 标量内存 |
| 201 | 0xC9 | TileSpmem | 2 | tile_spmem | ON | 每 tile SC SRAM (KB) |
| 202 | 0xCA | Spmem | 3 | spmem | off | 芯片共享 SC SRAM (MB) |
| 203 | 0xCB | HBM | 4 | hbm | off | 全局 (GB) embedding tables |
| 204 | 0xCC | Sflag | 5 | sflag | off | sync-flag 内存(也包括 MS 22 sflag_tc) |
| 205 | 0xCD | Vmem | 6 | vmem | off | TC vector memory(handoff) |
| 206 | 0xCE | (reserved) | 0 | — | — | 空洞 |
| 207 | 0xCF | (reserved) | 0 | — | — | 空洞 |
| 208 | 0xD0 | Dreg | 7 | dreg | off | data-register window |
| 209 | 0xD1 | (reserved) | 0 | — | — | 空洞 |
| 210 | 0xD2 | (reserved) | 0 | — | — | 空洞 |
| 211 | 0xD3 | SflagAny | 0 | — (alias) | off | sflag may-alias superset |
| 212 | 0xD4 | SmemAny | 9 | smem_any | off | smem may-alias superset |
| 213 | 0xD5 | HBMAny | 10 | hbm_any | off | hbm may-alias superset |
| 214 | 0xD6 | Timem | 11 | timem | off | 每 tile instruction memory |
| 215 | 0xD7 | (no desc → "Unknown") | 12 | simem | off | SC instruction memory † |
| 216 | 0xD8 | IOVA | 13 | iova | off | I/O virtual address |
| 217 | 0xD9 | SflagTile | 14 | sflag_tile | off | 每 tile sflag bank |
| 218 | 0xDA | SpmemAny | 15 | spmem_any | off | spmem may-alias superset |
| 219 | 0xDB | TileSmem | 16 | smem_tile | off | 每 tile SMEM |
| 220 | 0xDC | (no desc → "Unknown") | 17 | mar | off | memory-access-region † |
| 221 | 0xDD | (reserved) | 0 | — | — | 空洞 |
| 222 | 0xDE | (reserved) | 0 | — | — | 空洞 |
| 223 | 0xDF | SflagScs | 20 | sflag_scs | off | 每 SCS sflag bank |
| 224 | 0xE0 | SmemScs | 21 | smem_scs | off | 每 SCS SMEM |
| 225 | 0xE1 | SflagAnySynctile | 0 | — (alias) | off | sflag-any-synctile(无池) |
| 501 | 0x1F5 | TileSpmem Circular Buffer | 18 | tile_spmem_cb | ON | CBREG-windowed TILE_SPMEM |
| 502 | 0x1F6 | Smem Circular Buffer | 19 | smem_cb | off | CBREG-windowed SMEM |
NOTE — † ID 215 (
simem) 和 220 (mar) 携带有效MemorySpace(12 和 17),但AddressSpaceDescription没有它们的分支,并返回 fall-through 的"Unknown",这是此构建中的 description-switch 空洞。它们的池名称是来自stringifyMemorySpace的规范名称;ID 本身是存活的,并且可以干净地通过AddressSpaceToMemorySpace映射。MemorySpace 22(sflag_tc) 与 MS 5 一起复用 ID 204,所以反向表dword_AF36CE8中有一个 AS(0xCC)被两个MemorySpace值共享(条目 5 和 22)。
On-Tile 与 Off-Tile
IsOffTileMemory (0x13D7AC00) 是一行代码:return (a1 & 0xFFFFFFEF) != 2;,也就是 (ms & ~0x10) != 2。清除 bit 4 会把 MS 18(tile_spmem_cb,CBREG 别名)折叠到 MS 2(tile_spmem)上,所以只有两个 on-tile MemorySpace:tile_spmem 及其 circular-buffer 别名。其他一切,即 HBM、SPMEM、SMEM、SFLAG、VMEM、DREG、TIMEM、IOVA、MAR 和各 per-SCS bank,都是 off-tile,需要 DMA、stream 或 sync 才能到达。这个单一 bit-test 是 DMA 和 stream lowering 查询的访问语义门槛,也正是 TEC 需要 tile-id cast 的原因:它要把 on-tile TileSpmem (201) 指针转换成 execute-lane 寻址可用的 off-tile-addressable Spmem (202) 指针。
"Any" May-Alias 超集
五个 ID,即 211 SflagAny、212 SmemAny、213 HBMAny、218 SpmemAny 和合成的 225 SflagAnySynctile,是 alias-analysis 通配符:当指针的确切 tile 或 core 静态未知时,SparseCore LLVM 后端会给它分配 may-alias 超集。三者(212/213/218)携带专用 *_any 池(MemorySpace 9/10/15,池 smem_any/hbm_any/spmem_any);另外两个(211 SflagAny 和 225 SflagAnySynctile)完全不携带 MemorySpace,AddressSpaceToMemorySpace 对它们返回 0,因此它们是没有物理池的纯别名分组。GetAnyTypeFromAddressSpace (0x1357B400) 会把具体 ID 规范化为其通配符:
201 TileSpmem → 218 SpmemAny 205 Vmem → 205 Vmem (self; no wildcard)
202 Spmem → 218 SpmemAny 219 TileSmem → 212 SmemAny
203 HBM → 213 HBMAny 0 Smem → 212 SmemAny
204 Sflag → 211 SflagAny
```text
在已经是通配符的空间上,或在没有超集的叶子空间(Dreg, Timem, IOVA, SflagTile)上调用 `GetAnyTypeFromAddressSpace` 会 `LOG(FATAL)`;这些是叶子空间或已经规范化的空间。
---
## 实际的 SparseCore 指针表示
### 宽度与寄存器内值
SC 地址空间 ID(`0xC9`/`0xCA`/`0xCB`/`0xCC`/…)都没有出现在 `DataLayout` 的 `p` 列表中,所以每个都继承**默认 `p:64:64`**,即 64 位指针表示。但 SparseCore 指针携带的*值*是 32 位 SparseCore **word offset**:在 SelectionDAG 中,`TPUTargetLowering::LowerADDRSPACECAST` (`0x13B70480`) 会发出一个保值的自定义 `SDNode`(opcode `0xF3`,设置于 `0x13B70592`),其 `EVT = MVT::i32`(`0x13B70597` 处 `ecx = 0x7`,其中 `0x7` 是 `MVT::i32` 枚举值)。辅助诊断也一致:`"No GEP instruction on HBM address space allowed. On TPU, HBM pointers are at least full 32-bit."` (`0x9FF4DD5`),而 `SpmemAlignment` (`0x13DC5500`) 通过把每 SC 字节数除以 4 来计算 *word* 对齐。因此 SparseCore 指针至多是一个 64 位 LLVM ptr,其有意义内容是 32 位 word offset,绝不是 160/128/192 位 struct。
> **QUIRK —** re-tag 是保值的。两个 SC 空间之间的 `addrspacecast` 不改变 offset 值;它只改变附着在 64 位指针上的地址空间整数(并且在 tile-indexed TEC/TAC 情况下附加一个 tile-id 操作数)。`LowerADDRSPACECAST` 生成 `SDNode 0xF3 / MVT::i32`,携带相同的 word offset 输入和相同的 word offset 输出。重新实现者不能把 cast 建模为地址的算术变换;它是纯 tag 变更,加一个带外路由操作数。
### 每 AS 字段布局 — 路由是操作数,不是位
因为指针是没有结构化字段的平坦 32 位 word offset,胖指针通常会打包进位中的路由信息,改由建立该路由的 cast 上的**独立 SSA 操作数**携带。路由有两个维度,且每个都有自己的操作数:
```text
SparseCore pointer = ⟨ 64-bit LLVM ptr (default repr) ; AS-id ∈ {0, 0xC9..0xE1, 0x1F5/0x1F6} ⟩
value = 32-bit word offset (MVT::i32)
routing is NOT in the pointer bits — it rides as paired operands on the cast:
┌─ tile-indexed (TEC / TAC, per-tile execute lanes) ─────────────────────────┐
│ cast = tpu_addrspacecast_{spmem,smem,tec,…tec,tac} → 2 operands │
│ operand 0 = base ptr (TileSpmem 0xC9 …) │
│ operand 1 = tpu_tileid (i32 from the STILEID hardware register read) │
└────────────────────────────────────────────────────────────────────────────┘
┌─ singular-per-core (SCS / TC / plain) ─────────────────────────────────────┐
│ cast = tpu_addrspacecast{,_scs,_tc,…scs} → 1 operand │
│ operand 0 = base ptr (no tile id — these lanes are singular per core) │
└────────────────────────────────────────────────────────────────────────────┘
┌─ cross-chip (remote) ─────────────────────────────────────────────────────┐
│ the destination-id / remoteCoreId operand on the remote DMA / get_remote │
│ descriptor carries the {device, core, id} routing (not a pointer field) │
└────────────────────────────────────────────────────────────────────────────┘元数分裂就是实际存在的每 AS “字段布局”:它编码在 cast op 的操作数数量中,并由 …::create 构造器签名逐字节确认(mangled 名中的 S6_ = 第二个 Value 操作数;没有它 = 一个操作数)。tpu_addrspacecast_tec::create (0x146D69C0) 的签名是 (OpBuilder, Location, Type, Value, Value),并发出两次 addOperands 调用,即 operand 0 = base ptr、operand 1 = tile id,最后添加结果 Type。tpu_addrspacecast_scs::create (0x146D5F80) 和 plain tpu_addrspacecast::create (0x146D5EA0) 接受单个 Value 并发出一次 addOperands。tile-id 源是 tpu_tileid::create (0x149883A0),签名 (OpBuilder, Location, Type),有零个 Value 操作数,因为它读取 SparseCore 标量 TID 寄存器(STILEID.VRES / stileid.u32),而不是消费一个值。
| Cast 家族 | 构造器 | 操作数 | Tile id? | Sequencer |
|---|---|---|---|---|
tpu_addrspacecast (plain) | 0x146D5EA0 | 1 {base} | no | generic |
tpu_addrspacecast_scs | 0x146D5F80 | 1 {base} | no | SCS |
tpu_addrspacecast_tc | 0x146D68E0 | 1 {base} | no | TC |
tpu_addrspacecast_tac | — (NOperands<2>) | 2 {base, tileId} | YES | TAC |
tpu_addrspacecast_smem | 0x146D6500 | 2 {base, tileId} | YES | TEC |
tpu_addrspacecast_spmem | 0x146D67E0 | 2 {base, tileId} | YES | TEC |
tpu_addrspacecast_tec | 0x146D69C0 | 2 {base, tileId} | YES | TEC |
tpu_tileid (the i32 source) | 0x149883A0 | 0 (register read) | — | — |
QUIRK — 2 操作数与 1 操作数的分裂完全由 sequencer 决定,而不是由源/目标地址空间决定。两个 tile-indexed lane,即 TEC 和 TAC,都声明
NOperands<2>并携带 tile id;singular-per-core lane(SCS、TC 和 plain cast)声明OneOperand,并且不携带。这是因为 tile-indexed lane 寻址 per-tileTileSpmem,因此需要运行时 tile-select;singular sequencer lane 在没有 per-tile index 的情况下寻址其内存。完整 16-cast 名单、from→to AS 映射和 lowering 函数体见 addrspacecast ISel 与 Tile-ID Cast;本页只记录为什么路由是操作数而不是指针位。
地址空间整数流
SC op 在其 memref attribute 上携带的 MemorySpace 枚举,会由 MemorySpaceToAddressSpace (0x14B78780) 转换成 LLVM 地址空间整数:它用 bitmask 0x3FFF7F 验证 ms - 1 <= 0x15(用 "Unsupported memory space" LOG(FATAL) 拒绝 MS-8 空洞和越界值),然后返回 dword_AF36CE8[ms - 1],这是一个 22 条目的表,是 AddressSpaceToMemorySpace 的精确反函数。因此数据路径是:SC op MemorySpace attr → LLVM address-space ID(此表)→ 带该 AS 的 64 位 LLVM 指针 → 默认 p:64:64 表示 → ISA 上的 32 位 word-offset 值。没有任何阶段构造 160/128/192 位胖指针,也没有任何阶段让地址空间 ID 离开 {0, 201..225, 501, 502} 区段。
相关组件
| 名称 | 关系 |
|---|---|
AddressSpaceDescription (0x135462C0) | 本页枚举的 AS-id → name 表的权威来源 |
MemorySpaceToAddressSpace (0x14B78780) | MemorySpace → AS-id 正向映射(指针的地址空间整数) |
IsOffTileMemory (0x13D7AC00) | 驱动 tile-id-cast 要求的 on-tile/off-tile 门槛 |
tpu_tileid::create (0x149883A0) | 作为 TEC cast 第 2 个操作数输入的 i32 tile-id 源 |
AMDGPULowerBufferFatPointers (0x11999BA0) | 拥有(未使用)AS7/8/9 保留区及其诊断的 AMDGPU pass |
交叉引用
- SparseCore 概览 — Part IX 的导航入口;engine 名称、逐代存在性,以及指针所处的数据路径。
- SparseCore 硬件架构 — SPMEM ↔ TILE_SPMEM 的物理拆分,以及这些地址空间命名的四层内存模型。
- addrspacecast ISel — IR
MemorySpaceCast→llvm.addrspacecast转换,以及完整的 16-cast from→to AS 映射。 - Tile-ID Cast — on-tile 2 操作数
{base, tileId}cast lowering,以及 tile id 如何作为标量寄存器操作数到达 lowered TileSpmem load/store。 - Stream Gather/Scatter — 根据这些地址空间 ID 分派以选择 embedding gather/scatter intrinsic 的 stream lowering。
- Binary:
extracted/libtpu-0.0.40-cp314-cp314-manylinux_2_31_x86_64/libtpu/libtpu.so(build-id89edbbe81c5b328a958fe628a9f2207d) - 索引条目: Part IX — SparseCore & BarnaCore / SparseCore pointers & DMA — 返回索引