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.jsonfromaws-neuronx-gpsimd-customop-lib 0.21.2.0— the Cayman = NC-v3 tree, with the0xC3struct compile-verified bygcc sizeof/offsetofon 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 inlibnrtucode*.so/ KRT — not present as a0xC3handler in any shipped binary, which is itself the finding (§5); any KRT-internal lowering rule is taggedINFERREDand 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):
| off | size | field | C type | meaning |
|---|---|---|---|---|
| 0 | 4 | header | NEURON_ISA_TPB_HEADER | {opcode(1B packed enum)=0xC3, inst_word_len, debug_cmd, debug_hint} |
| 4 | 8 | events | NEURON_ISA_TPB_EVENTS | inline event/sema wait+update block (§2.1); naturally NONE/NONE for this fence |
| 12 | 4 | barrier_metadata | uint32_t | opaque KRT-lowering hint ("implementation hint to runtime", TONGA) — not a queue-mask / count / semaphore (§3) |
| 16 | 48 | reserved0[48] | uint8_t[48] | padding to 64 B; treat as 0 |
| 64 | total | one 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:12654carries only the empty section marker//* pseudo_dma_barrier_assert.h, immediately followed by the next marker//* pseudo_dma_direct2d_assert.hat:12657— there is nois_valid_pseudo_dma_barrierbody. Same pattern asCORE_BARRIER(:12648) andSYNC_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-vNbanner comment (diffof cayman vs mariana showsNC-v3↔NC-v4on line 3, nothing else). The opcode0xC3, 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'sint8_t dma_queue_name[32](aws_neuron_isa_tpb_pseudo_dma_trigger.h:31).DMABARRIERcarries no queue reference at all. - Not a completion / descriptor count. That lives in
DmaTrigger'scount_union {block_id | count}(:24,33), not here. - Not a semaphore handle. That is
CORE'ssemaphoreu32@16plus the eventssemaphore_value;DMABARRIERreferences no semaphore.
NOTE — most plausible concrete meaning: the
NUM_ROWShint. The doc saysDMABARRIER"is replaced byNop(NUM_ROWS)"; theNOPit lowers to carriescycle_cnt(u32) also at offset 12 (§4); andSTATE_BUF_NUM_PARTITIONS = PE_ARRAY_NUM_ROWS = 128U(common.h:39,29).barrier_metadatais the natural carrier for that row/partition count, and a straightbarrier_metadata → cycle_cntcopy at lowering is a same-offset, same-widthu32→u32move.[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'sWR_DONEand theDmaTrigger, the compiler insertsDMABARRIERso 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:
0xC3is 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 to0b110. Pseudo instructions are generated by compiler and translated into non-pseudo HW instructions by NRT." So the device sequencers never see0xC3; they see the loweredNOP(0xa4/CTRL_NO).[OBSERVED that 0xC3 is pseudo; INFERRED that this is why there is no 0xC3 arm.]- Exhaustive absence check.
DMABARRIER/DMA_BARRIER/DmaBarrierstrings appear only in the five ISA header packages (4 modern + 1 TONGA) and theirinstruction_mapping.json. Astrings | rg -cover the runtime ucode binarieslibnrtucode.so,libnrtucode_internal.so, andlibnrtucode.areturns 0 hits each; anrg -lover all ofextracted/finds zero non-.h/non-.jsonoccurrences.[HIGH/OBSERVED — exhaustive rg / strings over extracted/.] - The actual device-side execution is a plain
NOPidling the engine forcycle_cntcycles (§4) — no semaphore/event traffic, no DMA-ring interaction. The "device handler" forDMABARRIERis 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_BARRIERnaming inconsistency and left open whether two opcodes or a struct/opcode confusion was involved. Resolved: it is one opcode (0xC3, value 195). Theinstruction_mapping.jsonopcode 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:
| site | spelling | underscore? |
|---|---|---|
enum const (common.h:265) | OPCODE_PSEUDO_DMABARRIER = 0xc3 | no |
is_valid_enum_opcode (enums.h:307) | OPCODE_PSEUDO_DMABARRIER | no |
is_pseudo_op (instr_assert.h:597) | OPCODE_PSEUDO_DMABARRIER | no |
is_control_instruction (:1159) | OPCODE_PSEUDO_DMABARRIER | no |
disasm name (enums.h:2064-2065) | "PseudoDMABarrier" for value == 195 | n/a (CamelCase) |
| struct typedef | PSEUDO_DMA_BARRIER_STRUCT | yes |
union member (util.h:40) | pseudo_dma_barrier | yes |
mapping JSON key (:108) | PSEUDO_DMA_BARRIER_STRUCT | yes |
mapping JSON opcode (:109) | OPCODE_PSEUDO_DMA_BARRIER | yes ← DANGLING |
| — TONGA (v1) enum | OPCODE_PSEUDO_DMA_BARRIER = 0x03|(RT<<5) = 0xc3 | yes (legacy) |
| — TONGA (v1) struct | TONGA…PSEUDO_DMA_BARRIER_INST | yes (legacy) |
| — TONGA (v1) validity-check | checks == …OPCODE_PSEUDO_DMA_BARRIER | yes (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:266are 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_BARRIERform; 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*.hheaders;OPCODE_PSEUDO_DMABARRIER(no underscore) is absent frominstruction_mapping.json.[HIGH/OBSERVED]
GOTCHA —
CORE/SYNCare clean; onlyDMABARRIERdangles. TheCOREandSYNCJSON opcode tokens (OPCODE_PSEUDO_CORE_BARRIER:103,OPCODE_PSEUDO_SYNC_BARRIER:176) do appear incommon.h(:286,:283) — they resolve. OnlyDMABARRIERhas the split.[HIGH/OBSERVED —rg -cof 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.jsonby resolving the opcode token string against the C enum would fail to resolveDMABARRIER's binding (dangling token) — whereasCORE/SYNCresolve cleanly. A tool keyed on the numeric0xC3is 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):
| opcode | pseudo-op | offset-12 payload | lowers to | scope / nature |
|---|---|---|---|---|
0xD5 | PSEUDO_SYNC_BARRIER | (none — events-only) + reserved0[52] | EVENT_SEMA 0xA0 | ENGINE rendezvous within a core (1-bit EVENTS) |
0xD8 | PSEUDO_CORE_BARRIER | id u32@12 + semaphore u32@16 + reserved1[44] | EVENT_SEMA 0xA0 | PCORE rendezvous within a VNC (32-bit SEMA) |
0xC3 | PSEUDO_DMABARRIER | barrier_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:
0xD5SYNC — orders ENGINES within one core; a rendezvous on EVENTS (1-bit flags); lowers toEVENT_SEMAPHORE.0xD8CORE — orders PCOREs of a VNC; a counted rendezvous on 32-bit SEMAPHORES (INC/GE/DEC); lowers toEVENT_SEMAPHORE.0xC3DMA — 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 timedNOPstall; 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_barrierbody (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 verifiesopcode == OPCODE_PSEUDO_DMA_BARRIER,inst_word_len == INST_NWORDS (16), and the events modes, and is paired withSTATIC_ASSERT(sizeof == INST_NBYTES (64))(:26). The modern Neuron ISA dropped the function, consistent withCORE/SYNCbeing runtime-validated. Note also the TONGA events block is 4 B (nosemaphore_value,:229-235), so TONGAreserved[52]vs modernreserved0[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-bits0b110); DMA-pseudo cluster0xC1 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-vNbanner differs). INST_UNIONmemberpseudo_dma_barrier(util.h:40); member ofis_pseudo_op(instr_assert.h:597),is_control_instruction(:1159),is_valid_enum_opcode(enums.h:307); not ofis_valid_enum_pseudo_opcode.- No
dma_barrierassert body (empty marker,assert.h:12654). - Naming inventory (§6): enum/classifier = no-underscore
DMABARRIER; struct/member/JSON-key = underscoreDMA_BARRIER; JSON opcode token = underscoreOPCODE_PSEUDO_DMA_BARRIER(DANGLING — absent from headers); disasmvalue 195 → "PseudoDMABarrier".CORE/SYNCclean. - TONGA (v1, legacy):
OPCODE_PSEUDO_DMA_BARRIER = 0x03|(ENGINE_RT=0x6<<5) = 0xC3;barrier_metadataannotated "(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_nopOMITScycle_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
0xC3device arm;DMABARRIERabsent from every runtime binary (0 hits inlibnrtucode*.so/.a).
MED / INFERRED-STRONG (multiple OBSERVED facts converge; flagged):
barrier_metadata = NUM_ROWShint copied to the lowered NOP'scycle_cnt(bothu32 @12; doc saysNop(NUM_ROWS); TONGA annotates it a runtime hint).DMABARRIERlowers toNOP(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
0xC3device arm because pseudo-ops are pre-lowered (mirrors CORE/SYNC). - The
DMABARRIER-vs-DMA_BARRIERmismatch is a stale TONGA-era underscore token in the JSON; same single0xC3opcode (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_cntrule; the preciseNUM_ROWSper 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 == 128identity inherits that. - Whether
barrier_metadataever carries anything other thanNUM_ROWSis not pinned — the TONGA annotation says only "implementation hint to runtime";NUM_ROWSis the most plausible, not the only, reading.