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.
Choose what to place
Section titled “Choose what to place”| 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.
Budget tensor memory
Section titled “Budget tensor memory”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: 131072Use 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.
Place tensors
Section titled “Place tensors”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: ITCMFor constants staged from MRAM, use this rule instead:
memory: tensors: - type: constant attributes: memory: MRAM constant_destination_memory: ITCMA 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: ITCMThe tensor rules above complement the constraints block; they do not replace it. Check the residency report to see the actual arenas and bytes assigned.
Place generated code
Section titled “Place generated code”operators: - type: DILATE attributes: code_placement: ITCMThe 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.
Place library code and configure power
Section titled “Place library code and configure power”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.
Verify placement
Section titled “Verify placement”Inspect the final firmware, including symbol addresses and load sections:
arm-none-eabi-nm -n app.axf | grep -E '_run$|arena'arm-none-eabi-objdump -h app.axfCompare 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.