Applied competency reference | updated 2026-07-11

NPU Framework, Compiler, ISA, and Tooling Skills

An engineering path from framework execution semantics to an edge accelerator backend. It concentrates on PyTorch and TensorFlow internals, forensic ONNX analysis, current TVM architecture, RISC-V and NPU ISA integration, measured power/performance work, executable SDK examples, debugger GUI design, and cross-team practice.

CaptureKnow what framework behavior becomes a graph
ProvePreserve semantics through analysis and transformation
LowerConnect graph IR to ISA, descriptors, and runtime
DemonstrateShip examples, tools, tests, and decision records

Coverage boundary

Existing foundations stay in their original pages

This document does not repeat neural-network basics, accelerator comparisons, LLVM/MLIR introductions, generic graph optimization, quantization, C, Git, or the Analog CIM study. Use the foundation chapters first, then consult the Analog CIM specialization when it is relevant to the product or role.

Deep-learning foundationsTraining, architectures, transformers, deployment parity, and basic profiling already exist.Use Deep Learning Practice
LLVM and MLIRIR, SSA, dialects, bufferization, and progressive lowering already exist.Use LLVM/MLIR study
Compiler practiceFusion, tiling, layout, memory hierarchy, TVM basics, quantization, and interview questions already exist.Use NPU Practice
New: framework-to-backend reasoningDispatcher, autograd, graph capture, export constraints, retracing, and backend obligations.Study framework internals
New: integration evidenceONNX forensics, applied TVM, ISA/ABI, low-power decisions, examples, GUI, and collaboration artifacts.Study the evidence matrix

Deep-learning framework internals

Backend engineers must know which semantics survive capture

Eager execution, automatic differentiation, graph capture, ahead-of-time export, and backend lowering are different mechanisms. A graph compiler receives only the behavior that the selected capture path represents.

Dynamic execution

PyTorch eager: Python call to dispatched kernel

A tensor operation reaches the dispatcher, which selects behavior for backend and cross-cutting features such as autograd, autocast, or functionalization. Autograd records a reverse-mode graph of Function objects as the forward computation executes.

Reason aboutDispatch keys, ATen operator schema, tensor metadata, views/aliasing, mutation, saved tensors, grad mode.
Backend implicationAn NPU kernel registration is not enough if autograd, fake/meta, autocast, serialization, or profiling paths are missing.
Failure signatureWrong dispatch key, missing kernel, device mismatch, alias violation, unsupported layout, or backward error.
EvidenceOperator registration tests, gradcheck where applicable, fake-tensor shape tests, profiler events, CPU differential vectors.
QuestionPyTorchTensorFlowNPU engineering consequence
Eager pathDispatcher selects ATen kernels and cross-cutting behavior.Eager runtime executes TensorFlow ops immediately.Device integration needs operator, memory, error, profiler, and lifecycle support, not only a compiler.
AutodiffDynamic reverse graph of autograd Function objects.GradientTape records operations for differentiation.Inference-only backends must reject training paths clearly; training backends need backward and state semantics.
CaptureDynamo regions with guards and graph breaks; export offers AOT full-graph capture.tf.function traces and caches concrete graphs.Compile cache keys must include all specialization assumptions that affect generated code.
Dynamic shapesGuards, symbolic dimensions, specialization, possible recompilation.Input signatures and trace compatibility control concrete-function reuse.Choose bounded dynamic kernels, shape classes, or compile-on-demand with visible cache behavior.
Debug unitPython frame, FX/ATen graph, compiled region, generated kernel.Python function, ConcreteFunction/GraphDef, cluster, executable.Preserve IDs through each level so a device fault maps back to source behavior.

ONNX network analysis

Inspect the graph before optimizing it

ONNX separately versions the IR, operator sets, and model. Shape inference is useful but intentionally incomplete for some dynamic behavior. A production analyzer records unknowns instead of inventing shapes.

1ValidateIR, opsets, schemas, topology, external data
2InferTypes, ranks, static and symbolic dimensions
3InventoryOps, attributes, constants, subgraphs, state
4DiagnoseTarget predicates, dynamic regions, fallback islands
5TransformOrdered passes with local proof obligations
6VerifyStructural checks, numerical parity, performance delta
ONNX forensic inventoryPython
from collections import Counter
import math
import numpy as np
import onnx
from onnx import checker, helper, shape_inference

