IVGCVSW-6262 Add support for Reduce Prod

* Tflite parser
* Tflite delegate
* Serializer
* Deserializer
* Ref, CpuAcc and GpuAcc workloads

Signed-off-by: Teresa Charlin <teresa.charlinreyes@arm.com>
Change-Id: I601a9ee1680b372c7955d9a628857d08c3cfd377
diff --git a/src/armnnTfLiteParser/TfLiteParser.cpp b/src/armnnTfLiteParser/TfLiteParser.cpp
index 5c7cb9b..305f769 100644
--- a/src/armnnTfLiteParser/TfLiteParser.cpp
+++ b/src/armnnTfLiteParser/TfLiteParser.cpp
@@ -677,6 +677,7 @@
     m_ParserFunctions[tflite::BuiltinOperator_RELU6]                   = &TfLiteParserImpl::ParseRelu6;
     m_ParserFunctions[tflite::BuiltinOperator_REDUCE_MAX]              = &TfLiteParserImpl::ParseReduceMax;
     m_ParserFunctions[tflite::BuiltinOperator_REDUCE_MIN]              = &TfLiteParserImpl::ParseReduceMin;
+    m_ParserFunctions[tflite::BuiltinOperator_REDUCE_PROD]             = &TfLiteParserImpl::ParseReduceProd;
     m_ParserFunctions[tflite::BuiltinOperator_RESHAPE]                 = &TfLiteParserImpl::ParseReshape;
     m_ParserFunctions[tflite::BuiltinOperator_RESIZE_BILINEAR]         = &TfLiteParserImpl::ParseResizeBilinear;
     m_ParserFunctions[tflite::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR] = &TfLiteParserImpl::ParseResizeNearestNeighbor;
@@ -3321,6 +3322,11 @@
     ParseReduce(subgraphIndex, operatorIndex, armnn::ReduceOperation::Sum);
 }
 
+void TfLiteParserImpl::ParseReduceProd(size_t subgraphIndex, size_t operatorIndex)
+{
+    ParseReduce(subgraphIndex, operatorIndex, armnn::ReduceOperation::Prod);
+}
+
 void TfLiteParserImpl::ParseReduceMax(size_t subgraphIndex, size_t operatorIndex)
 {
     ParseReduce(subgraphIndex, operatorIndex, armnn::ReduceOperation::Max);
diff --git a/src/armnnTfLiteParser/TfLiteParser.hpp b/src/armnnTfLiteParser/TfLiteParser.hpp
index dcd00d8..5645503 100644
--- a/src/armnnTfLiteParser/TfLiteParser.hpp
+++ b/src/armnnTfLiteParser/TfLiteParser.hpp
@@ -150,6 +150,7 @@
     void ParseReduce(size_t subgraphIndex, size_t operatorIndex, armnn::ReduceOperation reduceOperation);
     void ParseReduceMax(size_t subgraphIndex, size_t operatorIndex);
     void ParseReduceMin(size_t subgraphIndex, size_t operatorIndex);
+    void ParseReduceProd(size_t subgraphIndex, size_t operatorIndex);
     void ParseRelu(size_t subgraphIndex, size_t operatorIndex);
     void ParseRelu6(size_t subgraphIndex, size_t operatorIndex);
     void ParseReshape(size_t subgraphIndex, size_t operatorIndex);
diff --git a/src/armnnTfLiteParser/test/Prod.cpp b/src/armnnTfLiteParser/test/Prod.cpp
new file mode 100644
index 0000000..33ef6e3
--- /dev/null
+++ b/src/armnnTfLiteParser/test/Prod.cpp
@@ -0,0 +1,106 @@
+//
+// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ParserFlatbuffersFixture.hpp"
+
+
+TEST_SUITE("TensorflowLiteParser_Prod")
+{
+struct ProdFixture : public ParserFlatbuffersFixture
+{
+    explicit ProdFixture(const std::string& inputShape,
+                        const std::string& outputShape,
+                        const std::string& axisShape,
+                        const std::string& axisData)
+    {
+        m_JsonString = R"(
+            {
+                "version": 3,
+                "operator_codes": [ { "builtin_code": "PROD" } ],
+                "subgraphs": [ {
+                    "tensors": [
+                        {
+                            "shape": )" + inputShape + R"(,
+                            "type": "FLOAT32",
+                            "buffer": 0,
+                            "name": "inputTensor",
+                            "quantization": {
+                                "min": [ 0.0 ],
+                                "max": [ 255.0 ],
+                                "scale": [ 1.0 ],
+                                "zero_point": [ 0 ],
+                            }
+                        },
+                        {
+                            "shape": )" + outputShape + R"( ,
+                            "type": "FLOAT32",
+                            "buffer": 1,
+                            "name": "outputTensor",
+                            "quantization": {
+                                "min": [ 0.0 ],
+                                "max": [ 255.0 ],
+                                "scale": [ 1.0 ],
+                                "zero_point": [ 0 ],
+                            }
+                        },
+                        {
+                            "shape": )" + axisShape + R"( ,
+                            "type": "INT32",
+                            "buffer": 2,
+                            "name": "axis",
+                            "quantization": {
+                                "min": [ 0.0 ],
+                                "max": [ 255.0 ],
+                                "scale": [ 1.0 ],
+                                "zero_point": [ 0 ],
+                            }
+                        }
+                    ],
+                    "inputs": [ 0 ],
+                    "outputs": [ 1 ],
+                    "operators": [
+                        {
+                            "opcode_index": 0,
+                            "inputs": [ 0 , 2 ],
+                            "outputs": [ 1 ],
+                            "builtin_options_type": "ReducerOptions",
+                            "builtin_options": {
+                              "keep_dims": true,
+                            },
+                            "custom_options_format": "FLEXBUFFERS"
+                        }
+                    ],
+                } ],
+                "buffers" : [
+                    { },
+                    { },
+                    { "data": )" + axisData + R"(, },
+                ]
+            }
+        )";
+        SetupSingleInputSingleOutput("inputTensor", "outputTensor");
+    }
+};
+
+struct SimpleProdFixture : public ProdFixture
+{
+    SimpleProdFixture() : ProdFixture("[ 1, 3, 2, 4 ]", "[ 1, 1, 1, 4 ]", "[ 2 ]", "[ 1, 0, 0, 0,  2, 0, 0, 0 ]") {}
+};
+
+TEST_CASE_FIXTURE(SimpleProdFixture, "ParseProd")
+{
+    RunTest<4, armnn::DataType::Float32, armnn::DataType::Float32>
+        (0, {{ "inputTensor", { 1.0f,   2.0f,   3.0f,   4.0f,
+                                5.0f,   6.0f,   7.0f,   8.0f,
+
+                                10.0f,  20.0f,  30.0f,  40.0f,
+                                50.0f,  60.0f,  70.0f,  80.0f,
+
+                                11.0f, 22.0f, 33.0f, 44.0f,
+                                55.0f, 66.0f, 77.0f, 88.0f  } } },
+            {{ "outputTensor", { 1512500.f,  20908800.f, 112058100.f, 396492800.f } } });
+}
+
+}