Implementation reference | source review 2026-07-11

Analog CIM SDK and Compiler: From Model to Running Code

This page turns the Analog CIM research into an implementable software architecture. It defines the public SDK, compiler IR and passes, target and calibration artifacts, simulator and hardware backends, runtime and firmware contracts, framework integration, tests, and the smallest vertical slice that should work before the project grows. It is a reference design, not a disclosure of iHW, Mythic, IBM, or Tenstorrent internals.

First frontendStandalone ONNX import; ORT plugin second
Compiler coreMLIR with plan, physical, and command levels
Stable boundaryC ABI over opaque handles and asynchronous events
Bring-up strategyFunctional simulator before noise, timing, or silicon

Documentation review

What the previous pages explained, and what was still missing for implementation

The existing pages remain useful for physics, evidence, co-design, and reuse decisions. The changes below remove ambiguous ownership and add the contracts needed to write and test code.

PriorityReview findingWhy it blocks real codeResolution in this guide
P1Model calibration, silicon characterization, and per-device calibration were discussed under one name.They have different producers, update schedules, security requirements, and consumers.Three separate schemas and lifecycle owners are defined.
P1The executable and serial-number-specific device state were treated as one artifact.That prevents portable AOT compilation and creates a rebuild for every replacement device.A device-class executable is bound to a separate device-state bundle at load time.
P1No stable SDK API, handle ownership, queue, event, buffer, or error contract was specified.Compiler, runtime, simulator, applications, and tests cannot evolve independently.A versioned C ABI, C++ HAL, and Python workflow are provided.
P1Accuracy simulation and performance simulation were not separated strongly enough.AIHWKit and CrossSim can model numerical non-idealities, but they are not a product cycle/energy model.Functional, statistical, cycle/resource, and hardware backends have distinct acceptance criteria.
P2PyTorch, ONNX, StableHLO, ORT, and PJRT appeared as equivalent starting points.Supporting several frontends before one executable path works multiplies semantic and build risk.The MVP starts with ONNX; ORT and PJRT are staged integrations.
P2The compiler pipeline had no repository ownership or executable acceptance test.A list of passes does not show which library owns state or when a feature is complete.Modules, CLI commands, CI lanes, and vertical-slice exit tests are defined.
P2Firmware validation and recovery were described but not represented as a command protocol.Raw or weakly checked descriptors can damage state, hang queues, or use stale calibration.A bounded command set, state machine, validation rules, and recovery policy are specified.
P3Patent evidence and implementation design occupied the same long page.Readers could confuse a proposed software design with a vendor-disclosed implementation.The patent page now labels its software mapping as proposed, links here, and makes this page the authoritative build specification.

Architecture recommendation: build a simulator-first inference stack around one stable executable contract. Keep framework adapters above the compiler, physical device state below the artifact, and vendor-specific hardware behind a HAL. Do not begin by forking TTMetal, implementing PJRT, or supporting a complete model before one statically shaped MatMul compiles and runs end to end.

Product boundaries

Toolchain, SDK, runtime, HAL, driver, and firmware are different products

LayerPublic responsibilityMust not ownPrimary consumers
Model toolsValidate ONNX, collect representative ranges, compare accuracy, and produce model-calibration inputs.Physical addresses, queue descriptors, kernel-driver calls, or device secretsML engineers and compiler CI
Compiler toolchainImport, legalize, quantize, partition, map, schedule, lower, package, inspect, and verify.Live device ownership, asynchronous request state, or field recovery decisionsBuild systems, framework plugins, release engineering
Public SDKExpose device discovery, executable loading, buffers, sessions, queues, events, telemetry, and errors.Compiler implementation classes, direct register access, or unstable C++ internalsApplications, frameworks, tests, samples
RuntimeValidate compatibility, bind device state, manage memory, submit work, synchronize, and apply recovery policy.Framework graph semantics or unrestricted firmware commandsSDK bindings and execution providers
HALProvide one internal device interface implemented by simulation and silicon backends.User-facing ABI promises or model-level graph transformationsRuntime, bring-up tests, emulators
DriverIsolation, DMA/IOMMU, interrupts, mapping, reset, power, and firmware transport.Model partitioning, quantization policy, or source-level debug meaningHAL hardware backend and system software
FirmwareValidate bounded descriptors, schedule engines, own programming/calibration sequences, report faults, and recover.Untrusted host pointers, arbitrary array voltages, or policy hidden from telemetryDriver, runtime, manufacturing tools

Corrected calibration model

Three kinds of calibration create three different artifacts

ArtifactProducer and inputContentsUpdate triggerConsumer
Model calibration .qcalML/compiler team; representative model inputsActivation histograms, clipping, group scales, outlier policy, sensitivity, dataset hashModel, preprocessing, dataset, or quantization policy changesQuantization and partition passes
Target characterization .acharSilicon/algorithm team; measured chip populations and PVT sweepsArray distributions, transfer models, ADC/DAC behavior, IR drop, drift, faults, timing, energy coefficients, confidenceDevice revision, process, firmware, characterization method, or qualification changesCompiler operation model and statistical/cycle simulators
Device state .acalManufacturing or firmware; one device serial numberGain/offset trims, usable-array bitmap, remaps, weak cells, sensor references, calibration age, signatureFactory test, replacement, boot check, thermal event, aging threshold, recalibration, or repairRuntime, firmware, and hardware backend

