/* * vnn_utils.cc * * This provides helper functions for nbg-benchmark tool and wrappers around OpenVX lib * function. The function are mainly used for converting data types and loading * network binary graph. * * Author: Othmane AHL ZOUAOUI for STMicroelectronics. * * Copyright (c) 2023 STMicroelectronics. All rights reserved. * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * * http://www.opensource.org/licenses/BSD-3-Clause */ #include #include "vnn_utils.h" #ifdef WIN32 static vx_float32 round(vx_float32 x) { #if defined(_M_X64) return (vx_float32) _copysignf(floorf(fabsf(x) + 0.5f), x); #else return (vx_float32) _copysign(floorf(fabsf(x) + 0.5f), x); #endif } #endif vx_uint32 vnn_GetTypeSize(vx_enum format) { switch(format) { case VX_TYPE_INT8: case VX_TYPE_UINT8: case VX_DF_IMAGE_U8: return 1; case VX_TYPE_INT16: case VX_TYPE_UINT16: case VX_DF_IMAGE_S16: case VX_DF_IMAGE_U16: return 2; case VX_TYPE_INT32: case VX_TYPE_UINT32: case VX_DF_IMAGE_S32: case VX_DF_IMAGE_U32: return 4; case VX_TYPE_INT64: case VX_TYPE_UINT64: return 8; case VX_TYPE_FLOAT32: case VX_DF_IMAGE_F32: return 4; case VX_TYPE_FLOAT64: return 8; case VX_TYPE_ENUM: return 4; case VX_TYPE_FLOAT16: return 2; default: printf("Not support format:%d,line=%d\n",format,__LINE__); } return 0; } vx_int8 vnn_Fp32toInt8(vx_float32 val, vx_int8 fixedPointPos) { vx_int8 result = 0; if (fixedPointPos > 0) { vx_int32 data = (vx_int32) round(val * (vx_float32)(1 << fixedPointPos)); result = (vx_int8)((data > 127) ? 127 : (data < -128) ? -128 : data); } else { vx_int32 data = (vx_int32) round(val * (1.0f / (vx_float32)(1 << -fixedPointPos))); result = (vx_int8)((data > 127) ? 127 : (data < -128) ? -128 : data); } return result; } vx_float32 vnn_Int8toFp32(vx_int8 val, vx_int8 fixedPointPos) { vx_float32 result = 0.0f; if (fixedPointPos > 0) { result = (vx_float32)val * (1.0f / ((vx_uint32) (1 << fixedPointPos))); } else { result = (vx_float32)val * ((vx_float32) (1 << -fixedPointPos)); } return result; } vx_uint8 vnn_Fp32toUint8(vx_float32 val, vx_int32 zeroPoint, vx_float32 scale) { vx_uint8 result = 0; vx_int32 data; data = (vx_int32) round((val / scale + (vx_uint8)zeroPoint)); if (data > 255) data = 255; if (data < 0) data = 0; result = (vx_uint8)(data); return result; } vx_float32 vnn_Uint8toFp32(vx_uint8 val, vx_int32 zeroPoint, vx_float32 scale) { vx_float32 result = 0.0f; result = (val - (vx_uint8)zeroPoint) * scale; return result; } vx_int8 vnn_Fp32toAsymInt8(vx_float32 val, vx_int32 zeroPoint, vx_float32 scale) { vx_int8 result = 0; vx_int32 data; data = (vx_int32) round((val / scale + (vx_uint8)zeroPoint)); if (data > 127) data = 127; if (data < -128) data = -128; result = (vx_int8)(data); return result; } vx_float32 vnn_AsymInt8toFp32(vx_int8 val, vx_int32 zeroPoint, vx_float32 scale) { vx_float32 result = 0.0f; result = (val - (vx_int8)zeroPoint) * scale; return result; } vx_float32 vnn_Int16toFp32(vx_int16 val, vx_int8 fixedPointPos) { vx_float32 result = 0.0f; vx_float32 value = val; if (fixedPointPos > 0) { result = value * (1.0f / ((vx_uint32) (1 << fixedPointPos))); } else { result = value * ((vx_float32) (1 << -fixedPointPos)); } return result; } vx_int16 vnn_Fp32toInt16(vx_float32 val, vx_int8 fixedPointPos) { vx_int16 result = 0; if (fixedPointPos > 0) { vx_int32 data = (vx_int32) round(val * (vx_float32)(1 << fixedPointPos)); result = (vx_int16)((data > 32767) ? 32767 : (data < -32768) ? -32768 : data); } else { vx_int32 data = (vx_int32) round(val * (1.0f / (vx_float32)(1 << -fixedPointPos))); result = (vx_int16)((data > 32767) ? 32767 : (data < -32768) ? -32768 : data); } return result; } vx_int16 vnn_Fp32toAsymInt16(vx_float32 val, vx_int32 zeroPoint, vx_float32 scale) { vx_int16 result = 0; vx_int32 data; data = (vx_int32) round((val / scale + (vx_int16)zeroPoint)); if (data > 32767) data = 32767; if (data < -32768) data = -32768; result = (vx_int16)(data); return result; } vx_float32 vnn_AsymInt16toFp32(vx_int16 val, vx_int32 zeroPoint, vx_float32 scale) { vx_float32 result = 0.0f; result = (val - (vx_int16)zeroPoint) * scale; return result; } vx_int16 vnn_Fp32toFp16(vx_float32 val) { #define F16_EXPONENT_BITS 0x1F #define F16_EXPONENT_BIAS 15 #define F16_EXPONENT_SHIFT 10 #define F16_MANTISSA_BITS ((1 << F16_EXPONENT_SHIFT) - 1) #define F16_MANTISSA_SHIFT (23 - F16_EXPONENT_SHIFT) #define F16_MAX_EXPONENT (F16_EXPONENT_BITS << F16_EXPONENT_SHIFT) vx_uint32 f32 = (*(vx_uint32 *) &val); vx_int16 f16 = 0; /* Decode IEEE 754 little-endian 32-bit floating-point value */ int sign = (f32 >> 16) & 0x8000; /* Map exponent to the range [-127,128] */ int exponent = ((f32 >> 23) & 0xff) - 127; int mantissa = f32 & 0x007fffff; if (exponent == 128) { /* Infinity or NaN */ if (mantissa) { /* Flush NaN to 0. */ f16 = (vx_int16)sign; } else { /* Clamp to HALF_MAX/HALF_MIN. */ f16 = (vx_int16)(sign | ((F16_EXPONENT_BITS - 1) << F16_EXPONENT_SHIFT) | F16_MANTISSA_BITS); } } else if (exponent > 15) { /* Overflow - clamp to HALF_MAX/HALF_MIN. */ f16 = (vx_int16)(sign | ((F16_EXPONENT_BITS - 1) << F16_EXPONENT_SHIFT) | F16_MANTISSA_BITS); } else if (exponent > -15) { /* Representable value */ /* RTNE */ int roundingBit = (mantissa >> (F16_MANTISSA_SHIFT - 1)) & 0x1; int stickyBits = mantissa & 0xFFF; exponent += F16_EXPONENT_BIAS; mantissa >>= F16_MANTISSA_SHIFT; if (roundingBit) { if (stickyBits || (mantissa & 0x1)) { mantissa++; if (mantissa > F16_MANTISSA_BITS) { exponent++; if (exponent > 30) { /* Clamp to HALF_MAX/HALF_MIN. */ exponent--; mantissa--; } else { mantissa &= F16_MANTISSA_BITS; } } } } f16 = (vx_int16)(sign | exponent << F16_EXPONENT_SHIFT | mantissa); } else { f16 = (vx_int16)sign; } return f16; } vx_float32 vnn_Fp16toFp32(const vx_uint16 in) { vx_uint32 t1; vx_uint32 t2; vx_uint32 t3; vx_float32 out; t1 = in & 0x7fff; // Non-sign bits t2 = in & 0x8000; // Sign bit t3 = in & 0x7c00; // Exponent t1 <<= 13; // Align mantissa on MSB t2 <<= 16; // Shift sign bit into position t1 += 0x38000000; // Adjust bias t1 = (t3 == 0 ? 0 : t1); // Denormals-as-zero t1 |= t2; // Re-insert sign bit *((uint32_t*)&out) = t1; return out; } vx_uint32 vnn_GetTensorSize(vx_tensor tensor) { vx_uint32 size[6]; vx_uint32 num=1,num_of_dim=0; vx_uint32 i = 0; vxQueryTensor(tensor, VX_TENSOR_NUMBER_OF_DIMS, &num_of_dim, sizeof(num_of_dim)); vxQueryTensor(tensor, VX_TENSOR_DIMS, size, sizeof(size)); for(i = 0; i < num_of_dim;i++) num = num*size[i]; return num; } vx_uint32 vnn_GetTensorDims(vx_tensor tensor) { vx_uint32 size[6]; vx_uint32 num_of_dim=0; vxQueryTensor(tensor, VX_TENSOR_NUMBER_OF_DIMS, &num_of_dim, sizeof(num_of_dim)); return num_of_dim; } vx_uint32 vnn_GetTensorBufferSize(vx_tensor tensor) { vx_uint32 size[6]; vx_uint32 num=1,num_of_dim=0; vx_enum data_format; vx_uint32 i = 0; vxQueryTensor(tensor, VX_TENSOR_NUMBER_OF_DIMS, &num_of_dim, sizeof(num_of_dim)); vxQueryTensor(tensor, VX_TENSOR_DIMS, size, sizeof(size)); vxQueryTensor(tensor, VX_TENSOR_DATA_TYPE, &data_format, sizeof(data_format)); num = vnn_GetTypeSize(data_format); for(i = 0; i < num_of_dim;i++) num = num*size[i]; return num; } vx_status vnn_CopyTensorToData(vx_tensor tensor,void **buf) { vx_uint32 size[MAX_NUM_DIMS]; vx_size stride[MAX_NUM_DIMS]; vx_size start[MAX_NUM_DIMS]; vx_size end[MAX_NUM_DIMS]; vx_uint32 num_of_dim=0; vx_status status = VX_SUCCESS; vx_uint32 i = 0; vx_enum data_format; vx_uint32 data_size = 0; vx_context context = vxGetContext((vx_reference)tensor); status |= vxQueryTensor(tensor, VX_TENSOR_NUMBER_OF_DIMS, &num_of_dim, sizeof(num_of_dim)); status |=vxQueryTensor(tensor, VX_TENSOR_DIMS, size, sizeof(size)); status |=vxQueryTensor(tensor, VX_TENSOR_DATA_TYPE, &data_format, sizeof(data_format)); stride[0] = vnn_GetTypeSize(data_format); for (i=0; i< num_of_dim; i++) { start[i] = 0; end[i] = (vx_size)size[i]; if(i>0) { stride[i] = stride[i - 1] * size[i - 1]; } } data_size = vnn_GetTensorBufferSize(tensor); if(*buf == NULL) *buf = (void*)malloc(data_size); status = vxCopyTensorPatch(tensor, num_of_dim,start,end,stride,(void*)*buf, VX_READ_ONLY,0); return status; } vx_status vnn_CopyTensorToFloat32Data(vx_tensor tensor,vx_float32 **buf) { vx_uint32 size[6]; vx_uint32 stride_size[6]; vx_uint32 num=1,num_of_dim=0; vx_tensor_addressing user_addr = NULL; vx_status status = VX_SUCCESS; vx_uint32 i = 0; vx_enum data_format,quant_format; vx_uint32 data_size = 0; vx_context context = vxGetContext((vx_reference)tensor); void *data = NULL; status |=vxQueryTensor(tensor, VX_TENSOR_DATA_TYPE, &data_format, sizeof(data_format)); status |=vxQueryTensor(tensor, VX_TENSOR_QUANT_FORMAT, &quant_format, sizeof(data_format)); num = vnn_GetTensorSize(tensor); if(*buf == NULL) *buf = (vx_float32*)malloc(num * sizeof(vx_float32)); status |= vnn_CopyTensorToData(tensor,&data); if(quant_format == VX_QUANT_DYNAMIC_FIXED_POINT && data_format == VX_TYPE_INT8) { vx_int8 fl=0; status |=vxQueryTensor(tensor, VX_TENSOR_FIXED_POINT_POSITION, &fl, sizeof(fl)); if(data_format == VX_TYPE_INT8) { for(i = 0;i < num; i++) (*buf)[i]= vnn_Int8toFp32( ((vx_int8*)data)[i],fl); } } else if(quant_format == VX_QUANT_DYNAMIC_FIXED_POINT && data_format == VX_TYPE_INT16) { vx_int8 fl=0; status |=vxQueryTensor(tensor, VX_TENSOR_FIXED_POINT_POSITION, &fl, sizeof(fl)); for(i = 0;i < num; i++) (*buf)[i]= vnn_Int16toFp32( ((vx_int16*)data)[i],fl); } else if(quant_format == VX_QUANT_AFFINE_SCALE && data_format == VX_TYPE_UINT8) { vx_int32 zp=0; vx_float32 scale; status |=vxQueryTensor(tensor, VX_TENSOR_ZERO_POINT, &zp, sizeof(zp)); status |=vxQueryTensor(tensor, VX_TENSOR_SCALE, &scale, sizeof(scale)); for(i = 0;i < num; i++) (*buf)[i]= vnn_Uint8toFp32( ((vx_uint8*)data)[i],zp,scale); } else if(quant_format == VX_QUANT_AFFINE_SCALE && data_format == VX_TYPE_INT8) { vx_int32 zp=0; vx_float32 scale; status |=vxQueryTensor(tensor, VX_TENSOR_ZERO_POINT, &zp, sizeof(zp)); status |=vxQueryTensor(tensor, VX_TENSOR_SCALE, &scale, sizeof(scale)); for(i = 0;i < num; i++) (*buf)[i]= vnn_AsymInt8toFp32( ((vx_int8*)data)[i],zp,scale); } else if(quant_format == VX_QUANT_AFFINE_SCALE && data_format == VX_TYPE_INT16) { vx_int32 zp=0; vx_float32 scale; status |=vxQueryTensor(tensor, VX_TENSOR_ZERO_POINT, &zp, sizeof(zp)); status |=vxQueryTensor(tensor, VX_TENSOR_SCALE, &scale, sizeof(scale)); for(i = 0;i < num; i++) (*buf)[i]= vnn_AsymInt16toFp32( ((vx_int8*)data)[i],zp,scale); } else if (quant_format ==VX_QUANT_NONE && data_format == VX_TYPE_UINT8) { for(i = 0;i < num; i++) (*buf)[i] = ((vx_uint8*)data)[i]; } else if(data_format == VX_TYPE_FLOAT16)/*VX_QUANT_NONE*/ { for(i = 0;i < num; i++) (*buf)[i]= vnn_Fp16toFp32( ((vx_int16*)data)[i]); } else if(data_format == VX_TYPE_FLOAT32)/*VX_QUANT_NONE*/ { for(i = 0;i < num; i++) (*buf)[i] = ((vx_float32*)data)[i]; } else if(quant_format ==VX_QUANT_NONE && data_format == VX_TYPE_INT32)/*VX_QUANT_NONE*/ { for(i = 0;i < num; i++) (*buf)[i] = (vx_float32)(((vx_int32*)data)[i]); } else if(quant_format ==VX_QUANT_NONE && data_format == VX_TYPE_UINT32)/*VX_QUANT_NONE*/ { for(i = 0;i < num; i++) (*buf)[i] = (vx_float32)(((vx_uint32*)data)[i]); } else { printf("can't support format!\n"); status = VX_FAILURE; } if(data){ free(data); } return status; } vx_status vnn_CopyDataToTensor(vx_tensor tensor,void *buf) { vx_uint32 size[MAX_NUM_DIMS]; vx_size stride[MAX_NUM_DIMS]; vx_size start[MAX_NUM_DIMS]; vx_size end[MAX_NUM_DIMS]; vx_uint32 num_of_dim=0; vx_tensor_addressing user_addr = NULL; vx_status status = VX_SUCCESS; vx_uint32 i = 0; vx_enum data_format; vx_uint32 data_size = 0; vx_context context = vxGetContext((vx_reference)tensor); status |= vxQueryTensor(tensor, VX_TENSOR_NUMBER_OF_DIMS, &num_of_dim, sizeof(num_of_dim)); status |=vxQueryTensor(tensor, VX_TENSOR_DIMS, size, sizeof(size)); status |=vxQueryTensor(tensor, VX_TENSOR_DATA_TYPE, &data_format, sizeof(data_format)); stride[0] = vnn_GetTypeSize(data_format); for (i=0; i< num_of_dim; i++) { start[i] = 0; end[i] = (vx_size)size[i]; if(i>0) { stride[i] = stride[i - 1] * size[i - 1]; } } status = vxCopyTensorPatch(tensor, num_of_dim,start,end,stride,buf, VX_WRITE_ONLY,0); return status; } vx_status vnn_CopyFloat32DataToTensor(vx_tensor tensor,vx_float32 *buf) { vx_uint32 size[6]; vx_uint32 stride_size[6]; vx_uint32 num=1,num_of_dim=0; vx_tensor_addressing user_addr = NULL; vx_status status = VX_SUCCESS; vx_uint32 i = 0; vx_enum data_format,quant_format; vx_uint32 data_size = 0; vx_context context = vxGetContext((vx_reference)tensor); void *data = NULL; status |=vxQueryTensor(tensor, VX_TENSOR_DATA_TYPE, &data_format, sizeof(data_format)); status |=vxQueryTensor(tensor, VX_TENSOR_QUANT_FORMAT, &quant_format, sizeof(data_format)); num = vnn_GetTensorSize(tensor); data = (void*)malloc(vnn_GetTensorBufferSize(tensor)); if(quant_format == VX_QUANT_DYNAMIC_FIXED_POINT && data_format == VX_TYPE_INT8) { vx_int8 fl=0; status |=vxQueryTensor(tensor, VX_TENSOR_FIXED_POINT_POSITION, &fl, sizeof(fl)); if(data_format == VX_TYPE_INT8) { for(i = 0;i < num; i++) ((vx_int8*)data)[i] = vnn_Fp32toInt8(buf[i],fl); } } else if(quant_format == VX_QUANT_DYNAMIC_FIXED_POINT && data_format == VX_TYPE_INT16) { vx_int8 fl=0; status |=vxQueryTensor(tensor, VX_TENSOR_FIXED_POINT_POSITION, &fl, sizeof(fl)); for(i = 0;i < num; i++) ((vx_int16*)data)[i] = vnn_Fp32toInt16(buf[i],fl); } else if(quant_format == VX_QUANT_AFFINE_SCALE && data_format == VX_TYPE_UINT8) { vx_int32 zp=0; vx_float32 scale; status |=vxQueryTensor(tensor, VX_TENSOR_ZERO_POINT, &zp, sizeof(zp)); status |=vxQueryTensor(tensor, VX_TENSOR_SCALE, &scale, sizeof(scale)); for(i = 0;i < num; i++) ((vx_uint8*)data)[i] = vnn_Fp32toUint8(buf[i],zp,scale); } else if(quant_format == VX_QUANT_AFFINE_SCALE && data_format == VX_TYPE_INT8) { vx_int32 zp=0; vx_float32 scale; status |=vxQueryTensor(tensor, VX_TENSOR_ZERO_POINT, &zp, sizeof(zp)); status |=vxQueryTensor(tensor, VX_TENSOR_SCALE, &scale, sizeof(scale)); for(i = 0;i < num; i++) ((vx_int8*)data)[i] = vnn_Fp32toAsymInt8(buf[i],zp,scale); } else if(quant_format == VX_QUANT_AFFINE_SCALE && data_format == VX_TYPE_INT16) { vx_int32 zp=0; vx_float32 scale; status |=vxQueryTensor(tensor, VX_TENSOR_ZERO_POINT, &zp, sizeof(zp)); status |=vxQueryTensor(tensor, VX_TENSOR_SCALE, &scale, sizeof(scale)); for(i = 0;i < num; i++) ((vx_int16*)data)[i] = vnn_Fp32toAsymInt16(buf[i],zp,scale); } else if(quant_format == VX_QUANT_NONE && data_format == VX_TYPE_UINT8) { for(i = 0;i < num; i++) ((vx_uint8*)data)[i] = (vx_uint8)buf[i]; } else if(data_format == VX_TYPE_FLOAT16)/*VX_QUANT_NONE*/ { for(i = 0;i < num; i++) ((vx_int16*)data)[i] = vnn_Fp32toFp16(buf[i]); } else if(data_format == VX_TYPE_FLOAT32)/*VX_QUANT_NONE*/ { for(i = 0;i < num; i++) ((vx_float32*)data)[i] = buf[i]; } else if(quant_format == VX_QUANT_NONE && data_format == VX_TYPE_INT32)/*VX_QUANT_NONE*/ { for(i = 0;i < num; i++) ((vx_int32*)data)[i] = (vx_int32)buf[i]; } else if(quant_format == VX_QUANT_NONE && data_format == VX_TYPE_UINT32)/*VX_QUANT_NONE*/ { for(i = 0;i < num; i++) ((vx_uint32*)data)[i] = (vx_uint32)buf[i]; } else { printf("can't support format!\n"); status = VX_FAILURE; } status |= vnn_CopyDataToTensor(tensor,data); if(data){ free(data); } return status; } static file_type get_file_type(const char *file_name) { const char *ptr; char sep = '.'; uint32_t pos,n; char buff[32] = {0}; ptr = strrchr(file_name, sep); pos = ptr - file_name; n = strlen(file_name) - (pos + 1); strncpy(buff, file_name+(pos+1), n); if(strcmp(buff, "tensor") == 0 || strcmp(buff, "txt") == 0) { return FILE_TYPE_TEXT; } else if(strcmp(buff, "bin") == 0 || strcmp(buff, "dat") == 0) { return FILE_TYPE_BIN; } else { return FILE_TYPE_NOT_SUPPORT; } } vx_status vnn_LoadTensorRandom(vx_tensor tensor) { vx_status status = VX_SUCCESS; vx_int32 i=0; char dumpInput[128]; vx_int32 num = vnn_GetTensorSize(tensor); vx_uint8 *buf = (vx_uint8*)malloc(num*sizeof(vx_uint8)); memset(buf, 0, num * sizeof(vx_uint8)); status |= vnn_CopyDataToTensor(tensor,buf); _CHECK_STATUS(status, exit); //printf("Info: Copied a buffer of a size of %d to tensor.\n", num); snprintf(dumpInput, sizeof(dumpInput), "input.dat"); vnn_SaveTensorToFileAsBinary(tensor, dumpInput); status = VX_SUCCESS; if(buf) free(buf); exit: return status; } vx_status vnn_LoadTensorFromFile(vx_tensor tensor,char *filename) { vx_status status = VX_SUCCESS; vx_int32 i=0; file_type ft = get_file_type(filename); if(ft == FILE_TYPE_TEXT) /*tensor*/ { vx_int32 num = vnn_GetTensorSize(tensor); vx_float32 *buf = (vx_float32*)malloc(num*sizeof(vx_float32)); FILE *fp = fopen(filename,"r"); if(fp) { for(i = 0;i < num;i++) { vx_int32 ret = fscanf(fp,"%f",&buf[i]); if(ret <=0 ) { printf("There is no enough data!\n"); status = VX_FAILURE; break; } } status |= vnn_CopyFloat32DataToTensor(tensor,buf); } else { printf("can't open file %s\n",filename); status |= VX_FAILURE; } if(buf){ free(buf); } if(fp) fclose(fp); } else if(ft == FILE_TYPE_BIN) /*dat or bin*/ { vx_int32 size = vnn_GetTensorBufferSize(tensor); void *buf = (void*)malloc(size); FILE *fp = fopen(filename,"rb"); if(fp) { vx_int32 ret = fread(buf,1,size,fp); if(ret < size) { printf("There is no enough data!\n"); status = VX_FAILURE; } vnn_CopyDataToTensor(tensor,buf); } else { printf("can't open file %s\n",filename); status |= VX_FAILURE; } if(buf){ free(buf); } if(fp) fclose(fp); } else { printf("not support file type:%s\n",filename); status |= VX_FAILURE; } return status; } vx_status vnn_SaveTensorToFileAsFloat32(vx_tensor tensor,char *filename) { vx_status status = VX_SUCCESS; vx_float32 *buf = NULL; vx_int32 i=0; FILE *fp = NULL; vx_uint32 size[6]; vx_uint32 num=0; num = vnn_GetTensorSize(tensor); fp = fopen(filename,"w"); if(fp) { status |= vnn_CopyTensorToFloat32Data(tensor,&buf); for(i = 0;idata_type == VX_TYPE_TENSOR) { status = vnn_LoadTensorFromFile(obj->u.tensor,filename); _CHECK_STATUS(status, exit); } else if(obj->data_type == VX_TYPE_IMAGE) { status = vnn_LoadImageFromFile(obj->u.image,filename); _CHECK_STATUS(status, exit); } else if(obj->data_type == VX_TYPE_ARRAY) { status = vnn_LoadArrayFromFile(obj->u.array,filename); _CHECK_STATUS(status, exit); } else if(obj->data_type == VX_TYPE_SCALAR) { status = vnn_LoadScalarFromFile(obj->u.scalar,filename); _CHECK_STATUS(status, exit); } else { status = VX_FAILURE; _CHECK_STATUS(status, exit); } exit: return status; } vx_status vnn_SaveDataToFile(inout_obj* obj,char *filename) { vx_status status = VX_FAILURE; if(obj->data_type == VX_TYPE_TENSOR) { file_type ft = get_file_type(filename); if(ft == FILE_TYPE_TEXT) status = vnn_SaveTensorToFileAsFloat32(obj->u.tensor,filename); else if (ft == FILE_TYPE_BIN) status = vnn_SaveTensorToFileAsBinary(obj->u.tensor,filename); else status = VX_FAILURE; _CHECK_STATUS(status, exit); } else if(obj->data_type == VX_TYPE_IMAGE) { status = vnn_SaveImageToFile(obj->u.image,filename); _CHECK_STATUS(status, exit); } else if(obj->data_type == VX_TYPE_ARRAY) { status = vnn_SaveArrayToFile(obj->u.array,filename); _CHECK_STATUS(status, exit); } else if(obj->data_type == VX_TYPE_SCALAR) { status = vnn_SaveScalarToFile(obj->u.scalar,filename); _CHECK_STATUS(status, exit); } else { status = VX_FAILURE; _CHECK_STATUS(status, exit); } exit: return status; } vx_bool get_top ( float *pfProb, float *pfMaxProb, uint32_t *pMaxClass, uint32_t outputCount, uint32_t topNum ) { uint32_t i, j; #define MAX_TOP_NUM 20 if (topNum > MAX_TOP_NUM) return vx_false_e; memset(pfMaxProb, 0, sizeof(float) * topNum); memset(pMaxClass, 0xff, sizeof(float) * topNum); for (j = 0; j < topNum; j++) { for (i=0; i *(pfMaxProb+j)) { *(pfMaxProb+j) = pfProb[i]; *(pMaxClass+j) = i; } } } return vx_true_e; } vx_status vnn_ShowTensorTop5(vx_tensor tensor) { vx_status status = VX_SUCCESS; vx_float32 *buf = NULL; vx_int32 num = vnn_GetTensorSize(tensor); uint32_t MaxClass[5]; vx_float32 fMaxProb[5]; vx_int32 i=0; status |= vnn_CopyTensorToFloat32Data(tensor,&buf); if (!get_top(buf, fMaxProb, MaxClass, num, 5)) { printf("Fail to show result.\n"); status |= VX_SUCCESS; goto final; } printf(" --- Top5 ---\n"); for(i=0; i<5; i++) { printf("%3d: %8.6f\n", MaxClass[i], fMaxProb[i]); } final: if(buf){ free(buf); } return status; } vx_status vnn_ShowTop5(inout_obj* obj) { if(obj->data_type == VX_TYPE_TENSOR) return vnn_ShowTensorTop5(obj->u.tensor); return VX_SUCCESS; } vx_status vnn_QueryInputsAndOutputsParam(vx_kernel kernel,inout_param *input,vx_int32 *in_cnt,inout_param *output,vx_int32 *out_cnt) { vx_status status = VX_SUCCESS; int i = 0; /* Query number of parameters in kernel. num_params = input_count + output_count */ vx_uint32 num_params; vx_int32 input_count=0,output_count=0; vx_enum direction = 0; vxQueryKernel(kernel, VX_KERNEL_PARAMETERS, &num_params, sizeof(vx_uint32)); for (i = 0; i < num_params; i++) { inout_param *ptrInOut = NULL; vx_parameter param_kernel = NULL; vx_meta_format meta; vx_size _dim_size[MAX_NUM_DIMS],_dim_count; param_kernel = vxGetKernelParameterByIndex(kernel, i); vxQueryParameter(param_kernel, VX_PARAMETER_DIRECTION, &direction, sizeof(enum vx_type_e)); if(direction == VX_INPUT) { ptrInOut = &input[input_count]; input_count++; } else { ptrInOut = &output[output_count]; output_count++; } vxQueryParameter(param_kernel,VX_PARAMETER_META_FORMAT,&meta, sizeof(vx_meta_format)); vxQueryMetaFormatAttribute(meta, VX_REFERENCE_TYPE, &ptrInOut->data_type, sizeof(ptrInOut->data_type)); vxQueryParameter(param_kernel,VX_PARAMETER_META_FORMAT, &meta, sizeof(vx_meta_format)); vxQueryMetaFormatAttribute(meta, VX_TENSOR_NUMBER_OF_DIMS,&_dim_count, sizeof(_dim_count)); ptrInOut->dim_count = _dim_count; vxQueryMetaFormatAttribute(meta, VX_TENSOR_DIMS, &_dim_size, sizeof(_dim_size)); for(int n = 0;ndim_count;n++) ptrInOut->dim_size[n] = _dim_size[n]; vxQueryMetaFormatAttribute(meta, VX_TENSOR_DATA_TYPE, &ptrInOut->data_format, sizeof(ptrInOut->data_format)); vxQueryMetaFormatAttribute(meta, VX_TENSOR_QUANT_FORMAT, &ptrInOut->quan_format, sizeof(ptrInOut->quan_format)); switch (ptrInOut->quan_format) { case VX_QUANT_DYNAMIC_FIXED_POINT: vxQueryMetaFormatAttribute(meta,VX_TENSOR_FIXED_POINT_POSITION, &ptrInOut->fixed_pos, sizeof(ptrInOut->fixed_pos)); break; case VX_QUANT_AFFINE_SCALE: vxQueryMetaFormatAttribute(meta, VX_TENSOR_ZERO_POINT, &ptrInOut->tf_zerop, sizeof(ptrInOut->tf_zerop)); vxQueryMetaFormatAttribute(meta, VX_TENSOR_SCALE, &ptrInOut->tf_scale, sizeof(ptrInOut->tf_scale)); break; case VX_QUANT_NONE: break; case VX_QUANT_AFFINE_SCALE_PER_CHANNEL: default: status = VX_FAILURE; printf("Quant format %u is not supported!", ptrInOut->quan_format); _CHECK_STATUS(status, exit); break; } vnn_Log("index:%d,in:%d, data_type:%d\ndim_cnt: %d, dims: %d, %d, %d, %d\nscale: %f, zp: %d, fixPos: %d\nquant_format:%d,data_format: %d\n", i,direction, ptrInOut->data_type, ptrInOut->dim_count, ptrInOut->dim_size[0], ptrInOut->dim_size[1],ptrInOut->dim_size[2], ptrInOut->dim_size[3], ptrInOut->tf_scale, ptrInOut->tf_zerop, ptrInOut->fixed_pos, ptrInOut->quan_format, ptrInOut->data_format); } *in_cnt = input_count; *out_cnt = output_count; exit: return status; } vx_status vnn_CreateObject(vx_context context, inout_param *param, inout_obj *obj) { vx_status status = VX_SUCCESS; if(param->data_type == VX_TYPE_TENSOR) { vx_tensor_create_params_t ts_params; ts_params.data_format = param->data_format; ts_params.num_of_dims = param->dim_count; ts_params.sizes = param->dim_size; ts_params.quant_format = param->quan_format; if(param->quan_format == VX_QUANT_AFFINE_SCALE) { ts_params.quant_data.affine.scale = param->tf_scale; ts_params.quant_data.affine.zeroPoint = param->tf_zerop; } else if(param->quan_format == VX_QUANT_DYNAMIC_FIXED_POINT) { ts_params.quant_data.dfp.fixed_point_pos = (vx_int8)param->fixed_pos; } else { /*nothing*/ } obj->u.tensor = vxCreateTensor2(context, &ts_params, sizeof(ts_params)); obj->data_type = param->data_type; _CHECK_OBJ(obj->u.tensor,exit); } else if (param->data_type == VX_TYPE_IMAGE) { obj->u.image = vxCreateImage(context, param->dim_size[0],param->dim_size[1],param->data_format); obj->data_type = VX_TYPE_IMAGE; _CHECK_OBJ(obj->u.image,exit); } else if (param->data_type == VX_TYPE_ARRAY) { obj->u.array = vxCreateArray(context, param->data_format, param->dim_size[0]); obj->data_type = VX_TYPE_ARRAY; _CHECK_OBJ(obj->u.array,exit); for(int i=0; i < param->dim_size[0];i++) { vx_float32 zero = 0; vxAddArrayItems(obj->u.array,1,&zero,0); } } else if (param->data_type == VX_TYPE_SCALAR) { vx_float32 num = 0; obj->u.scalar = vxCreateScalar(context, param->data_format, &num); obj->data_type = VX_TYPE_SCALAR; _CHECK_OBJ(obj->u.scalar,exit); } else { printf("Not support output data type:%d\n",param->data_type); status = VX_FAILURE; } exit: return status; } vx_status vnn_ReleaseObject(inout_obj *obj) { vx_status status = VX_SUCCESS; if(obj->data_type == VX_TYPE_TENSOR) { vxReleaseTensor( &obj->u.tensor); } else if (obj->data_type == VX_TYPE_IMAGE) { vxReleaseImage( &obj->u.image); } else if (obj->data_type == VX_TYPE_ARRAY) { vxReleaseArray( &obj->u.array); } else if (obj->data_type == VX_TYPE_SCALAR) { vxReleaseScalar( &obj->u.scalar); } else { printf("Not support output data type:%d\n",obj->data_type); status = VX_FAILURE; } return status; } void vnn_Log ( const char *fmt, ... ) { char arg_buffer[VSI_NN_MAX_DEBUG_BUFFER_LEN] = {0}; va_list arg; vx_int32 debug = 0; char *debug_s = getenv("VNN_DEBUG"); if(debug_s) { debug = atoi(debug_s); } if(debug != 1) { return ; } va_start(arg, fmt); vsnprintf(arg_buffer, VSI_NN_MAX_DEBUG_BUFFER_LEN, fmt, arg); va_end(arg); fprintf(stderr, "%s\n", arg_buffer); }