Memory-Load Slot
本页中的每个地址、字段偏移、opcode 值和字符串,均从
libtpu-0.0.40-cp314wheel 中的libtpu.so按字节精确读取(BuildID md589edbbe81c5b328a958fe628a9f2207d,未 stripped,含完整 C++ 符号)。.text/.rodata映射满足 VA == file offset。其他 wheel 版本会不同。
摘要
memory-load slot 是在单个 VLIW issue word 内把片上内存搬入计算寄存器文件的 bundle slot。它是 Memory-Store Slot 的读侧镜像。它不同于芯片内 DMA:DMA 通过 descriptor 在内存 tier 之间搬运块,并携带 sync flag 和 done-count;而 load slot 从某个 tier 搬运一个寄存器大小的数据到 vreg/sreg,并携带 destination register 和 sublane mask。binary 中的边界很清楚,这也是 load slot 没有 tier-selector bit 的架构原因;tier 由 op 占用的哪个 slot选择。
有三个 load tier 和四个物理落点:VMEM → vreg(vector load)、SMEM → sreg(scalar load)、CMEM → vreg(仅 Pufferfish 的专用 slot),以及 SPMEM → vreg(SparseCore tile load)。每一种都是不同的 bundle slot。单个 TensorCore load slot 是一个 discriminated union:1-/2-/3-bit sub-opcode 字段选择 addressing-mode variant(base+offset、base-only、strided、indexed/gather、circular-buffer-relative、sublane-shuffled)。逐字段 bit 位置从逐代 <Field>::GetConcatenatedValue() accessor 恢复;每个 accessor 都是一条 mov <word>; shr <shift>; and <mask> 指令,用来钉住字段在 decoded slot struct 中的精确位置。
核心的逐代故事是字段重打包:相同的逻辑字段(opcode、dest、sublane-mask、base-address、offset、stride、predication)在每一代都会移动到不同 bit 位置,并且 destination-register 字段在 v5 边界从 5 bit 加宽到 6 bit(vector register file 翻倍)。codename → slot-list 来自逐代 TensorCoreCodecBase<…Decoder, …Encoder, …> template argument 顺序;load slot 的数量以及 CMEM 是否获得自己的 slot 本身也是逐代差异。
对重新实现而言,契约是:逐代 slot-list(1/2/3 个 VMEM-load slot;CMEM slot 仅 Pufferfish)、addressing-mode sub-opcode discriminator 及其逐代取值、逐字段 word/shift/mask 布局、5→6-bit dest 加宽,以及 slot-selects-tier 模型。
| Slot role | 将一个寄存器大小的数据从 VMEM/SMEM/CMEM/SPMEM 搬入 vreg/sreg |
| Tier select | 由占用的 slot 决定(无 tier bit)— VMEM=VectorLoad,SMEM=Scalar*,CMEM=CmemLoad(仅 PF),SPMEM=SparseCore VectorLoad |
| PXC VMEM-load encoder | pxc::isa::TensorCoreVectorLoadEncoder::Encode @ 0x1ee287e0 |
| PXC CMEM-load encoder | pxc::isa::TensorCoreCmemLoadEncoder::Encode @ 0x1ecf89a0 |
| Sub-opcode discriminator | …VectorLoad…Opcode::Matches — PXC TensorCoreVectorLoadVmemLoadOpcode @ 0x1ee28100;V5+ TensorCoreVectorLoad0VectorLoadOpcode @ VXC 0x1f006960,GLC 0x1f3a2460,GFC 0x1f9e97e0 |
| Field accessor shape | <Field>::GetConcatenatedValue = (word@off >> shift) & mask(精确 bit 位置) |
| Dest field width | JF/PF 上为 5-bit,VF/GL/GFC 上为 6-bit(v5 起 vector register file 翻倍) |
| Register files | V0..V63(vreg,V5+ 为 64 / JF–PF 为 32),S0..S31(32 sreg),CB0..CB15(SparseCore),predicate file 15 entries(JF–PF)/ 14(V5+)— 但 slot 的 Predication field 是 5-bit,编码 preg index 外加 15=always / 31=never sentinel |
Load Slot 是逐代 VLIW Sub-Bundle
每一代的 TensorCore bundle 都是固定位置 slot 组成的 struct;slot 顺序是逐代 TensorCoreCodecBase<TensorCoreBundle, …Decoder, …Encoder, …> 的 template-argument 顺序。load slot 的数量,以及 CMEM 是否拥有专用 slot,是主要的逐代差异。CMEM 只在 Pufferfish 上是一等对象(它有自己的 bundle slot);Viperfish/Ghostlite/6acc60406 完全没有 *Cmem* ISA op family,并将释放出的 bundle 宽度复用于第 2/第 3 个 VMEM-load slot。
| Gen | VMEM-load slots (TC) | CMEM-load slots | SMEM scalar-load slots |
|---|---|---|---|
| Jellyfish | 1(slot-mask bit 0x040) | 0 | 2(scalar_0/scalar_1) |
| Dragonfish | 1(= Jellyfish codec) | 0 | 2 |
| Pufferfish | 1(VectorLoad) | 1(CmemLoad,专用) | 2(Scalar0/Scalar1) |
| Viperfish | 3(VectorLoad0/1/2) | 0 | 2(ScalarAlu0/ScalarAlu1) |
| Ghostlite | 2(VectorLoad0/1) | 0 | 2(ScalarAlu0/ScalarAlu1) |
| 6acc60406 | 2(VectorLoad0/1) | 0 | 2(ScalarAlu0/ScalarAlu1) |
在 Pufferfish 上,VectorLoad slot 的 control fields 落在绝对 bundle bits 119..140(VectorLoadEncoder::Encode body @ 0x1ee287e0 通过 BitCopy(dst, 136, …, 5) 写 Predication,Dest BitCopy(dst, 129, …, 5),Stride …126,3,Offset …124,2,BaseAddress …122,2,SublaneMask …119,3,Opcode …134,2);CmemLoad control fields 落在 103..118(CmemLoadEncoder::Encode body @ 0x1ecf89a0 写 Predication BitCopy(dst,114,5),Opcode …113,1,SublaneMask …110,3,BaseAddress …108,2,Offset …106,2,Stride …103,3)— 见 Pufferfish 51B Bundle。两个 control region 互不重叠,所以一个 CMEM load 和一个 VMEM load 可以在同一个 bundle cycle 中 issue;这是唯一具备此性质的世代(它们共享的 Vs0/Vs1/Vs2 和 Imm 字段落在更高且互不重叠的 bits 241..256+)。Viperfish 上的三个 VMEM-load slot 由三个不同的 per-slot encoder 符号 vxc::isa::TensorCoreVectorLoad{0,1,2}Encoder::Encode 确认。
NOTE — CMEM 在 Pufferfish 上需要自己的 slot 的架构原因,正是 load slot 的 wire encoding 不携带 tier selector(见 The Slot-Selects-Tier Model)。要在同一 cycle 读取 CMEM 和 VMEM,就需要两个物理不同的 slot。v5 去掉 CMEM 后,该 slot 被移除,宽度转给额外的 VMEM-load slot。
VMEM-Load Encoder Algorithm(VectorLoadEncoder::Encode)
Pufferfish VMEM-load slot 由 pxc::isa::TensorCoreVectorLoadEncoder::Encode(TensorCoreVectorLoad const&, Span<uint8>)(0x1ee287e0)打包;它是 cmem_load Encode 的读侧镜像。与每个 Pufferfish slot 一样,它通过对共享 bit-packing primitive BitCopy(buf, abs_bit, &field, src_bit=0, nbits)(0x1fa0a900)的一次调用写入每个字段,并且 dst_bit 参数就是字面量绝对 bundle bit,不需要反推 shift 算术(见 Pufferfish 51B Bundle §The Direct-BitCopy Model)。该结构从反汇编按字节精确得到:predication 从 proto[+0x1c] 暂存并先被无条件写入,然后 proto[+0x50] 处的 oneof discriminator 通过 self-relative jump table(lea -0x135e338d(%rip),%rcx → table base 0xb8454a4;cmp $0x9,%rax; ja <out-of-range>)选择十种行为之一,VmemLoad issue arm 重放下面的字段序列,每个字段由 TensorCoreVectorLoad_VmemLoad_globals_ submessage(0x22410b00)上的 per-field has-bit gate:
// pxc::isa::TensorCoreVectorLoadEncoder::Encode(proto, buf) @ 0x1ee287e0 (decoded byte-exactly)
pred = proto[+0x1c]; // movslq 0x1c(%rsi)
BitCopy(buf, 136, &pred, 0, 5); // Predication @136/5 — written first, unconditionally
tag = proto[+0x50]; // oneof discriminator; jump table over tags 0..9
if (tag > 9) abort(); // cmp $0x9; ja -> out-of-range trap
// dispatch via table @ 0xb8454a4 ; tag 5 (Noop) forces pred=31, tag 6 is the VmemLoad issue arm:
if (tag == NOOP) { pred = 31; BitCopy(buf, 136, &pred, 0, 5); return OK; } // kNeverExecute
// ---- VmemLoad issue arm (tag 6): inner = the VmemLoad submessage (or _globals_ default if clear) ----
inner = proto[+0x48]; // VmemLoad submessage
BitCopy(buf, 134, &Opcode, 0, 2); // Opcode @134/2 — addr-mode discriminator
if (inner.has[0x10] & 0x01) BitCopy(buf, 129, &inner.Dest, 0, 5); // Dest vreg @129/5
if (inner.has[0x10] & 0x02) BitCopy(buf, 126, &inner.Stride, 0, 3); // Stride @126/3 (off +0x1c)
if (inner.has[0x10] & 0x04) BitCopy(buf, 124, &inner.Offset, 0, 2); // Offset @124/2 (off +0x20)
if (inner.has[0x10] & 0x08) BitCopy(buf, 122, &inner.BaseAddress, 0, 2); // BaseAddress @122/2 (off +0x24)
if (inner.has[0x10] & 0x10) BitCopy(buf, 119, &inner.SublaneMask, 0, 3); // SublaneMask @119/3 (off +0x28)
// ----- shared operand pool (co-allocated across slots; abs 241/246/251 + 16-bit imms) -----
if (inner.has[0x10] & 0x20) BitCopy(buf, 251, &inner.Vs2, 0, 5); // Vs2 register selector
if (inner.has[0x10] & 0x40) BitCopy(buf, 246, &inner.Vs1, 0, 5); // Vs1
if (inner.has[0x10] & 0x80) BitCopy(buf, 241, &inner.Vs0, 0, 5); // Vs0 (dest VREG / base)
if (inner.has[0x11] & 0x01) BitCopy(buf, 304, &inner.Imm, 0, 16); // shared immediate word
if (inner.has[0x11] & 0x02) BitCopy(buf, 288, &inner.Imm, 0, 16); // shared immediate word
if (inner.has[0x11] & 0x04) BitCopy(buf, 272, &inner.Imm, 0, 16); // shared immediate word
if (inner.has[0x11] & 0x08) BitCopy(buf, 256, &inner.Imm, 0, 16); // shared immediate worddst-bit 常量直接来自每次 call 1fa0a900 <BitCopy> 前的 mov $imm,%esi:0x88=136(pred)、0x86=134(opcode)、0x81=129(dest)、0x7e=126(stride)、0x7c=124(offset)、0x7a=122(base)、0x77=119(sublane),以及 shared-pool 0xfb=251 / 0xf6=246 / 0xf1=241(Vs2/Vs1/Vs0,w5)和 0x130=304 / 0x120=288 / 0x110=272 / 0x100=256(immediates,w16)。它们与下面的 dedicated-region map 以及 cmem-load slot 的高位 shared pool(Vs 在 241/246/251,immediates 在 256/272/288/304 — 见 cmem_load §The Shared Operand Pool)逐 bit 一致,确认这两个 memory-read slot 从同一个物理 Y-register/immediate pool 取数。
NOTE — predication 在 tag 被读取之前就已写入。 encoder 暂存
proto[+0x1c],并在加载proto[+0x50]oneof discriminator 之前发出 @136/5 predicationBitCopy。因此 empty(tag-0)或 Noop(tag-5)slot 仍会携带一个 5-bit predication 值;idle encoding 为31(kNeverExecute),与 cmem_load slot 完全一致。两个 memory-read slot 共享这种 idle-encoding 约定;清零的 bundle buffer 不是 idle marker(predicate0是 live op)。QUIRK — oneof 覆盖十个 arm,而不是三个。 discriminator 上的
cmp $0x9,%rax; ja边界意味着 VMEM-load oneof 最多有十个 tag(0..9),而 cmem_load slot 只有三个(0/5/6)。额外 arm 是 addressing-mode variant(VmemLoad、VmemLoadShuffled、VmemLoadIndexedIar0/1)加上 empty/Noop idle 形式;每个都是不同的 jump-table arm,会用不同的 @134Opcode常量重放同一个BitCopy字段序列。重新实现者必须把 discriminator 设为 10 个 arm,并让每个 non-idle arm 都通过相同 field map;addressing mode 之间只有 @134 的 2-bit Opcode 值不同。
Load Op List(Addressing-Mode Sub-Opcodes)
每个 load slot 都是一个 discriminated union;sub-opcode 字段选择 addressing-mode variant。各 family 的 variant:
PXC TensorCore VectorLoad(VMEM → vreg) — byte @0x18 bits 6-7(mask 0xC0)处的 2-bit sub-opcode。discriminator 是 TensorCoreVectorLoadVmemLoadOpcode::Matches(@ 0x1ee28100,body (*((_BYTE*)this + 24) & 0xC0) == 0)中的字面 (byte@0x18 & 0xC0) 测试:
| value | variant | 含义 |
|---|---|---|
00 | VmemLoad | base + immediate offset |
01(0x40) | VmemLoadShuffled | base + offset,加载时 sublane shuffle |
10(0x80) | VmemLoadIndexedIar0 | 通过 index-address-register 0 gather |
11(0xC0) | VmemLoadIndexedIar1 | 通过 index-address-register 1 gather |
PXC TensorCore CmemLoad(CMEM → vreg) — byte @0x16 bit 1 处的 1-bit sub-opcode(TensorCoreCmemLoadCmemLoadOpcode::Matches @ 0x1ecf8800,body (*((_BYTE*)this+22) & 2) >> 1);当 word @0x10 的 bits 0x7c000000000000 全部置位时,Noop(slot-idle)variant 匹配;其 Matches(@ 0x1ecf87e0)为 (~word@0x10 & 0x7c000000000000) == 0。
PXC TensorCore Scalar1 ScalarLoadSmem(SMEM → sreg) — word @0x30 bits 50-55(mask 0xfc000000000000)处的 6-bit opcode。ScalarLoadSmemOpcode::Matches(@ 0x1ed27c60)测试 (word@0x30 & 0xfc000000000000) == 0x10000000000000(value 0x4 → ScalarLoadSmem);value 0x5 → ScalarLoadSmemOffset(Sreg ← SMEM[Sreg+imm])。
VXC/GLC/GFC TensorCore VectorLoad0/1/2(VMEM → vreg) — multi-bit sub-opcode(位置见下)。Variant:VectorLoad(base+offset)、VectorLoadBase(仅 base reg,无 offset)、VectorLoadShuffled / VectorLoadShuffledBase(加载时 shuffle)、VectorLoadIndexed0/1(通过 IAR0/IAR1 gather)、ReadIar0 / ReadIar1(把 index-address-register 读入 vreg 以暂存 gather),以及 Compact_* 形式(Compact_VectorLoad、Compact_ReadIar0/1、Compact_VectorLoadIndexed0/1、Compact_VectorLoadShuffled),当字段适配时可将 load 打包进更窄 slot。
VXC/GLC/GFC ScalarAlu1 ScalarLoadSmem — ScalarLoadSmemY(Sreg ← SMEM[Y imm])和 ScalarLoadSmemXY(Sreg ← SMEM[X base-Sreg + Y imm])。
SparseCore(vfc / glc::sparsecore / gfc::sparsecore)VectorLoad(SPMEM → vreg) — TileSpmemLoad(base+offset)、TileSpmemLoadCircularBuffer(CB-register-relative)、TileSpmemIndexedLoad(通过 Index gather)、TileSpmemIndexedLoadCircularBuffer(indexed + CB)。包含丰富 predication(NormalPredication、RotatePredication、IsRotatePredication、PredicationInversion)。
scalar/SparseCore/BarnaCore load 的 MC-layer mnemonic(TensorCore VMEM/CMEM load 经由 proto codec,而不是 MC table)记录在 MC-Emitter 页面:SLDi/SLDri/SLDrr(TC scalar)、scVLD*/scSLD*/scSLDCBREG* family(SparseCore),以及 bcVLDi/bcVLDr/bcVLD_aliaddr{i,r}(BarnaCore)。
Bit-Field Layout(已解码的 GetConcatenatedValue Accessors)
每个逐代 Field class 都暴露 GetConcatenatedValue(),其 body 字面上就是 (word@off >> shift) & mask,因此字段的精确位置可直接从反汇编读取,无需推断。slot struct 在固定 member offset(取决于 slot,@0x10、@0x18、@0x20、@0x30、@0x40)处以 64-bit word 保存原始 bundle bits。下面的偏移是 decoded slot struct 内部的 slot-relative member-word offsets(member-word @byte, shift, mask → width)。Pufferfish load slot 的 bundle-absolute bit(abs 119..140)位于 Pufferfish 51B Bundle 页面。
Pufferfish (PXC) — TensorCore VectorLoad(VMEM → vreg)
DestField::GetConcatenatedValue(@ 0x1ee281a0)按字节精确为:(*((_DWORD*)this + 6) >> 1) & 0x1F,即 member offset 24(@0x18)处的 DWORD,右移 1,并 mask 到 5 bit。
| Field | word | shift | mask | width | 含义 |
|---|---|---|---|---|---|
| Opcode | @0x18 | 6 | 0x3 | 2 | addr-mode discriminator |
| Dest (vreg) | @0x18 | 1 | 0x1f | 5 | destination vreg |
| SublaneMask | @0x10(128-bit) | 62 | 0x7 | 3 | sublane-group select(跨入 @0x18) |
| BaseAddress | @0x10 | 60 | 0x3 | 2 | base-address reg select |
| Offset | @0x10 | 58 | 0x3 | 2 | immediate-offset slot index |
| Stride | @0x10 | 55 | 0x7 | 3 | stride select |
| Vs0 / Vs1 / Vs2 | @0x20 | 59 / 54 / 49 | 5-bit | 5 | vector source ports(gather index) |
| Imm2..Imm5 | @0x2e/@0x2c/@0x2a/@0x28 | — | 16-bit | 16 | immediate displacement slots |
| Predication | (独立 Predication slot) | — | — | 5 | 0..14 preg / 15 always / 31 never |
IndexedIar0/IndexedIar1/Shuffled variant 共享这些精确位置;只有 2-bit Opcode 值变化(VmemLoad=0,VmemLoadShuffled=1,VmemLoadIndexedIar0=2,VmemLoadIndexedIar1 通过专用 branch)。Shuffled 增加 ShuffleField(sublane-shuffle selector);Indexed variant 使用 Vs0/Vs1/Vs2 作为逐 lane gather index。Accessor anchors:Opcode::Matches @ 0x1ee28100,DestField @ 0x1ee281a0,SublaneMaskField @ 0x1ee281c0,BaseAddressField @ 0x1ee281e0,OffsetField @ 0x1ee28200,StrideField @ 0x1ee28220,Vs0Field @ 0x1ee28240,Vs1Field @ 0x1ee28260,Vs2Field @ 0x1ee28280。三个 source port(Vs0/Vs1/Vs2)是 Pufferfish 上逐代稳定的计数;load slot 在 v4 尚未加宽其 gather-index port count;v5+ 可见的加宽体现在 load slot 数量,而非每 slot port count。
Pufferfish (PXC) — TensorCore CmemLoad(CMEM → vreg)
CMEM load 在字段上一一镜像 VMEM load,但位于独立的 CmemLoad slot/word:Opcode @0x16 bit 1(1-bit),Predication @0x10>>50 &0x1f,SublaneMask @0x10>>46 &0x7,BaseAddress @0x10>>44 &0x3,Offset @0x10>>42 &0x3,Stride @0x10>>39 &0x7,并且与 VMEM load 完全一样,拥有三个 gather index port:Vs0 @0x20>>59、Vs1 @0x20>>54 &0x1f、Vs2 @0x20>>49 &0x1f,外加相同的 Imm2..Imm5 16-bit slots。Anchors:NoopOpcode::Matches @ 0x1ecf87e0,CmemLoadOpcode @ 0x1ecf8800,PredicationField @ 0x1ecf8820,Vs0Field @ 0x1ecf88c0,Vs1Field @ 0x1ecf88e0,Vs2Field @ 0x1ecf8900。
Viperfish (VXC) — TensorCore VectorLoad0(VMEM → vreg)
discriminator 是两个测试,在 VectorLoadOpcode::Matches(@ 0x1f006960)中按字节精确:(*((_BYTE*)this + 25) & 0xC) == 0(byte @0x19 bits 2-3,即 qword @0x18 bits 10-11,mask 0xc00)以及 (~*((_QWORD*)this + 2) & 0x3800000000000000) != 0(word @0x10 的 high-word 测试,选择 Iar/Indexed family)。VectorLoadBaseOpcode 匹配 0x400;VectorLoadShuffledOpcode 匹配 0x800。
| Field | word | shift | mask | width | 含义 |
|---|---|---|---|---|---|
| Dest (vreg) | @0x18 | 4 | 0x3f | 6 | destination vreg(V0..V63) |
| SublaneMask | @0x18 | 0 | 0xf | 4 | sublane-group select |
| Predication | @0x18 | 12 | 0xf | 4 | predicate reg(0..15) |
| Stride | @0x10 | 55 | 0xf | 4 | stride select |
| Offset | @0x10 | 59 | 0x7 | 3 | immediate-offset slot index |
| BaseAddress (Indexed) | @0x10 | 62 | 0x3 | 2 | base-address reg select |
DestVregField::GetConcatenatedValue(@ 0x1f006b60)读取 (*((_DWORD*)this + 6) >> 4) & 0x3F,这是 6-bit dest 的字节精确证据。ReadIar0/Iar1 只携带一个 DestVreg(IAR 值落入 vreg)。Anchors:PredicationField @ 0x1f006ac0,StrideField @ 0x1f006b80,SublaneMaskField @ 0x1f006ba0,OffsetField @ 0x1f006bc0。
Ghostlite (GLC) — TensorCore VectorLoad0(VMEM → vreg)
GLC 将相同逻辑字段重打包到与 VXC 不同的位置。discriminator 是 (*((_QWORD*)this + 3) & 0x6000) == 0(word @0x18 bits 13-14)加上 high-word (word@0x10 >> 62) & 7 测试,在 VectorLoadOpcode::Matches(@ 0x1f3a2460)中按字节精确。
| Field | word | shift | mask | width |
|---|---|---|---|---|
| Dest (vreg) | @0x18 | 7 | 0x3f | 6 |
| SublaneMask | @0x18 | 3 | 0xf | 4 |
| Predication | @0x18 | 15 | 0xf | 4 |
| Stride | @0x10 | 58 | 0xf | 4 |
| BaseAddress (Indexed) | @0x18 | 1 | 0x3 | 2 |
| Offset | 跨 @0x10/@0x18(3-bit straddle) | — | — | 3 |
相较 VXC:Dest 从 bit 4 移到 7,SublaneMask 从 bit 0 移到 3,Predication 从 bit 12 移到 15,Stride 从 bit 55 移到 58,BaseAddress 从 word @0x10 bit 62 移到 word @0x18 bit 1。这是纯粹的逐代 layout delta;字段相同,位置不同。Anchors:DestVregField @ 0x1f3a26a0,StrideField @ 0x1f3a26c0,SublaneMaskField @ 0x1f3a26e0。
6acc60406 (GFC) — TensorCore VectorLoad0(VMEM → vreg)
GFC 使用更宽的 opcode。discriminator 是 (*((_BYTE*)this + 25) & 0x18) == 0(byte @0x19 bits 3-4)加上 word @0x10 & 0x7000000000000000(bits 60-62)中的 3-bit opcode,在 VectorLoadOpcode::Matches(@ 0x1f9e97e0)中按字节精确。3-bit opcode(相对 GLC 的 2-bit)与 GFC 添加 op 的事实一致。
| Field | word | shift | mask | width |
|---|---|---|---|---|
| Dest (vreg) | @0x18 | 5 | 0x3f | 6 |
| SublaneMask | @0x18 | 1 | 0xf | 4 |
| Stride | byte @0x17 | 0 | 0xf | 4 |
| Offset | @0x10 | 60 | 0x7 | 3 |
6acc60406(GFC)把 Stride 移入 byte @0x17,这是另一个逐代 layout delta。Anchors:DestVregField @ 0x1f9e99e0,StrideField @ 0x1f9e9a00,SublaneMaskField @ 0x1f9e9a20,OffsetField @ 0x1f9e9a40。
PXC / VXC scalar-load(SMEM → sreg)
PXC Scalar1 ScalarLoadSmem:Opcode @0x30>>50 &0x3f(0x4=Smem,0x5=SmemOffset),Address @0x30>>39 &0x3f,Dest(sreg)@0x30>>34 &0x1f,Imm0 @0x30>>18 &0xffff。VXC ScalarAlu1 ScalarLoadSmemY/XY(从 accessor 按字节精确得到):Opcode @0x40 & 0xFC0000(0x40000=SmemY → value 1,0x80000=SmemXY → value 2),Dest @0x40>>2 &0x1f(0x1eedc280),Y @0x40>>7 &0x3f(0x1eedc2a0),X @0x40>>13 &0x1f(0x1eedc2e0)。GLC/GFC 使用 gxc::glc/gxc::gfc analogues;GFC 还额外添加 SmemFetchAndAdd。
Addressing Modes
sub-opcode 选择六种 addressing mode 之一:
- Base + immediate offset(
VmemLoad/TileSpmemLoad):addr = base_reg + offset_imm。base_reg是 base-address register 的 2-bit selector;offset是进入 bundle 共享 immediate slot 的小型(2-/3-bit)index,这些 slot 保存 16-bit displacement word(Imm2..Imm5)。 - 仅 Base register(
VectorLoadBase,VXC/GLC/GFC):没有 offset 字段。 - Strided:
StrideField(3-/4-bit)选择 stride;load 以该 stride 读取 N 个 sublane。 - Indexed / gather(
VmemLoadIndexedIar0/1、VectorLoadIndexed0/1、TileSpmemIndexedLoad):逐 lane 地址来自 index-address register(IAR)或 Vs operand。ReadIar0/ReadIar1先把逐 lane index 暂存到 IAR;随后 Indexed load gatherVMEM[base + IAR[lane]]。PXC 使用Vs0/Vs1/Vs2作为 index port;VF/GL/GF 使用 IAR0/IAR1。 - Circular-buffer relative(仅 SparseCore):CB register(CB0..CB15)保存滚动 base;
TileSpmemLoadCircularBuffer相对它读取,并可选择自动更新 pointer。 - Sublane-shuffled(
VmemLoadShuffled/VectorLoadShuffled):load 在加载过程中应用 sublane permutation(ShuffleField),把 load + sublane-shuffle 融合进一个 slot。
indexed IAR port 与 store slot 共享:store 的 SetIar* sub-op 设置的 IAR 可由后续 indexed load 消费(见 Memory-Store Slot)。逐代 IAR 数量是 Target::IarsPerTensorCore()。
Slot-Selects-Tier Model {#the-slot-selects-tier-model}
load slot 内部没有 tier-select bit。tier 由 op 占用的 slot 选择:
| Source tier | Slot |
|---|---|
| VMEM | VectorLoad / VectorLoad0/1/2 |
| CMEM | 专用 CmemLoad slot(仅 Pufferfish) |
| SMEM | Scalar0/1(PXC)或 ScalarAlu0/1(VF/GL/GF),opcode ScalarLoadSmem* |
| SPMEM | SparseCore VectorLoad slot,opcode TileSpmemLoad* |
这是 MemorySpace Enum 的规范伴随模型:LLO operand 携带的运行时 MemorySpace 在 IR 层选择 tier,逐代 lowering 将它路由到匹配 slot;随后 slot 的 wire encoding 只携带地址(tier-relative byte offset 除以 tier granule)、base-address register 以及 offset/stride。bundle word 中的三 bit 无法编码 17 个 MemorySpace 值,这正是由 slot identity 而不是 tag 承载 tier 的原因。
Load Granularity
SublaneMask 字段控制 load granularity。一个 vector register 保存 lane_count × sublane_count 个元素;mask 选择该 load 写入哪些 sublane group。PXC SublaneMask 是 3-bit(8 个可选 group);VXC/GLC/GFC 将其加宽到 4-bit(16 个 group)。SparseCore 使用 MaskField(scVLD_MSK family)外加 _NP(no-predicate)和 _PASS(masked-out lane passthrough)modifier。没有独立 count 字段:granularity 是 SublaneMask 的 popcount,而 addressing mode(strided vs contiguous)决定触碰多少 memory word。默认(所有 sublane)是 full-vector load;Shuffled variant 还会在加载时置换 sublane。
Destination Register File 和 5→6-Bit 加宽
来自 TPURegStrings:vector V0..V63(64 vregs;多寄存器 load 的 wide pairs/triples/quads 如 V60_V61、V60_V61_V62_V63 存在)、scalar S0..S31(32 sregs)、circular-buffer CB0..CB15(16,SparseCore)、predicate P0..P31(32)。vector-load Dest 字段在 Pufferfish 上为 5-bit(字节精确 (DWORD@0x18 >> 1) & 0x1f,0x1ee281a0),在 Viperfish/Ghostlite/6acc60406 上为 6-bit(字节精确 (DWORD@0x18 >> 4) & 0x3f,0x1f006b60)。v5 边界的 dest 加宽 5 → 6 bits 是主要逐代差异,对应翻倍的 vector register file。scalar-load Dest 每一代都是 5-bit。
GOTCHA — 5-bit PXC dest 在 slot 中直接寻址 V0..V31;更宽的 V32..V63 半区以及 wide/complement multi-vreg destination(
V60_V61_V62_V63quads)通过独立的 wide/complement 机制到达,而不是通过加宽 slot 字段。multi-register destination 的 slot encoding 此处未解码。
Per-Gen Load Encoding Table(汇总)
| Dimension | Jellyfish/Dragonfish | Pufferfish (PXC) | Viperfish (VXC) | Ghostlite (GLC) | 6acc60406 (GFC) |
|---|---|---|---|---|---|
| Bundle width | 41 B | 51 B | 64 B | 64 B | 64 B |
| Codec namespace | jellyfish::isa | pxc::isa | vxc::isa | gxc::glc::isa | gxc::gfc::isa |
| VMEM-load slots | 1(slot-mask 0x040) | 1(VectorLoad) | 3(VectorLoad0/1/2) | 2(VectorLoad0/1) | 2(VectorLoad0/1) |
| CMEM-load slot | none | 1(CmemLoad) | none | none | none |
| VMEM addr-mode opcode | (InstBits) | 2-bit @ 0x18 bit6-7 | bits 10-11(0xc00)+hi-word | bits 13-14(0x6000) | byte0x19&0x18 + 3b@60-62 |
| VMEM Dest field | (InstBits) | 5-bit @ 0x18 bit1 | 6-bit @ 0x18 bit4 | 6-bit @ 0x18 bit7 | 6-bit @ 0x18 bit5 |
| VMEM SublaneMask | (InstBits) | 3-bit(straddle) | 4-bit @ 0x18 bit0 | 4-bit @ 0x18 bit3 | 4-bit @ 0x18 bit1 |
| VMEM Stride | (InstBits) | 3-bit @ 0x10 bit55 | 4-bit @ 0x10 bit55 | 4-bit @ 0x10 bit58 | 4-bit @ byte 0x17 |
| VMEM Offset | (InstBits) | 2-bit @ 0x10 bit58 | 3-bit @ 0x10 bit59 | 3-bit(straddle) | 3-bit @ 0x10 bit60 |
| VMEM BaseAddress | (InstBits) | 2-bit @ 0x10 bit60 | 2-bit @ 0x10 bit62 | 2-bit @ 0x18 bit1 | (3b opcode region) |
| VMEM Predication | 5-bit(15 preg) | 5-bit(sep. slot) | 4-bit @ 0x18 bit12 | 4-bit @ 0x18 bit15 | 4-bit |
| SMEM-load op | EmitScalarLoad | ScalarLoadSmem(+Offset) | ScalarLoadSmemY/XY | ScalarLoadSmemY/XY | …Y/XY(+FetchAndAdd) |
| Gather index source | n/a(no IAR) | Vs0/Vs1/Vs2 | IAR0/IAR1(ReadIar) | IAR0/IAR1 | IAR0/IAR1 |
| SparseCore load | none | none(BarnaCore bcVLD) | TileSpmem*(vfc) | TileSpmem*(glc::sc) | TileSpmem*(gfc::sc) |
Jellyfish/Dragonfish vector-load 使用 monolithic VectorLoadInstruction proto,由 EncoderJf 打包进 41-byte bundle 外加 LLVM InstBits table;slot presence(slot-mask bit 0x040)、dest-vreg semantics 和 sublane-shuffle variant 已确立,但精确 JXC bit offsets 位于 InstBits(codec 路径中磁盘上全零的 binary record)而不是 Field accessor 中,因此这里未逐 bit 枚举。
尚未钉住的内容
- Jellyfish/Dragonfish 精确 VMEM-load bit 位置。 Slot presence、dest semantics 和 sublane-shuffle variant 已确立;逐字段 offset 位于
InstBits,而不是Fieldaccessor。 - Offset→immediate-slot 映射。 2-/3-bit Offset 是 slot index;16-bit displacement 位于
Imm2..Imm5;逐 opcode 的Offset→Imm映射尚未完整枚举。 - IAR file size(
ReadIar0/Iar1暗示每 slot 2 个 IAR;register-file countIarsPerTensorCore()数值尚未在此恢复)。 - wide/complement multi-vreg load destination encoding(
V60_V61_V62_V63quads)。 - bundle 内每个 load slot 的字面 byte-range。 decoded slot struct 内的 field word offset 已钉住;绝对 Pufferfish load-slot region(abs 119..140)位于 Pufferfish 51B Bundle 页面,但 V5+ 的逐代 slot-to-byte map 来自各 codec 的
Encodedispatch。