Skip to content

PXC 家族 (Pufferfish)

地址适用于 libtpu-0.0.40-cp314 wheel 中的 libtpu.so (build-id 89edbbe81c5b328a958fe628a9f2207d)。其他版本会有所不同。

摘要

PXC 是单一代号家族:tpu::(anonymous namespace)::TpuHalPxcHardwareFactory 只服务一个硅代际,即 Pufferfish (TpuVersion::kPufferfish = 2)。因为它只服务一个版本,所以它是四个家族中最容易推理的一个:一个工厂实例、一次 Register 调用,以及一个将版本字面量 2 硬编码而不是在运行时读取的 CreateImpl

PXC 在子核心分类中的位置很关键:它是第一个将每个核心的指令流拆分为 fetch-core 和 load-core 的家族。在 JXC 仍然使用单一融合数据流的地方,PXC 引入了 asic_sw::driver::deepsea::pxc::pfc (Pufferfish fetch-core) 和 pxc::plc (Pufferfish load-core),作为不同的子命名空间。这种拆分延续到 VXC 和 GXC,使 PXC 成为后续每个家族的架构模板。PXC 还携带家族级的 pxc::isa 命名空间和 pxc::profiler 命名空间,这是第一个在自身家族标签下拥有 HAL-driver ISA 命名空间的家族。

本页遵循与 JXCVXCGXC 页面相同的语法。工厂的 vtable 形状与其他家族逐字节相同;差异在于版本处理、DMA 模型以及更重的 helper。共享的基类链见 HAL 家族

对重新实现而言,契约是:

  • 单版本注册:一个工厂实例、一次 Register 调用、CreateImpl 硬编码 version = 2
  • 5 槽工厂 vtable (形状与 JXC/VXC 相同) 以及 208 字节的 TpuHalPxcHardwareImpl
  • 构造链 HardwareImpl → CommonHelper (48 B) → Chip (408 B) → Core (800 B),其中 DMA 折叠进 tpu::TpuPxcDriver没有单独的 DMA-issuer 对象。
  • pxc::pfc / pxc::plc 的 fetch/load 拆分,以及 pxc::isa / pxc::profiler 命名空间。
工厂类tpu::(anonymous namespace)::TpuHalPxcHardwareFactory (anon-ns)
服务的 TpuVersions1 — kPufferfish (2)
工厂 vtable / vptr_ZTV 0x216085c8 / 已安装 vptr 0x216085d8
工厂 typeinfo_ZTI 0x21608600 (__si base → TpuHalHardwareFactoryBase 0x21d343f8)
HAL impl 类 / 大小TpuHalPxcHardwareImpl, 208 B (0xD0), vtable 0x21608618
Init 模块google_init_module_tpu_hal_pxc_hardware_impl @ 0x213e9ec0 (1× Register)
Fetch/load 拆分第一个带有该拆分的代际pxc::pfc + pxc::plc
DMA 引擎集成到 tpu::TpuPxcDriver (无 issuer 对象); DmaDescriptorV2

工厂绑定与注册

目的

PXC 工厂将 TpuVersion::kPufferfish 绑定到它的 HAL 实现。因为 Pufferfish 是 PXC 处理的唯一代号,注册只有一次调用,是四个家族中最精简的。

入口点

text
google_init_module_tpu_hal_pxc_hardware_impl (0x213e9ec0)
  └─ operator new(0x10)                     ── single factory instance (16 B)
       f[+8] = 2 (kPufferfish) ; f[+0] = vptr 0x216085d8
       TpuHalFactory::Register(kHardware, 2, f)   (0x1fbb16a0)
       CHECK(s == OK)   // string 0x94acd7e
```text

### 算法

```c
function google_init_module_tpu_hal_pxc_hardware_impl():   // 0x213e9ec0
    f = operator_new(0x10)                  // 16-byte factory object
    f[+8] = 2                               // kPufferfish (movl $0x2,0x8(%rax))
    f[+0] = &PxcFactory_vtable + 0x10        // installed vptr 0x216085d8
    s = TpuHalFactory::Register(kHardware /*0*/, 2, unique_ptr(f))
    if s != OK: LogMessageFatal(CHECK string @0x94acd7e)

怪癖 — 0x94acd7e 处的 CHECK 字符串是 std::make_unique<tpu::TpuHalPxcHardwareFactory>()没有参数;PXC 工厂构造函数不接收 TpuVersion,因为没有任何需要消歧的内容。对比 JXC 和 VXC,它们的 CHECK 字符串会把代号传给 make_unique。烘入二进制的源路径是 learning/45eac/tpu/runtime/hal/internal/pxc/tpu_hal_pxc_hardware_impl_registration.cc (string 0x877b845)。

