Master Opcode Reference
All symbols, ordinals, and addresses on this page apply to
neuronx_cc2.24.5133.0+58f8de22 (cp310 wheel). The L1 enum is defined inneuronxcc/starfish/lib/libBIR.so(md512bb979f7ca41248252abb0f16b2da98); the L2/L3 encoders andsetupHeaderare inneuronxcc/starfish/lib/libwalrus.so(.text/.rodatabase0x62d660/0x1c72000, VA == file offset). cp311/cp312 share the.textlogic — the opcode integers and the L1/L2/L3 arithmetic are ABI-stable across cp3xx, only the VAs drift. Other wheels differ — treat every address as version-pinned. See Build & Version Provenance.
Abstract
This appendix is the single consolidated lookup table for the neuronx-cc backend opcode space: all 110 bir::InstructionType arms × the wire opcode word per generation {V2, V3, V4} × the owning engine × the access/bundle family. It unifies what the three normative pages established separately — the 110-opcode InstructionType enum and its sameInst masks, the setupHeader L3 wire-word path and per-op opcode master, and the per-engine encoding pages (PE matmul, Pool, Activation, DVE, DMA) — into one row-per-opcode grid a reimplementer can scan by either the IR ordinal or the wire byte.
The reimplementation model is the three-layer opcode contract (§0): a BIR op carries up to three distinct integer identities in three separate namespaces. L1 is the bir::InstructionType ordinal (0..109, the IR class id). L2 is the NEURON_ISA_TPB_OPCODE enum value the COLLECT_OPCODES arm records (the engine-relative silicon micro-op id). L3 is the 16-bit wire header word setupHeader stamps at bundle[0:2], equal to (0x10 << 8) | L2byte. The cardinal invariant is L1 ≠ L2 for every op — they are different enums, equal for no opcode — so an opcode↔IT mapping is never one-to-one, and the only cross-layer-stable key is the shared name (the BIR-JSON "type" string), not any integer.
This page is a reference catalog, not an algorithm walkthrough; its value is completeness and correctness. The table in §1 is re-derived directly from InstructionType2string (0x2d5bf0), the sameInst switch (0x2db7b0), the three setupHeader bodies, and the per-op visitInst* COLLECT/GENERATE immediates — not hand-copied from the consolidated pages, so it catches their slips. Every per-gen cell carries a confidence tag; the five highest-risk rows (the per-arch Activation divergence, the MX family, the collective/custom-op/DMA arms) were adversarially re-verified against the binary in §4. Where a re-derivation disagreed with an earlier page, it is flagged in place as a CORRECTION with byte evidence, never silently overwritten.
| L1 enum | bir::InstructionType — 110 members, ordinals 0..109, uint32_t, at bir::Instruction + 0x58 — CONFIRMED |
| L1 name table | bir::InstructionType2string @ 0x2d5bf0 (110-case switch → assert "Unknown opcode" @ Instruction.cpp:79) |
| L2 enum | NEURON_ISA_TPB_OPCODE — COLLECT-set int; decoded by core_v4::enum_variant_string_opcode @ 0x143fd80 (161 named) |
| L3 word rule (INV-1) | L3word = (0x10 << 8) | L2byte; QuantizeMx sets byte[1] |= 1 on SATURATE — CONFIRMED |
| Header writer | CoreV{2,3,4}GenImpl::setupHeader @ 0x1172120 / 0x1369280 / 0x143f440 — byte-identical, 16-byte body — CONFIRMED |
inst_word_len | byte[1] = 0x10 = 16 dwords = 64-byte bundle, hardcoded, no non-16 length exists — CONFIRMED |
| Cardinal invariant (INV-3) | L1 ≠ L2 numerically for every op; the shared name is the only cross-layer key — CONFIRMED |
| Concrete-opcode ITs | ~85 of 110 reach a real L2/L3 opcode; ~25 are lowered / abstract / kernel-carrier (no opcode) |
0. The three-layer opcode contract
A BIR op has up to three integer identities. Conflating them is the cross-layer error the normative opcode page (§0) was written to kill, and it recurs in any map that prints "opcode 4 = Activation" without saying which opcode.
L1 bir::InstructionType ordinal (0..109)
= the C++ enum tag at bir::Instruction+0x58 (the 22nd dword)
= the IR class id — what the node *is*
defined in libBIR (2string @0x2d5bf0, sameInst @0x2db7b0) [CONFIRMED]
L2 NEURON_ISA_TPB_OPCODE value
= the int the COLLECT_OPCODES arm inserts into std::set<u32>
= the byte GENERATE writes to bundle[0]
= the engine-bitmap bit position in the wire validator
= the silicon micro-op id — engine-relative
decoded by core_v4::enum_variant_string_opcode @0x143fd80 [CONFIRMED]
L3 the 16-bit wire HEADER WORD setupHeader stamps at bundle[0:2]
bundle[0] = opcode byte (= L2 low byte)
bundle[1] = 0x10 = inst_word_len (16 dwords = 64-byte bundle, HARDCODED)
bundle[2:4] = 0x0000
⇒ L3word = (0x10 << 8) | L2byte [CONFIRMED]
The three invariants a reimplementation must honor:
- INV-1 —
L3word = (0x10 << 8) | L2byte. The high byte0x10is the fixed length nibble (16 dwords); the low byte is the L2 opcode.QuantizeMxis the only op that perturbs the high byte: it OR-s bit 0 (0x10 → 0x11) when theSATURATEflag is set. - INV-2 —
L2is one value, consistent across its uses: COLLECT-set int == GENERATEbundle[0]byte == opcode-count-map key == engine-bitmap bit. - INV-3 —
L1 ≠ L2numerically for every op. The encoder is the non-injective projectionL1 → {L2}. The only cross-layer-stable key is the L2/L1 name (BIR-JSON"type"), never any integer.
setupHeader itself is the same six instructions in all three generations (0f b6 02 c6 46 01 10 88 06 31 c0 66 89 46 02 c3): load the opcode byte, store 0x10 at bundle[1], store the opcode at bundle[0], zero bundle[2:4], return. It is reached as a virtual through the Generator vtable slot +0x48 (slot 9). All per-arch and per-op variation lives in the opcode byte fed to it, never in the header layout — which is exactly why this table can be one grid: only one column-family (the L3 byte) ever moves.
NOTE — the engine column is metadata, not a wire field. The physical engine rides the BIR
Instructionat+0x90(EngineType); the encoder only reads it as a census-map key.{PE=0, ACT=1, POOL=2, DVE=3, SP=4}on the wire. It is listed below because a reimplementer must route the op to the right engine, but it is never encoded in the 64-byte bundle.
1. Master 110-row opcode table
One row per bir::InstructionType ordinal. Words are shown as 0x10NN (NN = the L2 low byte). = in a per-gen column means inherits the prior generation's word verbatim (no override). — means not encoded on that generation (gen-gated). (lowered) / (no enc) / (base) mean the IT reaches no setupHeader at all (see the Kind column).
Columns: IT = L1 ordinal · Name = InstructionType2string name (= the cross-layer key) · L2 = NEURON_ISA_TPB_OPCODE low byte (hex) · V2/V3/V4 = the L3 16-bit word per generation · #B = 64-byte bundles this one op emits · Eng = physical engine (+0x90 metadata) · Kind/flags = reconciliation tags (legend below the table) · Conf = confidence of the opcode value.
Legend for Kind/flags: [base] abstract base IT (leaves carry the opcode) · [low] lowered-away / no encoder · [split] one IT forks into several L2 opcodes by a runtime field · [mb:n] multi-bundle (emits n wire words) · [col] L2 collision (this opcode is shared by another IT) · [ΔV4]/[ΔV3] genuine per-gen opcode-byte renumber · [newV3]/[newV4] gen-introduced (no earlier encoder) · [+1=cast] opcode low bit = dtype-cast flag.
| IT | Name | L2 | V2 | V3 | V4 | #B | Eng | Kind / flags | Conf |
|---|---|---|---|---|---|---|---|---|---|
| 0 | Generic | — | (lowered) | = | = | lo | — | [base][low] accepts IT≤3 in sameInst | CONFIRMED-absent |
| 1 | GenericCopy | — | (lowered) | = | = | lo | — | [low] no visitInstGenericCopy body | CONFIRMED-absent |
| 2 | GenericRelu | — | (lowered) | = | = | lo | — | [low] → Activation | INFERRED |
| 3 | AbstractCopy | — | (lowered) | = | = | lo | — | [low] LowerAC pass | CONFIRMED-absent |
| 4 | Activation | 0x21/0x25 | 0x1021 | = | 0x1025 | 1 | ACT | [ΔV4] ★ V4 byte 0x25 ≠ V2/V3 0x21 | CONFIRMED |
| 5 | ReadActivationAccumulator | 0x24 | 0x1024 | = | = | 1 | ACT | [col] shares 0x24 w/ IT101 | CONFIRMED |
| 6 | LoadActFuncSet | 0x23 | 0x1023 | = | = | 1 | ACT | — | CONFIRMED |
| 7 | MatmultBase | — | (base) | (base) | (base) | — | PE | [base] of {7,8,9,95} | n/a |
| 8 | Matmult | 0x01+0x02 | 0x1001+0x1002 | = | = | 1–4 | PE | [split][mb:2] fp32→4 bundles; cache may skip LdW | CONFIRMED |
| 9 | MatmultSparse | 0x06+0x07(+0x01) | — | 0x1006+0x1007 | = | 2–5 | PE | [split][mb:2+][newV3] +LdWeights 0x01; fp32→5 | CONFIRMED |
| 10 | Memset | 0x49/0x4D | 0x1049/0x104D | = | = | 1 | DVE | [split][col] 0x49 Const / 0x4D Random(==Rng IT100) | CONFIRMED |
| 11 | GetGlobalRankId | 0xDC | 0x10DC | = | = | 1 | CC | — | CONFIRMED |
| 12 | NoOp | 0xA4 | 0x10A4 | = | = | 1 | SP | Nop | CONFIRMED |
| 13 | EventSemaphore | 0xA0 | 0x10A0 | = | = | 1 | SP | — | CONFIRMED |
| 14 | GroupResetSemaphores | 0xB0 | 0x10B0 | = | = | 1 | SP | EventSemaphoreRangeClear (≠ IT13) | CONFIRMED |
| 15 | AllEngineBarrier | 0xD5 | 0x10D5 | = | = | 1 | SP | PseudoSyncBarrier | CONFIRMED |
| 16 | Drain | 0xA2 | 0x10A2 | = | = | 1 | SP | — | CONFIRMED |
| 17 | Halt | 0xA1 | 0x10A1 | = | = | 1 | SP | — | CONFIRMED |
| 18 | DMA | — | (base) | = | = | — | DMA | [base] accepts {18,19,22,32,41-46,67} | n/a |
| 19 | Load | 0xD4 | 0x10D4 | = | = | 1 | DMA | [col] → generateDynamicDMA (==Save,DMACopy) | CONFIRMED |
| 20 | Pool | 0x45 | 0x1045 | = | = | 1 | POOL | — | CONFIRMED |
| 21 | Reciprocal | 0x48 | 0x1048 | = | = | 1 | DVE | — | CONFIRMED |
| 22 | Save | 0xD4 | 0x10D4 | = | = | 1 | DMA | [col] → generateDynamicDMA | CONFIRMED |
| 23 | TensorCopy | 0x46/0x47 | 0x1046/0x1047 | = | = | 1 | DVE | [split][+1=cast] 0x47 = dtype change | CONFIRMED |
| 24 | TensorCopyDynamicSrc | — | (lowered) | = | = | lo | — | [low] lowered before CoreV2 | INFERRED |
| 25 | TensorCopyDynamicDst | — | (lowered) | = | = | lo | — | [low] lowered before CoreV2 | INFERRED |
| 26 | IndirectCopy | 0xE7 | 0x10E7 | = | (copy) | 1 | POOL | TRN1/V2-only; lowered to COPY on V3+ | CONFIRMED |
| 27 | TensorReduce | var | 0x107C/0x107D/0x1042/0x1052/0x1083/0x1084 | = | = | 1 | Pool/DVE | [split] TR 124/125 + CR 66/82/131/132 (6 opcodes) | CONFIRMED |
| 28 | TensorScalar | var | 0x1043/0x1093/0x1053/0x109A | (ext) | (ext) | 1 | DVE | [split] no own enc; shares IT29 dispatcher | CONFIRMED |
| 29 | TensorScalarPtr | var | 0x1043/93/53/9A/9C/9E/E5/74 | (ext) | (ext) | 1 | DVE | [split] dispatcher: OrPtr+STT+Addr | CONFIRMED |
| 30 | TensorScalarCache | 0x9A/0xE6 | 0x109A/0x10E6 | (ext) | (ext) | 1 | DVE | [split] 0x9A Reduce / 0xE6 Cumul+Scan by TSCMode | CONFIRMED |
| 31 | TensorTensor | 0x41/0x51 | 0x1041/0x1051 | 0x1041/0x1051 | = | 1 | DVE | [split] +GPSIMD int32 re-stamp 0x8A; V3 = field ext only | CONFIRMED |
| 32 | DMACopy | 0xD4(/0xDA) | 0x10D4(/0x10DA) | = | = | 1 | DMA | [col] → generateDynamicDMA; IT==32 test re-distinguishes | CONFIRMED |
| 33 | GPSIMDSB2SB | 0xBF | — | 0x10BF | = | 1 | GPSIMD | [newV3] Sb2sbCollective | CONFIRMED |
| 34 | BNStats | 0x61/0x82 | 0x1061/0x1082 | = | = | 1 | POOL | [split] 0x61/0x82 by apply_transpose | CONFIRMED |
| 35 | BNStatsAggregate | 0x62 | 0x1062 | = | = | 1 | POOL | BatchNormAggregate | CONFIRMED |
| 36 | BNGradients | 0x63/0x94 | 0x1063/0x1094 | = | = | 1 | POOL | [split] 0x63 AP-coeff / 0x94 register-coeff | CONFIRMED |
| 37 | BNBackprop | 0x64(+0x65) | 0x1064(+0x1065) | = | = | 1–2 | POOL | [mb:2] BACK_PROP 0x64 + PARAM_LOAD 0x65 | CONFIRMED |
| 38 | BNBackprop2 | 0x64(+0x8E) | 0x1064(+0x108E) | = | = | 1–2 | POOL | [mb:2] shares 0x64; V2 visit stamps 0x8E param | CONFIRMED |
| 39 | StreamShuffle | 0x69+0x6A | 0x1069+0x106A | = | = | 2 | DVE | [mb:2][col] mask 0x69 (==StreamTranspose) | CONFIRMED |
| 40 | StreamTranspose | 0x69+0x6B | 0x1069+0x106B | = | = | 2 | DVE | [mb:2][col] mask 0x69 (==StreamShuffle) | CONFIRMED |
| 41 | ReadVarAddr | 0xB2 | 0x10B2 | = | = | 1 | DMA | MoveShape (generateMoveShape) | STRONG |
| 42 | GenericIndirectLoad | — | (lowered→43) | = | = | lo | — | [low] → IndirectLoad | INFERRED |
| 43 | IndirectLoad | 0xD6/0xC4 | 0x10D6/0x10C4 | = | = | 1 | DMA | generateIndirectLoadSave(isLoad); see CORRECTION (OPC-1) | CONFIRMED |
| 44 | GenericIndirectSave | — | (lowered→45/46) | = | = | lo | — | [low] → IndirectSave(Accum) | INFERRED |
| 45 | IndirectSave | 0xD6/0xC4 | 0x10D6/0x10C4 | = | = | 1 | DMA | generateIndirectLoadSave(isLoad); see CORRECTION (OPC-1) | CONFIRMED |
| 46 | IndirectSaveAccumulate | 0xCA | 0x10CA | = | = | 1 | CCE/Pool/Act | PseudoEmbeddingUpdate (scatter-add) | CONFIRMED |
| 47 | Collective | — | (base) | = | = | — | POOL | [base] of {47,48,49,50} | n/a |
| 48 | CollectiveCompute | 0xD9/0xDA | 0x10D9/0x10DA | = | = | 1 | POOL | [split] fine 0xD9 / coarse 0xDA | CONFIRMED |
| 49 | CollectiveSend | 0xCB | 0x10CB | = | = | 1 | POOL | [col] shares 0xCB w/ Recv; direction = field | CONFIRMED |
| 50 | CollectiveRecv | 0xCB | 0x10CB | = | = | 1 | POOL | [col] shares 0xCB w/ Send | CONFIRMED |
| 51 | Select | — | (lowered) | = | = | lo | DVE | [low] → GenericCopy + CopyPredicated(0xEA) | CONFIRMED |
| 52 | CopyPredicated | 0xEA | 0x10EA | = | = | 1 | DVE | the masked-copy / SELECT emitter | CONFIRMED |
| 53 | CustomOp | 0x85+0x86 | 0x1085+0x1086 | = | = | ≥2 | any | [mb:≥2] header 0x85 + 0x86×(1+num_args) | CONFIRMED |
| 54 | BIRKernel | — | (no enc) | = | = | none | — | [low] kernel container; no 64-B bundle | INFERRED |
| 55 | NKIKernel | — | (no enc) | = | = | none | — | [low] "Not Implemented" (sameInst too) | CONFIRMED-absent |
| 56 | NKIKLIRKernel | — | (no enc) | = | = | none | — | [low] "Not Implemented" | CONFIRMED-absent |
| 57 | DevicePrint | — | (debug-meta) | = | = | none | — | [low] instruction_debug_info protobuf, NO setupHeader | CONFIRMED |
| 58 | GetRandState | 0x77 | 0x1077 | 0x1077 | = | 1 | DVE/Pool | [col] shares 0x77 w/ RandGetState IT99; V3 ovr = same op | CONFIRMED |
| 59 | SetRandState | 0xD0(/0x78) | 0x10D0 | 0x1078/0x10D0 | = | 1 | DVE/Pool | [split] V2=DVE 0xD0; V3 Pool-arm 0x78 / DVE-arm 0xD0 | CONFIRMED |
| 60 | Rand | — | (no enc) | (no enc) | see Rand2 | — | DVE | [low] no CoreV* encoder; Rand2(IT97) is the gen form | INFERRED |
| 61 | Iota | 0x7E | 0x107E | = | = | 1 | DVE | — | CONFIRMED |
| 62 | TensorScalarAffineSelect | 0x92 | 0x1092 | (ext) | (ext) | 1 | DVE | fixed 0x92; 4-D mask + 2-bit compare | CONFIRMED |
| 63 | RangeSelect | 0xBC | — | 0x10BC | = | 1 | DVE | [newV3] +0x9B DveReadAcc append (see CORRECTION OPC-2) | CONFIRMED |
| 64 | GetSequenceBounds | 0xBE | — | 0x10BE | = | 1 | GPSIMD | [newV3] | CONFIRMED |
| 65 | Dropout | 0x7F | 0x107F | = | = | 1 | DVE | — | CONFIRMED |
| 66 | GetCurProcessingRankID | 0xDB | 0x10DB | = | = | 1 | CC | pairs w/ GetGlobalRankId | CONFIRMED |
| 67 | DMATrigger | 0xC1 | 0x10C1 | = | = | 1 | DMA | PseudoDMATrigger | CONFIRMED |
| 68 | DMADescriptor | — | (no enc) | = | = | none | DMA | [base][low] of {68..72}; emitted via DMA path | INFERRED |
| 69 | DMADescriptorCopy | — | (no enc) | = | = | none | DMA | [low] | INFERRED |
| 70 | DMADescriptorCCE | — | (no enc) | = | = | none | DMA | [low] | INFERRED |
| 71 | DMADescriptorTranspose | — | (no enc) | = | = | none | DMA | [low] | INFERRED |
| 72 | DMADescriptorReplicate | — | (no enc) | = | = | none | DMA | [low] | INFERRED |
| 73 | RegisterAlu | 0xA8 | 0x10A8 | = | = | 1 | SP | AluOp | CONFIRMED |
| 74 | RegisterMove | 0xA7 | 0x10A7 | = | = | 1 | SP | Move | CONFIRMED |
| 75 | TensorLoad | 0xCE/0xAA | 0x10CE/0x10AA | = | = | 1 | scalar | [split] 0xCE imm-addr / 0xAA reg-mode | CONFIRMED |
| 76 | TensorSave | 0xAB/0xCD | 0x10AB/0x10CD | = | = | 1 | scalar | [split] 0xAB imm-addr / 0xCD reg-mode | CONFIRMED |
| 77 | Terminator | — | (base) | = | = | — | SP | [base] of {77,78,79,81,82}; rejects 80 | n/a |
| 78 | CompareAndBranch | 0xA9 | 0x10A9 | = | = | 1 | SP | [col] shares 0xA9 w/ UncondBranch | CONFIRMED |
| 79 | UnconditionalBranch | 0xA9 | 0x10A9 | = | = | 1 | SP | [col] shares 0xA9 w/ CmpBranch | CONFIRMED |
| 80 | BranchHint | 0xDD | 0x10DD | = | = | 1 | SP | PseudoBranchPrefetchHint; excluded from Terminator-class eq | CONFIRMED |
| 81 | Return | 0xD2 | 0x10D2 | = | = | 1×N | SP | [mb:N] broadcast 1 bundle per active engine | CONFIRMED |
| 82 | Exit | 0xDF | 0x10DF | = | = | 1 | SP | PseudoInst | CONFIRMED |
| 83 | Break | — | (control) | = | = | none | SP | [low] no standard ISA bundle | INFERRED |
| 84 | Call | 0xD3 | 0x10D3 | = | = | 1×N | SP | [mb:N] broadcast per engine; no sameInst | CONFIRMED |
| 85 | SwitchQueueInstance | 0xCF | 0x10CF | = | = | 1 | DMA | PseudoDMASwapQueueSet | CONFIRMED |
| 86 | ResetQueueInstance | 0xC2 | 0x10C2 | = | = | 1 | DMA | PseudoDMARearm | CONFIRMED |
| 87 | CoreBarrier | 0xD8 | — | 0x10D8 | = | 1 | SP | [newV3] PseudoCoreBarrier | CONFIRMED |
| 88 | Max | 0x6C | 0x106C | = | = | 1 | DVE | Max8 | CONFIRMED |
| 89 | MaxIndex | 0x6D+0x6E | 0x106D+0x106E | = | = | 2 | DVE | [mb:2][col] shares 0x6D+0x6E w/ IT91 | CONFIRMED |
| 90 | MatchReplace | 0x6F | 0x106F | = | = | 1 | DVE | MatchReplace8; sameInst accepts {90,91} | CONFIRMED |
| 91 | MaxIndexAndMatchReplace | 0x6D+0x6E | — | 0x106D+0x106E | = | 2 | DVE | [mb:2][col][newV3] via shared helper | STRONG |
| 92 | Gather | 0x67+0x68 | 0x1067+0x1068 | = | (copy) | 2 | POOL | [mb:2] TRN3+ → plain COPY | CONFIRMED |
| 93 | InlineASMBytes | (user) | (user bytes) | = | = | * | any | opcode = user byte0; no fixed value | CONFIRMED |
| 94 | TensorCompletion | 0xDE | 0x10DE | = | = | 1 | CC | PseudoTensorCompletion | CONFIRMED |
| 95 | MatmultMx | 0x09+0x0A | — | — | 0x1009+0x100A | 2 | PE | [split][mb:2][newV4] ALWAYS 2 bundles | CONFIRMED |
| 96 | QuantizeMx | 0xE3 | — | — | 0x10E3 | 1 | PE/DVE | [newV4] ★ byte[1] |= 1 on SATURATE | CONFIRMED |
| 97 | Rand2 | 0xE2 | — | — | 0x10E2 | 1 | DVE | [newV4] bounded RNG | CONFIRMED |
| 98 | RandSetState | 0x78 | — | 0x1078 | = | 1 | Pool/DVE | [newV3] | CONFIRMED |
| 99 | RandGetState | 0x77 | — | 0x1077 | = | 1 | Pool/DVE | [newV3][col] shares 0x77 w/ GetRandState IT58 | CONFIRMED |
| 100 | Rng | 0x4D | 0x104D | = | = | 1 | DVE | [col] ★ SAME wire opcode as Memset(Random) IT10 | CONFIRMED |
| 101 | ActivationReadAccumulator | 0x24 | 0x1024 | = | = | 1 | ACT | [col] shares 0x24 w/ IT5 (HEADER-only) | CONFIRMED |
| 102 | DveReadAccumulator | 0x9B | 0x109B | = | = | 1 | DVE | — | CONFIRMED |
| 103 | Exponential | 0x30 | — | — | 0x1030 | 1 | ACT | [newV4] fused exp+sum | CONFIRMED |
| 104 | NonzeroWithCount | 0xF2 | — | 0x10F2 | = | 1 | DVE | [newV3] see CORRECTION (OPC-3) | CONFIRMED |
| 105 | Loop | — | (lowered) | = | = | lo | — | [low] lowered to branch IR; no sameInst arm | HIGH |
| 106 | DynamicForLoop | — | (lowered) | = | = | lo | — | [low] lowered to branch IR | HIGH |
| 107 | DMABlock | — | (region) | = | = | lo | DMA | [low] DMA-block region carrier; no opcode | INFERRED |
| 108 | DoWhile | — | (lowered) | = | = | lo | — | [low] lowered to branch IR | INFERRED |
| 109 | TongaReduceMacroSymbolic | — | (macro) | = | = | lo | — | [low] macro/symbolic reduce carrier; no opcode | INFERRED |
GOTCHA — never assume
opcode ↔ ITis one-to-one. The grid is non-injective in both directions: one IT can emit several L2 opcodes ([split]/[mb]), and one L2 opcode is shared by several ITs ([col]). A reimplementation that keys a decode table on the bare opcode byte will aliasRngwithMemset,SendwithRecv, the two branches, and the three DMA-direct ops. The disambiguator is always an in-bundle field, the direction bool, or the engine — see §2 and §3.
2. L2 opcode collisions
Eight wire opcodes are emitted by more than one InstructionType. The silicon does not distinguish the colliding ITs by opcode; an in-bundle field, the direction bit, or the engine does. This is the [col] flag, gathered. (IndirectLoad/IndirectSave are not a collision — they carry two distinct opcodes selected by a direction bool; see CORRECTION OPC-1.)
| L2 word | ITs that share it | Disambiguator |
|---|---|---|
0x104D | Rng(100) == Memset-Random(10, mode 1) | fill immediate: Memset writes Inst+0xF8 fill, Rng forces fill = 0 |
0x10CB | CollectiveSend(49) == CollectiveRecv(50) | direction is an in-bundle field (encoder bodies are byte-identical) |
0x10A9 | CompareAndBranch(78) == UnconditionalBranch(79) | branch-condition presence (CTRL_BR struct) |
0x10D4 | Load(19) == Save(22) == DMACopy(32) | all route through generateDynamicDMA; an IT==32 test re-distinguishes DMACopy |
0x1024 | ReadActivationAccumulator(5) == ActivationReadAccumulator(101) | distinct encoder bodies, same opcode |
0x1077 | GetRandState(58) == RandGetState(99) | distinct ITs, same RNG-state-read micro-op |
0x1069 | StreamShuffle(39).MASK == StreamTranspose(40).MASK | the data-move word differs (0x6A vs 0x6B) |
0x106D+0x106E | MaxIndex(89) == MaxIndexAndMatchReplace(91) | shared generateInstMatchReplaceWithOptionalMaxIndex helper |
QUIRK —
Rng(100) andMemset(Random)(10) collapse to the same0x4DDVE-RNG slot — two distinct IR ops compiling to one micro-op, separated only by whether the fill immediate is forced to zero. A decoder cannot recover which IR op produced a0x104Dbundle from the opcode alone; that information is gone by L3.
3. Multi-bundle and [split] ops
Multi-bundle ops ([mb:n] — one IR op → n wire bundles)
A reimplementation must iterate the op's COLLECT set (it is a std::set<u32>, legally holding more than one opcode), not assume one opcode per instruction.
| IT | Op | Bundle sequence | Count |
|---|---|---|---|
| 8 | Matmult | LdWeights 0x01 + MatMul 0x02 | 1–4 (cache-hit skips LdW → 1; fp32 2-pass → 4) |
| 9 | MatmultSparse | Ldtags 0x06 + LoadWeights 0x01 + MatMulSparse 0x07 | 2–5 (fp32 split → 5) |
| 95 | MatmultMx | LdWeightMx 0x09 + MatmulMx 0x0A | always 2 |
| 89 | MaxIndex | 0x6D (value-load) + 0x6E (index) | 2 |
| 91 | MaxIndexAndMatchReplace | 0x6D + 0x6E | 2 |
| 39 | StreamShuffle | 0x69 mask + 0x6A data-move | 2 |
| 40 | StreamTranspose | 0x69 mask + 0x6B data-move | 2 |
| 92 | Gather | 0x67 buffer-load + 0x68 gather | 2 |
| 53 | CustomOp | 0x85 header + 0x86×(1 + num_args) | ≥2 |
| 37/38 | BNBackprop/BNBackprop2 | 0x64 control + 0x65/0x8E param-load | 1–2 |
| 81/84 | Return/Call | broadcast 0xD2/0xD3 once per active engine | 1×N |
[split] ops (one IT → multiple L2 opcodes selected by a runtime field)
The opcode is chosen at encode time by a sub-type discriminator, not fixed per IT:
TensorReduce(27): TR0x7C/0x7D+ CR0x42/0x52/0x83/0x84— selected by(apply_transpose, isBitVec)(6 opcodes total).TensorScalar(28)/TensorScalarPtr(29):0x43/0x93/0x53/0x9A/0x9C/0x9E/0xE5/0x74— one dispatcher (generateTensorScalarOrPtr); IT28 has no own encoder. V3/V4 widen the field bands, not the opcode.TensorScalarCache(30):0x9A(Reduce) /0xE6(Cumulative+Scan) byTSCMode.TensorTensor(31):0x41/0x51byisBitVecInstruction(+ GPSIMD int32 re-stamp0x8A).BNStats(34):0x61/0x82byapply_transpose.BNGradients(36):0x63/0x94by coeff source.Memset(10):0x49(Const) /0x4D(Random).CollectiveCompute(48):0xD9/0xDA(fine/coarse).TensorLoad(75):0xCE/0xAA(imm/reg).TensorSave(76):0xAB/0xCD(imm/reg).SetRandState(59):0x78(Pool) /0xD0(DVE) byEngineType.TensorCopy(23):0x46(no cast) →0x47(cast). The[+1=cast]low bit is decided on the raw src/dst dtype, not the reinterpreted one.
4. Adversarial verification — five highest-risk rows
These five rows are the ones most likely to be wrong in a transcription (per-gen divergence, gen-gated families, the collisions). Each was re-derived from the encoder body's COLLECT dword-store / GENERATE byte-store immediates and the 0x10<<8|byte word-store, read from the libwalrus disasm sidecars (cp310, VA == file offset).
| # | Row | Binary witness | Result |
|---|---|---|---|
| 1 | Activation(4) V2 ≠ V4 | CoreV2 visitInstActivation @ 0x12596f0: mov dword[rbp-150h],0x21 @0x125984f, byte 0x21 @0x12599fc. CoreV4 @ 0x143bbb0: mov dword[rbp-B0h],0x25 @0x143bc28, byte 0x25 @0x143c25f, mov esi,0x1025 @0x143c27e. | V2/V3 = 0x1021, V4 = 0x1025. [ΔV4] genuine renumber — CONFIRMED |
| 2 | MatmultMx(95) two-bundle | generateLdweightMx @ 0x143e350: dword 0x09 @0x143e43b, mov esi,0x1009 @0x143e4cc. generateMatmultMx @ 0x143ebd0: dword 0x0A @0x143ecbb, mov esi,0x100A @0x143ed5a. | 0x1009+0x100A, always 2 bundles, V4-only — CONFIRMED |
| 3 | QuantizeMx(96) + SATURATE | visitInstQuantizeMx @ 0x143dc60: dword 0xE3 @0x143dd4b, byte 0xE3 @0x143ddd2, mov esi,0x10E3 @0x143ddea; OR-s byte[1] to 0x11 on SATURATE. | 0x10E3, the sole high-byte perturbation — CONFIRMED |
| 4 | Rng(100) / Memset(10) collision | visitInstRng @ 0x12376a0: dword 0x4D @0x1237788, byte 0x4D @0x12377fb. visitInstMemset @ 0x125b320: 0x4D (Random) @0x125b37e, 0x49 (Const) @0x125b530. | both stamp 0x4D → 0x104D collision — CONFIRMED |
| 5 | CollectiveSend(49) / Recv(50) | visitInstCollectiveSend @ 0x1272440: dword 0xCB @0x127252b, byte 0xCB @0x12725ad. visitInstCollectiveRecv @ 0x1272ab0: dword 0xCB @0x1272b9b, byte 0xCB @0x1272c1d. | byte-identical encoder bodies → 0x10CB collision — CONFIRMED |
A further pair of DVE-engine [newV3] pins (RangeSelect and NonzeroWithCount) was spot-checked the same way: RangeSelect CoreV3 @ 0x135f8c0 stamps 0xBC (0x10BC) @0x135f95f; NonzeroWithCount CoreV3 @ 0x1355a30 stamps 0xF2 (0x10F2) @0x1355b18. Both CONFIRMED, both gen3-introduced (no CoreV2 sibling).
5. Corrections
Where the re-derivation disagreed with an earlier page or table, the binary witness is recorded here in place rather than silently merged. (These are the prior opcode-map slips this appendix exists to catch.)
CORRECTION (OPC-1) —
IndirectLoad(43) /IndirectSave(45) L2 byte. Two earlier reports disagreed — one named0xC4, the other the COLLECT-witness0xD6(214) — and a prior synthesis treated this as a single shared opcode, flagging it a collision. The binary settles it:generateIndirectLoadSave@0x1268c00emits both opcodes on two mutually-exclusive branches gated by itsbool a3(isLoad) argument. The0xC4(196) path stores its COLLECT dword @0x1268f89and GENERATE bytes @0x12690cd/0x12694b8; the0xD6(214,PseudoRangeCheck) path stores its dword @0x1269576and bytes @0x1269a6c/0x1269bd3. SoIndirectLoadandIndirectSavecarry distinct wire opcodes (one0xC4, one0xD6) selected by the direction bool — not a shared0xD6collision. Both reports were right for their respective sub-instruction; the "disagreement" was an artifact of reading one merged encoder as one opcode. CONFIRMED (both immediates byte-present in the disasm). The decompile does not label which bool value maps to Load vs Save by name, so the per-direction assignment of0xC4/0xD6is left open.
CORRECTION (OPC-2) —
RangeSelect(63) emission width. The op's opcode is0x10BC(188, byte-verified), but the CoreV3 encoder may append a0x9B(DveReadAccumulator) drain word, making the practical emission two wire words. The table row carries0xBCas the op opcode and notes the0x9Bappend rather than listing two opcodes — they are one logical op with an accumulator-drain tail, not a[split]. STRONG.
CORRECTION (OPC-3) —
NonzeroWithCountIT. An earlier annotation read "bir 231" for this op; the L1 ordinal is 104 (CONFIRMED from bothInstructionType2stringand thesameInstarm).231(0xE7) isIndirectCopy's L2 opcode, not this op's IT — a cross-layer conflation. There is no231-vs-242IT split; the only relation is the normalL1(104) ≠ L2(242=0xF2)that every op has. Resolved: IT = 104, L2/L3 =0xF2/0x10F2. CONFIRMED.
CORRECTION (OPC-4) —
MatmultSparse(9) opcode. An earlier table listed0x50; the binary read ofgenerateMatMulSparse@0x135d150stamps0x07(andgenerateLoadTagsSparse@0x135e960stamps0x06). The wire bytes are0x06+0x07;0x50('P') was an ASCII-band mislabel of an adjacent/unused slot. CONFIRMED via binary.
6. Reading the table — reimplementer notes
- Vestigial / not-emitted arms. Of the 110 ITs, ~25 reach no
setupHeader: the abstract bases (MatmultBase(7),DMA(18),Collective(47),Terminator(77),DMADescriptor(68)); the lowered-away ops (Generic(0),GenericRelu(2),AbstractCopy(3),GenericCopy(1),TensorCopyDynamicSrc/Dst(24/25),GenericIndirectLoad/Save(42/44),Select(51),Loop(105),DynamicForLoop(106),DoWhile(108),DMABlock(107),TongaReduceMacroSymbolic(109)); the kernel/debug carriers (BIRKernel(54),NKIKernel(55),NKIKLIRKernel(56),DevicePrint(57),Break(83)); andRand(60) (shipped asRand2/IT97).InlineASMBytes(93) has no fixed opcode — the user's first hex byte is the opcode. - No-
sameInstarms.NKIKernel(55),NKIKLIRKernel(56), andCall(84)__assert_fail "Not Implemented"ifsameInstis called — CSE/dedup over those ops is unsupported by design. The five structured-control opcodes (105–109) also have no meaningful structural-eq (they are region/loop carriers). See §sameInst. - Per-gen reading. Read across the V2/V3/V4 columns left to right;
=carries the prior word forward. A—then a word (e.g.RangeSelect:—/0x10BC/=) marks the generation the op was introduced. The only genuine byte renumber of an existing op across generations isActivation(0x21→0x25at V4); every other V3/V4 override either keeps the opcode and only widens field bands, or is a gen-new op. - Confidence.
CONFIRMEDrows have a binary-pinned encoder (the ~85 concrete ITs).STRONGrows are transcribed from the COLLECT site without a per-byte re-read this pass (e.g.ReadVarAddr, the indirect-load/save pair pending a 3rd witness).INFERRED/HIGHrows are the lowered/abstract ITs with no encoder body — classified by the absence of avisitInst*body and asameInstarm, consistent across both libraries.
Related Components
| Component | Relationship |
|---|---|
L1 bir::InstructionType | The 110-arm IR enum (InstructionType2string @ 0x2d5bf0); the IT and Name columns here are its ordinal→name table |
L2 NEURON_ISA_TPB_OPCODE | The engine micro-op enum the COLLECT arm records; the L2 column is its low byte |
L3 setupHeader | The byte-identical 3-arch header writer; the V2/V3/V4 columns are its output words |
Generator vtable | setupHeader is reached through slot +0x48; per-engine CoreV{2,3,4}GenImpl carry the visitInst* overrides |
Cross-References
- InstructionType — the 110-opcode L1 enum, the opcode field at
+0x58, and thesameInststructural-equality masks (the source of the IT/Name columns and the[base]/family flags) - The Opcode Master —
setupHeader, the L3 wire word, and the per-op L1↔L2↔L3 reconciliation (the source of the V2/V3/V4 word columns and the INV-1..3 contract) - Instruction Bundle — the 64-byte bundle the header word leads;
inst_word_len = 0x10= 16 dwords - DVE Opcode Table — the on-device 256-slot opcode→microcode-row map the DVE sequencer indexes with the L2 opcode byte
- Build & Version Provenance — the cp310/311/312 wheel pins and the VA-drift note for cross-version address translation