forked from nudt_dsp/netrans
584 lines
16 KiB
C
584 lines
16 KiB
C
/****************************************************************************
|
|
* Generated by NETRANS #NETRANS_VERSION#
|
|
* Match ovxlib #OVXLIB_VERSION#
|
|
*
|
|
* Neural Network application loop source file
|
|
****************************************************************************/
|
|
/*-------------------------------------------
|
|
Includes
|
|
-------------------------------------------*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#ifdef __linux__
|
|
#include <time.h>
|
|
#elif defined(_WIN32)
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#define _BASETSD_H
|
|
|
|
#include "vsi_nn_pub.h"
|
|
#include "vnn_global.h"
|
|
#include "vnn_loop.h"
|
|
|
|
/*-------------------------------------------
|
|
Types
|
|
-------------------------------------------*/
|
|
typedef struct
|
|
{
|
|
vsi_nn_tensor_attr_t attr;
|
|
uint8_t* data;
|
|
vsi_nn_size_t data_size; /* in bytes */
|
|
} vnn_internal_buffer_t;
|
|
|
|
/*-------------------------------------------
|
|
Macros and Variables
|
|
-------------------------------------------*/
|
|
#define VNN_CHECK_PTR( ptr, lbl, msg ) do {\
|
|
if( NULL == ptr ) {\
|
|
const char* message = msg ? msg : "None";\
|
|
const char* format = "Error: NULL pointer! %s: %s at %d, message: %s\n";\
|
|
printf(format, __FILE__, __FUNCTION__, __LINE__, message);\
|
|
goto lbl;\
|
|
}\
|
|
} while(0)
|
|
|
|
#define VNN_CHECK_STATUS( stat, lbl, msg ) do {\
|
|
if( VSI_SUCCESS != stat ) {\
|
|
const char* format = "Error: Status(%d) at %s:%s:%d";\
|
|
printf(format, (stat), __FILE__, __FUNCTION__, __LINE__);\
|
|
goto lbl;\
|
|
}\
|
|
} while(0)
|
|
|
|
/*-------------------------------------------
|
|
Functions
|
|
-------------------------------------------*/
|
|
|
|
/* internal buffer procedures */
|
|
vsi_status internal_buffer_init(vnn_internal_buffer_t* buffer, vsi_nn_tensor_t* tensor)
|
|
{
|
|
vsi_status status = VSI_FAILURE;
|
|
vsi_size_t element_num = 0;
|
|
vsi_size_t i = 0;
|
|
vsi_size_t stride = 0;
|
|
vsi_size_t data_size = 0;
|
|
uint8_t * data = NULL;
|
|
float default_value = 0.0f;
|
|
|
|
if( TRUE == tensor->attr.vtl )
|
|
{
|
|
VSILOGE("Internal tensors cannot be dumpped.\n");
|
|
return status;
|
|
}
|
|
|
|
if( NULL == buffer )
|
|
{
|
|
VSILOGE("Internal buffer is NULL.\n");
|
|
return status;
|
|
}
|
|
|
|
memcpy(&buffer->attr, &tensor->attr, sizeof(tensor->attr));
|
|
data_size = vsi_nn_GetTensorSize( buffer->attr.size, buffer->attr.dim_num, buffer->attr.dtype.vx_type );
|
|
element_num = vsi_nn_GetElementNum(tensor);
|
|
stride = (vsi_size_t)vsi_nn_TypeGetBytes( tensor->attr.dtype.vx_type );
|
|
|
|
data = (uint8_t *)malloc(data_size);
|
|
if( NULL == buffer )
|
|
{
|
|
printf("Out of memoery.\n");
|
|
goto error;
|
|
}
|
|
|
|
/* init data with zero */
|
|
for( i = 0; i < element_num; i++ )
|
|
{
|
|
status = vsi_nn_Float32ToDtype(default_value, data + i * stride, &buffer->attr.dtype);
|
|
VNN_CHECK_STATUS(status, error, "vsi_nn_Float32ToDtype fail");
|
|
}
|
|
|
|
buffer->data = data;
|
|
buffer->data_size = data_size;
|
|
|
|
error:
|
|
if( VSI_SUCCESS != status )
|
|
{
|
|
SAFE_FREE(data);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
vsi_status internal_buffer_deinit(vnn_internal_buffer_t* buffer)
|
|
{
|
|
vsi_status status = VSI_FAILURE;
|
|
|
|
if( NULL == buffer )
|
|
{
|
|
VSILOGE("Internal buffer is NULL.\n");
|
|
return status;
|
|
}
|
|
|
|
SAFE_FREE(buffer->data);
|
|
|
|
return VSI_SUCCESS;
|
|
}
|
|
|
|
vsi_status internal_buffer_copy_to_tensor
|
|
(
|
|
vsi_nn_graph_t* graph,
|
|
vnn_internal_buffer_t* buffer,
|
|
vsi_nn_tensor_t* tensor
|
|
)
|
|
{
|
|
vsi_status status = VSI_FAILURE;
|
|
vsi_size_t request_data_size = 0;
|
|
|
|
if( NULL == buffer )
|
|
{
|
|
VSILOGE("Internal buffer is NULL.\n");
|
|
return status;
|
|
}
|
|
|
|
request_data_size = vsi_nn_GetTensorSize( tensor->attr.size, tensor->attr.dim_num, tensor->attr.dtype.vx_type );
|
|
if( request_data_size != buffer->data_size )
|
|
{
|
|
VSILOGE("Internal buffer size error.\n");
|
|
return status;
|
|
}
|
|
|
|
status = vsi_nn_CopyDataToTensor(graph, tensor, buffer->data);
|
|
|
|
return status;
|
|
}
|
|
|
|
static vsi_status internal_buffer_copy_from_tensor
|
|
(
|
|
vsi_nn_graph_t* graph,
|
|
vnn_internal_buffer_t* buffer,
|
|
vsi_nn_tensor_t* tensor
|
|
)
|
|
{
|
|
vsi_status status = VSI_FAILURE;
|
|
vsi_size_t request_data_size = 0;
|
|
uint8_t* data = NULL;
|
|
|
|
if( NULL == buffer )
|
|
{
|
|
VSILOGE("Internal buffer is NULL.\n");
|
|
return status;
|
|
}
|
|
|
|
request_data_size = vsi_nn_GetTensorSize( tensor->attr.size, tensor->attr.dim_num, tensor->attr.dtype.vx_type );
|
|
if( request_data_size != buffer->data_size )
|
|
{
|
|
VSILOGE("Internal buffer size error.\n");
|
|
return status;
|
|
}
|
|
|
|
data = vsi_nn_ConvertTensorToData( graph, tensor );
|
|
if(buffer->data && data)
|
|
{
|
|
memcpy(buffer->data, data, request_data_size);
|
|
status = VSI_SUCCESS;
|
|
}
|
|
|
|
VSI_SAFE_FREE(data);
|
|
|
|
return status;
|
|
}
|
|
/* internal buffer procedures end */
|
|
|
|
/* common procedures */
|
|
uint32_t load_bin_data
|
|
(
|
|
const char* fname,
|
|
uint8_t** buffer_ptr,
|
|
uint32_t* buffer_sz
|
|
)
|
|
{
|
|
FILE *fp = NULL;
|
|
uint32_t fsize = 0;
|
|
uint32_t read_size = 0;
|
|
uint8_t* buffer = NULL;
|
|
/* load data from file */
|
|
fp = fopen(fname, "rb");
|
|
if( !fp )
|
|
{
|
|
fsize = 0;
|
|
goto final;
|
|
}
|
|
|
|
fsize = fseek(fp, 0, SEEK_END);
|
|
fsize = ftell(fp);
|
|
|
|
buffer = (uint8_t *)malloc(fsize);
|
|
fseek(fp, 0, SEEK_SET);
|
|
read_size = fread(buffer, 1, fsize, fp);
|
|
if(read_size != fsize)
|
|
{
|
|
fsize = 0;
|
|
free(buffer);
|
|
buffer = NULL;
|
|
goto final;
|
|
}
|
|
if(buffer_ptr != NULL)
|
|
{
|
|
*buffer_ptr = buffer;
|
|
}
|
|
if(buffer_sz != NULL)
|
|
{
|
|
*buffer_sz = read_size;
|
|
}
|
|
final:
|
|
if(!fsize)
|
|
{
|
|
printf("load data from %s fail!\n", fname);
|
|
}
|
|
if(fp)
|
|
{
|
|
fclose(fp);
|
|
}
|
|
return fsize;
|
|
}
|
|
|
|
uint32_t load_tensor_data_fp32
|
|
(
|
|
const char* fname,
|
|
uint8_t** buffer_ptr,
|
|
uint32_t* buffer_sz
|
|
)
|
|
{
|
|
float fval = 0.0;
|
|
uint32_t i = 0;
|
|
uint8_t* buffer = NULL;
|
|
uint32_t item_ount = 0;
|
|
uint32_t read_size = 0;
|
|
uint32_t stride = sizeof(fval);
|
|
FILE *fp = NULL;
|
|
|
|
fp = fopen(fname, "rb");
|
|
if( !fp )
|
|
{
|
|
read_size = 0;
|
|
goto final;
|
|
}
|
|
|
|
while(!feof(fp) && fscanf( fp, "%f ", &fval ) == 1)
|
|
{
|
|
item_ount++;
|
|
}
|
|
|
|
if( item_ount > 0 )
|
|
{
|
|
read_size = item_ount * stride;
|
|
buffer = (uint8_t *)malloc(read_size);
|
|
fseek(fp, 0, SEEK_SET);
|
|
for( i = 0; i < item_ount; i++ )
|
|
{
|
|
if(fscanf( fp, "%f ", &buffer[stride * i] ) != 1)
|
|
{
|
|
printf("Read tensor file fail.\n");
|
|
printf("Please check file lines or if the file contains illegal characters\n");
|
|
free(buffer);
|
|
goto final;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(buffer_ptr != NULL)
|
|
{
|
|
*buffer_ptr = buffer;
|
|
}
|
|
if(buffer_sz != NULL)
|
|
{
|
|
*buffer_sz = read_size;
|
|
}
|
|
|
|
final:
|
|
if(!read_size)
|
|
{
|
|
printf("load data from %s fail!\n", fname);
|
|
}
|
|
if(fp)
|
|
{
|
|
fclose(fp);
|
|
}
|
|
return read_size;
|
|
}
|
|
|
|
vsi_status conditional_loop
|
|
(
|
|
vsi_nn_graph_t *graph,
|
|
prepare_input_data_func_type prepare_input_data_func,
|
|
process_output_data_func_type process_output_data_func,
|
|
void* user_data
|
|
)
|
|
{
|
|
vsi_nn_node_t* node;
|
|
vsi_nn_tensor_t* tensor;
|
|
vsi_status status = VSI_FAILURE;
|
|
vnn_internal_buffer_t* buffer_ptr = NULL; /* ptr to hold internal recurrent inputs/outputs */
|
|
uint32_t buffer_cnt = 0;
|
|
uint32_t curr_buffer_index = 0;
|
|
uint32_t i = 0, j = 0;
|
|
uint32_t iteration = 0;
|
|
uint32_t err_code = 0;
|
|
|
|
for( i = 0; i < graph->node_num; i ++ )
|
|
{
|
|
node = graph->nodes[i];
|
|
if( NULL != node )
|
|
{
|
|
switch(node->op)
|
|
{
|
|
case VSI_NN_OP_LSTMUNIT:
|
|
{
|
|
buffer_cnt += 2; /* cell state and h statue */
|
|
}
|
|
break;
|
|
|
|
case VSI_NN_OP_CONCATSHIFT:
|
|
{
|
|
buffer_cnt += 1;
|
|
}
|
|
break;
|
|
|
|
case VSI_NN_OP_SVDF:
|
|
{
|
|
buffer_cnt += 1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
buffer_ptr = (vnn_internal_buffer_t *)malloc(buffer_cnt * sizeof(vnn_internal_buffer_t));
|
|
memset(buffer_ptr, 0x00, buffer_cnt * sizeof(vnn_internal_buffer_t));
|
|
|
|
/* malloc buffer */
|
|
for( i = 0; i < graph->node_num; i ++ )
|
|
{
|
|
node = graph->nodes[i];
|
|
if( NULL != node )
|
|
{
|
|
switch(node->op)
|
|
{
|
|
case VSI_NN_OP_LSTMUNIT:
|
|
{
|
|
/* h state in/out */
|
|
tensor = vsi_nn_GetTensor( graph, node->input.tensors[1] );
|
|
status = internal_buffer_init(&buffer_ptr[curr_buffer_index], tensor);
|
|
if( VSI_SUCCESS != status )
|
|
{
|
|
goto error_handling;
|
|
}
|
|
curr_buffer_index++;
|
|
|
|
/* cell state in/out */
|
|
tensor = vsi_nn_GetTensor( graph, node->input.tensors[2] );
|
|
status = internal_buffer_init(&buffer_ptr[curr_buffer_index], tensor);
|
|
if( VSI_SUCCESS != status )
|
|
{
|
|
goto error_handling;
|
|
}
|
|
curr_buffer_index++;
|
|
}
|
|
break;
|
|
|
|
case VSI_NN_OP_CONCATSHIFT:
|
|
{
|
|
tensor = vsi_nn_GetTensor( graph, node->input.tensors[0] );
|
|
status = internal_buffer_init(&buffer_ptr[curr_buffer_index], tensor);
|
|
if( VSI_SUCCESS != status )
|
|
{
|
|
goto error_handling;
|
|
}
|
|
curr_buffer_index++;
|
|
}
|
|
break;
|
|
|
|
case VSI_NN_OP_SVDF:
|
|
{
|
|
tensor = vsi_nn_GetTensor( graph, node->input.tensors[1] );
|
|
status = internal_buffer_init(&buffer_ptr[curr_buffer_index], tensor);
|
|
if( VSI_SUCCESS != status )
|
|
{
|
|
goto error_handling;
|
|
}
|
|
curr_buffer_index++;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
while(!err_code)
|
|
{
|
|
printf("iteration %d...\n", iteration);
|
|
if(!prepare_input_data_func(graph, iteration, user_data))
|
|
{
|
|
/* No input data available */
|
|
printf("No input data available.\n");
|
|
break;
|
|
}
|
|
/* copy internal buffer in */
|
|
curr_buffer_index = 0;
|
|
for( i = 0; i < graph->node_num; i ++ )
|
|
{
|
|
node = graph->nodes[i];
|
|
if( NULL != node )
|
|
{
|
|
switch(node->op)
|
|
{
|
|
case VSI_NN_OP_LSTMUNIT:
|
|
{
|
|
/* h state in/out */
|
|
j = 1;
|
|
tensor = vsi_nn_GetTensor( graph, node->input.tensors[j] );
|
|
status = internal_buffer_copy_to_tensor( graph, &buffer_ptr[curr_buffer_index], tensor);
|
|
if( status == VSI_FAILURE )
|
|
{
|
|
goto error_handling;
|
|
}
|
|
curr_buffer_index++;
|
|
|
|
/* cell state in/out */
|
|
j = 2;
|
|
tensor = vsi_nn_GetTensor( graph, node->input.tensors[j] );
|
|
status = internal_buffer_copy_to_tensor( graph, &buffer_ptr[curr_buffer_index], tensor);
|
|
if( status == VSI_FAILURE )
|
|
{
|
|
goto error_handling;
|
|
}
|
|
curr_buffer_index++;
|
|
}
|
|
break;
|
|
|
|
case VSI_NN_OP_CONCATSHIFT:
|
|
{
|
|
j = 0;
|
|
tensor = vsi_nn_GetTensor( graph, node->input.tensors[j] );
|
|
status = internal_buffer_copy_to_tensor( graph, &buffer_ptr[curr_buffer_index], tensor);
|
|
if( VSI_SUCCESS != status )
|
|
{
|
|
goto error_handling;
|
|
}
|
|
curr_buffer_index++;
|
|
}
|
|
break;
|
|
|
|
case VSI_NN_OP_SVDF:
|
|
{
|
|
j = 1;
|
|
tensor = vsi_nn_GetTensor( graph, node->input.tensors[j] );
|
|
status = internal_buffer_copy_to_tensor( graph, &buffer_ptr[curr_buffer_index], tensor);
|
|
if( VSI_SUCCESS != status )
|
|
{
|
|
goto error_handling;
|
|
}
|
|
curr_buffer_index++;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/* process graph */
|
|
status = vsi_nn_RunGraph(graph);
|
|
|
|
/* save internal buffer */
|
|
curr_buffer_index = 0;
|
|
for( i = 0; i < graph->node_num; i++ )
|
|
{
|
|
node = graph->nodes[i];
|
|
if( NULL != node )
|
|
{
|
|
switch(node->op)
|
|
{
|
|
case VSI_NN_OP_LSTMUNIT:
|
|
{
|
|
/* h state in/out */
|
|
j = 1;
|
|
tensor = vsi_nn_GetTensor( graph, node->output.tensors[j] );
|
|
status = internal_buffer_copy_from_tensor(graph, &buffer_ptr[curr_buffer_index], tensor);
|
|
if( status == VSI_FAILURE )
|
|
{
|
|
goto error_handling;
|
|
}
|
|
curr_buffer_index++;
|
|
|
|
/* cell state in/out */
|
|
j = 2;
|
|
tensor = vsi_nn_GetTensor( graph, node->output.tensors[j] );
|
|
status = internal_buffer_copy_from_tensor(graph, &buffer_ptr[curr_buffer_index], tensor);
|
|
if( status == VSI_FAILURE )
|
|
{
|
|
goto error_handling;
|
|
}
|
|
curr_buffer_index++;
|
|
}
|
|
break;
|
|
|
|
case VSI_NN_OP_CONCATSHIFT:
|
|
{
|
|
j = 1;
|
|
tensor = vsi_nn_GetTensor( graph, node->output.tensors[j] );
|
|
status = internal_buffer_copy_from_tensor(graph, &buffer_ptr[curr_buffer_index], tensor);
|
|
if( status == VSI_FAILURE )
|
|
{
|
|
goto error_handling;
|
|
}
|
|
curr_buffer_index++;
|
|
}
|
|
break;
|
|
|
|
case VSI_NN_OP_SVDF:
|
|
{
|
|
j = 1;
|
|
tensor = vsi_nn_GetTensor( graph, node->output.tensors[j] );
|
|
status = internal_buffer_copy_from_tensor(graph, &buffer_ptr[curr_buffer_index], tensor);
|
|
if( status == VSI_FAILURE )
|
|
{
|
|
goto error_handling;
|
|
}
|
|
curr_buffer_index++;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(process_output_data_func)
|
|
{
|
|
if(!process_output_data_func(graph, iteration, user_data))
|
|
{
|
|
printf("Output condition reach.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
iteration++;
|
|
}
|
|
|
|
error_handling:
|
|
for( i = 0; i < buffer_cnt; i++ )
|
|
{
|
|
internal_buffer_deinit(&buffer_ptr[i]);
|
|
}
|
|
SAFE_FREE(buffer_ptr);
|
|
|
|
return status;
|
|
}
|