函数映射

函数地址作用
google_init_module_tpu_hal_pxc_hardware_impl0x213e9ec0单次 Register (v2)
TpuHalFactory::Register0x1fbb16a0注册表插入 (共享)
TpuHalFactory::Get0x1fbb19c0运行时查找 (共享)
TpuHal::Create0x1e814180公共入口 (共享)

工厂 vtable

目的

PXC 的工厂 vtable 在形状上与 JXC 逐字节相同:两个家族特有 override (D0 dtor、CreateImpl) 和三个继承槽,它们的地址是 JXC 与 VXC 指向的完全相同的函数

Vtable 布局

vaddr解析为基类/override
0x216085d80 — ~TpuHalFactory() D20x0e723a80 (ret)INHERITED
0x216085e01 — ~TpuHalPxcHardwareFactory() D00x0e7f8260OVERRIDE
0x216085e82 — HardwareFactoryBase::Create(wq)0x1e80f560INHERITED
0x216085f03 — HardwareFactoryBase::CanCreate()0x1e80f520INHERITED
0x216085f84 — TpuHalPxcHardwareFactory::CreateImpl(wq)0x0e7f8280OVERRIDE

槽 1 编码 operator delete(this, 0x10);工厂是 16 字节,与四个家族都相同。

算法 — CreateImpl

c
function TpuHalPxcHardwareFactory::CreateImpl(out, this, wq):   // 0x0e7f8280
    version = 2                              // HARDCODED kPufferfish (mov $0x2,%esi)
    obj     = operator_new(0xD0)              // 208 B = TpuHalPxcHardwareImpl
    TpuHal::TpuHal(obj, 2, wq)                // base ctor 0x1e811c00: wq→+0x68, version→+0x78
    *(void**)(obj + 0)    = &PxcImpl_vtable + 0x10   // plant 0x21608618 → 0x21608628
    *(void**)(obj + 0xC8) = nullptr            // CommonHelper slot, null until init
    out.value = obj ; out.status = OK
    return out
```text

> **注意 —** PXC 的 `CreateImpl` 是唯一一个硬编码自身版本 (`mov $0x2`) 的实现。它既不读取工厂的 `+8`,也不读取 work-queue。结果在功能上等同于 JXC 读取 `factory+8` (注册键同样是 `2`),但源操作数不同:PXC 烘入了字面量。

### 注意事项

`TpuHalPxcHardwareImpl` override 了一个 JXC 没有的槽:槽 8,`GetConfiguredProperties` (@ 0x0e7f82e0),它尾调用到 `this+0xC8` 处的 helper。PXC impl override 数量为 7 (槽 0128192021)。完整的 23 槽 impl 表见 [HAL 工厂 Override 矩阵](hal-factory-override-matrix.md)。

---

## 工厂下方的构造链

### 目的

PXC 的 `CreateAndInitializeChips` (impl vtable 槽 20, @ 0x0e7f8300) 明显比 JXC 更精简 (~1.8 KB vs ~5 KB)。它不调用 `DriverFactory`,也不调用拓扑构建器;driver 和拓扑构造被折叠进一个无参数的 `InitializeDrivers`。

### 入口点

```text
TpuHalPxcHardwareImpl::CreateAndInitializeChips (0x0e7f8300)
  ├─ TpuChipParts::CoreCount / SharedMemoryCount   ── data-driven constraints
  ├─ TpuHalPxcCommonHelper (48 B, 0x0e7f8b60)        ── stored at impl+0xC8
  ├─ helper->InitializeDrivers() (0x0e7f8b80)        ── NO ARGS; builds TpuPxcDriver vector
  └─ helper->CreateChips (0x0e7f9a00)
       └─ TpuChipPxcDriverImpl (408 B, 0x0e7fa5a0)    ── single int + unique_ptr<TpuPxcDriver>
            └─ core-factory lambda (0x0e7fd3c0)
                 └─ TpuCorePxcDriverImpl (800 B, 0x0e7ffd40)  ── 6-arg ctor, NO DMA-issuer

注意事项

PXC 的 CommonHelper 是 48 字节 (JXC 为 24),因为它拥有一个 std::vector<unique_ptr<tpu::TpuPxcDriver>> (由 D0 dtor 在 free(helper, 0x30) 之前释放 helper+0x18/+0x28 处的 vector 证明)。chip ctor 接收一个 int (JXC 接收两个) 和一个 unique_ptr<TpuPxcDriver> (JXC 接收一个 driver-interface 加一个 register-interface)。core ctor 接收 6 个参数且没有 DMA-issuer;对比 JXC 的 8 参数 core ctor 及其 JfDmaIssuer*

