[feat][nmsis] add nmsis component and nn,dsp demo

This commit is contained in:
jzlv 2021-09-26 13:38:51 +08:00
parent b2aada479b
commit 5d1126d0f0
989 changed files with 286224 additions and 0 deletions

View file

@ -0,0 +1,123 @@
/*
* Copyright (C) 2010-2020 Arm Limited or its affiliates. All rights reserved.
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* ----------------------------------------------------------------------
* Project: NMSIS NN Library
* Title: riscv_avgpool_s8.c
* Description: Pooling function implementations
*
* $Date: May 29,2020
* $Revision: V.2.0.1
*
* Target Processor: RISC-V Cores
*
* -------------------------------------------------------------------- */
#include "ref_functions.h"
#include "riscv_nnsupportfunctions.h"
/**
* @ingroup groupNN
*/
/**
* @addtogroup Pooling
* @{
*/
/*
* s8 average pooling function
*
* Refer to header file for details.
*
*/
riscv_status riscv_avgpool_s8_ref(const nmsis_nn_context *ctx,
const nmsis_nn_pool_params *pool_params,
const nmsis_nn_dims *input_dims,
const q7_t *src,
const nmsis_nn_dims *filter_dims,
const nmsis_nn_dims *output_dims,
q7_t *dst)
{
const int32_t dim_src_height = input_dims->h;
const int32_t dim_src_width = input_dims->w;
const int32_t dim_dst_height = output_dims->h;
const int32_t dim_dst_width = output_dims->w;
const int32_t stride_height = pool_params->stride.h;
const int32_t stride_width = pool_params->stride.w;
const int32_t dim_kernel_height = filter_dims->h;
const int32_t dim_kernel_width = filter_dims->w;
const int32_t padding_height = pool_params->padding.h;
const int32_t padding_width = pool_params->padding.w;
const int32_t act_min = pool_params->activation.min;
const int32_t act_max = pool_params->activation.max;
const int32_t ch_src = input_dims->c;
q15_t *bufferA = (q15_t *)ctx->buf;
/* Reference C code adapted from NMSIS-NN riscv_avepool_q7_HWC.
*/
(void)bufferA;
int16_t i_ch_in, i_x, i_y;
int16_t k_x, k_y;
for (i_y = 0; i_y < dim_dst_height; i_y++)
{
for (i_x = 0; i_x < dim_dst_width; i_x++)
{
for (i_ch_in = 0; i_ch_in < ch_src; i_ch_in++)
{
int sum = 0;
int count = 0;
for (k_y = i_y * stride_height - padding_height; k_y < i_y * stride_height - padding_height + dim_kernel_height; k_y++)
{
for (k_x = i_x * stride_width - padding_width; k_x < i_x * stride_width - padding_width + dim_kernel_width; k_x++)
{
if (k_y >= 0 && k_x >= 0 && k_y < dim_src_height && k_x < dim_src_width)
{
sum += src[i_ch_in + ch_src * (k_x + k_y * dim_src_width)];
count++;
}
}
}
sum = sum > 0 ? (sum + count / 2) / count : (sum - count / 2) / count;
sum = MAX(sum, act_min);
sum = MIN(sum, act_max);
dst[i_ch_in + ch_src * (i_x + i_y * dim_dst_width)] = sum;
}
}
}
return RISCV_MATH_SUCCESS;
}
int32_t riscv_avgpool_s8_get_buffer_size_ref(const int dim_dst_width,
const int ch_src)
{
(void)dim_dst_width;
(void)ch_src;
return 0;
}
/**
* @} end of Pooling group
*/

View file