Proposed file extensions are illustrative. The important contract is ownership. A model build may depend on a target class and characterization version, but it should not embed mutable calibration from a particular serial number. The runtime binds an accepted .acal bundle and rejects stale or incompatible state.

Keep the portable executable separate from device binding

Target descriptor.atargetStatic device class, revision, arrays, memory, commands, formats, and ABI capabilities.
Model executable.acxPortable within declared target requirements; graph, constants, plans, commands, kernels, and debug maps.
Device binding.acalSerial-specific calibration, remap, health, age, and signature loaded independently.
Execution evidence.atraceCorrelation IDs, timings, bytes, phases, saturation, faults, fallback, and calibration identity.
Deterministic cache keyEverything that can change generated behavior
compile_cache_key = hash(
  normalized_model,
  model_calibration,
  target_descriptor,
  characterization_version,
  compiler_version,
  compiler_options,
  artifact_schema_major
)

load_binding_key = hash(
  executable_target_requirements,
  device_revision,
  firmware_abi,
  device_state_schema,
  device_state_calibration_id
)

End-to-end flow

Characterize the target, build the executable, then bind and run

Plane ATarget characterizationRuns in lab and manufacturing infrastructure, not on every application build.
  1. A1Measure siliconArrays, ADC/DAC, wires, programming, PVT, drift, timing, energy
  2. A2Fit modelsDistributions, correlations, guard bands, confidence, device classes
  3. A3Validate predictorsHold-out chips and workloads; numerical and cycle correlation
  4. A4Sign target dataVersioned .atarget and .achar artifacts
  5. A5Publish compatibilityCompiler, firmware, simulator, and qualification matrix
target class becomes a compiler input
Plane BOffline model buildRuns in CI, an SDK tool, or a framework execution-provider compile callback.
  1. B1Check and importONNX checker, shape inference, source locations, reference tensors
  2. B2Calibrate modelRepresentative inputs, ranges, clipping, scales, sensitivity
  3. B3Plan graphSupport, quantization, analog/digital partition, fusion, fallback
  4. B4Map physical workDigits, arrays, faults, ADC ranges, phases, buffers, schedule
  5. B5Lower and packageCommands, digital kernels, program recipe, ABI, debug map
  6. B6Verify artifactFunctional, statistical, cycle, version, schema, and reproducibility gates
portable executable is delivered
Plane CLoad and executionRuns through the public SDK, runtime, HAL, driver, firmware, and device.
  1. C1Discover deviceRevision, firmware ABI, memory, health, supported modes
  2. C2Bind device stateValidate calibration signature, age, temperature, and remaps
  3. C3Load executableCheck target requirements, allocate resources, program/verify weights
  4. C4Submit requestsBind buffers, enqueue, return event, overlap transfer and compute
  5. C5Execute and observePulse, MVM, convert, reconstruct, digital work, telemetry
  6. C6Recover or completeRepeat, remap, recalibrate, refresh, fallback, reset, or return
Closed feedback loopSilicon trace and model accuracy → correlation report → characterization or compiler update → new versioned artifacts → staged qualification

SDK sequence diagram

One executable moves through five ownership boundaries

The compile path may run once per model release. Device binding and load run per deployment or boot. Submit and completion repeat per request.

ApplicationPython, C, C++
Framework/CLIONNX or plugin
CompilerMLIR and packager
Runtime/HALBuffers and queues
Firmware/devicePhysical execution
  1. Offline compile
  2. Model + deployment policy + representative-data identity
  3. Normalized graph + target/characterization versions
  4. Import → analyze → partition → map → schedule → lower → verify
  5. .acx + support, accuracy, mapping, and cost reports
  6. Device binding and load
  7. Open device + load executable
  8. Query revision, firmware ABI, health, and .acal
  9. Validated calibration/remap identity and resource availability
  10. Program recipe + bounded write/verify commands
  11. Ready session + compatibility and load report
  12. Repeated asynchronous request
  13. Bind buffers + submit queue + request policy
  14. Return event immediately
  15. DMA → pulse/MVM → ADC → reconstruct → digital work
  16. Completion + counters + saturation/fault status
  17. Output + event status + trace correlation ID

Software architecture

Use a thin stable public API over replaceable compiler and device internals

