Skip to content

Commit 812c7f0

Browse files
authored
Arm backend: Various build fixes (#21641)
- Set ET_ARM_BAREMETAL_FAST_SCRATCH_TEMP_ALLOCATOR_POOL_SIZE depending on Dedicated_Sram configuration. - Refactor linker scripts to allow NOLOAD on zero-initialized sections, reducing built binary size. - Add functional output sections: - .sram.rodata / .ddr.rodata for constant data. - .sram.bss / rename ddr_noload ->.ddr.bss for memory arenas. These sections are NOLOAD. - Add rom_model PHDR so model data has its own load segment. - Change .heap and .stack from COPY to NOLOAD. - Move input sections: - network_model_sec: .sram/.ddr -> .sram.rodata/.ddr.rodata - .bss.tensor_arena: .sram.bss/.ddr -> .sram.bss/.ddr.bss - Make generated embedded PTE data const. cc @digantdesai @freddan80 @per @zingo @oscarandersson8218 @mansnils @Sebastian-Larsson @robell @rascani Signed-off-by: Erik Lundell <erik.lundell@arm.com>
1 parent 70594d3 commit 812c7f0

7 files changed

Lines changed: 123 additions & 59 deletions

File tree

backends/arm/scripts/corstone_utils.cmake

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,36 @@ function(fetch_ethos_u_content ETHOS_SDK_PATH ET_DIR_PATH)
7878
)
7979
endfunction()
8080

