Skip to content

地址空间 ID 表(AS0–AS225/501/502)

本页中的每个 ID、MemorySpace 编号和池名称,都是从 libtpu-0.0.40-cp314 wheel 中 libtpu.so(BuildID md5 89edbbe81c5b328a958fe628a9f2207d)里的 SparseCore LLVM lowering 函数按字节精确解码得到的。其他版本会有所不同。

摘要

LLVM 后端中的 SparseCore 指针携带一个数值型 地址空间 ID,也就是 !llvm.ptr<N> 中的整数 N。不同于典型 GPU 后端使用紧凑的 AS0..AS5 编号,SparseCore LLVM 方言使用稀疏的分段 ID 空间:0 表示继承的标量内存,201..225(基址 0xc9)表示 SparseCore 专用池及其别名组,501/5020x1f5/0x1f6)表示两个环形缓冲区窗口。每个 ID 都 1:1 映射到一个从 1 开始的 mlir::sparse_core::MemorySpace 枚举值,而该枚举值又命名一个物理(或虚拟/别名)内存池:smemtile_spmemspmemhbmsflagvmemdregtimemsimemiovamar、按 tile/按 SCS 的变体,以及可能别名的 *_any 超集。

ID 是 LowerToSparseCoreLlvm pass 将 ScDialect memref 操作数路由到叶子 tpu_* intrinsic 的方式:DMA 和 stream lowering 按 (srcMemSpaceID, dstMemSpaceID) 对分派,而 addrspacecast lowering 通过比较两个 ID 转换出的 LLVM 指针类型,来省略或发出 llvm.addrspacecast。这张表通过三条彼此独立且一致到 ID 级别的路径恢复出来:正向 AddressSpaceDescription(ID)→string switch、AddressSpaceToMemorySpace(ID)→MemorySpace jump table,以及反向 MemorySpaceToAddressSpace(MemorySpace)→ID 表。

对重新实现者的约定是:为每个 SparseCore 指针标上其池对应的 ID;用一行 IsOffTileMemory 掩码区分 on-tile 与 off-tile;当精确 tile/core 在静态上未知时,为别名分析规范化到 *Any 超集。

ID 分段0(基础 Smem);201..225 = 0xc9..0xe1(SC 池 + 别名组);501/502 = 0x1f5/0x1f6(CB 窗口)
命名 ID22 个(201 分段中的 19 个 + ID 0 + 501 + 502);6 个保留/空洞槽位(206、207、209、210、221、222)
MemorySpace 枚举22 个枚举槽位(从 1 开始,最大 0x16);21 个有效,值 8 是未使用空洞(空名称,无 AS)
正向(ID→name)mlir::sparse_core::LlvmTpuDialect::AddressSpaceDescription(int) @ 0x135462c0
正向(ID→MS)mlir::sparse_core::AddressSpaceToMemorySpace(uint) @ 0x14b78800
反向(MS→ID)mlir::sparse_core::MemorySpaceToAddressSpace(MemorySpace) @ 0x14b78780
池名称(MS→str)mlir::sparse_core::stringifyMemorySpace(MemorySpace) @ 0x14b78240
On-/off-tileIsOffTileMemory(MemorySpace) @ 0x13d7ac00 = (ms & ~0x10) != 2
别名规范化GetAnyTypeFromAddressSpace(int) @ 0x1357b400
可信度除非单元格另有标注,否则均为 CONFIRMED

主 AS-ID 表

AS# 是 LLVM 地址空间整数(!llvm.ptr<N> 中的 N)。Region/poolstringifyMemorySpace(MS#)MS#MemorySpace 枚举值(从 1 开始;0 = 无规范池)。Width 是该池覆盖的寻址尺度:每 tile 为 KB、芯片共享为 MB、全局为 GB。tile?IsOffTileMemory==false,仅 MS 2 和 MS 18 为 true。notes 中的 ✓ 表示 ID↔MS 映射已由反向 MemorySpaceToAddressSpace 表确认。

