Ver Fonte

CMSIS-NN: Add multiple batch support for depthwise

* Adds multiple batch support to depthwise_conv_s8_generic and update
  wrapper to reflect that.
* Adds a unit test as well.

Change-Id: Id80d35f3550e770c01b6bb9b9810e28fa681af52
Måns Nilsson há 4 anos atrás
pai
commit
1b9265ef76
17 ficheiros alterados com 395 adições e 38 exclusões
  1. 43 34
      CMSIS/NN/Source/ConvolutionFunctions/arm_depthwise_conv_s8.c
  2. 4 4
      CMSIS/NN/Source/ConvolutionFunctions/arm_depthwise_conv_wrapper_s8.c
  3. 2 0
      CMSIS/NN/Tests/UnitTest/PregeneratedData/depthwise_mult_batches/bias.txt
  4. 31 0
      CMSIS/NN/Tests/UnitTest/PregeneratedData/depthwise_mult_batches/input.txt
  5. 25 0
      CMSIS/NN/Tests/UnitTest/PregeneratedData/depthwise_mult_batches/kernel.txt
  6. 12 0
      CMSIS/NN/Tests/UnitTest/PregeneratedData/depthwise_mult_batches/params.txt
  7. 23 0
      CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/biases_data.h
  8. 40 0
      CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/config_data.h
  9. 27 0
      CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/input_data.h
  10. 23 0
      CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/output_mult_data.h
  11. 24 0
      CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/output_ref_data.h
  12. 23 0
      CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/output_shift_data.h
  13. 26 0
      CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/test_data.h
  14. 24 0
      CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/weights_data.h
  15. 2 0
      CMSIS/NN/Tests/UnitTest/TestCases/test_arm_depthwise_conv_s8/Unity/unity_test_arm_depthwise_conv_s8.c
  16. 61 0
      CMSIS/NN/Tests/UnitTest/TestCases/test_arm_depthwise_conv_s8/test_arm_depthwise_conv_s8.c
  17. 5 0
      CMSIS/NN/Tests/UnitTest/generate_test_data.py

+ 43 - 34
CMSIS/NN/Source/ConvolutionFunctions/arm_depthwise_conv_s8.c

