The ISA Datamodel Reflection Layer
All symbols, docstrings, and module offsets on this page apply to
neuronx_cc2.24.5133.0+58f8de22 (cp310 wheel). The Cython.somodules are per-ABI — cp311/cp312 are byte-parallel rebuilds, so any module offset (e.g.PyInit_neuron_isa_tpb_pybind @0xb82f0) is named for cp310 only; re-confirm against the target wheel. Every class name, method name, attribute name, docstring, and default-literal below is read directly from the shipped wheel: the Cython meta-schema modules underneuronxcc/include/isa/datamodels/(build-id ofinstruction_info2acbdc4a…), the pybind11 bridgeneuronxcc/isa_tpb/sunda/neuron_isa_tpb_pybind.cpython-310-…so(build-id0b81969a…), and the C++ generated images inneuronxcc/starfish/lib/libBIR.so(build-ida9b1ea38…). Cython compilation preserves Python identifiers and docstrings as interned.rodataconstants (__pyx_n_s_*,__pyx_k_*), which is the recovery surface — these are binary-derived, not invented. See Build & Version Provenance.
Abstract
The struct-family capstone (2.9) typed the Tonga L3 wire format as one compilable .h: a 64-byte bundle whose body is an opcode-discriminated union of ADDR4/TENSOR*/MEM_PATTERN* descriptors. That header answers what the bytes are. This page answers the complementary question: where does the compiler keep the machine-readable description of every instruction, and how does that single description drive both the Python and the C++ encoder so they cannot disagree?
The answer is a four-layer Cython meta-schema shipped under neuronxcc/include/isa/datamodels/ — a self-described "lightweight alternative to pydantic, tailored for ISA instruction datamodels." It is the reflection layer: a small framework (fields → specifications → schema → datamodel) that lets every opcode be declared as a typed, self-validating @datamodel class. The authoritative per-opcode declaration is ISAInstructionInfo (in instruction_info.so), whose arch_isa 5-tuple (api_name, arch_isa_name, arch_isa_opcode, arch_isa_type, arch_isa_struct) is the bridge table from the public NKI op name to the silicon. The Python-accessible runtime exposes a deliberately thin pybind11 surface — NeuronInstruction.get_bytes/set_bytes over the raw 64-byte bundle plus a single all-opcodes validator. And the central proof: the same spec is read by one generator (instabrew/brewer.py) that emits two outputs — a Cython front-end op class and a C++ bir::Inst* class — whose JSON wire-key sets are byte-identical, so penguin-emitted IR round-trips losslessly into the C++ BIR.
NOTE (provenance honesty). The generator
neuronxcc/instabrew/brewer.pyis not shipped in the wheel — only its outputs are (the Cython*OpGen.socarry a verbatim"Generated by brewer … brewer.py at line 3384"provenance line, and the C++ libs carryinstabrew/brewer.pyas anassert()__FILE__). The generator's contract is therefore reconstructed from its two uniform outputs. Every such reconstruction is tagged INFERRED/STRONG; everything read from a shipped.sois CONFIRMED.
At a glance — the four meta-schema layers
The package is neuronxcc.include.isa.datamodels. Four Cython modules, each a layer; __init__.so re-exports them. Listed bottom-up (each layer consumes the one above it):
| Layer | Module (cp310 .so) | Size | Role | Key surface | Conf |
|---|---|---|---|---|---|
| 1. fields | fields.cpython-310…so | 223 KB | typed-dataclass field primitive | Field(), FieldSpec, MISSING; knobs default/default_factory/min_length/pattern/metadata | CONFIRMED |
| 2. specifications | specifications.cpython-310…so | 71 KB | named reusable FieldSpec presets | non_empty, no_space_non_empty (regex ^[^\s]+$), max_count, factor, MAJOR_MINOR, compact | CONFIRMED |
| 3. schema | schema.cpython-310…so | 876 KB | runtime type/value validators | BaseSchema + Int/Float/Bool/Str/None/Any/List/Dict/Optional/Union/Enum/Datamodel Schema, each .validate(value) | CONFIRMED |
| 4. datamodel | datamodel.cpython-310…so | 1.05 MB | the @datamodel framework | @datamodel, field_validator, post_init_validator, model_construct/model_copy/model_dump, SchemaValidator | CONFIRMED |
The four layers are the meta-schema — how an ISA datamodel is declared and validated. The per-opcode instances live elsewhere: the schema's ISAInstructionInfo/ISAInstructionParam classes are declared in instruction_info.so (§3), and materialized once per opcode in the <op>_info.so modules (e.g. activate2_info.so).
┌──────────────────────────── META-SCHEMA (this page §2) ──────────────────────────┐
fields.so ───▶ specifications.so ───▶ schema.so ───▶ datamodel.so (@datamodel framework)
Field/FieldSpec no_space_non_empty… *Schema.validate ISAInstructionInfo / ISAInstructionParam
└─────────────────────────────────────────────┬──────────────────────────────────┘
│ declared in
▼
instruction_info.so ── arch_isa 5-tuple ──▶ <op>_info.so (one ISAInstructionInfo per opcode)
(§3 schema classes) (§3 instances; e.g. activate2_info)
│ read by (unshipped) brewer.py
┌──────────────────────┴──────────────────────┐
▼ ▼
Cython <Op>Gen.so / <Op>.so (penguin IR) C++ bir::Inst<Op> (libBIR.so)
toJson / fromJson (birpy InstActivation) toJson / readFieldsFromJson
└────────── same 11/13 wire keys (§5 proof) ──┘
│ exposed to Python via
▼
neuron_isa_tpb_pybind.so ── NeuronInstruction.get_bytes/set_bytes(64 B) + is_valid (§4)
1. The four meta-schema layers
Layer 1 — fields.so: the typed-field primitive [CONFIRMED]
fields.so (PyInit_fields, source neuronxcc/include/isa/datamodels/fields.py) is the substrate. Its module docstring, read verbatim from .rodata, is "Field specifications for ISA instruction datamodels." It exports exactly two public names plus a sentinel:
Field(...)— a factory returning a dataclass field. Its docstring (verbatim): "A dataclass field with embedded validation specifications in metadata." The recovered worked example in the docstring is the clearest statement of the contract:name: str = Field(min_length=1, pattern=r'^[A-Za-z]+$') emails: List[str] = Field(default_factory=list, min_length=1)FieldSpec— the validation-constraint container; docstring "Field specification for validation constraints." (FieldSpec.__init__is interned).MISSING— the required-field sentinel (docstring line: "Use MISSING for required fields.").
The constraint vocabulary is recovered from the interned docstring lines and __pyx_n_s_* names: default, default_factory, min_length, pattern, metadata, MISSING, message. The mechanism: Field() embeds a FieldSpec into the dataclass field's metadata dict; downstream validators read it back. This is a generic typed-dataclass field decorator — it carries no bit offsets or widths. [STRONG: the wire layout lives in the capstone .h, not here; fields.so only types the Python-level field.]
Layer 2 — specifications.so: named reusable presets [CONFIRMED]
specifications.so is the smallest module (71 KB), docstring "Common validation specifications for ISA instruction datamodels." It wraps Layer-1 FieldSpec into ready-to-apply named presets so opcode declarations reference a name, not a raw constraint. Recovered interned identifiers: non_empty, no_space_non_empty, max_count, factor, MAJOR_MINOR, compact.
The decisive recovery is the regex behind no_space_non_empty, present verbatim in the .rodata string pool:
^[^\s]+$
GOTCHA.
^[^\s]+$is the ground-truth lexical rule for ISA mnemonics. Every opcode/fieldapi_nameis constrainedno_space_non_empty— non-empty and whitespace-free. If you reimplement the op registry, this is the exact validity predicate a mnemonic must satisfy; an empty or space-containing name is rejected atvalidated_inittime, not silently coerced.
The same module's .rodata carries the build banner Copyright (c) 2025, Amazon.com. All Rights Reserved, the build path /opt/workspace/KaenaCompilerNativeBuild-310/build/private/src-3.10.16, and GCC: (GNU) 11.5.0 20240719 (Red Hat 11.5.0-5) — pinning the Cython toolchain.
Layer 3 — schema.so: the runtime validator hierarchy [CONFIRMED]
schema.so (876 KB) is a JSON-Schema-style runtime type system. It imports FieldSpec from Layer 1 and exposes a class hierarchy of *Schema nodes, every node a class with a .validate(value) method. The full roster, recovered from qualified __pyx_* names and docstrings:
BaseSchema "Base class for all schema types." (.__init__, .validate, abstractmethod)
IntSchema "Schema for validating integer values."
FloatSchema FloatSchema.validate (float)
BoolSchema (bool)
StrSchema "Schema for validating string values." (min_length, pattern)
NoneSchema (None only)
AnySchema "Schema that accepts any value." (wildcard / pass-through)
ListSchema(item_schema) (homogeneous list)
DictSchema(key_schema, value_schema, keys_are_strings)
OptionalSchema(inner_schema) (allows None)
UnionSchema(union_schemas: list[BaseSchema])
EnumSchema(enum_class) ← the enum-DOMAIN check
DatamodelSchema(model_class) ← validates a nested @datamodel
The validation semantics are recovered verbatim from the error-message .rodata — these are how a spec constraint becomes a runtime check inside <Schema>.validate():
| Schema node | Error string (verbatim) |
|---|---|
IntSchema | '<name>' must be an integer, got <type> |
FloatSchema | '<name>' must be a float, got <type> |
BoolSchema | '<name>' must be a boolean, got <type> |
StrSchema | '<name>' must be a string, got <type> / '<name>' does not match required pattern: <pat> |
NoneSchema | '<name>' must be None, got <type> |
ListSchema | '<name>' must be a list, got <type> |
DictSchema | '<name>' must be a dict, got <type> |
UnionSchema | '<value>' does not match any union types |
Two custom exceptions live here: ValidationError ("Raised when field validation fails.") and SchemaError ("Raised when schema definition is invalid."). This layer validates Python-level types and value ranges — min_length/max_count/pattern constraints, sourced from Layer-1/2 FieldSpec, are enforced here. It does not carry bit offsets; those are the C++ INST_UNION bitfields the capstone documents. [STRONG: name-and-type validation only; complementary to the wire layer, not redundant with it.]
Layer 4 — datamodel.so: the @datamodel framework [CONFIRMED]
datamodel.so (1.05 MB) is the declaration framework — the "lightweight pydantic." Its module docstring, read verbatim: "A lightweight alternative to pydantic, tailored for ISA instruction datamodels." The public surface:
@datamodel— class decorator; docstring "A decorator that performs runtime type and custom validation to dataclass." It wraps a@dataclassand installs the model API.field_validator/post_init_validator— decorators marking a function as a per-field or post-init validator.- The injected model API (all interned):
model_construct("Construct an instance bypassing validation."),model_copy("Create a deep copy of the model with optional field updates."),model_dump("Export model as a dictionary."), andvalidated_init(the validating__init__replacement). - The internal collectors/runners:
_collect_field_validators,_collect_post_init_validators,_run_field_validators,_run_post_init_validators,_setup_validation. SchemaValidator+ the type-hint→schema builders_build_schema/_build_list_schema/_build_dict_schema/_build_union_schema— these map a Python type hint onto the Layer-3*Schemanodes. So when a@datamodelclass annotatesparams: List[ISAInstructionParam],_build_list_schemamints aListSchema(DatamodelSchema(ISAInstructionParam))andvalidate()recurses element-wise.
The canonical example embedded verbatim in the @datamodel docstring is the keystone — it names the ISA classes directly:
@datamodel
class ISAInstructionInfo:
api_name: str
params: List[ISAInstructionParam]
@datamodel
class ISAInstructionParam:
...
This is the meta-schema closing on itself: the framework's own docstring demonstrates it by declaring the very ISA classes that instruction_info.so instantiates.
2. ISAInstructionInfo and the arch_isa 5-tuple [CONFIRMED]
instruction_info.so (1.04 MB, neuronxcc.include.isa.instruction_info) is where the Layer-4 example becomes a real, populated schema. It declares the @datamodel-decorated classes that are the per-opcode field schema.
ISAInstructionInfo — docstring "An ISA Instruction description for public API." Its fields (recovered from interned names) split into a public API name, a bridge to silicon, and a typed operand list:
@datamodel
class ISAInstructionInfo:
api_name: str # public op/mnemonic (no_space_non_empty)
arch_isa_name: str # the CamelCase NEURON_ISA_TPB enum member
arch_isa_opcode: ... # the wire opcode byte (low byte of 0x10NN)
arch_isa_type: ... # the NEURON_ISA_TPB_OPCODE enum constant
arch_isa_struct: str # the C++ INST_UNION arm, e.g. "s2d2_ac_struct"
default_engine: NeuronEngine # which engine executes it
params: List[ISAInstructionParam] # the ordered operand/field list
constraints: ISAInstructionConstraints # group legality (ConstraintList / …PerChip)
assertions: List[ISAAssertion] # named legality predicates
performance: ISAPerformanceEstimation # the per-op latency model
traits: ISAInstructionTraits
docs: ISADoc
Its post-init validators — validate_unique_names (every param name unique), validate_same_dtype_params, validate_same_par_size_params, validate_same_free_size_params — are exactly the cross-field group checks that fire through the Layer-4 _run_post_init_validators path.
The
arch_isa5-tuple. Verified present ininstruction_info.so(strings … | rg -w):api_name,arch_isa_name,arch_isa_opcode,arch_isa_type,arch_isa_struct,default_engine. This is the complete bridge from the public NKI op to silicon:
Tuple member Binds to Cross-reference api_namepublic NKI / user-facing mnemonic — arch_isa_nameCamelCase op-enum member (e.g. Activate,Matmul)the neuron_isa.soop rosterarch_isa_opcodethe wire opcode byte the BIR roster opcode (e.g. Matmul 0x02)arch_isa_typethe NEURON_ISA_TPB_OPCODEenum constantenum ordinals (2.23, planned) arch_isa_structthe C++ INST_UNIONarms#d#_<tag>_structthe capstone .hunion armi.e.
instruction_info.sois the bridge table that lets the compiler translate one public op into a wire opcode, an engine, a union arm, and a field list — without that table, the op name and the silicon would be two disconnected namespaces.
ISAInstructionParam — docstring "A parameter description of an ISA Instruction for public API using composition." One operand/field of an opcode. It carries name, a param_info (one of three sub-models below), default_val (or MISSING → required), rd_wr_trait, and predicates is_tensor/is_immediate/is_read/is_write. The three composition sub-models — the field-type taxonomy — are all verified present:
ISATensorParamInfo "Information specific to tensor parameters."
→ num_partitions_isa_name, free_dim_count_isa_name, dtype_isa_name, par_dim_max, has_known_size
ISAImmediateParamInfo "Information specific to immediate parameters." (scalar/vector)
→ imm_type_isa_name
ISAFieldParamInfo "Information specific to field parameters." (enum-valued: AluOp, AccumCmd, …)
This is the second tier of the three-name arch mapping: every ISA-visible quantity carries both a public name and an arch/wire ISA name. A tensor param's dtype_isa_name / num_partitions_isa_name / free_dim_count_isa_name, and an immediate's imm_type_isa_name, are the silicon field names that the per-opcode validators key on. Per-chip variation (e.g. an opcode that shifts byte between CoreV2 and CoreV4) is carried by ConstraintListPerChip inside constraints — one ISAInstructionInfo per op spans all generations; the arch layer selects the override at emit time.
The bit-exact widths/offsets are not in this Python schema — it carries typed field names, dtype names, defaults, and constraints. The bit layout is the C++ INST_UNION (capstone), enforced by the pybind validator (§4). The two are complementary layers, not redundant.
3. The pybind11 runtime — NeuronInstruction.get_bytes/set_bytes [CONFIRMED]
The Python-accessible runtime ISA is the pybind11 bridge neuronxcc/isa_tpb/sunda/neuron_isa_tpb_pybind.cpython-310…so (930 KB; PyInit_neuron_isa_tpb_pybind @0xb82f0). This is the genuine compiled-C++ validator — its module docstring (verbatim): "Python bindings for Neuron ISA TPB assertion functions using pybind11." It is not Cython; it is real pybind11 (the .rodata carries pybind11::handle, error_already_set, the build path …/pybind11/*).
The registered surface is deliberately thin — it does not expose per-field bit accessors to Python. The 64-byte bundle is opaque to Python; it is moved as a flat byte array and validated in C++:
// pybind11 module surface (recovered from .rodata symbol/docstring constants):
py::class_<NeuronInstruction> "NeuronInstruction"
.name : str // the opcode mnemonic
.instruction : <union payload>
.get_bytes() -> Sequence[int] // read the 64-byte wire bundle
.set_bytes(Sequence[int]) -> None // write the 64-byte wire bundle
py::class_<DebugResult> "DebugResult"
.result : bool
.error_messages : list[str] // the names of FAILED per-field asserts
is_valid_neuron_instruction(NeuronInstruction) -> bool
// "Check if the instruction is a valid Neuron instruction"
dbg_is_valid_neuron_instruction(NeuronInstruction) -> DebugResult
// "Debug version: Check if the instruction is a valid Neuron instruction"
All of NeuronInstruction, get_bytes, set_bytes, is_valid_neuron_instruction, dbg_is_valid_neuron_instruction, DebugResult, and error_messages are verified as interned strings in this .so. The underlying C++ type is NEURON_ISA_TPB_INST_UNION — the 25-char Itanium length-prefixed mangling 25NEURON_ISA_TPB_INST_UNION (and the validator signatures bRK25NEURON_ISA_TPB_INST_UNIONE / DebugResultRK25…) are present in .rodata. The opcode-enum prefix NEURON_ISA_TPB_OPCODE_ and the runtime errors Opcode is NEURON_ISA_TPB_OPCODE_… / opcode is not a known Neuron opcode confirm the union is opcode-discriminated. This is the same 64-byte INST_UNION the capstone types.
The "schema query" via 64 bytes. Because no per-field accessor is exposed, the Python way to ask "is this field combination legal?" is: assemble the 64-byte bundle (via the
isa_construction_helpers.create_tensorNd_mem_patternbuilders), wrap it asNeuronInstruction(name, bytes), and calldbg_is_valid_neuron_instruction()— the returnedDebugResult.error_messageslists the names of every violated per-field assertion. The rich per-opcode field/assert vocabulary (thed{2,3,4}_<op>_*field families and the*_checkpredicates) lives inside the C++ validator body, keyed by the opcode discriminant; only the assertion names survive as strings.
The per-opcode field families and the assertion idiom are verified in the .so string pool: opcode discriminants like s_s3d3_mm_opcode; descriptor-prefixed field names d3_mm_dtype, d3_mm_valid_xbus, d3_mm_valid_src_partition, d3_mm_valid_col_group_active_col, d3_mm_reserved2; the dtype legality checks type_fp32r_illegal / type_uint64_illegal_check; and the failure idiom inst failed assertion check: '<predicate_name>'. The descriptor prefix encodes the union arm: s = source-AP version, d# = dest-descriptor generation — the same s#d#_<tag>_struct naming as arch_isa_struct (§2).
The construction front-end (neuronxcc/isa_tpb/python/isa_construction_helpers.so, Cython) exposes the bundle builders create_tensor1d_mem_pattern … create_tensor4d_mem_pattern, whose descriptor inputs (num_elem, step_elem, psum_partition_address, …) are verified present and match the TENSOR1–4D descriptors one (step, num_elem) pair per dimension. The companion enum_mapping.so carries the dtype bridge map_dtype / map_alu over the Dtype enum — FP32R, BFLOAT16, FP8_EXP3/FP8_EXP4/FP8_EXP5 all verified — the authoritative dtype roster the dtype_isa_name field checks validate against.
4. One spec, two encoders — the single-spec → two-output proof [CONFIRMED]
This is the page's central claim: one ISA datamodel spec drives both the Python and the C++ encoder, and the proof is that their JSON wire-key sets are byte-identical. The mechanism is a single generator, neuronxcc/instabrew/brewer.py, that is a multi-target emitter.
4.1 One generator, present in both back-ends [CONFIRMED]
The decisive artifact is the path string …/neuronxcc/instabrew/brewer.py, verified present (one occurrence each) in all three C++ libraries:
$ strings -n6 libBIR.so | rg -c instabrew/brewer.py → 1
$ strings -n6 libwalrus.so | rg -c instabrew/brewer.py → 1
$ strings -n6 libBIRSimulator.so | rg -c instabrew/brewer.py → 1
In the C++, this path is the __FILE__ argument of generated assert() macros — it is loaded into RSI immediately before call __assert_fail@plt (glibc ABI __assert_fail(expr, FILE, line, func)), with the companion func argument naming generated per-op bodies such as bool bir::InstCall::sameInst(bir::Instruction*). So the C++ translation unit containing those bir::Inst* methods was emitted by brewer.py.
The identical generator is the Python provenance, read verbatim from ActivationOpGen.so:
Generated by brewer from the definition in neuronxcc/instabrew/brewer.py at line 3384
NOTE.
brewer.pyitself is not in the wheel (it is a build-time tool). Its multi-target emitter behaviour — read oneISAInstructionInfospec, emit a Python class and a C++bir::Inst*class — is INFERRED from the two uniform outputs; thebrewer.pyprovenance string in both languages is CONFIRMED.
4.2 The two outputs agree on the wire keys [CONFIRMED]
Take Activation (spec source: activate2_info.so, arch_isa_struct = "s2d2_ac_struct").
C++ side — bir::InstActivation in libBIR.so, verified by nm -DC at the exact addresses from the disassembly:
bir::InstActivation::toJson(…) @0x435450 // SERIALIZE
bir::InstActivation::readFieldsFromJson(…) @0x417f00 // DESERIALIZE
bir::InstActivation::createFromJson(…) @0x425b10 // FACTORY → readFieldsFromJson
toJson emits and readFieldsFromJson reads the same 11 wire keys (symmetric, lossless round-trip):
func, op0, op1, reverse0, reverse1, reduce_op, scale, acc, alpha, is_activate2, can_read_uninit
reverse0, reverse1, reduce_op, is_activate2, can_read_uninit are all verified present in libBIR.so's string pool. These keys are the brewer-emitted serialization of activate2_info's params — func ← activation_func, op0/op1 ← the tensor-scalar AluOps, reverse0/reverse1 ← "reverse operand order for first/second operation" (the verbatim spec docstring), alpha ← relu_param, etc.
Python side — birpy/InstructionOpcodes.so defines a class named exactly InstActivation with methods InstActivation.toJson, InstActivation.fromJson, and InstActivation.setAcc (all verified interned), carrying the same wire-key vocabulary. .setAcc corresponds to the C++ acc key.
activate2_info (ONE ISA datamodel spec)
├─ brewer.py ─▶ Python birpy InstActivation.toJson / .fromJson ── 11 keys
└─ brewer.py ─▶ C++ bir::InstActivation::toJson / readFieldsFromJson ── 11 keys (SAME SET)
InstMatmult is the second, independent confirmation: bir::InstMatmultBase::toJson/readFieldsFromJson round-trip 13 keys (accumulation_flag, psum_zero_region, replication_resolution, ifmap_quant_offset, perf_mode, … — all verified in libBIR.so), and the Python birpy InstMatmult carries 13/13 verbatim.
4.3 Enums serialize as strings — so the spellings must agree [CONFIRMED]
The wire encoding of every enum-valued field is the enum NAME string, not an integer. The C++ JSON serializers call <Enum>2string, verified by nm -DC on libBIR.so:
bir::Dtype2string(bir::Dtype) @0x2641e0
bir::string2Dtype(std::string const&) @0x265fb0 (inverse)
bir::AluOpType2string(bir::AluOpType) @0x400600
bir::ActivationFunctionType2string(bir::ActivationFunctionType) @0x4002a0
Because the wire carries the name string, the Python emitter must produce the identical spelling for the round-trip to parse — and it does, because both sides project the same spec enum domain. birpy/InstructionOpcodes.so imports neuronxcc.starfish.penguin.dtypes for its Dtype enum; the C++ Dtype is the 20-member enum (ordinals 0..19) whose names the Python BIR layer reuses.
The round-trip safety guarantee. Single-spec generation structurally prevents the classic two-implementation drift bugs: a field added on one side only (both regenerate from one
paramslist), an enum value spelled differently (one<Enum>2stringtable), a key-name/order skew (same brewer template, same param order), a dtype-tag mismatch (oneDtypeenum). The spec is the single source of truth; both languages are projections of it; so a BIR emitted by Python parses losslessly in C++ and re-emits byte-stable. This is whytoJsonkey-set==readFieldsFromJsonkey-set holds for both Activation (11) and Matmult (13).
4.4 The inheritance contract is identical across languages [STRONG]
Python: Activation(NeuronInst), MatMul : MatMulOpBase : NeuronInst. C++ (verified via RTTI __si_class_type_info relocations): InstActivation : bir::Instruction, InstMatmult : InstMatmultBase : bir::Instruction. The IR-plumbing root NeuronInst maps to bir::Instruction; the generated base owns the spec fields + serialize/verify, and op-specific logic layers on top. The Python two-module split (<Op>OpGen.so + <Op>.so) is a Cython packaging choice; the C++ side folds base + behaviour into one TU (with the Inst<Op>Base/Inst<Op> split where a shared base is needed). The brewer generator (Part 7, 7.3) is the same emitter on both paths.
Reconstructed mechanism — spec → field accessor → 64-byte get/set
Annotated pseudocode naming the real recovered symbols. The framework half (Layers 1–4) is CONFIRMED from the shipped .so; the brewer template is INFERRED from its uniform output (brewer.py not shipped).
# ── LAYER 4: declare one opcode as a @datamodel (CONFIRMED: instruction_info.so) ──
@datamodel # datamodel.so: installs validated_init, model_dump, …
class ISAInstructionInfo: # docstring "An ISA Instruction description for public API"
api_name: str = Field(metadata=no_space_non_empty) # specifications.so preset: ^[^\s]+$
arch_isa_name: str # the arch_isa 5-tuple (§2) — bridge to silicon
arch_isa_opcode: int # → wire opcode byte
arch_isa_type: ... # → NEURON_ISA_TPB_OPCODE enum constant
arch_isa_struct: str # → "s2d2_ac_struct" INST_UNION arm
default_engine: NeuronEngine
params: List[ISAInstructionParam] # the ordered field list
# ── LAYER 4: validated_init maps each annotation onto a LAYER-3 schema, then validates ──
def _build_schema(type_hint): # datamodel.so
if is List[T]: return ListSchema(_build_schema(T)) # schema.so
if is Enum: return EnumSchema(enum_class) # enum-DOMAIN check
if is @datamodel:return DatamodelSchema(model_class) # recurse
if is int: return IntSchema() # "'<name>' must be an integer, got <type>"
... # Str/Bool/Float/Optional/Union/Dict/None/Any
# field constraints (min_length/pattern) come from the LAYER-1 FieldSpec in field.metadata
# ── (UNSHIPPED) brewer.py reads ISAInstructionInfo, emits TWO encoders [INFERRED template] ──
# for p in spec.params:
# emit getter property p.name -> self._<p.name>
# emit ctor arg p.name (default = p.default_val; required if MISSING)
# emit serialize: result[p.arch_isa_name or p.name] = _emit(self._<p.name>)
# # _emit: x.serialize() if model/opcode/operand; <Enum>2string if enum;
# # number-wrap if scalar; 'none' if Optional unset
# ⇒ Python <Op>.toJson AND C++ bir::Inst<Op>::toJson — SAME key set (§4.2 CONFIRMED)
// ── RUNTIME: the 64-byte bundle is opaque to Python; validated in C++ (CONFIRMED) ──
// neuron_isa_tpb_pybind.so — NeuronInstruction wraps NEURON_ISA_TPB_INST_UNION (64 B)
struct NeuronInstruction { // py::class_ "NeuronInstruction"
std::string name; // .name = opcode mnemonic
NEURON_ISA_TPB_INST_UNION instruction;// 64-byte bundle; raw[0] = opcode discriminant
std::vector<unsigned char> get_bytes() const; // read 16 dwords
void set_bytes(std::vector<unsigned char>); // write 16 dwords
};
bool is_valid_neuron_instruction(const NeuronInstruction&); // → bool
DebugResult dbg_is_valid_neuron_instruction(const NeuronInstruction&); // .error_messages =
// names of the violated d{2,3,4}_<op>_* asserts, e.g. "type_fp32r_illegal" — keyed by raw[0]
Cross-References
- NEURON_ISA_TPB Struct-Family Capstone (the
.h) (2.9) — the 64-byteINST_UNIONbitfield layout this layer reflects;arch_isa_structnames its union arms, and the pybindget_bytes/set_bytesmove exactly those 64 bytes. - PE Matmul Encoding — Dense / Sparse / MX & Quantize (2.10) — the
d3_mm_*/InstMatmultBasefield names this layer reflects; the 13-key Matmult wire-key proof of §4.2 is the encoding that page documents. - ISA Enum Ordinals (2.23, planned) — the numeric values behind
arch_isa_type/ theDtype/AluOpTypeenum-name strings that §4.3 shows serialize by name. - Methodology & the Confidence Model — the CONFIRMED/STRONG/INFERRED grounding tags; the "generator-not-shipped, reconstruct-from-output" pattern used for
brewer.py. - Build & Version Provenance — the cp310/cp311/cp312 per-ABI
.sorebuild note that makes every module offset version-pinned. - The
brewergenerator (Part 7, 7.3) — the multi-target emitter whose two outputs §4 proves agree; this page documents its contract from the wheel side, Part 7 from the BIR side.