model = onnx.load("model.onnx", load_external_data=True)
checker.check_model(model, full_check=True)
typed = shape_inference.infer_shapes(model, strict_mode=False)
graph = typed.graph

def shape_of(value):
    tensor = value.type.tensor_type
    if not tensor.HasField("shape"):
        return "unknown-rank"
    dims = []
    for dim in tensor.shape.dim:
        dims.append(dim.dim_value or dim.dim_param or "?")
    return dims

print("IR:", typed.ir_version)
print("Opsets:", [(item.domain or "ai.onnx", item.version)
                  for item in typed.opset_import])
print("Operators:", Counter(node.op_type for node in graph.node))
print("Inputs:", [(value.name, shape_of(value)) for value in graph.input])
print("Outputs:", [(value.name, shape_of(value)) for value in graph.output])

def logical_bytes(tensor):
    if tensor.data_type == onnx.TensorProto.STRING:
        return sum(len(value) for value in tensor.string_data)
    dtype = np.dtype(helper.tensor_dtype_to_np_dtype(tensor.data_type))
    return math.prod(tensor.dims) * dtype.itemsize

weight_bytes = sum(logical_bytes(item) for item in graph.initializer)
print("Initializers:", len(graph.initializer), weight_bytes, "logical bytes")

for index, node in enumerate(graph.node):
    domain = node.domain or "ai.onnx"
    print(index, domain, node.op_type, list(node.input), list(node.output))

Analyzer outputs worth keeping in CI

  • IR and opset versions, model and external-data digests, producer metadata.
  • Input/output signatures with symbolic dimensions and bounded-shape policy.
  • Operator, domain, attribute, initializer, sparse tensor, function, and subgraph inventory.
  • Target support result for every node, with reason and estimated boundary transfer cost.
  • Quantization representation: QDQ, integer operators, scales, zero points, granularity, axis.
  • Reference vectors and per-output tolerances tied to preprocessing and postprocessing versions.
  • Peak live tensor estimate, constant bytes, dynamic allocation sites, and fallback memory.
Pass orderTransformationProof obligation before the next stage
1. Validate/versionReject malformed graphs; convert opsets only with defined adapters.Every node resolves to known semantics for its imported domain and version.
2. Type/shape analysisPropagate known facts and record unresolved symbols.No pass assumes a static dimension that analysis has not proved or guarded.
3. NormalizeCanonicalize equivalent forms and make implicit broadcasts/layouts explicit where needed.Reference output remains equal; source and quantization metadata survive.
4. SimplifyConstant fold, eliminate dead/identity work, simplify control and shape subgraphs.Folding respects dtype, overflow, NaN, rounding, and external-data policy.
5. Capability/partitionAssign maximal legal regions to NPU or fallback providers.Each region satisfies target predicates; boundary conversions are explicit and costed.
6. Target transformsFuse, choose layouts, quantize/lower, schedule, and plan memory inside owned regions.Numerical, memory, and resource constraints pass independent verifiers.
7. Package/compareEmit executable and run framework/ONNX/target parity plus performance measurements.Artifact provenance, tolerances, target versions, and regression result are retained.

Partition timing matters. ONNX Runtime performs provider-independent optimizations before partitioning and provider-specific work afterward. Its current documentation recommends a plugin execution provider for new integrations starting with ONNX Runtime 1.23. A vendor backend should verify which layer owns each rewrite so two optimizers do not erase one another's patterns or apply incompatible layouts.

Applied TVM architecture

Use TVM as two connected optimization levels plus a runtime

The site already introduces TVM beside MLIR. This section focuses on the current practical mapping: Relax for graph/dataflow structure, TensorIR for primitive tensor programs, scheduling for implementation choices, and runtime modules for deployment.

