diff options
author | Per Åstrand <per.astrand@arm.com> | 2020-10-20 10:29:59 +0200 |
---|---|---|
committer | Per Åstrand <per.astrand@arm.com> | 2020-11-16 10:53:59 +0100 |
commit | 3c8afccabc4622a5e16a2a75474c8c9bb82f248c (patch) | |
tree | 67572fe1cf6f03de25ba2f08b032129136c561d5 /src | |
parent | 4c94b30eb19f168a5e81e27a26c8e25bdab005b1 (diff) | |
download | ethos-u-core-driver-3c8afccabc4622a5e16a2a75474c8c9bb82f248c.tar.gz |
Flush and invalidate data caches
Implement a weak linked function to handle the data cache.
If the specific device is implementing a data cache the function should
be overriden with device specific implementation of the flush/invalidate
functions to make sure that the cache is properly maintained with
regards to the NPU DMA transaction.
Change-Id: I175644ef37bee62cc77d789d2b7bc3073e72ea5a
Diffstat (limited to 'src')
-rw-r--r-- | src/ethosu_driver.c | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/src/ethosu_driver.c b/src/ethosu_driver.c index d21e0a7..014fb54 100644 --- a/src/ethosu_driver.c +++ b/src/ethosu_driver.c @@ -225,6 +225,7 @@ static int handle_command_stream(struct ethosu_driver *drv, const uint8_t *cmd_stream, const int cms_length, const uint64_t *base_addr, + const size_t *base_addr_size, const int num_base_addr); static int read_apb_reg(struct ethosu_driver *drv, uint16_t); static int dump_shram(struct ethosu_driver *drv); @@ -375,7 +376,8 @@ int ethosu_invoke_v2(const void *custom_data_ptr, // It is safe to clear this flag without atomic, because npu is not running. irq_triggered = false; - ret = handle_command_stream(ðosu_drv, command_stream, cms_length, base_addr, num_base_addr); + ret = handle_command_stream( + ðosu_drv, command_stream, cms_length, base_addr, base_addr_size, num_base_addr); if (return_code == -1 && ethosu_drv.abort_inference) { @@ -536,10 +538,29 @@ static void npu_axi_init(struct ethosu_driver *drv) AXI_LIMIT3_MAX_OUTSTANDING_WRITES); } +/* Default implementation to flush the data cache. Override if available on the targeted device. + * Passing NULL as p argument expects the whole cache to be flushed. + */ +void __attribute__((weak)) ethosu_flush_dcache(uint32_t *p, size_t bytes) +{ + (void)p; + (void)bytes; +} + +/* Default implementation to invalidate the data cache. Override if available on the targeted device. + * Passing NULL as p argument expects the whole cache to be flushed. + */ +void __attribute__((weak)) ethosu_invalidate_dcache(uint32_t *p, size_t bytes) +{ + (void)p; + (void)bytes; +} + static int handle_command_stream(struct ethosu_driver *drv, const uint8_t *cmd_stream, const int cms_length, const uint64_t *base_addr, + const size_t *base_addr_size, const int num_base_addr) { uint32_t qread = 0; @@ -567,6 +588,25 @@ static int handle_command_stream(struct ethosu_driver *drv, } npu_axi_init(drv); + /* Flush the cache if available on our CPU. + * The upcasting to uin32_t* is ok since the pointer never is dereferenced. + * The base_addr_size is null if invoking from prior to invoke_V2, in that case + * the whole cache is being flushed. + */ + + if (base_addr_size != NULL) + { + ethosu_flush_dcache((uint32_t *)cmd_stream, cms_bytes); + for (int i = 0; i < num_base_addr; i++) + { + ethosu_flush_dcache((uint32_t *)base_addr[i], base_addr_size[i]); + } + } + else + { + ethosu_flush_dcache(NULL, 0); + } + if (ETHOSU_SUCCESS != ethosu_run_command_stream(&drv->dev, cmd_stream, cms_bytes, base_addr, num_base_addr)) { return -1; @@ -579,6 +619,18 @@ static int handle_command_stream(struct ethosu_driver *drv, return -1; } + if (base_addr_size != NULL) + { + for (int i = 0; i < num_base_addr; i++) + { + ethosu_invalidate_dcache((uint32_t *)base_addr[i], base_addr_size[i]); + } + } + else + { + ethosu_invalidate_dcache(NULL, 0); + } + (void)ethosu_get_qread(&drv->dev, &qread); if (qread != cms_bytes) { |