Skip to content

JXC 系列(Jellyfish、Dragonfish)

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

摘要

JXC 是 libtpu 仍然携带的四个 TPU HAL 系列中最早的一个。一个 C++ 类 tpu::(anonymous namespace)::TpuHalJxcHardwareFactory 服务两代芯片:Jellyfish(TpuVersion::kJellyfish = 0)和 Dragonfish(TpuVersion::kDragonfish = 1)。该工厂是一个很薄的 16 字节对象,唯一按系列定制的行为是分配正确的 HAL 实现;区分 Jellyfish 与 Dragonfish 的所有内容都通过嵌入的 TpuChipParts proto 数据驱动,而不是通过 C++ 类型。

JXC 的定义性架构特征,也是它锚定子核心分类的原因,是它没有 fetch/load-core 拆分。后续每个系列(PXC、VXC、GXC)都会把每个核心的指令流划分为 fetch-core 和 load-core 子命名空间,而 JXC 的驱动层是单一融合的数据流。它在 asic_sw::driver::deepsea::jxc:: 下的驱动子命名空间按引擎块组织(dfcjfcregisterssnap*_trace_entry 集合),而不是按 fetch/load 角色组织。两代的编译器侧 ISA 位于 platforms_deepsea::jellyfish::isa,而不在任何 jxc::isa 命名空间中。

本页遵循与 PXCVXCGXC 系列页面相同的语法:工厂绑定、构造路径、子命名空间名册,以及按代号区分的差异。所有四个系列共享的抽象基类链(TpuHalFactoryTpuHalHardwareFactoryBase → leaf)见 HAL 系列

对于重新实现,契约是:

  • 单类 / 双版本注册模型:一个 vtable,两个 16 字节实例,在对象偏移 +8 处以 TpuVersion 为键。
  • 5 槽工厂 vtable,以及生成 208 字节 TpuHalJxcHardwareImplCreateImpl 分配器。
  • 构造链 HardwareImpl → CommonHelper → Chip → Core,以及穿入每个核心的 JfDmaIssuer DMA 引擎。
  • 驱动子命名空间名册,以及明确事实:没有 fetch/load 拆分,也没有 jxc::isa
工厂类tpu::(anonymous namespace)::TpuHalJxcHardwareFactory(anon-ns)
服务的 TpuVersions2 — kJellyfish (0), kDragonfish (1)
工厂 vtable / vptr_ZTV 0x215fe530 / 已安装 vptr 0x215fe540
工厂 typeinfo_ZTI 0x215fe568(__si 基类 → TpuHalHardwareFactoryBase 0x21d343f8)
HAL impl 类 / 大小TpuHalJxcHardwareImpl, 208 B (0xD0), vtable 0x215fe580
初始化模块google_init_module_tpu_hal_jxc_hardware_impl @ 0x213e9d80 (2× Register)
Fetch/load 拆分 — 融合数据流(JXC 的定义性特征)
DMA 引擎JfDmaIssuer(每核心独立对象)

工厂绑定与注册

目的

该工厂在 dlopen 时选择给定 TpuVersion 将实例化哪一个 HAL 实现。JXC 是唯一一个工厂类注册到多个版本的系列,因为 Jellyfish 和 Dragonfish 在架构上足够接近,可以共享一个 HAL 实现。(xla_* 标志前缀证实了这种亲缘关系:根本不存在 xla_df_ 前缀,Dragonfish 完全复用 Jellyfish 的 xla_jf_ 标志。)

入口点

text
google_init_module_tpu_hal_jxc_hardware_impl (0x213e9d80)
  ├─ operator new(0x10)                     ── factory instance #1 (16 B)
  │    f0[+8] = 0 (kJellyfish) ; f0[+0] = vptr 0x215fe540
  │    TpuHalFactory::Register(kHardware, 0, f0)   (0x1fbb16a0)
  └─ operator new(0x10)                     ── factory instance #2 (16 B)
       f1[+8] = 1 (kDragonfish) ; f1[+0] = vptr 0x215fe540  (SAME vtable)
       TpuHalFactory::Register(kHardware, 1, f1)
