Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

PSEUDO_DMABARRIER (0xC3)

This page is the reimplementer's reference for PSEUDO_DMABARRIER (opcode 0xC3) on the Vision-Q7 / Trainium TPB: the 64-byte argument struct, the single barrier_metadata field, the staggered-write SBUF race it exists to close, its lowering to a timed Nop(NUM_ROWS) in-engine stall (emphatically not a runtime wait on a DMA-done semaphore or ring tail-pointer), its absent device handler, and the one textbook CORRECTION in the trilogy — the DMABARRIER-vs-DMA_BARRIER token mismatch in instruction_mapping.json.

It is the third and final page of the barrier trilogy. The one fact to anchor the trilogy: all three are 64-byte pseudo-ops the compiler emits and the host runtime rewrites before the stream reaches a HW sequencer — but they order different things. PSEUDO_SYNC_BARRIER 0xD5 orders engines within one core; PSEUDO_CORE_BARRIER 0xD8 orders PCOREs within a VNC; PSEUDO_DMABARRIER 0xC3 orders MEMORY — one producer's staggered SBUF write against a following DMA read. It is the only member of the three that is a single-actor memory fence with no rendezvous and no event/semaphore traffic at all.

All claims are tagged [CONFIDENCE × PROVENANCE]: HIGH/MED/LOW × OBSERVED (read directly from a header / JSON / binary), INFERRED, or CARRIED (established on a sibling page). v2–v4 struct facts are byte-grounded; v5/MAVERICK is header-observed; the TONGA (v1) copy is tagged as legacy-lineage evidence wherever it is the source.

