1 /*
2  * SPDX-FileCopyrightText: Copyright 2010-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the License); you may
7  * not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include "arm_nnfunctions.h"
20 #include "unity.h"
21 
22 #include "../TestData/avgpooling_int16/test_data.h"
23 #include "../TestData/avgpooling_int16_1/test_data.h"
24 #include "../TestData/avgpooling_int16_2/test_data.h"
25 #include "../TestData/avgpooling_int16_3/test_data.h"
26 #include "../Utils/validate.h"
27 
avgpooling_int16_arm_avgpool_s16(void)28 void avgpooling_int16_arm_avgpool_s16(void)
29 {
30     const arm_cmsis_nn_status expected = ARM_CMSIS_NN_SUCCESS;
31     int16_t output[AVGPOOLING_INT16_OUTPUT_C * AVGPOOLING_INT16_OUTPUT_W * AVGPOOLING_INT16_OUTPUT_H *
32                    AVGPOOLING_INT16_BATCH_SIZE] = {0};
33 
34     cmsis_nn_context ctx;
35     cmsis_nn_pool_params pool_params;
36     cmsis_nn_dims input_dims;
37     cmsis_nn_dims filter_dims;
38     cmsis_nn_dims output_dims;
39 
40     const int16_t *input_data = avgpooling_int16_input_tensor;
41 
42     input_dims.n = AVGPOOLING_INT16_BATCH_SIZE;
43     input_dims.w = AVGPOOLING_INT16_INPUT_W;
44     input_dims.h = AVGPOOLING_INT16_INPUT_H;
45     input_dims.c = AVGPOOLING_INT16_INPUT_C;
46     filter_dims.w = AVGPOOLING_INT16_FILTER_W;
47     filter_dims.h = AVGPOOLING_INT16_FILTER_H;
48     output_dims.w = AVGPOOLING_INT16_OUTPUT_W;
49     output_dims.h = AVGPOOLING_INT16_OUTPUT_H;
50     output_dims.c = AVGPOOLING_INT16_INPUT_C;
51 
52     pool_params.padding.w = AVGPOOLING_INT16_PADDING_W;
53     pool_params.padding.h = AVGPOOLING_INT16_PADDING_H;
54     pool_params.stride.w = AVGPOOLING_INT16_STRIDE_W;
55     pool_params.stride.h = AVGPOOLING_INT16_STRIDE_H;
56 
57     pool_params.activation.min = AVGPOOLING_INT16_ACTIVATION_MIN;
58     pool_params.activation.max = AVGPOOLING_INT16_ACTIVATION_MAX;
59 
60     ctx.size = arm_avgpool_s16_get_buffer_size(AVGPOOLING_INT16_OUTPUT_W, AVGPOOLING_INT16_INPUT_C);
61     ctx.buf = malloc(ctx.size);
62 
63     arm_cmsis_nn_status result =
64         arm_avgpool_s16(&ctx, &pool_params, &input_dims, input_data, &filter_dims, &output_dims, output);
65 
66     if (ctx.buf)
67     {
68         // The caller is responsible to clear the scratch buffers for security reasons if applicable.
69         memset(ctx.buf, 0, ctx.size);
70         free(ctx.buf);
71     }
72     TEST_ASSERT_EQUAL(expected, result);
73     TEST_ASSERT_TRUE(validate_s16(output,
74                                   avgpooling_int16_output,
75                                   AVGPOOLING_INT16_OUTPUT_C * AVGPOOLING_INT16_OUTPUT_W * AVGPOOLING_INT16_OUTPUT_H *
76                                       AVGPOOLING_INT16_BATCH_SIZE));
77 }
78 
avgpooling_int16_1_arm_avgpool_s16(void)79 void avgpooling_int16_1_arm_avgpool_s16(void)
80 {
81     const arm_cmsis_nn_status expected = ARM_CMSIS_NN_SUCCESS;
82     int16_t output[AVGPOOLING_INT16_1_OUTPUT_C * AVGPOOLING_INT16_1_OUTPUT_W * AVGPOOLING_INT16_1_OUTPUT_H *
83                    AVGPOOLING_INT16_1_BATCH_SIZE] = {0};
84 
85     cmsis_nn_context ctx;
86     cmsis_nn_pool_params pool_params;
87     cmsis_nn_dims input_dims;
88     cmsis_nn_dims filter_dims;
89     cmsis_nn_dims output_dims;
90 
91     const int16_t *input_data = avgpooling_int16_1_input_tensor;
92 
93     input_dims.n = AVGPOOLING_INT16_1_BATCH_SIZE;
94     input_dims.w = AVGPOOLING_INT16_1_INPUT_W;
95     input_dims.h = AVGPOOLING_INT16_1_INPUT_H;
96     input_dims.c = AVGPOOLING_INT16_1_INPUT_C;
97     filter_dims.w = AVGPOOLING_INT16_1_FILTER_W;
98     filter_dims.h = AVGPOOLING_INT16_1_FILTER_H;
99     output_dims.w = AVGPOOLING_INT16_1_OUTPUT_W;
100     output_dims.h = AVGPOOLING_INT16_1_OUTPUT_H;
101     output_dims.c = AVGPOOLING_INT16_1_INPUT_C;
102 
103     pool_params.padding.w = AVGPOOLING_INT16_1_PADDING_W;
104     pool_params.padding.h = AVGPOOLING_INT16_1_PADDING_H;
105     pool_params.stride.w = AVGPOOLING_INT16_1_STRIDE_W;
106     pool_params.stride.h = AVGPOOLING_INT16_1_STRIDE_H;
107 
108     pool_params.activation.min = AVGPOOLING_INT16_1_ACTIVATION_MIN;
109     pool_params.activation.max = AVGPOOLING_INT16_1_ACTIVATION_MAX;
110 
111     ctx.size = arm_avgpool_s16_get_buffer_size(AVGPOOLING_INT16_1_OUTPUT_W, AVGPOOLING_INT16_1_INPUT_C);
112     ctx.buf = malloc(ctx.size);
113 
114     arm_cmsis_nn_status result =
115         arm_avgpool_s16(&ctx, &pool_params, &input_dims, input_data, &filter_dims, &output_dims, output);
116 
117     if (ctx.buf)
118     {
119         memset(ctx.buf, 0, ctx.size);
120         free(ctx.buf);
121     }
122     TEST_ASSERT_EQUAL(expected, result);
123     TEST_ASSERT_TRUE(validate_s16(output,
124                                   avgpooling_int16_1_output,
125                                   AVGPOOLING_INT16_1_OUTPUT_C * AVGPOOLING_INT16_1_OUTPUT_W *
126                                       AVGPOOLING_INT16_1_OUTPUT_H * AVGPOOLING_INT16_1_BATCH_SIZE));
127 }
128 
avgpooling_int16_2_arm_avgpool_s16(void)129 void avgpooling_int16_2_arm_avgpool_s16(void)
130 {
131     const arm_cmsis_nn_status expected = ARM_CMSIS_NN_SUCCESS;
132     int16_t output[AVGPOOLING_INT16_2_OUTPUT_C * AVGPOOLING_INT16_2_OUTPUT_W * AVGPOOLING_INT16_2_OUTPUT_H *
133                    AVGPOOLING_INT16_2_BATCH_SIZE] = {0};
134 
135     cmsis_nn_context ctx;
136     cmsis_nn_pool_params pool_params;
137     cmsis_nn_dims input_dims;
138     cmsis_nn_dims filter_dims;
139     cmsis_nn_dims output_dims;
140 
141     const int16_t *input_data = avgpooling_int16_2_input_tensor;
142 
143     input_dims.n = AVGPOOLING_INT16_2_BATCH_SIZE;
144     input_dims.w = AVGPOOLING_INT16_2_INPUT_W;
145     input_dims.h = AVGPOOLING_INT16_2_INPUT_H;
146     input_dims.c = AVGPOOLING_INT16_2_INPUT_C;
147     filter_dims.w = AVGPOOLING_INT16_2_FILTER_W;
148     filter_dims.h = AVGPOOLING_INT16_2_FILTER_H;
149     output_dims.w = AVGPOOLING_INT16_2_OUTPUT_W;
150     output_dims.h = AVGPOOLING_INT16_2_OUTPUT_H;
151     output_dims.c = AVGPOOLING_INT16_2_INPUT_C;
152 
153     pool_params.padding.w = AVGPOOLING_INT16_2_PADDING_W;
154     pool_params.padding.h = AVGPOOLING_INT16_2_PADDING_H;
155     pool_params.stride.w = AVGPOOLING_INT16_2_STRIDE_W;
156     pool_params.stride.h = AVGPOOLING_INT16_2_STRIDE_H;
157 
158     pool_params.activation.min = AVGPOOLING_INT16_2_ACTIVATION_MIN;
159     pool_params.activation.max = AVGPOOLING_INT16_2_ACTIVATION_MAX;
160 
161     ctx.size = arm_avgpool_s16_get_buffer_size(AVGPOOLING_INT16_2_OUTPUT_W, AVGPOOLING_INT16_2_INPUT_C);
162     ctx.buf = malloc(ctx.size);
163 
164     arm_cmsis_nn_status result =
165         arm_avgpool_s16(&ctx, &pool_params, &input_dims, input_data, &filter_dims, &output_dims, output);
166 
167     if (ctx.buf)
168     {
169         memset(ctx.buf, 0, ctx.size);
170         free(ctx.buf);
171     }
172     TEST_ASSERT_EQUAL(expected, result);
173     TEST_ASSERT_TRUE(validate_s16(output,
174                                   avgpooling_int16_2_output,
175                                   AVGPOOLING_INT16_2_OUTPUT_C * AVGPOOLING_INT16_2_OUTPUT_W *
176                                       AVGPOOLING_INT16_2_OUTPUT_H * AVGPOOLING_INT16_2_BATCH_SIZE));
177 }
178 
avgpooling_int16_3_arm_avgpool_s16(void)179 void avgpooling_int16_3_arm_avgpool_s16(void)
180 {
181     const arm_cmsis_nn_status expected = ARM_CMSIS_NN_SUCCESS;
182     int16_t output[AVGPOOLING_INT16_3_OUTPUT_C * AVGPOOLING_INT16_3_OUTPUT_W * AVGPOOLING_INT16_3_OUTPUT_H *
183                    AVGPOOLING_INT16_3_BATCH_SIZE] = {0};
184 
185     cmsis_nn_context ctx;
186     cmsis_nn_pool_params pool_params;
187     cmsis_nn_dims input_dims;
188     cmsis_nn_dims filter_dims;
189     cmsis_nn_dims output_dims;
190 
191     const int16_t *input_data = avgpooling_int16_3_input_tensor;
192 
193     input_dims.n = AVGPOOLING_INT16_3_BATCH_SIZE;
194     input_dims.w = AVGPOOLING_INT16_3_INPUT_W;
195     input_dims.h = AVGPOOLING_INT16_3_INPUT_H;
196     input_dims.c = AVGPOOLING_INT16_3_INPUT_C;
197     filter_dims.w = AVGPOOLING_INT16_3_FILTER_W;
198     filter_dims.h = AVGPOOLING_INT16_3_FILTER_H;
199     output_dims.w = AVGPOOLING_INT16_3_OUTPUT_W;
200     output_dims.h = AVGPOOLING_INT16_3_OUTPUT_H;
201     output_dims.c = AVGPOOLING_INT16_3_INPUT_C;
202 
203     pool_params.padding.w = AVGPOOLING_INT16_3_PADDING_W;
204     pool_params.padding.h = AVGPOOLING_INT16_3_PADDING_H;
205     pool_params.stride.w = AVGPOOLING_INT16_3_STRIDE_W;
206     pool_params.stride.h = AVGPOOLING_INT16_3_STRIDE_H;
207 
208     pool_params.activation.min = AVGPOOLING_INT16_3_ACTIVATION_MIN;
209     pool_params.activation.max = AVGPOOLING_INT16_3_ACTIVATION_MAX;
210 
211     ctx.size = arm_avgpool_s16_get_buffer_size(AVGPOOLING_INT16_3_OUTPUT_W, AVGPOOLING_INT16_3_INPUT_C);
212     ctx.buf = malloc(ctx.size);
213 
214     arm_cmsis_nn_status result =
215         arm_avgpool_s16(&ctx, &pool_params, &input_dims, input_data, &filter_dims, &output_dims, output);
216 
217     if (ctx.buf)
218     {
219         memset(ctx.buf, 0, ctx.size);
220         free(ctx.buf);
221     }
222     TEST_ASSERT_EQUAL(expected, result);
223     TEST_ASSERT_TRUE(validate_s16(output,
224                                   avgpooling_int16_3_output,
225                                   AVGPOOLING_INT16_3_OUTPUT_C * AVGPOOLING_INT16_3_OUTPUT_W *
226                                       AVGPOOLING_INT16_3_OUTPUT_H * AVGPOOLING_INT16_3_BATCH_SIZE));
227 }
228 
buffer_size_mve_arm_avgpool_s16(void)229 void buffer_size_mve_arm_avgpool_s16(void)
230 {
231 #if defined(ARM_MATH_MVEI)
232     const int32_t buf_size = arm_avgpool_s16_get_buffer_size(AVGPOOLING_INT16_3_OUTPUT_W, AVGPOOLING_INT16_3_INPUT_C);
233     const int32_t mve_buf_size =
234         arm_avgpool_s16_get_buffer_size_mve(AVGPOOLING_INT16_3_OUTPUT_W, AVGPOOLING_INT16_3_INPUT_C);
235 
236     TEST_ASSERT_EQUAL(buf_size, mve_buf_size);
237 #endif
238 }
239 
buffer_size_dsp_arm_avgpool_s16(void)240 void buffer_size_dsp_arm_avgpool_s16(void)
241 {
242 #if defined(ARM_MATH_DSP) && !defined(ARM_MATH_MVEI)
243     const int32_t buf_size = arm_avgpool_s16_get_buffer_size(AVGPOOLING_INT16_3_OUTPUT_W, AVGPOOLING_INT16_3_INPUT_C);
244     const int32_t dsp_buf_size =
245         arm_avgpool_s16_get_buffer_size_dsp(AVGPOOLING_INT16_3_OUTPUT_W, AVGPOOLING_INT16_3_INPUT_C);
246 
247     TEST_ASSERT_EQUAL(buf_size, dsp_buf_size);
248 #endif
249 }
250 
avgpooling_int16_param_fail_arm_avgpool_s16(void)251 void avgpooling_int16_param_fail_arm_avgpool_s16(void)
252 {
253     const arm_cmsis_nn_status expected = ARM_CMSIS_NN_ARG_ERROR;
254     int16_t output[AVGPOOLING_INT16_3_OUTPUT_C * AVGPOOLING_INT16_3_OUTPUT_W * AVGPOOLING_INT16_3_OUTPUT_H *
255                    AVGPOOLING_INT16_3_BATCH_SIZE] = {0};
256 
257     cmsis_nn_context ctx;
258     cmsis_nn_pool_params pool_params;
259     cmsis_nn_dims input_dims;
260     cmsis_nn_dims filter_dims;
261     cmsis_nn_dims output_dims;
262 
263     const int16_t *input_data = avgpooling_int16_3_input_tensor;
264 
265     input_dims.n = 0;
266     input_dims.w = AVGPOOLING_INT16_3_INPUT_W;
267     input_dims.h = AVGPOOLING_INT16_3_INPUT_H;
268     input_dims.c = AVGPOOLING_INT16_3_INPUT_C;
269     filter_dims.w = AVGPOOLING_INT16_3_FILTER_W;
270     filter_dims.h = AVGPOOLING_INT16_3_FILTER_H;
271     output_dims.w = AVGPOOLING_INT16_3_OUTPUT_W;
272     output_dims.h = AVGPOOLING_INT16_3_OUTPUT_H;
273     output_dims.c = AVGPOOLING_INT16_3_INPUT_C;
274 
275     pool_params.padding.w = AVGPOOLING_INT16_3_PADDING_W;
276     pool_params.padding.h = AVGPOOLING_INT16_3_PADDING_H;
277     pool_params.stride.w = AVGPOOLING_INT16_3_STRIDE_W;
278     pool_params.stride.h = AVGPOOLING_INT16_3_STRIDE_H;
279 
280     pool_params.activation.min = AVGPOOLING_INT16_3_ACTIVATION_MIN;
281     pool_params.activation.max = AVGPOOLING_INT16_3_ACTIVATION_MAX;
282 
283     ctx.size = arm_avgpool_s16_get_buffer_size(AVGPOOLING_INT16_3_OUTPUT_W, AVGPOOLING_INT16_3_INPUT_C);
284     ctx.buf = malloc(ctx.size);
285 
286     arm_cmsis_nn_status result =
287         arm_avgpool_s16(&ctx, &pool_params, &input_dims, input_data, &filter_dims, &output_dims, output);
288 
289     if (ctx.buf)
290     {
291         memset(ctx.buf, 0, ctx.size);
292         free(ctx.buf);
293     }
294     TEST_ASSERT_EQUAL(expected, result);
295 }
296