Front endModel importBuild an IRModule with Relax functions
RelaxGraph transformsLegalize, fuse, plan buffers, preserve shapes
TensorIRPrimitive functionsLoop nests, buffers, loads/stores, tensor intrinsics
ScheduleImplementationTile, reorder, vectorize, bind, tensorize, search
CodegenTarget moduleLLVM or source code plus external kernels
RuntimeExecuteVM bytecode, compiled functions, PackedFunc, allocators
Extension pointNPU useAcceptance evidence
Relax import / rewriteRepresent target composite patterns, quantized forms, shape constraints, and offload regions.Before/after IR, structural matcher tests, numerical parity, rejection diagnostics.
Operator legalizationLower high-level ops to target primitives, TIR, or external PackedFunc calls.Semantic tests across dtype, shape boundary, attributes, and dynamic dimensions.
TensorIRRepresent local buffers, data movement, loop structure, and hardware tensor intrinsics.Generated access bounds, race analysis, bit parity, resource estimates.
Schedule / MetaScheduleSearch tile, layout, memory scope, parallelization, and tensorization choices.Reproducible workload key, search budget, measured target result, held-out validation.
Codegen / moduleEmit NPU command binaries, firmware code, target source, or runtime-call wrappers.Versioned module metadata, load tests, disassembly/descriptor inspection, compatibility checks.
Runtime / VMLoad modules, resolve functions, allocate devices, execute graph control, call compiled kernels.Lifecycle, concurrency, serialization, allocator, error, and remote-device tests.

RISC-V and NPU accelerator ISA

The key decision is how software submits work, not whether an opcode looks elegant

RISC-V reserves custom encoding spaces for vendor-specific extensions. An accelerator may instead use MMIO, memory-resident command queues, a standard device interface, or a combination. Workload granularity and system isolation usually matter more than instruction count.

Integration styleBest fitMain costCompiler/runtime consequence
Custom scalar/vector instructionFine-grain tightly coupled operations with registers or local state.Toolchain, context state, exceptions, virtualization, and memory-model integration.Intrinsic/builtin lowering, assembler/disassembler, ABI and scheduler awareness.
MMIO controlSimple control/status, boot, reset, capability, and low-rate commands.High per-command CPU overhead; ordering and posted writes require care.Driver API and register generation; rarely suitable for every tensor tile.
Memory command queueCoarse asynchronous kernels, DMA descriptors, multiple in-flight jobs.Descriptor validation, coherency, fences, queue wrap, reset and fault recovery.Compiler emits command graph; runtime owns buffers, dependencies, submission, events.
Firmware RPCComplex scheduling, stable host API across changing hardware internals.Firmware latency, version negotiation, watchdogs, diagnosability.Artifact carries firmware-facing operations; host remains insulated from microarchitecture.
Illustrative queue descriptorC ABI contract
#include <stdint.h>

struct npu_command_v1 {
    uint16_t size_bytes;       /* permits compatible extension */
    uint16_t opcode;
    uint32_t flags;
    uint64_t command_id;
    uint64_t executable_id;
    uint64_t input_iova;
    uint64_t output_iova;
    uint32_t input_bytes;
    uint32_t output_bytes;
    uint32_t dependency_count;
    uint32_t completion_slot;
};

/* Producer protocol:
 * 1. Validate ownership and bounds.
 * 2. Write descriptor and dependency records.
 * 3. Publish with the required release ordering.
 * 4. Update producer index and ring the doorbell.
 */

ISA and ABI review checklist

  • Define architectural state, privilege, context-switch cost, and reset value.
  • Specify operand widths, alignment, endianness, rounding, saturation, and exception behavior.
  • Separate virtual, physical, and I/O virtual addresses; state IOMMU and coherency assumptions.
  • Name memory ordering for descriptors, MMIO, DMA, completion, and CPU visibility.
  • Define malformed command, page fault, watchdog, engine fault, retry, and partial-write behavior.
  • Reserve feature bits and size-versioned messages; test old/new driver and firmware combinations.
  • Generate encoders, decoders, docs, simulator tables, and disassembly from one source of truth.
  • Run differential ISA tests plus whole-command random sequences through model and RTL.

RISC-V uses a relaxed memory model and explicit fences for required ordering. A queue protocol must translate that architectural rule into concrete producer/consumer barriers and device coherency operations. "Write the descriptor, then ring the doorbell" is incomplete until visibility and ordering are specified for every agent.

Low-power and high-performance optimization

Optimize energy under a latency and correctness constraint

Measurement formulas and trace correlation live in SoC Software Architecture. This section focuses on choosing and validating optimization levers across the stack.