陷阱 — PXC 在二进制中任何位置都没有 PfDmaIssuer 符号。Pufferfish 的 DMA 直接构建在 tpu::TpuPxcDriver 中 (ReadFromMemoryHelper 0x0e80f220、WriteToMemoryHelper 0x0e80bd80、OnChipTransfer 0x0e8139a0、InjectFishDescriptors 0x0e80a3a0)。片上队列模型是 asic_sw::deepsea::pxc::{DirectWrite,Debug,Infeed,Magic,Outfeed}QueueDescriptorstd::variant,硬件 descriptor 是 V2 DmaDescriptorV2 (≥96 字节、4 级 strided),也是第一个 V2 使用者。编译器侧 builder 是 xla::pufferfish::PufferfishDmaDescriptorState,其 CreateForViperfish 方法表明 V2 状态会向前共享到 Viperfish。


Driver 子命名空间清单

asic_sw::driver::deepsea::pxc:: 是第一个携带 fetch/load 拆分的家族命名空间。符号表确认的直接子命名空间如下:

子命名空间作用
pxc::pfcPufferfish fetch-core — fetch 侧指令流
pxc::plcPufferfish load-core — load 侧指令流
pxc::isa家族级 ISA (137K 符号)
pxc::profiler家族级 profiler (8125 符号),持有 TraceEntry
pxc::internal内部 driver helper

fetch-core 下还有更多命名空间:pxc::pfc::isa (46K 符号,包含 pxc::pfc::isa::BarnaCoreChannelBundleVectorBase)、pxc::pfc::profilerpxc::pfc::b0 (寄存器块命名空间)。load-core 携带 pxc::plc::profiler。位于 fetch-core 的 ISA 之下的 BarnaCore bundle 类型确认 Pufferfish 是最后一个搭载 BarnaCore 的家族;它在 VXC 中退役。

怪癖 — 命名的 profiler::TraceEntry 事件类位于家族级 (pxc::profiler::TraceEntry,3087 个 token 出现),不在 pfcplc 之下。pxc::pfc::profiler / pxc::plc::profiler 子命名空间反而持有 control-interface 和 limits-factory 类 (TracemarkLimitsFactoryEveryoneTraceControlFactory)。这不同于 VXC/GXC,后两者的 TraceEntry 类是按子核心划分的。因此 PXC 是子核心分类中的 trace-entry 家族之一,但 trace entry 的粒度是家族级。


按代号的区分

Pufferfish 有芯片变体 (B0 Mfg / B0 Water / B0 Air),它们通过 TpuChipParts::variant_name() (0x20b1eb40) 在同一 impl 内复用。它们不是单独的 TpuVersion 值,也不会改变工厂或 vtable;variant name 只为 census 报告和人类可读命名 (TpuVersionAndVariantToHumanReadableName, 0x20b3b040) 而读取,在 CreateAndInitializeChips 中未观察到按变体分支的代码。

Pufferfish (v2)来源
TpuVersion enumkPufferfish = 2TpuVersionToString 0x20b3a480
ToString"pufferfish"rodata
外部名称"TPU v4" (lite 变体: "TPU v4 lite")命名路径
Codec 类TpuCodecPufferfish (具名)TpuCodec::Create 0x1e835fa0 case 2
TensorCore / BarnaCore有 / 有 (最后一代 BarnaCore)TpuChipParts
SparseCoreTpuChipParts
Flag 前缀xla_pf_ (仅 3 个 flag;大多共享 xla_jf_)flag 扫描

注意 — 很小的 xla_pf_ 数量 (3 个 flag) 表明 Pufferfish 仍然接近 Jellyfish 的 flag 基础;它共享大部分 xla_jf_。架构断裂 (fetch/load 拆分、DMA-in-driver、V2 descriptor) 是结构性的,而不是通过 flag 暴露的。


交叉引用

  • JXC 家族 — 前代,具有融合数据流和单独的 JfDmaIssuer
  • VXC 家族 — 继承 fetch/load 拆分;第一个 SparseCore 家族;共享 V2 descriptor
  • GXC 家族 — Ghostlite + 6acc60406,注册到共享的 VXC 工厂
  • 子核心分类 — PXC 作为 fetch/load-core 拆分的起点
  • HAL 家族 — 共享的 TpuHalFactory 基类链和模板方法 Create
  • 代号矩阵 — 6 值 TpuVersion enum 和 HAL 路由
  • HAL 工厂 Override 矩阵 — 每个 impl 的 23 槽 override 表