mirror of
https://github.com/Fishwaldo/bl_mcu_sdk.git
synced 2025-07-23 21:29:17 +00:00
[feat][nmsis] add nmsis component and nn,dsp demo
This commit is contained in:
parent
b2aada479b
commit
5d1126d0f0
989 changed files with 286224 additions and 0 deletions
|
@ -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
|
||||
*/
|
|
@ -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
|
||||
*/
|
|
@ -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
|
||||
*/
|
Loading…
Add table
Add a link
Reference in a new issue