LayerHigh-value leversHidden tradeoffRequired experiment
Model / graphArchitecture choice, sequence/image size, sparsity, precision, fusion, partition boundaries.Accuracy recovery, unsupported operators, fallback copies, compile specialization.Task metric plus per-layer sensitivity and end-to-end target execution.
Kernel / scheduleTiling, locality, double buffering, tensorization, parallelism, layout, recompute versus spill.SRAM pressure, bank conflicts, tail inefficiency, code size, synchronization.Counter-backed roofline classification across representative shapes.
RuntimeAsync queues, zero-copy, buffer pools, compile cache, batching, overlap, reduced wakeups.Tail latency, memory residency, fairness, cancellation, cold-start behavior.Latency distribution and energy across arrival patterns, not only saturated throughput.
SoC / powerDVFS, clock/power gating, autosuspend, race-to-idle, memory frequency, thermal policy.Wake latency, leakage, droop, thermal throttling, deadline misses, shared-rail effects.Steady-state power and latency sweep by operating point and duty cycle.
ProductWorkload admission, quality modes, telemetry, field calibration, graceful fallback.User-visible quality, battery life, contention, privacy, fleet variability.Scenario-level acceptance criteria and canary/rollback evidence.
Classify

Find the limiting resource

Separate host dispatch, queue wait, DMA, memory bandwidth, engine occupancy, synchronization, power-state transition, and thermal throttling before selecting a lever.

Hypothesize

Predict two metrics

State the expected primary benefit and at least one regression risk. For example, a lower frequency may improve power but increase leakage energy and miss a latency deadline.

Validate

Use distributions and controls

Pin model, inputs, software versions, operating point, temperature, and concurrent load; compare repeated latency and energy distributions with accuracy unchanged.

SDK and application examples

Examples are executable compatibility contracts

SDK architecture and API ownership are covered in SoC Software Architecture. The missing skill is designing examples that remain small, realistic, testable, and safe to imitate.

ExampleContract demonstratedAutomated acceptance
Minimal inferenceDiscovery, artifact load, input/output binding, synchronous run, cleanup.Known output, leak-free lifecycle, clear unsupported-target error.
Asynchronous pipelineMultiple buffers, events, dependency ordering, overlap, callback/thread policy.Random completion timing, no early reuse, timeout and cancellation tests.
Camera zero-copyImported buffer, format/layout, cache/coherency, fence ownership, lifetime.Correct frames under producer/consumer stress and fallback path.
Dynamic inputsShape constraints, compile-cache key, bounded allocation, rejection behavior.Supported shape classes, cache hit/miss telemetry, out-of-bound diagnostic.
Multi-model serviceContexts, memory budget, queue fairness, priority, device loss and reload.Tail latency, isolation, bounded residency, fault containment.
Profiler/debuggerTrace session, layer/source map, counters, tensor checkpoint, replay package.Schema validation, timestamp correlation, first-divergence golden test.
Custom operatorRegistration, shape/type inference, fallback, compiler lowering, target kernel.Positive/negative shapes, reference parity, package and version compatibility.

GUI programming for NPU tools

A debugger GUI should be a view over stable analysis data

Qt's model/view architecture separates data from presentation. Keep trace decoding and tensor analysis off the UI thread, publish immutable or versioned result models, and make every visual selection addressable by stable IDs.

IngestReadersModel, artifact, trace, counters, tensors
NormalizeAnalysis modelStable IDs, time domains, layouts, errors
IndexQuery layerGraph, timeline, memory, tensor, search
PresentQt model/viewTables, tree, timeline, plots, inspectors
ActCommandsFilter, compare, checkpoint, replay, export
Data architecture

One selection identity across panes

Selecting a graph node should highlight its fused region, commands, timeline slices, buffers, counters, and tensor diffs through stable IDs rather than text-name matching.

Responsiveness

Stream and aggregate outside the UI thread

Workers parse traces and tensors, cancellation stops stale work, and views request bounded windows. Million-event traces should not become a million GUI objects.

Testability

Test models before pixels

Unit-test sorting, filtering, time conversion, diff thresholds, selection propagation, and empty/error states. Add screenshot tests only after the underlying data contracts are stable.

ViewPrimary modelPerformance ruleFailure state
Graph treeSource node, region, command hierarchy with support/fallback status.Lazy children and indexed search; do not rebuild the entire tree per selection.Missing source map remains explicit; never guess by operator name.
TimelineTime-windowed slices, counters, and cross-track flows.Level-of-detail aggregation and virtualized drawing.Clock uncertainty and dropped events are visible annotations.
Tensor inspectorTyped tensor view, layout transform, quantization, statistics, sampled values.Chunked reads and sampling before full materialization.Unavailable checkpoints explain compile mode and capture policy.
Memory mapLifetime intervals, address ranges, banks, aliases, residency.Interval indexes and viewport filtering.Overlaps distinguish legal alias from verifier error.
ComparisonAligned runs by graph/command ID, metric, software, and target version.Precompute summaries; load raw traces on demand.Incompatible artifacts or shape profiles block misleading comparison.

