SMEM 寄存器窗口
本页中的每个符号、偏移和地址都从
libtpu-0.0.40-cp314wheel 中的libtpu.so逐字节读取而来(构建libtpu_lts_20260413_b_RC00,build-id md589edbbe81c5b328a958fe628a9f2207d)。该镜像未剥离;反混淆后的 C++ 符号名均逐字引用。.textVA 等于文件偏移0xe63c000;.rodataVA 等于文件偏移0x84a0000。其他版本会有所不同。
摘要
"SMEM register-window" 这个短语并没有命名 libtpu.so 中的任何东西。在该二进制的 2.9M 个字符串或 1.2M 个符号里,都不存在 SmemRegisterWindow、SregWindow、RegisterWindow、WindowBase、window_base、reg_window 或 SmemSpillRegister 这样的符号或字符串。本页用于回答这个短语暗含的问题:"是否有一个 SMEM 窗口像 SPARC 寄存器窗口或旋转 ISA 寄存器文件那样映射到标量寄存器文件中?" 答案是没有。SPU 标量寄存器文件是一个扁平的、受硬件边界限制的 32 项文件,使用 5 位索引,没有 base/size 窗口寄存器,没有 bank 选择器,没有 overflow/underflow trap。SMEM 是它的溢出后备存储,通过普通的标量 load/store opcode 访问(SMEM 标量内存),而不是通过窗口映射访问。
实际存在的东西,也就是听到 "SMEM register-window" 的重实现者很可能被指向的东西,是三个各自命名的机制,其中没有一个会给 SREG 文件开窗口。它们中的两个确实给内存开窗口(其中一个可以位于 SMEM);第三个给谓词寄存器开窗口。最贴近该短语的机制是 CBREG(circular-buffer register):单个寄存器持有一个指向片上内存的 {base, offset, size} 窗口,并产生自动前进、末尾回绕的地址流。CBREG 是包含内存窗口的寄存器,正好是"寄存器上的窗口"的反向。
本页是内存子系统的消歧说明。它给出否定结论(SREG 文件没有窗口,SMEM 没有寄存器窗口机制),列举三个真实的 "window",说明每个实际给哪类资源开窗口,并展示它们分别如何与 SMEM 相关。CBREG opcode 位布局由 CBREG 循环缓冲寄存器负责,SPU slot 字段网格由 SPU / 标量 Slot负责,标量谓词文件由 谓词 Slot负责,SMEM 分配器由 SMEM 标量内存负责。
对重实现而言,契约是:
- 否定结论就是架构。 重实现不得为 SREG 文件分配 window-base/window-size 寄存器对,不得实现 SPARC 风格的窗口 overflow/underflow trap,并且必须像
libtpu一样显式地把 SREG 压力 spill 到 SMEM(LSRA-v2)。SREG 索引是 5 位;共有 32 个;这就是整个文件。 - "Register window" 在三类资源上被重载使用。 CBREG
{base,offset,size}内存窗口(持有内存窗口的寄存器)、流水线OperandWindow(暂存在 VMEM / SMEM / HOST 中的张量操作数子 tile),以及旋转谓词文件(TPU 上唯一真正的硬件"寄存器上的窗口")。交付物就是知道哪一个是哪一个。 - SMEM 关联是真实的,但都是间接的。 SMEM 会出现在 CBREG 可能的地址空间中,会作为
OperandWindow的合法放置位置,也会作为 fixed-window pipeline emitter 中动态窗口大小的可选存储;但这些情况没有任何一个把窗口映射到标量寄存器文件之上。
| SREG 文件(被错误称为有 "window" 的对象) | 扁平 32 项,5-bit 索引;边界由 ProtoUtils::EncodingToScalarRegister @ 0x1e871e40 强制执行(idx > 0x1F → error) |
| SREG bank 名称(没有窗口化变体) | SC_SCS_SREGS, SC_TAC_SREGS, SC_TEC_SREGS (.rodata) — 不存在 ROTATING/WINDOWED/BANKED SREG bank |
| CBREG(持有内存窗口的寄存器) | banks SC_{SCS,TAC,TEC}_CBREGS_{BASE,OFFSET,SIZE};16/sequencer;详情 → cbreg.md |
| 流水线 OperandWindow(内存子 tile) | xla::jellyfish::SetWindowParams(…OperandWindow&, Shape const&, mlir::MemRefType, …) @ 0x112658a0;space tag 存在 OperandWindow +0x4C1 |
| OperandWindow space tag | 0x3 = kVmem, 0x5 = kSmem, 0xD = HOST(从 SetWindowParams 读取) |
| 旋转 PREDICATE 窗口(真正的寄存器窗口) | banks SC_SCS_ROTATING_PREGS, SC_TEC_ROTATING_PREGS;后端 gate TPUGfcSubtarget::hasRotatingPredicates() @ 0x13c62c20 = 1(仅 6acc60406) |
| SREG overflow 处理 | 软件 spill 到保留 SMEM(LSRA-v2);没有硬件窗口,没有 overflow trap |
| 否定搜索 | 0 hits: SmemRegisterWindow / SregWindow / RegisterWindow / WindowBase / window_base / reg_window / SmemSpillRegister; 0 TPU hits: window_overflow / window_underflow / register_window_trap |
| 置信度 | CONFIRMED(字节锚定),除非某行或标注另有说明 |
1. 问题与否定结论
目的
有经典架构背景的读者看到 "SMEM register-window" 时,会把它理解成两种熟悉事物之一:(i) SPARC 风格的大物理寄存器文件滑动窗口,把寄存器的一个窗口映射到架构名 r0..r31,并有硬件 save/restore trap 由内存 spill 区支撑;或 (ii) 旋转寄存器文件(IA-64 风格),其中架构寄存器名会按每次循环迭代前进的窗口基址进行偏移。两者都可以叫作"映射到标量寄存器文件中的内存/寄存器窗口"。TPU 上两者都不存在。
二进制说明了什么
SPU 标量寄存器文件是扁平的。把 ScalarYEncoding 操作数转换为物理 SREG 索引的编码器 platforms_deepsea::jellyfish::isa::ProtoUtils::EncodingToScalarRegister(0x1e871e40)会拒绝任何大于 0x1F 的索引:
// EncodingToScalarRegister @ 0x1e871e40 (decompiled, condensed)
if ( a2 > 0x1F ) // index >= 32 is illegal
return InvalidArgument( // absl::Status, not a trap; proto_utils.cc:917
"Input is not a valid register encoding. "
"Input must be in the range [%d, %d]", 0, 31);
return /* flat index a2 */; // status OK, payload = flat index a2
```text
架构 SREG 正好有 32 个,用 5 位字段寻址;没有 window-base 寄存器加到索引上,也没有 bank 选择器来扩大名称空间。SparseCore register-bank 分类从另一个方向确认了这一点:标量 bank `SC_SCS_SREGS`、`SC_TAC_SREGS`、`SC_TEC_SREGS` 存在于 `.rodata` 中,而对任何 `SC_*_ROTATING_SREGS` / `SC_*_WINDOWED_SREGS` / `SC_*_BANKED_SREGS` bank 的搜索都返回 **zero** hits。谓词 bank *确实*有旋转变体(§4);标量 bank 没有。
> **NOTE —** [内存概览](overview.md) §1 用一句话说明了这一点:"'register window' is a misnomer for every on-chip tier here. SMEM, CMEM, and SFLAG are all flat byte/word arrays … Scalar register windowing lives on the SREG file (allocated by LSRA-v2), and SMEM is merely its spill backing store." 本页就是该句背后的证明和枚举。
### 缺失是穷尽性的
该短语的字面拼写已经在整个二进制中搜索过,均不存在:
| 搜索 token | `libtpu.so` 中的 hits | 含义 |
|---|---|---|
| `SmemRegisterWindow`, `SregWindow`, `SmemRegisterFile`, `SmemSpillRegister` | 0 | 没有命名任何 windowed-SMEM register file |
| `RegisterWindow`, `RegWindow`, `WindowBase`, `window_base`, `reg_window` | 0 | 没有任何类型的 register-window primitive |
| `window_overflow`, `window_underflow`, `register_window_trap`, `save_restore_window`, `spill_window`, `fill_window` | 0 TPU(只有 `zlib_rs::deflate::fill_window`,无关) | 没有 SPARC 风格的 window-trap 机制 |
唯一的 `fill_window` hit 属于静态链接的 `zlib_rs`,与寄存器无关。overflow/underflow/trap token 的缺失是决定性证据:窗口化寄存器文件*需要* spill/fill 机制,而这个机制根本不存在。
### 注意事项
重实现者应得到的是过程性结论,而不只是描述性结论。因为 SREG 文件是扁平且无 trap 的,超过 32 个 live value 的 SREG 压力由编译器解决,而不是由硬件解决。LSRA-v2 分配器会 spill 到保留的 SMEM 区域(`FLAGS_xla_jf_lsra_v2_reserved_smem` @ `0x223afaa8`);被 spill 的 SREG 会变成写入该区域的 `ScalarStoreSmem*`,以及之后读回的 `ScalarLoadSmem*`。load/store opcode 家族见 [SMEM 标量内存](smem-scalar-memory.md)。不存在硬件 fast-path:一次 spill 的成本是两个显式标量内存操作,编译器负责最小化它。
---
## 2. CBREG — 持有内存窗口的寄存器
### 目的
最符合"a register that windows memory" 这一*意图*的机制是 SparseCore **CBREG**(circular-buffer register)。它反转了 SPARC 思路:不是把一个内存窗口映射*进*寄存器名称空间,而是单个寄存器*持有*一个滑动内存窗口,并发出回绕地址流。这只是 v5+ SparseCore 特性(Viperfish `vfc`、Ghostlite `glc`、`6acc60406` `gfc`);JF/DF/PF 没有 CBREG。
### 机制
CBREG 由三个子寄存器组成:`{base, offset, size}`。它们物理上存放在三个独立硬件 bank 中,但通过 4 位 CBREG 索引作为一个寄存器寻址。所有三个 SparseCore sequencer 的 bank 名称都出现在 `.rodata` 中:
```text
SC_SCS_CBREGS_BASE SC_SCS_CBREGS_OFFSET SC_SCS_CBREGS_SIZE
SC_TAC_CBREGS_BASE SC_TAC_CBREGS_OFFSET SC_TAC_CBREGS_SIZE
SC_TEC_CBREGS_BASE SC_TEC_CBREGS_OFFSET SC_TEC_CBREGS_SIZEbase 是指向片上内存的窗口化指针(地址空间,即 SMEM vs TILE_SPMEM,在写入 base 时固定);size 是 offset 回绕时使用的模数;offset 是当前位置。一次访问会读取或写入 base + (offset mod size)。…PostUpdate 访问变体还会在访问后推进 offset = (offset + step) mod size,即经典的 circular-buffer auto-increment。没有 modulo 指令;回绕是 OFFSET 计数器的属性,"overflow" 按设计就是回绕,从不是 trap。
驱动 CBREG 的 scalar-ALU opcode 在反编译的 emitter glue 中得到确认:
| Op(符号片段) | 动作 | 确认位置 |
|---|---|---|
SparseCoreScalarAlu_ReadCbreg | 将 CBREG 子字段读入 SREG | scalar-ALU op set (gfc/glc/vfc) |
SparseCoreScalarAlu_WriteCbreg | 将 SREG 写入 CBREG 子字段 | scalar-ALU op set |
SparseCoreScalarAlu_AddCbreg | 给 CBREG offset 加 delta | scalar-ALU op set |
SparseCoreScalarAlu_MoveCbreg | 复制 CBREG(仅 gfc) | scalar-ALU op set |
SparseCoreScalarAlu_ScalarLoadCircularBuffer | load base+(offset mod size) | isa_emitter::EmitScalarLoadOrStoreFromCb<…SparseCoreScsBundle…> @ 0x13a5e560; …TacBundle… @ 0x13a03d60 |
SparseCoreScalarAlu_ScalarStoreCircularBuffer | store 到窗口化地址 | EmitScalarLoadOrStoreFromCb<…> @ 0x13a5e8e0 |
SparseCoreScalarAlu_ScalarLoadCircularBufferPostUpdate | load,然后推进 offset(回绕) | EmitScalarLoadOrStoreFromCb<…> @ 0x13a5e3a0 |
SparseCoreScalarAlu_ScalarStoreCircularBufferPostUpdate | store,然后推进 offset(回绕) | EmitScalarLoadOrStoreFromCb<…> @ 0x13a5e720 |
EmitScalarLoadOrStoreFromCb 模板按 SparseCore sequencer bundle 类型实例化(SparseCoreScsBundle、SparseCoreTacBundle 和 TEC bundle),因此相同的四种 circular-buffer load/store 形态会在不同地址重复出现:每个引擎一套。
面向编译器的表面
XLA 通过 LLVM intrinsic 和 MLIR dialect 驱动 CBREG,二者都以字符串/符号形式存在于二进制中:llvm.tpu.allocate.cbreg 分配一个;llvm.tpu.cbreg.add.offset[.in.place](MLIR sc_tpu.advance_cb_offset[_in_place])推进窗口;llvm.tpu.rdcbreg.offset / llvm.tpu.rdcbreg.size(MLIR tpu_rdcbreg_offset create @ 0x14734820)读取当前位置和模数。lowering 在 SparseCore pipeline emitter(§3)内部构造这些操作,使一个 tile 在一个自动递增的寄存器窗口控制下流过片上循环缓冲。
CROSS-REF — CBREG
{base,size,offset}子寄存器选择器(CbregMetadata= {0=BASE,1=SIZE,2=OFFSET})、精确的 scalar-ALU 位布局(opcode 位于 bundle bit 154;操作数 slot 位于 slot-relative bits 10/15/21),以及每个 op 的 opcode 值(Read=0x36,Write=0x35,Add=0x33,Moveprimary0x00/sub0x1b)归 CBREG 循环缓冲寄存器所有。opcode 名册位于 SCS 标量 Opcode 枚举;gather/scatter 消费者位于 Stream Gather/Scatter。本页只确定 CBREG 是持有内存窗口的寄存器,而不是寄存器上的窗口。
注意事项
重实现者必须保持方向正确。CBREG 占用一个专用硬件寄存器三元组,而不是 SREG slot;ReadCbreg/WriteCbreg 在 SREG 和 CBREG 子字段之间移动。它描述的窗口位于 SMEM 或 TILE_SPMEM 中,模数由软件设置;如果底层缓冲区太小,lowering 会报错(min_circular_buffer_byte_count,circular_buffer_size 默认 1000)。CBREG 是 SparseCore 的地址流生成器;对于 embedding datapath,它类似 NIC 的 DMA descriptor ring。
3. 流水线 OperandWindow — 可位于 SMEM 的内存子 Tile
目的
第二个同时出现 "window" 和 "SMEM" 的机制是流水线 OperandWindow:张量操作数的滑动子 tile,由编译器暂存在片上内存空间中以供流水线 kernel 使用。这是 "SMEM window" 最字面的解读:可以请求一个 OperandWindow 位于 SMEM 中;但它是缓冲区窗口,不是寄存器窗口。
机制
在 TensorCore fusion/conv 侧,窗口由 xla::jellyfish::SetWindowParams(PipelineEmitter::OperandWindow&, Shape const&, mlir::MemRefType, …) @ 0x112658a0 配置(源文件 platforms/xla/mosaic/python/mosaic_windowing_util.cc)。反编译函数从操作数的 MemRefType 读取 MLIR memory-space 属性,并映射为存储在 OperandWindow + 0x4C1(+1217)处的单字节 space tag:
// SetWindowParams @ 0x112658a0 (decompiled, condensed)
MemorySpace = mlir::MemRefType::getMemorySpace(&memref);
attr = (MemorySpaceAttr) MemorySpace;
Value = attr ? mlir::tpu::MemorySpaceAttr::getValue(attr) : 0;
if (Value == 0) v99 = 3; // (null attr) -> kVmem
else if (Value == 1) v99 = 5; // -> kSmem
else if (Value == 6) v99 = 13; // -> HOST
else // -> reject
return xla::InvalidArgument(
"Operand windows can only be requested in VMEM, SMEM, or HOST");
*(uint8_t *)(operand_window + 1217) = v99; // store space tag at +0x4C1
```text
因此合法放置位置是 tag `0x3`(`kVmem`)、`0x5`(`kSmem`)和 `0xD`(HOST);任何其他 MLIR memory space 都是编译期 `absl::InvalidArgument`。同一函数中的两个相邻诊断进一步钉住了模型:`"Scalar windows not implemented."`(拒绝 scalar-shaped window)和 `"An output window does not have a memory space assigned."`(未赋值的 output window)。
第二个兄弟家族位于 SparseCore 侧:`xla::tpu::sparse_core::OperandWindow` 和 `PipelineEmitterInterface::OperandWindowDescription`,由 `FixedWindowPipelineEmitter`(FWPE)和 `VariableWindowPipelineEmitter`(VWPE)物化。它们的窗口缓冲区通常落在 SPMEM。请求窗口的 MLIR 属性是 `window_params`,由诸如 "expected %d window_params based on the number of inputs and outputs" 和 "the window shape specified in the `window_params` attribute must match the full operand shape in a persistent argument." 这样的字符串验证。
### SREG 关联(以及为什么它*不是*寄存器窗口)
`OperandWindow` 接触标量寄存器文件的唯一地方是它的*offset*:窗口的运行 offset 会物化到一个 SREG 中(`window_offset->ProducesSreg()`),然后送入标量/DMA 地址生成。这才是正确心智模型:SPU 把窗口 offset*计算*到标量寄存器中;窗口本身是内存 tile,不是寄存器。该寄存器像任何地址计算一样持有一个标量值(offset);没有任何东西在寄存器文件*之上*开窗口。
### FWPE:动态窗口大小可以存放在 SMEM
SMEM 和 "window" 还有另一种共现方式。flag `FLAGS_xla_sc_disable_fwpe_syncadds`(@ `0x223354e0`,cl::opt 名称 `xla_sc_disable_fwpe_syncadds`)带有 help string,已在 `.rodata` 中逐字确认:
> "Use TileSmem to store dynamic window sizes in fixed-window pipeline emitter instead of using sync-adds."
设置该 flag 时,FWPE 会把*动态窗口大小*存放在 TileSmem tile 中(`llvm.tpu.allocate.tilesmem` / `mlir::sparse_core::tpu_allocate_tilesmem::create` @ `0x146d7740`),而不是通过 sync-add 链重新计算。这是位于 SMEM 中的窗口*元数据*;同样没有涉及寄存器窗口,SMEM 在这里是大小值的 scratch table。
> **GOTCHA — "window in SMEM" ≠ "register window."** 放置在 `kSmem` 中的 `OperandWindow`,以及缓存在 TileSmem 中的 FWPE 窗口大小,都是 *SMEM 中的数据*。二者都不会把 SMEM 的窗口映射到 SREG 名称空间中。若重实现把"operand window 可请求位于 SMEM"混同为"标量寄存器文件有 SMEM 窗口",就会建模一个不存在的寄存器分配机制。
---
## 4. 旋转 PREDICATE 寄存器 — 唯一真正的寄存器窗口
### 目的
TPU 上*确实*存在一个硬件寄存器窗口。它是唯一一个,而且它给**谓词**寄存器开窗口,不是标量寄存器,也不在 SMEM 中。它存在是因为 SparseCore 会对 embedding/scatter 循环做软件流水线,旋转谓词能在没有显式 prolog/epilog 代码的情况下实现流水线循环的 prolog/kernel/epilog。
### 机制
SparseCore SCS 和 TEC sequencer 同时带有扁平谓词 bank 和旋转谓词 bank:
```text
SC_SCS_PREGS + SC_SCS_ROTATING_PREGS (rotating variant present)
SC_TEC_PREGS + SC_TEC_ROTATING_PREGS (rotating variant present)
SC_TAC_PREGS (NO rotating variant)注意 TAC sequencer 没有 SC_TAC_ROTATING_PREGS bank,这由该字符串缺失确认。旋转文件有 16 项(enum literal SPARSECORE_ROTATE_PREDICATION_PREG0_IS_1 … PREG15_IS_1),旋转由 scalar-ALU op SetRotatingPredicateRegisterH 和 BranchRelativeRotatingPregH(字段 branch_relative_rotating_preg)驱动。
编译器通过 LLVM 后端按 generation 启用它,由 subtarget gate 控制。反编译 gate 方法没有歧义:
| Subtarget | hasRotatingPredicates() 返回 | Codename |
|---|---|---|
TPUGfcSubtarget (@ 0x13c62c20) | 1 | 6acc60406 (TPU7x) |
TPUVfcSubtarget (@ 0x13c5f1e0) | 0 | Viperfish (v5) |
TPUGlcSubtarget (@ 0x13c610c0) | 0 | Ghostlite (v6e) |
TPUBcSubtarget (@ 0x13c59400) | 0 | BarnaCore |
因此,尽管 SCS/TEC 中存在 rotating-PREG bank 名称,后端只在 gfc/6acc60406 subtarget 上启用旋转。谓词 Slot 页面记录了相同事实("Rotating predicates — 6acc60406-only — TPUGfcSubtarget::hasRotatingPredicates() = 1; all others 0")。两个 flag 控制使用和仿真:FLAGS_xla_sc_rotating_predicates(@ 0x223359d8)和 FLAGS_xla_sc_emulate_rotating_predicates(@ 0x22335978);LLVM 侧开关是 enable-rotating-predicate 和 enable-rotating-predicate-emulation,后者描述为把 prolog 和 epilog 折叠进循环,"but not actually using rotating predicate support."
CONFIDENCE — HIGH(对原始证据的细化)。 原始发现记录了 gfc/glc 前缀的 rotating-PREG op 符号,并读到 "vfc shows the rotating-preg bank name." 反编译的
hasRotatingPredicates()gate 更精确:只有TPUGfcSubtarget返回1;vfc、glc和 BarnaCore subtarget 都返回0。bank 名称可能跨 SCS/TEC 存在,但编译器只在gfc/6acc60406subtarget 上发出旋转。应把 bank-name presence 当作 ISA schema,把 subtarget flag 当作每代启用条件。
注意事项
这是重实现者唯一应该建模真实滑动寄存器窗口的地方,但它位于 SparseCore SCS/TEC sequencer 的谓词文件中,不在 SREG 文件中,也不在 SMEM 中。窗口位置按循环迭代前进(modulo scheduling);仿真模式会展开 prolog/epilog,而不是旋转。如果某个任务说 "TPU has a register window",这是唯一正确指代,而且它只适用于 predicate。
5. 资源分类
一张表中的分类
按 SparseCore sequencer,0.0.40 中存在的资源 bank 及其是否有窗口化变体如下:
| Bank | 资源 | 窗口化变体? | 给什么开窗口? |
|---|---|---|---|
SC_{SCS,TAC,TEC}_SREGS | 标量寄存器(扁平 32 个) | NO | — |
SC_{SCS,TEC,TAC}_DREGS/VREGS | 数据 / 向量寄存器 | NO | — |
SC_SCS_PREGS, SC_TEC_PREGS | 谓词寄存器 | YES → SC_{SCS,TEC}_ROTATING_PREGS | predicate regs |
SC_TAC_PREGS | 谓词寄存器 | NO | — |
SC_{SCS,TAC,TEC}_CBREGS_{BASE,OFFSET,SIZE} | circular-buffer register triple | 本身就是窗口 | tile/scalar memory |
SC_{SCS,TAC,TEC}_SMEM | 标量内存(扁平) | NO | — |
唯一的"寄存器上的窗口"是旋转谓词文件;唯一"本身就是内存窗口的寄存器"是 CBREG 三元组;SREG 文件和 SMEM 都是扁平的。这一张表就是完整消歧。
该术语附着的三件事
"Register window" 被宽泛地用于三类不同资源,没有一个是 SREG 文件:
| 说法 | 状态 | 原因 |
|---|---|---|
| SPU 没有 register window | TRUE | 扁平 32 个 SREG,5-bit 索引,LSRA spill 到 SMEM;EncodingToScalarRegister 限制 idx ≤ 0x1F |
| SMEM 没有 register-window 机制 | TRUE | 扁平 byte/word 内存;触及 SMEM 的窗口是 CBREG memory-window 和 OperandWindow buffer placement,二者都不给寄存器开窗口 |
| MXU gain 像 stationary weight "window" 一样工作 | TRUE as metaphor | GainLatchModeProto 把权重 latch 到 systolic array;二进制没有使用 任何 "window" 术语;与 SMEM 和 SPU 无关 |
为完整性,MXU "GainLatch register window" 值得用一句话说明:weight-stationary gain register 只是在描述上被称为 "window"。二进制把它们命名为 GainLatchModeProto(GAIN_LATCH_MODE_NONE / _NO_XPOSE_* / _XPOSE_* / _PACKED_* …),从不使用 "window"。这些 gain 是 MXU 内部寄存器集,会在多个 matmul 期间 stationary latch;功能上可称作权重的 "window",但与 SPU SREG 文件和 SMEM 无关。它不得与 SMEM/SREG 问题混同。
确定答案
不存在窗口化或旋转标量寄存器文件意义上的 SMEM register-window,也不存在映射在 SMEM 之上的 register-window。SREG 文件是一个扁平、受硬件边界限制的 32 项文件,通过软件(LSRA-v2)spill 到 SMEM。该短语至多指向:CBREG(持有 {base,offset,size} 内存窗口的寄存器,最贴切)、流水线 OperandWindow(可能暂存在 SMEM 中的内存子 tile),或旋转 PREDICATE 文件(唯一真正的硬件寄存器窗口,仅 predicate,仅在 gfc/6acc60406 subtarget 上启用)。重实现应把三者建模为不同机制,并保持 SREG 文件扁平。
交叉引用
- 内存层级概览 — §1 说明 "register window is a misnomer" 适用于每个片上 tier;本页是字节级证明。
- SMEM 标量内存 — 扁平 SMEM 标量模型,以及支撑 SREG spill 的
ScalarLoad/StoreSmem*家族。 - SFLAG 同步标志 Tier — 兄弟扁平片上 tier;同样不是 register window。
- SPU / 标量 Slot — 32 项扁平 SREG 文件、5-bit 字段,以及
EncodingToScalarRegister的idx ≤ 0x1F边界。 - 谓词 Slot — 标量谓词文件和仅
6acc60406的 rotating-predicate gate。 - CBREG 循环缓冲寄存器 — CBREG
{base,offset,size}三元组、CbregMetadata选择器,以及 scalar-ALU op 位布局。 - SCS 标量 Opcode 枚举 — SparseCore 标量 ISA 中的 CBREG-op opcode 值。
- Stream Gather/Scatter — CBREG 地址窗口的 gather/scatter 消费者。
- Memory-Space Assignment (MSA) — HBM↔VMEM coloring pass;SMEM 不由 MSA 管理。
- Index entry: Part X — On-Chip Memory & DMA / Memory tiers — 返回索引