blob: 05e604628e0120a96be0b994cc757d09ab5075b4 [file] [log] [blame]
telsoa015307bc12018-03-09 13:51:08 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beck93e48982018-09-05 13:05:09 +01003// SPDX-License-Identifier: MIT
telsoa015307bc12018-03-09 13:51:08 +00004//
5
6#define LOG_TAG "ArmnnDriver"
7
8#include "ModelToINetworkConverter.hpp"
telsoa015307bc12018-03-09 13:51:08 +00009
10#include <log/log.h>
telsoa01ce3e84a2018-08-31 09:31:35 +010011
surmeh0149b9e102018-05-17 14:11:25 +010012namespace armnn_driver
13{
kevmay01bc5f7842018-08-30 12:34:39 +010014
arovir01b0717b52018-09-05 17:03:25 +010015template<typename HalPolicy>
Nattapat Chaimanowongd5fd9762019-04-04 13:33:10 +010016ModelToINetworkConverter<HalPolicy>::ModelToINetworkConverter(const std::vector<armnn::BackendId>& backends,
kevmay01bc5f7842018-08-30 12:34:39 +010017 const HalModel& model,
telsoa015307bc12018-03-09 13:51:08 +000018 const std::set<unsigned int>& forcedUnsupportedOperations)
Nattapat Chaimanowongd5fd9762019-04-04 13:33:10 +010019 : m_Data(backends)
telsoa015307bc12018-03-09 13:51:08 +000020 , m_Model(model)
21 , m_ForcedUnsupportedOperations(forcedUnsupportedOperations)
telsoa015307bc12018-03-09 13:51:08 +000022 , m_ConversionResult(ConversionResult::Success)
23{
24 try
25 {
26 Convert();
27 }
Derek Lambertib9cb8442019-11-28 13:34:48 +000028 catch (std::exception& e)
telsoa015307bc12018-03-09 13:51:08 +000029 {
30 m_ConversionResult = ConversionResult::UnsupportedFeature;
31 ALOGE("%s: Unexpected exception: %s", __func__, e.what());
32 assert(false);
33 }
34}
35
arovir01b0717b52018-09-05 17:03:25 +010036template<typename HalPolicy>
37void ModelToINetworkConverter<HalPolicy>::Convert()
telsoa015307bc12018-03-09 13:51:08 +000038{
Sadik Armagan44bcc022019-06-18 17:21:36 +010039 using HalModel = typename HalPolicy::Model;
40 using HalOperand = typename HalPolicy::Operand;
41 using HalOperandType = typename HalPolicy::OperandType;
Matteo Martincighe48bdff2018-09-03 13:50:50 +010042
arovir01a15dc112018-09-03 17:12:56 +010043 ALOGV("ModelToINetworkConverter::Convert(): %s", GetModelSummary<HalModel>(m_Model).c_str());
telsoa015307bc12018-03-09 13:51:08 +000044
45 // map the memory pool into shared pointers
arovir01b0717b52018-09-05 17:03:25 +010046 m_Data.m_MemPools.clear();
47 if (!setRunTimePoolInfosFromHidlMemories(&m_Data.m_MemPools, m_Model.pools))
telsoa015307bc12018-03-09 13:51:08 +000048 {
49 Fail("%s: Setting of run time pool infos from Hidl Memories has failed.", __func__);
50 m_ConversionResult = ConversionResult::ErrorMappingPools;
51 return;
52 }
53
54 uint32_t totalPoolSize = 0;
55 for (auto&& pool : m_Model.pools)
56 {
57 totalPoolSize += pool.size();
58 }
59
60 // Create armnn::INetwork
arovir01b0717b52018-09-05 17:03:25 +010061 m_Data.m_Network = armnn::INetwork::Create();
telsoa015307bc12018-03-09 13:51:08 +000062
63 // add operations to it
64 // track which layer outputs each operand
arovir01b0717b52018-09-05 17:03:25 +010065 m_Data.m_OutputSlotForOperand = std::vector<armnn::IOutputSlot*>(m_Model.operands.size(), nullptr);
telsoa015307bc12018-03-09 13:51:08 +000066
67 try
68 {
69 for (uint32_t i = 0; i < m_Model.inputIndexes.size(); i++)
70 {
71 // inputs in android nn are represented by operands
72 uint32_t inputIndex = m_Model.inputIndexes[i];
Sadik Armagan44bcc022019-06-18 17:21:36 +010073 const HalOperand& operand = m_Model.operands[inputIndex];
telsoa015307bc12018-03-09 13:51:08 +000074 const armnn::TensorInfo& tensor = GetTensorInfoForOperand(operand);
arovir01b0717b52018-09-05 17:03:25 +010075 armnn::IConnectableLayer* layer = m_Data.m_Network->AddInputLayer(i);
telsoa015307bc12018-03-09 13:51:08 +000076
77 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
78 outputSlot.SetTensorInfo(GetTensorInfoForOperand(operand));
79
80 // store for later layers
arovir01b0717b52018-09-05 17:03:25 +010081 m_Data.m_OutputSlotForOperand[inputIndex] = &outputSlot;
telsoa015307bc12018-03-09 13:51:08 +000082 }
83 }
Sadik Armagan44bcc022019-06-18 17:21:36 +010084 catch (UnsupportedOperand<HalOperandType>& e)
telsoa015307bc12018-03-09 13:51:08 +000085 {
86 Fail("%s: Operand type %s not supported in ArmnnDriver", __func__, toString(e.m_type).c_str());
87 m_ConversionResult = ConversionResult::UnsupportedFeature;
88 }
89 catch (const armnn::InvalidArgumentException& e)
90 {
91 Fail("%s: Failed to convert input operand to TensorShape: %s", __func__, e.what());
92 m_ConversionResult = ConversionResult::UnsupportedFeature;
93 }
94
95 for (uint32_t operationIdx = 0; operationIdx < m_Model.operations.size(); operationIdx++)
96 {
97 const auto& operation = m_Model.operations[operationIdx];
98
99 bool ok = true;
100 if (m_ForcedUnsupportedOperations.find(operationIdx) != m_ForcedUnsupportedOperations.end())
101 {
102 Fail("%s: Operation at index %i has been forced to be unsupported.", __func__, operationIdx);
103 ok = false;
104 }
105
106 if (ok)
107 {
108 try
109 {
arovir01b0717b52018-09-05 17:03:25 +0100110 ok = HalPolicy::ConvertOperation(operation, m_Model, m_Data);
telsoa015307bc12018-03-09 13:51:08 +0000111 }
Sadik Armagan44bcc022019-06-18 17:21:36 +0100112 catch (UnsupportedOperand<HalOperandType>& e)
telsoa015307bc12018-03-09 13:51:08 +0000113 {
114 Fail("%s: Operand type %s not supported in ArmnnDriver", __func__, toString(e.m_type).c_str());
115 ok = false;
116 }
117 catch (const armnn::InvalidArgumentException& e)
118 {
119 Fail("%s: Failed to convert operation in %s", __func__, e.what());
120 ok = false;
121 }
122 }
123
124 // Store whether this operation was successfully converted.
125 m_OperationSupported.emplace(operationIdx, ok);
126
127 // Any single operation failing will fail the entire conversion.
128 // We still need to continue and check the other ones.
129 if (!ok)
130 {
131 m_ConversionResult = ConversionResult::UnsupportedFeature;
132 }
133 }
134 try
135 {
136 if (m_ConversionResult == ConversionResult::Success)
137 {
138 for (uint32_t i = 0; i < m_Model.outputIndexes.size(); i++)
139 {
140 // outputs in android nn are represented by operands
141 uint32_t outputIndex = m_Model.outputIndexes[i];
Sadik Armagan44bcc022019-06-18 17:21:36 +0100142 const HalOperand& operand = m_Model.operands[outputIndex];
telsoa015307bc12018-03-09 13:51:08 +0000143 const armnn::TensorInfo& tensor = GetTensorInfoForOperand(operand);
arovir01b0717b52018-09-05 17:03:25 +0100144 armnn::IConnectableLayer* layer = m_Data.m_Network->AddOutputLayer(i);
telsoa015307bc12018-03-09 13:51:08 +0000145
arovir01b0717b52018-09-05 17:03:25 +0100146 assert(m_Data.m_OutputSlotForOperand[outputIndex]);
147 m_Data.m_OutputSlotForOperand[outputIndex]->Connect(layer->GetInputSlot(0));
telsoa015307bc12018-03-09 13:51:08 +0000148 }
149 }
150 }
151 catch (const armnn::InvalidArgumentException& e)
152 {
153 Fail("%s: Failed to convert output operand to TensorShape: %s", __func__, e.what());
154 m_ConversionResult = ConversionResult::UnsupportedFeature;
155 }
156}
157
arovir01b0717b52018-09-05 17:03:25 +0100158template<typename HalPolicy>
159bool ModelToINetworkConverter<HalPolicy>::IsOperationSupported(uint32_t operationIndex) const
telsoa015307bc12018-03-09 13:51:08 +0000160{
161 std::map<uint32_t, bool>::const_iterator it = m_OperationSupported.find(operationIndex);
162 assert(it != m_OperationSupported.end());
163 return it->second;
164}
165
arovir01b0717b52018-09-05 17:03:25 +0100166///
167/// Class template specializations
168///
telsoa015307bc12018-03-09 13:51:08 +0000169
arovir01b0717b52018-09-05 17:03:25 +0100170template class ModelToINetworkConverter<hal_1_0::HalPolicy>;
171
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100172#ifdef ARMNN_ANDROID_NN_V1_1
arovir01b0717b52018-09-05 17:03:25 +0100173template class ModelToINetworkConverter<hal_1_1::HalPolicy>;
kevmay01bc5f7842018-08-30 12:34:39 +0100174#endif
175
Mike Kellyb5fdf382019-06-11 16:35:25 +0100176#ifdef ARMNN_ANDROID_NN_V1_2
177template class ModelToINetworkConverter<hal_1_1::HalPolicy>;
178template class ModelToINetworkConverter<hal_1_2::HalPolicy>;
179#endif
180
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100181} // armnn_driver