```text

### 算法

```c
function google_init_module_tpu_hal_jxc_hardware_impl():   // 0x213e9d80
    // Two registry entries, one shared vtable. The instances differ
    // ONLY in the TpuVersion stored at +8.
    for version in {0 /*kJellyfish*/, 1 /*kDragonfish*/}:
        f = operator_new(0x10)                  // 16-byte factory object
        f[+8] = version                         // u32 TpuVersion key
        f[+0] = &JxcFactory_vtable + 0x10        // installed vptr 0x215fe540
        s = TpuHalFactory::Register(kHardware /*0*/, version, unique_ptr(f))
        CHECK(s == OK)   // fail strings 0x94a3e44 (kJellyfish), 0x94a4057 (kDragonfish)

QUIRK — 不存在类级别的 Jellyfish-vs-Dragonfish 分派。两个 16 字节实例指向完全相同的 vtable 0x215fe540,只在 +8 处存储的 TpuVersion u32 上不同。两个 CHECK 字符串按字节确认了 std::make_unique<TpuHalJxcHardwareFactory>(...kJellyfish)(...kDragonfish),也就是说 JXC 工厂构造器确实接受 TpuVersion 参数,不同于 PXC 的无参 ctor。按代号区分的行为(核心数、MXU 形状、HBM 上限)稍后从 TpuChipParts 解析。

函数图

函数地址角色
google_init_module_tpu_hal_jxc_hardware_impl0x213e9d802× Register (v0, v1)
TpuHalFactory::Register0x1fbb16a0注册表插入 [platform][version]
TpuHalFactory::Get0x1fbb19c0运行时在 mutex 下查找注册表
TpuHal::Create0x1e814180公共入口:Get → Create → bind profiler

工厂 vtable

目的

该工厂公开抽象的 5 槽 TpuHalFactory 接口。JXC 只覆盖两个槽;另外三个槽与 PXC 和 VXC 指向的字面函数地址完全相同,即共享基类 Create/CanCreate,而不是按系列复制。

Vtable 布局

vaddr槽位解析为基类/覆盖
0x215fe5400 — ~TpuHalFactory() D20x0e723a80 (ret)继承
0x215fe5481 — ~TpuHalJxcHardwareFactory() D00x0e723aa0覆盖
0x215fe5502 — HardwareFactoryBase::Create(wq)0x1e80f560继承
0x215fe5583 — HardwareFactoryBase::CanCreate()0x1e80f520继承
0x215fe5604 — TpuHalJxcHardwareFactory::CreateImpl(wq)0x0e723ac0覆盖

槽 1(deleting destructor)是 tpu::(anonymous namespace)::TpuHalJxcHardwareFactory::~TpuHalJxcHardwareFactory(0x0e723aa0),在 operator delete(this, 0x10) 内联后只是裸 free(this),这证明工厂对象是 16 字节。槽 2 是 GoF 模板方法:Create 调用槽 3(CanCreate),随后在成功时调用槽 4(CreateImpl),否则构建 NotFoundError。槽 3 读取工厂在 +8 处存储的 TpuVersion,并将其与 ScanHardwareDevices(0x1fba53c0)匹配。

算法 — CreateImpl

c
function TpuHalJxcHardwareFactory::CreateImpl(out, this, wq):   // 0x0e723ac0
    version = *(u32*)(wq + 8)                 // TpuVersion read from the work-queue arg, *((_DWORD*)wq+2)
    obj     = operator_new(0xD0)              // 208 B = TpuHalJxcHardwareImpl
    TpuHal::TpuHal(obj, version, wq)          // base ctor stores wq + version into the TpuHal sub-object
    *(void**)(obj + 0)    = &JxcImpl_vtable + 0x10   // plant 0x215fe580 → vptr 0x215fe590
    *(void**)(obj + 0xC8) = nullptr            // CommonHelper slot (qword index 25), null until CreateAndInitializeChips
    out.value = obj ; out.status = OK
    return out
