Skip to content

CBREG 环形缓冲区寄存器

本页中的每个 opcode 值、位移、字段宽度和 enum 值,都是从 libtpu-0.0.40-cp314 wheel(build-id 89edbbe81c5b328a958fe628a9f2207d;build libtpu_lts_20260413_b_RC00)里的 libtpu.so 按字节精确读取的。.text VA 等于文件偏移 0xe63c000。除非标注为 vfc (Viperfish) 或 glc (Ghostlite),地址均来自 gfc (6acc60406) 实例;三代 SC 在不同地址携带相同 schema。其他版本会有所不同。

摘要

CBREG 是 SparseCore 的硬件管理环形缓冲区寄存器:一个逻辑寄存器,持有线性内存区域上的滑动窗口,并产生会自推进、到末端回绕的地址流。它是 DMA descriptor ring 在 SC 中的对应物,即让 embedding datapath 遍历 lookup-index 列表,或把 embedding row 流式送入 tile buffer,而无需对每个元素重新计算地址的机制。TensorCore 循环会在每次迭代发出一个 imul/add,而 CBREG 会从一个由硬件免费递增并回绕的寄存器发出确定性序列 base, base+s, base+2·s, …, base+(N-1)·s, base, …

从物理上看,CBREG 是三个子寄存器{base, offset, size},存放在三个独立的硬件 bank(SC_{SCS,TAC,TEC}_CBREGS_{BASE,OFFSET,SIZE})中,但通过单个 4-bit CBREG index 作为一个寄存器寻址,因此每个 sequencer bank 有 16 个 CBREGbase 是一个带窗口的指针(指向 SMEM TILE_SPMEM,地址空间在写入 base 时固定);size 是 offset 回绕的模数;offset 是实时位置。一次访问读取/写入 base + (offset mod size);一次 PostUpdate 访问还会推进 offset = (offset + step) mod size。二进制中没有 modulo 指令;回绕是 OFFSET counter 硬件的属性,而 “overflow” 按设计就是回绕,从不是 trap。

本页记录三个可重新实现的表面:(1) CBREG triple 和 CbregMetadata 子寄存器选择器,即 Read/Write ops 携带的 {0=BASE, 1=SIZE, 2=OFFSET} enum;(2) scalar-ALU CBREG-op 位布局,即统一的 ScalarAlu1 slot encoding(opcode 在 bundle bit 154,三个 operand field 在 slot-relative bits 10/15/21),它在 SCS/TAC/TEC scalar lane 之间以及三代之间共享,并列出每个 opcode 值;(3) slot-reference binding,即 AddCbreg 如何推进 OFFSET,Stream gather/scatterIndirectOffsetSource=CBREG 如何消费窗口,以及 TEC vector-store scatter-add 如何引用 CBREG。opcode 名单本身由 SCS Scalar Opcode Enumeration 页面负责(AddCbreg=0x33 位于该页);bundle 字节布局由 SCS Engine 负责。本页是那两个页面所指向的 CBREG 语义。

对于重新实现,契约如下:

  • 寄存器模型。 一个 4-bit CBREG index 在每个 bank 中选择 16 个寄存器之一;每个寄存器是在三个 bank 中的 {base, offset, size} triple,在一个 op 内由 6-bit CbregMetadata immediate {0,1,2} 选择。
  • scalar-ALU op encoding。 opcode 是 bundle bit 154(ScalarAlu1,slot-relative bit 26)处的 6-bit field;三个 operand slot 位于 slot-relative bits 10 (Dest, 5-bit)、15 (Meta/Y, 6-bit)、21 (X, 5-bit)。Read/Write/Add/Move/SLD/SST 都复用这三个 slot。
  • opcode 值。 Read=0x36Write=0x35Add=0x33SLD/SST CircularBuffer 及其 PostUpdate 变体,以及 Move=0x00-primary + 0x1b-sub(仅 gfc)均从各 op 的 Matches() predicate 读取,跨代不变。
  • 回绕与绑定。 addr = base + (offset mod size);PostUpdate 在硬件中推进 offset = (offset + step) mod sizeAddCbreg 是显式的 2-operand {cbreg, delta} OFFSET 推进;Stream/vector-store 路径通过 4-bit selector 绑定 CBREG,用于 indirect-offset windowing 和 scatter-add。
