/**************************************************************************** * * Copyright (c) 2026 by amlogic Corp. All rights reserved. * * The material in this file is confidential and contains trade secrets * of amlogic Corporation. No part of this work may be disclosed, * reproduced, copied, transmitted, or used in any way for any purpose, * without the express written permission of amlogic Corporation. * ***************************************************************************/ /*------------------------------------------- Includes -------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include "nnsdk2.h" /*------------------------------------------- Functions -------------------------------------------*/ typedef struct { uint32_t index; float score; } top5_item_t; typedef struct { uint32_t count; top5_item_t items[5]; } top5_result_t; typedef struct { void *handle; int (*init)(void **context, void *model, uint32_t size, amlnn_init_config *init_config); int (*query)(void *context, amlnn_query_cmd query_cmd, void *info, uint32_t size); int (*inputs_set)(void *context, uint32_t n_inputs, amlnn_input inputs[]); int (*run)(void *context, amlnn_run_config *run_config); int (*outputs_get)(void *context, uint32_t n_outputs, amlnn_output outputs[]); int (*destroy)(void *context); int (*alloc_dma_mem)(void *context, amlnn_dma_memory *dma_memory, amlnn_dma_config *dma_config); int (*bind_dma_mem)(void *context, amlnn_dma_memory *dma_memory, amlnn_dma_config *dma_config); int (*unbind_dma_mem)(void *context); int (*free_dma_mem)(void *context, amlnn_dma_memory *dma_memory, amlnn_dma_config *dma_config); int (*set_softop_opt)(void *context, amlnn_softop_opt_request requests[], uint32_t request_num); int (*set_input_shapes)(void *context, uint32_t n_inputs, amlnn_tensor_attr tensor_attr[]); } nnsdk_api_t; static nnsdk_api_t g_nnsdk_api = {}; template static bool load_symbol(void *handle, const char *symbol_name, T &symbol) { dlerror(); symbol = reinterpret_cast(dlsym(handle, symbol_name)); const char *err = dlerror(); if (err != NULL) { printf("dlsym %s fail! %s\n", symbol_name, err); return false; } return true; } static int load_nnsdk_api(const char *lib_path) { g_nnsdk_api.handle = dlopen(lib_path, RTLD_NOW | RTLD_LOCAL); if (g_nnsdk_api.handle == NULL) { printf("dlopen %s fail! %s\n", lib_path, dlerror()); return -1; } if (!load_symbol(g_nnsdk_api.handle, "amlnn_init", g_nnsdk_api.init) || !load_symbol(g_nnsdk_api.handle, "amlnn_query", g_nnsdk_api.query) || !load_symbol(g_nnsdk_api.handle, "amlnn_inputs_set", g_nnsdk_api.inputs_set) || !load_symbol(g_nnsdk_api.handle, "amlnn_run", g_nnsdk_api.run) || !load_symbol(g_nnsdk_api.handle, "amlnn_outputs_get", g_nnsdk_api.outputs_get) || !load_symbol(g_nnsdk_api.handle, "amlnn_destroy", g_nnsdk_api.destroy) || !load_symbol(g_nnsdk_api.handle, "amlnn_alloc_dma_mem", g_nnsdk_api.alloc_dma_mem) || !load_symbol(g_nnsdk_api.handle, "amlnn_bind_dma_mem", g_nnsdk_api.bind_dma_mem) || !load_symbol(g_nnsdk_api.handle, "amlnn_unbind_dma_mem", g_nnsdk_api.unbind_dma_mem) || !load_symbol(g_nnsdk_api.handle, "amlnn_free_dma_mem", g_nnsdk_api.free_dma_mem) || !load_symbol(g_nnsdk_api.handle, "amlnn_set_softop_opt", g_nnsdk_api.set_softop_opt) || !load_symbol(g_nnsdk_api.handle, "amlnn_set_input_shapes", g_nnsdk_api.set_input_shapes)) { dlclose(g_nnsdk_api.handle); g_nnsdk_api = {}; return -1; } return 0; } static void unload_nnsdk_api() { if (g_nnsdk_api.handle != NULL) { dlclose(g_nnsdk_api.handle); } g_nnsdk_api = {}; } static void dump_tensor_attr(amlnn_tensor_attr *attr) { printf(" index=%d, name=%s, n_dims=%d, dims=[%d, %d, %d, %d], n_elems=%d, size=%d, size_with_stride=%d, fmt=%s, type=%s, " "zp=%d, scale=%f\n", attr->index, attr->name, attr->n_dims, attr->dims[0], attr->dims[1], attr->dims[2], attr->dims[3], attr->n_elems, attr->size, attr->size_with_stride, get_format_string(attr->fmt), get_type_string(attr->type), attr->zp, attr->scale); } static void dump_input_dynamic_range(amlnn_input_range *dyn_range) { std::string range_str = ""; for (int n = 0; n < dyn_range->shape_number; ++n) { range_str += n == 0 ? "[" : ",["; range_str += dyn_range->n_dims < 1 ? "" : std::to_string(dyn_range->dyn_range[n][0]); for (int i = 1; i < dyn_range->n_dims; ++i) { range_str += ", " + std::to_string(dyn_range->dyn_range[n][i]); } range_str += "]"; } printf(" index=%d, name=%s, shape_number=%d, range=[%s], fmt = %s\n", dyn_range->index, dyn_range->name, dyn_range->shape_number, range_str.c_str(), get_format_string(dyn_range->fmt)); } static std::vector split(const std::string &str, const std::string &pattern) { std::vector res; if (str == "") return res; std::string strs = str + pattern; size_t pos = strs.find(pattern); while (pos != strs.npos) { std::string temp = strs.substr(0, pos); res.push_back(temp); strs = strs.substr(pos + 1, strs.size()); pos = strs.find(pattern); } return res; } static uint8_t *load_model(const char *filename, uint32_t *model_size) { FILE *fp = fopen(filename, "rb"); if (fp == nullptr) { printf("fopen %s fail!\n", filename); return NULL; } fseek(fp, 0, SEEK_END); uint32_t model_len = ftell(fp); uint8_t *model = (uint8_t *)malloc(model_len); fseek(fp, 0, SEEK_SET); if (model_len != fread(model, 1, model_len, fp)) { printf("fread %s fail!\n", filename); free(model); return NULL; } *model_size = model_len; if (fp) { fclose(fp); } return model; } static void *read_file(const char *file_path, uint32_t *file_size) { FILE *fp = NULL; uint32_t size = 0; void *buf = NULL; fp = fopen(file_path, "rb"); if (NULL == fp) { printf("open file fail!\n"); return NULL; } fseek(fp, 0, SEEK_END); size = ftell(fp); rewind(fp); buf = malloc(sizeof(uint8_t) * size); fread(buf, 1, size, fp); fclose(fp); *file_size = size; return buf; } template static top5_result_t collect_top5(const T *buf, uint32_t num) { uint32_t i, j, k; top5_result_t result = {}; float max_prob[5] = {-FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX}; result.count = num < 5 ? num : 5; for (i = 0; i < num; i++) { float score = static_cast(buf[i]); for (j = 0; j < 5; j++) { if (score > max_prob[j]) { for (k = 4; k > j; k--) { max_prob[k] = max_prob[k - 1]; result.items[k] = result.items[k - 1]; } max_prob[j] = score; result.items[j].index = i; result.items[j].score = score; break; } } } return result; } static top5_result_t process_top5_f32(float *buf, uint32_t num) { return collect_top5(buf, num); } static top5_result_t process_top5_i8(int8_t *buf, uint32_t num) { return collect_top5(buf, num); } static top5_result_t process_top5_u8(uint8_t *buf, uint32_t num) { return collect_top5(buf, num); } static void print_top5_result(const char *run_mode, uint32_t output_index, const top5_result_t &result) { printf("[%s] output %u top5:\n", run_mode, output_index); for (uint32_t i = 0; i < result.count; i++) { printf("%3u: %8.6f\n", result.items[i].index, result.items[i].score); } } static void print_top5_result_with_tag(const char *run_mode, const char *tag, uint32_t output_index, const top5_result_t &result) { printf("[%s][%s] output %u top5:\n", run_mode, tag, output_index); for (uint32_t i = 0; i < result.count; i++) { printf("%3u: %8.6f\n", result.items[i].index, result.items[i].score); } } /*------------------------------------------- Main Function -------------------------------------------*/ int base_api(int argc, char **argv) { int ret = 0; const char *model_path = argv[1]; const char *input_path = argv[2]; if (argc != 4) { printf("Usage: %s \n", argv[0]); return -1; } // Get sdk version amlnn_sdk_version sdk_ver; ret = g_nnsdk_api.query(NULL, AMLNN_QUERY_SDK_VERSION, &sdk_ver, sizeof(sdk_ver)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } printf("version info: sdk2-[%s], adla-[%s], delegate-[%s]\n", sdk_ver.sdk2_api_version, sdk_ver.adla_kmd_version, sdk_ver.delegate_version); // Load ADLA Model void *ctx = NULL; amlnn_init_config init_config; memset(&init_config, 0, sizeof(amlnn_init_config)); init_config.backend_type = AMLNN_BACKEND_ADLA_NPU; ret = g_nnsdk_api.init(&ctx, (void *)model_path, 0, &init_config); if (ret < 0) { printf("amlnn_init fail! ret=%d\n", ret); return -1; } // Get Model Input Output Info amlnn_input_output_num io_num; ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); printf("input tensors:\n"); amlnn_tensor_attr input_attrs[io_num.n_input]; memset(input_attrs, 0, sizeof(input_attrs)); for (uint32_t i = 0; i < io_num.n_input; i++) { input_attrs[i].index = i; ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(amlnn_tensor_attr)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } dump_tensor_attr(&(input_attrs[i])); } printf("output tensors:\n"); amlnn_tensor_attr output_attrs[io_num.n_output]; memset(output_attrs, 0, sizeof(output_attrs)); for (uint32_t i = 0; i < io_num.n_output; i++) { output_attrs[i].index = i; ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(amlnn_tensor_attr)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } dump_tensor_attr(&(output_attrs[i])); } // Load input data void *input_data; uint32_t input_size; uint32_t file_size; input_data = read_file(input_path, &file_size); input_size = input_attrs[0].n_elems * sizeof(uint8_t); // Set input printf("amlnn_inputs_set\n"); amlnn_input inputs[1]; memset(inputs, 0, sizeof(inputs)); inputs[0].index = 0; inputs[0].buf = input_data; inputs[0].size = input_size; ret = g_nnsdk_api.inputs_set(ctx, io_num.n_input, inputs); if (ret < 0) { printf("amlnn_inputs_set fail! ret=%d\n", ret); return -1; } // Run printf("amlnn_run\n"); ret = g_nnsdk_api.run(ctx, NULL); if (ret < 0) { printf("amlnn_run fail! ret=%d\n", ret); return -1; } // Get Output printf("amlnn_outputs_get\n"); amlnn_output outputs[io_num.n_output]; memset(outputs, 0, sizeof(outputs)); for (uint32_t i = 0; i < io_num.n_output; i++) { outputs[i].is_float = 1; outputs[i].index = i; } ret = g_nnsdk_api.outputs_get(ctx, io_num.n_output, outputs); if (ret < 0) { printf("amlnn_outputs_get fail! ret=%d\n", ret); return -1; } // Post Process for (uint32_t i = 0; i < io_num.n_output; i++) { float *buffer = (float *)outputs[i].buf; uint32_t sz = outputs[i].size / sizeof(float); top5_result_t result = process_top5_f32(buffer, sz); print_top5_result("base", i, result); } // Destroy ret = g_nnsdk_api.destroy(ctx); if (ret < 0) { printf("amlnn_destroy fail! ret=%d\n", ret); return -1; } if (input_data) { free(input_data); } return 0; } int dma_api(int argc, char **argv) { int ret = 0; char *model_path = argv[1]; char *input_path = argv[2]; if (argc != 4) { printf("Usage: %s \n", argv[0]); return -1; } // Load ADLA Model void *ctx = NULL; uint8_t *model = NULL; uint32_t model_len = 0; model = load_model(model_path, &model_len); amlnn_init_config init_config; memset(&init_config, 0, sizeof(amlnn_init_config)); ret = g_nnsdk_api.init(&ctx, (void *)model, model_len, &init_config); if (ret < 0) { printf("amlnn_init fail! ret=%d\n", ret); return -1; } // Get Model Input Output Info amlnn_input_output_num io_num; ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); printf("input tensors:\n"); amlnn_tensor_attr input_attrs[io_num.n_input]; memset(input_attrs, 0, io_num.n_input * sizeof(amlnn_tensor_attr)); for (uint32_t i = 0; i < io_num.n_input; i++) { input_attrs[i].index = i; // query info ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(amlnn_tensor_attr)); if (ret < 0) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } dump_tensor_attr(&input_attrs[i]); } printf("output tensors:\n"); amlnn_tensor_attr output_attrs[io_num.n_output]; memset(output_attrs, 0, io_num.n_output * sizeof(amlnn_tensor_attr)); for (uint32_t i = 0; i < io_num.n_output; i++) { output_attrs[i].index = i; // query info ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(amlnn_tensor_attr)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } dump_tensor_attr(&output_attrs[i]); } // Alloc input dma memory printf("amlnn_alloc_dma_mem input\n"); amlnn_dma_config dma_config_input; memset(&dma_config_input, 0, sizeof(amlnn_dma_config)); dma_config_input.cacheable = 1; dma_config_input.access_mode = AMLNN_EXT_MEM_ACCESS_READ_WRITE; dma_config_input.buffer_type = AMLNN_EXT_BUFFER_VIRTUAL_ADDR; dma_config_input.io_type = AMLNN_EXT_IO_INPUT; amlnn_dma_memory dma_memory_input[1]; memset(dma_memory_input, 0, sizeof(dma_memory_input)); dma_memory_input[0].index = 0; dma_memory_input[0].size = input_attrs[0].size_with_stride; ret = g_nnsdk_api.alloc_dma_mem(ctx, &dma_memory_input[0], &dma_config_input); if (ret != AMLNN_SUCCESS) { printf("amlnn_alloc_dma_mem fail! ret=%d\n", ret); return -1; } // Bind input dma memory printf("amlnn_bind_dma_mem input\n"); ret = g_nnsdk_api.bind_dma_mem(ctx, &dma_memory_input[0], &dma_config_input); if (ret != AMLNN_SUCCESS) { printf("amlnn_bind_dma_mem fail! ret=%d\n", ret); return -1; } // Alloc output dma memory printf("amlnn_alloc_dma_mem output\n"); amlnn_dma_config dma_config_output; memset(&dma_config_output, 0, sizeof(amlnn_dma_config)); dma_config_output.cacheable = 1; dma_config_output.access_mode = AMLNN_EXT_MEM_ACCESS_READ_WRITE; dma_config_output.buffer_type = AMLNN_EXT_BUFFER_VIRTUAL_ADDR; dma_config_output.io_type = AMLNN_EXT_IO_OUTPUT; amlnn_dma_memory dma_memory_output[1]; memset(dma_memory_output, 0, sizeof(dma_memory_output)); dma_memory_output[0].index = 0; dma_memory_output[0].size = output_attrs[0].size_with_stride; ret = g_nnsdk_api.alloc_dma_mem(ctx, &dma_memory_output[0], &dma_config_output); if (ret != AMLNN_SUCCESS) { printf("amlnn_alloc_dma_mem fail! ret=%d\n", ret); return -1; } // Bind output dma memory printf("amlnn_bind_dma_mem output\n"); ret = g_nnsdk_api.bind_dma_mem(ctx, &dma_memory_output[0], &dma_config_output); if (ret != AMLNN_SUCCESS) { printf("amlnn_bind_dma_mem fail! ret=%d\n", ret); return -1; } // Load input data void *input_data; uint32_t input_size; uint32_t file_size; input_data = read_file(input_path, &file_size); input_size = input_attrs[0].n_elems * sizeof(int8_t); // Copy input data to dma mem memcpy(dma_memory_input[0].viraddr, input_data, input_size); // Run printf("amlnn_run\n"); ret = g_nnsdk_api.run(ctx, NULL); if (ret < 0) { printf("amlnn_run fail! ret=%d\n", ret); return -1; } // Post Process for (uint32_t i = 0; i < io_num.n_output; i++) { uint8_t *buffer = (uint8_t *)dma_memory_output[i].viraddr; uint32_t sz = output_attrs[i].n_elems; top5_result_t result = process_top5_u8(buffer, sz); print_top5_result("dma", i, result); } // Unbind all dma memory ret = g_nnsdk_api.unbind_dma_mem(ctx); if (ret < 0) { printf("amlnn_unbind_dma_mem fail! ret=%d\n", ret); return -1; } // Free input dma memory ret = g_nnsdk_api.free_dma_mem(ctx, &dma_memory_input[0], &dma_config_input); if (ret < 0) { printf("amlnn_free_dma_mem fail! ret=%d\n", ret); return -1; } // Free output dma memory ret = g_nnsdk_api.free_dma_mem(ctx, &dma_memory_output[0], &dma_config_output); if (ret < 0) { printf("amlnn_free_dma_mem fail! ret=%d\n", ret); return -1; } // Destroy ret = g_nnsdk_api.destroy(ctx); if (ret < 0) { printf("amlnn_destroy fail! ret=%d\n", ret); return -1; } if (model) { free(model); } if (input_data) { free(input_data); } return 0; } int softop_acc_api(int argc, char **argv) { int ret = 0; const char *model_path = argv[1]; const char *input_path = argv[2]; if (argc != 4) { printf("Usage: %s \n", argv[0]); return -1; } // Load ADLA Model void *ctx = NULL; uint8_t *model = NULL; uint32_t model_len = 0; model = load_model(model_path, &model_len); amlnn_init_config init_config; memset(&init_config, 0, sizeof(amlnn_init_config)); ret = g_nnsdk_api.init(&ctx, (void *)model, model_len, &init_config); if (ret < 0) { printf("amlnn_init fail! ret=%d\n", ret); return -1; } // Get Model Input Output Info amlnn_input_output_num io_num; ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); printf("input tensors:\n"); amlnn_tensor_attr input_attrs[io_num.n_input]; memset(input_attrs, 0, sizeof(input_attrs)); for (uint32_t i = 0; i < io_num.n_input; i++) { input_attrs[i].index = i; ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(amlnn_tensor_attr)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } dump_tensor_attr(&(input_attrs[i])); } printf("output tensors:\n"); amlnn_tensor_attr output_attrs[io_num.n_output]; memset(output_attrs, 0, sizeof(output_attrs)); for (uint32_t i = 0; i < io_num.n_output; i++) { output_attrs[i].index = i; ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(amlnn_tensor_attr)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } dump_tensor_attr(&(output_attrs[i])); } // Set software operator acceleration amlnn_softop_opt_request softop_opt_requests[] = { { .softop_type = AMLNN_Unknown, .acc_type = AMLNN_SOFTOP_ACC_OPENMP, }, }; ret = g_nnsdk_api.set_softop_opt(ctx, softop_opt_requests, sizeof(softop_opt_requests) / sizeof(amlnn_softop_opt_request)); if (ret != AMLNN_SUCCESS) { printf("amlnn_set_softop_opt fail! ret=%d\n", ret); return -1; } // Load input data void *input_data; uint32_t input_size; uint32_t file_size; input_data = read_file(input_path, &file_size); input_size = input_attrs[0].n_elems * sizeof(uint8_t); // Set input printf("amlnn_inputs_set\n"); amlnn_input inputs[1]; memset(inputs, 0, sizeof(inputs)); inputs[0].index = 0; inputs[0].buf = input_data; inputs[0].size = input_size; ret = g_nnsdk_api.inputs_set(ctx, io_num.n_input, inputs); if (ret < 0) { printf("amlnn_inputs_set fail! ret=%d\n", ret); return -1; } // Run printf("amlnn_run\n"); ret = g_nnsdk_api.run(ctx, NULL); if (ret < 0) { printf("amlnn_run fail! ret=%d\n", ret); return -1; } // Get Output printf("amlnn_outputs_get\n"); amlnn_output outputs[io_num.n_output]; memset(outputs, 0, sizeof(outputs)); for (uint32_t i = 0; i < io_num.n_output; i++) { outputs[i].is_float = 1; outputs[i].index = i; } ret = g_nnsdk_api.outputs_get(ctx, io_num.n_output, outputs); if (ret < 0) { printf("amlnn_outputs_get fail! ret=%d\n", ret); return -1; } // Post Process for (uint32_t i = 0; i < io_num.n_output; i++) { float *buffer = (float *)outputs[i].buf; uint32_t sz = outputs[i].size / sizeof(float); top5_result_t result = process_top5_f32(buffer, sz); print_top5_result("softop_acc", i, result); } // Destroy ret = g_nnsdk_api.destroy(ctx); if (ret < 0) { printf("amlnn_destroy fail! ret=%d\n", ret); return -1; } if (model) { free(model); } if (input_data) { free(input_data); } return 0; } int dynamic_shape_api(int argc, char **argv) { int ret = 0; char *model_path = argv[1]; char *input_paths = argv[2]; if (argc != 4) { printf("Usage: %s \n", argv[0]); return -1; } std::vector input_paths_split = split(input_paths, "#"); // Load ADLA Model void *ctx = NULL; amlnn_init_config init_config; memset(&init_config, 0, sizeof(amlnn_init_config)); init_config.backend_type = AMLNN_BACKEND_ADLA_NPU; ret = g_nnsdk_api.init(&ctx, (void *)model_path, 0, &init_config); if (ret < 0) { printf("amlnn_init fail! ret=%d\n", ret); return -1; } // Get Model Input Output Info amlnn_input_output_num io_num; ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output); printf("input tensors:\n"); amlnn_tensor_attr input_attrs[io_num.n_input]; memset(input_attrs, 0, io_num.n_input * sizeof(amlnn_tensor_attr)); for (uint32_t i = 0; i < io_num.n_input; i++) { input_attrs[i].index = i; // query info ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(amlnn_tensor_attr)); if (ret < 0) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } dump_tensor_attr(&input_attrs[i]); } printf("output tensors:\n"); amlnn_tensor_attr output_attrs[io_num.n_output]; memset(output_attrs, 0, io_num.n_output * sizeof(amlnn_tensor_attr)); for (uint32_t i = 0; i < io_num.n_output; i++) { output_attrs[i].index = i; // query info ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(amlnn_tensor_attr)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } dump_tensor_attr(&output_attrs[i]); } printf("dynamic inputs shape range:\n"); amlnn_input_range shape_range[io_num.n_input]; memset(shape_range, 0, io_num.n_input * sizeof(amlnn_input_range)); for (uint32_t i = 0; i < io_num.n_input; i++) { shape_range[i].index = i; ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_INPUT_DYNAMIC_RANGE, &shape_range[i], sizeof(amlnn_input_range)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } dump_input_dynamic_range(&shape_range[i]); } void *input_data[io_num.n_input]; uint32_t input_size[io_num.n_input]; uint32_t file_size[io_num.n_input]; for (uint32_t i = 0; i < io_num.n_input; i++) { input_data[i] = NULL; input_size[i] = input_attrs[i].n_elems * sizeof(uint8_t); } uint32_t shape_num = shape_range[0].shape_number; // Load input data if (io_num.n_input != input_paths_split.size()) { return -1; } for (uint32_t i = 0; i < io_num.n_input; i++) { printf("%s\n", input_paths_split[i].c_str()); input_data[i] = read_file(input_paths_split[i].c_str(), &file_size[i]); } for (uint32_t s = 0; s < shape_num; ++s) { for (uint32_t i = 0; i < io_num.n_input; i++) { for (uint32_t j = 0; j < input_attrs[i].n_dims; ++j) { input_attrs[i].dims[j] = shape_range[i].dyn_range[s][j]; } } ret = g_nnsdk_api.set_input_shapes(ctx, io_num.n_input, input_attrs); if (ret < 0) { fprintf(stderr, "amlnn_set_input_shapes fail! ret=%d\n", ret); return -1; } printf("current input tensors:\n"); amlnn_tensor_attr cur_input_attrs[io_num.n_input]; memset(cur_input_attrs, 0, io_num.n_input * sizeof(amlnn_tensor_attr)); for (uint32_t i = 0; i < io_num.n_input; i++) { cur_input_attrs[i].index = i; // query info ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_CURRENT_INPUT_ATTR, &(cur_input_attrs[i]), sizeof(amlnn_tensor_attr)); if (ret < 0) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } dump_tensor_attr(&cur_input_attrs[i]); } printf("current output tensors:\n"); amlnn_tensor_attr cur_output_attrs[io_num.n_output]; memset(cur_output_attrs, 0, io_num.n_output * sizeof(amlnn_tensor_attr)); for (uint32_t i = 0; i < io_num.n_output; i++) { cur_output_attrs[i].index = i; // query info ret = g_nnsdk_api.query(ctx, AMLNN_QUERY_CURRENT_OUTPUT_ATTR, &(cur_output_attrs[i]), sizeof(amlnn_tensor_attr)); if (ret != AMLNN_SUCCESS) { printf("amlnn_query fail! ret=%d\n", ret); return -1; } dump_tensor_attr(&cur_output_attrs[i]); } uint32_t input_size_pad[io_num.n_input]; void *input_data_pad[io_num.n_input]; std::vector> input_buf_tmp(io_num.n_input); for (uint32_t i = 0; i < io_num.n_input; i++) { input_size_pad[i] = cur_input_attrs[i].n_elems * sizeof(uint8_t); input_buf_tmp[i].resize(input_size_pad[i], 0); uint32_t multiplier = input_size_pad[i] / input_size[i]; for (uint32_t j = 0; j < multiplier; j++) { memcpy(input_buf_tmp[i].data() + (j * input_size[i]), input_data[i], input_size[i]); } input_data_pad[i] = input_buf_tmp[i].data(); } printf("amlnn_inputs_set\n"); amlnn_input inputs[io_num.n_input]; memset(inputs, 0, io_num.n_input * sizeof(amlnn_input)); for (uint32_t i = 0; i < io_num.n_input; i++) { inputs[i].index = i; inputs[i].buf = input_data_pad[i]; inputs[i].size = input_size_pad[i]; } ret = g_nnsdk_api.inputs_set(ctx, io_num.n_input, inputs); if (ret < 0) { printf("amlnn_inputs_set fail! ret=%d\n", ret); return -1; } printf("amlnn_run\n"); ret = g_nnsdk_api.run(ctx, NULL); if (ret < 0) { printf("amlnn_run fail! ret=%d\n", ret); return -1; } printf("amlnn_outputs_get\n"); amlnn_output outputs[io_num.n_output]; memset(outputs, 0, io_num.n_output * sizeof(amlnn_output)); for (uint32_t i = 0; i < io_num.n_output; ++i) { outputs[i].is_float = 1; outputs[i].index = i; } ret = g_nnsdk_api.outputs_get(ctx, io_num.n_output, outputs); if (ret < 0) { printf("amlnn_outputs_get fail! ret=%d\n", ret); return ret; } for (uint32_t i = 0; i < io_num.n_output; i++) { float *buffer = (float *)outputs[i].buf; uint32_t sz = outputs[i].size / sizeof(float); top5_result_t result = process_top5_f32(buffer, sz); std::string tag = "shape_" + std::to_string(s); print_top5_result_with_tag("dynamic_shape", tag.c_str(), i, result); } } // Destroy ret = g_nnsdk_api.destroy(ctx); if (ret < 0) { printf("amlnn_destroy fail! ret=%d\n", ret); return -1; } for (uint32_t i = 0; i < io_num.n_input; i++) { free(input_data[i]); } return 0; } typedef enum { MODE_NONE, MODE_BASE, MODE_DMA, MODE_SOFTOP_ACC, MODE_DYNAMIC_SHAPE } run_mode_t; int main(int argc, char **argv) { run_mode_t mode = MODE_NONE; int ret = 0; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--base") == 0) { if (mode != MODE_NONE) goto multi_error; mode = MODE_BASE; } else if (strcmp(argv[i], "--dma") == 0) { if (mode != MODE_NONE) goto multi_error; mode = MODE_DMA; } else if (strcmp(argv[i], "--softop_acc") == 0) { if (mode != MODE_NONE) goto multi_error; mode = MODE_SOFTOP_ACC; } else if (strcmp(argv[i], "--dynamic_shape") == 0) { if (mode != MODE_NONE) goto multi_error; mode = MODE_DYNAMIC_SHAPE; } } if (mode == MODE_NONE) { printf("Error: Please specify one mode (--base, --dma, --softop_acc, --dynamic_shape).\n"); return 1; } if (load_nnsdk_api("libnnsdk.so") != 0) { return 1; } switch (mode) { case MODE_BASE: ret = base_api(argc, argv); break; case MODE_DMA: ret = dma_api(argc, argv); break; case MODE_SOFTOP_ACC: ret = softop_acc_api(argc, argv); break; case MODE_DYNAMIC_SHAPE: ret = dynamic_shape_api(argc, argv); break; default: ret = 1; break; } unload_nnsdk_api(); return ret == 0 ? 0 : 1; multi_error: printf("Error: Multiple modes specified. You can only run ONE at a time.\n"); return 1; }