Skip to content
heliaAOT
HELIA HUB

ITCM placement

Use ITCM placement when profiling identifies code or tensors worth moving into a target’s instruction tightly coupled memory. Check the registered target and your board’s linker and power configuration first. Code and data share the region: the converter’s tensor budget does not reserve space for linked code.

Item Control Placement owner
Constant, scratch or persistent tensors memory.tensors with memory: ITCM heliaAOT planner and application linker
Constants copied into ITCM at initialization memory: MRAM with constant_destination_memory: ITCM heliaAOT planner and hydration code
Generated operator run code operators[].attributes.code_placement: ITCM heliaAOT code generation and application linker
Kernel-library functions Linker script or code relocation rules Application build

Moving a generated wrapper does not move the kernel function it calls. Measure the resulting firmware before deciding whether the change helps your model.

ITCM is not in the registered targets’ default memory preference order. Include it in memory.constraints to make it available to the planner. This example allows a 128 KiB tensor budget, not a statement of the target’s capacity:

memory:
constraints:
- name: DTCM
- name: SRAM
- name: MRAM
- name: ITCM
max_size: 131072

Use only memory regions exposed by your target. The order gives unpinned tensors their placement preference; putting ITCM last allows eligible tensors to spill there after earlier compatible regions. Reserve room for generated code, library functions and other application sections when choosing max_size. The linker map must fit the combined usage.

For constant weights, choose which code initializes the ITCM storage:

Rule Initialization
memory: ITCM The firmware’s startup code copies the section’s load image into ITCM
memory: MRAM, constant_destination_memory: ITCM Generated model initialization hydrates the destination from the source blob
memory:
tensors:
- type: constant
attributes:
memory: ITCM

For constants staged from MRAM, use this rule instead:

memory:
tensors:
- type: constant
attributes:
memory: MRAM
constant_destination_memory: ITCM

A cold arena remains resident for the firmware’s lifetime. Staging is useful when the application supplies buffers that models reuse in turn. Follow the caller-owned arena contract and initialize each model before it uses the shared buffer.

Scratch and persistent tensors use the same placement mechanism:

memory:
tensors:
- type: scratch
attributes:
memory: ITCM
- type: persistent
attributes:
memory: ITCM

The tensor rules above complement the constraints block; they do not replace it. Check the residency report to see the actual arenas and bytes assigned.

operators:
- type: DILATE
attributes:
code_placement: ITCM

The converter annotates the matching operator’s run declaration with <PREFIX>_PUT_CODE_IN_ITCM. Shared generated helpers receive the annotation when one of their callers requests ITCM. Operator initialization and the model schedule keep their default placement. Library calls still follow the linker script, including compiler-generated calls such as memset.

code_placement accepts ITCM and MRAM. MRAM emits no placement annotation. An unsupported value or a target without ITCM produces a warning and keeps the default placement. The code macro is defined in <prefix>_platform.h and can be overridden:

Module format Default code macro Build requirement
nsx, neuralspot __attribute__((section(".itcm_text"))) The selected linker script must collect this section in ITCM
zephyr __itcm_section The board must configure the zephyr,itcm region
cmake, cmsis_pack Empty Supply a placement definition and matching linker section; conversion warns otherwise

For NSX, the data macros <PREFIX>_PUT_IN_ITCM and <PREFIX>_PUT_IN_ITCM_INIT have no placement default. Supply the module’s attributes header through <MODULE>_ATTRIBUTES_HEADER when placing arenas. The code macro has the default shown above. A planner report alone does not prove either kind of symbol landed in ITCM.

Keep application data and functions in separate source files or distinct sections when using section attributes. Toolchains can reject code and data that share a named section within one source file.

Use the application linker script for kernel-library functions. NSX boards can provide an ITCM-oriented script selected through NSX_LINKER_SCRIPT; inspect its object-name patterns because they may also match generated model code or data outside the planner’s budget. For Zephyr, use the board’s supported code relocation facilities, such as zephyr_code_relocate() with CONFIG_CODE_DATA_RELOCATION.

Check the board SDK’s TCM power and retention configuration. The powered region must cover all placed code and tensors, and data required after sleep must be retained or restored before inference resumes. A linker capacity check cannot establish that the corresponding memory remains powered.

Inspect the final firmware, including symbol addresses and load sections:

Terminal window
arm-none-eabi-nm -n app.axf | grep -E '_run$|arena'
arm-none-eabi-objdump -h app.axf

Compare addresses with the selected board’s memory map. Confirm that arenas have nonzero addresses, startup copies initialized sections correctly, and the combined code/data allocation fits the powered ITCM region. Then validate model outputs on the device and profile the result. Keep the linker map and build settings with the measurement.