Skip to content

合并 ALU 位布局

此页面上的所有地址、偏移量和位位置均适用于 libtpu-0.0.40-cp314 轮中的 libtpu.so(内部版本 libtpu_lts_20260413_b_RC00、内部版本 89edbbe81c5b328a958fe628a9f2207d)。 ELF 没有被剥离;存在完整的 C++ 符号。 .text VMA等于文件偏移量(0xe63c000);所有地址都是分析VMA。其他版本会有所不同。

摘要

BarnaCore 的 JF/DF 代(Jellyfish/Dragonfish,早于 Pufferfish 32 字节 BCS 捆绑包 的 v2-v3 嵌入加速器)通过 23 字节/184 位地址处理程序包驱动其嵌入地址数据路径。该捆绑包的两个插槽是矢量 ALU 通道 - Alu0Alu1 - 它们的编码方式是整个格式中最违反直觉的部分:地址处理程序编码器不编码 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位枚举)和操作数选择器(VectorRegisterVectorAluYEncoding)正是主要的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 编码 — 只是重新定位。

入口点

text
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 编码器并重新定位其输出。

功能图

功能地址角色
EncodeBarnaCoreAddressHandlerVectorAlu0x1e86f5c0每通道 ALU 插槽编码器;收获+合并
EncodeBundleInternal0x1e86c7c0完整 41 字节 JF 捆绑编码器(临时加壳器)
EncodeVectorAluInstruction0x1e864f00JF ALU 字段写入器;结构字节 0x16/0x1a/0x1c/0x1d
EncodeVectorAluYEncoding0x1e864be0Y编码跳转表@0xb83450c;复制 Common.imm 插槽
ValidateVectorAluInstruction0x1e8632e0原始偏移 → 字段绑定(操作码 @+0x50)
ProtoUtils::IsEupOpcode0x1e875900add edi,-0x30; cmp 5; setb → 操作码 0x30..0x34
EncodeBarnaCoreAddressHandlerBundle0x1e86fd80每束调度程序;调用 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。所以:

text
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 .. 525预测路径5位BCS预测(通道0)
Alu0 操作码53 .. 586VectorAluInstruction.opcodeVectorAluOpcode (§4)
Alu0 操作数主体59 .. 7820Vx/y_encoding/y_reg/destJF VectorAlu 操作数(通道 0 布局)
Alu1 预测79 .. 835预测路径5位BCS预测(通道1)
Alu1 操作码84 .. 896VectorAluInstruction.opcodeVectorAluOpcode (§4)
Alu1 Vx90 .. 945consumes_vector_register/x_regVectorRegister (VREG 0..31)
Alu1 Y 区域95 ..10410y_reg + y_encoding驱动VectorRegister + VectorAluYEncoding (§5)
Alu1 目的地105 ..1095produces_register/destinationVectorRegister

操作码/操作数主体是标准 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 位;Sb == JF 结构位 176+b)。清除掩码 0xffffc000000fffff 清除 qword1 位 20..49。反编译(@0x1e86f993,第302行):

text
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 级别进行编号。