寄存器文件每个 bank 16 个 CBREG(4-bit selector),bank 为 SC_{SCS,TAC,TEC}_CBREGS_*
每寄存器状态3 个硬件 bank 中的 {base, offset, size} triple
子寄存器选择器CbregMetadata(6-bit field,3 个有效值:BASE=0, SIZE=1, OFFSET=2)
Scalar op slotScalarAlu1 lane;opcode @bundle bit 154 宽度 6(slot-rel 26)
Operand fieldsDest @slot-rel 10/5 · Meta-or-Y @15/6 · X @21/5(decode word +0x18
Scalar opcodesRead 0x36 · Write 0x35 · Add 0x33 · SLD 0x3f/0x3e · SST 0x3d/0x3c · Move 0x00+0x1b
Vector CBREG selectorTEC VectorStore/Load Cbreg field & 0xF(4-bit → 16);shift 跨代变化(vfc >>21,glc >>22,gfc >>23
地址空间SMEM base(wrcbreg.smem.base)或 TILE_SPMEM base(wrcbreg.tilespmem.base
回绕offset = (offset + step) mod size,HW-implicit;无 trap,按设计回绕
跨代存在性仅 v5+:VF (vfc, Viperfish)、GL (glc, Ghostlite)、GF (gfc, 6acc60406);jxc/pxc 中没有

NOTE — 本页负责 CBREG 语义,而不是 opcode 名单或 bundle 布局。 AddCbreg=0x33 及其同族 opcode 值在 Scalar Opcode Enum 中编目;32-byte SCS bundle、slot base 和 27-bit scalar-slot template 在 SCS Engine 中说明。CBREG-as-Stream-offset-window 和 scatter-add slot 位布局在 Stream Gather/Scatter 中说明。本页记录 CBREG 是什么、如何寻址、如何回绕,以及这些 ops 如何绑定它。


CBREG 寄存器 Triple

用途

CBREG 是一个逻辑环形缓冲区寄存器,由编译器分配、初始化,然后交给硬件驱动。它存在的目的,是让 SC 能够产生回绕的地址流,用于 embedding-id 列表、gathered-row tile 或 gradient-accumulation 区域,而无需对每个元素重新计算 scalar 地址。该寄存器不是内存位置;它是一个小型硬件状态对象,由 address-generation 逻辑和 scalar/vector ops 按 index 引用。

三个子寄存器

一个 CBREG 选择 16 个逻辑寄存器之一;每个逻辑寄存器持有三个子寄存器值,它们位于三个独立的硬件 bank 中,但通过单个 4-bit index 作为一个寄存器寻址:

子寄存器BankCbregMetadata含义
baseSC_{SCS,TAC,TEC}_CBREGS_BASE0 (BASE)窗口起始地址,在 SMEM 或 TILE_SPMEM 中(地址空间在写入时固定)
sizeSC_{SCS,TAC,TEC}_CBREGS_SIZE1 (SIZE)窗口长度;用于回绕的模数
offsetSC_{SCS,TAC,TEC}_CBREGS_OFFSET2 (OFFSET)窗口内当前实时位置

寄存器类成员名在二进制中表现为 CBREG_BASE / CBREG_SIZE / CBREG_OFFSET;bank 后缀表现为 SC_<engine>_CBREGS_<sub>base 是一个带窗口的指针:通过 wrcbreg.smem.base 写入时,它指向 SCS SMEM tier;通过 wrcbreg.tilespmem.base 写入时,它指向 per-tile TILE_SPMEM(见 Addressing)。sizeoffset 是该 buffer 内无量纲的 word/element 计数。

CbregMetadata 选择器

Read/Write CBREG ops 携带一个 immediate,用来命名该 op 触及三个子寄存器中的哪一个。该选择器占用 scalar instruction 中的 6-bit slot,但只有 {0,1,2} 有效,实际上只用了 2 位,较高 encoding 保留。validator 是 GetCbMetadata<…::CbregMetadata>(vfc 0x13998fe0,glc 0x13a046c0,gfc 0x13a7a6a0);其函数体将 immediate 精确映射如下:

c
// GetCbMetadata<vfc::CbregMetadata>(out, MCOperand operand)   // 0x13998fe0
//   operand must be an immediate (else LogFatal "operand.isImm()")
if (operand.imm == 2)   metadata = 2;       // OFFSET
else if (operand.imm == 1) metadata = 1;    // SIZE
else if (operand.imm != 0)                  // any other value:
    return MakeErrorImpl(
        "CB Register Metadata operand must be an immediate with a value of "
        "0 (Base), 1 (Size) or 2 (Offset). Provided value: " + imm);
else                    metadata = 0;       // BASE  (the imm == 0 fall-through)
```text

proto enum(`CbregMetadata`)一致:`CBREG_METADATA_BASE=0`、`CBREG_METADATA_SIZE=1`、`CBREG_METADATA_OFFSET=2`,随后是 `CBREG_METADATA_RESERVED_0..6`(七个保留 encoding)。runtime decode 侧携带匹配的诊断:`"invalid cbreg metadata: %d"` 和 `"Field cbreg_metadata of SparseCoreScalarAlu CbregMetadata is an enum and value 0x%x does not match any encodings."`

> **QUIRK — `AddCbreg` 不携带 metadata field;它总是以 OFFSET 为目标。** `Add` 是 offset-advance primitive,其 operand 集合是 `{which CBREG, delta}`,没有 `CbregMetadata` selector,因此它隐式写入 OFFSET 子寄存器。只有 `Read`/`Write` 需要显式 metadata immediate 来触及 `base`/`size`/`offset`。如果重新实现者把 `AddCbreg` 当作通用的 “add to a CBREG sub-register”,就会寻找一个 encoding 中并不存在的 metadata operand。

---

## Scalar-ALU CBREG Op Encoding

### 用途

scalar 路径会修改和读取 CBREG(设置其 base/size、清零 offset、推进它、复制它),并执行 scalar circular-buffer loads/stores。所有这些都是 `SparseCoreScalarAlu1` lane-1 ops;它们在三个 sequencer bank(SCS、TAC、TEC)之间以及三代之间共享一个统一的 slot layout。这是重新实现者发出 CBREG 指令时必须复现的 encoding。

### 统一 Slot Layout

scalar slot 的 decoded word 是 `+0x18` 处的 struct DWORD(DWORD index 6);opcode 是 slot-relative bit 26 处的 6-bit field,也就是 bundle-absolute bit 154(来自 [SCS Engine](scs-engine.md) 的 `ScalarAlu1` opcode 位置)。三个 operand fields 被每个 CBREG op 复用;每个 op 的含义不同,但位位置不变。下面的 bit shift 取自各 op 的 `…Field::GetConcatenatedValue()` accessor(vfc TAC instances `0x1e8e53c0..0x1e8e54a0`;gfc SCS `0x1eb7cac0..0x1eb7cbe0`):

| Field | Slot-rel bits | Width | Bundle-abs bit | Decode(来自 accessor) |
|---|---|---:|---:|---|
| `Dest` | `[10:14]` | 5 | 138 | `(word_0x18 >> 10) & 0x1F` |
| `field@15` | `[15:20]` | 6 | 143 | `(word_0x18 >> 15) & 0x3F`(CbregMetadata,或 ScalarY) |
| `field@21` | `[21:25]` | 5 | 149 | `(word_0x18 >> 21) & 0x1F`(X / CBREG selector) |
| `opcode` | `[26:31]` | 6 | 154 | masked `& 0xFC000000`,value `>> 26` |

### 每个 Op 的 Operand 映射

每个 CBREG op 以不同方式分配三个 operand slot。Operand `X@21/5` 和 `Dest@10/5` 在物理上是 5-bit,但 CBREG file 为 16,因此 CBREG 选择只使用低 4 位(绑定的 4-bit 约束来自 vector 路径的 selector,见 [Per-Bank CBREG Count](#per-bank-cbreg-count))。

```text
ReadCbreg  (0x36):  SREG[Dest] <- CBREG[X][metadata]
    Dest @10/5  destination SREG          Meta @15/6  sub-register {0,1,2}    X @21/5  which CBREG

WriteCbreg (0x35):  CBREG[Dest][metadata] <- ScalarY
    Dest @10/5  which CBREG               Meta @15/6  sub-register             Y @21/5  ScalarY source

AddCbreg   (0x33):  CBREG[Dest].offset += ScalarY   (mod size)
    Dest @10/5  which CBREG               Y    @15/6  delta (ScalarY)          (no metadata — implicit OFFSET)

MoveCbreg  (0x00 primary + 0x1b sub @21):  CBREG[Dest] <- CBREG[src]   (gfc only)
    Dest @10/5  destination CBREG         src  @15/6  source CBREG            (copies whole {base,offset,size})

SLD CircularBuffer (0x3f) / PostUpdate (0x3e):  SREG[Dest] <- CB[CBREG][offset]
SST CircularBuffer (0x3d) / PostUpdate (0x3c):  CB[CBREG][offset] <- ScalarY
    Dest @10/5                           CB-sel @15/6                          index @21/5
    PostUpdate: after the access, offset = (offset + step) mod size

Opcode 值

每个 op 的 Matches() predicate 从 ScalarAlu1 slot word 中 mask 出 6-bit opcode,并与一个 signature 比较;该 signature 就是 opcode。数值跨代不变,gfc 与 vfc/glc predicate 按字节相同。已确认值如下:

OpcodeMnemonicMatches() 证据(gfc)
0x36ReadCbreg(word6 & 0xFC000000) == 0xD80000000xD8000000>>26 = 0x36(gfc 0x1eb7b560
0x35WriteCbreg(word6 & 0xFC000000) == 0xD40000000xD4000000>>26 = 0x35
0x33AddCbreg(word6 & 0xFC000000) == 0xCC0000000xCC000000>>26 = 0x33
0x3f / 0x3eScalarLoadCircularBuffer / …PostUpdateopcode field;PostUpdate 仅 VF/GL
0x3d / 0x3cScalarStoreCircularBuffer / …PostUpdateopcode field;PostUpdate 仅 VF/GL
0x00+0x1bMoveCbreg(word6 & 0xFFE00000) == 0x3600000>>26 = 0x00 primary,>>21 = 0x1b sub;仅 gfc

QUIRK — MoveCbreg 是两级(escape)opcode,不是扁平的 6-bit 值。 它的 Matches() mask 一个 11-bit field(& 0xFFE00000,bits 21–31),并比较 == 0x3600000。primary 6-bit opcode 部分(>>26)是 0x00,5-bit X field(>>21)携带 sub-opcode 0x1b(27)。如果重新实现者只读取 6-bit primary,会把 Move 看作 opcode 0x00,并与 control class 冲突;用于区分的位是 X-field sub-opcode。Move 仅存在于 gfc(6acc60406);VF/GL 没有 scalar MoveCbreg

一个 slot encoding-mode tag 将普通 Read/Write/Add/LD/ST 形式与 PostUpdate 形式区分开来;mode byte 携带 auto-increment bit,告诉硬件在访问后推进 OFFSET。PostUpdate-vs-plain 的判别器是独立的 …PostUpdate opcode predicate;这里不对精确的 mode-byte 值做 bit decode。

函数映射

FunctionAddress角色
GetCbMetadata<vfc::CbregMetadata>0x13998fe0validate metadata immediate {0,1,2};否则 LogFatal
GetCbMetadata<glc::CbregMetadata> / <gfc::…>0x13a046c0 / 0x13a7a6a0相同逻辑,按 gen
EmitReadCbregOp<vfc::CbregMetadata, …ReadCbreg>0x139983c0lower ReadCbreg MCInst → scalar slot
EmitWriteCbregOp<…, ScsBundle, …WriteCbreg> (vfc)0x139e6420write CBREG,SCS bundle
EmitWriteCbregOp<…, TacBundle / TecBundle, …> (vfc)0x13998b60 / 0x139d0d00write CBREG,TAC / TEC bundle
EmitMoveCbregOp<…, ScsBundle / TecBundle, …MoveCbreg> (gfc)0x13ac9540 / 0x13a73c80copy CBREG triple;仅 gfc,无 TAC
…TacScalarAlu1ReadCbregDestField::GetConcatenatedValue0x1e8e5400Dest >>10 & 0x1F
…TacScalarAlu1ReadCbregCbregMetadataField::…0x1e8e53c0Meta >>15 & 0x3F
…TacScalarAlu1ReadCbregXField::…0x1e8e53e0X >>21 & 0x1F
…ScalarAlu1AddCbregOpcode::Matches (gfc)0x1eb7b5a0(word6 & 0xFC000000)==0xCC0000000x33
…ScalarAlu1MoveCbregOpcode::Matches (gfc)0x1eb7b5c0(word6 & 0xFFE00000)==0x36000000x00+0x1b
BitCopy0x1fa0a900LE bit-field packer (dst, dst_off, src, src_off, nbits)

寻址与回绕 {#addressing-and-wraparound}

用途

CBREG 将它的 {base, offset, size} triple 转换为 effective address,并且对 PostUpdate ops 转换为自推进地址流。这是重新实现者分配 circular buffer 时编码的模型,也是硬件每次访问时执行的模型。

Effective-Address 与 Advance 公式

c
// Per-access effective address (conceptual; the wrap is HW-implicit):
addr = base + (offset mod size);          // read or write this element

// PostUpdate access (mode tag 0x60) advances after the access:
offset = (offset + step) mod size;        // wrap at the SIZE sub-register
```text

`SIZE` 是模数。普通(非 PostUpdate)访问保持 OFFSET 不变;只有 PostUpdate 形式(`scSLDCBREG…PostUpdate`、`scSST…PostUpdate`、TEC vector-store `…PostUpdateAdd*`,以及 Stream `post_update_indirect_offset_circular_buffer`)会推进并回绕它。显式 advance op `AddCbreg` / `llvm.tpu.cbreg.add.offset` 是 2-operand functional op `{cbreg, delta} → new_offset`;`.in.place` 变体就地修改 CBREG。

因此,初始化为 `{base, offset=0, size=N, step=s}` 的 CBREG 会发出确定性的 ring:

```text
base, base+s, base+2·s, …, base+(N-1)·s, base, base+s, …

这是 address-generation 逻辑在无需逐元素 scalar 地址计算的情况下流式处理 embedding rows 或 lookup indices 所需的地址序列预测,即 SC 的硬件管理 DMA-descriptor-ring 对应物。

QUIRK — 没有 modulo 指令;回绕是 OFFSET counter,overflow 从不 trap。 二进制中不存在显式 modulo opcode。OFFSET 子寄存器就是 modulo-SIZE counter;编译器可见的 advance ops 只携带 {cbreg, delta},从不携带显式 % size。因此回绕公式 offset = (offset + step) mod size 是从 op 形状加上 “circular buffer” 语义推断出来的;显式 modulo 是硬件内在行为,而不是被转录出来的指令。“Overflow” 对 CBREG 来说按设计就是回绕;不同于 SREG file(会 overflow 到 LSRA spill),CBREG 从不 trap,而是回绕。

双地址空间:SMEM vs TILE_SPMEM

base 子寄存器有两个 typed accessor,用于固定窗口指向哪个 memory tier。选择在写入 base 时完成;硬件上只有一个 CBREG 寄存器,但地址空间由哪个 wrcbreg.*.base intrinsic 设置它来确定:

text
llvm.tpu.rdcbreg.smem.base      / .wrcbreg.smem.base       -> SCS SMEM tier
llvm.tpu.rdcbreg.tilespmem.base / .wrcbreg.tilespmem.base  -> per-tile TILE_SPMEM tier
```text

scalar `ScalarLoadCircularBuffer`(`scSLDCBREG`)对 SCS SMEM tier 开窗;TEC vector `TileSpmemLoadCircularBuffer` 对 TILE_SPMEM 开窗。`smem.base` 和 `tilespmem.base` accessor string 都存在于二进制中。这解答了 SCS scalar-memory 工作提出的 SMEM-address-space 问题:CBREG 是一个寄存器,持有指向 SMEM 或 TILE_SPMEM 的*带窗口指针*,在写入 base 时选择。

---

## 每个 Bank 的 CBREG 数量 {#per-bank-cbreg-count}

CBREG file 是**每个 sequencer bank 16 项**。绑定证据是 TEC vector load/store `Cbreg` field 上的 4-bit selector,并已跨 glc 和 gfc 确认:

| Bank | Count | Selector width |
|---|---:|---|
| `SC_SCS_CBREGS_*` | 16 | 4-bit |
| `SC_TAC_CBREGS_*` | 16 | 4-bit |
| `SC_TEC_CBREGS_*` | 16 | 4-bit |

> **NOTE — scalar field 是 5-bit,但 CBREG file 是 16,由 vector 路径的 4-bit selector 确定。** scalar-ALU `Dest@10` 和 `X@21` field 在物理上是 5-bit(足以表示 32),但 TEC vector Cbreg field 是硬性的 `& 0xF`(16 项)。scalar 5-bit field 的高位未用于 CBREG 选择。重新实现者必须将 CBREG file 定为 16;5-bit scalar slot 不是 32 个寄存器的证据。TAC 在 VF/GL 上有 CBREG(`EmitWriteCbregOp` 在 vfc/glc 下为 Tac 实例化),但 gfc 上没有。

---

## Slot-Reference Binding:其他 Slot 如何命名 CBREG

### 用途

CBREG 会从三个位置按 index 被引用:上面的 scalar-ALU ops、Stream-engine indirect-offset source,以及 TEC vector-store scatter-add。后两者使 CBREG 成为 embedding-table window。本节是绑定表面;那两个 slot 的位布局位于各自页面。

### Stream Indirect-Offset Source

[Stream gather/scatter](stream-gather-scatter.md) engine 通过 proto enum `IndirectOffsetSource` 选择其每元素 offset/size 来自哪里:

```text
IndirectOffsetSource (1-bit):  SREG = 0    CBREG = 1

选择 CBREG 时,index/offset 列表会通过 CBREG window 读取,且 post_update_indirect_offset_circular_buffer 按每个元素推进 CBREG offset(mod size);CBREG 就是 lookup-index buffer 上的 sliding window。Stream slot 自身没有 CBREG-index field;windowing CBREG 是 SCS 在发出 stream 之前设置好的那个(indirect-offset 路径绑定到 engine 的 CBREG state,而不是每个 stream 重新选择)。

TEC Vector-Store Scatter-Add

embedding-gradient scatter-add 将累积的 gradient 写入 CBREG-windowed TILE_SPMEM 区域。TEC vector-store family TileSpmemStoreCircularBuffer[PostUpdate]Add{Bf16,F32,S16,S32} 携带显式 4-bit Cbreg field,用来命名 16 个 CBREG 中哪个为目标 tile 开窗:

text
// TileSpmemStoreCircularBufferAdd{Bf16,F32,S16,S32} CbregField, decode word12 (+0x30):
Cbreg = (word12 >> shift) & 0xF;         // which CBREG (16); & 0xF is gen-invariant
//   shift gen-variant: vfc >>21 (0x1e9c1d00), glc >>22 (0x1eb4f160), gfc >>23 (0x1ecca4c0)
```text

完整的 store-slot field 集合(`{Mask, Stride, Offset, BaseAddress, Cbreg, Source}`)和 gradient-flow 细节在 [Stream Gather/Scatter](stream-gather-scatter.md) 与 [VectorStore Slot](vectorstore-slot.md) 中说明。与此处相关的绑定点是:vector store 通过 4-bit selector *命名* 一个 CBREG,post-update 其 offset,从而使 gradient tile 一次一个元素地流过 buffer。

### Embedding-Lookup 流程(引用在此组合)

```text
1. SCS allocates a CBREG and writes its triple:
     wrcbreg.smem.base / wrcbreg.tilespmem.base  <- index-list / tile base
     wrcbreg.size                                <- per-window word count
     wrcbreg.offset                              <- 0
2. Stream gather runs with IndirectOffsetSource = CBREG:
     reads next index through the CBREG window,
     computes HBM[table_base + index*row_stride], DMAs the row -> TILE_SPMEM,
     post-updates the CBREG offset (mod size) so the next gather reads the next index.
3. TEC vector-loads the gathered rows (TileSpmemLoadCircularBuffer[PostUpdate]),
   reduces, and on the backward pass
   TileSpmemStoreCircularBufferPostUpdateAddF32 scatter-adds the gradient back
   into the CBREG-windowed region, advancing the offset per store.

compiler driver LinearStreamStartOpLowering::rewriteSparseCoreStreamOpToLLVM(以及 …AddStartOpLowering scatter-add sibling)接收一个 WideOffset 变体,它会解析为 SREG 值或 CBREG-sourced offset;这就是 stream 变成 CBREG-windowed 的解析点。


LLVM / MLIR Intrinsic 表面

面向编译器、用于驱动 CBREG 的 ops。下面所有名称都作为字符串存在于二进制中;read/write intrinsics 携带按子寄存器和按地址空间区分的变体。

Op-name string角色
llvm.tpu.allocate.cbreg分配一个 CBREG(每 bank 16 个)
llvm.tpu.cbreg.add.offsetoffset += delta → new offset,wrap mod size
llvm.tpu.cbreg.add.offset.in.place相同,但修改 CBREG
llvm.tpu.copy.cbreg复制整个 CBREG triple → MoveCbreg
llvm.tpu.rdcbreg.offset / .size读取 OFFSET / SIZE 子寄存器
llvm.tpu.rdcbreg.smem.base / .tilespmem.base读取 BASE(按地址空间)
llvm.tpu.wrcbreg.offset / .size写入 OFFSET / SIZE
llvm.tpu.wrcbreg.smem.base / .tilespmem.base写入 BASE(按地址空间)
sc_tpu.advance_cb_offset / read_cb_offset用于 advance / read 的文本 MLIR op 名称

MLIR sc_tpu op creators 支撑这些(tpu_allocate_cbreg::create 0x146d6d80tpu_cbreg_add_offset::create 0x146d7e60OneResult/NOperands<2>tpu_cbreg_add_offset_in_place::create 0x146d7f60tpu_rdcbreg_offset 0x14734820tpu_wrcbreg_offset/_size 0x14a30fe0/0x14a310e0)。SC ISel 通过 matchReadCbreg<13419u,13417u,13418u>0x13b39200)和 <13420u,…>0x13b39620)匹配 reads,即 rdcbreg.{offset,size,base} family 的 intrinsic IDs 0x3469..0x346c

配置 Knobs

Knob / string含义
circular_buffer_size(default 1000XLA emitter window-size estimate,不是 HW capacity
min_circular_buffer_byte_count要分配的最小 CB buffer;"Invalid min_circular_buffer_byte_count value" validator
" row size exceeds circular buffer capacity within SparseMapRow Emitter"lookup row 超过 CBREG SIZE 时的 emitter error
HardwareManagedCircularBufferMinSizeBytes0x10e4a660legacy BarnaCore HW-managed CB minimum,与 v5+ SC CBREG 不同
is_circular_buffer flag触发 SC tile allocator 的 VFC HW-bug guard(不能将 CB 放入最后一个 TILE_SPMEM entry)

NOTE — circular_buffer_size=1000 是 emitter estimate,不是 SIZE 子寄存器宽度。 XLA emitter 用于确定 buffer 大小的默认窗口大小是软件 knob;物理 CBREG SIZE 子寄存器 bit-width 属于 chip_parts geometry,不在 C++ 中。不要把 1000-word emitter default 与硬件容量混淆。HardwareManagedCircularBufferMinSizeBytes 属于 legacy BarnaCore circular buffer,是不同于这里记录的 v5+ SC CBREG 的另一种机制。


跨代存在性

CBREG 是 v5+ SparseCore 特性。jxc (Jellyfish) 或 pxc (Pufferfish) namespace 下没有 Cbreg ops,这些代没有 SparseCore CBREG。在三代 SC 中,差异集中在 scalar PostUpdate(gfc 中移除,迁移到 TEC vector path)和 scalar MoveCbreg(gfc 新增)。

MechanismVF (vfc, Viperfish)GL (glc, Ghostlite)GF (gfc, 6acc60406)
CBREG file(每 SCS/TAC/TEC bank 16 个)yesyesyes(无 TAC)
ReadCbreg / WriteCbreg / AddCbreg(scalar)yes(0x36/0x35/0x33yesyes
MoveCbreg(scalar)yes(0x00+0x1b
ScalarLoad/StoreCircularBufferyes(0x3f/0x3dyesyes
ScalarLoad/StoreCircularBufferPostUpdateyes(0x3e/0x3cyes—(moved to TEC vector)
TEC TileSpmemLoad/StoreCircularBufferyesyesyes
TEC …StoreCircularBufferPostUpdateAdd{dt}yes(int/float)yes(4 dtypes)yes(4 dtypes)
Stream IndirectOffsetSource = CBREGyesyesyes
smem.base + tilespmem.base CBREG variantsyesyesyes

gen split 由 namespace presence 按字节确认:MoveCbreg 文件仅存在于 gxc/gfc 下(20 个实例,仅为 Scs 和 Tec bundles 提供 EmitMoveCbregOp,例如 0x13ac9540 / 0x13a73c80);EmitWriteCbregOp 在 vfc/glc 下为 Scs/Tac/Tec 实例化,但在 gfc 下仅为 Scs/Tec 实例化(gfc 下无 TAC)。jxc/pxc 下有零个 Cbreg 文件。


限制与未决项

项目备注
CbregMetadata enum {BASE=0, SIZE=1, OFFSET=2}proto + validator 一致,body 已读
Scalar-ALU CBREG slot layout(opcode @154/6,fields @138/5@143/6@149/5accessor shifts 已读;bundle-abs 来自 SCS slot base
Opcode values Read 0x36 / Write 0x35 / Add 0x33 / Move 0x00+0x1bMatches() immediates 已读,gen-invariant
每 bank 16 个 CBREG(4-bit selector)TEC vector Cbreg & 0xF(shift gen-variant:vfc/glc/gfc >>21/>>22/>>23
双地址空间(SMEM base / TILE_SPMEM base)两个 accessor string 均存在;两个 wrcbreg.*.base variants
IndirectOffsetSource SREG=0 / CBREG=1 + scatter-add Cbreg bindingenum + vector-store Cbreg field
跨代存在性(仅 v5+;Move 仅 gfc;PostUpdate 非 gfc-scalar)namespace file presence
回绕算术 offset = (offset + step) mod size由 op 形状 + circular-buffer 语义推断;无显式 modulo op
SLD/SST 0x3f/0x3e/0x3d/0x3c opcode valuesopcode-field roster;PostUpdate-bit 未完全 bit-decoded
物理 OFFSET/SIZE 子寄存器 bit widthschip_parts geometry,不在 C++ 中
PostUpdate step source(element-size vs fixed-1 vs operand Stride)vector form 有 4-bit Stride;scalar step source 未经 bit-confirmed
写入 SIZE mid-loop 是否合法以及 in-flight PostUpdates 的 HW orderingproto 允许 WriteCbreg[SIZE];ordering 未恢复
scIMPLICIT_CBREG operand role(可能是 SLD/SST 的 default CB0)未解码

相关组件

NameRelationship
GetCbMetadata<…::CbregMetadata>0x13998fe0验证 metadata immediate {0,1,2};BASE/SIZE/OFFSET decode
EmitReadCbregOp / EmitWriteCbregOp / EmitMoveCbregOpper-bundle lowering MCInst → scalar CBREG slot
…ScalarAlu1AddCbregOpcode::Matches0x1eb7b5a0从 slot 读回的 0x33 opcode signature
TEC …StoreCircularBufferPostUpdateAdd{dt} CbregField将 scatter-add 绑定到 window 的 4-bit CBREG selector
BitCopy0x1fa0a900每个 scalar/vector encoder 都通过它写入的 LE bit-field packer

交叉引用

  • SCS Scalar Opcode EnumerationScalarAlu1 opcode roster,其中编目了 AddCbreg=0x33ReadCbregWriteCbregMoveCbreg
  • SCS (Scalar) Engine — 32-byte bundle 和 27-bit ScalarAlu1 slot template,CBREG-op opcode field(@154)位于其中。
  • Stream Gather/Scatter — 引用 CBREG 的 IndirectOffsetSource=CBREG indirect-offset window 和 TEC vector-store scatter-add Cbreg field。
  • SparseCore Architecture — embedding datapath end to end;CBREG windowing 在 gather/compute/scatter pipeline 中的位置。
  • SparseCore Overview — engine classes、per-gen SC presence,以及 host-table → HBM → SC gather path。
  • TEC Engine — 对 CBREG-windowed tile 发出 TileSpmemLoad/StoreCircularBuffer 的 vector engine。
  • TAC Engine — VF/GL access engine,它也携带 CBREG scalar slot(gfc/6acc60406 下没有 TAC CBREG emitter)。
  • VectorStore Slot / VectorLoad SlotCbreg field 所属的完整 TEC vector circular-buffer slot family。
  • M-Register Predicate Word — 覆盖每个 scalar slot、位于 CBREG-op opcode field 上方的 predication header。
  • Binary: extracted/libtpu-0.0.40-cp314-cp314-manylinux_2_31_x86_64/libtpu/libtpu.so(build-id 89edbbe81c5b328a958fe628a9f2207d
  • Index entry: Part IX — SparseCore & BarnaCore / SparseCore ISA — 返回索引