summaryrefslogtreecommitdiff
path: root/runtime/onert/frontend/nnapi/wrapper
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/onert/frontend/nnapi/wrapper')
-rw-r--r--runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.cc12
-rw-r--r--runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.h16
-rw-r--r--runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksEvent.cc2
-rw-r--r--runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.cc65
-rw-r--r--runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.h7
-rw-r--r--runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc29
-rw-r--r--runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.h5
-rw-r--r--runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.test.cc25
-rw-r--r--runtime/onert/frontend/nnapi/wrapper/NNAPIConvert.cc7
-rw-r--r--runtime/onert/frontend/nnapi/wrapper/OperationFactory.cc533
-rw-r--r--runtime/onert/frontend/nnapi/wrapper/OperationFactory.h2
11 files changed, 326 insertions, 377 deletions
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.cc b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.cc
index 81cd38f4f..3b5edc180 100644
--- a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.cc
+++ b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.cc
@@ -18,21 +18,23 @@
#include "util/logging.h"
+using namespace onert;
+
// TODO Support multiple subgraphs
ANeuralNetworksCompilation::ANeuralNetworksCompilation(const ANeuralNetworksModel *model) noexcept
- : _subgraphs{model->getSubGraphs()}, _compiler{new onert::compiler::Compiler{_subgraphs}}
+ : _model{model->getModel()}, _coptions{compiler::CompilerOptions::fromGlobalConfig()},
+ _compiler{std::make_shared<compiler::Compiler>(_model, *_coptions)}
{
if (model->allowedToFp16())
- {
- _compiler->enableToFp16();
- }
+ _coptions->enableToFp16();
}
bool ANeuralNetworksCompilation::finish() noexcept
{
try
{
- _executors = _compiler->compile();
+ _artifact = _compiler->compile();
+ _compiler = nullptr;
}
catch (const std::exception &e)
{
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.h b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.h
index 5f0650b9a..3898f1d5e 100644
--- a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.h
+++ b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.h
@@ -21,8 +21,9 @@
#include "compiler/Compiler.h"
#include "ir/Graph.h"
-#include "ir/Subgraphs.h"
-#include "exec/IExecutor.h"
+#include "ir/Model.h"
+#include "exec/IExecutors.h"
+#include "util/TracingCtx.h"
struct ANeuralNetworksCompilation
{
@@ -31,17 +32,18 @@ public:
public:
bool finish() noexcept;
+ bool isFinished() noexcept { return _compiler == nullptr; }
- onert::compiler::State state(void) noexcept { return _compiler->state(); }
- void publish(std::shared_ptr<onert::exec::ExecutorMap> &executors) noexcept
+ void publish(std::shared_ptr<onert::exec::IExecutors> &executors) noexcept
{
- executors = _executors;
+ executors = _artifact ? _artifact->_executors : nullptr;
}
private:
- std::shared_ptr<onert::ir::Subgraphs> _subgraphs;
+ std::shared_ptr<onert::ir::Model> _model;
+ std::unique_ptr<onert::compiler::CompilerOptions> _coptions;
std::shared_ptr<onert::compiler::Compiler> _compiler;
- std::shared_ptr<onert::exec::ExecutorMap> _executors;
+ std::shared_ptr<onert::compiler::CompilerArtifact> _artifact;
};
#endif
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksEvent.cc b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksEvent.cc
index 2bea729be..b0ea51917 100644
--- a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksEvent.cc
+++ b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksEvent.cc
@@ -20,7 +20,7 @@
#include "util/logging.h"
ANeuralNetworksEvent::ANeuralNetworksEvent(const std::shared_ptr<onert::exec::Execution> &execution)
- : _execution{execution}
+ : _execution{execution}
{
// DO NOTHING
}
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.cc b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.cc
index eb12d7e76..2265e990f 100644
--- a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.cc
+++ b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.cc
@@ -64,7 +64,7 @@ bool ANeuralNetworksExecution::compareDataType(const ANeuralNetworksOperandType
{
try
{
- const auto operand_type = _execution->primary_subgraph().operands().at(index).typeInfo();
+ const auto &operand_type = _execution->primary_subgraph().operands().at(index).typeInfo();
const auto typeInfo = NNAPIConvert::getTypeInfo(type);
if (operand_type != typeInfo)
@@ -98,9 +98,20 @@ bool ANeuralNetworksExecution::compareShape(const ANeuralNetworksOperandType *ty
return operand_shape == shape_from_type;
}
+bool ANeuralNetworksExecution::IsOptionalInput(const onert::ir::OperandIndex index) noexcept
+{
+ const auto &operand_shape = _execution->primary_subgraph().operands().at(index).shape();
+ for (int32_t i = 0; i < operand_shape.rank(); ++i)
+ {
+ if (operand_shape.dim(i) != 0)
+ return false;
+ }
+ return true;
+}
+
bool ANeuralNetworksExecution::hasUnspecifiedDims(const onert::ir::OperandIndex index) noexcept
{
- const auto operand_shape = _execution->primary_subgraph().operands().at(index).shape();
+ const auto &operand_shape = _execution->primary_subgraph().operands().at(index).shape();
return operand_shape.hasUnspecifiedDims();
}
@@ -127,10 +138,10 @@ bool ANeuralNetworksExecution::setInput(uint32_t index, const ANeuralNetworksOpe
onert::ir::IOIndex input_index{index};
const auto operand_index = getInputOperandIndex(index);
- const auto type_info = _execution->primary_subgraph().operands().at(operand_index).typeInfo();
+ const auto &type_info = _execution->primary_subgraph().operands().at(operand_index).typeInfo();
const auto shape = (type != nullptr)
- ? NNAPIConvert::getShape(type)
- : _execution->primary_subgraph().operands().at(operand_index).shape();
+ ? NNAPIConvert::getShape(type)
+ : _execution->primary_subgraph().operands().at(operand_index).shape();
// NOTE The nnapi does not provide setting io_layout and not support changing layout. In other
// words, we can assume that io_layout from nnapi always is the same as layout of the used
@@ -148,6 +159,44 @@ bool ANeuralNetworksExecution::setInput(uint32_t index, const ANeuralNetworksOpe
return true;
}
+bool ANeuralNetworksExecution::setOptionalInput(uint32_t index,
+ const ANeuralNetworksOperandType *type,
+ const void *buffer, size_t length) noexcept
+{
+ assert(type == nullptr);
+ assert(buffer == nullptr);
+ assert(length == 0);
+ try
+ {
+ onert::ir::IOIndex input_index{index};
+ const auto operand_index = getInputOperandIndex(index);
+
+ const auto shape = (type != nullptr)
+ ? NNAPIConvert::getShape(type)
+ : _execution->primary_subgraph().operands().at(operand_index).shape();
+
+ // ANeuralNetworksExecution::setInput() uses only shape information
+ ANeuralNetworksOperandType optional_input_type;
+ optional_input_type.dimensionCount = shape.rank();
+ std::vector<uint32_t> dims(optional_input_type.dimensionCount);
+ for (uint32_t i = 0; i < optional_input_type.dimensionCount; ++i)
+ {
+ dims.at(i) = shape.dim(i);
+ }
+ optional_input_type.dimensions = dims.data();
+
+ return setInput(index, &optional_input_type, buffer, length);
+ }
+ catch (const std::exception &e)
+ {
+ VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+ return false;
+ }
+
+ return true;
+}
+
bool ANeuralNetworksExecution::setOutput(uint32_t index, const ANeuralNetworksOperandType *type,
void *buffer, size_t length) noexcept
{
@@ -156,10 +205,10 @@ bool ANeuralNetworksExecution::setOutput(uint32_t index, const ANeuralNetworksOp
onert::ir::IOIndex output_index{index};
const auto operand_index = getOutputOperandIndex(index);
- const auto type_info = _execution->primary_subgraph().operands().at(operand_index).typeInfo();
+ const auto &type_info = _execution->primary_subgraph().operands().at(operand_index).typeInfo();
const auto shape = (type != nullptr)
- ? NNAPIConvert::getShape(type)
- : _execution->primary_subgraph().operands().at(operand_index).shape();
+ ? NNAPIConvert::getShape(type)
+ : _execution->primary_subgraph().operands().at(operand_index).shape();
// NOTE The nnapi does not provide setting io_layout and not support changing layout. In other
// words, we can assume that io_layout from nnapi always is the same as layout of the used
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.h b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.h
index 848ae743f..6fbc4c2e0 100644
--- a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.h
+++ b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.h
@@ -26,8 +26,8 @@
struct ANeuralNetworksExecution
{
public:
- ANeuralNetworksExecution(const std::shared_ptr<onert::exec::ExecutorMap> &executors)
- : _execution{std::make_shared<onert::exec::Execution>(executors)}
+ ANeuralNetworksExecution(const std::shared_ptr<onert::exec::IExecutors> &executors)
+ : _execution{std::make_shared<onert::exec::Execution>(executors)}
{
// DO NOTHING
}
@@ -35,6 +35,8 @@ public:
public:
bool setInput(uint32_t index, const ANeuralNetworksOperandType *type, const void *buffer,
size_t length) noexcept;
+ bool setOptionalInput(uint32_t index, const ANeuralNetworksOperandType *type, const void *buffer,
+ size_t length) noexcept;
bool setOutput(uint32_t index, const ANeuralNetworksOperandType *type, void *buffer,
size_t length) noexcept;
bool startExecute(void) noexcept;
@@ -46,6 +48,7 @@ public:
const onert::ir::OperandIndex index) noexcept;
bool compareShape(const ANeuralNetworksOperandType *type,
const onert::ir::OperandIndex index) noexcept;
+ bool IsOptionalInput(const onert::ir::OperandIndex index) noexcept;
bool hasUnspecifiedDims(const onert::ir::OperandIndex index) noexcept;
size_t getOperandSize(const onert::ir::OperandIndex index) noexcept;
const std::shared_ptr<onert::exec::Execution> instance(void) noexcept;
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc
index 97b820aea..837dac954 100644
--- a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc
+++ b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc
@@ -27,7 +27,8 @@
// ANeuralNetworksModel
//
ANeuralNetworksModel::ANeuralNetworksModel() noexcept
- : _optional_operands{}, _operand_usages{}, _allowFloat32toFloat16{false}
+ : _finished_building{false}, _optional_operands{}, _operand_usages{}, _allowFloat32toFloat16{
+ false}
{
_graph = std::make_shared<onert::ir::Graph>();
}
@@ -72,12 +73,12 @@ bool ANeuralNetworksModel::setOperandValue(uint32_t index, const void *buffer, s
if (copy)
{
_graph->operands().at(ind).data(
- std::make_unique<CachedData>(reinterpret_cast<const uint8_t *>(buffer), length));
+ std::make_unique<CachedData>(reinterpret_cast<const uint8_t *>(buffer), length));
}
else
{
_graph->operands().at(ind).data(
- std::make_unique<ExternalData>(reinterpret_cast<const uint8_t *>(buffer), length));
+ std::make_unique<ExternalData>(reinterpret_cast<const uint8_t *>(buffer), length));
}
}
catch (const std::exception &e)
@@ -111,9 +112,9 @@ bool ANeuralNetworksModel::addOperation(ANeuralNetworksOperationType type, uint3
if (type == ANEURALNETWORKS_FULLY_CONNECTED)
{
const auto &input_operand =
- _graph->operands().at(node->getInputs().at(onert::ir::operation::FullyConnected::INPUT));
+ _graph->operands().at(node->getInputs().at(onert::ir::operation::FullyConnected::INPUT));
auto &weights_operand =
- _graph->operands().at(node->getInputs().at(onert::ir::operation::FullyConnected::WEIGHT));
+ _graph->operands().at(node->getInputs().at(onert::ir::operation::FullyConnected::WEIGHT));
if (input_operand.typeInfo().type() == onert::ir::DataType::FLOAT32 &&
weights_operand.typeInfo().type() == onert::ir::DataType::QUANT_UINT8_ASYMM)
{
@@ -208,9 +209,9 @@ bool ANeuralNetworksModel::finish() noexcept
{
fillOptionalOperand();
- _graph->finishBuilding();
-
+ _graph->verify();
_operand_usages.clear();
+ _finished_building = true;
}
catch (const std::exception &e)
{
@@ -222,7 +223,7 @@ bool ANeuralNetworksModel::finish() noexcept
return true;
}
-bool ANeuralNetworksModel::isFinished() noexcept { return !_graph->isBuildingPhase(); }
+bool ANeuralNetworksModel::isFinished() noexcept { return _finished_building; }
bool ANeuralNetworksModel::isExistOperand(uint32_t index) noexcept
{
@@ -260,8 +261,8 @@ void ANeuralNetworksModel::setOptionalOperand(const onert::ir::OperandIndex idx)
void ANeuralNetworksModel::fillOptionalOperand(void)
{
- _graph->operations().iterate([&](const onert::ir::OperationIndex &, onert::ir::Operation &node) {
- for (auto input : node.getInputs())
+ _graph->operations().iterate([&](const onert::ir::OperationIndex &, onert::ir::IOperation &node) {
+ for (auto &&input : node.getInputs())
{
// TODO fill default value for optional operands
if (_optional_operands.find(input) != _optional_operands.end())
@@ -272,16 +273,16 @@ void ANeuralNetworksModel::fillOptionalOperand(void)
});
}
-std::shared_ptr<onert::ir::Subgraphs> ANeuralNetworksModel::getSubGraphs() const
+std::shared_ptr<onert::ir::Model> ANeuralNetworksModel::getModel() const
{
- auto all_subgs = std::make_shared<onert::ir::Subgraphs>();
+ auto model = std::make_shared<onert::ir::Model>();
- all_subgs->push(onert::ir::SubgraphIndex{0}, _graph);
+ model->push(onert::ir::SubgraphIndex{0}, _graph);
// TODO Find all child subgraphs and copy them to all_subgs
// Must find the same subgraph by using to compare pointer of subgraphs and set subgraph's index
// to operands of control flow operations
// Must clean all child subgraphs's pointer to prevent memory leak in case of that graph has
// subgraph itself recursively
- return all_subgs;
+ return model;
}
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.h b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.h
index df6c97c44..04f4cf0f2 100644
--- a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.h
+++ b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.h
@@ -22,7 +22,7 @@
#include <NeuralNetworksEx.h>
#include "ir/Graph.h"
-#include "ir/Subgraphs.h"
+#include "ir/Model.h"
struct ANeuralNetworksModel
{
@@ -59,7 +59,7 @@ public:
size_t operandSize(uint32_t index) noexcept;
bool isUsageSet(uint32_t index) noexcept;
bool isOperationOutput(uint32_t index) noexcept;
- std::shared_ptr<onert::ir::Subgraphs> getSubGraphs() const;
+ std::shared_ptr<onert::ir::Model> getModel() const;
private:
void setOptionalOperand(const onert::ir::OperandIndex idx);
@@ -67,6 +67,7 @@ private:
private:
std::shared_ptr<onert::ir::Graph> _graph;
+ bool _finished_building;
std::unordered_set<onert::ir::OperandIndex> _optional_operands;
std::vector<OperandUsage> _operand_usages;
bool _allowFloat32toFloat16;
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.test.cc b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.test.cc
new file mode 100644
index 000000000..bb42f2b08
--- /dev/null
+++ b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.test.cc
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#include <gtest/gtest.h>
+
+#include "ANeuralNetworksModel.h"
+
+TEST(MODEL, neg_model_build)
+{
+ ANeuralNetworksModel model;
+ ASSERT_FALSE(model.isFinished());
+}
diff --git a/runtime/onert/frontend/nnapi/wrapper/NNAPIConvert.cc b/runtime/onert/frontend/nnapi/wrapper/NNAPIConvert.cc
index 63d4e3c09..94b8f02f5 100644
--- a/runtime/onert/frontend/nnapi/wrapper/NNAPIConvert.cc
+++ b/runtime/onert/frontend/nnapi/wrapper/NNAPIConvert.cc
@@ -39,6 +39,13 @@ DataType NNAPIConvert::getDataType(OperandCode type)
case ANEURALNETWORKS_BOOL:
case ANEURALNETWORKS_TENSOR_BOOL8:
return DataType::BOOL8;
+ case ANEURALNETWORKS_TENSOR_FLOAT16:
+ case ANEURALNETWORKS_FLOAT16:
+ return DataType::FLOAT16;
+ case ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL:
+ return DataType::QUANT_INT8_SYMM_PER_CHANNEL;
+ case ANEURALNETWORKS_TENSOR_QUANT8_ASYMM_SIGNED:
+ return DataType::QUANT_INT8_ASYMM;
default:
throw std::runtime_error("Unsupported type");
}
diff --git a/runtime/onert/frontend/nnapi/wrapper/OperationFactory.cc b/runtime/onert/frontend/nnapi/wrapper/OperationFactory.cc
index 8e3d83db4..ba739f618 100644
--- a/runtime/onert/frontend/nnapi/wrapper/OperationFactory.cc
+++ b/runtime/onert/frontend/nnapi/wrapper/OperationFactory.cc
@@ -82,6 +82,27 @@ uint32_t getUint32Scalar(Operands &operands, const OperandIndex index)
return static_cast<uint32_t>(int32_value);
}
+Activation getActivation(Operands &operands, const OperandIndex index)
+{
+ switch (operands.at(index).asScalar<int32_t>())
+ {
+ case 0:
+ return Activation::NONE;
+ case 1:
+ return Activation::RELU;
+ case 2:
+ return Activation::RELU1;
+ case 3:
+ return Activation::RELU6;
+ case 4:
+ return Activation::TANH;
+ case 6:
+ return Activation::SIGMOID;
+ default:
+ throw std::runtime_error("Unsupported activation type");
+ }
+}
+
OperationFactory::Generator
getElementwiseActivationGenerator(const onert::ir::operation::ElementwiseActivation::Type op_type,
float alpha = 0.f, float beta = 0.f)
@@ -107,7 +128,7 @@ getElementwiseActivationGenerator(const onert::ir::operation::ElementwiseActivat
}
OperationFactory::Generator getElementwiseBinaryGenerator(
- const onert::ir::operation::ElementwiseBinary::ElementwiseBinaryType op_type)
+ const onert::ir::operation::ElementwiseBinary::ElementwiseBinaryType op_type)
{
return [op_type](const OperationFactory::Param &init_param, Operands &) {
assert(init_param.input_count == 2);
@@ -182,7 +203,7 @@ getBinaryArithmeticGenerator(const onert::ir::operation::BinaryArithmetic::Arith
param.arithmetic_type = op_type;
const auto activation_index = OperandIndex{init_param.inputs[2]};
param.activation =
- NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
+ NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
return new operation::BinaryArithmetic{inputs, outputs, param};
};
@@ -221,12 +242,12 @@ getPool2DGenerator(const onert::ir::operation::Pool2D::PoolType pool_type)
const auto activation_index = OperandIndex{init_param.inputs[6]};
param.padding.type =
- NNAPIConvert::getPaddingType(operands.at(padding_index).asScalar<PaddingCode>());
+ NNAPIConvert::getPaddingType(operands.at(padding_index).asScalar<PaddingCode>());
param.stride = makeStride(operands, hstride_index, vstride_index);
param.kw = getUint32Scalar(operands, kw_index);
param.kh = operands.at(kh_index).asScalar<uint32_t>();
param.activation =
- NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
+ NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
}
else // support explicit padding
{
@@ -259,7 +280,7 @@ getPool2DGenerator(const onert::ir::operation::Pool2D::PoolType pool_type)
param.kw = getUint32Scalar(operands, kw_index);
param.kh = getUint32Scalar(operands, kh_index);
param.activation =
- NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
+ NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
}
return new operation::Pool2D{inputs, outputs, param};
};
@@ -382,11 +403,11 @@ OperationFactory::OperationFactory()
const auto activation_index = OperandIndex{init_param.inputs[7]};
param.padding.type =
- NNAPIConvert::getPaddingType(operands.at(padding_index).asScalar<PaddingCode>());
+ NNAPIConvert::getPaddingType(operands.at(padding_index).asScalar<PaddingCode>());
param.stride = makeStride(operands, hstride_index, vstride_index);
param.multiplier = getUint32Scalar(operands, multiplier_index);
param.activation =
- NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
+ NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
}
else
{
@@ -417,9 +438,13 @@ OperationFactory::OperationFactory()
param.stride = makeStride(operands, hstride_index, vstride_index);
param.multiplier = getUint32Scalar(operands, multiplier_index);
param.activation =
- NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
+ NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
}
+ // TODO set dilation
+ param.dilation.width_factor = 1;
+ param.dilation.height_factor = 1;
+
return new operation::DepthwiseConv2D{inputs, outputs, param};
};
@@ -486,7 +511,8 @@ OperationFactory::OperationFactory()
operation::FullyConnected::Param param;
const auto activation_index = OperandIndex{init_param.inputs[3]};
param.activation =
- NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
+ NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
+ param.weights_format = FullyConnectedWeightsFormat::Default;
return new operation::FullyConnected{inputs, outputs, param};
};
@@ -512,11 +538,7 @@ OperationFactory::OperationFactory()
};
_map[ANEURALNETWORKS_CAST] =
- getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::CAST);
-
- // ANEURALNETWORKS_CAST_EX is deprecated
- // TODO Remove ANEURALNETWORKS_CAST_EX
- _map[ANEURALNETWORKS_CAST_EX] = _map[ANEURALNETWORKS_CAST];
+ getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::CAST);
_map[ANEURALNETWORKS_CONV_2D] = [](const OperationFactory::Param &init_param,
Operands &operands) {
@@ -552,14 +574,14 @@ OperationFactory::OperationFactory()
const auto activation_index = OperandIndex{init_param.inputs[6]};
param.padding.type =
- NNAPIConvert::getPaddingType(operands.at(padding_index).asScalar<PaddingCode>());
+ NNAPIConvert::getPaddingType(operands.at(padding_index).asScalar<PaddingCode>());
param.stride = makeStride(operands, hstride_index, vstride_index);
param.dilation.width_factor = 1;
param.dilation.height_factor = 1;
param.activation =
- NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
+ NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
}
else if (init_param.input_count == 10) // support explicit padding
{
@@ -590,7 +612,7 @@ OperationFactory::OperationFactory()
param.dilation.height_factor = 1;
param.activation =
- NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
+ NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
}
else if (init_param.input_count == 13) // support dilation
{
@@ -628,7 +650,7 @@ OperationFactory::OperationFactory()
param.dilation.height_factor = height_factor;
param.activation =
- NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
+ NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
}
else
{
@@ -639,19 +661,15 @@ OperationFactory::OperationFactory()
};
_map[ANEURALNETWORKS_ADD] =
- getBinaryArithmeticGenerator(onert::ir::operation::BinaryArithmetic::ArithmeticType::ADD);
+ getBinaryArithmeticGenerator(onert::ir::operation::BinaryArithmetic::ArithmeticType::ADD);
_map[ANEURALNETWORKS_ADDV2_EX] = _map[ANEURALNETWORKS_ADD];
_map[ANEURALNETWORKS_REDUCE_SUM] =
- getReduceGenerator(onert::ir::operation::Reduce::ReduceType::SUM);
-
- // ANEURALNETWORKS_REDUCE_SUM_EX is deprecated
- // TODO Remove ANEURALNETWORKS_REDUCE_SUM_EX
- _map[ANEURALNETWORKS_REDUCE_SUM_EX] = _map[ANEURALNETWORKS_REDUCE_SUM];
+ getReduceGenerator(onert::ir::operation::Reduce::ReduceType::SUM);
_map[ANEURALNETWORKS_SUB] =
- getBinaryArithmeticGenerator(onert::ir::operation::BinaryArithmetic::ArithmeticType::SUB);
+ getBinaryArithmeticGenerator(onert::ir::operation::BinaryArithmetic::ArithmeticType::SUB);
_map[ANEURALNETWORKS_SLICE] = [](const OperationFactory::Param &init_param, Operands &) {
assert(init_param.input_count == 3 && init_param.output_count == 1);
@@ -703,39 +721,15 @@ OperationFactory::OperationFactory()
param.begin_mask = operands.at(OperandIndex{init_param.inputs[4]}).asScalar<std::int32_t>();
param.end_mask = operands.at(OperandIndex{init_param.inputs[5]}).asScalar<std::int32_t>();
param.shrink_axis_mask =
- operands.at(OperandIndex{init_param.inputs[6]}).asScalar<std::int32_t>();
+ operands.at(OperandIndex{init_param.inputs[6]}).asScalar<std::int32_t>();
return new operation::StridedSlice{inputs, outputs, param};
};
- _map[ANEURALNETWORKS_TRANSPOSE] = [](const OperationFactory::Param &init_param,
- Operands &operands) {
- // TODO make this work with init_param.input_count == 1 (when permutation vector is optional)
-
- // Inputs
- // 0: An n-D tensor, specifying the tensor to be transposed.
- // 1: An optional 1-D Tensor of {@link ANEURALNETWORKS_TENSOR_INT32},
- // the permutation of the dimensions of the input tensor.
- // The returned tensor's dimension i corresponds to the input dimension
- // perm[i]. If perm is not given, it is set to (n-1...0), where n is the
- // rank of the input tensor. Hence by default, this operation performs a
- // regular matrix transpose on 2-D input Tensors.
- assert(init_param.input_count == 2);
- assert(init_param.output_count == 1);
-
- OperandIndexSequence inputs{init_param.inputs[0]};
- OperandIndexSequence outputs{init_param.outputs[0]};
- std::vector<std::int32_t> perm =
- operands.at(OperandIndex{init_param.inputs[1]}).asVector<std::int32_t>();
-
- operation::Transpose::Param param;
- param.perm.assign(perm.cbegin(), perm.cend());
-
- return new operation::Transpose{inputs, outputs, param};
- };
+ _map[ANEURALNETWORKS_TRANSPOSE] = createSimpleBinaryOp<operation::Transpose>;
_map[ANEURALNETWORKS_MUL] =
- getBinaryArithmeticGenerator(onert::ir::operation::BinaryArithmetic::ArithmeticType::MUL);
+ getBinaryArithmeticGenerator(onert::ir::operation::BinaryArithmetic::ArithmeticType::MUL);
_map[ANEURALNETWORKS_SQUEEZE] = [](const OperationFactory::Param &init_param,
Operands &operands) {
@@ -777,151 +771,49 @@ OperationFactory::OperationFactory()
};
_map[ANEURALNETWORKS_TANH] = getElementwiseActivationGenerator(
- onert::ir::operation::ElementwiseActivation::Type::TANH, 1.f, 1.f);
+ onert::ir::operation::ElementwiseActivation::Type::TANH, 1.f, 1.f);
_map[ANEURALNETWORKS_LOG] = getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::LOG);
- _map[ANEURALNETWORKS_LOGISTIC] = getElementwiseActivationGenerator(
- onert::ir::operation::ElementwiseActivation::Type::LOGISTIC);
+ _map[ANEURALNETWORKS_LOGISTIC] =
+ getElementwiseActivationGenerator(onert::ir::operation::ElementwiseActivation::Type::LOGISTIC);
_map[ANEURALNETWORKS_DIV] =
- getBinaryArithmeticGenerator(onert::ir::operation::BinaryArithmetic::ArithmeticType::DIV);
+ getBinaryArithmeticGenerator(onert::ir::operation::BinaryArithmetic::ArithmeticType::DIV);
_map[ANEURALNETWORKS_EXP] = getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::EXP);
- // ANEURALNETWORKS_EXP_EX is deprecated
- // TODO Remove ANEURALNETWORKS_EXP_EX
- _map[ANEURALNETWORKS_EXP_EX] = _map[ANEURALNETWORKS_EXP];
-
// Each input should be interpreted as follows:
// 0 -> Input Tensor Index
// 1 -> Axis Tensor Index
_map[ANEURALNETWORKS_EXPAND_DIMS] = createSimpleBinaryOp<operation::ExpandDims>;
_map[ANEURALNETWORKS_GREATER] =
- getComparisonGenerator(operation::Comparison::ComparisonType::Greater);
+ getComparisonGenerator(operation::Comparison::ComparisonType::Greater);
_map[ANEURALNETWORKS_GREATER_EQUAL] =
- getComparisonGenerator(operation::Comparison::ComparisonType::GreaterEqual);
+ getComparisonGenerator(operation::Comparison::ComparisonType::GreaterEqual);
_map[ANEURALNETWORKS_LESS] = getComparisonGenerator(operation::Comparison::ComparisonType::Less);
_map[ANEURALNETWORKS_LESS_EQUAL] =
- getComparisonGenerator(operation::Comparison::ComparisonType::LessEqual);
+ getComparisonGenerator(operation::Comparison::ComparisonType::LessEqual);
_map[ANEURALNETWORKS_NOT_EQUAL] =
- getComparisonGenerator(operation::Comparison::ComparisonType::NotEqual);
+ getComparisonGenerator(operation::Comparison::ComparisonType::NotEqual);
_map[ANEURALNETWORKS_EQUAL] =
- getComparisonGenerator(operation::Comparison::ComparisonType::Equal);
-
- // ANEURALNETWORKS_GREATER_EQUAL_EX is deprecated
- // TODO Remove ANEURALNETWORKS_GREATER_EQUAL_EX
- _map[ANEURALNETWORKS_GREATER_EQUAL_EX] = [](const OperationFactory::Param &init_param,
- Operands &operands) {
- assert(init_param.input_count == 2 && init_param.output_count == 1);
-
- OperandIndexSequence outputs{init_param.outputs[0]};
-
- // Each input should be interpreted as follows:
- //
- // 0 -> input0 Tensor Index
- // 1 -> input1 Tensor Index
- OperandIndexSequence inputs{init_param.inputs[0], init_param.inputs[1]};
-
- operation::Comparison::Param param;
- param.comparison_type = operation::Comparison::ComparisonType::GreaterEqual;
-
- // Output operand type must be boolean
- replaceDataType(operands, outputs.at(0), DataType::BOOL8);
-
- return new operation::Comparison{inputs, outputs, param};
- };
-
- // ANEURALNETWORKS_LESS_EX is deprecated
- // TODO Remove ANEURALNETWORKS_LESS_EX
- _map[ANEURALNETWORKS_LESS_EX] = [](const OperationFactory::Param &init_param,
- Operands &operands) {
- assert(init_param.input_count == 2 && init_param.output_count == 1);
-
- OperandIndexSequence outputs{init_param.outputs[0]};
-
- // Each input should be interpreted as follows:
- //
- // 0 -> input0 Tensor Index
- // 1 -> input1 Tensor Index
- OperandIndexSequence inputs{init_param.inputs[0], init_param.inputs[1]};
-
- operation::Comparison::Param param;
- param.comparison_type = operation::Comparison::ComparisonType::Less;
-
- // Output operand type must be boolean
- replaceDataType(operands, outputs.at(0), DataType::BOOL8);
-
- return new operation::Comparison{inputs, outputs, param};
- };
+ getComparisonGenerator(operation::Comparison::ComparisonType::Equal);
_map[ANEURALNETWORKS_REDUCE_ALL] =
- getReduceGenerator(onert::ir::operation::Reduce::ReduceType::ALL);
+ getReduceGenerator(onert::ir::operation::Reduce::ReduceType::ALL);
_map[ANEURALNETWORKS_REDUCE_ANY] =
- getReduceGenerator(onert::ir::operation::Reduce::ReduceType::ANY);
+ getReduceGenerator(onert::ir::operation::Reduce::ReduceType::ANY);
_map[ANEURALNETWORKS_REDUCE_MAX] =
- getReduceGenerator(onert::ir::operation::Reduce::ReduceType::MAX);
-
- // ANEURALNETWORKS_REDUCE_MAX_EX is deprecated
- // TODO Remove ANEURALNETWORKS_REDUCE_MAX_EX
- _map[ANEURALNETWORKS_REDUCE_MAX_EX] = _map[ANEURALNETWORKS_REDUCE_MAX];
-
- // ANEURALNETWORKS_NOT_EQUAL_EX is deprecated
- // TODO Remove ANEURALNETWORKS_NOT_EQUAL_EX
- _map[ANEURALNETWORKS_NOT_EQUAL_EX] = [](const OperationFactory::Param &init_param,
- Operands &operands) {
- assert(init_param.input_count == 2 && init_param.output_count == 1);
-
- OperandIndexSequence outputs{init_param.outputs[0]};
-
- // Each input should be interpreted as follows:
- //
- // 0 -> input1 Tensor Index
- // 1 -> input2 Tensor Index
- OperandIndexSequence inputs{init_param.inputs[0], init_param.inputs[1]};
-
- operation::Comparison::Param param;
- param.comparison_type = operation::Comparison::ComparisonType::NotEqual;
-
- // Output operand type must be boolean
- replaceDataType(operands, outputs.at(0), DataType::BOOL8);
-
- return new operation::Comparison{inputs, outputs, param};
- };
-
- _map[ANEURALNETWORKS_LOGICAL_AND] = getElementwiseBinaryGenerator(
- operation::ElementwiseBinary::ElementwiseBinaryType::LOGICAL_AND);
-
- // ANEURALNETWORKS_LOGICAL_AND_EX is deprecated
- // TODO Remove ANEURALNETWORKS_LOGICAL_AND_EX
- _map[ANEURALNETWORKS_LOGICAL_AND_EX] = [](const OperationFactory::Param &init_param,
- Operands &operands) {
- assert(init_param.input_count == 2 && init_param.output_count == 1);
-
- OperandIndexSequence outputs{init_param.outputs[0]};
-
- // Each input should be interpreted as follows:
- //
- // 0 -> input0 Tensor Index
- // 1 -> input1 Tensor Index
- OperandIndexSequence inputs{init_param.inputs[0], init_param.inputs[1]};
-
- // This operation's operands must be boolean type.
- replaceDataType(operands, inputs.at(0), DataType::BOOL8);
- replaceDataType(operands, inputs.at(1), DataType::BOOL8);
- replaceDataType(operands, outputs.at(0), DataType::BOOL8);
+ getReduceGenerator(onert::ir::operation::Reduce::ReduceType::MAX);
- operation::ElementwiseBinary::Param param;
- param.op_type = operation::ElementwiseBinary::ElementwiseBinaryType::LOGICAL_AND;
-
- return new operation::ElementwiseBinary{inputs, outputs, param};
- };
+ _map[ANEURALNETWORKS_LOGICAL_AND] =
+ getElementwiseBinaryGenerator(operation::ElementwiseBinary::ElementwiseBinaryType::LOGICAL_AND);
_map[ANEURALNETWORKS_RSQRT] =
- getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::RSQRT);
+ getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::RSQRT);
_map[ANEURALNETWORKS_SELECT] = [](const OperationFactory::Param &init_param, Operands &) {
assert(init_param.input_count == 3 && init_param.output_count == 1);
@@ -938,28 +830,11 @@ OperationFactory::OperationFactory()
return new operation::Select{inputs, outputs};
};
- _map[ANEURALNETWORKS_SELECT_V2_EX] = [](const OperationFactory::Param &init_param, Operands &) {
- assert(init_param.input_count == 3 && init_param.output_count == 1);
-
- OperandIndexSequence outputs{init_param.outputs[0]};
-
- // Each input should be interpreted as follows:
- //
- // 0 -> Condition Tensor Index
- // 1 -> Input X(true) Tensor Index
- // 2 -> Input Y(false) Tensor Index
- OperandIndexSequence inputs{init_param.inputs[0], init_param.inputs[1], init_param.inputs[2]};
-
- return new operation::Select{inputs, outputs};
- };
-
- // ANEURALNETWORKS_RSQRT_EX is deprecated
- // TODO Remove ANEURALNETWORKS_RSQRT_EX
- _map[ANEURALNETWORKS_RSQRT_EX] = _map[ANEURALNETWORKS_RSQRT];
+ _map[ANEURALNETWORKS_SELECT_V2_EX] = _map[ANEURALNETWORKS_SELECT];
_map[ANEURALNETWORKS_RELU] =
- getElementwiseActivationGenerator(onert::ir::operation::ElementwiseActivation::Type::RELU,
- onert::ir::operation::ElementwiseActivation::infinity, 0);
+ getElementwiseActivationGenerator(onert::ir::operation::ElementwiseActivation::Type::RELU,
+ onert::ir::operation::ElementwiseActivation::infinity, 0);
_map[ANEURALNETWORKS_RESIZE_BILINEAR] = [](const OperationFactory::Param &init_param,
Operands &operands) {
@@ -982,11 +857,33 @@ OperationFactory::OperationFactory()
return new operation::ResizeBilinear{inputs, outputs, param};
};
+ _map[ANEURALNETWORKS_RESIZE_NEAREST_NEIGHBOR] = [](const OperationFactory::Param &init_param,
+ Operands &operands) {
+ assert((init_param.input_count == 3 || init_param.input_count == 4) &&
+ init_param.output_count == 1);
+
+ OperandIndexSequence outputs{init_param.outputs[0]};
+
+ // Each input should be interpreted as follows:
+ //
+ // 0 -> IFM Index
+ // 1 -> Height Index
+ // 2 -> Width Index
+ OperandIndexSequence inputs{init_param.inputs[0]};
+
+ operation::ResizeNearestNeighbor::Param param;
+ param.height_out = operands.at(OperandIndex{init_param.inputs[1]}).asScalar<int32_t>();
+ param.width_out = operands.at(OperandIndex{init_param.inputs[2]}).asScalar<int32_t>();
+ param.align_corners = false;
+ // The layout input is not supported yet
+ return new operation::ResizeNearestNeighbor{inputs, outputs, param};
+ };
+
_map[ANEURALNETWORKS_RELU1] = getElementwiseActivationGenerator(
- onert::ir::operation::ElementwiseActivation::Type::RELU, 1.f, -1.f);
+ onert::ir::operation::ElementwiseActivation::Type::RELU, 1.f, -1.f);
_map[ANEURALNETWORKS_RELU6] = getElementwiseActivationGenerator(
- onert::ir::operation::ElementwiseActivation::Type::RELU, 6.f, 0.f);
+ onert::ir::operation::ElementwiseActivation::Type::RELU, 6.f, 0.f);
_map[ANEURALNETWORKS_REVERSE_EX] = [](const OperationFactory::Param &init_param, Operands &) {
assert(init_param.input_count == 2 && init_param.output_count == 1);
@@ -1028,13 +925,13 @@ OperationFactory::OperationFactory()
operation::RNN::Param param;
const auto activation_index = OperandIndex{init_param.inputs[5]};
param.activation =
- NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
+ NNAPIConvert::getFusedActivation(operands.at(activation_index).asScalar<FuseCode>());
return new operation::RNN{inputs, outputs, param};
};
_map[ANEURALNETWORKS_FLOOR] =
- getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::FLOOR);
+ getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::FLOOR);
_map[ANEURALNETWORKS_SPACE_TO_BATCH_ND] = [](const OperationFactory::Param &init_param,
Operands &) {
@@ -1138,10 +1035,6 @@ OperationFactory::OperationFactory()
return new operation::PReLU{inputs, outputs};
};
- // ANEURALNETWORKS_PRELU_EX is deprecated
- // TODO Remove ANEURALNETWORKS_PRELU_EX
- _map[ANEURALNETWORKS_PRELU_EX] = _map[ANEURALNETWORKS_PRELU];
-
_map[ANEURALNETWORKS_TRANSPOSE_CONV_EX] = [](const OperationFactory::Param &init_param,
Operands &operands) {
assert(init_param.input_count == 6 && init_param.output_count == 1);
@@ -1166,72 +1059,20 @@ OperationFactory::OperationFactory()
const auto vstride_index = OperandIndex{init_param.inputs[5]};
param.padding.type =
- NNAPIConvert::getPaddingType(operands.at(padding_index).asScalar<PaddingCode>());
+ NNAPIConvert::getPaddingType(operands.at(padding_index).asScalar<PaddingCode>());
param.stride = makeStride(operands, hstride_index, vstride_index);
return new operation::TransposeConv{inputs, outputs, param};
};
_map[ANEURALNETWORKS_SQRT] =
- getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::SQRT);
+ getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::SQRT);
- // ANEURALNETWORKS_SQRT_EX is deprecated
- // TODO Remove ANEURALNETWORKS_SQRT_EX
- _map[ANEURALNETWORKS_SQRT_EX] = _map[ANEURALNETWORKS_SQRT];
-
- _map[ANEURALNETWORKS_LOGICAL_OR] = getElementwiseBinaryGenerator(
- operation::ElementwiseBinary::ElementwiseBinaryType::LOGICAL_OR);
-
- // ANEURALNETWORKS_LOGICAL_OR_EX is deprecated
- // TODO Remove ANEURALNETWORKS_LOGICAL_OR_EX
- _map[ANEURALNETWORKS_LOGICAL_OR_EX] = [](const OperationFactory::Param &init_param,
- Operands &operands) {
- assert(init_param.input_count == 2 && init_param.output_count == 1);
-
- OperandIndexSequence outputs{init_param.outputs[0]};
-
- // Each input should be interpreted as follows:
- //
- // 0 -> input0 Tensor Index
- // 1 -> input1 Tensor Index
- OperandIndexSequence inputs{init_param.inputs[0], init_param.inputs[1]};
-
- // This operation's operands must be boolean type.
- replaceDataType(operands, inputs.at(0), DataType::BOOL8);
- replaceDataType(operands, inputs.at(1), DataType::BOOL8);
- replaceDataType(operands, outputs.at(0), DataType::BOOL8);
-
- operation::ElementwiseBinary::Param param;
- param.op_type = operation::ElementwiseBinary::ElementwiseBinaryType::LOGICAL_OR;
-
- return new operation::ElementwiseBinary{inputs, outputs, param};
- };
+ _map[ANEURALNETWORKS_LOGICAL_OR] =
+ getElementwiseBinaryGenerator(operation::ElementwiseBinary::ElementwiseBinaryType::LOGICAL_OR);
_map[ANEURALNETWORKS_LOGICAL_NOT] =
- getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::LOGICAL_NOT);
-
- // ANEURALNETWORKS_LOGICAL_NOT_EX is deprecated
- // TODO Remove ANEURALNETWORKS_LOGICAL_NOT_EX
- _map[ANEURALNETWORKS_LOGICAL_NOT_EX] = [](const OperationFactory::Param &init_param,
- Operands &operands) {
- assert(init_param.input_count == 1 && init_param.output_count == 1);
-
- OperandIndexSequence outputs{init_param.outputs[0]};
-
- // Each input should be interpreted as follows:
- //
- // 0 -> input Tensor Index
- OperandIndexSequence inputs{init_param.inputs[0]};
-
- // This operation's operands must be boolean type.
- replaceDataType(operands, inputs.at(0), DataType::BOOL8);
- replaceDataType(operands, outputs.at(0), DataType::BOOL8);
-
- operation::ElementwiseUnary::Param param;
- param.op_type = operation::ElementwiseUnary::Type::LOGICAL_NOT;
-
- return new operation::ElementwiseUnary{inputs, outputs, param};
- };
+ getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::LOGICAL_NOT);
_map[ANEURALNETWORKS_LSTM] = [](const OperationFactory::Param &init_param, Operands &operands) {
assert(init_param.input_count == 23 && init_param.output_count == 4);
@@ -1277,58 +1118,86 @@ OperationFactory::OperationFactory()
}
operation::LSTM::Param param;
- const auto activation_index = OperandIndex{init_param.inputs[20]};
- switch (operands.at(activation_index).asScalar<int32_t>())
- {
- case 0:
- param.activation = Activation::NONE;
- break;
- case 1:
- param.activation = Activation::RELU;
- break;
- case 2:
- param.activation = Activation::RELU1;
- break;
- case 3:
- param.activation = Activation::RELU6;
- break;
- case 4:
- param.activation = Activation::TANH;
- break;
- case 6:
- param.activation = Activation::SIGMOID;
- break;
- default:
- throw std::runtime_error("Unsupported activation type");
- break;
- }
+ param.activation = getActivation(operands, OperandIndex{init_param.inputs[20]});
param.cell_threshold = operands.at(OperandIndex{init_param.inputs[21]}).asScalar<float>();
param.projection_threshold = operands.at(OperandIndex{init_param.inputs[22]}).asScalar<float>();
+ // This is initialization to prevent warning or error by static code analyzer. LSTM operation
+ // does not need time_major
+ param.time_major = false;
return new operation::LSTM{inputs, outputs, param};
};
- // ANEURALNETWORKS_EQUAL_EX is deprecated
- // TODO Remove ANEURALNETWORKS_EQUAL_EX
- _map[ANEURALNETWORKS_EQUAL_EX] = [](const OperationFactory::Param &init_param,
- Operands &operands) {
- assert(init_param.input_count == 2 && init_param.output_count == 1);
-
- OperandIndexSequence outputs{init_param.outputs[0]};
+ _map[ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_LSTM] = [](const OperationFactory::Param &init_param,
+ Operands &operands) {
+ assert((init_param.input_count >= 24 || init_param.input_count <= 28) &&
+ (init_param.output_count >= 1 && init_param.output_count <= 3));
// Each input should be interpreted as follows:
//
- // 0 -> input0 Tensor Index
- // 1 -> input1 Tensor Index
- OperandIndexSequence inputs{init_param.inputs[0], init_param.inputs[1]};
+ // 0 -> Input Tensor Index
+ // 1 -> Input to Input Tensor Index
+ // 2 -> Input to Forget Tensor Index
+ // 3 -> Input to Cell Tensor Index
+ // 4 -> Input to Output Tensor Index
+ // 5 -> Recurrent to Input Weights Tensor Index
+ // 6 -> Recurrent to Forget Weights Tensor Index
+ // 7 -> Recurrent to Cell Weights Tensor Index
+ // 8 -> Recurrent to Output Weights Tensor Index
+ // 9 -> Cell to Input Weights Tensor Index
+ // 10 -> Cell to Forget Weights Tensor Index
+ // 11 -> Cell to Output Weights Tensor Index
+ // 12 -> Input Gate Bias Tensor Index
+ // 13 -> Forget Gate Bias Tensor Index
+ // 14 -> Cell Bias Tensor Index
+ // 15 -> Output Gate Bias Tensor Index
+ // 16 -> Projection Weights Tensor Index
+ // 17 -> Projection Bias Tensor Index
+ // 18 -> Output State In Tensor Index
+ // 19 -> Cell State In Tensor Index
+ assert(init_param.input_count - 3 > 20);
+ OperandIndexSequence inputs;
+ for (uint32_t n = 0; n < 20; ++n)
+ {
+ inputs.append(OperandIndex{init_param.inputs[n]});
+ }
- operation::Comparison::Param param;
- param.comparison_type = operation::Comparison::ComparisonType::Equal;
+ // 24 -> Input Layer Normalization Weights Tensor Index
+ // 25 -> Forget Layer Normalization Weights Tensor Index
+ // 26 -> Cell Layer Normalization Weights Tensor Index
+ // 27 -> Output Layer Normalization Weights Tensor Index
+ if (init_param.input_count > 24)
+ {
+ for (uint32_t n = 24; n < 28; ++n)
+ {
+ if (init_param.input_count > n)
+ {
+ inputs.append(OperandIndex{init_param.inputs[n]});
+ }
+ }
+ }
+
+ // Each output should be interpreted as follows:
+ //
+ // 0 -> Output Tensor Index -> 3
+ // 1 -> Output State Out Tensor Index
+ // 2 -> Cell State Out Tensor Index
+ const OperandIndex scratch_buffer_index;
+ OperandIndex output_state_index =
+ init_param.output_count >= 2 ? OperandIndex{init_param.outputs[1]} : OperandIndex();
+ OperandIndex cell_state_index =
+ init_param.output_count >= 3 ? OperandIndex{init_param.outputs[2]} : OperandIndex();
+ const OperandIndex output_index = OperandIndex{init_param.outputs[0]};
+ OperandIndexSequence outputs{scratch_buffer_index, output_state_index, cell_state_index,
+ output_index};
- // Output operand type must be boolean
- replaceDataType(operands, outputs.at(0), DataType::BOOL8);
+ operation::LSTM::Param param;
+ param.activation = getActivation(operands, OperandIndex{init_param.inputs[20]});
+ param.cell_threshold = operands.at(OperandIndex{init_param.inputs[21]}).asScalar<float>();
+ param.projection_threshold = operands.at(OperandIndex{init_param.inputs[22]}).asScalar<float>();
+ param.time_major = operands.at(OperandIndex{init_param.inputs[23]}).asScalar<bool>();
- return new operation::Comparison{inputs, outputs, param};
+ return new operation::LSTM{inputs, outputs, param};
};
_map[ANEURALNETWORKS_SQUARED_DIFFERENCE_EX] = [](const OperationFactory::Param &init_param,
@@ -1368,10 +1237,6 @@ OperationFactory::OperationFactory()
return new operation::TopKV2{inputs, outputs, param};
};
- // ANEURALNETWORKS_CAST_EX is deprecated
- // TODO Remove ANEURALNETWORKS_CAST_EX
- _map[ANEURALNETWORKS_TOPK_V2_EX] = _map[ANEURALNETWORKS_TOPK_V2];
-
_map[ANEURALNETWORKS_GATHER] = [](const OperationFactory::Param &init_param, Operands &operands) {
assert(init_param.input_count == 3 && init_param.output_count == 1);
@@ -1390,23 +1255,11 @@ OperationFactory::OperationFactory()
return new operation::Gather{inputs, outputs, param};
};
- // ANEURALNETWORKS_GATHER_EX is deprecated
- // TODO Remove ANEURALNETWORKS_GATHER_EX
- _map[ANEURALNETWORKS_GATHER_EX] = _map[ANEURALNETWORKS_GATHER];
-
_map[ANEURALNETWORKS_NEG] = getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::NEG);
- // ANEURALNETWORKS_NEG_EX is deprecated
- // TODO Remove ANEURALNETWORKS_NEG_EX
- _map[ANEURALNETWORKS_NEG_EX] = _map[ANEURALNETWORKS_NEG];
-
_map[ANEURALNETWORKS_ABS] = getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::ABS);
- // ANEURALNETWORKS_ABS_EX is deprecated
- // TODO Remove ANEURALNETWORKS_ABS_EX
- _map[ANEURALNETWORKS_ABS_EX] = _map[ANEURALNETWORKS_ABS];
-
- _map[ANEURALNETWORKS_ARGMAX] = [](const OperationFactory::Param &init_param, Operands &operands) {
+ _map[ANEURALNETWORKS_ARGMAX] = [](const OperationFactory::Param &init_param, Operands &) {
assert(init_param.input_count == 2 && init_param.output_count == 1);
OperandIndexSequence outputs{init_param.outputs[0]};
@@ -1415,22 +1268,37 @@ OperationFactory::OperationFactory()
//
// 0 -> Input Tensor Index
// 1 -> Axis Tensor Index
- OperandIndexSequence inputs{init_param.inputs[0]};
+ OperandIndexSequence inputs{init_param.inputs[0], init_param.inputs[1]};
- operation::ArgMax::Param param;
- param.axis = operands.at(OperandIndex{init_param.inputs[1]}).asScalar<std::int32_t>();
+ operation::ArgMinMax::Param param;
// NNAPI ARGMAX output type is always int32
param.output_type = DataType::INT32;
+ param.is_arg_max = true;
- return new operation::ArgMax{inputs, outputs, param};
+ return new operation::ArgMinMax{inputs, outputs, param};
};
- // ANEURALNETWORKS_ARGMAX_EX is deprecated
- // TODO Remove ANEURALNETWORKS_ARGMAX_EX
- _map[ANEURALNETWORKS_ARGMAX_EX] = _map[ANEURALNETWORKS_ARGMAX];
+ _map[ANEURALNETWORKS_ARGMIN] = [](const OperationFactory::Param &init_param, Operands &) {
+ assert(init_param.input_count == 2 && init_param.output_count == 1);
+
+ OperandIndexSequence outputs{init_param.outputs[0]};
+
+ // Each input should be interpreted as follows:
+ //
+ // 0 -> Input Tensor Index
+ // 1 -> Axis Tensor Index
+ OperandIndexSequence inputs{init_param.inputs[0], init_param.inputs[1]};
+
+ operation::ArgMinMax::Param param;
+ // NNAPI ARGMIN output type is always int32
+ param.output_type = DataType::INT32;
+ param.is_arg_max = false;
+
+ return new operation::ArgMinMax{inputs, outputs, param};
+ };
_map[ANEURALNETWORKS_DEQUANTIZE] =
- getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::DEQUANTIZE);
+ getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::DEQUANTIZE);
_map[ANEURALNETWORKS_MEAN] = [](const OperationFactory::Param &init_param, Operands &operands) {
assert(init_param.input_count == 3 && init_param.output_count == 1);
@@ -1507,17 +1375,13 @@ OperationFactory::OperationFactory()
};
_map[ANEURALNETWORKS_REDUCE_MIN] =
- getReduceGenerator(onert::ir::operation::Reduce::ReduceType::MIN);
-
- // ANEURALNETWORKS_REDUCE_MIN_EX is deprecated
- // TODO Remove ANEURALNETWORKS_REDUCE_MIN_EX
- _map[ANEURALNETWORKS_REDUCE_MIN_EX] = _map[ANEURALNETWORKS_REDUCE_MIN];
+ getReduceGenerator(onert::ir::operation::Reduce::ReduceType::MIN);
_map[ANEURALNETWORKS_SPLIT] = [](const OperationFactory::Param &init_param, Operands &operands) {
assert(init_param.input_count == 3);
assert(init_param.output_count >= 1); // At least one output tensor and axis
- OperandIndexSequence inputs{init_param.inputs[0]};
+ OperandIndexSequence inputs{init_param.inputs[1], init_param.inputs[0]};
OperandIndexSequence outputs;
for (uint32_t n = 0; n < init_param.output_count; ++n)
{
@@ -1525,7 +1389,6 @@ OperationFactory::OperationFactory()
}
operation::Split::Param param;
- param.axis = operands.at(OperandIndex{init_param.inputs[1]}).asScalar<std::int32_t>();
param.num_splits = operands.at(OperandIndex{init_param.inputs[2]}).asScalar<std::int32_t>();
return new operation::Split{inputs, outputs, param};
@@ -1548,10 +1411,6 @@ OperationFactory::OperationFactory()
return new operation::SplitV{inputs, outputs, param};
};
- // ANEURALNETWORKS_SPLIT_EX is deprecated
- // TODO Remove ANEURALNETWORKS_SPLIT_EX
- _map[ANEURALNETWORKS_SPLIT_EX] = _map[ANEURALNETWORKS_SPLIT];
-
_map[ANEURALNETWORKS_UNPACK_EX] = [](const OperationFactory::Param &init_param,
Operands &operands) {
assert(init_param.input_count == 3 && init_param.output_count >= 1);
@@ -1589,10 +1448,10 @@ OperationFactory::OperationFactory()
_map[ANEURALNETWORKS_PAD_V2] = _map[ANEURALNETWORKS_PAD];
_map[ANEURALNETWORKS_MINIMUM] =
- getElementwiseBinaryGenerator(operation::ElementwiseBinary::ElementwiseBinaryType::MIN);
+ getElementwiseBinaryGenerator(operation::ElementwiseBinary::ElementwiseBinaryType::MIN);
_map[ANEURALNETWORKS_MAXIMUM] =
- getElementwiseBinaryGenerator(operation::ElementwiseBinary::ElementwiseBinaryType::MAX);
+ getElementwiseBinaryGenerator(operation::ElementwiseBinary::ElementwiseBinaryType::MAX);
_map[ANEURALNETWORKS_ONE_HOT_EX] = [](const OperationFactory::Param &init_param,
Operands &operands) {
@@ -1619,7 +1478,7 @@ OperationFactory::OperationFactory()
};
_map[ANEURALNETWORKS_COS_EX] =
- getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::COS);
+ getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::COS);
_map[ANEURALNETWORKS_SIN] = getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::SIN);
@@ -1633,10 +1492,10 @@ OperationFactory::OperationFactory()
};
_map[ANEURALNETWORKS_REDUCE_PROD] =
- getReduceGenerator(onert::ir::operation::Reduce::ReduceType::PROD);
+ getReduceGenerator(onert::ir::operation::Reduce::ReduceType::PROD);
_map[ANEURALNETWORKS_ROUND_EX] =
- getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::ROUND);
+ getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::ROUND);
_map[ANEURALNETWORKS_RANGE_EX] = [](const OperationFactory::Param &init_param, Operands &) {
assert(init_param.input_count == 3 && init_param.output_count == 1);
@@ -1664,7 +1523,7 @@ OperationFactory::OperationFactory()
_map[ANEURALNETWORKS_FILL_EX] = createSimpleBinaryOp<operation::Fill>;
_map[ANEURALNETWORKS_ZEROS_LIKE_EX] =
- getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::ZEROS_LIKE);
+ getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::ZEROS_LIKE);
// Each input should be interpreted as follows:
// 0 -> Input Tensor Index
// 1 -> Multiple Tensor Index
@@ -1804,7 +1663,7 @@ OperationFactory::OperationFactory()
};
_map[ANEURALNETWORKS_QUANTIZE] =
- getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::QUANTIZE);
+ getElementwiseUnaryGenerator(operation::ElementwiseUnary::Type::QUANTIZE);
}
Operation *OperationFactory::create(ANeuralNetworksOperationType type,
diff --git a/runtime/onert/frontend/nnapi/wrapper/OperationFactory.h b/runtime/onert/frontend/nnapi/wrapper/OperationFactory.h
index 367cf74db..74e187421 100644
--- a/runtime/onert/frontend/nnapi/wrapper/OperationFactory.h
+++ b/runtime/onert/frontend/nnapi/wrapper/OperationFactory.h
@@ -40,7 +40,7 @@ public:
public:
using Generator =
- std::function<onert::ir::Operation *(const OperationFactory::Param &, onert::ir::Operands &)>;
+ std::function<onert::ir::Operation *(const OperationFactory::Param &, onert::ir::Operands &)>;
public:
static OperationFactory &get();