ModuleSuggested libraryOwnsDependency rule
ONNX frontendlibacim_frontend_onnxChecker, shape inference, semantic import, source locations, constantsMay depend on ONNX and MLIR; must not depend on runtime or driver
Compiler corelibacim_compilerDialects, analyses, passes, target operation model, reportsDepends on MLIR and schema libraries; hardware access is forbidden
Artifact supportlibacim_artifactSchema, serialization, hashes, signatures, inspect, compatibility rulesShared by compiler and runtime; may not depend on either implementation
Public runtime ABIlibacimC handles, status codes, discovery, sessions, buffers, queues, events, tracesOnly stable exported surface; hides C++ classes and backend choice
Runtime corelibacim_runtimeCompatibility, memory plan, load, binding, queueing, recovery policyDepends on artifact and HAL interfaces, never on a framework
HAL interfaceslibacim_halBackend, device, buffer, executable, command queue, event, telemetry interfacesNo vendor headers in public interfaces; backends are loadable or link-time modules
Simulation backendsacim_hal_functional, _analog, _cycleExact numerics, non-ideal distributions, timing/resourcesImplement the same HAL and artifact semantics as hardware
Hardware backendacim_hal_deviceDriver calls, DMA, command submission, firmware events, reset, telemetryOnly module allowed to include driver or firmware transport headers
Framework pluginsacim_ort_ep, later acim_pjrtFramework capabilities, graph handoff, buffer adaptation, fallback integrationCall compiler and public runtime APIs; do not duplicate backend logic
Python packageacim_sdkErgonomic compiler/runtime wrappers, reports, examples, notebooksThin bindings over stable C ABI plus optional compiler Python API
Repository structureOne ownership boundary per top-level directory
acim-stack/
  include/acim/              stable C API and versioned public structs
  api/cpp/                   header-only RAII wrapper over the C ABI
  python/acim_sdk/           Python compiler and runtime bindings
  compiler/
    frontend/onnx/           ONNX validation and import
    dialect/plan/            logical ACiM planning operations and attributes
    dialect/physical/        arrays, slices, converters, calibration requirements
    dialect/command/         firmware-visible command graph
    analysis/                shape, range, sensitivity, legality, cost, liveness
    transforms/              quantize, partition, map, schedule, lower, verify
    target/                  target and characterization schema readers
  artifact/                  FlatBuffer schema, serializer, verifier, inspector
  runtime/                   sessions, buffers, queues, events, load, recovery
  hal/                       backend interfaces and backend registry
  backends/{functional,analog,cycle,device}/
  driver/                    OS integration; separate release and privilege boundary
  firmware/                  descriptor parser, scheduler, health, reset, calibration
  integrations/{onnxruntime,pjrt}/
  tools/                     acim-compile, inspect, run, profile, characterize
  tests/{unit,ir,golden,differential,hardware,models}/
  examples/{matmul,onnx_ep,async_pipeline}/

Detailed repository guide: the accelerator repository blueprint expands this compact ownership sketch into schemas, generated code, C++ and Python packages, GoogleTest and pytest lanes, smoke through qualification tests, CI routing, contribution rules, performance methodology, and a full debug evidence bundle. Its minimal ACiM native example provides the first working CMake/Ninja, compiler, CTest, installation, and functional MVM path.

Compiler implementation

Start with upstream IR, then introduce hardware meaning in three small dialects

MLIR's declarative ODS and dialect-conversion infrastructure provide generated operation classes, verifiers, parsing, printing, and legality-driven lowering. Use them for infrastructure; do not import Tenstorrent target semantics into an ACiM backend.

IR stageRecommended representationAllowed knowledgeVerifier examples
Imported graphUpstream func, tensor, arith, linalg, quant, or a small normalized frontend layerTensor semantics, shapes, constants, source names, QDQ scalesRanks known where required, contraction dimensions agree, quantized zero is representable
acim_planLogical MVM/Conv regions plus candidate precision, scale domain, fallback, and error budgetTarget capabilities and measured operation-model estimates, not physical addressesEvery op has a legal implementation; scale and accumulator types are complete
acim_physicalArrays, rows/columns, digit slices, sign paths, ADC grades, phases, buffers, and calibration classTarget geometry, characterization, fault-reserve policy, and static schedule resourcesNo overlap, current and range limits pass, all slices reconstruct, resources fit
acim_commandBounded commands, dependencies, events, DMA, program/verify, execute, telemetry, and recovery pointsFirmware ABI and driver-visible memory handlesNo raw pointers, all buffer ranges valid, dependency graph acyclic, firmware supports opcode/version
Starter ODS shapeLogical MVM is pure; programming and command operations are not
def ACIMPlan_MvmOp : ACIMPlan_Op<"mvm", [Pure]> {
  let summary = "Logical matrix-vector operation eligible for ACiM planning";
  let arguments = (ins
    AnyRankedTensor:$activation,
    AnyRankedTensor:$weight,
    ACIM_PrecisionAttr:$precision,
    ACIM_ErrorBudgetAttr:$error_budget,
    ACIM_FallbackAttr:$fallback);
  let results = (outs AnyRankedTensor:$result);
  let hasVerifier = 1;
}

def ACIMCmd_ProgramArrayOp : ACIMCmd_Op<"program_array"> {
  let summary = "Request a bounded firmware-owned program and verify sequence";
  let arguments = (ins
    ACIM_ArrayRefType:$array,
    ACIM_ProgramImageType:$image,
    ACIM_CalibrationClassAttr:$calibration_class,
    ACIM_EventType:$dependency);
  let results = (outs ACIM_EventType:$completion);
  let hasVerifier = 1;
}

Implement passes in dependency order and save every boundary