@@ -19,10 +19,10 @@
 /* ----------------------------------------------------------------------
  * Project:      CMSIS NN Library
  * Title:        arm_depthwise_conv_s8.c
- * Description:	 s8 version of depthwise convolution.
+ * Description:  s8 version of depthwise convolution.
  *
- * $Date:        09. October 2020
- * $Revision:    V.2.0.1
+ * $Date:        11. May 2021
+ * $Revision:    V.2.5.0
  *
  * Target Processor:  Cortex-M CPUs
  *
@@ -140,6 +140,7 @@ static void depthwise_conv_s8_mult_4(const int8_t *input,
 }
 
 static void depthwise_conv_s8_generic(const q7_t *input,
+                                      const uint16_t input_batches,
                                       const uint16_t input_x,
                                       const uint16_t input_y,
                                       const uint16_t input_ch,
@@ -165,49 +166,56 @@ static void depthwise_conv_s8_generic(const q7_t *input,
 {
     (void)output_ch;
     int i_out = 0;
-    for (int i_out_y = 0; i_out_y < output_y; i_out_y++)
+    int i_batch;
+
+    for (i_batch = 0; i_batch < input_batches; i_batch++)
     {
-        const int16_t base_idx_y = (i_out_y * stride_y) - pad_y;
-        for (int i_out_x = 0; i_out_x < output_x; i_out_x++)
+        for (int i_out_y = 0; i_out_y < output_y; i_out_y++)
         {
-            const int16_t base_idx_x = (i_out_x * stride_x) - pad_x;
-            for (int i_input_ch = 0; i_input_ch < input_ch; i_input_ch++)
+            const int16_t base_idx_y = (i_out_y * stride_y) - pad_y;
+            for (int i_out_x = 0; i_out_x < output_x; i_out_x++)
             {
-                for (int i_ch_mult = 0; i_ch_mult < ch_mult; i_ch_mult++)
+                const int16_t base_idx_x = (i_out_x * stride_x) - pad_x;
+                for (int i_input_ch = 0; i_input_ch < input_ch; i_input_ch++)
                 {
-                    const int idx_out_ch = i_ch_mult + i_input_ch * ch_mult;
-                    int32_t acc_0;
-                    /* Condition for kernel start dimension: (base_idx_<x,y> + ker_<x,y>_start) >= 0 */
-                    const int ker_y_start = MAX(0, -base_idx_y);
-                    const int ker_x_start = MAX(0, -base_idx_x);
-                    /* Condition for kernel end dimension: (base_idx_<x,y> + ker_<x,y>_end) < input_<x,y> */
-                    const int ker_y_end = MIN(kernel_y, input_y - base_idx_y);
-                    const int ker_x_end = MIN(kernel_x, input_x - base_idx_x);
-                    acc_0 = bias[idx_out_ch];
-
-                    for (int i_ker_y = ker_y_start; i_ker_y < ker_y_end; i_ker_y++)
+                    for (int i_ch_mult = 0; i_ch_mult < ch_mult; i_ch_mult++)
                     {
-                        const int32_t idx_y = base_idx_y + i_ker_y;
-                        for (int i_ker_x = ker_x_start; i_ker_x < ker_x_end; i_ker_x++)
+                        const int idx_out_ch = i_ch_mult + i_input_ch * ch_mult;
+                        int32_t acc_0;
+                        /* Condition for kernel start dimension: (base_idx_<x,y> + ker_<x,y>_start) >= 0 */
+                        const int ker_y_start = MAX(0, -base_idx_y);
+                        const int ker_x_start = MAX(0, -base_idx_x);
+                        /* Condition for kernel end dimension: (base_idx_<x,y> + ker_<x,y>_end) < input_<x,y> */
+                        const int ker_y_end = MIN(kernel_y, input_y - base_idx_y);
+                        const int ker_x_end = MIN(kernel_x, input_x - base_idx_x);
+                        acc_0 = bias[idx_out_ch];
+
+                        for (int i_ker_y = ker_y_start; i_ker_y < ker_y_end; i_ker_y++)
                         {
-                            const int32_t idx_x = base_idx_x + i_ker_x;
-                            int32_t idx_0 = (idx_y * input_x + idx_x) * input_ch + i_input_ch;
-                            int32_t ker_idx_0 = (i_ker_y * kernel_x + i_ker_x) * (input_ch * ch_mult) + idx_out_ch;
+                            const int32_t idx_y = base_idx_y + i_ker_y;
+                            for (int i_ker_x = ker_x_start; i_ker_x < ker_x_end; i_ker_x++)
+                            {
+                                const int32_t idx_x = base_idx_x + i_ker_x;
+                                int32_t idx_0 = (idx_y * input_x + idx_x) * input_ch + i_input_ch;
+                                int32_t ker_idx_0 = (i_ker_y * kernel_x + i_ker_x) * (input_ch * ch_mult) + idx_out_ch;
 
-                            acc_0 += (input[idx_0] + input_offset) * kernel[ker_idx_0];
+                                acc_0 += (input[idx_0] + input_offset) * kernel[ker_idx_0];
+                            }
                         }
-                    }
 
-                    /* Requantize and clamp output to provided range */
-                    acc_0 = arm_nn_requantize(acc_0, output_mult[idx_out_ch], output_shift[idx_out_ch]);
-                    acc_0 += output_offset;
-                    acc_0 = MAX(acc_0, output_activation_min);
-                    acc_0 = MIN(acc_0, output_activation_max);
+                        /* Requantize and clamp output to provided range */
+                        acc_0 = arm_nn_requantize(acc_0, output_mult[idx_out_ch], output_shift[idx_out_ch]);
+                        acc_0 += output_offset;
+                        acc_0 = MAX(acc_0, output_activation_min);
+                        acc_0 = MIN(acc_0, output_activation_max);
 
-                    output[i_out++] = acc_0;
+                        output[i_out++] = acc_0;
+                    }
                 }
             }
         }
+        /* Advance to the next batch */
+        input += (input_x * input_y * input_ch);
     }
 }
 
