Skip to main content

vyre_runtime/megakernel/protocol/
opcode.rs

1/// Do nothing. Useful for heartbeat probes.
2pub const NOP: u32 = 0;
3/// `control[args[1]] = args[0]`.
4pub const STORE_U32: u32 = 1;
5/// `atomic_add(control[args[1]], args[0])`.
6pub const ATOMIC_ADD: u32 = 2;
7/// Read `control[args[0]]` into `control[OBSERVABLE_BASE + args[1]]`.
8pub const LOAD_U32: u32 = 3;
9/// `CAS(control[args[0]], expected=args[1], desired=args[2])`.
10pub const COMPARE_SWAP: u32 = 4;
11/// Bulk GPU-to-GPU copy within the control buffer.
12pub const MEMCPY: u32 = 5;
13/// DFA single-step: `next_state = dfa_table[args[0] * 256 + args[1]]`.
14pub const DFA_STEP: u32 = 6;
15/// Batch fence signaling that the published batch is complete.
16pub const BATCH_FENCE: u32 = 7;
17/// GPU-initiated load miss: the megakernel writes a DMA request to the IO
18/// queue and polls for completion. The argument is the consumer's
19/// resource identifier (32-bit, opaque to vyre). vyre is a generic GPU
20/// substrate; it does not know what "the resource" is  -  that is the
21/// consumer's domain. See the boundary rule in AGENTS.md.
22pub const LOAD_MISS: u32 = 0x0000_FFFD;
23/// Deprecated alias retained for source-level compatibility. Will be
24/// removed once all in-tree consumers have migrated; new code must use
25/// [`LOAD_MISS`].
26#[deprecated(
27    since = "0.5.0",
28    note = "vyre is a generic GPU substrate  -  use `LOAD_MISS`. The wire \
29            format is unchanged; only the symbolic name moves."
30)]
31pub const EXPERT_LOAD_MISS: u32 = LOAD_MISS;
32/// Packed slot: one outer ring slot carries several inner ops.
33pub const PACKED_SLOT: u32 = 0x8000_0001;
34/// Write one PRINTF event to the debug log.
35pub const PRINTF: u32 = 0x0000_FFFE;
36/// Set `control[SHUTDOWN] = 1`.
37pub const SHUTDOWN: u32 = u32::MAX;
38/// High bit is reserved for system opcodes.
39pub const SYSTEM_MASK: u32 = 0x8000_0000;
40/// Lower bound for the high reserved range.
41pub const RESERVED_MAX_RANGE_MIN: u32 = 0x0000_FFF0;
42
43/// Return true if the opcode is reserved by the megakernel.
44#[must_use]
45pub const fn is_system(op: u32) -> bool {
46    (op & SYSTEM_MASK) != 0
47        || (op >= RESERVED_MAX_RANGE_MIN && op <= 0x0000_FFFF)
48        || op <= BATCH_FENCE
49}
50
51/// Return true if the opcode is one of the frozen built-in opcodes.
52#[must_use]
53pub const fn is_builtin(op: u32) -> bool {
54    op <= BATCH_FENCE || op == PACKED_SLOT || op == PRINTF || op == SHUTDOWN
55}
56
57/// Validate a user-defined opcode.
58///
59/// # Errors
60///
61/// Returns a static string when `op` overlaps a reserved system range.
62pub const fn validate_user_opcode(op: u32) -> Result<(), &'static str> {
63    if is_system(op) {
64        Err("User opcode overlaps with reserved system range or uses the high bit.")
65    } else {
66        Ok(())
67    }
68}
69
70/// Validate an opcode that is about to be written to the ring.
71pub const fn validate_publish_opcode(op: u32) -> Result<(), &'static str> {
72    if is_builtin(op) {
73        Ok(())
74    } else {
75        validate_user_opcode(op)
76    }
77}
78
79const _: () = {
80    let opcodes = [
81        NOP,
82        STORE_U32,
83        ATOMIC_ADD,
84        LOAD_U32,
85        COMPARE_SWAP,
86        MEMCPY,
87        DFA_STEP,
88        BATCH_FENCE,
89        LOAD_MISS,
90        PACKED_SLOT,
91        PRINTF,
92        SHUTDOWN,
93    ];
94    let mut i = 0;
95    while i < opcodes.len() {
96        let mut j = i + 1;
97        while j < opcodes.len() {
98            assert!(opcodes[i] != opcodes[j], "Duplicate opcode");
99            j += 1;
100        }
101        assert!(is_system(opcodes[i]), "Opcode is not system");
102        i += 1;
103    }
104};