OrderPass/libraryImplementation responsibilityMinimum test
1onnx-check-importRun ONNX checking and shape inference; import only MatMul/Gemm first; preserve source location and constants.Valid model imports; invalid rank/K dimension returns a stable diagnostic.
2canonicalize-contractsNormalize transpose, bias, broadcast, and contraction forms into one MVM semantic contract.Equivalent ONNX forms produce identical normalized IR.
3attach-quant-contractConsume QDQ or .qcal; materialize scale, zero point, clipping, rounding, and accumulator type.Integer software reference exactly matches expected output and saturation.
4analyze-capabilityGenerate reason-coded analog, digital, and host candidates from target capabilities.Unsupported shapes are rejected or receive an explicit fallback candidate.
5partition-and-fuseChoose regions using boundary conversion and transfer cost, not operation support alone.A forced analog/digital override produces a report and valid graph.
6decompose-weightsGenerate radix/sign slices and reconstruction coefficients; preserve logical-to-physical debug mapping.Reconstructed logical weights exactly equal the quantized reference.
7place-arraysTile matrices, reserve spares, constrain current, pack slices, and emit calibration-class requirements.No overlap; capacity and current constraints are checked by an independent verifier.
8plan-adc-phasesSelect ranges, converter sharing, phase count, repeat policy, and saturation/fallback guard.Every candidate reports predicted error, phases, saturation margin, and confidence.
9plan-memory-scheduleAllocate static arenas and overlap DMA, input encoding, MVM, ADC, reconstruction, and digital work.Lifetime intervals do not overlap illegally; cycle model accepts the schedule.
10lower-command-abiEmit versioned bounded commands and events; insert firmware validation and recovery checkpoints.Command schema round-trips and malformed descriptors fail before execution.
11serialize-acxPackage target requirements, programs, constants, plans, commands, reports, and debug maps.Artifact is deterministic, inspectable, schema-conformant, and rejects wrong target major versions.
12differential-verifyRun exact reference and selected backends; compare checkpoints and release thresholds.First divergent op, expected tolerance, seed, profile versions, and tensors are retained.

Candidate selection needs measured coefficients and uncertainty

Candidate record and constrained objectivePersist this data in compiler reports
candidate = {
  implementation: analog | digital | host,
  layout: {tiles, groups, buffers, sharding},
  numerics: {weight_digits, activation_bits, adc_grade, accumulator},
  physical: {arrays, phases, spares, calibration_class},
  estimates: {latency_ns, energy_pj, error_distribution, confidence},
  boundaries: {copies, conversions, synchronization},
  fallback: {trigger, implementation, recovery_cost}
}

minimize latency_weight * latency_p99
       + energy_weight  * energy
       + risk_weight    * accuracy_risk
       + boundary_weight * transfer_and_conversion
       + wear_weight    * programming_and_refresh

subject to error_budget, SRAM, current, ADC range, capacity,
           firmware ABI, calibration class, and service policy.

Do not use an accuracy simulator as a latency oracle. CrossSim explicitly states that it does not model accelerator energy, area, or speed. Use AIHWKit or CrossSim adapters for numerical studies, then maintain a separately correlated cycle/resource model for queues, SRAM, NoC, converters, firmware, and digital work.

Public SDK

Stabilize a C ABI, then build C++ and Python ergonomics on top

Opaque handles prevent ABI exposure of STL, compiler, and driver classes. Every public struct starts with its size and API version so newer libraries can accept older callers safely.

C ABI v0 starter headerCompile-ready shape; the API remains a proposed design
#ifndef ACIM_SDK_H_
#define ACIM_SDK_H_

#include <stddef.h>
#include <stdint.h>

#if defined(_WIN32)
#  if defined(ACIM_SDK_EXPORTS)
#    define ACIM_API __declspec(dllexport)
#  else
#    define ACIM_API __declspec(dllimport)
#  endif
#elif defined(__GNUC__)
#  define ACIM_API __attribute__((visibility("default")))
#else
#  define ACIM_API
#endif

#define ACIM_API_VERSION 1u
#define ACIM_MAX_RANK 8u