Provenance. ISA headers + instruction_mapping.json from aws-neuronx-gpsimd-customop-lib 0.21.2.0 — the Cayman = NC-v3 tree, with the 0xC3 struct compile-verified by gcc sizeof/offsetof on the real shipped headers (#include "aws_neuron_isa_tpb_pseudo_dma_barrier.h"). The struct body is diff-verified byte-identical across Cayman (v3) / Mariana (v4) / Maverick (v5) / Sunda (v2). A fifth, older TONGA (v1) ISA copy (arch-isa/tpb/aws_tonga_isa_tpb_pseudo_dma_barrier.h) is the lineage key for the naming mismatch (§6). The runtime lowering target lives in libnrtucode*.so / KRT — not present as a 0xC3 handler in any shipped binary, which is itself the finding (§5); any KRT-internal lowering rule is tagged INFERRED and flagged. No vendor source snapshot was referenced.


1 · TL;DR — what DMABARRIER is

DMABARRIER (NEURON_ISA_TPB_OPCODE_PSEUDO_DMABARRIER = 0xc3, aws_neuron_isa_tpb_common.h:265) is a 64-byte pseudo instruction. It is a memory-consistency / write-ordering fence, not a rendezvous barrier. Its header doc comment is verbatim (aws_neuron_isa_tpb_pseudo_dma_barrier.h:13-28):

//  DmaBarrier assures that writes to SBUF are completed. It is typically
//  used prior to reading the results from the SBUF through a DMA
//  transaction.  DmaBarrier is a pseudo-instruction generated by
//  compiler. It is replaced by Nop(NUM_ROWS), by KRT.
//
//  The TPB architecture uses staggered reads/writes. Thus, an
//  instruction that 'finished' writing to the SBUF (WR_DONE event) had
//  actually only finished writing to the first partition. ... a DMA
//  could read higher partition before reading partition 0, and thus
//  break the staggering synchronization. By calling this instruction
//  prior to a DmaTrigger, it is guaranteed that such a race condition
//  will not happen.

So the compiler drops a DMABARRIER before a DmaTrigger to guarantee a staggered SBUF write has fully drained across all 128 partitions before the DMA reads the SBUF. Being a pseudo-op (0xC3 = 0b1100_0011, upper three bits 0b110 ✓), it never executes as-is: KRT rewrites it to Nop(NUM_ROWS) — a timed in-engine stall (§4), not a runtime wait on a DMA-done semaphore or ring tail-pointer. [doc HIGH/OBSERVED; the timed-stall mechanism INFERRED-STRONG, §4.]

The struct carries exactly one meaningful field beyond the common header + events block: barrier_metadata (u32 @12) — annotated in the legacy TONGA header as "barrier metadata (implementation hint to runtime)" (§3). It is not a DMA-queue mask, not a completion count, not a semaphore.


2 · Struct layout — barrier_metadata @12, sizeof == 64

The struct, verbatim from aws_neuron_isa_tpb_pseudo_dma_barrier.h:32-37:

typedef struct NEURON_ISA_TPB_PSEUDO_DMA_BARRIER_STRUCT {
    NEURON_ISA_TPB_HEADER header;            // 4    ( 0 -  3)
    NEURON_ISA_TPB_EVENTS events;            // 8    ( 4 - 11)
    uint32_t              barrier_metadata;  // 4    (12 - 15)
    uint8_t               reserved0[48];     // 48   (16 - 63)
} NEURON_ISA_TPB_PSEUDO_DMA_BARRIER_STRUCT;

Compile-verified (gcc, real header #included; sizeof/offsetof):

offsizefieldC typemeaning
04headerNEURON_ISA_TPB_HEADER{opcode(1B packed enum)=0xC3, inst_word_len, debug_cmd, debug_hint}
48eventsNEURON_ISA_TPB_EVENTSinline event/sema wait+update block (§2.1); naturally NONE/NONE for this fence
124barrier_metadatauint32_topaque KRT-lowering hint ("implementation hint to runtime", TONGA) — not a queue-mask / count / semaphore (§3)
1648reserved0[48]uint8_t[48]padding to 64 B; treat as 0
64totalone 64-B TPB instruction word

[HIGH/OBSERVED — compile-verified: sizeof==64, header@0, events@4, barrier_metadata@12, reserved0@16; HEADER==4, EVENTS==8.]

INST_UNION binding (aws_neuron_isa_tpb_util.h:40): NEURON_ISA_TPB_PSEUDO_DMA_BARRIER_STRUCT pseudo_dma_barrier; [HIGH/OBSERVED]

Mapping JSON (instruction_mapping.json:108-109): "NEURON_ISA_TPB_PSEUDO_DMA_BARRIER_STRUCT" → ["NEURON_ISA_TPB_OPCODE_PSEUDO_DMA_BARRIER"] — note the with-underscore opcode token; that token is the dangling reference of §6. [HIGH/OBSERVED]

Classifier membership. 0xC3 is a member of is_pseudo_op (aws_neuron_isa_tpb_instr_assert.h:594, clause at :597 — sitting in the DMA-pseudo cluster DMATRIGGER:595 / DMAREARM:596 / DMABARRIER:597 / DMAMEMCPY_FULL_IND:598) and of is_control_instruction (:1143, clause at :1159). It is in is_valid_enum_opcode (aws_neuron_isa_tpb_enums.h:307, spelled …DMABARRIER) — a valid TPB opcode — and is not a member of the unrelated tiny is_valid_enum_pseudo_opcode set {INVALID, PSEUDO_EXIT_EXECUTION, PSEUDO_LIBRARY_RELOAD_INDEX} (:352-355). All references use the no-underscore spelling. [HIGH/OBSERVED]

GOTCHA — no static validator body. aws_neuron_isa_tpb_assert.h:12654 carries only the empty section marker //* pseudo_dma_barrier_assert.h, immediately followed by the next marker //* pseudo_dma_direct2d_assert.h at :12657 — there is no is_valid_pseudo_dma_barrier body. Same pattern as CORE_BARRIER (:12648) and SYNC_BARRIER. The pseudo-op is validated and lowered by the runtime, not by the static assert layer. Do not look for a field-range checker in the headers — there isn't one. (The legacy TONGA header did ship one; the modern ISA dropped it, §6.) [HIGH/OBSERVED]

QUIRK — byte-identical across arches. Diffing the four modern copies, the struct body is identical on Cayman (v3) / Mariana (v4) / Maverick (v5) / Sunda (v2); the only difference is the ISA header for NC-vN banner comment (diff of cayman vs mariana shows NC-v3NC-v4 on line 3, nothing else). The opcode 0xC3, the JSON binding, and the union member are identical on all four. [HIGH/OBSERVED — Maverick interior INFERRED from the header read, not a v5 binary.]

2.1 · Base field types — HEADER (4 B) + EVENTS (8 B)

From aws_neuron_isa_tpb_common.h:411-424:

typedef struct NEURON_ISA_TPB_HEADER {        // sizeof == 4
    NEURON_ISA_TPB_OPCODE opcode;             // 1 (packed enum) -> 0xC3
    uint8_t               inst_word_len;
    uint8_t               debug_cmd;
    uint8_t               debug_hint;
} NEURON_ISA_TPB_HEADER;

typedef struct NEURON_ISA_TPB_EVENTS {        // sizeof == 8
    NEURON_ISA_TPB_WAIT_MODE   wait_mode;     // +0  1B packed
    uint8_t                    wait_idx;      // +1
    NEURON_ISA_TPB_UPDATE_MODE update_mode;   // +2  1B packed
    uint8_t                    update_idx;    // +3
    uint32_t                   semaphore_value;// +4  4B
} NEURON_ISA_TPB_EVENTS;

DMABARRIER carries the 8-byte events block (every TPB instruction does), but as a pure write-ordering fence it needs no rendezvous: its lowered form (a NOP) performs no event/semaphore arrive/wait of its own, so the block is most naturally wait_mode = WAIT_MODE_NONE (0x0), update_mode = UPDATE_MODE_NONE (0x0) (common.h:314,348; the header even ships a commented Events::default() with both None, :428). Contrast CORE (uses the events semaphore family) and SYNC (uses the events event family); DMABARRIER uses neither — the ordering is the timed NOP, not an event. [events-block PRESENCE + NONE enum values OBSERVED HIGH; "NONE/NONE for the fence" INFERRED-MED — no captured stream pins the modes, but the "replaced by Nop" lowering needs no rendezvous.]


3 · The barrier_metadata field — what it is, and what it is not

barrier_metadata is a u32 at offset 12 — exactly where CORE puts id and where SYNC's first reserved byte begins. The modern Cayman header gives it no annotation; its meaning is pinned by the legacy TONGA header, which ships the same field with an inline comment (aws_tonga_isa_tpb_pseudo_dma_barrier.h:22):

uint32_t barrier_metadata; /* barrier metadata (implementation hint to runtime) */

So barrier_metadata is an opaque implementation hint consumed by KRT during lowering. The field type/width (a bare u32), the TONGA annotation, and the absence of any mask/count semantics in either header together make it decisively NOT: [HIGH/OBSERVED]

  • Not a DMA-queue bitmask. There is no queue enumeration; the DMA queue is named by the separate DmaTrigger's int8_t dma_queue_name[32] (aws_neuron_isa_tpb_pseudo_dma_trigger.h:31). DMABARRIER carries no queue reference at all.
  • Not a completion / descriptor count. That lives in DmaTrigger's count_union {block_id | count} (:24,33), not here.
  • Not a semaphore handle. That is CORE's semaphore u32@16 plus the events semaphore_value; DMABARRIER references no semaphore.

NOTE — most plausible concrete meaning: the NUM_ROWS hint. The doc says DMABARRIER "is replaced by Nop(NUM_ROWS)"; the NOP it lowers to carries cycle_cnt (u32) also at offset 12 (§4); and STATE_BUF_NUM_PARTITIONS = PE_ARRAY_NUM_ROWS = 128U (common.h:39,29). barrier_metadata is the natural carrier for that row/partition count, and a straight barrier_metadata → cycle_cnt copy at lowering is a same-offset, same-width u32→u32 move. [field + TONGA "runtime hint" annotation OBSERVED HIGH; the "= NUM_ROWS → cycle_cnt" identification INFERRED-MED — the offsets and the "Nop(NUM_ROWS)" doc align, but no shipped artifact states the literal copy rule; KRT is not in this extraction.] See the row-count discussion under Move / dtype gate and the SBUF row geometry in SBUF / PSUM Banks.


4 · The DMA-ordering mechanism — the staggered-write race + Nop(NUM_ROWS)

The hazard (verbatim doc)

The TPB SBUF is a 128-partition (row) banked memory — 16 SBUF ECC banks, 128 partitions × a 256 KiB per-partition stride on NC-v3, per SBUF / PSUM Banks (STATE_BUF_NUM_PARTITIONS = 128, common.h:39). Writes and reads to/from the SBUF are staggered across partitions: an engine that asserts its WR_DONE event has actually only finished writing partition 0 — the higher partitions are still draining down the pipeline. On-chip data-consistency is preserved because the SBUF reads are staggered the same way: a consumer engine reading partition k arrives at k only after the producer wrote k. That same-direction producer/consumer staggering is an implicit pipeline ordering — it needs no explicit fence between two TPB engines. [doc OBSERVED HIGH; the 128-partition count CARRIED from SBUF / PSUM Banks.]

The break (verbatim doc)

A DMA does not honor the staggering. A DMA engine reading the SBUF can read a high partition before partition 0. So a DMA launched right after a WR_DONE could read partition k before the producer's staggered write reached k — a producer-vs-DMA-consumer data race: the DMA captures stale data in the not-yet-drained high partitions. [OBSERVED HIGH.]

The fence and its realisation

DMABARRIER, emitted by the compiler before the DmaTrigger, closes the race by stalling the producing engine long enough that the staggered write has drained to the last partition before the DMA's tail-pointer write fires. KRT realises that stall as a timed NOP (OPCODE_NOP = 0xa4, struct CTRL_NO_STRUCT; instruction_mapping.json:30-37 maps CTRL_NO to {ACTIVATION_TABLE_LOAD, NOP, HALT, DRAIN, INSTRUCTION_FLUSH, NOTIFY}).

The decisive evidence that NOP is a timed stall — and the one CTRL_NO variant permitted a nonzero cycle_cnt — is a validity asymmetry in the commented assert functions of aws_neuron_isa_tpb_ctrl_no.h:

// CTRL_NO struct (ctrl_no.h:36-46) -- cycle_cnt is u32 @12, the SAME offset as
//                                     DMABARRIER's barrier_metadata:
//   NEURON_ISA_TPB_HEADER header;     // 0-3
//   NEURON_ISA_TPB_EVENTS events;     // 4-11
//   uint32_t              cycle_cnt;  // 12-15   <-- the timed-stall count

// is_valid_nop(i)  (ctrl_no.h:73-80)  -- OMITS the cycle-zero constraint:
//    has_valid_neuron_header && has_valid_neuron_events && has_opcode_nop
//    && notify_fields_zero && zero_act_tbl_sel && ctrl_no_reserved_zero
//    // NOTE: NO  cycle_count_field_zero(i)

// every OTHER CTRL_NO variant REQUIRES cycle_count_field_zero(i)  (== cycle_cnt 0):
//    is_valid_acttableld :67   is_valid_halt :88   is_valid_drain :98
//    is_valid_iflush    :110   is_valid_notify :120
// cycle_count_field_zero(i) := (i.ctrl_no.cycle_cnt == 0)   (ctrl_no.h:162-164)

NOP is therefore the only CTRL_NO opcode allowed to carry a nonzero cycle_cnt — it idles the engine for cycle_cnt cycles. Nop(NUM_ROWS) is a NOP with cycle_cnt = NUM_ROWS = 128 — exactly the number of staggered-pipeline steps for the last partition's write to land. The producing engine is held for NUM_ROWS cycles, after which every partition's write is complete, and the following DmaTrigger (a Write to the DMA-queue tail pointer, aws_neuron_isa_tpb_pseudo_dma_trigger.h:15-16: "initiates a DMA data-transfer, by writing to the DMA tail pointer … replaced by Write, by KRT") can safely launch the read. [CTRL_NO cycle_cnt@12 + the is_valid_nop omission are OBSERVED HIGH; DMABARRIER → NOP(cycle_cnt=NUM_ROWS) is INFERRED-STRONG from the verbatim "replaced by Nop(NUM_ROWS)" doc + the matching offset-12 u32 fields.]

The KRT lowering, in pseudocode (the rewrite is INFERRED-STRONG; the offsets/types are OBSERVED):

// KRT pre-issue rewrite of a PSEUDO_DMABARRIER (0xC3) into a timed CTRL_NO NOP (0xa4).
// barrier_metadata and cycle_cnt are BOTH u32 @ offset 12 -> a same-offset u32 copy.
NEURON_ISA_TPB_CTRL_NO_STRUCT
lower_dmabarrier(const NEURON_ISA_TPB_PSEUDO_DMA_BARRIER_STRUCT *db) {
    NEURON_ISA_TPB_CTRL_NO_STRUCT nop = {0};
    nop.header.opcode = NEURON_ISA_TPB_OPCODE_NOP;             // 0xa4  (was 0xC3)
    nop.events        = db->events;                            // carry the (NONE/NONE) events block
    nop.cycle_cnt     = db->barrier_metadata                   // the NUM_ROWS hint, if encoded there ...
                      ? db->barrier_metadata
                      : NEURON_ISA_TPB_STATE_BUF_NUM_PARTITIONS;// ... else 128 (== PE_ARRAY_NUM_ROWS)
    // is_valid_nop permits cycle_cnt != 0 (it omits cycle_count_field_zero);
    // every other CTRL_NO variant would REJECT this instruction.
    return nop;
}

What it does not do (the distinction from a DMA-completion barrier)

DMABARRIER does not wait on the SDMA completion ring, does not poll the RDM tail-pointer, does not wait on a DMA-done semaphore. It is a producer-side, pre-DMA, fixed-duration stall that orders the SBUF write (which the producer just issued) ahead of the DMA read (which the next DmaTrigger will issue). It fences the write → read-by-DMA hazard, not DMA completion — those are a separate mechanism (the SDMA M2S/S2M descriptor-done semaphores and the DmaTrigger's own events block). [INFERRED-STRONG — the lowering target is a plain timed NOP with no event/semaphore wait of its own; the doc frames it as a pre-write drain, not a post-DMA wait.]

NOTE — the use-case. A kernel/collective computes a result into the SBUF (a staggered engine write), then must ship it out via a DMA read (e.g. compute → SBUF → DmaTrigger → RDMA descriptor → peer). Between the compute's WR_DONE and the DmaTrigger, the compiler inserts DMABARRIER so the DMA cannot read stale high-partition data: "typically used prior to reading the results from the SBUF through a DMA transaction" (verbatim). [doc OBSERVED; the SB2SB instance INFERRED-MED.]


5 · Device handling — no 0xC3 arm (pre-lowered to NOP)

There is no dedicated firmware handler for opcode 0xC3 — the correct, expected finding for a pseudo-op, exactly mirroring CORE 0xD8 and SYNC 0xD5:

  1. 0xC3 is a pseudo opcode (§2). The header states the rule verbatim (common.h:263): "NRT relies on the fact that all pseudo instructions have upper three bits of the opcode equal to 0b110. Pseudo instructions are generated by compiler and translated into non-pseudo HW instructions by NRT." So the device sequencers never see 0xC3; they see the lowered NOP (0xa4 / CTRL_NO). [OBSERVED that 0xC3 is pseudo; INFERRED that this is why there is no 0xC3 arm.]
  2. Exhaustive absence check. DMABARRIER / DMA_BARRIER / DmaBarrier strings appear only in the five ISA header packages (4 modern + 1 TONGA) and their instruction_mapping.json. A strings | rg -c over the runtime ucode binaries libnrtucode.so, libnrtucode_internal.so, and libnrtucode.a returns 0 hits each; an rg -l over all of extracted/ finds zero non-.h/non-.json occurrences. [HIGH/OBSERVED — exhaustive rg / strings over extracted/.]
  3. The actual device-side execution is a plain NOP idling the engine for cycle_cnt cycles (§4) — no semaphore/event traffic, no DMA-ring interaction. The "device handler" for DMABARRIER is the engine's NOP timed-stall path, nothing more. [NOP-with-cycle_cnt OBSERVED in ctrl_no.h; DMABARRIER→it INFERRED-STRONG, §4.]

Unlike CORE and SYNC (which lower to the EVENT_SEMAPHORE 0xA0 HW path over tpb_semaphores / tpb_events), DMABARRIER lowers to NOP (0xa4) — no event/semaphore HW path at all. This is the cleanest expression of "DMA orders MEMORY, not engines/cores": the fence is a time delay, not a rendezvous on the event-semaphore array.


6 · CORRECTION — the DMABARRIER-vs-DMA_BARRIER token mismatch, resolved

CORRECTION. An early pass flagged a DMABARRIER/DMA_BARRIER naming inconsistency and left open whether two opcodes or a struct/opcode confusion was involved. Resolved: it is one opcode (0xC3, value 195). The instruction_mapping.json opcode token …OPCODE_PSEUDO_DMA_BARRIER (with underscore) is a dangling reference — a stale TONGA-era underscore token left behind by the TONGA→Neuron no-underscore rename of the DMA-pseudo family. No current Neuron enum constant resolves it. [HIGH/OBSERVED — grepped both directions; lineage OBSERVED in the TONGA copy.]

Byte-exact inventory of every spelling:

sitespellingunderscore?
enum const (common.h:265)OPCODE_PSEUDO_DMABARRIER = 0xc3no
is_valid_enum_opcode (enums.h:307)OPCODE_PSEUDO_DMABARRIERno
is_pseudo_op (instr_assert.h:597)OPCODE_PSEUDO_DMABARRIERno
is_control_instruction (:1159)OPCODE_PSEUDO_DMABARRIERno
disasm name (enums.h:2064-2065)"PseudoDMABarrier" for value == 195n/a (CamelCase)
struct typedefPSEUDO_DMA_BARRIER_STRUCTyes
union member (util.h:40)pseudo_dma_barrieryes
mapping JSON key (:108)PSEUDO_DMA_BARRIER_STRUCTyes
mapping JSON opcode (:109)OPCODE_PSEUDO_DMA_BARRIERyes ← DANGLING
— TONGA (v1) enumOPCODE_PSEUDO_DMA_BARRIER = 0x03|(RT<<5) = 0xc3yes (legacy)
— TONGA (v1) structTONGA…PSEUDO_DMA_BARRIER_INSTyes (legacy)
— TONGA (v1) validity-checkchecks == …OPCODE_PSEUDO_DMA_BARRIERyes (legacy)

Two consistent spelling clusters, one stray token:

  • The opcode enum constant in the modern Neuron ISA is the no-underscore OPCODE_PSEUDO_DMABARRIER (= 0xc3). This matches the entire modern DMA-pseudo cluster's convention — DMATRIGGER:263 / DMAREARM:264 / DMABARRIER:265 / DMAMEMCPY_FULL_IND:266 are all collapsed to no-underscore — and every static classifier uses that form. [HIGH/OBSERVED]
  • The struct / union-member / mapping-key use the with-underscore PSEUDO_DMA_BARRIER form; these three are internally consistent. [HIGH/OBSERVED]
  • The anomaly is exactly one token: the mapping JSON's opcode binding OPCODE_PSEUDO_DMA_BARRIER (with underscore) names an enum constant that exists in no modern Neuron header — the only modern enum constant is the no-underscore …DMABARRIER. Grep-verified both directions: OPCODE_PSEUDO_DMA_BARRIER (underscore) is absent from all modern *.h headers; OPCODE_PSEUDO_DMABARRIER (no underscore) is absent from instruction_mapping.json. [HIGH/OBSERVED]

GOTCHA — CORE/SYNC are clean; only DMABARRIER dangles. The CORE and SYNC JSON opcode tokens (OPCODE_PSEUDO_CORE_BARRIER :103, OPCODE_PSEUDO_SYNC_BARRIER :176) do appear in common.h (:286, :283) — they resolve. Only DMABARRIER has the split. [HIGH/OBSERVED — rg -c of each token in headers vs JSON.]

The lineage / resolution

The repo ships an older TONGA (v1) ISA whose DMA-barrier enum constant is the with-underscore TONGA_ISA_TPB_OPCODE_PSEUDO_DMA_BARRIER, computed (aws_tonga_isa_tpb_common.h:117, with ENGINE_RT = 0x6, :45):

TONGA_ISA_TPB_ENGINE_RT = 0x6,   /* instructions that are patched by the runtime */
...
TONGA_ISA_TPB_OPCODE_PSEUDO_DMA_BARRIER = 0x03 | (TONGA_ISA_TPB_ENGINE_RT << 5);
//                                      = 0x03 | (0x6 << 5) = 0x03 | 0xC0 = 0xC3 = 195

The TONGA ENGINE_RT = 0b110 is the modern "upper-three-bits-0b110 pseudo" rule; TONGA's engine-scoped byte = local | (ENGINE<<5) form is documented on the Cross-Gen Opcode Diff page. When the ISA migrated TONGA→Neuron, the DMA-pseudo family's enum constants were renamed to the no-underscore convention (DMABARRIER), but instruction_mapping.json kept the old underscore opcode token. The mismatch is a stale token carried over from the TONGA naming — a cosmetic mapping artifact, not two opcodes and not a struct/opcode confusion. [the TONGA underscore opcode + its 0xC3 value OBSERVED HIGH (legacy); the "migration left a stale token" reading INFERRED-STRONG — the underscore form exists ONLY in the TONGA enum and the modern JSON, nowhere else.]

Are they the same opcode? Yes — unambiguously. One numeric value (0xC3 = 195) is involved everywhere: the modern enum constant = 0xc3; the TONGA 0x03|(RT<<5) = 0xc3; and the disasm pretty-printer keys on value == 195 → "PseudoDMABarrier" (enums.h:2064-2065, with 194 → "PseudoDMARearm" / 196 → "PseudoDMAMemcpyFullInd" bracketing it — i.e. 0xc2/0xc3/0xc4). The runtime decoder dispatches on the numeric value, which is unaffected by the C-token spelling. There is no second DMA-barrier opcode anywhere.

NOTE — practical impact. A tool that consumes instruction_mapping.json by resolving the opcode token string against the C enum would fail to resolve DMABARRIER's binding (dangling token) — whereas CORE/SYNC resolve cleanly. A tool keyed on the numeric 0xC3 is unaffected. This is a latent mapping-bug surface, cosmetic for value-based decoders, a resolve-failure for token-based ones. [INFERRED-MED — the dangling token is OBSERVED; the tool-impact is its consequence.]

(A secondary, purely presentational inconsistency: the doc comment and disasm spell it DmaBarrier / PseudoDMABarrier in CamelCase; TONGA's doc spells it DmaBarrier too. No token resolution is involved.)


7 · The trilogy — within-trilogy distinction

All three barriers are 64-B pseudo-ops carrying the common 4-B header + the 8-B events block; they differ in their barrier-specific payload (always at offset 12), their lowering target, and their scope. Field inventories compile-verified from the headers directly (all sizeof == 64):

opcodepseudo-opoffset-12 payloadlowers toscope / nature
0xD5PSEUDO_SYNC_BARRIER(none — events-only) + reserved0[52]EVENT_SEMA 0xA0ENGINE rendezvous within a core (1-bit EVENTS)
0xD8PSEUDO_CORE_BARRIERid u32@12 + semaphore u32@16 + reserved1[44]EVENT_SEMA 0xA0PCORE rendezvous within a VNC (32-bit SEMA)
0xC3PSEUDO_DMABARRIERbarrier_metadata u32@12 + reserved0[48]NOP 0xa4 (timed stall)SBUF write-ordering MEMORY fence (no rendezvous)

[all three structs read directly: sync-barrier.h:25-29, core-barrier.h:19-25, dma_barrier.h:32-37; all sizeof==64 compile-verified.]

The offset-12 story is a clean structural mnemonic. All three put their distinguishing payload at offset 12, where SYNC has nothing:

SYNC @12 : reserved[52]              (events-only -- no payload)
CORE @12 : id (u32) + semaphore @16  (a rendezvous identity + 32-bit handle)
DMA  @12 : barrier_metadata (u32)    (a lowering hint -> NOP cycle_cnt)

SYNC.reserved0[52] = CORE.reserved1[44] + 8 (id+sema); DMA.reserved0[48] sits between (CORE minus its 4-B semaphore, since DMA carries metadata only) — and all three sum to 64.

The decisive boundary:

  • 0xD5 SYNC — orders ENGINES within one core; a rendezvous on EVENTS (1-bit flags); lowers to EVENT_SEMAPHORE.
  • 0xD8 CORE — orders PCOREs of a VNC; a counted rendezvous on 32-bit SEMAPHORES (INC/GE/DEC); lowers to EVENT_SEMAPHORE.
  • 0xC3 DMA — orders MEMORY (an SBUF write vs a DMA read), not engines, not cores, not a rendezvous; synchronizes one producer's staggered WRITE against a DMA READ via a timed NOP stall; the only member with no event/semaphore traffic.

The first two are multi-actor rendezvous (someone arrives, someone waits); the third is a single-actor memory fence (a producer stalls itself so its write lands before a DMA read). DMA is orthogonal to the rendezvous axis — it is the only one of the three that orders DATA rather than CONTROL. [scopes + lowering targets OBSERVED in the respective doc comments + mapping; the "control-rendezvous vs memory-fence" axis is the architectural reading, INFERRED-STRONG.]

The naming anomaly of §6 is unique to DMABARRIER; CORE and SYNC resolve cleanly.


8 · Error / timeout — there is none

The modern DMABARRIER path has no timeout, no error field, no validator: [HIGH/OBSERVED]

  • The struct carries only header / events / barrier_metadata / reserved0 — no timeout, no error-code (compile-verify + header read, §2).
  • There is no is_valid_pseudo_dma_barrier body (empty section marker, §2).

GOTCHA — the TONGA validity-check the modern ISA dropped. The legacy TONGA header shipped tonga_isa_tpb_dma_barrier_check_validity (aws_tonga_isa_tpb_pseudo_dma_barrier.h:32-58): it verifies opcode == OPCODE_PSEUDO_DMA_BARRIER, inst_word_len == INST_NWORDS (16), and the events modes, and is paired with STATIC_ASSERT(sizeof == INST_NBYTES (64)) (:26). The modern Neuron ISA dropped the function, consistent with CORE/SYNC being runtime-validated. Note also the TONGA events block is 4 B (no semaphore_value, :229-235), so TONGA reserved[52] vs modern reserved0[48] — both → 64. [HIGH/OBSERVED (legacy).]

Consequence: a DMABARRIER cannot "fail" or "time out" — its lowered NOP is a fixed cycle_cnt stall that always completes. There is no wait-on-an-external-event semantics, so no deadlock/timeout failure mode — unlike CORE/SYNC, whose unconditional GE/EVT spins can hang if a participant never arrives. DMABARRIER's correctness is a compile-time guarantee: the compiler must size the stall (NUM_ROWS) to cover the worst-case staggered drain and place the barrier before every hazardous DmaTrigger. [the absence of timeout/error OBSERVED HIGH; the "cannot hang, always completes" consequence INFERRED-STRONG from the timed-NOP lowering having no external wait.]


9 · Confidence ledger

HIGH / OBSERVED (compile-verified layout / verbatim header text / grepped byte-exact):

  • Struct: header(0-3) + events(4-11) + barrier_metadata u32(12-15) + reserved0[48](16-63); sizeof == 64 (compile-verified); HEADER == 4, EVENTS == 8.
  • Opcode 0xC3 = 0b1100_0011 (pseudo, upper-3-bits 0b110); DMA-pseudo cluster 0xC1 DMATRIGGER / 0xC2 DMAREARM / 0xC3 DMABARRIER / 0xC4 DMAMEMCPY_FULL_IND (common.h:263-266).
  • Verbatim doc (SBUF staggered-write fence; WR_DONE = partition-0-only; DMA can read high partition first; "replaced by Nop(NUM_ROWS), by KRT"; "prior to a DmaTrigger … race condition will not happen").
  • Struct body byte-identical on cayman/mariana/maverick/sunda (diff-verified — only the NC-vN banner differs).
  • INST_UNION member pseudo_dma_barrier (util.h:40); member of is_pseudo_op (instr_assert.h:597), is_control_instruction (:1159), is_valid_enum_opcode (enums.h:307); not of is_valid_enum_pseudo_opcode.
  • No dma_barrier assert body (empty marker, assert.h:12654).
  • Naming inventory (§6): enum/classifier = no-underscore DMABARRIER; struct/member/JSON-key = underscore DMA_BARRIER; JSON opcode token = underscore OPCODE_PSEUDO_DMA_BARRIER (DANGLING — absent from headers); disasm value 195 → "PseudoDMABarrier". CORE/SYNC clean.
  • TONGA (v1, legacy): OPCODE_PSEUDO_DMA_BARRIER = 0x03|(ENGINE_RT=0x6<<5) = 0xC3; barrier_metadata annotated "(implementation hint to runtime)"; ships a validity-check the modern header dropped; TONGA events = 4 B → reserved[52].
  • NOP target: OPCODE_NOP = 0xa4 → CTRL_NO_STRUCT; cycle_cnt u32 @12; is_valid_nop OMITS cycle_count_field_zero (HALT/DRAIN/IFLUSH/NOTIFY/ACTTABLELD all require it).
  • DmaTrigger (0xC1): "writes to the DMA tail pointer … replaced by Write, by KRT"; dma_queue_name[32]; count_union {block_id|count}.
  • STATE_BUF_NUM_PARTITIONS = PE_ARRAY_NUM_ROWS = 128 (common.h:39,29).
  • No 0xC3 device arm; DMABARRIER absent from every runtime binary (0 hits in libnrtucode*.so/.a).

MED / INFERRED-STRONG (multiple OBSERVED facts converge; flagged):

  • barrier_metadata = NUM_ROWS hint copied to the lowered NOP's cycle_cnt (both u32 @12; doc says Nop(NUM_ROWS); TONGA annotates it a runtime hint).
  • DMABARRIER lowers to NOP(cycle_cnt = NUM_ROWS = 128) — a timed in-engine stall.
  • Producer-side pre-DMA fence; does not wait on the SDMA ring / RDM tail / a DMA-done semaphore.
  • No 0xC3 device arm because pseudo-ops are pre-lowered (mirrors CORE/SYNC).
  • The DMABARRIER-vs-DMA_BARRIER mismatch is a stale TONGA-era underscore token in the JSON; same single 0xC3 opcode (195); value-based decoders unaffected.
  • Events block most naturally NONE/NONE.
  • Cannot hang / cannot time out (fixed-cycle NOP); correctness is a compile-time guarantee.

LOW / NOTED:

  • The exact KRT lowering (the literal barrier_metadata → cycle_cnt rule; the precise NUM_ROWS per kernel) is not in the shipped headers — it lives in KRT/NRT, absent from this extraction.
  • The 128-partition row count is CARRIED from SBUF / PSUM Banks (the systolic 128-wide PE array); the NUM_ROWS == 128 identity inherits that.
  • Whether barrier_metadata ever carries anything other than NUM_ROWS is not pinned — the TONGA annotation says only "implementation hint to runtime"; NUM_ROWS is the most plausible, not the only, reading.