aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTianle Cheng <tianle.cheng@arm.com>2023-07-03 11:24:12 +0100
committerTianle Cheng <tianle.cheng@arm.com>2023-07-05 09:39:27 +0000
commite5a30ff7e3ebc61592cc96b148c2c36eda9de02c (patch)
treecf582fb97d864ac959b84b19e1630df63d21376b
parent22c8a4b48efe4c6cfa563c734e771e77f4d7c1b0 (diff)
downloadarmnn-e5a30ff7e3ebc61592cc96b148c2c36eda9de02c.tar.gz
IVGCVSW-7833 Add ReverseV2 support to TFLite Parser
* Added ReverseV2 support to TFLite Parser * Added ReverseV2 TFLite Parser unit tests * Updated Parser Docs Signed-off-by: Tianle Cheng <tianle.cheng@arm.com> Change-Id: Idb9a9213f75cd6cf01509a5d06ea5772cf56ac5b
-rw-r--r--CMakeLists.txt1
-rw-r--r--docs/05_01_parsers.dox1
-rw-r--r--src/armnnTfLiteParser/TfLiteParser.cpp62
-rw-r--r--src/armnnTfLiteParser/TfLiteParser.hpp1
-rw-r--r--src/armnnTfLiteParser/test/ReverseV2.cpp100
5 files changed, 165 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 148e77254d..537455d3b3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -708,6 +708,7 @@ if(BUILD_UNIT_TESTS)
src/armnnTfLiteParser/test/ReshapeDynamic.cpp
src/armnnTfLiteParser/test/ResizeBilinear.cpp
src/armnnTfLiteParser/test/ResizeNearestNeighbor.cpp
+ src/armnnTfLiteParser/test/ReverseV2.cpp
src/armnnTfLiteParser/test/Quantize.cpp
src/armnnTfLiteParser/test/Softmax.cpp
src/armnnTfLiteParser/test/SpaceToBatchND.cpp
diff --git a/docs/05_01_parsers.dox b/docs/05_01_parsers.dox
index 08d569d065..cfce7ec580 100644
--- a/docs/05_01_parsers.dox
+++ b/docs/05_01_parsers.dox
@@ -173,6 +173,7 @@ The Arm NN SDK TensorFlow Lite parser currently supports the following operators
- RESHAPE
- RESIZE_BILINEAR
- RESIZE_NEAREST_NEIGHBOR
+- REVERSE_V2
- RSQRT
- SHAPE
- SIN
diff --git a/src/armnnTfLiteParser/TfLiteParser.cpp b/src/armnnTfLiteParser/TfLiteParser.cpp
index 1c5b4fc9f0..f44a747815 100644
--- a/src/armnnTfLiteParser/TfLiteParser.cpp
+++ b/src/armnnTfLiteParser/TfLiteParser.cpp
@@ -808,6 +808,7 @@ TfLiteParserImpl::TfLiteParserImpl(const Optional<ITfLiteParser::TfLiteParserOpt
m_ParserFunctions[tflite::BuiltinOperator_RESHAPE] = &TfLiteParserImpl::ParseReshape;
m_ParserFunctions[tflite::BuiltinOperator_RESIZE_BILINEAR] = &TfLiteParserImpl::ParseResizeBilinear;
m_ParserFunctions[tflite::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR] = &TfLiteParserImpl::ParseResizeNearestNeighbor;
+ m_ParserFunctions[tflite::BuiltinOperator_REVERSE_V2] = &TfLiteParserImpl::ParseReverseV2;
m_ParserFunctions[tflite::BuiltinOperator_RSQRT] = &TfLiteParserImpl::ParseRsqrt;
m_ParserFunctions[tflite::BuiltinOperator_SQRT] = &TfLiteParserImpl::ParseSqrt;
m_ParserFunctions[tflite::BuiltinOperator_SHAPE] = &TfLiteParserImpl::ParseShape;
@@ -3276,6 +3277,67 @@ void TfLiteParserImpl::ParseResize(size_t subgraphIndex, size_t operatorIndex, R
RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
}
+void TfLiteParserImpl::ParseReverseV2(size_t subgraphIndex, size_t operatorIndex)
+{
+ CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
+
+ auto inputs = GetInputs(m_Model, subgraphIndex, operatorIndex);
+ CHECK_VALID_SIZE(inputs.size(), 2);
+
+ auto outputs = GetOutputs(m_Model, subgraphIndex, operatorIndex);
+ CHECK_VALID_SIZE(outputs.size(), 1);
+
+ auto layerName = fmt::format("ReverseV2:{}:{}", subgraphIndex, operatorIndex);
+
+ TensorInfo inputTensorInfo = ToTensorInfo(inputs[0]);
+ TensorInfo axisTensorInfo = ToTensorInfo(inputs[1]);
+ TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
+
+ std::vector<int32_t> axisTensorData(axisTensorInfo.GetNumElements());
+
+ BufferRawPtr axisBufferPtr = GetBuffer(m_Model, inputs[1]->buffer);
+ ::memcpy(axisTensorData.data(), axisBufferPtr->data.data(), axisTensorInfo.GetNumBytes());
+
+ ReverseV2Descriptor descriptor(axisTensorData);
+
+ auto inputRank = static_cast<int32_t>(inputTensorInfo.GetNumDimensions());
+ std::vector<bool> dimFlag(inputRank, false);
+
+ for (auto axis : axisTensorData)
+ {
+ if (axis < -inputRank || axis >= inputRank)
+ {
+ throw ParseException(
+ fmt::format("Operation has invalid axis: {} It is out of bounds [ -{}, {} ) {}",
+ axis,
+ inputRank, inputRank,
+ CHECK_LOCATION().AsString()));
+ }
+
+ auto posAxis = axis < 0 ? axis + inputRank : axis;
+
+ if (dimFlag[posAxis])
+ {
+ throw ParseException(
+ fmt::format("Operation has repeated axis: {} {}",
+ axis,
+ CHECK_LOCATION().AsString()));
+ }
+ dimFlag[posAxis] = true;
+ }
+
+ IConnectableLayer* layer = m_Network->AddReverseV2Layer(descriptor, layerName.c_str());
+ ARMNN_ASSERT(layer != nullptr);
+
+ layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
+
+ auto inputTensorIndexes = AsUnsignedVector(GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
+ RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
+
+ auto outputTensorIndexes = AsUnsignedVector(GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
+ RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
+}
+
void TfLiteParserImpl::ParseConcatenation(size_t subgraphIndex, size_t operatorIndex)
{
CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
diff --git a/src/armnnTfLiteParser/TfLiteParser.hpp b/src/armnnTfLiteParser/TfLiteParser.hpp
index 774d054572..dad2d67f3c 100644
--- a/src/armnnTfLiteParser/TfLiteParser.hpp
+++ b/src/armnnTfLiteParser/TfLiteParser.hpp
@@ -176,6 +176,7 @@ private:
void ParseResize(size_t subgraphIndex, size_t operatorIndex, armnn::ResizeMethod resizeMethod);
void ParseResizeBilinear(size_t subgraphIndex, size_t operatorIndex);
void ParseResizeNearestNeighbor(size_t subgraphIndex, size_t operatorIndex);
+ void ParseReverseV2(size_t subgraphIndex, size_t operatorIndex);
void ParseRsqrt(size_t subgraphIndex, size_t operatorIndex);
void ParseShape(size_t subgraphIndex, size_t operatorIndex);
void ParseSin(size_t subgraphIndex, size_t operatorIndex);
diff --git a/src/armnnTfLiteParser/test/ReverseV2.cpp b/src/armnnTfLiteParser/test/ReverseV2.cpp
new file mode 100644
index 0000000000..9604a3a1de
--- /dev/null
+++ b/src/armnnTfLiteParser/test/ReverseV2.cpp
@@ -0,0 +1,100 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ParserFlatbuffersFixture.hpp"
+
+TEST_SUITE("TensorflowLiteParser_ReverseV2")
+{
+struct ReverseV2Fixture : public ParserFlatbuffersFixture
+{
+ explicit ReverseV2Fixture(const std::string& inputShape,
+ const std::string& outputShape,
+ const std::string& axisShape,
+ const std::string& axisData,
+ const std::string& dataType = "FLOAT32",
+ const std::string& scale = "1.0",
+ const std::string& offset = "0")
+ {
+ m_JsonString = R"(
+ {
+ "version": 3,
+ "operator_codes": [ { "builtin_code": "REVERSE_V2" } ],
+ "subgraphs": [ {
+ "tensors": [
+ {
+ "shape": )" + inputShape + R"(,
+ "type": )" + dataType + R"(,
+ "buffer": 0,
+ "name": "inputTensor",
+ "quantization": {
+ "min": [ 0.0 ],
+ "max": [ 255.0 ],
+ "scale": [ )" + scale + R"( ],
+ "zero_point": [ )" + offset + R"( ],
+ }
+ },
+ {
+ "shape": )" + axisShape + R"( ,
+ "type": "INT32",
+ "buffer": 1,
+ "name": "axis",
+ "quantization": {
+ "min": [ 0.0 ],
+ "max": [ 255.0 ],
+ "scale": [ 1.0 ],
+ "zero_point": [ 0 ],
+ }
+ },
+ {
+ "shape": )" + outputShape + R"(,
+ "type": )" + dataType + R"(,
+ "buffer": 2,
+ "name": "outputTensor",
+ "quantization": {
+ "min": [ 0.0 ],
+ "max": [ 255.0 ],
+ "scale": [ )" + scale + R"( ],
+ "zero_point": [ )" + offset + R"( ],
+ }
+ }
+ ],
+ "inputs": [ 0, 1 ],
+ "outputs": [ 2 ],
+ "operators": [
+ {
+ "opcode_index": 0,
+ "inputs": [ 0, 1 ],
+ "outputs": [ 2 ],
+ "builtin_options_type": "ReverseV2Options",
+ "builtin_options": {},
+ "custom_options_format": "FLEXBUFFERS"
+ }
+ ],
+ } ],
+ "buffers" : [
+ { },
+ { "data": )" + axisData + R"(, },
+ { },
+ ]
+ }
+ )";
+ Setup();
+ }
+};
+
+struct SimpleReverseV2Fixture : public ReverseV2Fixture
+{
+ SimpleReverseV2Fixture() : ReverseV2Fixture("[ 2, 2, 2 ]", "[ 2, 2, 2 ]", "[ 2 ]", "[ 0,0,0,0, 1,0,0,0 ]") {}
+};
+
+TEST_CASE_FIXTURE(SimpleReverseV2Fixture, "ParseReverseV2")
+{
+ RunTest<3, armnn::DataType::Float32>
+ (0,
+ {{ "inputTensor", { 1, 2, 3, 4, 5, 6, 7, 8 }}},
+ {{ "outputTensor", { 7, 8, 5, 6, 3, 4, 1, 2 }}});
+}
+
+} \ No newline at end of file