@@ -234,7 +242,7 @@ arm_status arm_depthwise_conv_s8(const cmsis_nn_context *ctx,
     (void)bias_dims;
     (void)ctx;
 
-    if (dw_conv_params->ch_mult % 4 == 0)
+    if (dw_conv_params->ch_mult % 4 == 0 && input_dims->n == 1)
     {
         depthwise_conv_s8_mult_4(input,
                                  input_dims->w,
@@ -263,6 +271,7 @@ arm_status arm_depthwise_conv_s8(const cmsis_nn_context *ctx,
     else
     {
         depthwise_conv_s8_generic(input,
+                                  input_dims->n,
                                   input_dims->w,
                                   input_dims->h,
                                   input_dims->c,

+ 4 - 4
CMSIS/NN/Source/ConvolutionFunctions/arm_depthwise_conv_wrapper_s8.c

@@ -22,8 +22,8 @@
  * Description:  Wrapper API to select appropriate depthwise conv API based
  *               on dimensions.
  *
- * $Date:        09. October 2020
- * $Revision:    V.1.0.2
+ * $Date:        11. May 2021
+ * $Revision:    V.1.0.3
  *
  * Target Processor:  Cortex-M CPUs
  *
@@ -59,7 +59,7 @@ arm_status arm_depthwise_conv_wrapper_s8(const cmsis_nn_context *ctx,
                                          q7_t *output)
 {
     arm_status status = ARM_MATH_SUCCESS;
-    if (1 == dw_conv_params->ch_mult)
+    if (1 == dw_conv_params->ch_mult && input_dims->n == 1)
     {
 #if !defined(ARM_MATH_MVEI)
         if ((filter_dims->w == 3) && (filter_dims->h == 3) && (dw_conv_params->padding.h <= 1))
@@ -119,7 +119,7 @@ int32_t arm_depthwise_conv_wrapper_s8_get_buffer_size(const cmsis_nn_dw_conv_par
     (void)dw_conv_params;
     int32_t size = 0;
 
-    if (input_dims->c == output_dims->c)
+    if (input_dims->c == output_dims->c && input_dims->n == 1)
     {
         size = arm_depthwise_conv_s8_opt_get_buffer_size(input_dims, filter_dims);
     }

+ 2 - 0
CMSIS/NN/Tests/UnitTest/PregeneratedData/depthwise_mult_batches/bias.txt

@@ -0,0 +1,2 @@
+# 3
+1.000000000000000000e+00,1.000000000000000000e+00,1.000000000000000000e+00

+ 31 - 0
CMSIS/NN/Tests/UnitTest/PregeneratedData/depthwise_mult_batches/input.txt

@@ -0,0 +1,31 @@
+# 2,5,3,3
+-1.000000000000000000e+00,-1.000000000000000000e+00,-2.000000000000000000e+00
+1.000000000000000000e+00,1.000000000000000000e+00,1.000000000000000000e+00
+-1.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00
+-1.000000000000000000e+00,1.000000000000000000e+00,-2.000000000000000000e+00
+-1.000000000000000000e+00,-1.000000000000000000e+00,-1.000000000000000000e+00
+-2.000000000000000000e+00,1.000000000000000000e+00,-1.000000000000000000e+00
+-1.000000000000000000e+00,-2.000000000000000000e+00,-2.000000000000000000e+00
+-1.000000000000000000e+00,1.000000000000000000e+00,1.000000000000000000e+00
+-2.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00
+-1.000000000000000000e+00,-1.000000000000000000e+00,0.000000000000000000e+00
+1.000000000000000000e+00,-2.000000000000000000e+00,1.000000000000000000e+00
+-1.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00
+0.000000000000000000e+00,-1.000000000000000000e+00,1.000000000000000000e+00
+0.000000000000000000e+00,1.000000000000000000e+00,-2.000000000000000000e+00
+0.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00
+-1.000000000000000000e+00,1.000000000000000000e+00,-2.000000000000000000e+00
+-1.000000000000000000e+00,-2.000000000000000000e+00,-2.000000000000000000e+00
+1.000000000000000000e+00,0.000000000000000000e+00,-2.000000000000000000e+00
+1.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00
+1.000000000000000000e+00,-2.000000000000000000e+00,-1.000000000000000000e+00
+-1.000000000000000000e+00,-1.000000000000000000e+00,1.000000000000000000e+00
+-1.000000000000000000e+00,-1.000000000000000000e+00,-1.000000000000000000e+00
+-2.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00
+1.000000000000000000e+00,0.000000000000000000e+00,1.000000000000000000e+00
+-1.000000000000000000e+00,1.000000000000000000e+00,-2.000000000000000000e+00
+0.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00
+0.000000000000000000e+00,-1.000000000000000000e+00,-1.000000000000000000e+00
+-2.000000000000000000e+00,-2.000000000000000000e+00,1.000000000000000000e+00
+0.000000000000000000e+00,1.000000000000000000e+00,1.000000000000000000e+00
+-2.000000000000000000e+00,0.000000000000000000e+00,1.000000000000000000e+00

+ 25 - 0
CMSIS/NN/Tests/UnitTest/PregeneratedData/depthwise_mult_batches/kernel.txt

@@ -0,0 +1,25 @@
+# 4,2,3,1
+0.000000000000000000e+00
+0.000000000000000000e+00
+-1.000000000000000000e+00
+-1.000000000000000000e+00
+-2.000000000000000000e+00
+1.000000000000000000e+00
+-1.000000000000000000e+00
+-1.000000000000000000e+00
+-1.000000000000000000e+00
+0.000000000000000000e+00
+-1.000000000000000000e+00
+-1.000000000000000000e+00
+0.000000000000000000e+00
+0.000000000000000000e+00
+-1.000000000000000000e+00
+0.000000000000000000e+00
+0.000000000000000000e+00
+-1.000000000000000000e+00
+1.000000000000000000e+00
+-2.000000000000000000e+00
+1.000000000000000000e+00
+-1.000000000000000000e+00
+-2.000000000000000000e+00
+-2.000000000000000000e+00

+ 12 - 0
CMSIS/NN/Tests/UnitTest/PregeneratedData/depthwise_mult_batches/params.txt

@@ -0,0 +1,12 @@
+3
+3
+3
+5
+2
+4
+2
+2
+0
+1
+2
+1

+ 23 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/biases_data.h

@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2010-2021 Arm Limited or its affiliates. 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.
+ */
+
+// Generated by generate_test_data.py using TFL version 2.4.1 as reference.
+#pragma once
+#include <stdint.h>
+
+const int32_t depthwise_mult_batches_biases[3] = {5398, 2699, 2699};

+ 40 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/config_data.h

@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010-2021 Arm Limited or its affiliates. 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.
+ */
+
+// Generated by generate_test_data.py using TFL version 2.4.1 as reference.
+#pragma once
+#define DEPTHWISE_MULT_BATCHES_OUT_CH 3
+#define DEPTHWISE_MULT_BATCHES_IN_CH 3
+#define DEPTHWISE_MULT_BATCHES_INPUT_W 3
+#define DEPTHWISE_MULT_BATCHES_INPUT_H 5
+#define DEPTHWISE_MULT_BATCHES_DST_SIZE 36
+#define DEPTHWISE_MULT_BATCHES_INPUT_SIZE 45
+#define DEPTHWISE_MULT_BATCHES_OUT_ACTIVATION_MIN -128
+#define DEPTHWISE_MULT_BATCHES_OUT_ACTIVATION_MAX 127
+#define DEPTHWISE_MULT_BATCHES_INPUT_BATCHES 2
+#define DEPTHWISE_MULT_BATCHES_INPUT_OFFSET 0
+#define DEPTHWISE_MULT_BATCHES_OUTPUT_OFFSET 0
+#define DEPTHWISE_MULT_BATCHES_FILTER_X 2
+#define DEPTHWISE_MULT_BATCHES_FILTER_Y 4
+#define DEPTHWISE_MULT_BATCHES_STRIDE_X 2
+#define DEPTHWISE_MULT_BATCHES_STRIDE_Y 2
+#define DEPTHWISE_MULT_BATCHES_PAD_X 0
+#define DEPTHWISE_MULT_BATCHES_PAD_Y 1
+#define DEPTHWISE_MULT_BATCHES_OUTPUT_W 2
+#define DEPTHWISE_MULT_BATCHES_OUTPUT_H 3
+#define DEPTHWISE_MULT_BATCHES_CH_MULT 1

+ 27 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/input_data.h

@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2010-2021 Arm Limited or its affiliates. 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.
+ */
+
+// Generated by generate_test_data.py using TFL version 2.4.1 as reference.
+#pragma once
+#include <stdint.h>
+
+const q7_t depthwise_mult_batches_input[90] = {
+    -42, -42, -85, 42,  42,  42,  -42, 0,   0,   -42, 42,  -85, -42, -42, -42, -85, 42, -42, -42, -85, -85, -42, 42,
+    42,  -85, 0,   0,   -42, -42, 0,   42,  -85, 42,  -42, 0,   0,   0,   -42, 42,  0,  42,  -85, 0,   0,   0,   -42,
+    42,  -85, -42, -85, -85, 42,  0,   -85, 42,  0,   0,   42,  -85, -42, -42, -42, 42, -42, -42, -42, -85, 0,   0,
+    42,  0,   42,  -42, 42,  -85, 0,   0,   0,   0,   -42, -42, -85, -85, 42,  0,   42, 42,  -85, 0,   42};

+ 23 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/output_mult_data.h

@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2010-2021 Arm Limited or its affiliates. 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.
+ */
+
+// Generated by generate_test_data.py using TFL version 2.4.1 as reference.
+#pragma once
+#include <stdint.h>
+
+const int32_t depthwise_mult_batches_output_mult[3] = {1629660588, 1629660588, 1629660588};

+ 24 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/output_ref_data.h

@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010-2021 Arm Limited or its affiliates. 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.
+ */
+
+// Generated by generate_test_data.py using TFL version 2.4.1 as reference.
+#pragma once
+#include <stdint.h>
+
+const q7_t depthwise_mult_batches_output_ref[36] = {2, 3, 1, 0, 1, 2, 3,  4, 7, 3,  1, 2, 0, 5, 3, 1, 1, 1,
+                                                    3, 4, 5, 1, 1, 3, -1, 8, 2, -2, 1, 1, 3, 2, 1, 3, 1, 1};

+ 23 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/output_shift_data.h

@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2010-2021 Arm Limited or its affiliates. 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.
+ */
+
+// Generated by generate_test_data.py using TFL version 2.4.1 as reference.
+#pragma once
+#include <stdint.h>
+
+const int32_t depthwise_mult_batches_output_shift[3] = {-12, -11, -11};

+ 26 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/test_data.h

@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010-2021 Arm Limited or its affiliates. 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.
+ */
+
+// Generated by generate_test_data.py using TFL version 2.4.1 as reference.
+#include "biases_data.h"
+#include "config_data.h"
+#include "input_data.h"
+#include "output_mult_data.h"
+#include "output_ref_data.h"
+#include "output_shift_data.h"
+#include "weights_data.h"

+ 24 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/depthwise_mult_batches/weights_data.h

@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010-2021 Arm Limited or its affiliates. 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.
+ */
+
+// Generated by generate_test_data.py using TFL version 2.4.1 as reference.
+#pragma once
+#include <stdint.h>
+
+const q7_t depthwise_mult_batches_weights[24] = {0, 0, -64, -127, -127, 64,  -127, -64,  -64, 0,    -64,  -64,
+                                                 0, 0, -64, 0,    0,    -64, 127,  -127, 64,  -127, -127, -127};

+ 2 - 0
CMSIS/NN/Tests/UnitTest/TestCases/test_arm_depthwise_conv_s8/Unity/unity_test_arm_depthwise_conv_s8.c

@@ -51,3 +51,5 @@ void test_stride2pad1_arm_depthwise_conv_s8(void) { stride2pad1_arm_depthwise_co
 void test_depthwise_2_arm_depthwise_conv_s8(void) { depthwise_2_arm_depthwise_conv_s8(); }
 
 void test_depthwise_out_activation_arm_depthwise_conv_s8(void) { depthwise_out_activation_arm_depthwise_conv_s8(); }
+
+void test_depthwise_mult_batches_arm_depthwise_conv_s8(void) { depthwise_mult_batches_arm_depthwise_conv_s8(); }

+ 61 - 0
CMSIS/NN/Tests/UnitTest/TestCases/test_arm_depthwise_conv_s8/test_arm_depthwise_conv_s8.c

@@ -21,6 +21,7 @@
 
 #include "../TestData/basic/test_data.h"
 #include "../TestData/depthwise_2/test_data.h"
+#include "../TestData/depthwise_mult_batches/test_data.h"
 #include "../TestData/depthwise_out_activation/test_data.h"
 #include "../TestData/stride2pad1/test_data.h"
 #include "../Utils/validate.h"
@@ -263,3 +264,63 @@ void depthwise_out_activation_arm_depthwise_conv_s8(void)
     TEST_ASSERT_EQUAL(expected, result);
     TEST_ASSERT_TRUE(validate(output, depthwise_out_activation_output_ref, DEPTHWISE_OUT_ACTIVATION_DST_SIZE));
 }
+
+void depthwise_mult_batches_arm_depthwise_conv_s8(void)
+{
+    const arm_status expected = ARM_MATH_SUCCESS;
+    q7_t output[DEPTHWISE_MULT_BATCHES_DST_SIZE] = {0};
+
+    cmsis_nn_context ctx;
+    cmsis_nn_dw_conv_params dw_conv_params;
+    cmsis_nn_per_channel_quant_params quant_params;
+    cmsis_nn_dims input_dims;
+    cmsis_nn_dims filter_dims;
+    cmsis_nn_dims bias_dims;
+    cmsis_nn_dims output_dims;
+
+    const q31_t *bias_data = depthwise_mult_batches_biases;
+    const q7_t *kernel_data = depthwise_mult_batches_weights;
+    const q7_t *input_data = depthwise_mult_batches_input;
+
+    input_dims.n = DEPTHWISE_MULT_BATCHES_INPUT_BATCHES;
+    input_dims.w = DEPTHWISE_MULT_BATCHES_INPUT_W;
+    input_dims.h = DEPTHWISE_MULT_BATCHES_INPUT_H;
+    input_dims.c = DEPTHWISE_MULT_BATCHES_IN_CH;
+    filter_dims.w = DEPTHWISE_MULT_BATCHES_FILTER_X;
+    filter_dims.h = DEPTHWISE_MULT_BATCHES_FILTER_Y;
+    output_dims.w = DEPTHWISE_MULT_BATCHES_OUTPUT_W;
+    output_dims.h = DEPTHWISE_MULT_BATCHES_OUTPUT_H;
+    output_dims.c = DEPTHWISE_MULT_BATCHES_OUT_CH;
+
+    dw_conv_params.padding.w = DEPTHWISE_MULT_BATCHES_PAD_X;
+    dw_conv_params.padding.h = DEPTHWISE_MULT_BATCHES_PAD_Y;
+    dw_conv_params.stride.w = DEPTHWISE_MULT_BATCHES_STRIDE_X;
+    dw_conv_params.stride.h = DEPTHWISE_MULT_BATCHES_STRIDE_Y;
+    dw_conv_params.ch_mult = DEPTHWISE_MULT_BATCHES_CH_MULT;
+
+    dw_conv_params.input_offset = DEPTHWISE_MULT_BATCHES_INPUT_OFFSET;
+    dw_conv_params.output_offset = DEPTHWISE_MULT_BATCHES_OUTPUT_OFFSET;
+    dw_conv_params.activation.min = DEPTHWISE_MULT_BATCHES_OUT_ACTIVATION_MIN;
+    dw_conv_params.activation.max = DEPTHWISE_MULT_BATCHES_OUT_ACTIVATION_MAX;
+    quant_params.multiplier = (int32_t *)depthwise_mult_batches_output_mult;
+    quant_params.shift = (int32_t *)depthwise_mult_batches_output_shift;
+
+    ctx.buf = NULL;
+    ctx.size = 0;
+
+    arm_status result = arm_depthwise_conv_s8(&ctx,
+                                              &dw_conv_params,
+                                              &quant_params,
+                                              &input_dims,
+                                              input_data,
+                                              &filter_dims,
+                                              kernel_data,
+                                              &bias_dims,
+                                              bias_data,
+                                              &output_dims,
+                                              output);
+
+    free(ctx.buf);
+    TEST_ASSERT_EQUAL(expected, result);
+    TEST_ASSERT_TRUE(validate(output, depthwise_mult_batches_output_ref, DEPTHWISE_MULT_BATCHES_DST_SIZE));
+}

+ 5 - 0
CMSIS/NN/Tests/UnitTest/generate_test_data.py

@@ -1098,6 +1098,10 @@ def load_all_testdatasets():
     ALL_TESTDATA_SETS[dataset] = ConvSettings(dataset, type_of_test, args, in_ch=3, out_ch=3, x_in=6, y_in=5, w_x=3,
                                               w_y=4, pad=False, randmin=-7, randmax=7, out_activation_min=-31,
                                               out_activation_max=24)
+    dataset = 'depthwise_mult_batches'
+    ALL_TESTDATA_SETS[dataset] = ConvSettings(dataset, type_of_test, args, in_ch=3, out_ch=3, x_in=3, y_in=5, w_x=2,
+                                              w_y=4, stride_x=2, stride_y=2, pad=True, randmin=-2, randmax=2,
+                                              batches=2)
 
     type_of_test = 'fully_connected'
     dataset = 'fully_connected'
@@ -1119,6 +1123,7 @@ def load_all_testdatasets():
     ALL_TESTDATA_SETS[dataset] = FullyConnectedSettings(dataset, type_of_test, args, in_ch=10, out_ch=4, randmin=-15,
                                                         randmax=15, input_zero_point=0, output_zero_point=0,
                                                         out_activation_min=-105, out_activation_max=120)
+
     type_of_test = 'avgpool'
     dataset = 'avgpooling'
     ALL_TESTDATA_SETS[dataset] = PoolingSettings(dataset, type_of_test, args, channels=8, x_in=22, y_in=12, stride_x=9,