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