Skip to content

Payload: jxc Legacy Trace (PerformanceTraceEntry)

本页中的所有地址和偏移均适用于 libtpu-0.0.40-cp314 wheel 中的 libtpu.so(build-id 89edbbe81c5b328a958fe628a9f2207d)。该二进制 stripped,完整 C++ symbols 存在,且 .text/.rodata VMA 等于 file offset。其他版本会有所不同。

摘要

jxc,即 Jellyfish,是最早被 profiling 的 TPU generation,它不使用之后每个家族都会解码的定宽 TraceEntriesCoder packet。它的设备端 trace ring 会由一个不同的 DecodeTraceBuffers 实例解码成自描述 proto2 消息 asic_sw::driver::deepsea::jxc::PerformanceTraceEntry。deepsea gens(pxc/vfc/vlc/glc/gfc)读取固定的 16-byte bit-packed packet:2-bit framing、59-bit TraceHeader、一串 GetBits64 width sequence,以及 per-event consumed-bit CHECK;而 jxc 解析的是普通 proto2 record:timestamp(field 1,GTC cycle stamp)、chip_id(field 2),以及选择 17 个 band sub-messages 之一的 oneof entry_data(fields 3..19)。jxc 上没有 GetBits sequence,也没有 consumed-bit CHECK;wire 就是 proto2 message layout 本身。

把 jxc 与现代路径统一起来的唯一事实是路由 key。deepsea codec 在 decode 时按 8-bit on-wire trace_point_id 分发,在 encode 时按稠密 oneof field 分发。jxc 根本没有 on-wire id byte,因此 TracePoint<jxc>::FromTraceEntry 会通过把 oneof case 放入 high byte、把该 band 的本地 id enum 放入 low byte,合成一个 16-bit key:key = (EntryDataCase << 8) | (id & 0xff)。这就是 tracepoints registry 在 jxc 0x9xx/0xaxx range 中记录的 key。在这个 key 之上,subscriber 层与现代 gens 统一:cross-gen TraceEntryWrapper<jxc> 暴露同样的 CoreId()/MemoryCommand()/GetDmaId()/SyncFlagValue() accessor surface,因此 CoreDispatcher<jxc>::Dispatch 是 deepsea dispatcher 的 byte-for-byte structural twin;只有 wire format 和 key composition 不同。

本页负责 jxc legacy PerformanceTraceEntry wire format(17-band oneof、per-band TracePoint enums 与 payload fields、selector enum value tables、packed-key composition)以及 两个 jxc 独有的 trace subscribersHbmMuxSubscriber(HBM read/write multiplexer occupancy band,位于自己的 XLine)和 DmaSubscriber(Node-Fabric DMA command/data-end band,通过 synthetic dma_id 配对)。这两个 band 在 newer gens 中被折入其 ICI/intra-DMA payloads,因此在 UHI/OCI/ICI/DMAvfc/vlc/gfc 上没有 analog。与 fixed-16-byte codec 的对比见 TraceEntriesCoder

对重实现而言,契约是:

  • proto2 record,而不是 bit packetPerformanceTraceEntry 由标准 proto2 runtime 解析;band fields 是 message-layout offsets,而不是 GetBits64 width sequence。codec 在 GetTraceCodec 内作为独立的 std::variant alternative 被选择。
  • synthetic packed routing key key = (EntryDataCase << 8) | (band.id & 0xff),由 FromTraceEntry 从 per-band id-field offset 组合而成;这是现代 dual dispatch 在 jxc 上折叠到一个 16-bit value 的 analog。
  • 17 个 bands — 每个 band 的 oneof field number、其 TracePoint enum(本地 16-bit id range)、具名 payload fields,以及 selector enum value tables。
  • 两个独有 subscribersHbmMux(单 key 0x728,XLine 56 上的 2-state switch tracker)和 Dma(17 个 nf-band keys 0x603..0x617,通过以 GetDmaId() 为 key 的 FlatHashMap<dma_id, pending-begin> 配对)。