操作码名称操作码名称
0x00VECTOR_INT_ADD0x1dVECTOR_SUBLANE_CIRCULAR_ROTATE_DOWN
0x01VECTOR_INT_SUB0x1eVECTOR_RELUX
0x02VECTOR_AND0x1fVECTOR_MOVE
0x03VECTOR_OR0x20VECTOR_INT_EQUAL
0x04VECTOR_XOR0x21VECTOR_INT_NOT_EQUAL
0x05VECTOR_FLOAT_ADD0x22VECTOR_INT_GREATER
0x06VECTOR_FLOAT_SUB0x23VECTOR_INT_GREATER_EQUAL
0x07VECTOR_FLOAT_MUL0x24VECTOR_INT_LESS
0x08VECTOR_FLOAT_MAX0x25VECTOR_INT_LESS_EQUAL
0x09VECTOR_FLOAT_MIN0x26VECTOR_INT_ADD_CARRY_OUT
0x0aVECTOR_LOGICAL_SHIFT_LEFT0x28VECTOR_FLOAT_EQUAL
0x0bVECTOR_LOGICAL_SHIFT_RIGHT0x29VECTOR_FLOAT_NOT_EQUAL
0x0cVECTOR_ARITHMETIC_SHIFT_RIGHT0x2aVECTOR_FLOAT_GREATER
0x0dVECTOR_ROUNDING_ARITHMETIC_SHIFT_RIGHT0x2bVECTOR_FLOAT_GREATER_EQUAL
0x0eVECTOR_CONVERT_INT_TO_FLOAT0x2cVECTOR_FLOAT_LESS
0x0fVECTOR_CONVERT_FLOAT_TO_INT0x2dVECTOR_FLOAT_LESS_EQUAL
0x10..0x17VECTOR_SELECT_VMSK0..VMSK70x2eVECTOR_FLOAT_IS_INF_OR_NAN
0x18VECTOR_LANE_ID0x30VECTOR_RECIPROCAL_SQUARE_ROOT (EUP)
0x19VECTOR_EXTRACT_EXPONENT0x31VECTOR_POW_2 (EUP)
0x1aVECTOR_EXTRACT_SIGNIFICAND0x32VECTOR_LOG_2 (EUP)
0x1bVECTOR_COMPOSE_FLOAT0x33VECTOR_TANH (EUP)
0x1cVECTOR_PACK_AS_HALF_FLOATS0x34VECTOR_RECIPROCAL (EUP)
0x3aVECTOR_POP_COUNT0x3cVECTOR_SET_RNG_SEED
0x3bVECTOR_COUNT_LEADING_ZEROS0x3dVECTOR_GET_RNG_SEED
0x3eVECTOR_RNG

QUIRK — 五个 EUP(扩展/超越单元)操作码在 0x30..0x34 (rsqrt → pow2 → log2 → tanh → recip) 处是 连续的,这正是 IsEupOpcode (@0x1e875900, add edi,-0x30; cmp 5; setb) 返回的范围真实的。这是 EUP 结果排出 (§6) 的编码端触发器:只有这五个操作码会产生需要结果槽的延迟结果;每个其他操作都通过每通道目标字段内联写入其结果。相同的连续 0x30..0x34 块出现在 BCS 通道硬件操作码空间 中,独立确认块内 EUP 顺序。

注意 — 操作码 0x270x2f0x35..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_* 复制到捆绑包的直接区域中。

名称集团
0VECTOR_ALU_Y_VREG向量寄存器(y_reg字段)
1VECTOR_ALU_Y_INTEGER_ONE硬件常数(整数+1)
2VECTOR_ALU_Y_INTEGER_NEGATIVE_ONEHW常数(int −1)
3VECTOR_ALU_Y_ZEROHW常数(零)
4..7VECTOR_ALU_Y_FLOAT_ONE / _NEGATIVE_ONE / _TWO / _ZERO_POINT_FIVE硬件常数(浮点 ±1、+2、+0.5)
8..13VECTOR_ALU_Y_ZERO_IMM0..IMM5IMM0..5 零扩展
14..19VECTOR_ALU_Y_ONES_IMM0..IMM5IMM0..5个-扩展
20..25VECTOR_ALU_Y_IMM0_ZERO..IMM5_ZEROIMM0..5 位于高半部分
26..28VECTOR_ALU_Y_IMM1_IMM0 / IMM3_IMM2 / IMM5_IMM4配对 32 位立即数
29..31VECTOR_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 结果写回的位置。

路由

c
// 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/terminator
text
DMA 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 .. 345EncodeBarnaCoreAddressHandlerScalarSlot (DF)
分支型361相同
分支目标 PC37 .. 437相同 (&0x7f)
prog_end441相同(<<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} 子字段。窗口范围是字节精确的;窗口内边界遵循 JF EncodeVectorAluInstruction 每场移位,但未单独固定(推断)。
  • 解码端。 此版本中不存在将 23 字节包读回 VectorAluInstructionBarnaCoreAddressHandler ALU 解码器 — 地址处理程序路径仅进行编码。编码端合并映射是权威的,但未经独立读者交叉验证。
  • 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)