Codename Cheat-Sheet
All addresses on this page apply to
libtpu.sofrom thelibtpu-0.0.40-cp314wheel (build-id89edbbe81c5b328a958fe628a9f2207d— the unambiguous anchor; the runtime-reported0.103is not statically verifiable in the binary). The binary is not stripped — every symbol is a demangled C++ name;.text,.rodata, and.lrodatamap VMA == file offset. Other builds will differ.
Abstract
A single TPU generation wears at least seven different names inside libtpu.so, and they live on three independent integer axes that do not share a numbering. A reader chasing one fact — "which chip is gfc?", "what does DeviceType 12 mean?", "is TpuVersion 4 Trillium or v7x?" — keeps hitting a different axis than the one they hold, and the off-by-ones between those axes are exactly where prior analysis went wrong. This page is the one card to come back to: it pins every name of every generation to the binary site that defines it, side by side, so the rest of the wiki can point here instead of re-deriving the mapping.
The three axes are the internal tpu::TpuVersion enum (a dense 0..5, the compiler's notion of "which silicon", defined by TpuVersionToString @ 0x20b3a480); the profiler's xprof::DeviceType enum (a sparse 1..13, the trace pipeline's notion of "which device", defined by DeviceTypeFromDeviceIdentifiers @ 0xf6993a0 and DeviceTypeString @ 0xf69c7c0); and the protobuf TpuVersionProto (a 1..6 wire enum, internal = proto − 1, TpuVersionFromProto @ 0x20b3a8c0). Orthogonal to all three are the codec/ISA codenames (jxc, pxc/plc, vfc/vlc, glc, gfc), the fish marketing codenames (Jellyfish … Trillium), the PCI device-ids, and the public Cloud-API strings (v2…tpu7x). Every binary-anchored cell below carries its evidence address; where a name is not in the binary (Trillium, Ironwood, "Ghostfish"), the page says so rather than inventing it.
For navigation, the contract is:
- The master table binds every axis for every generation in one row, each cell carrying its own confidence — the canonical lookup the rest of the wiki links to.
- The two-axes warning explains why
TpuVersionandDeviceTypedisagree numerically, so a reimplementer never indexes one table with the other's ordinal. - The gotchas collect the traps: the two off-by-one SparseCore sequencer enums, the nested codec namespaces (
pxc::plc,vxc::vlc,gxc::gfc), and the v7x6acc60406/gfcshipping SparseCore SCS+TEC but not TAC.
| Internal enum | tpu::TpuVersion 0..5 — TpuVersionToString @ 0x20b3a480, table off_22011BF0 (6 ptrs) |
| Profiler enum | xprof::DeviceType 1..13 (sparse) — DeviceTypeFromDeviceIdentifiers @ 0xf6993a0, names off_21772F00 |
| Proto enum | TpuVersionProto 1..6 — TpuVersionFromProto @ 0x20b3a8c0 (internal = proto − 1) |
| Codec factory | tpu::TpuCodec::Create(TpuVersion) @ 0x1e835fa0 (6-case switch, order = TpuVersion) |
| Trace codec | xprof::tpu::GetTraceCodec @ 0xf5a2900 (keyed on PCI identity, not on either ordinal) |
| PCI vendor | 0x1ae0 (Google) for every TPU device |
The Master Cheat-Sheet
One row per generation, in TpuVersion order. Read left-to-right to translate any one name into all the others. The Confidence column applies to the whole row's binary-anchored cells; the marketing column is called out separately because it is the one column not sourced from the binary.
| Codec codename | Fish codename | TpuVersion (internal) | DeviceType (profiler) | Marketing display | PCI chip DID | HAL family |
|---|---|---|---|---|---|---|
jxc (jellyfish) | Jellyfish | 0 | 3 | TPU v2 | 0x004e | TpuHalJxc |
jxc (dragonfish) | Dragonfish | 1 | 5 | TPU v3 | 0x004f | TpuHalJxc |
pxc / pfc | Pufferfish | 2 | 7 | TPU v4 (v4 lite) | 0x0050/51/52 | TpuHalPxc |
pxc / plc | Puffylite | — (no own TpuVersion) | 8 | (v4-class lite) | (chip-parts variant) | TpuHalPxc |
vxc / vfc | Viperfish | 3 | 10 | TPU v5 (v5 lite) | 0x00ac/0x00ad | TpuHalVxc |
vxc / vlc | Viperlite | — (folds into v3) | 11 | (v5-class lite) | 0x00ae/0x00af | TpuHalVxc |
gxc / glc | Ghostlite | 4 | 13 | TPU v6 lite | 0x00d1 | TpuHalVxc |
gxc / gfc | (none — 6acc60406) | 5 | 12 | TPU7x | 0x00f2 | TpuHalVxc |
NOTE — the
TpuVersion→codename binding is the single most-anchored fact in the binary.TpuVersionToString(0x20b3a480) indexes the 6-pointer.data.rel.rotable atoff_22011BF0, whoseR_X86_64_RELATIVErelocations target the literalsjellyfish(0x863f064),dragonfish(0x863f392),pufferfish(0x863f1c4),viperfish(0x863f172),ghostlite(0x86864e0),6acc60406(0x863f0cf). This compiled array is the root every other axis hangs off.
The marketing / Cloud-API column (separate confidence)
The fish and codec codenames are internal names baked into symbols and .rodata. The customer-facing Cloud-TPU names are a parallel string set reached through TpuVersionToExternalName (0x20b3a500) and the AcceleratorType… parser (0x204cf620 / 0x20b3a740). The public product codenames are layered on externally and are not all in the binary:
TpuVersion | Fish | TpuVersionToExternalName string | Cloud-API string(s) | Public marketing | Marketing confidence |
|---|---|---|---|---|---|
| 0 | Jellyfish | TPU v2 | v2 | TPU v2 | HIGH (string in binary) |
| 1 | Dragonfish | TPU v3 | v3 | TPU v3 | HIGH (string in binary) |
| 2 | Pufferfish | TPU v4 / TPU v4 lite | v4, v4lite | TPU v4 | HIGH (string in binary) |
| 3 | Viperfish | TPU v5 / TPU v5 lite | v5, v5e, v5p | TPU v5p / v5e | HIGH (string in binary) |
| 4 | Ghostlite | TPU v6 lite | v6e | Trillium | LOW — "Trillium" is NOT in the binary |
| 5 | 6acc60406 | TPU7x | tpu7x, tpu7 | Ironwood | LOW — "Ironwood" is NOT in the binary (external name) |
GOTCHA — the string
Trilliumhas zero occurrences inlibtpu.so; so doesIronwood; so doesGhostfish. Trillium = Cloudv6e=Ghostlite/glc/TpuVersion4 and Ironwood = Cloudtpu7x=6acc60406/gfc/TpuVersion5 are both external facts (Cloud-TPU documentation), correct but un-sourceable from the binary. The newest generation's only internal name is the obfuscated tag6acc60406; itsgxc::gfcdirectory abbreviation plausibly stands for a "Ghostfish"-style fish name, but that name is not present — do not assert it. Cite6acc60406(orTPU7xfor the display string) as the canonical internal name forTpuVersion5, and treat Ironwood as the external-only marketing label.
Two Axes, Two Numberings — Why TpuVersion ≠ DeviceType
The most common error is to index one table with the other's ordinal. TpuVersion 4 is Ghostlite; DeviceType 4 is not any generation in this table at all. They are different enums maintained by different subsystems, and they were never meant to align.
TpuVersion — the dense compiler axis (0..5)
tpu::TpuVersion is the compiler / codec / HAL axis. It is a contiguous 0..5, one value per silicon family that the compiler emits code for. TpuVersionToString bounds it at < 6; TpuCodec::Create (0x1e835fa0) is a clean 6-case switch (case 0→Jellyfish … case 5→ the anonymous gfc codec via sub_1E838380); TpuVersionFromProto maps proto 1..6 onto it as internal = proto − 1. Lite variants (Puffylite, Viperlite) do not get their own TpuVersion — they multiplex inside the parent family's HAL through the embedded TpuChipParts proto, so this axis has exactly six values.
DeviceType — the sparse profiler axis (1..13)
xprof::DeviceType is the profiler / trace axis. DeviceTypeFromDeviceIdentifiers (0xf6993a0) reads a captured device's 12-byte PCI DeviceIdentifiers tuple and assigns a DeviceType ordinal directly — and that ordinal set is sparse: the eight real TPU silicon generations land on ordinals {3, 5, 7, 8, 10, 11, 12, 13}, skipping 1, 2, 4, 6, 9. The skipped values are not gaps: in the 13-entry name table off_21772F00, ordinal 1 is "GPU" and ordinals 2, 4, 6, 9 all read the generic "Cloud TPU" placeholder string, so the TPU silicon slots are interleaved with a GPU slot and several unassigned/fallback slots. DeviceTypeString (0xf69c7c0) computes index = ordinal − 1 and indexes that table, bounding at ordinal − 1 > 0xC (i.e. ordinal 1..13); out-of-range returns "Cloud TPU". The ordinal store is a literal mov in each branch of DeviceTypeFromDeviceIdentifiers:
// xprof::tpu::DeviceTypeFromDeviceIdentifiers(DeviceIdentifiers) // 0xf6993a0
// each branch matches the PCI tuple against a kXxxChipIdentifiers constant,
// then stores the DeviceType ordinal at result+8 (decompiler: result[2]):
if matches kJellyfishIdentifiers: DeviceType = 3
else if matches kDragonfishIdentifiers: DeviceType = 5
else if matches kPuffyliteChipIdentifiers: DeviceType = 8 // pxc::plc — its own ordinal
else if matches kPufferfishChipB0{Mfg,Water,Air}Identifiers:
DeviceType = 7 // pxc::pfc
else if matches kViperliteChip{A0,A1}{PF,VF}Identifiers:
DeviceType = 11 // vxc::vlc
else if matches kViperfishChip{PF,VF}Identifiers:
DeviceType = 10 // vxc::vfc
else if IsGlc(ids): DeviceType = 13 // gxc::glc, Ghostlite / v6e
else if IsGfc(ids): DeviceType = 12 // gxc::gfc, 6acc60406 / v7x
else: error("Unsupported device identifiers") // device_identifiers_utils.cc:152
QUIRK — on the
DeviceTypeaxis the two newest generations are numerically inverted relative to chronology: Ghostlite (older, v6e) is13, while6acc60406(newer, v7x) is12. The name table itself confirms it directly —off_21772F00slot 11 (ordinal 12) is"TPU v7x"and slot 12 (ordinal 13) is"TPU v6 Lite". This is the single fact that trips every analyst —DeviceType12 < 13 does not imply v7x is older than v6e. The profiler's perf-counter layer gates onDeviceType == 12precisely because v7x is the only generation in this build that exposes named on-device counters (see v7x Perf-Counters); a reimplementer who gates on== 13expecting "the latest chip" silences the entire v7x counter pipeline.
GOTCHA —
Puffylite(pxc::plc) andViperlite(vxc::vlc) exist as first-classDeviceTypeordinals (8 and 11) but have noTpuVersionof their own — they fold into Pufferfish (TpuVersion2) and Viperfish (TpuVersion3) respectively. SoDeviceType → TpuVersionis many-to-one. Translating a capturedDeviceTypeto a compilerTpuVersionmust collapse8→2and11→3; the reverse direction loses the lite/non-lite distinction (which is recovered from theTpuChipPartsvariant, not fromTpuVersion).
The proto axis (1..6) and the public TpuType
A third enum, TpuVersionProto, is the protobuf wire form: TPU_V2=1 … TPU_V6_LITE=5, TPU_V7X=6. TpuVersionFromProto (0x20b3a8c0) is the literal internal = proto − 1 translation; this is why the embedded 6acc60406_chip_parts.binarypb blob carries version = 6 (proto) for the chip whose internal TpuVersion is 5. A fourth, coarser public enum — superpod::routing::TpuType (GetTpuType @ 0x1ff94340) — spreads the lite/standard split back out (type=2…type=10). Four enums, fully reconcilable through the master table above; see Dual-Enum: Proto vs Internal.
Gotchas and Namespace Nesting
Codec namespace nesting — family vs sub-core
The codec/ISA namespaces are two levels deep: a family tag, then a sub-core — for the split families (pxc, vxc, gxc) that sub-core is a fetch/load pair; jxc is fused and instead nests engine blocks. A symbol search for the family tag alone (pxc, vxc, gxc) lands in the wrong sub-namespace half the time. The nesting, under asic_sw::driver::deepsea:::
| Family | Sub-cores (nested namespaces) | Serves |
|---|---|---|
jxc | jxc::jfc (Jellyfish core), jxc::dfc (dataflow), jxc::registers, jxc::snap | Jellyfish, Dragonfish (fused, no fetch/load split) |
pxc | pxc::pfc (fetch), pxc::plc (load) | Pufferfish, Puffylite |
vxc | vxc::vfc (fetch), vxc::vlc (load) | Viperfish, Viperlite |
gxc | gxc::glc (load), gxc::gfc (fetch) | Ghostlite (glc), 6acc60406 (gfc) |
GOTCHA —
jxc::jellyfish,jxc::dragonfish,jxc::bcs, andjxc::brnare not namespaces. The only real nested namespaces underjxcare the engine blocks (jfc,dfc,registers,snap); thebcs/brntokens are prefixes inside*_trace_entrytype names (bcs_internal_trace_entry,brn_perf1_trace_entry), andjellyfish/dragonfishappear only as*_performance_countersidentifiers. JXC's compiler-side ISA lives inplatforms_deepsea::jellyfish::isa, not in anyjxc::isa. See Sub-Core Taxonomy.
QUIRK — the
gxcfamily registers its HAL into the sharedTpuHalVxcHardwareFactory(vtable0x21cabf70), the same factory class Viperfish uses — there is noTpuHalGxcfactory. Three internal codenames (Viperfish, Ghostlite,6acc60406) share one factory class and one vtable, differing only by the storedTpuVersionat+8. The per-generation HAL registration is whatgoogle_init_module_tpu_hal_{vxc,glc,gfc}_hardware_implinjects; the family tag in the codec namespace (gxc) and the HAL factory class (Vxc) are deliberately different — don't expect them to match.
NOTE — only
TpuVersion4 (glc) ships a named codec class,tpu::TpuCodecGhostlite(_ZTV@0x21d35c00).TpuVersion5 (gfc) ships an anonymous codec (vtable0x21d35898, built bysub_1E838380, reached ascase 5ofTpuCodec::Create); there is noTpuCodec6acc60406symbol. The codec'sEncodeguard re-proves the proto axis independently: theglccodec checksproto_tag == 5at+0x58, thegfccodec checksproto_tag == 6.
The two off-by-one SparseCore sequencer enums
TpuSequencerType (the sub-core a bundle targets) has two numberings one apart, and mixing them silently encodes for the wrong engine. The codec template instantiates SCS/TAC/TEC at internal values {3, 4, 5}; the proto/runtime form is one higher, {4, 5, 6}:
| Sequencer | Codec-template (internal) | Proto / runtime |
|---|---|---|
| TensorCore (TC) | 0 | 1 |
| BarnaCore (BCS) | 1 | 2 |
| (reserved) | 2 | 3 |
| SparseCore Scalar (SCS) | 3 | 4 |
| SparseCore Tile-Access (TAC) | 4 | 5 |
| SparseCore Tile-Execute (TEC) | 5 | 6 |
TpuSequencerTypeFromProto (0x20b36300) is the literal internal = proto − 1 switch that joins them; the SCS codec is instantiated at (TpuSequencerType)3, the TAC codec at (TpuSequencerType)4. Full op rosters per generation are on Sequencer Ops Per Gen.
GOTCHA — 6acc60406 (v7x) ships SCS + TEC only, no TAC.
gxc::gfc::isa::SparseCoreScs{Bundle,CodecBase,Program}andgfc::isa::SparseCoreTec{Bundle,Program}are present in the symbol table;gfc::isa::SparseCoreTac{Bundle,CodecBase,Program}is absent. Viperfish (vfc) and Ghostlite (glc) carry all three SparseCore sequencers;6acc60406/gfc(v7x) drops the tile-access engine. A reimplementation that assumes the SparseCore triad is uniform across the SparseCore-bearing generations (Viperfish onward) will emit a TAC codec for v7x that the hardware has no sequencer for.
Trace-codec selection is keyed on PCI identity, not on either ordinal
GetTraceCodec (0xf5a2900) does not take a TpuVersion or a DeviceType. It re-classifies the raw DeviceIdentifiers tuple with the Is{Jfc,Dfc,Pfc,Plc,Vfc,Vlc,Glc,Gfc} predicates and selects one of six std::variant codec alternatives. The variant index is a fourth, independent small enum (jxc=6, glc=1, gfc=2, vlc=3, vfc=4, pxc=5 in the decompiled __assign<N> calls) that matches none of the other three axes. When wiring the profiler, drive codec selection from the PCI tuple through these predicates — not from a DeviceType or TpuVersion you computed elsewhere. See Riegeli Trace Container for how the selected codec is then framed.
Cross-References
- TpuVersion Codename Matrix — the deep page that owns the
TpuVersion→codename derivation and its eighteen cross-validation sites - PCI Device IDs — the full
DeviceIdentifierstable, header DIDs, rev-masks, and theIsGlc/IsGfcchip-DID compares - Dual-Enum: Proto vs Internal —
TpuVersionProto1..6vs internalTpuVersion0..5, theproto − 1reconciliation - Marketing / Cloud Naming — external
TPU vN, Cloud-API strings, and the Trillium/Ironwood "not in binary" note - Codename Superseded Labels — the
Ghostlite=v5p/Trillium=6acc60406/ "Ghostfish" mislabels to avoid, with the binary site that disproves each - GXC Family · VXC Family · PXC Family · JXC Family — per-family codec, ISA, and HAL detail
- Sub-Core Taxonomy — the
fetch/loadsub-core split and thexc/fc/lcnaming pattern - HAL Families — the three
TpuHal{Jxc,Pxc,Vxc}HardwareFactoryclasses and whichTpuVersioneach registers - Per-DeviceType Profiler Struct — the
kDeviceTypeInfoarray indexed by the sparseDeviceTypeordinal - v7x Perf-Counters — the
DeviceType == 12gate and why v7x is the only counter-naming generation - Sequencer Ops Per Gen — the
(TpuVersion, TpuSequencerType)op rosters and the v7x6acc60406TAC drop - Riegeli Trace Container — how the PCI-identity-selected trace codec frames its records
- Per-Gen Function Dispatcher — the binary's per-
TpuVersiondispatch pattern across the codebase