#ifdef __cplusplus
extern "C" {
#endif

typedef struct acim_context acim_context_t;
typedef struct acim_device acim_device_t;
typedef struct acim_executable acim_executable_t;
typedef struct acim_session acim_session_t;
typedef struct acim_queue acim_queue_t;
typedef struct acim_buffer acim_buffer_t;
typedef struct acim_event acim_event_t;

typedef enum acim_status {
  ACIM_STATUS_OK = 0,
  ACIM_STATUS_INVALID_ARGUMENT,
  ACIM_STATUS_UNSUPPORTED,
  ACIM_STATUS_INCOMPATIBLE_ARTIFACT,
  ACIM_STATUS_STALE_CALIBRATION,
  ACIM_STATUS_RESOURCE_EXHAUSTED,
  ACIM_STATUS_BUSY,
  ACIM_STATUS_TIMEOUT,
  ACIM_STATUS_CANCELED,
  ACIM_STATUS_DEVICE_FAULT,
  ACIM_STATUS_INTERNAL
} acim_status_t;

typedef enum acim_io_kind {
  ACIM_IO_INPUT = 0,
  ACIM_IO_OUTPUT = 1
} acim_io_kind_t;

typedef enum acim_element_type {
  ACIM_ELEMENT_I8 = 0,
  ACIM_ELEMENT_I32,
  ACIM_ELEMENT_F16,
  ACIM_ELEMENT_F32
} acim_element_type_t;

typedef enum acim_memory_flags {
  ACIM_MEMORY_HOST_VISIBLE = 1u << 0,
  ACIM_MEMORY_HOST_PINNED  = 1u << 1,
  ACIM_MEMORY_DEVICE_LOCAL = 1u << 2
} acim_memory_flags_t;

typedef struct acim_context_options {
  uint32_t struct_size;
  uint32_t api_version;
  const char* backend_name;      /* functional, analog, cycle, device */
  const char* backend_options;   /* validated JSON or key/value text */
} acim_context_options_t;

typedef struct acim_tensor_desc {
  uint32_t struct_size;
  uint32_t api_version;
  const char* name;              /* executable-owned; valid until release */
  acim_element_type_t element_type;
  uint32_t rank;
  int64_t dimensions[ACIM_MAX_RANK];
  size_t byte_size;
} acim_tensor_desc_t;

typedef struct acim_buffer_binding {
  uint32_t struct_size;
  uint32_t api_version;
  uint32_t tensor_index;
  acim_buffer_t* buffer;
  size_t offset;
  size_t size;
} acim_buffer_binding_t;

typedef struct acim_error_info {
  uint32_t struct_size;
  uint32_t api_version;
  acim_status_t status;
  uint32_t subsystem;
  int64_t device_code;
  uint64_t trace_id;
  char message[256];
} acim_error_info_t;

ACIM_API uint32_t acim_api_version(void);
ACIM_API acim_status_t acim_context_create(
    const acim_context_options_t*, acim_context_t**);
ACIM_API acim_status_t acim_context_get_last_error(
    acim_context_t*, acim_error_info_t*);
ACIM_API acim_status_t acim_device_count(acim_context_t*, uint32_t*);
ACIM_API acim_status_t acim_device_open(acim_context_t*, uint32_t, acim_device_t**);
ACIM_API acim_status_t acim_device_get_capabilities(
    acim_device_t*, char* json, size_t* inout_size);
ACIM_API acim_status_t acim_device_bind_state(
    acim_device_t*, const void* bytes, size_t size);
ACIM_API acim_status_t acim_executable_load(
    acim_device_t*, const void* bytes, size_t size, acim_executable_t**);
ACIM_API acim_status_t acim_executable_get_tensor_desc(
    acim_executable_t*, acim_io_kind_t, uint32_t index, acim_tensor_desc_t*);
ACIM_API acim_status_t acim_session_create(
    acim_device_t*, acim_executable_t*, acim_session_t**);
ACIM_API acim_status_t acim_queue_create(
    acim_session_t*, uint32_t queue_flags, acim_queue_t**);
ACIM_API acim_status_t acim_buffer_allocate(
    acim_device_t*, size_t bytes, uint32_t memory_flags, acim_buffer_t**);
ACIM_API acim_status_t acim_buffer_write(
    acim_buffer_t*, size_t offset, const void* source, size_t size);
ACIM_API acim_status_t acim_buffer_read(
    acim_buffer_t*, size_t offset, void* destination, size_t size);
ACIM_API acim_status_t acim_queue_submit(
    acim_queue_t*, const acim_buffer_binding_t* inputs, size_t input_count,
    const acim_buffer_binding_t* outputs, size_t output_count, acim_event_t**);
ACIM_API acim_status_t acim_event_wait(acim_event_t*, uint64_t timeout_ns);
ACIM_API acim_status_t acim_event_cancel(acim_event_t*);
ACIM_API acim_status_t acim_event_get_result(acim_event_t*, acim_error_info_t*);

ACIM_API void acim_event_release(acim_event_t*);
ACIM_API void acim_buffer_release(acim_buffer_t*);
ACIM_API void acim_queue_release(acim_queue_t*);
ACIM_API void acim_session_release(acim_session_t*);
ACIM_API void acim_executable_release(acim_executable_t*);
ACIM_API void acim_device_release(acim_device_t*);
ACIM_API void acim_context_release(acim_context_t*);

#ifdef __cplusplus
}  /* extern "C" */
#endif
#endif  /* ACIM_SDK_H_ */
API ruleRequired behaviorTest
OwnershipEvery successful create/open/load/allocate returns one owned reference. Parents outlive children; queues are drained or canceled before release; release is called exactly once.Sanitizer and fault-injection tests cover success, partial construction, outstanding events, and every failure path.
Thread safetyContext/device queries are concurrent; a queue is ordered; independent queues may overlap; session concurrency is reported by capabilities, never assumed.Multi-threaded submit and teardown with deterministic per-queue order and allowed cross-queue overlap.
AsynchronySubmit returns an event without waiting; buffer lifetime extends through event completion.Two queues overlap transfers and execution in the cycle and hardware backends.
ErrorsStatus codes are stable categories. Synchronous details are thread-local to the context; event results carry structured subsystem, device code, trace ID, and bounded message text.Firmware fault, timeout, stale calibration, cancellation, and incompatibility map consistently across backends.
VersioningThe caller initializes struct_size and api_version; the library copies input strings and ignores compatible unknown trailing fields.Old header/new library and new header/old library compatibility matrix plus malformed-size tests.
Tensor bindingExecutable metadata fixes input/output index, name, type, shape, and byte size. Every binding validates index, offset, size, and memory compatibility before enqueue.Wrong type/shape/order, undersized buffer, overlap, and stale-handle tests fail before device work begins.
Device stateThe trusted .acal bundle is signature-, family-, schema-, age-, and temperature-checked before executable load and programming.Wrong serial/family, expired calibration, revoked signature, and remap-capacity failures are reason-coded.
Memoryv0 exposes allocated host-visible, pinned, and device-local buffers with blocking read/write convenience calls. Zero-copy import is added only with explicit ownership, coherence, and synchronization rules.Alignment, bounds, DMA direction, cache maintenance, and IOMMU isolation tests.
CancellationCancellation is best-effort and reports whether execution stopped, completed, or required reset.Cancel before dispatch, during DMA, during MVM, and after completion.