81+
function(set_ethosu_dedicated_sram_fast_scratch_size OUT_VAR MEMORY_MODE)
82+
if("${MEMORY_MODE}" STREQUAL "Dedicated_Sram")
83+
set(${OUT_VAR}
84+
0x60000
85+
PARENT_SCOPE
86+
)
87+
return()
88+
endif()
89+
90+
if(NOT "${MEMORY_MODE}" MATCHES "^Dedicated_Sram_([0-9]+)(KB|MB)$")
91+
message(
92+
FATAL_ERROR
93+
"Unsupported Dedicated_Sram MEMORY_MODE ${MEMORY_MODE}. Expected Dedicated_Sram_<size>KB, Dedicated_Sram_<size>MB, or Dedicated_Sram."
94+
)
95+
endif()
96+
97+
set(_fast_scratch_value "${CMAKE_MATCH_1}")
98+
set(_fast_scratch_unit "${CMAKE_MATCH_2}")
99+
if(_fast_scratch_unit STREQUAL "KB")
100+
math(EXPR _fast_scratch_size "${_fast_scratch_value} * 1024")
101+
else()
102+
math(EXPR _fast_scratch_size "${_fast_scratch_value} * 1024 * 1024")
103+
endif()
104+
105+
set(${OUT_VAR}
106+
${_fast_scratch_size}
107+
PARENT_SCOPE
108+
)
109+
endfunction()
110+
81111
function(add_corstone_subdirectory SYSTEM_CONFIG ETHOS_SDK_PATH)
82112
if(SYSTEM_CONFIG MATCHES "Ethos_U55" OR SYSTEM_CONFIG MATCHES "Ethos_U65")
83113
add_subdirectory(
@@ -90,11 +120,29 @@ function(add_corstone_subdirectory SYSTEM_CONFIG ETHOS_SDK_PATH)
90120
else()
91121
message(FATAL_ERROR "Unsupported SYSTEM_CONFIG ${SYSTEM_CONFIG}.")
92122
endif()
93-
if(MEMORY_MODE MATCHES "Dedicated_Sram")
123+
if(MEMORY_MODE MATCHES "^Dedicated_Sram($|_)")
124+
# Both model and scratch in DRAM.
125+
set(ETHOSU_MODEL
126+
1
127+
PARENT_SCOPE
128+
)
129+
set(ETHOSU_ARENA
130+
1
131+
PARENT_SCOPE
132+
)
94133
target_compile_definitions(
95134
ethosu_target_common INTERFACE ETHOSU_MODEL=1 ETHOSU_ARENA=1
96135
)
97136
elseif(MEMORY_MODE MATCHES "Shared_Sram" OR MEMORY_MODE MATCHES "Sram_Only")
137+
# Model in DRAM, scratch in SRAM.
138+
set(ETHOSU_MODEL
139+
1
140+
PARENT_SCOPE
141+
)
142+
set(ETHOSU_ARENA
143+
0
144+
PARENT_SCOPE
145+
)
98146
target_compile_definitions(
99147
ethosu_target_common INTERFACE ETHOSU_MODEL=1 ETHOSU_ARENA=0
100148
)
@@ -341,7 +389,7 @@ function(configure_timing_adapters SYSTEM_CONFIG MEMORY_MODE)
341389
ETHOSU_TA_HISTBIN_1=0
342390
ETHOSU_TA_HISTCNT_1=0
343391
)
344-
elseif(MEMORY_MODE MATCHES "Dedicated_Sram")
392+
elseif(MEMORY_MODE MATCHES "^Dedicated_Sram($|_)")
345393
target_compile_definitions(
346394
ethosu_target_common
347395
INTERFACE # Configure NPU architecture timing adapters This is just
@@ -389,7 +437,7 @@ function(configure_timing_adapters SYSTEM_CONFIG MEMORY_MODE)
389437
"corstone-320"
390438
PARENT_SCOPE
391439
)
392-
if(MEMORY_MODE MATCHES "Dedicated_Sram")
440+
if(MEMORY_MODE MATCHES "^Dedicated_Sram($|_)")
393441
target_compile_definitions(
394442
ethosu_target_common
395443
INTERFACE # Configure NPU architecture timing adapters This is just
@@ -465,7 +513,7 @@ function(configure_timing_adapters SYSTEM_CONFIG MEMORY_MODE)
465513
"corstone-320"
466514
PARENT_SCOPE
467515
)
468-
if(MEMORY_MODE MATCHES "Dedicated_Sram")
516+
if(MEMORY_MODE MATCHES "^Dedicated_Sram($|_)")
469517
target_compile_definitions(
470518
ethosu_target_common
471519
INTERFACE # Configure NPU architecture timing adapters This is just
@@ -577,7 +625,7 @@ function(configure_timing_adapters SYSTEM_CONFIG MEMORY_MODE)
577625
NPU_REGIONCFG_6=0
578626
NPU_REGIONCFG_7=0
579627
)
580-
elseif(MEMORY_MODE MATCHES "Dedicated_Sram")
628+
elseif(MEMORY_MODE MATCHES "^Dedicated_Sram($|_)")
581629
target_compile_definitions(
582630
ethosu_core_driver
583631
PRIVATE NPU_QCONFIG=3

examples/arm/ethos-u-porting-guide.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,17 @@ expected to place the scratch buffer and NN in the correct memory location.
8585
For example, if you generate a pte file with compile specification for Shared Sram, the scratch buffer should be placed in the SRAM and the NN in the external memory in the runtime application code. You can see we are following
8686
this approach in the `examples/arm/executor_runner/arm_executor_runner.cpp` example application. In the linker scripts for the application(`examples/arm/executor_runner/Corstone-320.ld` and
8787
`examples/arm/executor_runner/Corstone-300.ld`) we check the value of `ETHOSU_ARENA` to determine whether the ethos-u scratch buffer is placed in the on-chip memory or in the external memory. In this
88-
way, depending on the `ETHOSU_ARENA` parameter, the linker knows whether the symbol is to be placed in the .ddr or .sram.bss sections. The `ETHOSU_ARENA` parameter is set in the `backends/arm/scripts/corstone_utils.cmake` and
89-
its value is derived based on the memory mode parameter that is passed to the `examples/arm/run.sh` shell script. Then, at link time, the .ddr section is always placed in the external memory and the .sram.bss is always placed in the SRAM.
88+
way, depending on the `ETHOSU_ARENA` parameter, the linker knows whether the input section is to be placed in the .ddr.bss or .sram.bss sections. The `ETHOSU_ARENA` parameter is set in the `backends/arm/scripts/corstone_utils.cmake` and
89+
its value is derived based on the memory mode parameter that is passed to the `examples/arm/run.sh` shell script. Then, at link time, the .ddr.bss section is always placed in the external memory and the .sram.bss is always placed in the SRAM.
9090
Finally, note that in the `examples/arm/executor_runner/arm_executor_runner.cpp` application code, we place the buffers for the Ethos-u scratch and the neural network in the correct symbol from the linker script. For instance,
91-
the Ethos-u scratch buffer corresponds to the the `.bss.tensor_arena` section in the linker script, In the application code, when we allocate memory for the Ethos-u scratch buffer, we place this array in the .bss.tensor_arena section in the memory map.
91+
the Ethos-u scratch buffer corresponds to the the `.bss.tensor_arena` input section in the linker script, In the application code, when we allocate memory for the Ethos-u scratch buffer, we place this array in the .bss.tensor_arena section in the memory map.
9292

9393
```
9494
unsigned char __attribute__((
9595
section(".bss.tensor_arena"),
9696
aligned(16))) temp_allocation_pool[temp_allocation_pool_size];
9797
```
98-
and the `.bss.tensor_arena` section is placed in the correct location in the memory map thanks to
98+
and the `.bss.tensor_arena` input section is placed in the correct location in the memory map thanks to
9999
the `ETHOSU_ARENA` parameter.
100100

101101
There is a tight coupling between the memory mode for the Ethos-U and the placement of the ethos-u scratch buffer,
@@ -125,4 +125,4 @@ how we populate the input tensor depending on its data type.
125125
The ExecuTorch project already provides an Arm Ethos-U backend in `executorch/backends/arm/runtime/` that you can reuse as is. The key steps to bring up a new platform is to reuse the Ethos-U driver
126126
and ensure that the NPU base address and interrupt assignment matches your SoC. The `examples/arm/executor_runner/arm_executor_runner.cpp` is an example application running on the Corstone platform.
127127
For the `arm_executor_runner.cpp` application, we are relying on the NPU initialization done in the core-platform project and we integrate core-platform in the
128-
`backends/arm/scripts/corstone_utils.cmake` script. Then, we inherit the core-platform integration of the Ethos-U driver and the CMSIS boot code for the Cortex-M core.
128+
`backends/arm/scripts/corstone_utils.cmake` script. Then, we inherit the core-platform integration of the Ethos-U driver and the CMSIS boot code for the Cortex-M core.

examples/arm/executor_runner/CMakeLists.txt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,14 +178,16 @@ message(STATUS "MEMORY_MODE is ${MEMORY_MODE}")
178178
message(STATUS "ET_NUM_INFERENCES is ${ET_NUM_INFERENCES}")
179179

180180
# By default, use 2MB of temporary scratch buffer. For Dedicated_Sram, use 64MB
181-
# for the temporary scratch buffer and 384KB for the fast scratch buffer (the
182-
# cache, applicable only for Ethos-U65 and Ethos-U85). Allow -D overrides.
183-
if(MEMORY_MODE MATCHES "Dedicated_Sram")
181+
# for the temporary scratch buffer and derive the fast scratch buffer size from
182+
# the memory mode suffix, e.g. Dedicated_Sram_384KB. Allow -D overrides.
183+
if(MEMORY_MODE MATCHES "^Dedicated_Sram($|_)")
184184
if(NOT DEFINED ET_ARM_BAREMETAL_SCRATCH_TEMP_ALLOCATOR_POOL_SIZE)
185185
set(ET_ARM_BAREMETAL_SCRATCH_TEMP_ALLOCATOR_POOL_SIZE 0x4000000)
186186
endif()
187187
if(NOT DEFINED ET_ARM_BAREMETAL_FAST_SCRATCH_TEMP_ALLOCATOR_POOL_SIZE)
188-
set(ET_ARM_BAREMETAL_FAST_SCRATCH_TEMP_ALLOCATOR_POOL_SIZE 0x60000)
188+
set_ethosu_dedicated_sram_fast_scratch_size(
189+
ET_ARM_BAREMETAL_FAST_SCRATCH_TEMP_ALLOCATOR_POOL_SIZE "${MEMORY_MODE}"
190+
)
189191
endif()
190192
else()
191193
if(NOT DEFINED ET_ARM_BAREMETAL_SCRATCH_TEMP_ALLOCATOR_POOL_SIZE)
@@ -289,7 +291,9 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
289291
endif()
290292

291293
set(_arm_runner_linker_preprocessor_options ${COMPILER_PREPROCESSOR_OPTIONS})
292-
foreach(_arm_runner_linker_define IN ITEMS HEAP_SIZE STACK_SIZE)
294+
foreach(_arm_runner_linker_define IN ITEMS HEAP_SIZE STACK_SIZE ETHOSU_MODEL
295+
ETHOSU_ARENA
296+
)
293297
if(DEFINED ${_arm_runner_linker_define})
294298
list(APPEND _arm_runner_linker_preprocessor_options
295299
"-D${_arm_runner_linker_define}=${${_arm_runner_linker_define}}"

examples/arm/executor_runner/Corstone-300.ld

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ PHDRS
4949
{
5050
rom_exec PT_LOAD;
5151
rom_dram PT_LOAD;
52+
rom_model PT_LOAD;
5253
null PT_NULL;
5354
}
5455

@@ -208,35 +209,35 @@ SECTIONS
208209
__data_end__ = .;
209210
} > DTCM :rom_exec
210211

211-
.sram.bss :
212+
#if (ETHOSU_MODEL == 0)
213+
.sram.rodata :
212214
{
213215
. = ALIGN(16);
214-
#if (ETHOSU_MODEL == 0)
215-
* (network_model_sec)
216+
*(network_model_sec)
217+
} > SRAM :rom_model
218+
#else
219+
.ddr.rodata :
220+
{
221+
. = ALIGN(16);
222+
*(network_model_sec)
223+
} > DDR :rom_model
216224
#endif
217225

226+
.sram.bss (NOLOAD) :
227+
{
218228
#if (ETHOSU_ARENA == 0)
219229
. = ALIGN(32);
220230
*(.bss.tensor_arena)
221231
#endif
222232
. = ALIGN(16);
223233
*(.bss.ethosu_scratch);
224-
*.(output_data_sec)
225234
} > SRAM :null
226235

227236
.ddr :
228237
{
229-
#if (ETHOSU_ARENA == 1)
230-
. = ALIGN(32);
231-
*(.bss.tensor_arena)
232-
#endif
233-
234238
. = ALIGN(4);
235239
*(input_data_sec)
236240
. = ALIGN(16);
237-
#if (ETHOSU_MODEL == 1)
238-
*(network_model_sec)
239-
#endif
240241
* (expected_output_data_sec)
241242
. = ALIGN(16);
242243
* (sec_command_stream, sec_weight_data, sec_input_data)
@@ -252,12 +253,15 @@ SECTIONS
252253
KEEP(*(.asan_shadow))
253254
__asan_shadow_end = .;
254255
} > DDR :null
255-
.ddr_noload (NOLOAD) :
256+
257+
.ddr.bss (NOLOAD) :
256258
{
257-
. = ALIGN(16);
258-
*(input_data_sec)
259-
. = ALIGN(16);
259+
#if (ETHOSU_ARENA == 1)
260+
. = ALIGN(32);
261+
*(.bss.tensor_arena)
262+
#endif
260263
} > DDR :null
264+
261265
__eddr_data = ALIGN(4);
262266
.sram.data :
263267
{
@@ -288,7 +292,7 @@ SECTIONS
288292
__bss_end__ = .;
289293
} > DTCM :null
290294

291-
.heap (COPY) :
295+
.heap (NOLOAD) :
292296
{
293297
. = ALIGN(8);
294298
__end__ = .;
@@ -298,7 +302,7 @@ SECTIONS
298302
__HeapLimit = .;
299303
} > DTCM :null
300304

301-
.stack (ORIGIN(DTCM) + LENGTH(DTCM) - __STACK_SIZE) (COPY) :
305+
.stack (ORIGIN(DTCM) + LENGTH(DTCM) - __STACK_SIZE) (NOLOAD) :
302306
{
303307
. = ALIGN(8);
304308
__StackLimit = .;

examples/arm/executor_runner/Corstone-320.ld

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2025 Arm Limited and/or its affiliates.
2+
* Copyright 2025-2026 Arm Limited and/or its affiliates.
33
*
44
* This source code is licensed under the BSD-style license found in the
55
* LICENSE file in the root directory of this source tree.
@@ -51,6 +51,7 @@ PHDRS
5151
rom_boot PT_LOAD;
5252
rom_exec PT_LOAD;
5353
rom_dram PT_LOAD;
54+
rom_model PT_LOAD;
5455
null PT_NULL;
5556
}
5657

@@ -188,11 +189,6 @@ SECTIONS
188189

189190
.sram : AT(__etext)
190191
{
191-
#if (ETHOSU_MODEL == 0)
192-
. = ALIGN(16);
193-
*(network_model_sec)
194-
#endif
195-
196192
. = ALIGN(16);
197193
*(.sram.data)
198194

@@ -219,29 +215,32 @@ SECTIONS
219215
KEEP(*(.jcr*))
220216
} > SRAM :rom_dram
221217

222-
.sram.bss :
218+
#if (ETHOSU_MODEL == 0)
219+
.sram.rodata :
220+
{
221+
. = ALIGN(16);
222+
*(network_model_sec)
223+
} > SRAM :rom_model
224+
#else
225+
.ddr.rodata :
226+
{
227+
. = ALIGN(16);
228+
*(network_model_sec)
229+
} > DDR :rom_model
230+
#endif
231+
232+
.sram.bss (NOLOAD) :
223233
{
224234
#if (ETHOSU_ARENA == 0)
225235
. = ALIGN(32);
226236
*(.bss.tensor_arena)
227237
#endif
228-
229238
. = ALIGN(16);
230239
*(.bss.ethosu_scratch);
231240
} > SRAM :null
232241

233242
.ddr :
234243
{
235-
#if (ETHOSU_ARENA == 1)
236-
. = ALIGN(32);
237-
*(.bss.tensor_arena)
238-
#endif
239-
240-
#if (ETHOSU_MODEL == 1)
241-
. = ALIGN(16);
242-
*(network_model_sec)
243-
#endif
244-
245244
. = ALIGN(4);
246245
*(input_data_sec)
247246
*(expected_output_data_sec)
@@ -259,11 +258,15 @@ SECTIONS
259258
KEEP(*(.asan_shadow))
260259
__asan_shadow_end = .;
261260
} > DDR :null
262-
.ddr_noload (NOLOAD) :
261+
262+
.ddr.bss (NOLOAD) :
263263
{
264-
. = ALIGN(16);
265-
*(input_data_sec)
264+
#if (ETHOSU_ARENA == 1)
265+
. = ALIGN(32);
266+
*(.bss.tensor_arena)
267+
#endif
266268
} > DDR :null
269+
267270
.bss :
268271
{
269272
. = ALIGN(4);
@@ -277,7 +280,7 @@ SECTIONS
277280
__bss_end__ = .;
278281
} > BRAM :null
279282

280-
.heap (ORIGIN(BRAM) + LENGTH(BRAM) - __HEAP_SIZE) (COPY) :
283+
.heap (ORIGIN(BRAM) + LENGTH(BRAM) - __HEAP_SIZE) (NOLOAD) :
281284
{
282285
. = ALIGN(8);
283286
__end__ = .;
@@ -287,7 +290,7 @@ SECTIONS
287290
__HeapLimit = .;
288291
} > BRAM :null
289292

290-
.stack (ORIGIN(DTCM) + LENGTH(DTCM) - __STACK_SIZE) (COPY) :
293+
.stack (ORIGIN(DTCM) + LENGTH(DTCM) - __STACK_SIZE) (NOLOAD) :
291294
{
292295
. = ALIGN(8);
293296
__StackLimit = .;

examples/arm/executor_runner/pte_to_header.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ def input_file_path(path):
6060
if __name__ == "__main__":
6161
args = parser.parse_args()
6262
outfile = os.path.join(args.outdir, args.outfile)
63-
attr = f'__attribute__((section("{args.section}"), aligned(16))) unsigned char '
63+
attr = (
64+
f'__attribute__((section("{args.section}"), aligned(16))) '
65+
"const unsigned char "
66+
)
6467

6568
with open(args.pte, "rb") as fr, open(outfile, "w") as fw:
6669
data = fr.read()

examples/arm/mobilesam_prompt_segmentation_example_ethos_u/runtime/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,15 @@ target_link_libraries(
126126
mobilesam_prompt_segmentation_example PUBLIC executorch_delegate_ethos_u
127127
)
128128

129-
if(MEMORY_MODE MATCHES "Dedicated_Sram")
129+
if(MEMORY_MODE MATCHES "^Dedicated_Sram($|_)")
130130
set(ETHOSU_ARENA "1")
131131
if(NOT DEFINED ET_SEGMENTATION_SCRATCH_TEMP_ALLOCATOR_POOL_SIZE)
132132
set(ET_SEGMENTATION_SCRATCH_TEMP_ALLOCATOR_POOL_SIZE 0x1000000)
133133
endif()
134134
if(NOT DEFINED ET_SEGMENTATION_FAST_SCRATCH_TEMP_ALLOCATOR_POOL_SIZE)
135-
set(ET_SEGMENTATION_FAST_SCRATCH_TEMP_ALLOCATOR_POOL_SIZE 0x60000)
135+
set_ethosu_dedicated_sram_fast_scratch_size(
136+
ET_SEGMENTATION_FAST_SCRATCH_TEMP_ALLOCATOR_POOL_SIZE "${MEMORY_MODE}"
137+
)
136138
endif()
137139
else()
138140
set(ETHOSU_ARENA "0")

0 commit comments

Comments
 (0)