SCS 标量 Opcode 枚举
本页上的每个 opcode 值、掩码立即数和位位置都从
libtpu-0.0.40-cp314wheel 中的libtpu.so逐字节读取(build-id89edbbe81c5b328a958fe628a9f2207d)。其他版本会不同。
摘要
SCS(SparseCore Scalar)定序器在每个 32 字节 bundle 中有三个标量槽位 — ScsScalarMisc、ScalarAlu1、ScalarAlu0 — 每个槽位都是一个 27 位字段,在槽位相对位 +16 携带 6 位主 opcode,落在绝对 bundle 位 127、154 和 181。本页是 SCS 引擎 页的 opcode 名册配套页;后者负责 bundle 字节布局和 27 位槽位模板;这里枚举每个槽位可编码的每个操作、其整数 opcode 值,以及承载它的编码形式。最接近的熟悉类比是从解码器匹配谓词中恢复出的 ISA opcode 表,而不是来自手册:没有可读取的 opcode 名称字符串表,因此每个值都从每个 op 的比较立即数重建。
该名册可恢复,是因为 libtpu 会为每代的每个 opcode 发出一个 C++ 类型 — asic_sw::deepsea::<pxc>::<gen>::isa::SparseCore<Slot><OpName>Opcode — 并且每个类型都携带一个 Matches() const 谓词,该谓词从指令结构体中掩出已解码的 opcode 字段,并将其与该 op 自身签名比较。Matches() 内的 cmp/movabs 立即数就是 opcode 值;槽位 Encoder::Encode 在对应的绝对位通过 BitCopy(dst, dst_bitoff, src, src_bitoff, nbits) 将相同值写回 bundle。因为解码谓词和编码写入一致,Matches() 立即数就是权威编码。下方每个值都用反编译的 gfc(6acc60406)命名空间中的 Matches() 谓词交叉检查,并抽样 vfc(Viperfish)确认跨代不变性。
opcode 空间是两级的。6 位主字段要么选择一个具体 op(IntegerAdd=0x0a、BitwiseAnd=0x0e),要么选择一个 op 类。当它命名一个类时,具体 op 位于覆盖该槽位的更宽 escape 字段中:控制 op 位于 11 位字段,寄存器读取位于 17 位字段(ReadRegister* = 0x280..0x28d),配置设置位于 16 位字段(Set* = 0x4001..0x4005),divide-push 位于 0x16xxxx 字段。两个 ALU lane 共享一个 opcode 命名空间,仅在 bundle 位位置和少量 lane 专属 op 上不同;ScsScalarMisc 承载 sync-flag / atomic / barrier 家族(编码为 6 位 base + 5 位 sub-opcode mode),再加上一个 integer-ALU 子集,没有 FP,也没有 branch。本页记录三种谓词形态、每个槽位的名册及其整数值、四种类 escape,以及逐代差异。
对于重新实现,契约是:
- 三种
Matches()谓词形态。 形式 A(平坦 6 位,opcode 跨 word 边界)、形式 B(复合:6 位 base + 结构体相对位 47 的 5 位 sub-opcode mode,或位 58 的扩展 ALU 类)、形式 C(针对槽位 word 的掩码比较,ALU lane 使用)。复现解码器意味着复现这些掩码。 - 两个 ALU lane 共享的平坦 6 位名册。
0x0a..0x31integer/FP/bitwise/shift/compare op,在ScalarAlu0和ScalarAlu1上值相同;只有 bundle 位(@181对@154)和少数 lane 专属 op 不同。 - 四种类 escape 及其值范围。 控制
0x00..0x1d(11 位)、寄存器读取0x280..0x28d(17 位)、配置设置0x4001..0x4005(16 位)、divide-push0x160001..0x160002。这些值与槽位无关;只有字段的位基址按 lane 改变。 ScsScalarMisc复合编码。 6 位 base 命名一个类(Sync0x01、SyncWatch0x02、set-sync0x05、barrier0x07、Atomic0x08、extended-ALU0x00);结构体位 47(sync/atomic mode)或位 58(extended-ALU)的 5 位 sub-opcode 选择成员。
| 槽位 | ScsScalarMisc(op @127)· ScalarAlu1(op @154)· ScalarAlu0(op @181) |
| 主 opcode 宽度 | 6 位,槽位相对 @+16 |
| Opcode->助记符来源 | 每个 op 的 SparseCore<Slot><OpName>Opcode::Matches() 比较立即数 |
| 谓词形态 | A 平坦 6 位 · B 复合(base + 5 位 sub)· C 掩码比较 |
| 类 escape | 控制 11 位(0x00..0x1d)· reg-read 17 位(0x280..0x28d)· config 16 位(0x4001..0x4005)· divide-push(0x16xxxx) |
| gfc op-form 数量 | SparseCoreScalarMisc* 82 · ScsScalarMisc* 81 · ScalarAlu0* 78 · ScalarAlu1* 82 |
| 共享 ALU 命名空间 | ScalarAlu0 ≡ ScalarAlu1 值;lane 仅因位位置 + lane 专属 op 而不同 |
| 跨代不变性 | 共享 op 值 VF/GL/GF 逐字节相同(两者 IntegerAdd=0x0a) |
| 置信度 | 除非行或说明另有标注,否则为 CONFIRMED(以反编译为锚) |
注意 — 本页枚举 opcode 名册;bundle 字节布局位于 SCS 引擎。 32 字节 bundle、绝对槽位基址(111/138/165)、27 位槽位模板(x0
@+0、ScalarY@+5、x1@+11、opcode@+16、predication header@+22),以及 no-check-trailer 规则都记录在那里,此处不重复。M-Register 谓词字 页负责位于每个 opcode 字段之上的 3 位 / 4 位 predication-header 重叠。
Opcode 谓词模型
为什么没有 opcode 字符串表
SC ISA 不携带用于字符串化的 opcode 名称数组。相反,每个 opcode 都是 asic_sw::deepsea::<pxc>::<gen>::isa:: 命名空间中一个独立的空 C++ 类 SparseCore<Slot><OpName>Opcode,反汇编器 / 校验器通过 Matches() 询问每个类“这是你吗?”。匹配谓词从指令结构体(一个 128 位以上的 word 数组;标量槽位读取 this+0x10 和 this+0x18 处的 word)中解码 opcode 字段,并与该 op 的硬编码签名比较。该签名就是 opcode。这使得 Matches() 比较立即数成为权威 opcode->助记符来源,是 SC 中类似 TensorCore LLO opcode 字符串化路径的对应物。
标量槽位中出现三种谓词形态。形态对重新实现者很重要,因为它们揭示了 opcode 位的物理位置,以及一个类如何拆成 base 加 sub-opcode。
形式 A — 平坦 6 位
主 opcode 跨越 64 位 word 边界:this+0x10 的 word 位 63 是低位,this+0x18 的 word 位 0..4 是高位,掩到 6 位后比较。ScsScalarMisc IntegerAdd(0x1ebabf00):
// SparseCoreScalarMiscIntegerAddOpcode::Matches (gfc 0x1ebabf00)
// shld $1, word_0x10, word_0x18 → (word_0x18<<1) | (word_0x10>>63)
return ((((word_0x18 << 1) | (word_0x10 >> 63)) & 0x3F) == 0x0A); // opcode 0x0a, 6-bit straddle
```text
(反编译器将这个跨界字段渲染为 `(*((__int128*)this + 1) >> 63) & 0x3F`;`+1` 处的 `__int128` 视图是 `+0x10/+0x18` 的 word 对。)
### 形式 B — 复合(base + sub-opcode)
6 位 base 命名一个类,5 位 sub-opcode 选择成员。base 被重组为 `(bit63 | low5<<1)`;谓词将它与类值 XOR,然后 AND 出 sub 字段并与成员签名 XOR,再 OR 两半并测试是否为零。`ScsScalarMisc AtomicTileAdd`(`0x1ebabbe0`)— base 8(Atomic),sub 1:
```c
// SparseCoreScalarMiscAtomicTileAddOpcode::Matches (gfc 0x1ebabbe0)
// base = (word_0x10>>63) + 2*(word_0x18 & 0x1F)
// sub mode field = word_0x10 & 0xF800000000000 (struct-rel bit 47, 5 bits)
return ( (((word_0x10>>63) + 2*(word_0x18 & 0x1F)) ^ 0x08)
| ((word_0x10 & 0xF800000000000) ^ 0x800000000000) ) == 0; // base 8, sub 1sync/atomic mode 字段位于结构体相对位 47(0xF800000000000)。extended-ALU 类改用位 58 的 5 位字段(0x7C00000000000000);CountLeadingZeros(base 0x00,sub 14)确认了这一点:(word_0x10 & 0x7C00000000000000) ^ 0x3800000000000000,且 0x3800000000000000 >> 58 = 14。
形式 C — 掩码比较(ALU lane)
ScalarAlu0/ScalarAlu1 使用单个 AND 掩码 + 针对槽位 word 的比较。ScalarAlu0 IntegerAdd(0x1eb67660):
// SparseCoreScalarAlu0IntegerAddOpcode::Matches (gfc 0x1eb67660)
return (word_0x18 & 0x7E0000000000000) == 0x140000000000000; // 0x140.. >> 53 = 0x0a
```text
opcode 是 `VAL >> tzcnt(MASK)`:`0x140000000000000 >> 53 = 0x0a`。`ScalarAlu1` 从*不同* word 中读取相同 opcode 值 — 它的谓词掩码 `*((_DWORD*)this + 6) & 0xFC000000`(`+0x18` 处的 32 位 word,位 26..31),因此 `AddCbreg`(`0x1eb7b5a0`)测试 `== 0xCC000000`,且 `0xCC000000 >> 26 = 0x33`。相同 opcode 值,lane 特定位位置 — 这正是 `@181`(Alu0)对 `@154`(Alu1)的 bundle 位差异。
> **怪异点 — 编码侧 switch 对 op 的编号不同于 `Matches()` 立即数;相信 `Matches()`。** 在 `ScalarAlu0Encoder::Encode`(`0x1eb693c0`)内部,dispatch `switch(*(a2+88))` 使用*顺序 ODS enum* case 标签(case `0xA` -> `AtomicTile...`,case `0x13` -> `IntegerAdd`),然后通过 `BitCopy(dst, 181, ..., 6)` 写入*硬件* opcode。case 标签是高层 enum ordinal;`BitCopy` 值(以及读回它的 `Matches()` 立即数)才是硅片 opcode。将 switch case 数字当作 opcode 的重新实现者会错误编码每个 op。本页上的值是 `Matches()`/`BitCopy` 硬件值。
---
## 共享 ALU 名册(ScalarAlu0 / ScalarAlu1)
### 平坦 6 位主集合
两个 ALU lane 共享一个 opcode 命名空间:`IntegerAdd=0x0a`、`BitwiseAnd=0x0e`、`CompareIntegerEq=0x1e`,FP-compare 块 `0x2a..0x2f` 在两个 lane 上解码为相同值。它们只在 (a) opcode 落入的 bundle 位 — `ScalarAlu0` 的 `@181`(从 `this+0x18` word 位 53 解码)、`ScalarAlu1` 的 `@154`(从 `this+0x18` word 位 26..31 解码)— 以及 (b) 下列一小组 lane 专属 op 上不同。共享 op 的值跨代不变(vfc `IntegerAdd` 为 `==0x0a`,与 gfc 逐字节相同)。
| Opcode | 助记符 | 类 | Lane |
|---:|---|---|---|
| `0x0a` | `IntegerAdd` | integer ALU | Alu0 + Alu1 |
| `0x0b` | `IntegerAddWithOverflowCheck` | integer ALU | both |
| `0x0c` / `0x0d` | `IntegerSubtractYX` / `...WithOverflowCheck` | integer ALU | both |
| `0x0e` / `0x0f` / `0x10` | `BitwiseAnd` / `BitwiseOr` / `BitwiseXor` | bitwise | both |
| `0x11` / `0x12` | `FloatingPointAdd` / `FloatingPointSubtractYX` | FP ALU | Alu1 |
| `0x13` | `FloatingPointMultiply` | FP ALU | Alu0 |
| `0x14` / `0x15` | `Multiply32BitIntegers` / `Multiply32BitUnsignedIntsReturningHighHalf` | integer mul | Alu0 |
| `0x16` | `DivideWithRemainderXY` | integer div | Alu0 |
| `0x17` / `0x18` / `0x19` | `LogicalShiftLeft` / `LogicalShiftRight` / `ArithmeticShiftRight` `XByYPlaces` | shift | both |
| `0x1a` / `0x1b` | `MaxOfTwoFloatingPointValues` / `MinOfTwoFloatingPointValues` | FP minmax | both |
| `0x1c` / `0x1d` | `MaxOfTwoUnsignedIntValues` / `MinOfTwoUnsignedIntValues` | int minmax | both |
| `0x1e`–`0x23` | `CompareIntegerEq/Ne`, `CompareSignedIntegerGt/Gte/Lt/Lte` | int compare | both |
| `0x24`–`0x27` | `CompareUnsignedIntegerGt/Gte/Lt/Lte` | uint compare | both |
| `0x28` | `CarryOutFromIntegerUnsigned` | carry | both |
| `0x29` | `PredicateOr` | predicate | both |
| `0x2a`–`0x2f` | `CompareFloatingPoint{Eq,Neq,Gt,Gte,Lt,Lte}` | FP compare | both |
| `0x30` | `IsInfOrNan` | FP classify | both |
| `0x31` | `ArithmeticShiftLeftXByYPlacesCheckOverflow` | shift | both |
| `0x3e` | `LogicalShiftLeftOnesXByYPlaces` | shift (GF-only) | Alu0 |
compare 块是稠密的:`0x1e..0x27` 是十个 integer compare(Eq/Ne,然后 signed Gt/Gte/Lt/Lte,再 unsigned Gt/Gte/Lt/Lte),`0x2a..0x2f` 是六个 FP compare。重新实现者可以按线性 opcode 索引解码整个 compare 区域。
### Lane 专属主 ALU op
这些 lane 不能互换。`ScalarAlu1` 承载 SMEM load/store、circular-buffer([CBREG](cbreg.md))和 task-request op;`ScalarAlu0` 承载 FP-multiply / integer-multiply / divide op,以及(在下方 escape 字段中)branch/call/convert/divide-push op。
| Opcode | 助记符 | Lane |
|---:|---|---|
| `0x01` | `ScalarLoadSmemY` | Alu1 |
| `0x02` | `ScalarLoadSmemXY` | Alu1 |
| `0x03` | `ScalarStoreXToSmemY` | Alu1 |
| `0x09` | `DescriptorBasedDma` | Alu1 |
| `0x32` | `ScalarStoreXToSmemSumDestAndY` | Alu1 |
| `0x33` | `AddCbreg` | Alu1 |
| `0x34` | `TaskRequestClearIbuf` | Alu1 |
| `0x35` | `WriteCbreg` | Alu1 |
| `0x36` | `ReadCbreg` | Alu1 |
| `0x37` | `TaskRequest` | Alu1 |
| `0x3c` | `ScalarStoreCircularBuffer` | Alu1 |
| `0x3d` | `ScalarLoadCircularBuffer` | Alu1 |
`AddCbreg=0x33` 由 `(word6 & 0xFC000000) == 0xCC000000` 确认,`0xCC000000 >> 26 = 0x33`;`TaskRequest=0x37` 是 `== 0xDC000000`,`0xDC000000 >> 26 = 0x37`。`FloatingPointAdd=0x11` 只作为 `SparseCoreScalarAlu1FloatingPointAddOpcode`(`0x1eb7b4a0`,`== 0x44000000`,`0x44000000 >> 26 = 0x11`)存在;gfc 中没有 `ScalarAlu0FloatingPointAddOpcode` 类型 — 该 lane 非对称性是结构性的,不是标签伪影。
> **陷阱 — `0x33`/`0x37` 不是共享 op;它们只属于 Alu1。** 将整个 `0x00..0x3f` 范围视为平坦 lane 无关表的调度器会把 `AddCbreg` 或 `TaskRequest` 放入 lane 0,而 lane 0 没有它们的编码器。共享区域是 arithmetic/compare 块(`0x0a..0x31`);memory/CBREG/task op(`0x01..0x09`、`0x32..0x3d`)和 lane 专属 FP/mul/div op 只存在于一个 lane 上。
---
## 四种类 Escape
当主 6 位值命名一个类时,具体 op 位于覆盖该槽位的更宽 escape 字段中。escape *值*与槽位无关(Alu0 和 Alu1 使用相同数字);只有字段的位基址按 lane 不同(`ScalarAlu0` 在结构体中更高,`ScalarAlu1` 更低),对应 `@181`/`@154` opcode 分裂。
| Escape | 字段宽度 | 值范围 | 解码来源 |
|---|---|---|---|
| Control | 11-bit | `0x00..0x1d` | Alu0 word `+0x18` / Alu1 word `+6` |
| Register-read | 17-bit | `0x280..0x28d` | `(word3 & 0x7FFFC0000000000)` Alu0 |
| Config-set | 16-bit | `0x4001..0x4005` | `(word3 & 0x7FF03E000000000)` Alu0 |
| Divide-push | `0x16xxxx` | `0x160001..0x160002` | `(word3 & 0x7E003E000000000)` Alu0 |
### Control op(11 位 escape)
这些是 branch/call/fence/convert op。escape 字段位于 6 位主字段之上(Alu0 结构体位 48 / Alu1 位 21)。`Halt`(`0x1eb67500`)确认了 base:`(word15 & 0x7FF) == 0` -> control `0x00`。`BranchAbsolute`(`0x1eb67d40`):`(word3 & 0x7FF000000000000) == 0x4000000000000`,`0x4000000000000 >> 48 = 0x04`。
| Opcode | 助记符 | Opcode | 助记符 |
|---:|---|---:|---|
| `0x00` | `Halt` | `0x0d` | `MoveY` |
| `0x02` | `PopDrf` | `0x0e` | `CountLeadingZeros` |
| `0x03` | `Delay` | `0x0f` | `Ceiling` |
| `0x04` | `BranchAbsolute` | `0x10` | `Floor` |
| `0x05` | `BranchRelative` | `0x18` | `BranchRelativeRotatingPreg` (GF, Alu0) |
| `0x06` | `CallAbsolute` | `0x1a` | `ScalarFenceSelect` |
| `0x07` | `CallRelative` | `0x1c` | `ScalarFenceStreamHbm` |
| `0x09` | `ScalarFence` | `0x1d` | `ScalarFenceStreamSpmem` |
| `0x0b` | `ConvertInt32ToFloat32` | | |
| `0x0c` | `ConvertFloat32ToInt32` | | |
`ScalarAlu1` 向此集合添加三个 control op:`0x14 ReadDreg`、`0x15 WriteDreg`、`0x1b MoveCbreg`。`BranchSreg`/`CallSreg` 作为 `ScalarAlu0` 6 位字段形式出现(值 4/5),不同于上方的 absolute/relative branch。
### Register-read op(17 位 escape)
门控 SCS 前进的芯片硬件寄存器读取。`ReadRegisterLccLow`(`0x1eb67560`):`(word3 & 0x7FFFC0000000000) == 0xA000000000000`,`0xA000000000000 >> 42 = 0x280`。
| Opcode | 助记符 | Opcode | 助记符 |
|---:|---|---:|---|
| `0x280` | `ReadRegisterLccLow` | `0x288` | `ReadRegisterTracemark` |
| `0x281` | `ReadRegisterLccHigh` | `0x289` | `ReadRegisterTileid` |
| `0x282` | `ReadRegisterGtcLow` | `0x28a` | `ReadRegisterTaskBitmap` |
| `0x283` | `ReadRegisterGtcHigh` | `0x28b` | `ReadRegisterFenceStatus` |
| `0x286` | `ReadRegisterSparseCoreId` | `0x28c` | `ReadRegisterDifDepthRegister` |
| `0x287` | `ReadRegisterTag` | `0x28d` | `ReadRegisterDmaCreditRegister` |
### Config-set op(16 位 escape)
DMA-credit / tag / filter / throttle 写入。`SetDmaCredit`(`0x1eb67ac0`):`(word3 & 0x7FF03E000000000) == 0x8006000000000`。
| Opcode | 助记符 |
|---:|---|
| `0x4001` | `SetTag` |
| `0x4002` | `SetIndirectFilterValue` |
| `0x4003` | `SetDmaCredit` |
| `0x4004` | `SetDmaThrottleSflagRange` |
| `0x4005` | `SetRotatingPredicateRegister` (GF, Alu0) |
### Divide-push op(仅 Alu0)
推送 quotient 或 remainder 的双结果 divide。`DivideWithRemainderXYPushQuotient`(`0x1eb67e60`):`(word3 & 0x7E003E000000000) == 0x2C0002000000000`;主部分 `0x2C0000000000000 >> 53 = 0x16`(`DivideWithRemainderXY` base)和 sub 部分 `0x2000000000 >> 37 = 1` 给出 `0x160001` 形式。
| Opcode | 助记符 |
|---:|---|
| `0x160001` | `DivideWithRemainderXYPushQuotient` |
| `0x160002` | `DivideWithRemainderXYPushRemainder` |
> **怪异点 — register-read 和 config-set 值无法放入 6 位主字段;它们是更宽的 escape 字段。** 看到 “`ReadRegisterGtcLow = 0x282`” 的重新实现者必须将 `0x282` 放入 17 位 register-read 字段,而不是 6 位 opcode 字段(后者只覆盖 `0x00..0x3f`)。主 opcode 标记*类*(register-read / config-set);具体 `0x28x` / `0x400x` 值位于其上的重叠 escape 字段。escape 字段在物理上与槽位的操作数选择位重叠,这就是 register-read op 不携带 x0/x1 操作数的原因。
---
## ScsScalarMisc — Sync / Atomic 槽位
### 复合编码
`ScsScalarMisc`(op `@127`)是 sync/atomic 引擎。它不携带 FP,也不携带 branch;它保存协调 SC tile 彼此之间以及与 TensorCore 之间关系的 sync-flag 家族,再加上从 ALU lane 复制来的 integer-ALU 子集。其 opcode 空间高度复合(形式 B):6 位 base 命名一个类,5 位 sub-opcode — 结构体相对位 47(`0xF800000000000`)处的 sync/atomic *mode*,或位 58(`0x7C00000000000000`)处的 extended-ALU 类 — 选择确切 op。
| Base | 类 | Sub 字段 | 成员(sub 值) |
|---:|---|---|---|
| `0x00` | extended-ALU | bit 58 | `CoreInterrupt(0)`, `MoveY(13)`, `CountLeadingZeros(14)` |
| `0x01` | Sync compare-and-set | bit 47 | `SyncDone(0)`, `SyncEqual(1)`, `SyncNotEqual(2)`, `SyncGreater(3)`, `SyncGreaterOrEqual(4)`, `SyncLess(5)`, `SyncNotDone(6)`, `SyncEqualOrDone(7)`, `SyncNotEqualOrDone(8)`, `SyncGreaterOrDone(9)`, `SyncGreaterOrEqualOrDone(10)`, `SyncLessOrDone(11)` |
| `0x02` | SyncWatch | bit 47 | `SyncWatch{Done,Equal,NotEqual,Greater,GreaterOrEqual,Less,NotDone,EqualOrDone,NotEqualOrDone,GreaterOrDone,GreaterOrEqualOrDone,LessOrDone}` (modes 0..11) |
| `0x03` | SyncWatch escape | bit 58 | `SyncWatchWait(0)`, `SyncWatchWaitSelect(1)` |
| `0x04` | SyncWatch escape | bit 58 | `SyncWatchEnd(0)`, `SyncWatchEndSelect(1)` |
| `0x05` | set-sync | bit 47 | `SetSyncFlag(0)`, `SetSyncDone(1)`, `AddSyncFlag(2)` |
| `0x06` | read-sync | bit 58 | `ReadSyncFlag(0)`, `ReadSyncDone(1)`, `ReadSyncPublicAccess(2)` |
| `0x07` | barrier | bit 47 | `SyncBarrier(0)`, `SetPOrTState(4)` |
| `0x08` | Atomic | bit 47 | `AtomicTile{Write(0),Add(1),WriteSetDone(2),AddSetDone(3),WriteSetDoneInverted(4),AddSetDoneInverted(5)}`, `AtomicRemote{Write(6),Add(7),WriteSetDone(8),AddSetDone(9),WriteSetDoneInverted(10),AddSetDoneInverted(11)}` |
`SetSyncFlag`(base `0x05`)由 `((base) ^ 5 | (word & 0xF800000000000)) == 0`(sub 0)确认;`AtomicTileAdd` 由 base `^8` / sub `^0x800000000000` 确认 -> base 8,sub 1;`CoreInterrupt` 是全零 opcode(base 0,extended-ALU sub 0);`CountLeadingZeros` 是 base 0,extended-ALU sub `0x3800000000000000 >> 58 = 14`。
Atomic base `0x08` sub 字段是一个小型乘积:`{Tile, Remote} x {Write, Add} x {plain, SetDone, SetDoneInverted}`,布局使低位选择 Add-vs-Write,下一对选择 set-done 修饰符,而 `+6` 将 Tile 切换为 Remote。
### 从 ALU 集合镜像的平坦 6 位 op
`ScsScalarMisc` 还携带平坦形式 A 的 6 位 op,即一个 integer-ALU 子集加上 sync-state 读取和 trace op:
| Opcode | 助记符 | Opcode | 助记符 |
|---:|---|---:|---|
| `0x0a` | `IntegerAdd` | `0x27` | `CompareUnsignedIntegerLte` |
| `0x0b` | `IntegerAddWithOverflowCheck` | `0x28` | `CarryOutFromIntegerUnsigned` |
| `0x0c` / `0x0d` | `IntegerSubtractYX` / `...WithOverflowCheck` | `0x29` | `PredicateOr` |
| `0x0e` / `0x0f` / `0x10` | `BitwiseAnd` / `BitwiseOr` / `BitwiseXor` | `0x2a` | `ReadSyncStateValue` |
| `0x17` / `0x18` / `0x19` | shift `XByYPlaces` (LSL/LSR/ASR) | `0x2b` | `ReadSyncStateDone` |
| `0x1c` / `0x1d` | `MaxOfTwoUnsignedIntValues` / `MinOf...` | `0x2d` | `SetTracemark` |
| `0x1e`–`0x23` | int compare Eq/Ne + signed Gt/Gte/Lt/Lte | `0x2e` | `Trace` |
| `0x24`–`0x26` | unsigned compare Gt/Gte/Lt | `0x2f` | `SetSyncFlagPublicAccess` |
| `0x31` | `ArithmeticShiftLeftXByYPlacesCheckOverflow` | `0x38` | `SmemFetchAndAdd` |
`IntegerAdd=0x0a` 由 `((word>>63) & 0x3F) == 0x0a` 确认。integer-ALU 子集正是 lane 无关的 arithmetic/compare 块 — Misc 槽位省略 FP、multiply、divide、branch 和 SMEM load/store,因此它是专用 sync/atomic + 轻量 integer lane。
> **陷阱 — `ScsScalarMisc` 在 gfc 中持有两组平行 op-form 家族。** 二进制同时发出 `SparseCoreScalarMisc<Op>Opcode`(82 种)和 `SparseCoreScsScalarMisc<Op>Opcode`(81 种),相同 op 的 `Matches()` 谓词逐字节相同(例如 `SyncEqual` 在两者中都解码为 base 1 / mode 1)。它们是同一硬件 opcode 的两种类型拼写;槽位编码器 `SparseCoreScsScalarMiscEncoder`(`0x1eb914a0`)接受一个 `SparseCoreScalarMisc` 参数。重新实现者需要一个名册,而不是两个 — 重复类型集不会让编码空间翻倍。
---
## 逐代差异
标量 ISA 对共享 op 跨代不变(vfc `IntegerAdd` 解码为 `==0x0a`,与 gfc 逐字节相同);差异很小,集中在 halt/yield 和 rotating-predicate 环。下方存在性声明由每个 gen 命名空间中对应 `Matches()` 类型的存在(或不存在)确认:存在 `vfc SparseCoreScalarAlu0HaltYieldOpcode`,不存在 gfc 版本;存在 `gfc SparseCoreScalarAlu0SetRotatingPredicateRegisterOpcode`,不存在 vfc 版本。
| 方面 | Viperfish (vfc) | Ghostlite (glc) | 6acc60406 (gfc) |
|---|---|---|---|
| 主 opcode 宽度 | 6-bit | 6-bit | 6-bit |
| Opcode bundle 位 | 127 / 154 / 181 | identical | identical |
| `ScsScalarMisc` op-form | ~100 | (transitional) | 82 |
| `ScalarAlu0` op-form | 79 | (transitional) | 78 |
| `ScalarAlu1` op-form | 84 | (transitional) | 82 |
| `IntegerAdd` 值 | `0x0a` | `0x0a` | `0x0a` |
| VF-only op | `HaltYield`, `HaltYieldConditional`, `ReadRegisterYieldRequest`, `ScalarFenceScmf` | — | — |
| GF-only op | — | — | `BranchRelativeRotatingPreg`, `LogicalShiftLeftOnesXByYPlaces`, `SetRotatingPredicateRegister`, `MoveCbreg`, `ScalarStoreXToSmemSumDestAndY` |
> **注意 — 6acc60406 简化了 sync 模型。** VF/GL 的 `ScsScalarMisc` 携带双通道 sync 家族(`Set{Both,Other}Sync*`、`Add{Both,Other}SyncFlag`)和一个 `Yieldable*` sync 集;gfc 名册删除了两者(降到 82 种),并添加单个 `SetPOrTState`。解释是非 yielding tile 调度器 — sync primitive 更少、延迟确定,由 rotating-predicate 环驱动。面向 6acc60406 的重新实现者不得发出 `Yieldable*` 或 `*Both*`/`*Other*` sync op,也不得发出 VF halt/yield op;它们在 gfc 中没有编码器类型。
---
## 函数映射
除非另有说明,所有地址都是 gfc(6acc60406);`Matches()` 立即数是权威 opcode 值。
| 符号 | 地址 | Opcode 证据 |
|---|---|---|
| `SparseCoreScalarMiscIntegerAddOpcode::Matches` | `0x1ebabf00` | 形式 A `((w>>63)&0x3F)==0x0a` |
| `SparseCoreScalarMiscAtomicTileAddOpcode::Matches` | `0x1ebabbe0` | 形式 B base 8 / sub 1 |
| `SparseCoreScalarMiscSyncEqualOpcode::Matches` | `0x1ebab320` | 形式 B base 1 / mode 1 |
| `SparseCoreScalarMiscSetSyncFlagOpcode::Matches` | (gfc) | 形式 B base 5 / sub 0 |
| `SparseCoreScalarMiscCoreInterruptOpcode::Matches` | (gfc) | 形式 B base 0 / ext-ALU sub 0 |
| `SparseCoreScalarMiscCountLeadingZerosOpcode::Matches` | (gfc) | 形式 B base 0 / ext-ALU sub 14 |
| `SparseCoreScalarAlu0IntegerAddOpcode::Matches` | `0x1eb67660` | 形式 C `(w&0x7E0...)==0x140...` -> 0x0a |
| `SparseCoreScalarAlu0BitwiseAndOpcode::Matches` | (gfc) | 形式 C -> 0x0e |
| `SparseCoreScalarAlu0CompareIntegerEqOpcode::Matches` | (gfc) | 形式 C -> 0x1e |
| `SparseCoreScalarAlu0HaltOpcode::Matches` | `0x1eb67500` | control escape `(w15&0x7FF)==0` -> 0x00 |
| `SparseCoreScalarAlu0BranchAbsoluteOpcode::Matches` | `0x1eb67d40` | control escape -> 0x04 |
| `SparseCoreScalarAlu0ReadRegisterLccLowOpcode::Matches` | `0x1eb67560` | 17 位 escape -> 0x280 |
| `SparseCoreScalarAlu0SetDmaCreditOpcode::Matches` | `0x1eb67ac0` | 16 位 escape -> 0x4003 |
| `SparseCoreScalarAlu0DivideWithRemainderXYPushQuotientOpcode::Matches` | `0x1eb67e60` | divide-push -> 0x160001 |
| `SparseCoreScalarAlu0SetRotatingPredicateRegisterOpcode::Matches` | `0x1eb67b00` | config escape,GF-only |
| `SparseCoreScalarAlu1FloatingPointAddOpcode::Matches` | `0x1eb7b4a0` | 形式 C `==0x44000000` -> 0x11,Alu1-only |
| `SparseCoreScalarAlu1AddCbregOpcode::Matches` | `0x1eb7b5a0` | 形式 C `(w6&0xFC000000)==0xCC000000` -> 0x33 |
| `SparseCoreScalarAlu1TaskRequestOpcode::Matches` | `0x1eb7b620` | 形式 C `==0xDC000000` -> 0x37 |
| `SparseCoreScalarAlu0Encoder::Encode` | `0x1eb693c0` | opcode `BitCopy(.,181,.,6)`;escapes @176/170/165 |
| `SparseCoreScsScalarMiscEncoder::Encode` | `0x1eb914a0` | opcode `BitCopy(.,127,.,6)`;pred @133/136/137 |
| `BitCopy` | `0x1fa0a900` | LE 打包器 `(dst, dst_bitoff, src, src_bitoff, nbits)` |
跨代锚点:vfc `SparseCoreScalarMiscIntegerAddOpcode::Matches` `0x1e8ff7c0` 解码为 `==0x0a`(跨代不变性);vfc `SparseCoreScalarAlu0HaltYieldOpcode::Matches` `0x1ee81460` 存在(VF-only)。`TensorCore*` 和 `SparseCoreTec*` op-form 类型共享 gfc `isa` 命名空间 — 要精确匹配 `SparseCoreScalar`/`SparseCoreScsScalar` 前缀,以免将 TC 或 TEC 谓词拉入 SCS 标量名册。
---
## 注意事项
- **Opcode 真相来源是 `Matches()` 立即数,而不是编码侧 switch。** `Encoder::Encode` dispatch 使用顺序 ODS enum ordinal 作为 `switch` case 标签;只有它写入的 `BitCopy` 值(以及读回该值的 `Matches()` 值)才是硅片 opcode。解码和编码在 `Matches()` 值上达成一致;switch case 数字是内部 ordinal。
- **Misc 槽位中没有 FP,也没有 branch。** `ScsScalarMisc` 仅是 sync/atomic + integer-ALU。FP arithmetic、FP compare、branch、call、multiply、divide 和 SMEM load/store 位于 ALU lane 中。调度器不得将 sync op 放入 ALU lane,也不得将 FP/branch op 放入 Misc。
- **Lane 非对称性是结构性的。** `ScalarAlu1` 拥有 SMEM load/store、CBREG、Dreg、FP add/sub 和 task-request;`ScalarAlu0` 拥有 branch/call/convert/divide-push 以及 FP/integer multiply。共享 arithmetic/compare 块 `0x0a..0x31` 在两者上解码相同,但 lane 专属 op 只在一个 lane 上有编码器类型。
- **复合 sub-opcode 绝对 bundle 位是部分推断的(HIGH / LOW)。** 6 位主 opcode bundle 位已确认(`@127`/`@154`/`@181`)。复合 `ScsScalarMisc` sub-opcode 字段恢复为*结构体相对*偏移(sync/atomic mode 在位 47,extended-ALU 类在位 58);其*绝对* bundle 位(槽位基址 111 + 槽内偏移,按 [SCS 引擎](scs-engine.md) 的 27 位模板)并未针对约 50 个复合 Misc op 逐个固定。按主 opcode + 结构体相对 sub 字段解码每个 op;sub 字段的绝对位图仍是一个剩余缺口。
- **`FloatingPointMultiply=0x13` 以及 FP minmax/compare 值是 HIGH,不是 CONFIRMED。** integer/bitwise/shift/compare 以及 lane 专属 `AddCbreg`/`TaskRequest`/`FloatingPointAdd` 值都直接从其 `Matches()` 立即数读取;FP-multiply、FP-minmax(`0x1a/0x1b`)和 FP-compare(`0x2a..0x2f`)值来自 op-form 名册顺序和抽样子集,而不是完整逐 op 立即数扫描。
---
## 相关组件
| 名称 | 关系 |
|---|---|
| `SparseCoreScsScalarMiscEncoder::Encode`(`0x1eb914a0`) | 写入 `ScsScalarMisc` opcode `@127` 和 predication header |
| `SparseCoreScalarAlu0Encoder::Encode`(`0x1eb693c0`) | 写入 `ScalarAlu0` opcode `@181` 和 escape 字段 |
| `BitCopy`(`0x1fa0a900`) | 每个槽位编码器用于写入 opcode 位的 LE 打包器 |
| 每个 op 的 `SparseCore<Slot><OpName>Opcode::Matches()` | opcode->助记符来源 — 每代每个 opcode 一个类型 |
## 交叉引用
- [SCS(标量)引擎](scs-engine.md) — 32 字节 bundle、槽位基址(111/138/165),以及此名册 opcode 字段所在的 27 位标量槽位模板。
- [向量 Opcode 枚举](vector-opcode-enum.md) — TEC 向量槽位 opcode 名册(VectorAlu / Load / Store / Result / Extended);本页的向量侧对应物。
- [TAC 引擎](tac-engine.md) — tile-fetch DMA issuer(VF/GL),其 Dma/Stream 形式复用 SCS 标量 lane bundle 布局。
- [SparseCore 概览](overview.md) — 三类引擎、按代存在性,以及 `TpuSequencerType` codec-template enum。
- [M-Register 谓词字](m-register-predicate.md) — 覆盖在每个标量槽位 opcode 字段之上的 3 位 / 4 位 predication header。
- [CBREG 循环缓冲寄存器](cbreg.md) — 此处枚举的 Alu1 `AddCbreg`/`ReadCbreg`/`WriteCbreg`/`MoveCbreg` op 所驱动的 circular-buffer 寄存器。
- **二进制:** `extracted/libtpu-0.0.40-cp314-cp314-manylinux_2_31_x86_64/libtpu/libtpu.so`(build-id `89edbbe81c5b328a958fe628a9f2207d`)
- **索引项:** 第 IX 部分 — SparseCore & BarnaCore / SparseCore ISA — [返回索引](../index.md)