解码后的消息asic_sw::driver::deepsea::jxc::PerformanceTraceEntry(proto2;自描述,非 bit-packed)
Container 布局field 1 timestamp(u64,GTC cycle stamp);field 2 chip_id(u32);oneof entry_data fields 3..19(17 个 band sub-messages)
Codec 选择xprof::tpu::DecodeTrace(DeviceType, JfTrace*) @ 0xf59dba0GetTraceCodec @ 0xf5a2900(variant alternative unique_ptr<TraceCodecInterface<…jxc::PerformanceTraceEntry>>
路由 keyTracePoint<jxc>::FromTraceEntry @ 0xf1bace0key = (EntryDataCase << 8) | (id & 0xff)
DispatcherCoreDispatcher<jxc>::Dispatch @ 0xf1dcee0FlatHashMap<u16 packed-key, vector<subscriber>>,SwissTable probe,fan-out call *0x10(vtable)
Name lookupJxcTracePointName(EntryDataCase, u16) @ 0xf69d800(per-band NameOfDenseEnum;default "Unknown" @ 0x85dd1fd
Subscriber setupjxc ConvertTpuTraceToXPlaneV2<jxc::PerformanceTraceEntry> lambda @ 0xf1da7c010RegisterSubscriber sites
独有 subscribersHbmMuxSubscriber<jxc> @ 0xf1def00(vtable 0x21643ce0);DmaSubscriber<jxc> @ 0xf1dfee0(vtable 0x21643dc0

jxc 为何分叉 — Proto2 对 16-Byte Packet

这个跨 gen 分裂是基础性的,并在 codec-selection 时决定。xprof::tpu::DecodeTrace(DeviceType, JfTrace*) @ 0xf59dba0 调用 GetTraceCodec @ 0xf5a2900(device generation 从 *(int*)(a2 + 260) 读取),后者返回一个 std::variant,其 alternatives 为:

text
variant<
  monostate,
  unique_ptr<TraceCodecInterface<gxc::glc::profiler::TraceEntry>>,   // glc
  unique_ptr<TraceCodecInterface<gxc::gfc::profiler::TraceEntry>>,   // gfc
  unique_ptr<TraceCodecInterface<vxc::vlc::profiler::TraceEntry>>,   // vlc
  unique_ptr<TraceCodecInterface<vxc::vfc::profiler::TraceEntry>>,   // vfc
  unique_ptr<TraceCodecInterface<pxc::profiler::TraceEntry>>,        // pxc
  unique_ptr<TraceCodecInterface<jxc::PerformanceTraceEntry>>        // jxc — DISTINCT TYPE
>

随后 decode 对该 variant 执行 __visit。五个 deepsea alternatives 都是 TraceEntry codecs,即 16-byte fixed-width packet。jxc alternative 则是完全不同的 proto type:PerformanceTraceEntry,由标准 proto2 runtime 解析。DecodeTrace decompile 中已 byte-confirmed:codec 通过一个 __variant_detail::__visitation __fmatrix 分发,最后一个 alternative 命名为 jxc::PerformanceTraceEntry。jxc decode path 中没有任何 GetBits64/SkipBits 调用。

对重实现者的直接后果是:

QUIRK — jxc trace 是自定界 proto2,因此没有固定字段宽度,也没有 per-event total-bit CHECK。试图用现代 codec 的 framing(2-bit valid/started、59-bit header、GetBits64 width sequence)驱动 jxc 的重实现会误解析每条 record。jxc 没有 framing bits,没有 TraceHeader sub-record,也没有 TraceIdHeader;GTC timestamp 是 proto field 1,chip_id 是 field 2,band 是 active oneof member。proto wire-tag layout 就是格式。

Container 与 band offsets

解码后的 PerformanceTraceEntry 对象暴露两个路由 key 会读取的 offsets。oneof discriminator(EntryDataCase)位于 entry + 0x30,active oneof member pointer 位于 entry + 0x28(proto2 把 case 存为 int,把 variant member 存为 pointer)。两者在 FromTraceEntry 中得到确认(*(int*)(a1 + 48) 读取 case;*(_QWORD*)(a1 + 40) 解引用 member)。Fields 1/2(timestampchip_id)是 scalar,不属于 oneof,因此它们从不用来索引 band。

字段Offset类型含义
EntryDataCase+0x30int (oneof case)17 个 bands 中哪一个处于 active 状态(3..19);0 = DATA_NOT_SET
active oneof member+0x28ptrband sub-message;其 id field 在 per-band offset 处读取
timestamp (field 1)proto-layoutu64GTC cycle stamp(→ GtcSpanConverter,cycle→ps downstream)
chip_id (field 2)proto-layoutu32chip identifier

Packed Routing Key

jxc 没有 on-wire trace_point_id byte;band 的身份在 proto oneof case 中,event 的身份在 band sub-message 自己的 id enum 中。TracePoint<jxc>::FromTraceEntry @ 0xf1bace0 把两者折叠为一个 16-bit dispatch key:

c
// TracePoint<jxc>::FromTraceEntry @0xf1bace0 — packed-key composer
function FromTraceEntry(entry):
    case = *(int*)(entry + 0x30);            // EntryDataCase (oneof discriminator)
    switch (case):
        case 0:  id = case;                   // DATA_NOT_SET — degenerate
        case 1, 2: __builtin_trap();          // timestamp/chip_id are scalar, never keyed
        case 3, 8:                  id = member->[+0x18];   // nf_descriptor / ici_packet
        case 4, 6, 10, 12, 15, 16:  id = member->[+0x30];   // nf_control / nf / cs_internal / brn_sync_wait / bcs_internal / hib_request
        case 5:                     id = member->[+0x34];   // nf_ici
        case 7:                     id = member->[+0x20];   // hbm_mux_switch
        case 9, 18:                 id = member->[+0x40];   // cs_external_sync / hib_sync_update
        case 11:                    id = member->[+0x24];   // brn_fabric_sync
        case 13, 14, 19:            id = member->[+0x38];   // brn_perf1 / brn_perf2 / hib_hbm_write
        case 17:                    id = member->[+0x4c];   // hib_interrupt
    return ((u16)case << 8) | (u8)id;          // <- the packed key

最终组合是 byte-exact:((unsigned __int16)case << 8) | (unsigned __int8)id。per-case id-field offset 是该 band 第一个字段在其 sub-message 内的 proto2 layout offset,通过 +0x28 member pointer 读取。

GOTCHA — id-field offset 不是跨 band 恒定的;它根据每个 band 的 proto2 message 中有多少 fixed-layout fields 位于 id 前面,在 +0x18+0x4c 之间变化。在单一硬编码 offset 读取 band id 的重实现,会给除恰好共享该 offset 的 bands 外的所有 bands 建错 key。应像 FromTraceEntry 一样由 oneof case 驱动 offset。(Cases 1 和 2 会 trap;它们是 scalar timestamp/chip_id,从不是 active oneof member。)

这个 packed key 直接解码 tracepoints registry 为 jxc 报告的 namespace。已 byte-confirmed 的 worked examples:

Packed key= (case << 8) | idbandevent
0x728(7<<8)|0x28case 7 hbm_mux_switchid 40 EVENT
0x603..0x617(6<<8)|lowcase 6 nf17 个 DMA command/data-end ids(见 DMA band
0x93c(9<<8)|0x3ccase 9 cs_external_sync_flag_updateid 60 DMA_DONE
0xa3d(10<<8)|0x3dcase 10 cs_internalid 61 SET_SYNC_FLAG
0xa40(10<<8)|0x40case 10 cs_internalid 64 SET_TRACEMARK
0xa41(10<<8)|0x41case 10 cs_internalid 65 TRACE_INSTRUCTION
0xa45/0xa46(10<<8)|0x45/0x46case 10 cs_internalids 69/70 SCALAR_FENCE_{START,END}

Dispatch

CoreDispatcher<jxc>::Dispatch @ 0xf1dcee0 是 deepsea dispatcher 的结构孪生。它调用 FromTraceEntry 获得 u16 key,然后探测 FlatHashMap<u16 packed-key, vector<shared_ptr<TraceEventSubscriber>>>,并把 entry 分发给每个已注册 subscriber:

c
// CoreDispatcher<jxc>::Dispatch @0xf1dcee0
function Dispatch(self, entry_wrapper):
    lock(self);
    key = FromTraceEntry(entry_wrapper->[+0x10], entry_wrapper);   // u16 packed key
    // SwissTable probe of FlatHashMap<u16, vector<subscriber>>:
    h    = crc32(seed, key);                       // _mm_crc32_u64
    grp  = vpshufb(h7);                             // 16-lane control byte broadcast
    for (slot in groups):
        if (vpcmpeqb(grp, ctrl) match && *(u16*)slot == key)   // cmp word, (slot)
            break;
    for (sub in bucket.vector):                    // fan-out
        sub->vtable[0x10](sub, entry_wrapper);     // call *0x10(vtable) = ProcessTraceEntry

hash 是带 vpcmpeqb group scan 和 cmp %ax,(slot) final compare 的 16-bit key 上的 crc32,与现代 CoreDispatcher<TraceEntry> 使用的同一套 absl SwissTable probe 相同。唯一的 jxc-specific 部分是 FromTraceEntry;key 之上的所有内容都是 gen-independent。


17 个 Bands

oneof entry_data 持有 17 个 band sub-messages,即 oneof fields 3..19。每个 band 中某个 event 的 packed routing key 是 (field << 8) | (band.id & 0xff)JxcTracePointName(EntryDataCase, u16) @ 0xf69d800 通过 per-band NameOfDenseEnum<descriptor, Lo, Hi> table(Lo/Hi = 该 band 的本地 id range)把 key 解析成 name;越界 id 解析为 "Unknown",len 7,@ 0x85dd1fd。与其 dump 每个字段,下表给出每个 band 的 oneof field、本地 id range、key range 和角色;后面的字段列表描述 subscriber 实际读取的 bands。

CaseBand sub-messageLocal idsKey range角色
3nf_descriptor0..20x300..0x302Node-Fabric descriptor — OCI-descriptor analog(完整 src/dst + 3 个 sync-flag-update channels)
4nf_control_message28..290x31c..0x31dNode-Fabric control message
5nf_ici24..260x518..0x51aNode-Fabric ICI receive/send framing
6nf3..270x603..0x61bNode-Fabric DMA band — DmaSubscriber source
7hbm_mux_switch400x728HBM read/write multiplexer switch — HbmMuxSubscriber source
8ici_packet0..70x800..0x807Node-Fabric router flit band(jxc analog of deepsea ICI link)
9cs_external_sync_flag_update600x93cTC cross-chip sync set-done(DMA_DONE)— SyncSubscriber
10cs_internal61..700xa3d..0xa46TC sequencer internal sync/trace band — Sync/Step/Hlo/Overlay/ScalarFence
11brn_fabric_sync1120xb70BarnaCore fabric sync
12brn_sync_wait1130xc71BarnaCore sync wait
13brn_perf1109..1110xd6d..0xd6fBarnaCore FSM perf group 1
14brn_perf2100..108, 114..1210xe64..0xe79BarnaCore FSM 16-channel controllers
15bcs_internal122..1270xf7a..0xf7fBarnaCore sequencer internal
16hib_request80..830x1050..0x1053Host Interface Block DMA request — UHI/HDE analog
17hib_interrupt84..850x1154..0x1155HIB interrupt(queue-occupancy snapshot)
18hib_sync_update860x1256HIB sync-flag update
19hib_hbm_write870x1357HIB→HBM write

NOTE — brn_perf2 enum range Lo..Hi = 100..121brn_perf1/brn_fabric_sync/brn_sync_wait id values 重叠,但 EntryDataCase 会消歧:case 14 永远是 16-channel-controller band,与 raw id 无关。BarnaCore bands 中仅 id 是有歧义的;只有 packed key(case + id)唯一。这正是 routing key 把 case 打包进 high byte 的原因。

Subscribers 读取的 bands

cs_internal band(case 10)最繁忙,会按 id fan 到五个不同 subscribers:

text
case 10 cs_internal (ids 61..70)  fields: id, tensor_node, data_field,
                                          sync_flag_number, program_counter,
                                          sfence_end, sfence_start
  61 SET_SYNC_FLAG           ┐
  62 ADD_SYNC_FLAG           │
  66 UNSUCCESSFUL_SYNC_ATTEMPT├─ SyncSubscriber   (in-body mask 0xe3 over id-base 61)
  67 SUCCESSFUL_SYNC_ATTEMPT │
  68 READ_SYNC_FLAG          ┘
  64 SET_TRACEMARK           ── TensorCoreStep   (key 0xa40 → StepTracker)
  65 TRACE_INSTRUCTION       ── Hlo+Overlay+OnDevTraceMe+LloOp  (key 0xa41, 4-way fan-out)
  69 SCALAR_FENCE_START      ┐
  70 SCALAR_FENCE_END        ┴─ ScalarFence      (keys 0xa45/0xa46)
  63 HOST_INTERRUPT  · 65 (also) covered above

nf band(case 6)是 DmaSubscriber 消费的 DMA-started/completed band:通过 Node Fabric 的每次 transfer 都会按 memory engine 发出一个 *_COMMAND/RECEIVE begin 和一个 *_DATA_END completion。其字段是 id, tensor_node, trace_id, descriptor_source, node_id, chip_id, first, lasthbm_mux_switch band(case 7)只携带 id, tensor_node, fsmfsmHbmMuxSubscriber 跟踪的 2-state mux-switch direction。

Selector enum value tables

若干 band 字段是 enum,其 value tables 从 descriptor pool byte-exact 得到:

text
descriptor_source_value:  0=TENSOR_CORE 1=BARNA_CORE 2=HIB 3=HIB_HBM_QUEUE
nf_ici.vc_value:          0=CONTROL 1=DATA
ici_packet.router_port_id_value:  0..3=EXTERNAL_PORT_0..3  4=NODE_FABRIC_0  5=NODE_FABRIC_1
hib_sync_update.sf_rsrc_value:    0=TENSOR_CORE 1=BARNA_CORE
hib_hbm_write.queue_type_value:   0=TC_INFEED 1=BC_INFEED 2=HBM_WRITE
hib_request.requester_tag_value:  0=TC_INFQ 1=TC_OFQ 2=BC_INFQ 3=BC_OFQ 4=HBM_WRQ
                                  5=BC_FSMQ 6=NF_DESCRQ 7=CHIP_DEBUGQ 8=NF_OFQ
hib_request.requester_id_value:   0=TC_OF 1=BC_OF 2=NF_OF 3=CHIP_DEBUG 4=STATUS_BLOCK_WRITE
                                  5=TC_INF 6=BC_INF 7=HBM_WR 8=BC_FSM 9=QUEUE_FETCH 10=PAGE_TABLE_REQ

NOTE — hib_request.virt_addr(u64)与 hib_hbm_write.virt_addr(u64)的拆分,以及每个 sub-message 字段的确切 proto2 wire-tag offset,都是标准 proto2 message layout,而不是手写 bit-codec;因此它们从 descriptor 恢复,而不是从 GetBits width sequence 恢复。(这两个 u64 的确切 in-RAM offset 为 LOW confidence;字段的存在与类型由 descriptor pool 确认,CERTAIN。)


十个 jxc Subscribers

jxc ConvertTpuTraceToXPlaneV2<jxc::PerformanceTraceEntry> setup lambda @ 0xf1da7c0 精确发起 10RegisterSubscriber 调用(由 E8-rel32 caller scan 确认)。其中八个复用 deepsea begin/end-pairing trackers;两个,即 HbmMuxDma,是 jxc 独有的。

#Subscriber (vtable)Packed key(s)jellyfish event(s)备注
1HbmMux (0x21643ce0, threaded){0x728}hbm_mux_switch EVENT(40)XLine 56 "HBM Mux";2-state fsm tracker
2Dma (0x21643dc0, threaded){0x603..0x617} (17)nf DMA cmd/data-enddma_id pairing(FlatHashMap);XStat 0x38
3Sync (0x21643e88, threaded){0x93c,0xa3d,0xa3e,0xa42,0xa43,0xa44}cs_external DMA_DONE + cs_internal sync setin-body mask 0xe3 over id-base 61
4ScalarFence (0x21643ed8, threaded){0xa45,0xa46}cs_internal SCALAR_FENCE_{START,END}XLine 9 (Scalar Unit)
5TensorCoreStep (0x21643f28){0xa40}cs_internal SET_TRACEMARK(64)→ StepTracker (TraceMark id)
6TensorCoreHlo (ctor 0xf1e27c0){0xa41}cs_internal TRACE_INSTRUCTION(65)XLA Ops line
7TensorCoreOverlay (0x21644178){0xa41}cs_internal TRACE_INSTRUCTION(65)→ OverlayTracker
8TensorCoreOnDeviceTraceMe (0x216441c8){0xa41}cs_internal TRACE_INSTRUCTION(65)XLA TraceMe
9LloOpEvent (0x21644218, threaded){0xa41}cs_internal TRACE_INSTRUCTION(65)Tensor Core line
10ScalarFence (0x21643ed8, threaded){0xa45,0xa46}cs_internal SCALAR_FENCE_{START,END}XLine 62 (Barna Core Fence)

QUIRK — key 0xa41TRACE_INSTRUCTION)是一个 4-way fan-out 点:HloOverlayOnDeviceTraceMeLloOp 都注册到同一个 packed key,并共享 setup lambda 中的一个 TracePoints buffer。这精确镜像 deepsea id-85 4-way fan-out;dispatcher 会把一个 entry 交付给全部四个 subscribers,每个 subscriber 再把它投影到不同 XPlane line。假设每个 key 只有一个 subscriber 的重实现会丢掉四个 TRACE_INSTRUCTION consumers 中的三个。

Step/Overlay/Sync trackers 复用 deepsea begin/end-pairing model:StepTracker 以 TraceMark id 为 key,OverlayTracker 以 overlay operand 为 key,SyncTrackersync_flag_number 为 key。两个 jxc 独有 trackers,即基于 dma_idDmaSubscriber 和基于 fsm direction 的 HbmMux,详见下文。


DMA Subscriber — Node-Fabric DMA Band {#the-dma-subscriber-the-node-fabric-dma-band}

DmaSubscriber<jxc>(vtable 0x21643dc0)是第二个注册的 subscriber。它和 HbmMux 都被包在一个 0x240 字节的 ThreadedSubscriber 中(ThreadLoop @ 0xf1ddd60+0xa0 处为 ClosureThread worker),因此二者都应视为 threaded。其内部对象在 +0x18 持有一个 XStat StatMetadata(StatType 0x38)。它消费 nf band(case 6),也就是 newer gens 折入 ICI/intra-DMA payloads 的 jxc DMA band。

注册的 keys — 17 个 nf DMA bands

lambda 通过遍历 .rodata table @ 0xab53940 中的 17 个 dword entries 构建 Dma TracePoints buffer:每次读取 low byte(一个 nf TracePoint id)并 OR 0x600(case 6 位于 high byte),得到 17 个 packed keys:

text
 key  nf id  event                       key  nf id  event
0x603   3   HBM_READ_COMMAND           0x60a  10  VMEM_ICI_WRITE_COMMAND
0x604   4   HBM_WRITE_COMMAND          0x60b  11  VMEM_ICI_WRITE_DATA_END
0x605   5   HBM_WRITE_DATA_END         0x60c  12  SMEM_READ_COMMAND
0x606   6   VMEM_HBM_READ_COMMAND      0x60d  13  SMEM_WRITE_COMMAND
0x607   7   VMEM_HBM_WRITE_COMMAND     0x60e  14  SMEM_WRITE_DATA_END
0x608   8   VMEM_HBM_WRITE_DATA_END    0x60f  15  IMEM_WRITE_COMMAND
0x609   9   VMEM_ICI_READ_COMMAND      0x610  16  IMEM_WRITE_DATA_END
0x614  20   HIB_WRITE_RECEIVE          0x616  22  HIB_WRITE_COMMAND
                                       0x617  23  HIB_WRITE_DATA_END

NOTE — nf ids 17/18/19(BMEM)和 27(ICI_SEND_END)存在于 nf band 中,但Dma subscriber 注册;只有六类 memory-engine command/data-end families(HBM、VMEM-HBM、VMEM-ICI、SMEM、IMEM、HIB)会被配对。注册整个 band 6 的重实现会拾取 subscriber 从不配对的 BMEM 和 ICI-send events。

Match key — dma_id pairing

DmaSubscriber<jxc>::ProcessTraceEntry @ 0xf1dfee0 是一个以 synthetic dma_id 为 key 的 begin/end pairer:

c
// DmaSubscriber<jxc>::ProcessTraceEntry @0xf1dfee0
function ProcessTraceEntry(self, entry):
    if (!CoreId_matches(self, entry)) return;          // chip/core filter (+0x08/+0x0c)
    if (!(MemoryCommand(entry) || MemoryDataEnd(entry)))  return;  // gate: begin or end only
    if (entry.EntryDataCase != 6) return;              // confirm nf band (member+0x30 == 6)
    switch (nf.id - 3):                                // 0..0x14 → per-engine XStat selector
        // picks a TypeInfo label (typeinfo @0x21643e20/e30),
        // a kind (4=command, 5=data-end), a StatType (0x12/0x13/0x14/0x34/0x39)
    dma_id = GetDmaId(entry);                          // @0xf698180 — composite pairing key
    bucket = pending.find_or_prepare_insert_large(dma_id);   // FlatHashMap<dma_id, vector<begin>>
    if (MemoryCommand(entry) && First(entry)):         // @0xf698620
        bucket.vector = { entry };                     // open a pending begin
    else if (MemoryDataEnd(entry)):
        emit_duration_span(bucket.vector[0], entry);   // pair, emit, clear the slot

gate 和 EntryDataCase == 6 confirm 均为 byte-exact(MemoryCommand() || MemoryDataEnd(),然后 *(int*)(member + 0x30) == 6)。pairing store 是一个 FlatHashMap<unsigned long, vector<shared_ptr<TraceEntryWrapper>>>,通过 find_or_prepare_insert_large<unsigned long> @ 0xf1e05e0 到达。带 First()*_COMMAND/RECEIVE 会在 dma_id 下打开一个 begin;匹配的 *_DATA_END 发出 duration span 并清除 slot。读/写显示名由 0xf1e0152 处的 "Writ" magic compare 选择。

GetDmaId — composite key

GetDmaId @ 0xf698180 是 synthetic-key composer。它基于 nf oneof case switch,并把 nf sub-message 的 per-direction fields 折叠到一个 unsigned long 中,使 command 和其 data-end 生成相同 key(并让不同 concurrent DMAs 有差异)。HBM/VMEM-HBM/ICI-packet arms 已 byte-confirmed:

c
// GetDmaId @0xf698180 — composite-key composition (HBM/VMEM-HBM arm)
key = (trace_id & 0x1f00)                  // bits 8..12 of trace_id
| ((resource & 3)   << 13)             // 2-bit src/dst resource
| ((node_id  & 1)   << 15)             // node bit
| ((chip_id  << 16) & 0x7ff0000)       // 11-bit chip
| (id & 0xff);                          // low byte = the nf id
// simple arms (VMEM-ICI / SMEM / IMEM / BMEM / HIB): key = 0 (degenerate — no composite, low byte never set)

GOTCHA — simple-engine arms(switch 中的 case 7,9,0xA..0x11)会落到 LABEL_12 并返回 0;这些 case 从不赋值 composite fields(v3 保持 0,low byte 也保持 0),因此没有 rich command/data-end identity 的 engine families 会折叠到单一 degenerate key。只有 composite arms(case 3 nf_descriptorcase 4/6 nf_control/nfcase 5 nf_icicase 8 ici_packet,以及两个 HIB arms case 0x12/0x13)会构建 full key。该是确定性的,且能按 engine 正确配对,但每个 arm 的确切 LSB bit layout 是 CONFIRMED-PARTIAL:每个方向的字段选择是从 arm table @ 0xab88674 byte-read 得到,composite family 的 OR/shift composition 已读取,但未完整列出 per-arm bit map。重实现者必须复现逐 arm 的字段选择,而不是使用单一全局公式。

per-engine XStat assignment(哪个 engine/direction 落到 StatType 0x12/0x13/0x14/0x34/0x39)以及 read-vs-write XEvent display-name table("Writ" branch)尚未完整制表(整数→XStat-name 映射为 LOW confidence;机制为 CERTAIN)。


HBM-Mux Subscriber — HBM Multiplexer Band

HbmMuxSubscriber<jxc>(vtable 0x21643ce0)是第一个注册的 subscriber;它被 ThreadedSubscriber 包装(0x240 bytes)。它是 jxc 独有的:HBM read/write multiplexer occupancy band 在 deepsea gens 上没有 analog(它们把这类信息折入 intra-DMA/HBM bands)。构造时它预先创建两个 XEventMetadata,用于两个 switch directions:

text
+0x18 = "BFIFO to Node Fabric"   (rodata @0x8732bba, len 20)
+0x20 = "Node Fabric to BFIFO"   (rodata @0x929bc3b, len 20)

注册 key 与 2-state tracker

它注册单个 packed key 0x728(由 movw $0x728,(buf) @ 0xf1db361 构建):0x728 = (7<<8)|0x28 = case 7 (hbm_mux_switch) id 40 = EVENTHbmMuxSubscriber<jxc>::ProcessTraceEntry @ 0xf1def00 是一个四符号 open/close FSM{1,2} 打开一个方向,{0,3} 关闭它:

c
// HbmMuxSubscriber<jxc>::ProcessTraceEntry @0xf1def00 (byte-confirmed)
function ProcessTraceEntry(self, entry):
    if (!CoreId_matches(self, entry)) return;          // +0x08
    state = HbmMuxSwitchState(entry);                  // @0xf6986e0
    // HbmMuxSwitchState: if EntryDataCase==7 -> return (fsm | 0x100000000); else 0
    if ((state >> 32) == 0) return;                    // not an hbm_mux_switch entry
    fsm = state & 0xffffffff;
    if ((fsm - 1) < 2):                                // fsm in {1,2} — OPEN, no emit
        self[+0x28] = entry;  self[+0x30] = entry.rc;  // stash prev entry + refcount
        self[+0x38] = fsm;                              // open_dir (1 or 2)
        return
    if (fsm == 3):                                      // CLOSE what fsm==1 opened
        if (self[+0x38] != 1) { clear(); return; }
        start = self[+0x28].gtc - (DurationCycles(prev) << 4);
        AddEvent(GetOrCreateLine(56), start, entry.gtc - start, self[+0x20]); // "Node Fabric to BFIFO"
        clear();                                        // zero +0x28/+0x30/+0x38
    else if (fsm == 0):                                 // CLOSE what fsm==2 opened
        if (self[+0x38] != 2) { clear(); return; }
        start = self[+0x28].gtc - (DurationCycles(prev) << 4);
        AddEvent(GetOrCreateLine(56), start, entry.gtc - start, self[+0x18]); // "BFIFO to Node Fabric"
        clear();

HbmMuxSwitchState @ 0xf6986e0 已 byte-confirmed:它检查 EntryDataCase == 7,在 member + 0x1c 读取 fsm field,并返回 fsm | 0x100000000(bit-32 = present marker,低 32 bits = state);否则返回 0。

HBM-mux event payload 是 {fsm switch-symbol, tensor_node};四个 fsm 符号形成两组 open/close pair(1320),因此一个 span 就是 mux 指向某方向所持续的区间。Spans 落在 XLine TpuComponent 56 = "HBM Mux"(name @ 0x84c06ed)上。

NOTE — FSM 是四符号 open/close,不是 two-state toggle:fsm 1 = open(BFIFO→NF)fsm 3 = close 配对(发出 "Node Fabric to BFIFO",meta +0x20);fsm 2 = open(NF→BFIFO)fsm 0 = close 配对(发出 "BFIFO to Node Fabric",meta +0x18)。State 3 是 fsm==1 方向的 close marker,而不是第三种 mux mode。decompiled 0xf1def00 body 中已 byte-confirmed(if ((fsm-1) >= 2) 是 close branch;open branch stash a2 并设置 *(this+56)=fsm)。完整 open/close pairing 由 jxc DMA / HbmMux / brn_perf 负责。


相关 Struct 与 Table Offsets

SymbolAddress / offset角色
PerformanceTraceEntry (proto2)+0x30 EntryDataCase; +0x28 active oneof member ptr; field 1 timestamp (GTC); field 2 chip_id解码后的 jxc message
TracePoint<jxc>::FromTraceEntry0xf1bace0key = (case<<8)|(member->[per-case off] & 0xff)
CoreDispatcher<jxc>::Dispatch0xf1dcee0FlatHashMap<u16, vector<subscriber>>, crc32/vpcmpeqb probe, call *0x10
JxcTracePointName0xf69d800key → name(per-band NameOfDenseEnum;default "Unknown" @ 0x85dd1fd
DecodeTrace(DeviceType, JfTrace*)0xf59dba0通过 GetTraceCodec @ 0xf5a2900 选择 codec;proto path,无 GetBits
setup lambda0xf1da7c010 个 RegisterSubscriber sites;RegisterSubscriber @ 0xf1dca40
HbmMuxSubscriber<jxc>vtable 0x21643ce0; ProcessTraceEntry 0xf1def00+0x18/+0x20 direction XEvents;+0x28 start gtc;+0x38 current dir
HbmMuxSwitchState0xf6986e0fsm @ member+0x1c;返回 fsm | 0x100000000
DmaSubscriber<jxc>vtable 0x21643dc0; ProcessTraceEntry 0xf1dfee0+0x18 XStat(StatType 0x38);+0x20 FlatHashMap<dma_id, vector<begin>>
GetDmaId0xf698180(arm jt 0xab88674composite pairing key;HBM/VMEM-HBM arms 完整,simple arms id & 0xff
nf key table0xab5394017 dwords(low byte = nf id,OR 0x600
ThreadedSubscriber<jxc>0x240 B;+0x20 inner vtable;+0x38 inner ptr;+0xa0 worker包装 HbmMux 和 Dma

相关组件

组件关系
TraceEntriesCoderjxc 使用的现代 fixed-16-byte codec;jxc 是同一 GetTraceCodec selector 中独立的 PerformanceTraceEntry proto2 variant
TracePoints Master Registry记录本页解码为 (case<<8)|id 的 jxc 0x9xx/0xaxx packed keys
Payload: UHI/OCI/ICI/DMA现代 bands;jxc nf DMA band 和 hib_request band 是 newer gens 折入 ICI/intra-DMA 的 legacy analogs
Payload: vfc/vlc/gfcnewer-family payload deltas;没有任何一个携带 jxc 独有的 HBM-mux band
Profiling and Telemetry Overviewcapture→decode→xplane 流水线;本 legacy decode 是其中 jxc-specific 阶段

交叉引用