Python should expose the same lifecycle without hiding events or reports

Python compile and runOne obvious path from ONNX to a simulator or device
from acim_sdk import Compiler, CompileOptions, Context, TargetProfile

target = TargetProfile.load("targets/rev_b.atarget", "targets/rev_b.achar")
compiler = Compiler(target)

artifact, report = compiler.compile_onnx(
    "models/linear.onnx",
    model_calibration="build/linear.qcal",
    options=CompileOptions(
        accuracy_budget=0.005,
        latency_target_us=100,
        allow_digital_fallback=True,
        save_intermediate_ir="build/ir",
    ),
)
artifact.save("build/linear.acx")
report.save("build/linear.compile.json")

with Context(backend="functional") as context:
    device = context.open_device(0)
    session = device.load("build/linear.acx")
    output = session.run({"input": input_tensor})

with Context(backend="device") as context:
    device = context.open_device(0)
    session = device.load("build/linear.acx")
    event = session.submit({"input": input_tensor})
    output = event.result(timeout=1.0)
    event.trace().save("build/linear.atrace")

HAL and backends

Make simulation and silicon execute the same artifact through the same internal interface

C++ HAL boundaryInternal interface; the C ABI remains the public contract
class Device {
 public:
  virtual ~Device() = default;
  virtual StatusOr<Capabilities> QueryCapabilities() = 0;
  virtual Status BindDeviceState(const DeviceState&) = 0;
  virtual StatusOr<ExecutableHandle> Load(const Artifact&) = 0;
  virtual StatusOr<BufferHandle> Allocate(const BufferDesc&) = 0;
  virtual StatusOr<EventHandle> Submit(
      QueueId, ExecutableHandle, Span<BufferBinding>, const RunPolicy&) = 0;
  virtual Status Wait(EventHandle, Duration timeout) = 0;
  virtual StatusOr<Trace> ReadTrace(EventHandle) = 0;
  virtual Status Recover(const RecoveryRequest&) = 0;
};

class Backend {
 public:
  virtual ~Backend() = default;
  virtual StatusOr<std::vector<DeviceInfo>> Enumerate() = 0;
  virtual StatusOr<std::unique_ptr<Device>> Open(DeviceId) = 0;
};
BackendPurposeMust modelMust not claimExit criterion
FunctionalBring up artifact, commands, memory, and exact quantized semantics quickly.Shapes, types, saturation, rounding, slices, reconstruction, dependencies, fallbackAnalog accuracy, timing, energy, area, or silicon behaviorBit-exact against quantized reference for every supported operation
Statistical analogStudy accuracy sensitivity and hardware-aware training.Programming error, noise, ADC/DAC bounds, drift, IR drop, sign mapping, variation distributionsCycle latency or full-chip energy unless explicitly modeled and correlatedError distributions match held-out device traces within declared confidence
Cycle/resourcePredict schedule, utilization, queueing, bandwidth, latency, and energy components.Firmware phases, SRAM/NoC, converters, DMA, overlap, contention, fallback, countersTask accuracy beyond inputs supplied by the numerical modelKernel and model timelines correlate with RTL/C++ model and silicon measurements
HardwareExecute on the real driver/firmware/device stack.All ABI validation, memory, queues, calibration binding, faults, telemetry, recoverySupport not present in the queried firmware/device capabilitiesSame artifact passes differential, stress, PVT, reset, and long-run tests

Adapter strategy: after license and dependency review, use AIHWKit or CrossSim behind the statistical backend, not as the public SDK. Translate the target characterization into their parameters and retain the adapter/version in every report so results remain reproducible when those projects evolve.

Executable format

Use a schema with explicit compatibility rules, not an opaque binary blob

Illustrative FlatBuffer schemaProposed minimum; field IDs protect parallel schema evolution
namespace acim.artifact;

table Version {
  major:ushort (id: 0);
  minor:ushort (id: 1);
  patch:uint   (id: 2);
}

table TargetRequirements {
  device_family:string        (id: 0);
  revision_min:uint           (id: 1);
  revision_max:uint           (id: 2);
  firmware_abi:Version        (id: 3);
  calibration_schema:Version (id: 4);
  characterization_hash:[ubyte] (id: 5);
  required_features:[string]  (id: 6);
}

