From 2b201c340788ac582cec160b7217c2b5405b04f9 Mon Sep 17 00:00:00 2001 From: Kristofer Jonsson Date: Wed, 2 Sep 2020 16:42:43 +0200 Subject: Move fast memory area to core driver Change-Id: Ie4186f5ab881d5c13021299404322ff582180d26 --- src/ethosu_driver.c | 216 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 135 insertions(+), 81 deletions(-) (limited to 'src/ethosu_driver.c') diff --git a/src/ethosu_driver.c b/src/ethosu_driver.c index 702edb4..4398d33 100644 --- a/src/ethosu_driver.c +++ b/src/ethosu_driver.c @@ -16,6 +16,10 @@ * limitations under the License. */ +/****************************************************************************** + * Includes + ******************************************************************************/ + #include "ethosu_driver.h" #include "ethosu_common.h" #include "ethosu_config.h" @@ -29,70 +33,9 @@ #include #include -struct ethosu_driver ethosu_drv = { - .dev = {.base_address = NULL, .pmccntr = 0, .pmu_evcntr = {0, 0, 0, 0}, .pmu_evtypr = {0, 0, 0, 0}}, - .abort_inference = false}; - -// IRQ -static volatile bool irq_triggered = false; -#if defined(CPU_CORTEX_M3) || defined(CPU_CORTEX_M4) || defined(CPU_CORTEX_M7) || defined(CPU_CORTEX_M33) || \ - defined(CPU_CORTEX_M55) -void ethosu_irq_handler(void) -{ - uint8_t irq_raised = 0; - - LOG_DEBUG("Interrupt. status=0x%08x, qread=%d\n", - ethosu_read_reg(ðosu_drv.dev, NPU_REG_STATUS), - ethosu_read_reg(ðosu_drv.dev, NPU_REG_QREAD)); - - // Verify that interrupt has been raised - (void)ethosu_is_irq_raised(ðosu_drv.dev, &irq_raised); - ASSERT(irq_raised == 1); - irq_triggered = true; - - // Clear interrupt - (void)ethosu_clear_irq_status(ðosu_drv.dev); - - // Verify that interrupt has been successfully cleard - (void)ethosu_is_irq_raised(ðosu_drv.dev, &irq_raised); - ASSERT(irq_raised == 0); -} - -static inline void wait_for_irq(struct ethosu_driver *drv) -{ - while (1) - { - __disable_irq(); - if (irq_triggered || drv->abort_inference) - { - __enable_irq(); - break; - } - - __WFI(); - - __enable_irq(); - } -} -#else -// Just polling the status register -static inline void wait_for_irq(struct ethosu_driver *drv) -{ - uint8_t irq_raised = 0; - - for (int i = 0; i < 5000; ++i) - { - (void)ethosu_is_irq_raised(&drv->dev, &irq_raised); - if (1 == irq_raised) - { - break; - } - } - ASSERT(1 == irq_raised); - - irq_triggered = true; -} -#endif +/****************************************************************************** + * Defines + ******************************************************************************/ #define MACS_PER_CYCLE_LOG2_MASK 0x000F #define SHRAM_SIZE_MASK 0xFF00 @@ -107,6 +50,11 @@ static inline void wait_for_irq(struct ethosu_driver *drv) #define BYTES_1KB 1024 #define PRODUCT_MAJOR_ETHOSU55 (4) #define MASK_16_BYTE_ALIGN (0xF) +#define FAST_MEMORY_BASE_ADDR_INDEX 2 + +/****************************************************************************** + * Types + ******************************************************************************/ // Driver actions enum DRIVER_ACTION_e @@ -129,29 +77,38 @@ struct custom_data_s { // Driver action command (valid values in DRIVER_ACTION_e) uint8_t driver_action_command; + // reserved uint8_t reserved; + // Driver action data union { + // DA_CMD_OPT_CFG struct - { // DA_CMD_OPT_CFG + { uint16_t rel_nbr : 4; uint16_t patch_nbr : 4; uint16_t opt_cfg_reserved : 8; }; + + // DA_CMD_CMSTRM struct - { // DA_CMD_CMSTRM + { uint16_t length; }; + + // DA_CMD_READAPB struct - { // DA_CMD_READAPB + { uint16_t start_address : 12; uint16_t nbr_reg_minus1 : 4; }; + uint16_t driver_action_data; }; }; + uint32_t word; }; }; @@ -187,6 +144,75 @@ struct opt_cfg_s }; }; +/****************************************************************************** + * Functions + ******************************************************************************/ + +struct ethosu_driver ethosu_drv = { + .dev = {.base_address = NULL, .pmccntr = 0, .pmu_evcntr = {0, 0, 0, 0}, .pmu_evtypr = {0, 0, 0, 0}}, + .abort_inference = false}; + +// IRQ +static volatile bool irq_triggered = false; +#if defined(CPU_CORTEX_M3) || defined(CPU_CORTEX_M4) || defined(CPU_CORTEX_M7) || defined(CPU_CORTEX_M33) || \ + defined(CPU_CORTEX_M55) +void ethosu_irq_handler(void) +{ + uint8_t irq_raised = 0; + + LOG_DEBUG("Interrupt. status=0x%08x, qread=%d\n", + ethosu_read_reg(ðosu_drv.dev, NPU_REG_STATUS), + ethosu_read_reg(ðosu_drv.dev, NPU_REG_QREAD)); + + // Verify that interrupt has been raised + (void)ethosu_is_irq_raised(ðosu_drv.dev, &irq_raised); + ASSERT(irq_raised == 1); + irq_triggered = true; + + // Clear interrupt + (void)ethosu_clear_irq_status(ðosu_drv.dev); + + // Verify that interrupt has been successfully cleard + (void)ethosu_is_irq_raised(ðosu_drv.dev, &irq_raised); + ASSERT(irq_raised == 0); +} + +static inline void wait_for_irq(struct ethosu_driver *drv) +{ + while (1) + { + __disable_irq(); + if (irq_triggered || drv->abort_inference) + { + __enable_irq(); + break; + } + + __WFI(); + + __enable_irq(); + } +} +#else +// Just polling the status register +static inline void wait_for_irq(struct ethosu_driver *drv) +{ + uint8_t irq_raised = 0; + + for (int i = 0; i < 5000; ++i) + { + (void)ethosu_is_irq_raised(&drv->dev, &irq_raised); + if (1 == irq_raised) + { + break; + } + } + ASSERT(1 == irq_raised); + + irq_triggered = true; +} +#endif + static int handle_optimizer_config(struct ethosu_driver *drv, struct opt_cfg_s *opt_cfg_p); static int handle_command_stream(struct ethosu_driver *drv, const uint8_t *cmd_stream, @@ -199,11 +225,18 @@ static void dump_npu_register(struct ethosu_driver *drv, int npu_reg, int npu_re static void dump_command_stream(const uint32_t *cmd_stream, const int cms_length, int qread); static void npu_axi_init(struct ethosu_driver *drv); -int ethosu_init(const void *base_address) +int ethosu_init_v2(const void *base_address, const void *fast_memory, const size_t fast_memory_size) { int return_code = 0; - LOG_INFO("ethosu_init calling NPU embed driver ethosu_dev_init\n"); + LOG_INFO("%s. base_address=%p, fast_memory=%p, fast_memory_size=%zu\n", + __FUNCTION__, + base_address, + fast_memory, + fast_memory_size); + + ethosu_drv.fast_memory = (uint64_t)fast_memory; + ethosu_drv.fast_memory_size = fast_memory_size; if (ETHOSU_SUCCESS != ethosu_dev_init(ðosu_drv.dev, base_address)) { @@ -261,37 +294,56 @@ int ethosu_get_version(struct ethosu_version *version) return return_code; } -int ethosu_invoke(const void *custom_data_ptr, - const int custom_data_size, - const uint64_t *base_addr, - const int num_base_addr) +int ethosu_invoke_v2(const void *custom_data_ptr, + const int custom_data_size, + const uint64_t *base_addr, + const size_t *base_addr_size, + const int num_base_addr) { - struct custom_data_s *data_start_ptr = (struct custom_data_s *)custom_data_ptr; + const struct custom_data_s *data_ptr = custom_data_ptr; + const struct custom_data_s *data_end = custom_data_ptr + custom_data_size; int return_code = 0; - LOG_INFO("ethosu_invoke\n"); + LOG_INFO("%s\n", __FUNCTION__); // First word in custom_data_ptr should contain "Custom Operator Payload 1" - if (data_start_ptr->word != ETHOSU_FOURCC) + if (data_ptr->word != ETHOSU_FOURCC) { - LOG_ERR("Custom Operator Payload: %x is not correct, expected %x\n", data_start_ptr->word, ETHOSU_FOURCC); + LOG_ERR("Custom Operator Payload: %x is not correct, expected %x\n", data_ptr->word, ETHOSU_FOURCC); return -1; } - data_start_ptr += CUSTOM_OPTION_LENGTH_32_BIT_WORD; - struct custom_data_s *data_ptr = data_start_ptr; + // Custom data length must be a multiple of 32 bits if ((custom_data_size % BYTES_IN_32_BITS) != 0) { LOG_ERR("ethosu_invoke ERROR custom_data_size=0x%x not a multiple of 4\n", custom_data_size); return -1; } - int custom_data_32bit_size = (custom_data_size / BYTES_IN_32_BITS - CUSTOM_OPTION_LENGTH_32_BIT_WORD); + + ++data_ptr; + + // Adjust base address to fast memory area + if (ethosu_drv.fast_memory != NULL && num_base_addr >= FAST_MEMORY_BASE_ADDR_INDEX) + { + uint64_t *fast_memory = (uint64_t *)&base_addr[FAST_MEMORY_BASE_ADDR_INDEX]; + + if (base_addr_size != NULL && base_addr_size[FAST_MEMORY_BASE_ADDR_INDEX] > ethosu_drv.fast_memory_size) + { + LOG_WARN("Fast memory area too small. fast_memory_size=%u, base_addr_size=%u\n", + ethosu_drv.fast_memory_size, + base_addr_size[FAST_MEMORY_BASE_ADDR_INDEX]); + } + else + { + *fast_memory = ethosu_drv.fast_memory; + } + } ethosu_soft_reset(ðosu_drv.dev); ethosu_set_clock_and_power(ðosu_drv.dev, ETHOSU_CLOCK_Q_ENABLE, ETHOSU_POWER_Q_DISABLE); ethosu_restore_pmu_config(ðosu_drv.dev); - while (data_ptr < (data_start_ptr + custom_data_32bit_size)) + while (data_ptr < data_end) { int ret = 0; switch (data_ptr->driver_action_command) @@ -352,8 +404,10 @@ int ethosu_invoke(const void *custom_data_ptr, break; } } + ethosu_save_pmu_config(ðosu_drv.dev); ethosu_set_clock_and_power(ðosu_drv.dev, ETHOSU_CLOCK_Q_ENABLE, ETHOSU_POWER_Q_ENABLE); + return return_code; } -- cgit v1.2.1