xref: /aosp_15_r20/external/executorch/backends/arm/runtime/VelaBinStream.cpp (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1*523fa7a6SAndroid Build Coastguard Worker /*
2*523fa7a6SAndroid Build Coastguard Worker  * Copyright 2023 Arm Limited and/or its affiliates.
3*523fa7a6SAndroid Build Coastguard Worker  *
4*523fa7a6SAndroid Build Coastguard Worker  * This source code is licensed under the BSD-style license found in the
5*523fa7a6SAndroid Build Coastguard Worker  * LICENSE file in the root directory of this source tree.
6*523fa7a6SAndroid Build Coastguard Worker  */
7*523fa7a6SAndroid Build Coastguard Worker 
8*523fa7a6SAndroid Build Coastguard Worker /*
9*523fa7a6SAndroid Build Coastguard Worker  * Warning: Do not change this without changing arm_backend.py::vela_compile
10*523fa7a6SAndroid Build Coastguard Worker  *          as that function emits this format and the two need to align.
11*523fa7a6SAndroid Build Coastguard Worker  */
12*523fa7a6SAndroid Build Coastguard Worker 
13*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/arm/runtime/VelaBinStream.h>
14*523fa7a6SAndroid Build Coastguard Worker 
15*523fa7a6SAndroid Build Coastguard Worker #include <cstring>
16*523fa7a6SAndroid Build Coastguard Worker 
17*523fa7a6SAndroid Build Coastguard Worker #include <executorch/runtime/core/error.h>
18*523fa7a6SAndroid Build Coastguard Worker 
19*523fa7a6SAndroid Build Coastguard Worker namespace executorch {
20*523fa7a6SAndroid Build Coastguard Worker namespace backends {
21*523fa7a6SAndroid Build Coastguard Worker namespace arm {
22*523fa7a6SAndroid Build Coastguard Worker 
23*523fa7a6SAndroid Build Coastguard Worker // get next mul of 16 ptr, return n if already aligned
next_mul_16(uintptr_t n)24*523fa7a6SAndroid Build Coastguard Worker static uintptr_t next_mul_16(uintptr_t n) {
25*523fa7a6SAndroid Build Coastguard Worker   return ((n - 1) | 15) + 1;
26*523fa7a6SAndroid Build Coastguard Worker }
27*523fa7a6SAndroid Build Coastguard Worker 
vela_bin_validate(const char * data,int size)28*523fa7a6SAndroid Build Coastguard Worker bool vela_bin_validate(const char* data, int size) {
29*523fa7a6SAndroid Build Coastguard Worker   const char* foot = data + size - sizeof(VelaBinBlock);
30*523fa7a6SAndroid Build Coastguard Worker 
31*523fa7a6SAndroid Build Coastguard Worker   // Check 16 byte alignment
32*523fa7a6SAndroid Build Coastguard Worker   bool valid = true;
33*523fa7a6SAndroid Build Coastguard Worker   if ((uintptr_t)data != next_mul_16((uintptr_t)data)) {
34*523fa7a6SAndroid Build Coastguard Worker     ET_LOG(Error, "Vela bin ptr not aligned to 16 bytes: %p", (void*)data);
35*523fa7a6SAndroid Build Coastguard Worker     valid = false;
36*523fa7a6SAndroid Build Coastguard Worker   }
37*523fa7a6SAndroid Build Coastguard Worker   if ((uintptr_t)foot != next_mul_16((uintptr_t)foot)) {
38*523fa7a6SAndroid Build Coastguard Worker     ET_LOG(Error, "End of vela bin not aligned to 16 bytes: %p", (void*)foot);
39*523fa7a6SAndroid Build Coastguard Worker     valid = false;
40*523fa7a6SAndroid Build Coastguard Worker   }
41*523fa7a6SAndroid Build Coastguard Worker   // Check header and footer blocks are the right format
42*523fa7a6SAndroid Build Coastguard Worker   if (strncmp(data, "vela_bin_stream", strlen("vela_bin_stream")) != 0) {
43*523fa7a6SAndroid Build Coastguard Worker     ET_LOG(Error, "Incorrect header in vela_bin_stream");
44*523fa7a6SAndroid Build Coastguard Worker     valid = false;
45*523fa7a6SAndroid Build Coastguard Worker   }
46*523fa7a6SAndroid Build Coastguard Worker   if (strncmp(foot, "vela_end_stream", strlen("vela_end_stream")) != 0) {
47*523fa7a6SAndroid Build Coastguard Worker     ET_LOG(Error, "Incorrect footer in vela_bin_stream");
48*523fa7a6SAndroid Build Coastguard Worker     valid = false;
49*523fa7a6SAndroid Build Coastguard Worker   }
50*523fa7a6SAndroid Build Coastguard Worker 
51*523fa7a6SAndroid Build Coastguard Worker   return valid;
52*523fa7a6SAndroid Build Coastguard Worker }
53*523fa7a6SAndroid Build Coastguard Worker 
vela_bin_read(const char * data,VelaHandles * handles,int size)54*523fa7a6SAndroid Build Coastguard Worker bool vela_bin_read(const char* data, VelaHandles* handles, int size) {
55*523fa7a6SAndroid Build Coastguard Worker   const char* ptr = data;
56*523fa7a6SAndroid Build Coastguard Worker 
57*523fa7a6SAndroid Build Coastguard Worker   while (ptr - data < size) {
58*523fa7a6SAndroid Build Coastguard Worker     VelaBinBlock* b = (VelaBinBlock*)ptr;
59*523fa7a6SAndroid Build Coastguard Worker     ptr += sizeof(VelaBinBlock) + next_mul_16(b->size);
60*523fa7a6SAndroid Build Coastguard Worker 
61*523fa7a6SAndroid Build Coastguard Worker     if (!strncmp(b->name, "vela_bin_stream", strlen("vela_bin_stream"))) {
62*523fa7a6SAndroid Build Coastguard Worker       // expect vela_bin_stream first
63*523fa7a6SAndroid Build Coastguard Worker       if ((char*)b != (char*)data)
64*523fa7a6SAndroid Build Coastguard Worker         return false;
65*523fa7a6SAndroid Build Coastguard Worker     } else if (!strncmp(b->name, "cmd_data", strlen("cmd_data"))) {
66*523fa7a6SAndroid Build Coastguard Worker       // This driver magic header confirms a valid command stream in binary
67*523fa7a6SAndroid Build Coastguard Worker       if (strncmp(b->data, "COP1", strlen("COP1")))
68*523fa7a6SAndroid Build Coastguard Worker         return false;
69*523fa7a6SAndroid Build Coastguard Worker       handles->cmd_data = b->data;
70*523fa7a6SAndroid Build Coastguard Worker       handles->cmd_data_size = b->size;
71*523fa7a6SAndroid Build Coastguard Worker     } else if (!strncmp(b->name, "weight_data", strlen("weight_data"))) {
72*523fa7a6SAndroid Build Coastguard Worker       handles->weight_data = b->data;
73*523fa7a6SAndroid Build Coastguard Worker       handles->weight_data_size = b->size;
74*523fa7a6SAndroid Build Coastguard Worker     } else if (!strncmp(b->name, "scratch_data", strlen("scratch_data"))) {
75*523fa7a6SAndroid Build Coastguard Worker       handles->scratch_data = b->data;
76*523fa7a6SAndroid Build Coastguard Worker       handles->scratch_data_size = b->size;
77*523fa7a6SAndroid Build Coastguard Worker     } else if (!strncmp(b->name, "inputs", strlen("inputs"))) {
78*523fa7a6SAndroid Build Coastguard Worker       handles->inputs = (VelaIOs*)b->data;
79*523fa7a6SAndroid Build Coastguard Worker     } else if (!strncmp(b->name, "outputs", strlen("outputs"))) {
80*523fa7a6SAndroid Build Coastguard Worker       handles->outputs = (VelaIOs*)b->data;
81*523fa7a6SAndroid Build Coastguard Worker     } else if (!strncmp(
82*523fa7a6SAndroid Build Coastguard Worker                    b->name, "vela_end_stream", strlen("vela_end_stream"))) {
83*523fa7a6SAndroid Build Coastguard Worker       // expect vela_end_stream last
84*523fa7a6SAndroid Build Coastguard Worker       if (ptr - data != size) {
85*523fa7a6SAndroid Build Coastguard Worker         ET_LOG(Error, "Expected vela binary to end with vela_end_stream");
86*523fa7a6SAndroid Build Coastguard Worker         return false;
87*523fa7a6SAndroid Build Coastguard Worker       }
88*523fa7a6SAndroid Build Coastguard Worker       return true;
89*523fa7a6SAndroid Build Coastguard Worker     } else {
90*523fa7a6SAndroid Build Coastguard Worker       // Unrecognised block name
91*523fa7a6SAndroid Build Coastguard Worker       ET_LOG(Error, "Invalid block name or malformed binary");
92*523fa7a6SAndroid Build Coastguard Worker       return false;
93*523fa7a6SAndroid Build Coastguard Worker     }
94*523fa7a6SAndroid Build Coastguard Worker   }
95*523fa7a6SAndroid Build Coastguard Worker 
96*523fa7a6SAndroid Build Coastguard Worker   // We've fallen off the end without finding vela_end_stream
97*523fa7a6SAndroid Build Coastguard Worker   return false;
98*523fa7a6SAndroid Build Coastguard Worker }
99*523fa7a6SAndroid Build Coastguard Worker 
100*523fa7a6SAndroid Build Coastguard Worker } // namespace arm
101*523fa7a6SAndroid Build Coastguard Worker } // namespace backends
102*523fa7a6SAndroid Build Coastguard Worker } // namespace executorch
103