AS#hexRegion / poolMS#Widthtile?含义 · 可信度
00x0smem1KBoff继承的基础 TPU 标量内存 ✓
2010xc9tile_spmem2KBON每 tile SparseCore SRAM ✓
2020xcaspmem3MBoff芯片共享 SparseCore SRAM ✓
2030xcbhbm4GBoff全局 HBM(embedding 表)✓
2040xccsflag5off同步标志内存 ✓(MS 22 sflag_tc 也映射到这里)
2050xcdvmem6MBoffTensorCore 向量内存(TC↔SC 交接)✓
2060xce0保留 / 空洞
2070xcf0保留 / 空洞
2080xd0dreg7off数据寄存器窗口 ✓
2090xd10保留 / 空洞
2100xd20保留 / 空洞
2110xd3— (alias)0offSflagAny 可能别名超集(无池)
2120xd4smem_any9offSmemAny 可能别名超集 ✓
2130xd5hbm_any10offHBMAny 可能别名超集 ✓
2140xd6timem11off每 tile 指令内存 ✓
2150xd7simem12offSC 指令内存 ✓ †
2160xd8iova13GBoffI/O 虚拟地址 ✓
2170xd9sflag_tile14off每 tile sflag bank ✓
2180xdaspmem_any15offSpmemAny 可能别名超集 ✓
2190xdbsmem_tile16KBoff每 tile SMEM(TileSmem)✓
2200xdcmar17offmemory-access-region ✓ †
2210xdd0保留 / 空洞
2220xde0保留 / 空洞
2230xdfsflag_scs20off每 SCS sflag bank(SflagScs)✓
2240xe0smem_scs21KBoff每 SCS SMEM(SmemScs)✓
2250xe1— (alias)0offSflagAnySynctile(无池)
5010x1f5tile_spmem_cb18KBONCBREG 窗口化的 TILE_SPMEM
5020x1f6smem_cb19KBoffCBREG 窗口化的 SMEM

某行上的 表示该 ID 的池名称只来自 stringifyMemorySpace,而非 AddressSpaceDescription(见下面的 GOTCHA)。

命名 ID 的 descAddressSpaceDescription)字符串按 case 顺序为:TileSpmemSpmemHBMSflagVmemDregSflagAnySmemAnyHBMAnyTimemIOVASflagTileSpmemAnyTileSmemSflagScsSmemScsSflagAnySynctile;ID 0 返回 Smem;501/502 返回 "TileSpmem Circular Buffer" / "Smem Circular Buffer";其他全部返回 "Unknown"

GOTCHA — ID 215simem)和 220mar)携带真实的 MemorySpace(12 和 17),但 AddressSpaceDescription 会为它们返回空默认值——它们落入与真正保留空洞相同的 case 206/207/209/210/215/220/221/222: return result 分支。池名称 simem/mar 来自 stringifyMemorySpace,而不是 description switch。只从 AddressSpaceDescription 派生名称的读取器会错误地把 215/220 当作保留项。


后端如何标记指针

LlvmTpuDialect 不为每个池声明单独的“指针类型”。相反,上面的地址空间整数就是 LLVM 指针类型 !llvm.ptr<N> 中的 N,而 ScDialect memref 通过 memref 属性携带其 MemorySpace。lowering 将其转换为 LLVM AS 编号,并将它用作分派键:

text
ScDialect op (memref with MemorySpace attr)
  → AddressSpaceToMemorySpace / MemorySpaceToAddressSpace  (ID ↔ MS, 1:1)
  → getStridedElementPtr → !llvm.ptr<AS#>                  (raw element pointer)
  → DMA/stream lowering dispatch on (srcAS, dstAS)         (selects tpu_* intrinsic)
```text

`AddressSpaceToMemorySpace(uint)` 是覆盖 ID `201..224` 并带有显式 `501→18` / `502→19` 分支的 jump table;其 `0x1_0000000N` 返回值的低 32 位就是 `MemorySpace` 枚举。`MemorySpaceToAddressSpace(MemorySpace)` 是精确反函数:它索引 `dword_AF36CE8[ms-1]`,并受范围检查 `ms-1 > 0x15`(拒绝 `ms > 22`)和有效性掩码 `0x3fff7f` 约束,后者以 `(0x3fff7f >> (ms-1)) & 1` 测试——`0x3fff7f` 有 **21 位被置位**(21 个有效 MemorySpace 值;bit 7 清零,即值 8 被拒绝)。`stringifyMemorySpace` 和 `TpuVersionToString` 都是指针表查找(`off_219AF590[ms-1]` 和 `off_22011BF0[ver]`,都从 1 开始),其字符串指针位于 `.data.rel.ro`,并在加载时由 `R_X86_64_RELATIVE` 重定位填入——它们在磁盘镜像中读作零(已确认:`off_219AF590` 的每个槽位在磁盘上都是 `0x0`;解析 RELATIVE 重定位后得到 `smem`、`tile_spmem`、…、`sflag_tc`)。

---

## On-Tile 与 Off-Tile(访问语义门控)

`IsOffTileMemory(MemorySpace)` 是一个单独的带掩码比较:

```c
bool IsOffTileMemory(int ms) { return (ms & 0xFFFFFFEF) != 2; }   // (ms & ~0x10) != 2

