blob: d5f5e4783603b582996af9b26b3fa5fea8521adf [file] [log] [blame]
Kshitij Sisodiac22e80e2022-03-14 09:26:48 +00001/*
Richard Burtonf32a86a2022-11-15 11:46:11 +00002 * SPDX-FileCopyrightText: Copyright 2022 Arm Limited and/or its affiliates <open-source-office@arm.com>
Kshitij Sisodiac22e80e2022-03-14 09:26:48 +00003 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include "ethosu_cpu_cache.h"
19
20#include "RTE_Components.h" /* For CPU related defintiions */
21#include "ethosu_driver.h" /* Arm Ethos-U driver header */
22#include "log_macros.h" /* Logging macros */
23
Kshitij Sisodiade54e162022-12-20 16:09:15 +000024/** Structure to maintain data cache states. */
25typedef struct _cpu_cache_state {
26 uint32_t dcache_invalidated : 1;
27 uint32_t dcache_cleaned : 1;
28} cpu_cache_state;
29
30/** Static CPU cache state object.
31 * @note This logic around flipping these states is based on the driver
32 * calling the functions in this sequence:
33 *
34 * Cache flush (ethosu_flush_dcache)
35 * ↓
36 * Start inference (ethosu_inference_begin)
37 * ↓
38 * Inference (ethosu_dev_run_command_stream)
39 * ↓
40 * End inference (ethosu_inference_end)
41 * ↓
42 * Cache invalidate (ethosu_dcache_invalidate)
43 **/
44static cpu_cache_state s_cache_state = {.dcache_cleaned = 0, .dcache_invalidated = 0};
45
46/**
47 * @brief Gets the current CPU cache state.
48 * @return Pointer to the CPU cache state object.
49 */
50static cpu_cache_state* ethosu_get_cpu_cache_state(void)
51{
52 return &s_cache_state;
53}
54
55void ethosu_clear_cache_states(void)
56{
57 cpu_cache_state* const state = ethosu_get_cpu_cache_state();
58 trace("Clearing cache state members\n");
59 state->dcache_invalidated = 0;
60 state->dcache_cleaned = 0;
61}
62
Kshitij Sisodiac22e80e2022-03-14 09:26:48 +000063void ethosu_flush_dcache(uint32_t *p, size_t bytes)
64{
Kshitij Sisodiac22e80e2022-03-14 09:26:48 +000065 UNUSED(p);
66 UNUSED(bytes);
Kshitij Sisodiade54e162022-12-20 16:09:15 +000067#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
68 cpu_cache_state* const state = ethosu_get_cpu_cache_state();
69 if (SCB->CCR & SCB_CCR_DC_Msk) {
70
71 /**
72 * @note We could choose to call the `SCB_CleanDCache_by_Addr` function
73 * here, but the sizes which this function is called for, can
74 * cause unnecessary delays. It's worth noting that this function
75 * is called from the Arm Ethos-U NPU drive repeatedly for each
76 * region it accesses. This could even be RO memory which does
77 * not need cache maintenance, along with parts of the input and
78 * output tensors which rightly need to be cleaned. Therefore, to
79 * reduce overhead of repeated calls for large memory sizes, we
80 * call the clean and invalidation functions for whole cache.
81 *
82 * If the neural network to be executed is completely falling
83 * onto the NPU, consider disabling the data cache altogether
84 * for the duration of the inference to further reduce the cache
85 * maintenance burden in these functions.
86 */
87
88 /** Clean the cache if it hasn't been cleaned already */
89 if (!state->dcache_cleaned) {
90 trace("Cleaning data cache\n");
91 SCB_CleanDCache();
92
93 /** Assert the cache cleaned state and clear the invalidation
94 * state. */
95 state->dcache_cleaned = 1;
96 state->dcache_invalidated = 0;
97 }
98 }
Kshitij Sisodiac22e80e2022-03-14 09:26:48 +000099#endif /* defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) */
100}
101
102void ethosu_invalidate_dcache(uint32_t *p, size_t bytes)
103{
Kshitij Sisodiac22e80e2022-03-14 09:26:48 +0000104 UNUSED(p);
105 UNUSED(bytes);
Kshitij Sisodiade54e162022-12-20 16:09:15 +0000106#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
107 cpu_cache_state* const state = ethosu_get_cpu_cache_state();
108 if (SCB->CCR & SCB_CCR_DC_Msk) {
109 /**
110 * See note in ethosu_flush_dcache function for why we clean the whole
111 * cache instead of calling it for specific addresses.
112 **/
113 if (!state->dcache_invalidated) {
114 trace("Invalidating data cache\n");
115 SCB_InvalidateDCache();
116
117 /** Assert the cache invalidation state and clear the clean
118 * state. */
119 state->dcache_invalidated = 1;
120 state->dcache_cleaned = 0;
121 }
122 }
Kshitij Sisodiac22e80e2022-03-14 09:26:48 +0000123#endif /* defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) */
124}