ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_ethosu_shim.c
Go to the documentation of this file.
1
23
24#include "ra8_device.h"
25
26#ifdef RA8_HAS_NPU
27
28#include <stddef.h>
29#include <stdint.h>
30
31#include "ra8_attributes.h"
32#include "ra8_err.h"
33#include "ra8_ethosu_shim.h"
34#include "ra8_log.h"
35#include "ra8_npu.h"
36#include "ra8_npu_regs.h"
37
45static const char* s_tag = "ETHOSU";
46
60typedef enum : int32_t {
61 k_ra8_ethosu_ret_ok = 0,
62 k_ra8_ethosu_ret_err = -1,
63} ra8_ethosu_ret_t;
64
79struct ethosu_driver {
80 bool reserved;
81};
82
91static struct ethosu_driver s_ethosu_driver = {};
92
101static bool s_ethosu_driver_ready = false;
102
103struct ethosu_driver* ethosu_reserve_driver(void)
104{
105 if (!s_ethosu_driver_ready) {
106 const ra8_err_t err = ra8_npu_init();
107 if (ra8_err_is_error(err)) {
108 ra8_log_error(s_tag, "reserve: npu_init failed");
109 return nullptr;
110 }
111 s_ethosu_driver_ready = true;
112 }
113 s_ethosu_driver.reserved = true;
114 return &s_ethosu_driver;
115}
116
144static bool internal_invoke_args_ok(const struct ethosu_driver* drv,
145 const void* custom_data_ptr,
146 int custom_data_size,
147 const uint64_t* base_addr,
148 int num_base_addr)
149{
150 if (drv == nullptr) {
151 ra8_log_error(s_tag, "invoke: null driver");
152 return false;
153 }
154 if (custom_data_ptr == nullptr) {
155 ra8_log_error(s_tag, "invoke: null command stream");
156 return false;
157 }
158 if (custom_data_size <= 0) {
159 ra8_log_error(s_tag, "invoke: empty command stream");
160 return false;
161 }
162 if (num_base_addr < 0) {
163 ra8_log_error(s_tag, "invoke: negative region count");
164 return false;
165 }
166 /* Bound the region count to ra8_npu's fixed region_base[] capacity BEFORE the
167 * copy loop, so an oversized count can never overflow the job descriptor. */
168 if ((uint32_t)num_base_addr > (uint32_t)k_ra8_npu_region_count) {
169 ra8_log_error(s_tag, "invoke: too many regions");
170 return false;
171 }
172 if ((num_base_addr > 0) && (base_addr == nullptr)) {
173 ra8_log_error(s_tag, "invoke: null base_addr array");
174 return false;
175 }
176 return true;
177}
178
179int ethosu_invoke_v3(struct ethosu_driver* drv,
180 const void* custom_data_ptr,
181 int custom_data_size,
182 const uint64_t* base_addr,
183 const size_t* base_addr_size,
184 int num_base_addr,
185 void* user_arg)
186{
187 /* base_addr_size (per-region byte sizes) and user_arg (Arm callback cookie)
188 * are part of the ABI but have no analogue in the ra8_npu job model. */
189 (void)base_addr_size;
190 (void)user_arg;
191
192 if (!internal_invoke_args_ok(drv, custom_data_ptr, custom_data_size, base_addr, num_base_addr)) {
193 return (int)k_ra8_ethosu_ret_err;
194 }
195
196 ra8_npu_job_t job = {};
197 job.cmd_stream = custom_data_ptr;
198 job.cmd_stream_bytes = (uint32_t)custom_data_size;
199 job.region_count = (uint8_t)num_base_addr;
200 for (uint8_t i = 0U; i < job.region_count; i++) {
201 job.region_base[i] = base_addr[i];
202 }
203
204 const ra8_err_t serr = ra8_npu_submit(&job);
205 if (ra8_err_is_error(serr)) {
206 ra8_log_error(s_tag, "invoke: submit");
207 return (int)k_ra8_ethosu_ret_err;
208 }
209 const ra8_err_t rerr = ra8_npu_run();
210 if (ra8_err_is_error(rerr)) {
211 ra8_log_error(s_tag, "invoke: run");
212 return (int)k_ra8_ethosu_ret_err;
213 }
214 const ra8_err_t werr = ra8_npu_wait();
215 if (ra8_err_is_error(werr)) {
216 ra8_log_error(s_tag, "invoke: wait");
217 return (int)k_ra8_ethosu_ret_err;
218 }
219 return (int)k_ra8_ethosu_ret_ok;
220}
221
222void ethosu_release_driver(struct ethosu_driver* drv)
223{
224 if (drv == nullptr) {
225 ra8_log_error(s_tag, "release: null driver");
226 return;
227 }
228 /* Single persistent NPU: the block stays initialised so a later
229 * ethosu_reserve_driver() re-hands the same context. Only clear the
230 * caller-visible reserved flag. */
231 drv->reserved = false;
232}
233
234#else
235/* RA8D2 (no NPU): this translation unit is intentionally empty. */
237#endif /* RA8_HAS_NPU */
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Compile-time device selection for the RA8 multi-chip build (RA8D2 / RA8P1).
Error Code Definitions for ra8-firmware.
static bool ra8_err_is_error(ra8_err_t err)
Test whether a code represents failure.
Definition ra8_err.h:568
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
int ra8_ethosu_shim_not_on_this_device_t
Arm ethos-u-core-driver C API shim over the ra8_npu driver (RA8P1-only).
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_error(tag, message)
RA8 log error.
Definition ra8_log.h:335
Arm Ethos-U55 NPU command/queue driver foundation (RA8P1-only).
ra8_err_t ra8_npu_submit(const ra8_npu_job_t *job)
Program the command queue and tensor region base pointers for a job.
ra8_err_t ra8_npu_run(void)
Kick the currently-submitted job (transition the NPU to running).
ra8_err_t ra8_npu_init(void)
Bring the NPU out of module-stop and soft-reset it.
ra8_err_t ra8_npu_wait(void)
Bounded busy-wait until the running job completes or faults.
Arm Ethos-U55 NPU register window on the Renesas RA8P1 (RA8P1-only).
@ k_ra8_npu_region_count
Number of BASEPn region base-pointer pairs.
One Ethos-U55 inference job: a command stream plus its tensor arenas.
Definition ra8_npu.h:87
uint8_t region_count
Number of region_base[] entries in use.
Definition ra8_npu.h:90
uint32_t cmd_stream_bytes
Command stream length in bytes (> 0).
Definition ra8_npu.h:89
uint64_t region_base[k_ra8_npu_region_count]
AXI base of each BASEPn arena.
Definition ra8_npu.h:91
const void * cmd_stream
Vela command stream base in SRAM.
Definition ra8_npu.h:88