@ -0,0 +1,204 @@
/*
* Copyright (C) 2010-2020 Arm Limited or its affiliates. All rights reserved.
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* ----------------------------------------------------------------------
* Project: NMSIS NN Library
* Title: riscv_max_pool_s8.c
* Description: Pooling function implementations
*
* $Date: June 11, 2020
* $Revision: V.2.0.0
*
* Target Processor: RISC-V Cores
*
* -------------------------------------------------------------------- */
#include "ref_functions.h"
#include "riscv_nnsupportfunctions.h"
static void compare_and_replace_if_larger_q7_ref(q7_t *base,
const q7_t *target,
int32_t length)
{
q7_t *dst = base;
const q7_t *src = target;
union riscv_nnword ref_max;
union riscv_nnword comp_max;
int32_t cnt = length >> 2;
while (cnt > 0l)
{
ref_max.word = riscv_nn_read_q7x4(dst);
comp_max.word = riscv_nn_read_q7x4_ia(&src);
if (comp_max.bytes[0] > ref_max.bytes[0])
{
ref_max.bytes[0] = comp_max.bytes[0];
}
if (comp_max.bytes[1] > ref_max.bytes[1])
{
ref_max.bytes[1] = comp_max.bytes[1];
}
if (comp_max.bytes[2] > ref_max.bytes[2])
{
ref_max.bytes[2] = comp_max.bytes[2];
}
if (comp_max.bytes[3] > ref_max.bytes[3])
{
ref_max.bytes[3] = comp_max.bytes[3];
}
write_q7x4_ia(&dst, ref_max.word);
cnt--;
}
cnt = length & 0x3;
while (cnt > 0l)
{
if (*src > *dst)
{
*dst = *src;
}
dst++;
src++;
cnt--;
}
}
static void
clamp_output_ref(q7_t *source, int32_t length, const int32_t act_min, const int32_t act_max)
{
union riscv_nnword in;
int32_t cnt = length >> 2;
while (cnt > 0l)
{
in.word = riscv_nn_read_q7x4(source);
in.bytes[0] = MAX(in.bytes[0], act_min);
in.bytes[0] = MIN(in.bytes[0], act_max);
in.bytes[1] = MAX(in.bytes[1], act_min);
in.bytes[1] = MIN(in.bytes[1], act_max);
in.bytes[2] = MAX(in.bytes[2], act_min);
in.bytes[2] = MIN(in.bytes[2], act_max);
in.bytes[3] = MAX(in.bytes[3], act_min);
in.bytes[3] = MIN(in.bytes[3], act_max);
write_q7x4_ia(&source, in.word);
cnt--;
}
cnt = length & 0x3;
while (cnt > 0l)
{
int32_t comp = *source;
comp = MAX(comp, act_min);
comp = MIN(comp, act_max);
*source++ = (int8_t)comp;
cnt--;
}
}
/**
* @ingroup groupNN
*/
/**
* @addtogroup Pooling
* @{
*/
/*
* Optimized s8 max pooling function
*
* Refer to header file for details.
*
*/
riscv_status
riscv_max_pool_s8_ref(const nmsis_nn_context *ctx,
const nmsis_nn_pool_params *pool_params,
const nmsis_nn_dims *input_dims,
const q7_t *src,
const nmsis_nn_dims *filter_dims,
const nmsis_nn_dims *output_dims,
q7_t *dst)
{
const int32_t input_y = input_dims->h;
const int32_t input_x = input_dims->w;
const int32_t output_y = output_dims->h;
const int32_t output_x = output_dims->w;
const int32_t stride_y = pool_params->stride.h;
const int32_t stride_x = pool_params->stride.w;
const int32_t kernel_y = filter_dims->h;
const int32_t kernel_x = filter_dims->w;
const int32_t pad_y = pool_params->padding.h;
const int32_t pad_x = pool_params->padding.w;
const int32_t act_min = pool_params->activation.min;
const int32_t act_max = pool_params->activation.max;
const int32_t channel_in = input_dims->c;
(void)ctx;
q7_t *dst_base = dst;
for (int i_y = 0, base_idx_y = -pad_y; i_y < output_y; base_idx_y += stride_y, i_y++)
{
for (int i_x = 0, base_idx_x = -pad_x; i_x < output_x; base_idx_x += stride_x, i_x++)
{
/* Condition for kernel start dimension: (base_idx_<x,y> + kernel_<x,y>_start) >= 0 */
const int32_t ker_y_start = MAX(0, -base_idx_y);
const int32_t ker_x_start = MAX(0, -base_idx_x);
/* Condition for kernel end dimension: (base_idx_<x,y> + kernel_<x,y>_end) < dim_src_<width,height> */
const int32_t kernel_y_end = MIN(kernel_y, input_y - base_idx_y);
const int32_t kernel_x_end = MIN(kernel_x, input_x - base_idx_x);
int count = 0;
for (int k_y = ker_y_start; k_y < kernel_y_end; k_y++)
{
for (int k_x = ker_x_start; k_x < kernel_x_end; k_x++)
{
const q7_t *start = src + channel_in * (k_x + base_idx_x + (k_y + base_idx_y) * input_x);
if (count == 0)
{
memcpy(dst, start, channel_in);
count++;
}
else
{
compare_and_replace_if_larger_q7_ref(dst, start, channel_in);
}
}
}
/* 'count' is expected to be non-zero here. */
dst += channel_in;
}
}
clamp_output_ref(dst_base, output_x * output_y * channel_in, act_min, act_max);
return RISCV_MATH_SUCCESS;
}
/**
* @} end of Pooling group
*/

View file