```text

> **NOTE —** JXC 的 `CreateImpl` 从 **work-queue 参数**的 `+8`(`*((_DWORD*)wq + 2)`)读取它传给 `TpuHal` 基类 ctor 的 `TpuVersion`,而不是从工厂自身存储的 `this+8` 键读取。这与 VXC 使用的机制相同(`*((unsigned int*)wq + 2)`):这两个携带版本的系列都从 work queue 获取版本。只有 PXC 因服务单一世代,才把字面量 `2` 硬编码进 ctor 调用。(初始化模块写入 `this+8` 的工厂自身 `TpuVersion` 用于 `CanCreate` 与 `ScanHardwareDevices` 匹配;它不是 `CreateImpl` 转发的值。)208 字节 impl 和 qword 索引 25(`+0xC8`)处的 helper 槽由 JXC 和 PXC 共享;VXC 的 impl 是 216 字节(`operator new(0xD8)`,在 `+0xD0` 处有额外 flag 字节)。完整的 impl 覆盖表见 [HAL 工厂覆盖矩阵](hal-factory-override-matrix.md)。

---

## 工厂以下的构造链

### 目的

工厂只返回 HAL 对象。芯片/核心图在 `TpuHalJxcHardwareImpl::CreateAndInitializeChips`(impl vtable 槽 20,@ 0x0e723c20)中惰性构建,该函数在 `Initialize` 期间调用。

### 入口点

```text
TpuHalJxcHardwareImpl::CreateAndInitializeChips (0x0e723c20)
  ├─ TpuChipParts::CoreCount / SharedMemoryCount   ── data-driven constraints
  ├─ tpu::CreateFishTopology (0x1fc57c60)           ── Jellyfish-class BarnaCore mesh
  ├─ jxc::DriverFactory::Create (0x0e778a40)        ── per-device jxc::DriverInterface
  ├─ TpuHalJxcCommonHelper (24 B, 0x0e725820)       ── stored at impl+0xC8
  └─ helper->CreateChips (0x0e726a40)
       └─ TpuChipJxcDriverImpl (432 B, 0x0e727f80)
            └─ core-factory lambda
                 └─ TpuCoreJxcDriverImpl (824 B, 0x0e733760)  ── takes a JfDmaIssuer*

注意事项

JXC 的构造路径是四个系列中最重的(一个很大的 CreateAndInitializeChips 函数体,函数跨越了 tpu_hal_jxc_hardware_impl.cc 的大部分内容,其 source line 69–142 可在 fatal-log site annotations 中看到)。它是唯一一个先通过独立的 jxc::DriverFactory::Create 为每个设备构建驱动集,并通过 CreateFishTopology 网格构建器构建拓扑,然后才把结果交给 TpuHalJxcCommonHelper::InitializeDrivers 的系列;后续系列把按设备驱动构造直接折叠进自己的 helper 中,不再有单独的工厂或 fish-topology 构建器。JXC 在该路径中强制三个硬编码上限,每个上限都有不同的 fatal/error 字符串:最多 2 TensorCores"Jellyfish Hardware only supports at most 2 TensorCore."CoreCount(...,0) >= 3 guard,line 71)、最多 2 BarnaCores"… 2 Barnacore."CoreCount(...,1) >= 3,line 78),以及 HBM 上限 2("TPU platform only supports up to two HBMs."SharedMemoryCount(...,0) >= 3,line 83)。这三个 “two” 限制都是烘入消息文本中的 JXC 专属字面量,而 PXC/VXC 会在运行时格式化它们的上限。

GOTCHA — 按核心构造器接受一个 JfDmaIssuer*(Jellyfish 系列 DMA 引擎,ctor @ 0x0e73aea0),这是每个核心单独创建的独立对象。这是 JXC 独有的:PXC、VXC 和 GXC 没有独立的 DMA-issuer 类,它们把 DMA 折叠进按系列的驱动(TpuPxcDriver / TpuVxcDriver)中。假设较新系列也有 DMA-issuer 对象的重新实现将找不到这样的符号。


