1/* @ajax/mesh-abi-view-pipedemo: The pipe demo's records and views: msg, digest, sources, pipehash, sinks.
2 *
3 * Part of alpha-c-mesh, a C port of alpha-rust-mesh (README.md says from where). */
4#ifndef MESH_ABI_VIEW_PIPEDEMO_H
5#define MESH_ABI_VIEW_PIPEDEMO_H
67#include <stdbool.h>
8#include <stddef.h>
9#include <stdint.h>
10#include "sha256_compress.h"
11#include "hist_quantile.h"
1213/* The pipe demo (docs/plan-fleet-scheduling.md F2; README "Pipes"): a CPU
14 * stage feeds a GPU stage, whose results a CPU stage checks, all through
15 * pipes (v2::pipe):
16 *
17 * pipesrc (wasm) / pipesrc-n (native) --msg--> pipehash (CUDA / Metal) --digest--> pipesink (native) / pipesink-w (wasm)
18 * and, `mode 1`, a source straight into a sink (it hashes on the CPU itself).
19 *
20 * A `msg` (64 bytes) is (seq, the source's host-clock stamp, origin, 12
21 * payload words derived from seq); its `digest` (48 bytes) is (seq, stamp,
22 * origin | path, sha256d of the msg's 64 bytes). A sink rebuilds the msg
23 * from seq, checks the digest against its own SHA-256 and the record's stamp
24 * against the host clock: one clock for every executor (CLOCK_MONOTONIC;
25 * macOS CLOCK_UPTIME_RAW), so the latency is the whole pipeline's. */
26#define MESH_PIPEDEMO_MSG_TYPE "msg"
27#define MESH_PIPEDEMO_MSG_BYTES 64u
28#define MESH_PIPEDEMO_DIGEST_TYPE "digest"
29#define MESH_PIPEDEMO_DIGEST_BYTES 48u
30/* Record words. */
31#define MESH_PIPEDEMO_R_SEQ 0
32#define MESH_PIPEDEMO_R_STAMP_LO 1
33#define MESH_PIPEDEMO_R_STAMP_HI 2
34/* ORIGIN_* | PATH_* (a digest's path bits say who hashed it). */
35#define MESH_PIPEDEMO_R_ORIGIN 3
36#define MESH_PIPEDEMO_R_PAYLOAD 4
37#define MESH_PIPEDEMO_ORIGIN_WASM 1u
38#define MESH_PIPEDEMO_ORIGIN_NATIVE 2u
39#define MESH_PIPEDEMO_PATH_GPU 0x100u
40/* Sources (pipesrc, pipesrc-n): the view (0x100 bytes; no inbox). */
41#define MESH_PIPEDEMO_S_MODE 0x00u /* u32 MODE_* */
42#define MESH_PIPEDEMO_S_BATCH 0x04u /* u32 records a task at most */
43#define MESH_PIPEDEMO_S_INTERVAL_US 0x08u /* u32 0: as fast as the pipe takes them; else one batch per interval */
44#define MESH_PIPEDEMO_S_NEXT_SEQ 0x0cu /* u32 */
45#define MESH_PIPEDEMO_S_SENT 0x10u /* u32 records pushed */
46#define MESH_PIPEDEMO_S_FULL 0x14u /* u32 pushes refused (the pipe was full: backpressure) */
47#define MESH_PIPEDEMO_S_GONE 0x18u /* u32 tasks with no consumer to push to */
48#define MESH_PIPEDEMO_S_LAST_NS 0x20u /* u64 the last batch's time */
49#define MESH_PIPEDEMO_S_DST 0x28u /* u32 the slot pushed to last + 1 (0: none) */
50#define MESH_PIPEDEMO_MODE_GPU 0u /* msgs to pipehash */
51#define MESH_PIPEDEMO_MODE_DIRECT 1u /* hashed here, digests straight to a sink */
52#define MESH_PIPEDEMO_MODE_OFF 2u
53/* ops (on demand, `task <src> <op> <arg>`): set mode / batch / interval; reset the counters. */
54#define MESH_PIPEDEMO_OP_MODE 2u
55#define MESH_PIPEDEMO_OP_BATCH 3u
56#define MESH_PIPEDEMO_OP_INTERVAL 4u
57#define MESH_PIPEDEMO_OP_RESET 5u
58#define MESH_PIPEDEMO_SRC_BATCH 64u
59/* pipehash: the view, its inbox of msgs at H_INBOX (1024 records), and
60 * per node a carry: the digests a full (or gone) sink did not take yet,
61 * pushed first by the node's next task (nothing is dropped).
62 * Counters: 0 hashed (pushed on), 1 stalls (a task that found the sink
63 * without room and carried or waited), 2 carried (digests put in a carry). */
64#define MESH_PIPEDEMO_H_DST 0x0cu /* u32 the sink's slot + 1 (0: none found) */
65#define MESH_PIPEDEMO_H_INBOX 0x80u
66#define MESH_PIPEDEMO_H_CAP 1024u
67#define MESH_PIPEDEMO_H_CARRY 0x12200u /* node n's carry at H_CARRY + n * H_CARRY_BYTES: u32 count, then (16-aligned) up to 32 digests */
68#define MESH_PIPEDEMO_H_CARRY_BYTES 0x610u
69#define MESH_PIPEDEMO_H_CARRY_REC 0x10u
70#define MESH_PIPEDEMO_H_NODES_MAX 8u
71/* Sinks (pipesink, pipesink-w): the view, the inbox of digests at K_INBOX. */
72#define MESH_PIPEDEMO_K_RECORDS 0x00u /* u32 digests taken */
73#define MESH_PIPEDEMO_K_BAD 0x04u /* u32 of those, the ones whose sha256d did not match */
74#define MESH_PIPEDEMO_K_GPU 0x08u /* u32 ... hashed on the GPU (PATH_GPU) */
75#define MESH_PIPEDEMO_K_CPU 0x0cu /* u32 ... hashed by a source */
76#define MESH_PIPEDEMO_K_MAX_US 0x10u /* u32 the largest latency seen */
77#define MESH_PIPEDEMO_K_P50_US 0x14u /* u32 (refreshed every K_STATS_EVERY tasks of node 0, and on op OP_STATS) */
78#define MESH_PIPEDEMO_K_P90_US 0x18u
79#define MESH_PIPEDEMO_K_P99_US 0x1cu
80#define MESH_PIPEDEMO_K_EMPTY 0x20u /* u32 tasks that found the inbox empty */
81#define MESH_PIPEDEMO_K_LAST_BAD 0x40u /* [u32; 12] the last digest record that did not check */
82#define MESH_PIPEDEMO_K_HIST 0x100u /* u32 x K_BINS: latency in 1 us bins (the last: >= K_BINS - 1 us) */
83#define MESH_PIPEDEMO_K_BINS 4096u
84#define MESH_PIPEDEMO_K_INBOX 0x4100u
85#define MESH_PIPEDEMO_K_CAP 4096u
86#define MESH_PIPEDEMO_K_STATS_EVERY 64u
87/* ops: refresh the percentiles now; zero the counters and histogram. */
88#define MESH_PIPEDEMO_OP_STATS 2u
89#define MESH_PIPEDEMO_OP_SINK_RESET 3u
9091/* Payload word i (4..16) of msg seq. */
92static inline uint32_t mesh_pipedemo_payload(uint32_t seq, size_t i) {
93 return (seq ^ 0x5bd1e995u) * 0x9e3779b9u + (uint32_t)i * 0x85ebca6bu;
94}
95/* The msg of seq: (seq, stamp, origin, 12 payload words). */
96void mesh_pipedemo_msg(uint32_t seq, uint64_t stamp, uint32_t origin, uint32_t out[16]);
97/* sha256d of the msg's 64 bytes (its words little-endian), as the 8 state
98 * words of the second hash (big-endian bytes of the digest). */
99void mesh_pipedemo_sha256d_msg(const uint32_t m[16], uint32_t out[8]);
100/* A digest record for msg m hashed on path (0 or PATH_GPU). */
101void mesh_pipedemo_digest(const uint32_t m[16], uint32_t path, uint32_t out[12]);
102/* `quantile` of the Rust is hist_quantile (@ajax/hist-quantile). */
103104#endif