1/* @ajax/mesh-abi-header: The mailbox header (H_*): 0x0000..0x0100.
2 *
3 * Part of alpha-c-mesh, a C port of alpha-rust-mesh (README.md says from where). */
4#ifndef MESH_ABI_HEADER_H
5#define MESH_ABI_HEADER_H
67#include <stdbool.h>
8#include <stddef.h>
9#include <stdint.h>
10#include "mesh/abi/fields.h"
1112/* ---------------------------------------------------------------- header */
13/* 0x0000 .. 0x0100. Line 0 is read-mostly; TRACE has no global counter in v2 */
14/* (each program counts its own records, P_TRACE_N), so nothing here is hot. */
15#define MESH_H_MAGIC 0x00 /* u32 MAGIC */
16#define MESH_H_VERSION 0x04 /* u32 VERSION */
17#define MESH_H_PEER 0x18 /* u32 this system 0..H_SYSTEMS-1 of a cluster, or PEER_NONE */
18/* u32, host: 1 while a blink is in progress. Nodes take no new ticket while
19 * it is set (they keep checking P_SHUTDOWN). */
20#define MESH_H_BLINK 0x20
21/* u32, host: bumped at the end of every blink (module set changed). */
22#define MESH_H_EPOCH 0x24
23/* u32, host: bumped after every program-table change (viewers re-read the table). */
24#define MESH_H_PROG_SEQ 0x28
25/* u32, host: the device's SM count (mesh-rt's `Ctx::sms`). */
26#define MESH_H_SMS 0x2c
27/* u32, host: the fleet's size N (1 single, 2..=MAX_SYSTEMS in a fleet), set
28 * before any program's OP_INIT; with H_PEER the fleet's ids (viewers, http).
29 * Lockstep programs read their group (H_GROUP_*). */
30#define MESH_H_SYSTEMS 0x30
31/* u32, host: the device's compute capability, major * 10 + minor (GB10 121,
32 * RTX 3060 86). With H_BLOCKS_PER_SM, H_SMS_TOTAL and each program's PT_REGS
33 * / PX_PER_SM these are the per-machine facts a heterogeneous cluster shows.
34 * The header is the one source of truth for them: the snapshot carries the
35 * header (viewers read them there) and F_JOIN's caps are read from it. */
36#define MESH_H_CC 0x34
37/* u32, host: CU_DEVICE_ATTRIBUTE_MAX_BLOCKS_PER_MULTIPROCESSOR (GB10 24, sm_86 16). */
38#define MESH_H_BLOCKS_PER_SM 0x38
39/* u32, host: the device's SM count (H_SMS is the SMs meshd's context runs on). */
40#define MESH_H_SMS_TOTAL 0x3c
41/* u32, host: which GPU backend runs the programs, BACKEND_* in bits 0..8 and
42 * the device family in bits 8..16 (Metal: the highest MTLGPUFamilyAppleN the
43 * device supports, M3 Ultra 9; CUDA: 0). The word is 0 on a CUDA machine
44 * (BACKEND_CUDA), so every CUDA header reads as before. A non-CUDA device
45 * has no compute capability: H_CC is 0 there, and H_SMS / H_SMS_TOTAL count
46 * its compute units instead of SMs (Metal: GPU cores), H_BLOCKS_PER_SM is 0
47 * (no resident blocks: Metal runs leases, see BACKEND_METAL). */
48#define MESH_H_BACKEND 0x40
49/* u32, host: the device's maximum threads per threadgroup / block (Metal:
50 * maxThreadsPerThreadgroup, M3 Ultra 1024; CUDA: MAX_THREADS_PER_BLOCK, 1024). */
51#define MESH_H_MAX_TG_THREADS 0x44
52/* u32, host: the load window, bumped by meshd's load sampler about once a
53 * second. A node that sees it change starts a new longest-gap word
54 * (NL_MAX_GAP_NS, NL_WIN). */
55#define MESH_H_LOAD_WIN 0x48
56/* u32 each, host: this member's lockstep group (fleet plan F3): its rank in
57 * the group's ordered member list, the group's size, and the group's epoch.
58 * A lockstep program exchanges with the group (ex_counter(rank),
59 * ex_slots(rank); it sums ranks 0..N-1 in order), never with H_SYSTEMS. N is
60 * 0 when this member is in no group (single, or left out of the current
61 * epoch). meshd writes them only while the lockstep program is halted or
62 * drained and unfed (an epoch change), so a task never sees them move. */
63#define MESH_H_GROUP_RANK 0x4c
64#define MESH_H_GROUP_N 0x50
65#define MESH_H_GROUP_EPOCH 0x54
66/* u32, host: the pipes' flight epoch (mesh-abi pipe::flight_begin). A push
67 * counts itself in its producer's PP_FLIGHT word of parity H_PIPE_EPOCH & 1;
68 * meshd bumps it before it waits for the pushes in flight to end, so the
69 * pushes that count in the old parity's word only drain. */
70#define MESH_H_PIPE_EPOCH 0x58
71/* u32, host: the most shared (threadgroup) memory one node may have, in
72 * bytes (CUDA: MAX_SHARED_MEMORY_PER_BLOCK_OPTIN, Metal:
73 * maxThreadgroupMemoryLength), the runtime's RT_SHARED_BYTES included. A
74 * manifest whose RT_SHARED_BYTES + shared_bytes exceeds it is refused here. */
75#define MESH_H_MAX_SHARED 0x5c
76#define MESH_H_BYTES 0x100
77/* Every field of a region as (offset, bytes): the compile-time checks
78 * require that no two of them alias (two branches once both put a word at
79 * header 0x30), and each table's last field must end inside its region. */
80#define MESH_HEADER_FIELDS_LEN 19
81extern const mesh_field MESH_HEADER_FIELDS[19];
8283/* The Rust const asserts that only involve this package. */
84_Static_assert(MESH_H_SMS < MESH_H_SYSTEMS, "H_SMS < H_SYSTEMS");
85_Static_assert(MESH_H_SYSTEMS < MESH_H_CC, "H_SYSTEMS < H_CC");
86_Static_assert(MESH_H_SMS_TOTAL + 4 <= MESH_H_BACKEND, "H_SMS_TOTAL + 4 <= H_BACKEND");
87_Static_assert(MESH_H_MAX_TG_THREADS + 4 <= MESH_H_BYTES, "H_MAX_TG_THREADS + 4 <= H_BYTES");
88_Static_assert(MESH_H_SYSTEMS + 4 <= MESH_H_BYTES, "H_SYSTEMS + 4 <= H_BYTES");
8990#endif