@ -0,0 +1,177 @@
/*
* Copyright (C) 2010-2018 Arm Limited or its affiliates. All rights reserved.
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* ----------------------------------------------------------------------
* Project: NMSIS NN Library
* Title: riscv_pool_q7_HWC.c
* Description: Pooling function implementations
*
* $Date: 17. January 2018
* $Revision: V.1.0.0
*
* Target Processor: RISC-V Cores
*
* -------------------------------------------------------------------- */
#include "ref_functions.h"
#include "riscv_nnsupportfunctions.h"
/**
* @ingroup groupNN
*/
/**
* @addtogroup Pooling
* @{
*/
/**
* @brief Q7 max pooling function
* @param[in, out] Im_in pointer to input tensor
* @param[in] dim_im_in input tensor dimention
* @param[in] ch_im_in number of input tensor channels
* @param[in] dim_kernel filter kernel size
* @param[in] padding padding sizes
* @param[in] stride convolution stride
* @param[in] dim_im_out output tensor dimension
* @param[in,out] bufferA Not used
* @param[in,out] Im_out pointer to output tensor
*
* @details
*
* The pooling function is implemented as split x-pooling then
* y-pooling.
*
* This pooling function is input-destructive. Input data is undefined
* after calling this function.
*
*/
// REMOVED
// void
// riscv_maxpool_q7_HWC_ref(q7_t * Im_in,
// const uint16_t dim_im_in,
// const uint16_t ch_im_in,
// const uint16_t dim_kernel,
// const uint16_t padding,
// const uint16_t stride, const uint16_t dim_im_out, q7_t * bufferA, q7_t * Im_out)
// {
// (void)bufferA;
// /* Run the following code as reference implementation for RISC-V Core without DSP */
// int16_t i_ch_in, i_x, i_y;
// int16_t k_x, k_y;
// for (i_ch_in = 0; i_ch_in < ch_im_in; i_ch_in++)
// {
// for (i_y = 0; i_y < dim_im_out; i_y++)
// {
// for (i_x = 0; i_x < dim_im_out; i_x++)
// {
// int max = -129;
// for (k_y = i_y * stride - padding; k_y < i_y * stride - padding + dim_kernel; k_y++)
// {
// for (k_x = i_x * stride - padding; k_x < i_x * stride - padding + dim_kernel; k_x++)
// {
// if (k_y >= 0 && k_x >= 0 && k_y < dim_im_in && k_x < dim_im_in)
// {
// if (Im_in[i_ch_in + ch_im_in * (k_x + k_y * dim_im_in)] > max)
// {
// max = Im_in[i_ch_in + ch_im_in * (k_x + k_y * dim_im_in)];
// }
// }
// }
// }
// Im_out[i_ch_in + ch_im_in * (i_x + i_y * dim_im_out)] = max;
// }
// }
// }
// }
/**
* @brief Q7 average pooling function
* @param[in,out] Im_in pointer to input tensor
* @param[in] dim_im_in input tensor dimention
* @param[in] ch_im_in number of input tensor channels
* @param[in] dim_kernel filter kernel size
* @param[in] padding padding sizes
* @param[in] stride convolution stride
* @param[in] dim_im_out output tensor dimension
* @param[in,out] bufferA pointer to buffer space for input
* @param[in,out] Im_out pointer to output tensor
*
* @details
*
* <b>Buffer size:</b>
*
* bufferA size: 2*dim_im_out*ch_im_in
*
* The pooling function is implemented as split x-pooling then
* y-pooling.
*
* This pooling function is input-destructive. Input data is undefined
* after calling this function.
*
*/
// REMOVED
// void
// riscv_avepool_q7_HWC_ref(q7_t * Im_in,
// const uint16_t dim_im_in,
// const uint16_t ch_im_in,
// const uint16_t dim_kernel,
// const uint16_t padding,
// const uint16_t stride, const uint16_t dim_im_out, q7_t * bufferA, q7_t * Im_out)
// {
// /* Run the following code as reference implementation for RISC-V Core without DSP */
// (void)bufferA;
// int16_t i_ch_in, i_x, i_y;
// int16_t k_x, k_y;
// for (i_ch_in = 0; i_ch_in < ch_im_in; i_ch_in++)
// {
// for (i_y = 0; i_y < dim_im_out; i_y++)
// {
// for (i_x = 0; i_x < dim_im_out; i_x++)
// {
// int sum = 0;
// int count = 0;
// for (k_y = i_y * stride - padding; k_y < i_y * stride - padding + dim_kernel; k_y++)
// {
// for (k_x = i_x * stride - padding; k_x < i_x * stride - padding + dim_kernel; k_x++)
// {
// if (k_y >= 0 && k_x >= 0 && k_y < dim_im_in && k_x < dim_im_in)
// {
// sum += Im_in[i_ch_in + ch_im_in * (k_x + k_y * dim_im_in)];
// count++;
// }
// }
// }
// Im_out[i_ch_in + ch_im_in * (i_x + i_y * dim_im_out)] = sum / count;
// }
// }
// }
// }
/**
* @} end of Pooling group
*/