合并 ALU 位布局
此页面上的所有地址、偏移量和位位置均适用于
libtpu-0.0.40-cp314轮中的libtpu.so(内部版本libtpu_lts_20260413_b_RC00、内部版本89edbbe81c5b328a958fe628a9f2207d)。 ELF 没有被剥离;存在完整的 C++ 符号。.textVMA等于文件偏移量(0xe63c000);所有地址都是分析VMA。其他版本会有所不同。
摘要
BarnaCore 的 JF/DF 代(Jellyfish/Dragonfish,早于 Pufferfish 32 字节 BCS 捆绑包 的 v2-v3 嵌入加速器)通过 23 字节/184 位地址处理程序包驱动其嵌入地址数据路径。该捆绑包的两个插槽是矢量 ALU 通道 - Alu0 和 Alu1 - 它们的编码方式是整个格式中最违反直觉的部分:地址处理程序编码器不编码 ALU 本身。 EncoderJf::EncodeBarnaCoreAddressHandlerVectorAlu (@0x1e86f5c0) 构建一次性的完整 isa::Bundle,将 VectorAluInstruction 原型复制到该捆绑包的 vector_alu 通道中,运行标准 41 字节 JF 捆绑包编码器 (EncoderJf::EncodeBundleInternal @0x1e86c7c0),然后从 41 字节输出中获取 7 字节窗口,并将其移位合并到 23 字节地址处理程序包中。因此,地址处理程序 ALU 不是一个独特的 ISA — 它是主要的 JF 向量 ALU ISA,重新定位。
这对于重新实现者来说有一个干净的结果。操作码空间(VectorAluOpcode,56值6位枚举)和操作数选择器(VectorRegister,VectorAluYEncoding)正是主要的JF向量ALU编码;只有5 位通道预测和通道选择是特定于地址处理程序的。合并将 56 位 JF 窗口映射到两个连续的 31 位通道槽(5 位 pred + 26 位主体),绝对位 48..78 处的 Alu0 和 79..109 处的 Alu1,填充了预测基数(位 48)和存储槽基数(位 110)之间先前未映射的间隙。父 JF/DF 束映射。
此页面记录了三个工件。 (1) 合并的向量 ALU 位布局 — 收获机制、12 字节标头条和字节精确的每通道合并映射,以及 VectorAluOpcode (56v) 和 VectorAluYEncoding (32v) 枚举。 (2) VectorSlot 存储/加载/结果字段引用的两个 共享操作数值枚举 — VectorResultDestination(EUP 结果路由目标)和 BaseAddressEncoding(2 位存储/加载基地址模式) — 加上 Result.which_destination 路由和每通道 EUP 结果放置。 (3) 程序级 BCS 汇编 — 地址处理程序如何成为一个平面 N × 23 字节束流,没有标头、分隔符和终止符字节,并由每个束 prog_end 位终止。
重新实现,合约为:
- 收获和合并模型:合并的 ALU 主体是标准 JF
VectorAluInstruction编码,由完整的 41 字节 JF 捆绑编码器生成,并通过每通道移位/掩码合并重新定位。通过重新运行 JF 编码器来重新编码 ALU,而不是直接打包字段。 - 12字节头条+每通道合并映射:
Alu0插槽abs 48..78,Alu1插槽abs 79..109,每个都是5位预测+ 26位操作码/操作数体,具有精确的移位/掩码算法。 - 共享操作数枚举:
VectorResultDestination(V0/V1/VLD,3 个值)和BaseAddressEncoding(ZERO/VS0/VS1/VS2,4 个值),从其EnumDescriptorProto进行字节固定。 - 程序结构:
BarnaCoreAddressHandlerProgram= 单个重复的bundles字段; DMA 缓冲区是23·N字节背对背打包,32 字节对齐;终止符是最终捆绑包的绝对位 44 处的prog_end(ScalarSlot 字段 5),而不是单独的终止符字节。
| 合并 ALU 编码器 | EncoderJf::EncodeBarnaCoreAddressHandlerVectorAlu(int lane, …) @0x1e86f5c0 |
| 收获的 JF 编码器 | EncoderJf::EncodeBundleInternal @0x1e86c7c0(41 字节/0x29 JF 捆绑包) |
| JF ALU 字段写入器 | EncoderJf::EncodeVectorAluInstruction @0x1e864f00(结构字节0x16/0x1a/0x1c/0x1d) |
| 每通道插槽 | Alu0 abs 48..78、Alu1 abs 79..109 — 每个 5 位 pred + 26 位主体 |
| 操作码枚举 | VectorAluOpcode — 56 个值,6 位 (EnumDescriptorProto @0xc01e7d3) |
| Y 操作数枚举 | VectorAluYEncoding — 32 个值,5 位 (EnumDescriptorProto @0xc01dc38) |
| 结果目标枚举 | VectorResultDestination — V0/V1/VLD,3 个值 (@0xc01f14e) |
| 基地址枚举 | BaseAddressEncoding — ZERO/VS0/VS1/VS2,4 个值,2 位 (@0xc01f977) |
| 程序编码器 | tpu::EncodeBarnaCoreAddressHandler<EncoderJf,…> @0x1e841640 / <EncoderDf,…> @0x1e836ea0 |
| DMA 缓冲区 | 23·N 字节,posix_memalign(buf, 0x20, 23·N) — 无标头/分隔符/终止符 |
| 捆绑调度程序 | EncoderJf::EncodeBarnaCoreAddressHandlerBundle @0x1e86fd80 |
1. 收获与合并 ALU 编码器
用途
EncodeBarnaCoreAddressHandlerVectorAlu 是 23 字节包的两个 ALU 通道的时隙编码器。它的工作是将 VectorAluInstruction(操作码 + 操作数)放入通道的 31 位区域中。它间接地执行此操作:它不是根据地址处理程序包对 ALU 字段进行编码,而是重新使用完整的 JF 包编码器作为暂存打包程序并收集它生成的字节。合并的 ALU 主体是逐字节的标准 JF 矢量 ALU 编码 — 只是重新定位。
入口点
EncoderJf::EncodeBarnaCoreAddressHandlerBundle (0x1e86fd80) ── per-bundle dispatcher
├─ EncodeBarnaCoreAddressHandlerVectorAlu(lane=0, …) (0x1e86f5c0) @+0x1b7
└─ EncodeBarnaCoreAddressHandlerVectorAlu(lane=1, …) (0x1e86f5c0) @+0x1d5
└─ EncoderJf::EncodeBundleInternal(temp_bundle, true) (0x1e86c7c0) ── full 41-byte JF encoder
└─ EncoderJf::EncodeVectorAluInstruction(…, lane, …) (0x1e864f00)
└─ EncoderJf::EncodeVectorAluYEncoding(…) (0x1e864be0) ── y_encoding → imm copy
```text
### 算法
```c
// Models EncoderJf::EncodeBarnaCoreAddressHandlerVectorAlu @0x1e86f5c0.
// lane = 0 (Alu0) or 1 (Alu1); bundle = the address-handler bundle (proto);
// bits = the 23-byte output struct (qword0 @+0, qword1 @+8, dword @+16, word @+20, byte @+22).
function EncodeAddrHandlerVectorAlu(lane, bundle, bits):
alu = bundle.vector_slot[lane].alu.instruction // the VectorAluInstruction proto
// (1) BUILD A SCRATCH FULL BUNDLE and copy the ALU into the matching JF lane.
temp = isa::Bundle() // stack-local, zero-initialized
temp.vector_alu[lane].CopyFrom(alu) // JF lane N == addr-handler lane N
// has-bit 0x8 (lane0) / 0x10 (lane1)
// (1a) If y_encoding names an immediate, propagate the Common.imm metadata so the
// JF encoder can pack it. Special-case checks at proto+0x54:
if alu.y_encoding in {0x1d, 0x1e, 0x1f} // cmp [alu+0x54],0x1d/0x1e/0x1f
or BIT(0x249, alu.y_encoding) // bt 0x249 (the IMMx_IMMy paired forms)
or BIT(0x4208200, alu.y_encoding): // bt 0x4208200
temp.common.imm_* = bundle.common.imm_* // copy the addressed immediate slot(s)
// (2) RUN THE STANDARD 41-BYTE JF BUNDLE ENCODER as a scratch packer.
out = EncodeBundleInternal(temp, /*final=*/true) // 0x1e86c7c0 → StatusOr<vector<u8>>, size 0x29=41
// out is the JF bundle-bits struct with its 12-byte header STRIPPED (see §1.1):
// out[0xa..0x11] == the JF VectorAlu region (struct bytes 0x16..0x1d).
// (3) HARVEST + MERGE the 7-byte window into the address-handler bundle.
if lane != 0: // Alu1 → qword1, mask 0xffffc000000fffff (clear bits 20..49)
MergeAlu1(bits.qword1, out) // §3 Table A1
else: // Alu0 → qword0 bits53..63 + qword1 bits0..14
MergeAlu0(bits.qword0, bits.qword1, out) // §3 Table A0
// The 5-bit lane predication and the lane select are NOT harvested; they are written
// separately (Alu0 pred → abs 48, Alu1 pred → abs 79) by the predication path.QUIRK — ALU 编码器运行整个41 字节 JF 捆绑编码器只是为了收获其中的 7 个字节。尝试针对 23 字节包逐个字段对地址处理程序 ALU 主体进行编码的重新实现者将发生微妙的分歧,因为收获窗口内的操作数子字段边界遵循 JF Lane-N 布局(在车道 0 和车道 1 之间略有不同 - 请参阅第 3 节),而不是干净的地址处理程序布局。正确的、字节相同的再现是重新运行 JF 编码器并重新定位其输出。
功能图
| 功能 | 地址 | 角色 |
|---|---|---|
EncodeBarnaCoreAddressHandlerVectorAlu | 0x1e86f5c0 | 每通道 ALU 插槽编码器;收获+合并 |
EncodeBundleInternal | 0x1e86c7c0 | 完整 41 字节 JF 捆绑编码器(临时加壳器) |
EncodeVectorAluInstruction | 0x1e864f00 | JF ALU 字段写入器;结构字节 0x16/0x1a/0x1c/0x1d |
EncodeVectorAluYEncoding | 0x1e864be0 | Y编码跳转表@0xb83450c;复制 Common.imm 插槽 |
ValidateVectorAluInstruction | 0x1e8632e0 | 原始偏移 → 字段绑定(操作码 @+0x50) |
ProtoUtils::IsEupOpcode | 0x1e875900 | add edi,-0x30; cmp 5; setb → 操作码 0x30..0x34 |
EncodeBarnaCoreAddressHandlerBundle | 0x1e86fd80 | 每束调度程序;调用 ALU 通道 0,然后调用 1 |
注意 — 反编译直接确认调用链:
EncodeBundleInternal在合并 ALU 编码器的第 249 行调用,IsEupOpcode在操作码上调用(原始偏移+0x50,即v40+0x14作为uint) 在第 324 行,合并写入紧随其后。收获窗口读取out[0xa](双字)、out[0xe](字)、out[0x10](字节)——在反编译的合并表达式中确认为*(v37+10)、*(v37+14)、*(v37+16)。
1.1 12 字节标头条
EncodeBundleInternal 的 41 字节输出不是其内部捆绑位结构的开始。在成功路径上,编码器在 new(0x29) 和 41 字节复制之前执行 add r15, 0xc (@0x1e86d766),然后记录 StatusOr 长度 [rbx+0x10] = 0x29。所以:
output byte N == internal-struct byte (0xc + N)
```text
内部结构的前 12 个字节保存 JF 标量/谓词/立即头 — 23 字节地址处理程序包在其自己的布局中重新实现的内容,并且不借用。因此,JF `VectorAlu` 区域(结构字节 `0x16..0x1d`,`EncodeVectorAluInstruction` 写入的位置)位于 **输出字节 `0xa..0x11`** — 正是合并读取的窗口:
| 输出字节 | JF 结构字节 | 持有(JF VectorAlu 区域) |
|---|---|---|
| `0xa`(双字) | `0x16` | Alu1 操作码 + Vx + Y 区域低位 |
| `0xe`(字) | `0x1a` | Alu1 Y 区高位/Alu0 操作数 |
| `0x10`(字节) | `0x1c` | 溢出字节(56位窗口的位48) |
| `0x11`(字) | `0x1d` | Alu0操作码+低位 |
> **GOTCHA —** 41 字节长度是 *post-strip* 大小:内部结构至少为 `0xc + 0x29 = 53` 字节,但仅发出偏移 `0xc` 中的 41 字节。将 41 字节缓冲区视为完整的 JF 包(而不是剥离了 12 字节的尾部)会将每个字段错误定位 12 字节。该条带是 41 字节 JF 包和 23 字节地址处理程序包之间的字节级桥。
---
## 2. 每通道时隙布局
每个 ALU 通道占用一个 **31 位槽**:5 位预测,后跟 26 位操作码/操作数体。 `Alu0` 基于绝对位 48,`Alu1` 基于绝对位 79。这两个槽连续打包并填充父 JF/DF 捆绑映射中 Alu0 预测基 (48) 和存储槽基 (110) 之间的精确间隙 - 先前未映射的 48..110 区域的完整字节级帐户。
```text
23-byte address-handler bundle (184 bits): the 48..110 ALU region
bit: 48 53 78 79 84 109 110
+-------+-----------------------------+ +-------+-----------------------------+----...
| Alu0 | Alu0 body | | Alu1 | Alu1 body | Store
| pred | opcode 6b | operand 20b | | pred | opcode 6b | operand 20b | slot
| 5b@48 | @53..58 | @59..78 | | 5b@79 | @84..89 | @90..109 | @110
+-------+-----------------------------+ +-------+-----------------------------+----...
(written by predication path) (written by predication path)插槽字段
| 槽位字段 | 绝对位 | 宽度 | 源码 | 角色 |
|---|---|---|---|---|
Alu0 预测 | 48 .. 52 | 5 | 预测路径 | 5位BCS预测(通道0) |
Alu0 操作码 | 53 .. 58 | 6 | VectorAluInstruction.opcode | VectorAluOpcode (§4) |
Alu0 操作数主体 | 59 .. 78 | 20 | Vx/y_encoding/y_reg/dest | JF VectorAlu 操作数(通道 0 布局) |
Alu1 预测 | 79 .. 83 | 5 | 预测路径 | 5位BCS预测(通道1) |
Alu1 操作码 | 84 .. 89 | 6 | VectorAluInstruction.opcode | VectorAluOpcode (§4) |
Alu1 Vx | 90 .. 94 | 5 | consumes_vector_register/x_reg | VectorRegister (VREG 0..31) |
Alu1 Y 区域 | 95 ..104 | 10 | y_reg + y_encoding驱动 | VectorRegister + VectorAluYEncoding (§5) |
Alu1 目的地 | 105 ..109 | 5 | produces_register/destination | VectorRegister |
操作码/操作数主体是标准 JF VectorAlu 编码,已重新定位。只有预测和通道选择是特定于地址处理程序的。预测位由预测路径写入(反编译:对于 Alu0,将 (pred & 0x1F) << 48 写入 qword0;对于 Alu1,将 (pred & 0x1F) << 15 写入 qword1,即,abs 位 79),而不是通过收获写入。
注意 — 窗口内操作数分割是 JF ISA 布局,这里不是逐位隔离的(推断,参见§7)。合并将 Alu1 Y 区域收集为连续的 10 位窗口(JF 编码器将
{y_reg 5b, a 5b}写入其中),并将 Alu0 操作数收集为 20 位窗口。 窗口范围是字节精确的(在反编译中确认);内部场边界遵循EncodeVectorAluInstruction的每场移位。收获窗口内的确切{y_reg / y_encoding-driven}和{Vx / Y / dest}子分割并未被隔离。
3. 每通道合并算法
合并将 56 位 JF VectorAlu 窗口 S 映射到地址处理程序 qword 上。两条路径均从反编译中按字节精确解码;两个通道使用不同的窗口,因为 JF 编码器将通道 0 写入结构字节 0x1d,将通道 1 写入结构字节 0x16..0x1c。
Lane 1 (Alu1) — 合并到 qword1
窗口:S = out[0xa] (dword) | out[0xe] (word) << 32 | out[0x10] (byte) << 48(56 位;S 位 b == JF 结构位 176+b)。清除掩码 0xffffc000000fffff 清除 qword1 位 20..49。反编译(@0x1e86f993,第302行):
step (decompiled) -> address-handler qword1
-------------------------------------------------- ----------------------------------------
(S >> 10) & 0x3F00000 S30..35 (OPCODE) -> qw1 bits20..25 (ABS 84..89)
2 * (S & 0x3E000000) S25..29 (Vx) -> qw1 bits26..30 (ABS 90..94) [<<1]
(S & 0x1FF8000) << 16 S15..24 (Y 10b) -> qw1 bits31..40 (ABS 95..104)
((S >> 10) & 0x1F) << 41 S10..14 (Dest) -> qw1 bits41..45 (ABS 105..109)
```text
### Lane 0 (Alu0) — 合并到 qword0 + qword1
读取操作码/低位的 `out[0x11]`(字,= JF 结构 `0x1d`),以及操作数溢出的 `out[0xe]|out[0x10]` 字。反编译(`@0x1e86faa3`,第313行):
```text
step (decompiled) -> address-handler bundle
-------------------------------------------------- ----------------------------------------
((out[0x11] >> 5) & 0x3F) << 53 OPCODE 6b -> qword0 bits53..58 (ABS 53..58)
out[0x11] << 59 low 5b -> qword0 bits59..63 (ABS 59..63)
((W >> 14) & 0xFFFFFFE0) | ((W >> 14) & 0x1F) operand -> qword1 bits0..14 (ABS 64..78)
2 * (out[0xe] & 0x3E00) Dest 5b -> qword1 bits10..14 (ABS 74..78) [<<1]
(W = out[0xe] | out[0x10]<<16 ; clear 0xffffffffffff8000)qword0 用 0x1FFFFFFFFFFFFF 清除(保留位 0..52,写入 53..63); qword1 通过 0xFFFFFFFFFFFF8000 清除(写入位 0..14)。尾部 2 * (out[0xe] & 0x3E00) 项(字位 9..13 的 <<1)将 Alu0 5 位目标子字段放置在 qword1 位 10..14 (ABS 74..78) — 与结果路由路径的 <<10(第 342 行,第 6 行)针对 EUP 的目标相同的子字段V0 结果。
QUIRK — Alu1 路径中的
2 *乘法(及其从中编译的lea [reg+reg*2])是折叠到合并中的 1 位左移:5 位Vx窗口位于其源位置上方一位,因此编码器在屏蔽时将其左移 1。如果不使用<<1进行掩码,则幼稚的重新实现会将Vx置于错误的位。这种转变是现场布局的一部分,而不是优化。
4. VectorAluOpcode — 56 值操作码枚举
ALU 操作码是一个 6 位字段,承载 56 个 VectorAluOpcode 值之一,从其 EnumDescriptorProto @0xc01e7d3(0a <len> name (12 <l> 0a <nl> NAME 10 <num>)* 序列化模式)精确解码字节。符号名册已确认存在于符号表中。相同的操作集是 BCS通道 VectorAlu 名册和 标量0/标量1 ISA 共享 ALU 尾部,这里在枚举值级别而不是硬件操作码或 proto-oneof 级别进行编号。
| 操作码 | 名称 | 操作码 | 名称 |
|---|---|---|---|
0x00 | VECTOR_INT_ADD | 0x1d | VECTOR_SUBLANE_CIRCULAR_ROTATE_DOWN |
0x01 | VECTOR_INT_SUB | 0x1e | VECTOR_RELUX |
0x02 | VECTOR_AND | 0x1f | VECTOR_MOVE |
0x03 | VECTOR_OR | 0x20 | VECTOR_INT_EQUAL |
0x04 | VECTOR_XOR | 0x21 | VECTOR_INT_NOT_EQUAL |
0x05 | VECTOR_FLOAT_ADD | 0x22 | VECTOR_INT_GREATER |
0x06 | VECTOR_FLOAT_SUB | 0x23 | VECTOR_INT_GREATER_EQUAL |
0x07 | VECTOR_FLOAT_MUL | 0x24 | VECTOR_INT_LESS |
0x08 | VECTOR_FLOAT_MAX | 0x25 | VECTOR_INT_LESS_EQUAL |
0x09 | VECTOR_FLOAT_MIN | 0x26 | VECTOR_INT_ADD_CARRY_OUT |
0x0a | VECTOR_LOGICAL_SHIFT_LEFT | 0x28 | VECTOR_FLOAT_EQUAL |
0x0b | VECTOR_LOGICAL_SHIFT_RIGHT | 0x29 | VECTOR_FLOAT_NOT_EQUAL |
0x0c | VECTOR_ARITHMETIC_SHIFT_RIGHT | 0x2a | VECTOR_FLOAT_GREATER |
0x0d | VECTOR_ROUNDING_ARITHMETIC_SHIFT_RIGHT | 0x2b | VECTOR_FLOAT_GREATER_EQUAL |
0x0e | VECTOR_CONVERT_INT_TO_FLOAT | 0x2c | VECTOR_FLOAT_LESS |
0x0f | VECTOR_CONVERT_FLOAT_TO_INT | 0x2d | VECTOR_FLOAT_LESS_EQUAL |
0x10..0x17 | VECTOR_SELECT_VMSK0..VMSK7 | 0x2e | VECTOR_FLOAT_IS_INF_OR_NAN |
0x18 | VECTOR_LANE_ID | 0x30 | VECTOR_RECIPROCAL_SQUARE_ROOT (EUP) |
0x19 | VECTOR_EXTRACT_EXPONENT | 0x31 | VECTOR_POW_2 (EUP) |
0x1a | VECTOR_EXTRACT_SIGNIFICAND | 0x32 | VECTOR_LOG_2 (EUP) |
0x1b | VECTOR_COMPOSE_FLOAT | 0x33 | VECTOR_TANH (EUP) |
0x1c | VECTOR_PACK_AS_HALF_FLOATS | 0x34 | VECTOR_RECIPROCAL (EUP) |
0x3a | VECTOR_POP_COUNT | 0x3c | VECTOR_SET_RNG_SEED |
0x3b | VECTOR_COUNT_LEADING_ZEROS | 0x3d | VECTOR_GET_RNG_SEED |
0x3e | VECTOR_RNG |
QUIRK — 五个 EUP(扩展/超越单元)操作码在
0x30..0x34(rsqrt → pow2 → log2 → tanh → recip) 处是 连续的,这正是IsEupOpcode(@0x1e875900,add edi,-0x30; cmp 5; setb) 返回的范围真实的。这是 EUP 结果排出 (§6) 的编码端触发器:只有这五个操作码会产生需要结果槽的延迟结果;每个其他操作都通过每通道目标字段内联写入其结果。相同的连续0x30..0x34块出现在 BCS 通道硬件操作码空间 中,独立确认块内 EUP 顺序。注意 — 操作码
0x27、0x2f和0x35..0x39在此枚举中未使用。VECTOR_FLOAT_ADD/SUB(0x05/0x06) 和四班 (0x0a..0x0d) 是河豚生成通道能力表中仅通道锁定的Alu1操作(它们在河豚代通道能力表中不存在)MigrateInstruction集记录在 BCS捆绑页面 上);地址处理程序包通过 JF 通道 N 收获继承了相同的通道不对称性。
5. VectorAluYEncoding — 32 值 Y 操作数选择器
ALU 的 Y 操作数不是原始寄存器索引,而是一个 5 位选择器,命名以下之一:向量寄存器、烘焙硬件常量、地址处理程序立即槽或标量寄存器。从 EnumDescriptorProto @0xc01dc38 精确解码字节(符号在符号表中确认)。选择器在 VectorAluInstruction 原始偏移 +0x54 处读取; EncodeVectorAluYEncoding (@0x1e864be0) 对其 (@0xb83450c) 进行跳转表,并将选定的 Common.imm_* 复制到捆绑包的直接区域中。
| 值 | 名称 | 集团 |
|---|---|---|
0 | VECTOR_ALU_Y_VREG | 向量寄存器(y_reg字段) |
1 | VECTOR_ALU_Y_INTEGER_ONE | 硬件常数(整数+1) |
2 | VECTOR_ALU_Y_INTEGER_NEGATIVE_ONE | HW常数(int −1) |
3 | VECTOR_ALU_Y_ZERO | HW常数(零) |
4..7 | VECTOR_ALU_Y_FLOAT_ONE / _NEGATIVE_ONE / _TWO / _ZERO_POINT_FIVE | 硬件常数(浮点 ±1、+2、+0.5) |
8..13 | VECTOR_ALU_Y_ZERO_IMM0..IMM5 | IMM0..5 零扩展 |
14..19 | VECTOR_ALU_Y_ONES_IMM0..IMM5 | IMM0..5个-扩展 |
20..25 | VECTOR_ALU_Y_IMM0_ZERO..IMM5_ZERO | IMM0..5 位于高半部分 |
26..28 | VECTOR_ALU_Y_IMM1_IMM0 / IMM3_IMM2 / IMM5_IMM4 | 配对 32 位立即数 |
29..31 | VECTOR_ALU_Y_VS0 / VS1 / VS2 | 标量寄存器 vs0/vs1/vs2 |
明白了 — Y 选择器使合并传播直接元数据(§1,步骤 1a)。当
y_encoding命名立即数时(0x1d/0x1e/0x1f直接检查加上覆盖IMMx_IMMy配对形式的bt 0x249/bt 0x4208200位测试),合并在运行 JF 编码器之前将寻址的Common.imm_*复制到暂存包中,因此立即数被打包到收获的窗口中。忽略 Y 选择器的重新实现将产生 ALU 操作,其 Y 操作数为每个立即寻址形式读取垃圾。
6. VectorResultDestination 路由
五个 EUP 操作码 (0x30..0x34) 产生一个延迟结果,该结果不会落在发出通道的目标字段中 - 它由单独的结果槽排出。 EncodeBarnaCoreAddressHandlerVectorResult (@0x1e86eb40) 对该插槽进行编码。 2 位 Result.which_destination 字段(原始字段 2,VectorResultDestination)选择 EUP 结果写回的位置。
路由
// Models EncodeBarnaCoreAddressHandlerVectorResult @0x1e86eb40.
function EncodeVectorResult(result, bits):
// which_destination at [result+0x20], 2-bit value placed at dword@16 bit19..20 (ABS 147..148):
bits.dword16 |= (result.which_destination & 3) << 0x13 // ABS 147..148
bits.byte18 |= 0x4 // result-valid bit, ABS 146
// result predication → ABS 141..145 (dword@16 << 0xd)
switch result.which_destination: // cmp [result+0x20], 2/1/0 @0x1e86ec30
case V0_DEST (0): bits.qword1 |= result.dest << 0xa // → Alu0 dest, ABS 74..78
case V1_DEST (1): bits.qword1 |= result.dest << 0x29 // → Alu1 dest, ABS 105..109
case VLD_DEST (2): route to the vector-load destination slot
```text
`ApplyEupResultTargetWorkaround` (`@0x1e8478a0`) 将 2 位字段重新定位到 Jellyfish 芯片上的 ABS 147..148 — 与该编码器写入的位相同。
### `VectorResultDestination` 枚举 (`EnumDescriptorProto @0xc01f14e`)
| 值 | 名称 | 角色 |
|---|---|---|
| `0` | `V0_DEST` | EUP 结果 → 矢量 ALU 通道 0 目标寄存器 (ABS 74..78) |
| `1` | `V1_DEST` | EUP 结果 → 矢量 ALU 通道 1 目标寄存器 (ABS 105..109) |
| `2` | `VLD_DEST` | EUP 结果→向量加载目的地(加载行寄存器) |
> **注意 —** `VectorResultDestination` 仅在 `.rodata` 中显示为其 `EnumDescriptorProto` 名称(没有自己的损坏的 C++ 符号),但三个值名称 `V0_DEST`/`V1_DEST`/`VLD_DEST` 和`cmp 2/1/0` 路由通过描述符和编码器的分支梯形图进行字节固定。结果目标放置(V0 为 `<<0xa`,V1 为 `<<0x29`,在反编译行 334/337/342 处确认)重新使用每通道主体原本会写入的相同 Alu0/Alu1 目标子字段 — EUP 路径只是从结果槽中写入它们。
---
## 7. `BaseAddressEncoding` — 存储/加载基地址模式
存储槽和加载槽各自承载 2 位基地址模式:嵌入行地址为零或三个标量基指针之一。 `BaseAddressEncoding` 是从 `EnumDescriptorProto @0xc01f977` 字节固定的(在 `.rodata` 中确认的描述符名称)。它是父 JF/DF 束映射中 `Store.base` (ABS 121..122) 和 `Load.base` (ABS 137..138) 处的 `<4` 检查值。
| 值 | 名称 | 角色 |
|---|---|---|
| `0` | `BASE_ADDRESS_ZERO` | 基数 = 0(绝对/无标量基数) |
| `1` | `BASE_ADDRESS_VS0` | 基址 = vs0 标量寄存器 |
| `2` | `BASE_ADDRESS_VS1` | 基址 = vs1 标量寄存器 |
| `3` | `BASE_ADDRESS_VS2` | 基址 = vs2 标量寄存器 |
vs0/vs1/vs2 标量寄存器与其他地方命名的物理 `BarnaCoreAddressHandlerScalarRegister` 选择器相同(BarnaCore-id / 梯度 / 权重 / 参数 VMEM 地址寄存器)。两个相邻的共享操作数枚举以相同的方式解码,并在此处列出作为更广泛的 JF 向量 ISA 的上下文:
| 枚举 | 描述符 | 值 |
|---|---|---|
| `OffsetEncoding` | `@0xc01f9e7` | `OFFSET_IMM_2`..`OFFSET_IMM_5` = 0..3 |
| `ShuffleEncoding` | `@0xc01fa42` | `SHUFFLE_VS0`/`VS1`/`VS2` = 1/2/3; `SHUFFLE_IMM1_IMM0`/`IMM3_IMM2`/`IMM5_IMM4` = 4/5/6 |
| `VectorRegister` | `@0xc01e0cf` | `VREG_0`..`VREG_31` = 0..31; `VREG_COUNT` = 32; `VREG_INVALID` = −1(5 位字段) |
> **注意 —** 这三个上下文枚举共享 `VectorAluYEncoding` (§5) 的 IMM0..5 / vs0..vs2 操作数源词汇 — 整个 JF 向量 ISA 通过同一小组寄存器/立即槽/标量寄存器选择器对操作数进行寻址。使用 `BASE_ADDRESS_VS1` 的存储和使用 `BASE_ADDRESS_VS2` 的加载引用与 ALU 的 `VECTOR_ALU_Y_VS1`/`VS2` 选择器相同的 `vs1`/`vs2`。
---
## 8. 程序级 BCS 汇编
### 用途
BarnaCore 地址处理程序是最高级别的工件:DMA 引擎推送到 BarnaCore 定序器的字节流。它是由没有任何框架的单独捆绑包构建的 - 该程序是固定宽度捆绑包的纯粹串联,并且终止在最后一个捆绑包*内部*编码,而不是作为尾随标记。
### 程序原型 + DMA 缓冲区
`BarnaCoreAddressHandlerProgram` (`DescriptorProto @0xc0188f6`) **仅有一个字段**:`bundles`(字段 1,重复消息 `BarnaCoreAddressHandlerBundle`)。没有标头字段、没有计数字段、没有版本字段。程序长度是隐式的:`N = buffer_size / 23`。
顶部编码器 `tpu::EncodeBarnaCoreAddressHandler<EncoderJf,…>`(`@0x1e841640`;`<EncoderDf,…>` `@0x1e836ea0` 相同)分配并填充 DMA 缓冲区:
```c
// Models tpu::EncodeBarnaCoreAddressHandler<EncoderJf,…> @0x1e841640 (DF @0x1e836ea0 identical).
function EncodeProgram(program):
N = program.bundles_count // @program+0x20
size = 23 * N // decompile: `v2 = 23LL * *(int*)(a2+32)`
// compiled as (N*3)<<3 - N = 23N
posix_memalign(&buf, 0x20, size) // 32-byte aligned
out = buf
for bundle in program.bundles: // repeated-ptr walk, stride 8
bits = EncodeBarnaCoreAddressHandlerBundle(bundle) // 0x1e86fd80 → 23-byte struct
// copy the 23-byte struct image back-to-back:
memcpy16(out, bits.qword0_qword1) // 16 bytes (qword0 @0..7, qword1 @8..15)
memcpy4 (out + 0x10, bits.dword16) // dword @16..19
memcpy2 (out + 0x14, bits.word20) // word @20..21
memcpy1 (out + 0x16, bits.byte22) // byte @22
out += 0x17 // 23; decompile: `_R14 += 23`
return buf // N×23 bytes, no header/separator/terminatorDMA buffer layout (N×23 bytes, 32-byte aligned):
+------------------+------------------+-----+--------------------+
| bundle[0] (23 B) | bundle[1] (23 B) | ... | bundle[N-1] (23 B) |
+------------------+------------------+-----+--------------------+
^ no program header ^ no separator ^ no trailing terminator/check byte
```text
> **QUIRK —** 与 Pufferfish PxC 定序器(与 `BundleCheckByte` 捆绑在一起)不同,JF/DF 地址处理程序具有 **零** 成帧字节。无标头、无捆绑包间分隔符、无尾随检查字节 — 字节流是 `N` 固定 23 字节捆绑包的原始串联。重新实现者不得在捆绑包之间插入任何对齐填充(唯一的对齐方式是整个缓冲区基数的 32 字节对齐);每个包正好是 23 个字节,下一个包立即开始。
### Tier-2 组装:一条指令 → 一个捆绑包
`barna_core::EncodeProgramAsProto` (`@0x141697c0`) 构建程序原型。它遍历高级 `BarnaCoreAddressHandlerInstruction` 跨度(每条指令为 `0x148` 字节),并通过 `EncodeBundleAsProto` (`@0x14165f60`) 和 `RepeatedPtrField::Add` — 1 条指令 → 1 个捆绑,按顺序为每条指令附加一个 `BarnaCoreAddressHandlerBundle`,在这一层没有调度或合并。 VLIW 槽打包(将 Load/Alu/Store/Result 元组折叠到一条指令中)发生在 `MakeInstruction<Slot...>` 构造函数系列的上游(此处未跟踪 - 请参阅第 9 节)。 `BarnaCoreAddressHandlerEmitter::AddBundles` (`@0x141604c0`) 将 `N` 空包预先分配到程序中。
### `prog_end` — 停止标记
程序终止是单个每束位,而不是单独的终止符。 `prog_end` 是 `BarnaCoreAddressHandlerScalarSlot` 字段 5(布尔值;ScalarSlot 原型位于 `@0xc017d35`,字段为 `loop`/`shift_mask`/`push`/`branch`/`prog_end`)。 `EncoderDf::EncodeBarnaCoreAddressHandlerScalarSlot` (`@0x1e85e8a0`) 将其写入 **abs 位 44**:
```text
prog_end encode (decompile @0x1e85e8a0, line 55):
*a3 = ((u64)*((u8*)scalar_slot + 0x38) << 44) | (*a3 & 0xFFFFEFFFFFFFFFFF)
^ ScalarSlot proto+0x38 (the prog_end bool) ^ clear bit 44
gated by ScalarSlot has-bit 0x10.编译器在 final 包的标量控制槽中设置 prog_end = 1;硬件排序器在执行该包后停止。程序内控制流位于同一 DF 标量槽的分支字段中 — 预测 (ABS 30..34)、branch_type (ABS 36)、branch_target_pc (ABS 37..43、&0x7f); prog_end (ABS 44) 是无条件停止。
| 字段 | 绝对位 | 宽度 | 编码器 |
|---|---|---|---|
| 分支预测 | 30 .. 34 | 5 | EncodeBarnaCoreAddressHandlerScalarSlot (DF) |
| 分支型 | 36 | 1 | 相同 |
| 分支目标 PC | 37 .. 43 | 7 | 相同 (&0x7f) |
prog_end | 44 | 1 | 相同(<<0x2c,掩码0xFFFFEFFFFFFFFFFF) |
QUIRK — 仅 DF 地址处理程序标量表面公开 Branch 和
prog_end。 JF 独立标量槽助手 (EncodeBarnaCoreAddressHandlerScalarSlotHelper@0x1e86f2e0) 则没有。针对 JF 生成的重新实现者必须从 DF 标量时隙编码中获取程序终止和程序内控制流,与父 JF/DF 捆绑工作中注意到的不对称性一致。
9. 未追踪
- 采集窗口内的内部子分割。 Alu1 10 位 Y 区域 (ABS 95..104) 和 Alu0 20 位操作数体 (ABS 59..78) 采集为连续窗口;合并不会逐位隔离
{y_reg / y_encoding-driven}和{Vx / Y / dest}子字段。窗口范围是字节精确的;窗口内边界遵循 JFEncodeVectorAluInstruction每场移位,但未单独固定(推断)。 - 解码端。 此版本中不存在将 23 字节包读回
VectorAluInstruction的BarnaCoreAddressHandlerALU 解码器 — 地址处理程序路径仅进行编码。编码端合并映射是权威的,但未经独立读者交叉验证。 MakeInstruction<Slot...>VLIW 打包构造函数。{ScalarSlot, VectorLoad, VectorStore, VectorAluSlot, EupResultRead}的哪些元组在一条指令中是合法的(address_handler_program_constructors::MakeInstruction<…>系列,9 个模板重载@0xfa96040..0xfa96680)及其插槽冲突规则(此字节映射之上的调度层)未跟踪。consumes_scalar_register(原始字段 11)在合并的正文中。x_reg/consumes_vector_register/produces_register映射到 Vx/dest 正文字段;标量寄存器操作数路径在合并中未隔离(它可能使用通用 vs0/vs1/vs2 标量选择器而不是 ALU 主体)(推断)。- 硬件解码器是否读取每通道的所有 26 个主体位。 编码器写入完整的标准 JF 主体;硅字段宽度推断以匹配(无解码端读取器;收获的窗口为 26 位并适合 31 位插槽)。
相关组件
| 名称 | 关系 |
|---|---|
EncodeBarnaCoreAddressHandlerVectorAlu (@0x1e86f5c0) | 本页解码的收获和合并 ALU 插槽编码器 |
EncodeBundleInternal (@0x1e86c7c0) | ALU 收获的完整 41 字节 JF 捆绑编码器 |
tpu::EncodeBarnaCoreAddressHandler<EncoderJf/Df,…> | 程序编码器; 23·N字节DMA缓冲区,无帧 |
barna_core::EncodeProgramAsProto (@0x141697c0) | Tier-2 组件; 1 条指令 → 1 包 |
EncoderDf::EncodeBarnaCoreAddressHandlerScalarSlot (@0x1e85e8a0) | 写入 prog_end (ABS 44) + 分支控制流程 |
交叉引用
- 概览 — BarnaCore,传统嵌入加速器:地址处理程序数据路径位于管道中的位置
- BCS 32 字节捆绑包 — 河豚一代通道/定序器包;相同的
VectorAluOpcode操作集、硬件操作码编号以及该 ALU 继承的MigrateInstruction通道功能表 - BCS Scalar0/Scalar1 ISA — 每操作控制+内存 ISA,其共享 ALU 尾部与
VectorAluOpcode枚举重叠 - 每代性能网格 — 将 JF/DF 与 PxC 矢量 ALU 运算放在成本方面的定价原始网格
- 退休 — BarnaCore↔SparseCore 退休矩阵和该捆绑包所属的 BCAH=2 地址处理程序个性字节
- 指数 — 第九部分 — SparseCore 和 BarnaCore / BarnaCore(旧版 v2–v4)