Просмотр исходного кода

CMSIS-NN: Add support for null bias for Fully Connected op

NULL bias support is added for processors with and without
DSP extension.

Added Test case to verify it

Change-Id: I2b4957e27d59ef7a8b10b58bedf17aa33bcd41ea
Felix Johnny 5 лет назад
Родитель
Сommit
6049661f2b

+ 2 - 1
CMSIS/NN/.gitignore

@@ -1,3 +1,4 @@
 Tests/UnitTest/TestCases/*/Unity/TestRunner/*
 Tests/UnitTest/Output/*
-Tests/UnitTest/Unity/*
+Tests/UnitTest/Unity/*
+Tests/UnitTest/*.ld

+ 24 - 6
CMSIS/NN/Source/NNSupportFunctions/arm_nn_vec_mat_mult_t_s8.c

@@ -200,8 +200,13 @@ arm_status arm_nn_vec_mat_mult_t_s8(const q7_t *lhs,
         const q7_t *lhs_ptr = &lhs[0];
         const q7_t *rhs_ptr = &rhs[0];
 
-        q31_t res00 = *bias++;
-        q31_t res01 = *bias++;
+        q31_t res00 = 0;
+        q31_t res01 = 0;
+        if (bias)
+        {
+            res00 = *bias++;
+            res01 = *bias++;
+        }
 
         int32_t rhs_cols_idx = 0;
 
@@ -323,7 +328,11 @@ arm_status arm_nn_vec_mat_mult_t_s8(const q7_t *lhs,
         const q7_t *lhs_ptr = &lhs[0];
         const q7_t *rhs_ptr = &rhs[0];
 
-        q31_t res00 = *bias++;
+        q31_t res00 = 0;
+        if (bias)
+        {
+            res00 = *bias++;
+        }
 
         int32_t rhs_cols_idx = 0;
 
@@ -406,8 +415,13 @@ arm_status arm_nn_vec_mat_mult_t_s8(const q7_t *lhs,
         const q7_t *lhs_ptr = &lhs[0];
         const q7_t *rhs_ptr = &rhs[0];
 
-        q31_t res00 = *bias++;
-        q31_t res01 = *bias++;
+        q31_t res00 = 0;
+        q31_t res01 = 0;
+        if (bias)
+        {
+            res00 = *bias++;
+            res01 = *bias++;
+        }
 
         for (int32_t rhs_cols_idx = 0; rhs_cols_idx < rhs_cols; ++rhs_cols_idx)
         {
@@ -447,7 +461,11 @@ arm_status arm_nn_vec_mat_mult_t_s8(const q7_t *lhs,
         const q7_t *lhs_ptr = &lhs[0];
         const q7_t *rhs_ptr = &rhs[0];
 
-        q31_t res00 = *bias++;
+        q31_t res00 = 0;
+        if (bias)
+        {
+            res00 = *bias++;
+        }
 
         for (int32_t rhs_cols_idx = 0; rhs_cols_idx < rhs_cols; ++rhs_cols_idx)
         {

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

@@ -0,0 +1,2 @@
+# 5
+3.000000000000000000e+00,1.000000000000000000e+00,-4.000000000000000000e+00,1.000000000000000000e+00,3.000000000000000000e+00

+ 3 - 0
CMSIS/NN/Tests/UnitTest/PregeneratedData/fully_connected_null_bias_0/input.txt

@@ -0,0 +1,3 @@
+# 2,1,1,33
+-2.000000000000000000e+00,-1.000000000000000000e+00,1.000000000000000000e+00,2.000000000000000000e+00,-2.000000000000000000e+00,-3.000000000000000000e+00,-2.000000000000000000e+00,-1.000000000000000000e+00,0.000000000000000000e+00,-4.000000000000000000e+00,-3.000000000000000000e+00,3.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00,-3.000000000000000000e+00,-3.000000000000000000e+00,-4.000000000000000000e+00,0.000000000000000000e+00,3.000000000000000000e+00,-2.000000000000000000e+00,-4.000000000000000000e+00,0.000000000000000000e+00,-1.000000000000000000e+00,-4.000000000000000000e+00,2.000000000000000000e+00,-3.000000000000000000e+00,-3.000000000000000000e+00,2.000000000000000000e+00,0.000000000000000000e+00,-4.000000000000000000e+00,-4.000000000000000000e+00,-1.000000000000000000e+00,-2.000000000000000000e+00
+2.000000000000000000e+00,3.000000000000000000e+00,3.000000000000000000e+00,-4.000000000000000000e+00,0.000000000000000000e+00,1.000000000000000000e+00,-3.000000000000000000e+00,2.000000000000000000e+00,-2.000000000000000000e+00,-1.000000000000000000e+00,-3.000000000000000000e+00,2.000000000000000000e+00,3.000000000000000000e+00,-2.000000000000000000e+00,-3.000000000000000000e+00,-2.000000000000000000e+00,-4.000000000000000000e+00,-2.000000000000000000e+00,3.000000000000000000e+00,2.000000000000000000e+00,-3.000000000000000000e+00,0.000000000000000000e+00,3.000000000000000000e+00,2.000000000000000000e+00,-4.000000000000000000e+00,0.000000000000000000e+00,-4.000000000000000000e+00,0.000000000000000000e+00,-1.000000000000000000e+00,-4.000000000000000000e+00,2.000000000000000000e+00,0.000000000000000000e+00,-4.000000000000000000e+00

+ 34 - 0
CMSIS/NN/Tests/UnitTest/PregeneratedData/fully_connected_null_bias_0/kernel.txt

@@ -0,0 +1,34 @@
+# 1,1,33,5
+2.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00,-4.000000000000000000e+00,2.000000000000000000e+00
+-1.000000000000000000e+00,0.000000000000000000e+00,3.000000000000000000e+00,-2.000000000000000000e+00,0.000000000000000000e+00
+1.000000000000000000e+00,-4.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00,1.000000000000000000e+00
+2.000000000000000000e+00,1.000000000000000000e+00,-3.000000000000000000e+00,-1.000000000000000000e+00,-2.000000000000000000e+00
+1.000000000000000000e+00,-2.000000000000000000e+00,2.000000000000000000e+00,-4.000000000000000000e+00,-3.000000000000000000e+00
+-1.000000000000000000e+00,0.000000000000000000e+00,1.000000000000000000e+00,0.000000000000000000e+00,2.000000000000000000e+00
+1.000000000000000000e+00,-2.000000000000000000e+00,1.000000000000000000e+00,0.000000000000000000e+00,3.000000000000000000e+00
+-1.000000000000000000e+00,-4.000000000000000000e+00,-2.000000000000000000e+00,0.000000000000000000e+00,2.000000000000000000e+00
+0.000000000000000000e+00,-1.000000000000000000e+00,2.000000000000000000e+00,1.000000000000000000e+00,-1.000000000000000000e+00
+-3.000000000000000000e+00,-1.000000000000000000e+00,-4.000000000000000000e+00,1.000000000000000000e+00,-2.000000000000000000e+00
+-4.000000000000000000e+00,1.000000000000000000e+00,-2.000000000000000000e+00,-4.000000000000000000e+00,-2.000000000000000000e+00
+0.000000000000000000e+00,-2.000000000000000000e+00,3.000000000000000000e+00,1.000000000000000000e+00,2.000000000000000000e+00
+-2.000000000000000000e+00,-1.000000000000000000e+00,-3.000000000000000000e+00,-1.000000000000000000e+00,3.000000000000000000e+00
+1.000000000000000000e+00,-1.000000000000000000e+00,-4.000000000000000000e+00,-3.000000000000000000e+00,2.000000000000000000e+00
+-2.000000000000000000e+00,-1.000000000000000000e+00,-2.000000000000000000e+00,-4.000000000000000000e+00,-4.000000000000000000e+00
+0.000000000000000000e+00,2.000000000000000000e+00,3.000000000000000000e+00,3.000000000000000000e+00,-4.000000000000000000e+00
+3.000000000000000000e+00,3.000000000000000000e+00,1.000000000000000000e+00,-1.000000000000000000e+00,1.000000000000000000e+00
+2.000000000000000000e+00,2.000000000000000000e+00,1.000000000000000000e+00,-1.000000000000000000e+00,3.000000000000000000e+00
+2.000000000000000000e+00,3.000000000000000000e+00,-2.000000000000000000e+00,-4.000000000000000000e+00,0.000000000000000000e+00
+0.000000000000000000e+00,3.000000000000000000e+00,-2.000000000000000000e+00,3.000000000000000000e+00,-3.000000000000000000e+00
+1.000000000000000000e+00,2.000000000000000000e+00,-2.000000000000000000e+00,-3.000000000000000000e+00,1.000000000000000000e+00
+-4.000000000000000000e+00,-2.000000000000000000e+00,-2.000000000000000000e+00,2.000000000000000000e+00,1.000000000000000000e+00
+-4.000000000000000000e+00,3.000000000000000000e+00,2.000000000000000000e+00,0.000000000000000000e+00,-3.000000000000000000e+00
+-4.000000000000000000e+00,-2.000000000000000000e+00,1.000000000000000000e+00,-4.000000000000000000e+00,-3.000000000000000000e+00
+2.000000000000000000e+00,-1.000000000000000000e+00,-4.000000000000000000e+00,-2.000000000000000000e+00,1.000000000000000000e+00
+1.000000000000000000e+00,3.000000000000000000e+00,3.000000000000000000e+00,-3.000000000000000000e+00,3.000000000000000000e+00
+-3.000000000000000000e+00,0.000000000000000000e+00,-1.000000000000000000e+00,3.000000000000000000e+00,-2.000000000000000000e+00
+3.000000000000000000e+00,3.000000000000000000e+00,3.000000000000000000e+00,1.000000000000000000e+00,3.000000000000000000e+00
+-1.000000000000000000e+00,-1.000000000000000000e+00,0.000000000000000000e+00,1.000000000000000000e+00,2.000000000000000000e+00
+-2.000000000000000000e+00,2.000000000000000000e+00,1.000000000000000000e+00,-4.000000000000000000e+00,2.000000000000000000e+00
+2.000000000000000000e+00,-2.000000000000000000e+00,0.000000000000000000e+00,-2.000000000000000000e+00,-1.000000000000000000e+00
+-3.000000000000000000e+00,3.000000000000000000e+00,-3.000000000000000000e+00,2.000000000000000000e+00,-1.000000000000000000e+00
+-4.000000000000000000e+00,-2.000000000000000000e+00,2.000000000000000000e+00,-2.000000000000000000e+00,3.000000000000000000e+00

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

@@ -0,0 +1,12 @@
+33
+5
+1
+1
+1
+1
+1
+1
+0
+0
+2
+0

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

@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2010-2020 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.1.0 as reference.
+#pragma once
+#include <stdint.h>
+
+const int32_t fully_connected_null_bias_0_biases[5] = {0, 0, 0, 0, 0};

+ 35 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/fully_connected_null_bias_0/config_data.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010-2020 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.1.0 as reference.
+#pragma once
+#define FULLY_CONNECTED_NULL_BIAS_0_OUT_CH 5
+#define FULLY_CONNECTED_NULL_BIAS_0_IN_CH 33
+#define FULLY_CONNECTED_NULL_BIAS_0_INPUT_W 1
+#define FULLY_CONNECTED_NULL_BIAS_0_INPUT_H 1
+#define FULLY_CONNECTED_NULL_BIAS_0_DST_SIZE 10
+#define FULLY_CONNECTED_NULL_BIAS_0_INPUT_SIZE 33
+#define FULLY_CONNECTED_NULL_BIAS_0_INPUT_OFFSET 1
+#define FULLY_CONNECTED_NULL_BIAS_0_OUTPUT_OFFSET 0
+#define FULLY_CONNECTED_NULL_BIAS_0_OUT_ACTIVATION_MIN -128
+#define FULLY_CONNECTED_NULL_BIAS_0_OUT_ACTIVATION_MAX 127
+#define FULLY_CONNECTED_NULL_BIAS_0_INPUT_BATCHES 2
+#define FULLY_CONNECTED_NULL_BIAS_0_WEIGHTS_OFFSET -3
+#define FULLY_CONNECTED_NULL_BIAS_0_OUTPUT_MULTIPLIER 1073741824
+#define FULLY_CONNECTED_NULL_BIAS_0_OUTPUT_SHIFT 1
+#define FULLY_CONNECTED_NULL_BIAS_0_ACCUMULATION_DEPTH 33

+ 26 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/fully_connected_null_bias_0/input_data.h

@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010-2020 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.1.0 as reference.
+#pragma once
+#include <stdint.h>
+
+const q7_t fully_connected_null_bias_0_input[66] = {-3, -2, 0,  1,  -3, -4, -3, -2, -1, -5, -4, 2,  -1, -1, -4, -4, -5,
+                                                    -1, 2,  -3, -5, -1, -2, -5, 1,  -4, -4, 1,  -1, -5, -5, -2, -3, 1,
+                                                    2,  2,  -5, -1, 0,  -4, 1,  -3, -2, -4, 1,  2,  -3, -4, -3, -5, -3,
+                                                    2,  1,  -4, -1, 2,  1,  -5, -1, -5, -1, -2, -5, 1,  -1, -5};

+ 23 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/fully_connected_null_bias_0/output_ref_data.h

@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2010-2020 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.1.0 as reference.
+#pragma once
+#include <stdint.h>
+
+const q7_t fully_connected_null_bias_0_output_ref[10] = {-46, 26, -40, 57, 23, 3, 24, -28, 54, -9};

+ 24 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/fully_connected_null_bias_0/test_data.h

@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010-2020 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.1.0 as reference.
+#include "biases_data.h"
+#include "config_data.h"
+#include "input_data.h"
+#include "output_ref_data.h"
+#include "weights_data.h"

+ 28 - 0
CMSIS/NN/Tests/UnitTest/TestCases/TestData/fully_connected_null_bias_0/weights_data.h

@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010-2020 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.1.0 as reference.
+#pragma once
+#include <stdint.h>
+
+const q7_t fully_connected_null_bias_0_weights[165] = {
+    5, 3,  3, -1, 5, 2, 3,  6,  1,  3, 4, -1, 3, 3,  4,  5, 4,  0,  2, 1,  4,  1, 5, -1, 0, 2, 3, 4,  3,  5, 4, 1, 4,
+    3, 6,  2, -1, 1, 3, 5,  3,  2,  5, 4, 2,  0, 2,  -1, 4, 1,  -1, 4, 1,  -1, 1, 3, 1,  6, 4, 5, 1,  2,  0, 2, 6, 4,
+    2, -1, 0, 5,  1, 2, 1,  -1, -1, 3, 5, 6,  6, -1, 6,  6, 4,  2,  4, 5,  5,  4, 2, 6,  5, 6, 1, -1, 3,  3, 6, 1, 6,
+    0, 4,  5, 1,  0, 4, -1, 1,  1,  5, 4, -1, 6, 5,  3,  0, -1, 1,  4, -1, 0,  5, 2, -1, 1, 4, 4, 6,  6,  0, 6, 0, 3,
+    2, 6,  1, 6,  6, 6, 4,  6,  2,  2, 3, 4,  5, 1,  5,  4, -1, 5,  5, 1,  3,  1, 2, 0,  6, 0, 5, 2,  -1, 1, 5, 1, 6};

+ 5 - 0
CMSIS/NN/Tests/UnitTest/TestCases/test_arm_fully_connected_s8/Unity/unity_test_arm_fully_connected_s8.c

@@ -49,3 +49,8 @@ void test_fully_connected_arm_fully_connected_s8(void) { fully_connected_arm_ful
 void test_fully_connected_mve_0_arm_fully_connected_s8(void) { fully_connected_mve_0_arm_fully_connected_s8(); }
 
 void test_fully_connected_mve_1_arm_fully_connected_s8(void) { fully_connected_mve_1_arm_fully_connected_s8(); }
+
+void test_fully_connected_null_bias_0_arm_fully_connected_s8(void)
+{
+    fully_connected_null_bias_0_arm_fully_connected_s8();
+}

+ 64 - 0
CMSIS/NN/Tests/UnitTest/TestCases/test_arm_fully_connected_s8/test_arm_fully_connected_s8.c

@@ -23,6 +23,7 @@
 #include "../TestData/fully_connected/test_data.h"
 #include "../TestData/fully_connected_mve_0/test_data.h"
 #include "../TestData/fully_connected_mve_1/test_data.h"
+#include "../TestData/fully_connected_null_bias_0/test_data.h"
 #include "../Utils/validate.h"
 
 void fully_connected_arm_fully_connected_s8(void)
@@ -186,3 +187,66 @@ void fully_connected_mve_1_arm_fully_connected_s8(void)
     TEST_ASSERT_EQUAL(expected, result);
     TEST_ASSERT_TRUE(validate(output, output_ref, output_ref_size));
 }
+
+void fully_connected_null_bias_0_arm_fully_connected_s8(void)
+{
+    const arm_status expected = ARM_MATH_SUCCESS;
+    q7_t output[FULLY_CONNECTED_NULL_BIAS_0_DST_SIZE] = {0};
+    cmsis_nn_context ctx;
+    cmsis_nn_fc_params fc_params;
+    cmsis_nn_per_tensor_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 = fully_connected_null_bias_0_biases;
+    const q7_t *kernel_data = fully_connected_null_bias_0_weights;
+    const q7_t *input_data = fully_connected_null_bias_0_input;
+    const q7_t *output_ref = fully_connected_null_bias_0_output_ref;
+    const int32_t output_ref_size = FULLY_CONNECTED_NULL_BIAS_0_DST_SIZE;
+    input_dims.n = FULLY_CONNECTED_NULL_BIAS_0_INPUT_BATCHES;
+    input_dims.w = FULLY_CONNECTED_NULL_BIAS_0_INPUT_W;
+    input_dims.h = FULLY_CONNECTED_NULL_BIAS_0_INPUT_H;
+    input_dims.c = FULLY_CONNECTED_NULL_BIAS_0_IN_CH;
+    filter_dims.n = FULLY_CONNECTED_NULL_BIAS_0_ACCUMULATION_DEPTH;
+    filter_dims.c = FULLY_CONNECTED_NULL_BIAS_0_OUT_CH;
+    output_dims.n = FULLY_CONNECTED_NULL_BIAS_0_INPUT_BATCHES;
+    output_dims.c = FULLY_CONNECTED_NULL_BIAS_0_OUT_CH;
+    fc_params.input_offset = FULLY_CONNECTED_NULL_BIAS_0_INPUT_OFFSET;
+    fc_params.filter_offset = FULLY_CONNECTED_NULL_BIAS_0_WEIGHTS_OFFSET;
+    fc_params.output_offset = FULLY_CONNECTED_NULL_BIAS_0_OUTPUT_OFFSET;
+    fc_params.activation.min = FULLY_CONNECTED_NULL_BIAS_0_OUT_ACTIVATION_MIN;
+    fc_params.activation.max = FULLY_CONNECTED_NULL_BIAS_0_OUT_ACTIVATION_MAX;
+    quant_params.multiplier = FULLY_CONNECTED_NULL_BIAS_0_OUTPUT_MULTIPLIER;
+    quant_params.shift = FULLY_CONNECTED_NULL_BIAS_0_OUTPUT_SHIFT;
+
+    arm_status ip_check = ARM_MATH_SUCCESS;
+    for (int i = 0; i < FULLY_CONNECTED_NULL_BIAS_0_OUT_CH; i++)
+    {
+        if (bias_data[i] != 0)
+        {
+            ip_check = ARM_MATH_ARGUMENT_ERROR;
+            break;
+        }
+    }
+    TEST_ASSERT_EQUAL(expected, ip_check);
+
+    int32_t buf_size = arm_fully_connected_s8_get_buffer_size(&filter_dims);
+    ctx.buf = malloc(buf_size);
+    ctx.size = buf_size;
+    arm_status result = arm_fully_connected_s8(&ctx,
+                                               &fc_params,
+                                               &quant_params,
+                                               &input_dims,
+                                               input_data,
+                                               &filter_dims,
+                                               kernel_data,
+                                               &bias_dims,
+                                               NULL,
+                                               &output_dims,
+                                               output);
+
+    free(ctx.buf);
+    TEST_ASSERT_EQUAL(expected, result);
+    TEST_ASSERT_TRUE(validate(output, output_ref, output_ref_size));
+}

+ 17 - 8
CMSIS/NN/Tests/UnitTest/generate_test_data.py

@@ -97,7 +97,7 @@ class TestSettings(ABC):
     UINT8_MIN = 0
 
     def __init__(self, dataset, testtype, args, in_ch, out_ch, x_in, y_in, w_x, w_y, stride_x, stride_y, pad, randmin,
-                 randmax, outminrange=-128, outmaxrange=127, batches=1):
+                 randmax, outminrange=-128, outmaxrange=127, batches=1, generate_bias=True):
 
         self.tensor_flow_reference_version = ("// Generated by {} using TFL version {} as reference.\n".
                                               format(os.path.basename(__file__), tf.__version__))
@@ -128,6 +128,9 @@ class TestSettings(ABC):
         # which may cause output to differ.
         self.output_scale = 1.0
 
+        # Bias is optional.
+        self.generate_bias = generate_bias
+
         self.generated_header_files = []
         self.pregenerated_data_dir = self.PREGEN
         self.testdataset = DEFAULT_TESTDATA_SET
@@ -269,7 +272,9 @@ class TestSettings(ABC):
 
     def get_randomized_bias_data(self, biases):
         # Generate or load saved bias data unless hardcoded data provided
-        if biases is not None:
+        if not self.generate_bias:
+            biases = tf.reshape(np.full([self.output_ch], 0), [self.output_ch])
+        elif biases is not None:
             biases = tf.reshape(biases, [self.output_ch])
         else:
             biases = self.get_randomized_data([self.output_ch],
@@ -442,9 +447,9 @@ class TestSettings(ABC):
 class ConvSettings(TestSettings):
 
     def __init__(self, dataset, testtype, args, in_ch=1, out_ch=1, x_in=7, y_in=7, w_x=3, w_y=3, stride_x=2, stride_y=2,
-                 pad=True, randmin=-7, randmax=7, outminrange=-128, outmaxrange=127, batches=1):
+                 pad=True, randmin=-7, randmax=7, outminrange=-128, outmaxrange=127, batches=1, generate_bias=True):
         super().__init__(dataset, testtype, args, in_ch, out_ch, x_in, y_in, w_x, w_y, stride_x, stride_y, pad,
-                         randmin, randmax, outminrange, outmaxrange, batches)
+                         randmin, randmax, outminrange, outmaxrange, batches, generate_bias=generate_bias)
 
         self.scaling_factors = []
 
@@ -669,9 +674,9 @@ class FullyConnectedSettings(TestSettings):
     def __init__(self, dataset, testtype, args, in_ch=1, out_ch=1, x_in=1, y_in=1, w_x=1, w_y=1, stride_x=1, stride_y=1,
                  pad=False, randmin=-7, randmax=7, outminrange=-128, outmaxrange=127, batches=1, input_scale=1.0,
                  input_zero_point=0, weights_scale=1.0, weights_zero_point=0, bias_scale=1.0, output_scale=1.0,
-                 output_zero_point=0):
+                 output_zero_point=0, generate_bias=True):
         super().__init__(dataset, testtype, args, in_ch, out_ch, x_in, y_in, w_x, w_y, stride_x, stride_y, pad, randmin,
-                         randmax, outminrange, outmaxrange, batches)
+                         randmax, outminrange, outmaxrange, batches, generate_bias=generate_bias)
 
         if not self.test_type == 'fully_connected':
             raise RuntimeError("Invalid test type {}".format(self.test_type))
@@ -801,12 +806,16 @@ def load_all_testdatasets():
                                                         output_zero_point=-2)
     dataset = 'fully_connected_mve_0'
     ALL_TESTDATA_SETS[dataset] = FullyConnectedSettings(dataset, type_of_test, args, in_ch=16, out_ch=9, x_in=1, y_in=1,
-                                                        input_zero_point=-3, w_x=1, w_y=1, randmin=-4, randmax=4, batches=1,
-                                                        output_zero_point=-2)
+                                                        input_zero_point=-3, w_x=1, w_y=1, randmin=-4, randmax=4,
+                                                        batches=1, output_zero_point=-2)
     dataset = 'fully_connected_mve_1'
     ALL_TESTDATA_SETS[dataset] = FullyConnectedSettings(dataset, type_of_test, args, in_ch=20, out_ch=4, x_in=1, y_in=1,
                                                         input_zero_point=-1, weights_zero_point=3, w_x=1, w_y=1,
                                                         randmin=-4, randmax=4, batches=1, output_zero_point=3)
+    dataset = 'fully_connected_null_bias_0'
+    ALL_TESTDATA_SETS[dataset] = FullyConnectedSettings(dataset, type_of_test, args, in_ch=33, out_ch=5,
+                                                        input_zero_point=-1, weights_zero_point=3,
+                                                        randmin=-4, randmax=4, batches=2, generate_bias=False)
     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,