Technical soft skills

Cross-functional work becomes visible in engineering artifacts

Interface writing

Turn assumptions into contracts

Write version, ownership, state, ordering, units, error, timeout, and compatibility rules. A short executable schema plus adversarial examples is stronger than a long ambiguous design note.

Evidence discipline

Separate observation, inference, and decision

Attach traces, counters, inputs, versions, and uncertainty to claims. State what the evidence rules out, what remains possible, and the next cheapest discriminating experiment.

Cross-team debugging

Build a shared reproduction boundary

Reduce the failure to an artifact, input, expected output, component matrix, and first divergent layer/command. Assign investigation by evidence, not organizational blame.

Design review

Expose tradeoffs early

Present workload, constraints, alternatives, cost model, failure modes, observability, rollout, and rollback. Record the decision and the evidence that would cause it to change.

Code review

Review behavior at boundaries

Look for silent fallback, unchecked dimensions, lifetime races, nondeterministic pass order, ABI drift, missing negative tests, and metric changes before style details.

Incident learning

Repair the detection system

A useful postmortem adds a contract, assertion, counter, replay test, compatibility gate, or deployment safeguard so the same class of failure becomes cheaper to detect.

Evidence matrix

Competence is a result another engineer can inspect

Framework

Trace semantics

Explain eager dispatch, autograd, graph capture, guards/retracing, export, and backend boundaries.

Evidence: one model traced through PyTorch and TensorFlow with graph-break/retrace report and parity tests.

Framework

Custom backend surface

Define capability predicates, fallback, shape policy, compile cache, error propagation, and profiling integration.

Evidence: small backend or mock execution provider with negative tests and diagnostics.

ONNX

Graph forensics

Validate versions, infer known shapes, inventory nodes/constants/subgraphs, and find unsupported islands.

Evidence: reproducible analyzer output checked into CI for a model corpus.

ONNX

Verified transformations

Order normalization, simplification, partitioning, target transforms, and numerical comparison.

Evidence: three graph passes with structural, randomized, and framework/runtime parity tests.

Compiler

TVM extension

Connect Relax graph work to TensorIR, scheduling, codegen/module packaging, and runtime execution.

Evidence: custom legalization plus schedule experiment measured on a real or modeled target.

Compiler

Lowering to device work

Lower an operator through intrinsic or target IR into commands, descriptors, relocations, and debug maps.

Evidence: inspectable artifact with disassembly/descriptor dump and model parity.

ISA

RISC-V/NPU integration

Reason about custom instructions versus queues, ordering, coherency, privilege, faults, and versioning.

Evidence: ISA/ABI specification, generated encoder/decoder, simulator, and randomized differential tests.

Performance

Power/performance decision

Classify a bottleneck, predict tradeoffs, control variables, and validate latency, energy, and correctness.

Evidence: trace-backed optimization memo with raw data, uncertainty, and regression guard.

SDK

Executable examples

Cover sync, async, zero-copy, dynamic shape, multi-model, profiling, custom op, and recovery paths.

Evidence: examples run in CI and assert outputs, errors, lifetime, and compatibility.

GUI

Debugger/profiler application

Build indexed data models, worker pipelines, linked selections, scalable views, and explicit error states.

Evidence: Qt/PySide tool loading a replay package with graph, timeline, tensor diff, and memory views.

Collaboration

Boundary design

Write a reviewable interface with ownership, state, errors, ordering, observability, and compatibility.

Evidence: accepted design record plus schema, adversarial examples, and integration tests.

Collaboration

Cross-team debug

Reduce a failure, separate observations from hypotheses, choose discriminating experiments, and prevent recurrence.

Evidence: replay package, first-divergence report, decision log, and new regression gate.

Capstone

Build a miniature edge NPU platform

Each increment produces an inspectable artifact and reuses the architecture contracts from the companion SoC software page.

0 / 8 complete

Primary documentation

Framework, compiler, ISA, and GUI sources

Extending PyTorchDispatcher, native API extension, custom functions, and backend behavior
PyTorch exportAhead-of-time ExportedProgram capture, constraints, and deployment representation
TVM Relax VMCompilation, bytecode, executable, compiled kernels, allocators, and execution
Qt multithreadingWorker execution, queued events, thread-safe communication, and responsive UI design