table Executable {
  schema:Version                    (id: 0);
  build_id:string                   (id: 1);
  model_hash:[ubyte]                (id: 2);
  target:TargetRequirements         (id: 3);
  graph:[ubyte]                     (id: 4);
  constants:[ubyte]                 (id: 5);
  weight_program:[ubyte]            (id: 6);
  command_streams:[ubyte]           (id: 7);
  digital_kernels:[ubyte]           (id: 8);
  memory_plan:[ubyte]               (id: 9);
  numerical_contract:[ubyte]        (id: 10);
  recovery_policy:[ubyte]           (id: 11);
  debug_map:[ubyte]                 (id: 12);
  compile_report:[ubyte]            (id: 13);
  signature:[ubyte]                 (id: 14);
}

root_type Executable;
file_identifier "ACIX";
Compatibility ruleRequired behavior
Schema majorMismatch is rejected unless an explicit offline converter exists.
Schema minorReaders accept older compatible fields; optional new fields use defaults and feature checks.
Firmware ABIMajor must match; minor compatibility follows queried feature/opcode support.
Target revisionMust fall in the compiled range and expose every required physical capability.
CharacterizationHash must be recognized by the runtime policy; unknown or revoked profiles require recompile.
Device stateCalibration schema, device family, serial signature, age, and temperature policy are checked at load.
Schema CIRun flatc --conform against the previous released schema and round-trip old artifacts.
SecurityVerify hashes/signatures before programming; firmware independently validates every descriptor and bound.

Runtime and firmware

Make state transitions and recovery observable

ClosedNo ownershipDevice handle absent; no mapped memory or pending work.
DiscoveredCapabilities knownRevision, ABI, features, memory, and health queried.
BoundCalibration acceptedDevice state signature, age, temperature, and remaps valid.
LoadedExecutable readyResources allocated; weights programmed and verified.
RunningQueues activeRequests execute asynchronously with trace correlation.
DegradedRecovery requiredRepeat, remap, recalibrate, refresh, fallback, reset, or fail.
Command classExamplesFirmware validationCompletion evidence
MemoryDMA copy, fill, bind, releaseIOMMU handle, bounds, alignment, direction, overlap, lifetimeBytes, cycles, fault address, queue/event IDs
Weight lifecycleErase, program, verify, commit, rollbackArray ownership, recipe ID, voltage/current limits, endurance policy, transaction stateProgram distribution, retries, failed cells, remap, image hash
ComputeInput encode, MVM phase, ADC read, reconstruct, digital kernelArray/range/mode support, current bound, dependencies, buffers, calibration classPhases, saturation, ADC range, cycles, output checksum
HealthRead sensors, self-test, calibrate, refreshPrivilege, idle state, thermal and power envelope, accepted procedure versionCalibration ID, temperature, weak resources, health vector, expiry
ControlBarrier, event, cancel, timeout, resetQueue ownership, dependency validity, safe reset point, outstanding DMA/programmingFinal state, canceled/completed work, data validity, reset reason

Framework integration

Add framework plugins only after the standalone contract works

StageIntegrationWhat to implementWhy this order
MVPStandalone ONNX CLI and Python compilerChecker, shape inference, MatMul/Gemm import, static shapes, compile, inspect, runSmallest dependency surface; deterministic artifacts; easy golden testing
Stage 2ONNX Runtime plugin EPGetCapability, Compile, allocator/stream if needed, compatibility info, session optionsProvides heterogeneous CPU fallback and a production application API without owning the whole framework
Stage 3PyTorch export through ONNXDocument supported export profile, dynamic-shape limits, QDQ handling, and reproducible model preprocessingReuses the proven ONNX path instead of creating a second importer
Stage 4StableHLO/PJRT pluginPJRT C API client/device/buffer/executable/event behavior and StableHLO compiler entryUseful for JAX/PyTorch-XLA, but larger ABI, async, sharding, and packaging surface

Since ONNX Runtime 1.23, its official guidance is to implement a new provider as a plugin EP. The separate plugin development contract asks GetCapability() which graph regions are supported and Compile() to produce executable compute functions, while another provider can handle fallback. That is a good second integration after the standalone compiler is stable.

Execution Provider responsibilitiesKeep the plugin thin
GetCapability(graph, target):
  validate shapes and dtypes
  ask libacim_compiler for legal candidate regions
  subtract regions whose boundary cost or error budget fails
  return reason-coded supported subgraphs

Compile(subgraphs):
  compile each accepted subgraph to .acx bytes
  retain compatibility metadata and cache key
  create compute callback that calls the public acim runtime API

Compute(inputs, outputs):
  bind ORT buffers or copy through declared memory rules
  submit asynchronously where the EP contract permits
  translate acim status/faults to ORT status
  never implement quantization, mapping, or driver logic in the EP

First buildable vertical slice

Prove one exact MatMul from ONNX to artifact to simulator

Start with [1,128] x [128,64], INT8 inputs and weights, INT32 accumulation, static shapes, no analog noise, one functional backend, and no framework plugin. This deliberately tests software contracts before physical fidelity.

1Create ONNX modelKnown constants and reference output
2Import to MLIRValidated shape and MVM semantics
3Lower planQuant contract and logical slices
4Map virtual arrayOne target descriptor, no faults
5Serialize .acxVersion, program, commands, debug map
6Run functional HALPublic C API, buffers, queue, event
7Compare and traceBit-exact output and inspectable evidence
Developer loopCommands the repository should support before adding Conv or hardware
cmake -G Ninja -S . -B build \
  -DACIM_ENABLE_ONNX=ON \
  -DACIM_ENABLE_FUNCTIONAL_BACKEND=ON
