TPU v4 BCS 目标#
tpu-v4-bcs(BarnaCore Sequencer)是独立的硬件目标。它复用公共的源码语法、Bits 位模型、操作数表达式和 export_program,但有自己的 ISA 表、求解器和原生校验方式。TC 标量槽的字段布局不能套用到 BCS。本文说明 BCS 与 TC 在实现上的不同之处;两者共用的机制见汇编与可逆导出。
与 TC 的差异#
方面 |
TC |
BCS |
|---|---|---|
bundle 与程序映像 |
51 字节 bundle,每 512 字节块 10 个,另有块内分隔字节;Python 机器字不直接对应映像字节 |
32 字节 little-endian bundle,每块 16 个,无分隔字节;机器字就是映像中对应的 32 个字节 |
物理槽 |
12 个 |
|
共享字段 |
|
4 个 16 位立即数 lane |
形式的固定位 |
opcode 字段加少量额外字段 |
任意的固定 mask / value( |
约束取值 |
selector 用符号名 |
所有字段都用无符号整数,名称为 |
求解 |
分支定界搜索 |
两个槽候选的笛卡尔积,比较键为(实际读取的 lane 数, 32 字节 little-endian 字节串) |
原生校验 |
往返校验加逐槽 formatter |
仅 codec 往返( |
编译来源映射 |
支持 |
不支持, |
硬件表示#
S0 的谓词与 opcode 起始位分别为 128 与 122,S1 的为 101 与 95。空槽的谓词为 NEVER,因此规范空 bundle 为 (31 << 128) | (31 << 101)。四个立即数 lane 的起始位为 63、47、31、15。
ScalarY 是 6 位 selector:0–31 选择寄存器;32–45 选择 inline lane 的编码方式,包括零扩展、高位全一扩展、取高半字和两个 lane 拼成的 32 位值;46–63 是内置 selector,按当前 descriptor 的枚举名写作 sy.NAME。既往 BCS 研究对部分内置常量的数值说法不一,所以汇编器不把数值自动替换为这些 selector,也不从 selector 名称推出数值。
DMA 的字段与 S1 的部分编码位重叠,destination memory / core 与 outfeed queue 也共用同一段位。这些关系都由 Bits.merge 按位处理,不需要为 DMA 写特殊规则。
位布局的来源#
tpu_v4_bcs_isa_data.py 中的字段名、字段号、oneof 结构和枚举,来自 libtpu 内嵌的 BCS program、bundle、scalar_0、scalar_1 和 isa_base descriptor。descriptor 只给出这些信息,不给出机器位布局。位布局通过原生 codec 探测得到:
对每个槽内形式,先编码所有参数为零的版本作为基线;
每次只改变一个字段,整数取
1、2、-1、0x55555555、0xaaaaaaaa,枚举遍历全部取值;与基线做 XOR,确认差异是一段连续位域,并且截断后与字段值直接对应;
谓词单独探测,其余始终固定的位记为该形式的 fixed mask / value。
两个已支持的 libtpu 版本独立探测的结果一致。descriptor 中有 114 个槽内形式,其中 2 个是 Noop,其余 112 个全部登记(S0 57 个,S1 55 个)。这个数字是编解码的覆盖范围,不是设备执行的覆盖范围。仓库没有保留探测脚本;新版本的 descriptor 若有变化,需要按上述方法重新探测,并与现有表逐项比较。
汇编与导出#
tpu_v4_bcs_assembler.py 中,每个 (slot, mnemonic) 只对应一个签名。求解得到机器字后,依次进行三项核对:
原生 encoder 生成的程序映像与求解出的机器字逐字节相同;
程序映像通过原生往返校验;
重新解码后,已占用的槽集合与源码相同。
第三项检查是必要的:某些组合编码后,某个槽会在解码时消失,例如 DMA 占用了 S1 的位,或者指令的谓词为 NEVER。这类情况必须报错,不能静默接受。
解码时,从原生 protobuf 读出的每个字段值都必须等于从映像字节中按登记位置读出的值。这项检查持续核对位布局表与 libtpu 是否一致。
exact 导出的约束候选是全部 imm* 和两个槽的所有字段,删减方法与 TC 相同。canonical 导出重汇编后,核对每个 bundle 的 (槽, 助记符, 操作数, 谓词) 保持不变。
semantic protobuf 互操作#
tpu_v4_bcs_program.py 在 semantic protobuf 与程序映像之间提供两个方向的转换。它们处理的是已经完成 lowering、调度和链接的 BarnaCoreSequencerProgram。
encode_tpu_v4_bcs_program:先在 Python 中解析 semantic protobuf,把其中显式出现的字段转换为要求的位,同时检查位宽、别名冲突和跨槽冲突。没有出现的字段交给原生 codec 处理,不当作要求为零。随后调用原生编码,检查每一个要求的位都保持原值,最后做往返校验。bundle 数必须是 16 的正整数倍,不替调用方补齐。Noop 与槽级辅助字段(latency、resource_usage、bit_width)可以出现,但不参与编码。decode_tpu_v4_bcs_program:原生解码得到 protobuf,并检查它再次编码后得到原程序映像。只保证机器映像是这对转换的固定点,不保留原 protobuf 的字段顺序、presence 或辅助元数据。
内存分配、装载、生命周期等运行时职责仍由调用方负责。本工具不限制程序长度,只要求 bundle 数是 16 的正整数倍。
程序容器#
extract_tpu_v4_bcs_program 从单个 TpuCoreProgramProto 中沿 barna_core(6) → sequencer(1) → pufferfish_barna_core_sequencer(10) 提取 semantic body,要求 sequencer_type(3)=2,且 program alternative 唯一。在 serialized executable 中,候选记录的条件是 platform_type(2)=1 并含有 barna_core(6)。field 2 是平台类型,不是 core 种类。找到后同样沿上述路径提取,再编码为程序映像。
提取不涉及 Channel Controller,也不改写 executable。普通的 JAX 编译产物中不一定有 BCS 程序,找不到 BCS 记录时报错。