清除 bit 4(0x10)会把 MS 2(tile_spmem)和 MS 18 = 0x12tile_spmem_cb)折叠到一起,因此只有这两个是 on-tile。其他每个池——hbmspmemsmemsflagvmemdregtimemsimemiovamar,以及所有 *_tile/*_scs/*_any 变体——都是 off-tile,需要通过 DMA、stream 或 sync 才能到达。这就是 DMA 和 stream lowering 在选择数据移动 intrinsic 前查询的谓词。


*Any 可能别名规范化

当指针的精确 tile 或 core 在静态上未知时,SparseCore LLVM 后端会将其拓宽到通配 *Any 空间,以供别名分析使用。GetAnyTypeFromAddressSpace(int) 是规范化器:

具体 ID(名称)→ 规范 ID(名称)
201 TileSpmem, 202 Spmem218 SpmemAny
203 HBM213 HBMAny
204 Sflag211 SflagAny
205 Vmem205 Vmem(自身——没有单独的通配符)
219 TileSmem, 0 Smem212 SmemAny

*Any ID(211/212/213/218)携带 description,但没有 MemorySpace 池——它们是别名分析分组,不是物理池。对已经是通配空间或叶子空间(DregTimemIOVASflagTile*Any ID 自身)调用 GetAnyTypeFromAddressSpace 会命中 LogFatal("Unsupported address space: ") 分支(llvm_tpu_dialect_only.h:100),因此该规范化器只在上面的具体空间上是全函数。

NOTE — *Any 拓宽是 SparseCore 对 fat-pointer 问题的回答:指向 HBM/SPMEM 且所属 tile 为运行时值的指针,无法证明与另一个同类指针不相交,因此后端为两者都分配 HBMAny/SpmemAny 超集,并让别名分析把它们视为 may-alias。具体空间与 Any 空间的区别,让静态解析出的 tile-local 访问不会被悲观化。


交叉验证与 CheckAddressSpaces

四个访问器构成一个闭合的自检系统:

text
AddressSpaceDescription(ID)   : ID → human string      @0x135462c0
AddressSpaceToMemorySpace(ID) : ID → MemorySpace        @0x14b78800
MemorySpaceToAddressSpace(MS) : MemorySpace → ID (inv)  @0x14b78780
stringifyMemorySpace(MS)      : MemorySpace → pool name  @0x14b78240
```text

对全部 21 个命名 ID,正向和反向 ID↔MS 映射都是精确反函数(已逐分支对照反编译 switch 验证)。`CheckAddressSpaces(SparseCoreTarget&, Operation*, int, int)` @ `0x135b8e00` 是 lowering 在发出数据移动 intrinsic 之前,用来针对目标验证 `(src, dst)` ID 对的 verifier;它的完整合法性矩阵(每个 primitive 允许哪些 pair)此处未枚举——这里只确认其存在和签名。

---

## 相关组件

| 名称 | 关系 |
|---|---|
| `LowerToSparseCoreLlvm` pass | 读取这些 ID,将 memref 操作数路由到 `tpu_*` intrinsic |
| `MemorySpaceCastOpLowering` @ `0x135a5c20` | 通过比较转换后的指针类型来省略/发出 `llvm.addrspacecast` |
| `DmaSimpleStartOpLowering` / `LinearStreamStartOpLowering` | 按 `(srcAS, dstAS)` / `(dtype, off-tile MS, verb)` 分派 |
| `getStridedElementPtr` | 将 memref+index 转成原始 `!llvm.ptr<AS#>` |

## 交叉引用

- [内存层级](memory-hierarchy.md) — 这些池所填充的 HBM/VMEM/SMEM/SFLAG/CMEM 分层模型
- [内存空间枚举](../isa/memory-space-enum.md) — `MemorySpace` 枚举:22 个槽位,21 个有效(值 8 为空洞)
- [Fat Pointers (AS 7/8/9)](../sparsecore/fat-pointers-as789.md) — SparseCore fat-pointer 编码与 `*Any` 超集关系
- [addrspacecast ISel](../sparsecore/addrspacecast-isel.md) — 针对这些 ID 的 `llvm.addrspacecast` 省略或发出规则
- [Tile-ID Cast](../sparsecore/tile-id-cast.md) — 具体 tile-local AS 如何拓宽为其 `*Any` 规范形式
- [SC Type Converter](../compiler/sc-type-converter.md) — `SCTypeConverter` 将 `MemorySpace` memref 属性映射到 `!llvm.ptr<AS#>` 的方式
- [Lower To SparseCore LLVM](../compiler/lower-to-sparsecore-llvm.md) — 消费这些 ID 并将 memref 操作数路由到 `tpu_*` intrinsic 的 pass