驱动子命名空间名册

asic_sw::driver::deepsea::jxc:: 命名空间是 JXC 无拆分性质的最强证据。符号表确认的直接子命名空间按引擎块和 trace-entry 类型组织,不是按 fetch/load 角色组织:

子命名空间角色
jxc::dfcdataflow controller 引擎(1991 个符号)
jxc::jfcJellyfish core 引擎(988 个符号)
jxc::registersregister-block 定义(330 个符号)
jxc::snapsnapshot / checkpoint 支持(241 个符号)
jxc::jellyfish_performance_countersgen-0 perf counters
jxc::dragonfish_performance_countersgen-1 perf counters
jxc::*_trace_entryprofiler trace-entry 类型(见下文)

*_trace_entry 系列包括 bcs_internalbrn_fabric_syncbrn_sync_waitcs_internalcs_external_sync_flag_updatehbm_mux_switchhib_requesthib_interrupthib_hbm_writehib_sync_updateici_packet 以及 nf_* 集合;这些是引擎块事件记录,不是独立命名空间。

NOTE — 不存在独立的 jxc::bcs/brn/hbm/hib/ici/isa 命名空间。这些 token 是 trace-entry 类型名称中的前缀(例如 bcs_internal_trace_entryici_packet_trace_entry)。两代的编译器侧 ISA 位于 platforms_deepsea::jellyfish::isa(mangled platforms_deepsea9jellyfish3isa;例如 BarnaCoreAddressHandlerProgramProgramFacadeBundleFacade),反映了 deepsea 伞形结构:其中 jellyfish:: 是所有世代共享的编译器基命名空间。

QUIRK — JXC 没有 jxc::profiler::TraceEntry 类。子核心分类归组的具名 profiler::TraceEntry 事件类只存在于 fetch/load 拆分的系列中。JXC 的 profiler 支持通过按引擎的 *_trace_entry 类型实现。因此,尽管 JXC 是一个 HAL 系列,它并不是 trace-entry 子核心之一。


按代号区分的差异

Jellyfish 和 Dragonfish 只在数据上不同,从不在 C++ 类型上不同。二者都会产生相同的 TpuHalJxcHardwareImpl、相同的 TpuChipJxcDriverImpl/TpuCoreJxcDriverImpl,并共享同一个 DMA 描述符模型(V1 jxc::DmaDescriptor,8×32-bit = 32 bytes)。每代都有自己的具名 codec 类 TpuCodecJellyfishTpuCodecDragonfish(二者都有完整名称和 RTTI 符号),由 TpuCodec::Create 的 case 0/1 选择,但这些是 codec 对象,不是 HAL 类型。

维度Jellyfish (v0)Dragonfish (v1)来源
TpuVersion enumkJellyfish = 0kDragonfish = 1TpuVersionToString 0x20b3a480
ToString"jellyfish""dragonfish"rodata pointer table 0x22011bf0
Codec classTpuCodecJellyfish(具名)TpuCodecDragonfish(具名)symtab;TpuCodec::Create case 0/1
TensorCore / BarnaCoreyes / yesyes / yesTpuChipParts (Core.type BARNA_CORE)
SparseCorenonoTpuChipParts (no SPARSE_CORE Core)
Flag prefixxla_jf_(417 个 flags)xla_jf_(无 xla_df_flag scan

交叉引用

  • PXC 系列 — 下一代;第一个拆分 fetch/load cores 的系列,移除了 JfDmaIssuer
  • VXC 系列 — 第一个带 SparseCore 的系列;一个工厂服务三个代号
  • GXC 系列 — Ghostlite + 6acc60406,注册到共享的 VXC 工厂中
  • 子核心分类 — JXC 的融合数据流在 fetch/load 拆分演进中的位置
  • HAL 系列 — 共享的 TpuHalFactory 基类链和模板方法 Create
  • 代号矩阵 — 6 值 TpuVersion 枚举和 HAL 路由
  • HAL 工厂覆盖矩阵 — 按 impl 划分的 23 槽覆盖表