/* * Copyright 2023 Arm Limited and/or its affiliates. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ /* * Warning: Do not change this without changing arm_backend.py::vela_compile * as that function emits this format and the two need to align. */ #include #include #include namespace executorch { namespace backends { namespace arm { // get next mul of 16 ptr, return n if already aligned static uintptr_t next_mul_16(uintptr_t n) { return ((n - 1) | 15) + 1; } bool vela_bin_validate(const char* data, int size) { const char* foot = data + size - sizeof(VelaBinBlock); // Check 16 byte alignment bool valid = true; if ((uintptr_t)data != next_mul_16((uintptr_t)data)) { ET_LOG(Error, "Vela bin ptr not aligned to 16 bytes: %p", (void*)data); valid = false; } if ((uintptr_t)foot != next_mul_16((uintptr_t)foot)) { ET_LOG(Error, "End of vela bin not aligned to 16 bytes: %p", (void*)foot); valid = false; } // Check header and footer blocks are the right format if (strncmp(data, "vela_bin_stream", strlen("vela_bin_stream")) != 0) { ET_LOG(Error, "Incorrect header in vela_bin_stream"); valid = false; } if (strncmp(foot, "vela_end_stream", strlen("vela_end_stream")) != 0) { ET_LOG(Error, "Incorrect footer in vela_bin_stream"); valid = false; } return valid; } bool vela_bin_read(const char* data, VelaHandles* handles, int size) { const char* ptr = data; while (ptr - data < size) { VelaBinBlock* b = (VelaBinBlock*)ptr; ptr += sizeof(VelaBinBlock) + next_mul_16(b->size); if (!strncmp(b->name, "vela_bin_stream", strlen("vela_bin_stream"))) { // expect vela_bin_stream first if ((char*)b != (char*)data) return false; } else if (!strncmp(b->name, "cmd_data", strlen("cmd_data"))) { // This driver magic header confirms a valid command stream in binary if (strncmp(b->data, "COP1", strlen("COP1"))) return false; handles->cmd_data = b->data; handles->cmd_data_size = b->size; } else if (!strncmp(b->name, "weight_data", strlen("weight_data"))) { handles->weight_data = b->data; handles->weight_data_size = b->size; } else if (!strncmp(b->name, "scratch_data", strlen("scratch_data"))) { handles->scratch_data = b->data; handles->scratch_data_size = b->size; } else if (!strncmp(b->name, "inputs", strlen("inputs"))) { handles->inputs = (VelaIOs*)b->data; } else if (!strncmp(b->name, "outputs", strlen("outputs"))) { handles->outputs = (VelaIOs*)b->data; } else if (!strncmp( b->name, "vela_end_stream", strlen("vela_end_stream"))) { // expect vela_end_stream last if (ptr - data != size) { ET_LOG(Error, "Expected vela binary to end with vela_end_stream"); return false; } return true; } else { // Unrecognised block name ET_LOG(Error, "Invalid block name or malformed binary"); return false; } } // We've fallen off the end without finding vela_end_stream return false; } } // namespace arm } // namespace backends } // namespace executorch