cmake --build build
ctest --test-dir build --output-on-failure

python examples/matmul/create_model.py --output build/matmul.onnx
acim-compile build/matmul.onnx \
  --target testdata/virtual.atarget \
  --characterization testdata/ideal.achar \
  --emit-ir build/ir \
  --report build/matmul.compile.json \
  -o build/matmul.acx

acim-inspect build/matmul.acx --all
acim-run build/matmul.acx \
  --backend functional \
  --inputs testdata/matmul_input.npz \
  --golden testdata/matmul_golden.npz \
  --trace build/matmul.atrace
acim-profile build/matmul.atrace --summary

Definition of done: a clean checkout builds without device hardware; the same .acx is inspected and executed through the public C API; output is bit-exact; malformed artifacts and incompatible targets fail with stable status codes; IR, compile report, command list, and trace IDs identify the original ONNX node.

Second vertical slice: extend this exact artifact and HAL with capability, live-health, calibration, binding, and topology epochs. Compile row- and column-parallel linear variants, bind around injected row/column/tile faults, execute collectives on a fake AcimMesh, and recover from one link failure. The scale-out implementation plan defines the schemas, sequence, and acceptance metrics.

Physical-board vertical slice: the PCIe board bring-up guide implements the hardware HAL boundary with host/device requirements, UMD and KMD APIs, BAR and queue schemas, DMA/MSI-X ordering, firmware boot, analog program/verify, and a staged YOLO path.

Profiling vertical slice: the host Tracy and device cycle-trace guide defines optional CMake integration, scoped host zones, a firmware-safe trace ABI, UMD/KMD drain ownership, clock correlation, ACiM counters, profiling modes, and measurement gates.

Implementation roadmap

Expand only after each boundary has an executable test

0 / 10 complete

Testing and CI

Separate fast deterministic gates from statistical and hardware qualification

CI laneRunsRequired evidenceFailure blocks
Every changeFormatting, static analysis, schema conform, unit tests, IR verifier, exact golden operationsDeterministic logs, seeds, artifacts, and compiler pass failuresMerge
Nightly simulatorModel corpus, statistical sweeps, cycle/resource regressions, memory/concurrency stressAccuracy distributions, latency/energy deltas, coverage, first divergenceRelease candidate
Hardware presubmitSmall device pool, load/run/reset, firmware compatibility, differential ops, telemetryDevice IDs, firmware/calibration versions, traces, fault and reset reportsHardware-facing merge
QualificationChip/lot population, PVT, thermal cycling, drift, retention, endurance, long-run service loadMean/tails, rejected devices, remap, recalibration, recovery, accuracy and performance distributionsProduct release
BenchmarkSame application path for accuracy and performance, single-stream and throughput scenariosComplete system configuration, preprocessing, datasets, calibration, power, latency percentilesPublished claim
CorrectnessExact before approximate

Functional backend must be bit-exact before analog tolerance is introduced.

ReproducibilityHash every input

Model, data, target, characterization, compiler, schema, seed, and device state.

CorrelationFirst divergent boundary

Framework, quantized, statistical, cycle, RTL/C++, firmware, and silicon checkpoints.

PerformanceMeasure end to end

Programming, conversion, fallback, memory, NoC, host, idle, and recovery costs.

Primary references and explicit limits

Use these projects for contracts and evidence, not as proof of an iHW implementation

TT-MLIR architectureOfficial high-level and target dialect layering used as a compiler-structure reference.
TT-MLIR optimizerOfficial legal-layout, operation-model, memory-layout, and configuration-search concepts.
Tenstorrent ttrtOfficial artifact inspect/run/check/perf/debug and strict-versioning workflow.
MLIR ODSOfficial declarative operation, attribute, verifier, parser, printer, and generated-code specification.
ONNX checkerOfficial model validation API used before import.
ONNX Runtime plugin EPOfficial provider discovery, capability, compile, allocator, stream, compatibility, and concurrency contracts.
PJRT plugin integrationOfficial C API integration and testing path; recommended here only after the MVP and ORT integration.
IREE HAL driver designOfficial driver/device/buffer/executable/command-buffer/event/semaphore structure used as a HAL reference.
IBM AIHWKitOpen-source analog numerical simulation, ADC/DAC bounds, noise, mapping, and hardware-aware training.
Sandia CrossSimOpen-source crossbar accuracy simulation with device, ADC, parasitic, slicing, sign, and array-size models; explicitly not a speed/energy/area model.
MLPerf Inference rulesPrimary reference for system-under-test, quality, latency/throughput scenarios, reproducibility, and audit boundaries.
iHW patent studyPatent mechanisms and evidence limits that motivate, but do not disclose, this software design.
Tenstorrent pattern studyApplied architecture translation from model import through compiler, runtime, simulator, device control and correlation labs.
PCIe board bring-up guideConcrete UMD/KMD, BAR, DMA, MSI-X, firmware, analog lifecycle, YOLO dataflow, recovery, security, and validation contracts.
ACiM scale-out and LLM designFault-aware descriptors, logical mesh, distributed placement, hybrid LLM mapping, recovery, and the second vertical slice.