From da0c2b3ac9bc6e8d612a5d974218738ce647fd05 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Wed, 12 Mar 2025 16:41:47 +0200 Subject: [PATCH] Add ethosu_config_select platform hook Allow config and hence port selection to be done at run-time based on region address, avoiding need to recompile C code for linker map changes, and permitting an application to have one model in SRAM and another in external memory. Change-Id: I425ee1ad2598b65a3c891261a7eff00e9565bdbe Signed-off-by: Kevin Bracey --- include/ethosu_driver.h | 13 ++++++++++ src/ethosu_device_u55_u65.c | 48 +++++++++++++++++++++++-------------- src/ethosu_device_u85.c | 40 +++++++++++++++++++------------ 3 files changed, 68 insertions(+), 33 deletions(-) diff --git a/include/ethosu_driver.h b/include/ethosu_driver.h index 1e71791..9b3428c 100644 --- a/include/ethosu_driver.h +++ b/include/ethosu_driver.h @@ -1,5 +1,6 @@ /* * SPDX-FileCopyrightText: Copyright 2019-2024 Arm Limited and/or its affiliates + * SPDX-FileCopyrightText: Copyright 2025 Alif Semiconductor * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -228,6 +229,18 @@ void ethosu_inference_end(struct ethosu_driver *drv, void *user_arg); */ uint64_t ethosu_address_remap(uint64_t address, int index); +/** + * Select configuration for region access. + * + * Default implementation uses NPU_QCONFIG and NPU_REGIONCFG_n defines. + * + * @param address Address of region. + * @param index -1 command stream, 0-n base address index + * + * @return Configuration to use + */ +unsigned int ethosu_config_select(uint64_t address, int index); + /****************************************************************************** * Prototypes ******************************************************************************/ diff --git a/src/ethosu_device_u55_u65.c b/src/ethosu_device_u55_u65.c index 24e8949..ffd71e1 100644 --- a/src/ethosu_device_u55_u65.c +++ b/src/ethosu_device_u55_u65.c @@ -1,5 +1,6 @@ /* * SPDX-FileCopyrightText: Copyright 2019-2024 Arm Limited and/or its affiliates + * SPDX-FileCopyrightText: Copyright 2025 Alif Semiconductor * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -66,6 +67,25 @@ uint64_t __attribute__((weak)) ethosu_address_remap(uint64_t address, int index) return address; } +unsigned int __attribute__((weak)) ethosu_config_select(uint64_t address, int index) +{ + (void)(address); + assert(index >= -1 && index <= 7); + switch (index) + { + case -1: return NPU_QCONFIG; + default: + case 0: return NPU_REGIONCFG_0; + case 1: return NPU_REGIONCFG_1; + case 2: return NPU_REGIONCFG_2; + case 3: return NPU_REGIONCFG_3; + case 4: return NPU_REGIONCFG_4; + case 5: return NPU_REGIONCFG_5; + case 6: return NPU_REGIONCFG_6; + case 7: return NPU_REGIONCFG_7; + } +} + bool ethosu_dev_init(struct ethosu_device *dev, void *base_address, uint32_t secure_enable, uint32_t privilege_enable) { dev->reg = (volatile struct NPU_REG *)base_address; @@ -93,23 +113,10 @@ bool ethosu_dev_init(struct ethosu_device *dev, void *base_address, uint32_t sec enum ethosu_error_codes ethosu_dev_axi_init(struct ethosu_device *dev) { - struct regioncfg_r rcfg = {0}; - struct axi_limit0_r l0 = {0}; - struct axi_limit1_r l1 = {0}; - struct axi_limit2_r l2 = {0}; - struct axi_limit3_r l3 = {0}; - - dev->reg->QCONFIG.word = NPU_QCONFIG; - - rcfg.region0 = NPU_REGIONCFG_0; - rcfg.region1 = NPU_REGIONCFG_1; - rcfg.region2 = NPU_REGIONCFG_2; - rcfg.region3 = NPU_REGIONCFG_3; - rcfg.region4 = NPU_REGIONCFG_4; - rcfg.region5 = NPU_REGIONCFG_5; - rcfg.region6 = NPU_REGIONCFG_6; - rcfg.region7 = NPU_REGIONCFG_7; - dev->reg->REGIONCFG.word = rcfg.word; + struct axi_limit0_r l0 = {0}; + struct axi_limit1_r l1 = {0}; + struct axi_limit2_r l2 = {0}; + struct axi_limit3_r l3 = {0}; l0.max_beats = AXI_LIMIT0_MAX_BEATS_BYTES; l0.memtype = AXI_LIMIT0_MEM_TYPE; @@ -148,6 +155,7 @@ void ethosu_dev_run_command_stream(struct ethosu_device *dev, assert(num_base_addr <= NPU_REG_BASEP_ARRLEN); struct cmd_r cmd; + struct regioncfg_r rcfg = {0}; uint64_t qbase = ethosu_address_remap((uintptr_t)cmd_stream_ptr, -1); assert(qbase <= ADDRESS_MASK); LOG_DEBUG("QBASE=0x%016llx, QSIZE=%" PRIu32 ", cmd_stream_ptr=%p", qbase, cms_length, cmd_stream_ptr); @@ -156,7 +164,8 @@ void ethosu_dev_run_command_stream(struct ethosu_device *dev, #ifdef ETHOSU65 dev->reg->QBASE.word[1] = qbase >> 32; #endif - dev->reg->QSIZE.word = cms_length; + dev->reg->QSIZE.word = cms_length; + dev->reg->QCONFIG.word = ethosu_config_select(qbase, -1); for (int i = 0; i < num_base_addr; i++) { @@ -167,8 +176,11 @@ void ethosu_dev_run_command_stream(struct ethosu_device *dev, #ifdef ETHOSU65 dev->reg->BASEP[i].word[1] = addr >> 32; #endif + rcfg.word |= ethosu_config_select(addr, i) << (i * 2); } + dev->reg->REGIONCFG.word = rcfg.word; + cmd.word = dev->reg->CMD.word & NPU_CMD_PWR_CLK_MASK; cmd.transition_to_running_state = 1; diff --git a/src/ethosu_device_u85.c b/src/ethosu_device_u85.c index 098320c..79709fe 100644 --- a/src/ethosu_device_u85.c +++ b/src/ethosu_device_u85.c @@ -1,5 +1,6 @@ /* * SPDX-FileCopyrightText: Copyright 2019-2024 Arm Limited and/or its affiliates + * SPDX-FileCopyrightText: Copyright 2025 Alif Semiconductor * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -56,6 +57,25 @@ uint64_t __attribute__((weak)) ethosu_address_remap(uint64_t address, int index) return address; } +unsigned int __attribute__((weak)) ethosu_config_select(uint64_t address, int index) +{ + (void)(address); + assert(index >= -1 && index <= 7); + switch (index) + { + case -1: return NPU_QCONFIG; + default: + case 0: return NPU_REGIONCFG_0; + case 1: return NPU_REGIONCFG_1; + case 2: return NPU_REGIONCFG_2; + case 3: return NPU_REGIONCFG_3; + case 4: return NPU_REGIONCFG_4; + case 5: return NPU_REGIONCFG_5; + case 6: return NPU_REGIONCFG_6; + case 7: return NPU_REGIONCFG_7; + } +} + bool ethosu_dev_init(struct ethosu_device *dev, void *base_address, uint32_t secure_enable, uint32_t privilege_enable) { dev->reg = (volatile struct NPU_REG *)base_address; @@ -79,7 +99,6 @@ bool ethosu_dev_init(struct ethosu_device *dev, void *base_address, uint32_t sec enum ethosu_error_codes ethosu_dev_axi_init(struct ethosu_device *dev) { - struct regioncfg_r rcfg = {0}; struct axi_sram_r axi_s = {0}; struct axi_ext_r axi_e = {0}; @@ -91,20 +110,6 @@ enum ethosu_error_codes ethosu_dev_axi_init(struct ethosu_device *dev) dev->reg->MEM_ATTR[2].word = NPU_MEM_ATTR_2; dev->reg->MEM_ATTR[3].word = NPU_MEM_ATTR_3; - // Set MEM_ATTR entry for command stream - dev->reg->QCONFIG.word = NPU_QCONFIG; - - // Set MEM_ATTR entries to use for regions 0-7 - rcfg.region0 = NPU_REGIONCFG_0; - rcfg.region1 = NPU_REGIONCFG_1; - rcfg.region2 = NPU_REGIONCFG_2; - rcfg.region3 = NPU_REGIONCFG_3; - rcfg.region4 = NPU_REGIONCFG_4; - rcfg.region5 = NPU_REGIONCFG_5; - rcfg.region6 = NPU_REGIONCFG_6; - rcfg.region7 = NPU_REGIONCFG_7; - dev->reg->REGIONCFG.word = rcfg.word; - // Set AXI limits on SRAM AXI interfaces axi_s.max_outstanding_read_m1 = AXI_LIMIT_SRAM_MAX_OUTSTANDING_READ_M1 - 1; axi_s.max_outstanding_write_m1 = AXI_LIMIT_SRAM_MAX_OUTSTANDING_WRITE_M1 - 1; @@ -129,6 +134,7 @@ void ethosu_dev_run_command_stream(struct ethosu_device *dev, assert(num_base_addr <= NPU_REG_BASEP_ARRLEN); struct cmd_r cmd; + struct regioncfg_r rcfg = {0}; uint64_t qbase = ethosu_address_remap((uintptr_t)cmd_stream_ptr, -1); assert(qbase <= ADDRESS_MASK); LOG_DEBUG("QBASE=0x%016llx, QSIZE=%" PRIu32 ", cmd_stream_ptr=%p", qbase, cms_length, cmd_stream_ptr); @@ -136,6 +142,7 @@ void ethosu_dev_run_command_stream(struct ethosu_device *dev, dev->reg->QBASE.word[0] = qbase & 0xffffffff; dev->reg->QBASE.word[1] = qbase >> 32; dev->reg->QSIZE.word = cms_length; + dev->reg->QCONFIG.word = ethosu_config_select(qbase, -1); for (int i = 0; i < num_base_addr; i++) { @@ -144,8 +151,11 @@ void ethosu_dev_run_command_stream(struct ethosu_device *dev, LOG_DEBUG("BASEP%d=0x%016llx", i, addr); dev->reg->BASEP[i].word[0] = addr & 0xffffffff; dev->reg->BASEP[i].word[1] = addr >> 32; + rcfg.word |= ethosu_config_select(addr, i) << (i * 2); } + dev->reg->REGIONCFG.word = rcfg.word; + cmd.word = dev->reg->CMD.word & NPU_CMD_PWR_CLK_MASK; cmd.transition_to_running_state = 1; -- GitLab