blob: 8bf84e940336274d031ff4739f4df3e6f1ad1114 [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>
16ModelToINetworkConverter<HalPolicy>::ModelToINetworkConverter(armnn::Compute compute,
kevmay01bc5f7842018-08-30 12:34:39 +010017 const HalModel& model,
telsoa015307bc12018-03-09 13:51:08 +000018 const std::set<unsigned int>& forcedUnsupportedOperations)
arovir01b0717b52018-09-05 17:03:25 +010019 : m_Data(compute)
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 }
28 catch (armnn::Exception& e)
29 {
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{
arovir01b0717b52018-09-05 17:03:25 +010039 using HalModel = typename HalPolicy::Model;
Matteo Martincighe48bdff2018-09-03 13:50:50 +010040
arovir01a15dc112018-09-03 17:12:56 +010041 ALOGV("ModelToINetworkConverter::Convert(): %s", GetModelSummary<HalModel>(m_Model).c_str());
telsoa015307bc12018-03-09 13:51:08 +000042
43 // map the memory pool into shared pointers
arovir01b0717b52018-09-05 17:03:25 +010044 m_Data.m_MemPools.clear();
45 if (!setRunTimePoolInfosFromHidlMemories(&m_Data.m_MemPools, m_Model.pools))
telsoa015307bc12018-03-09 13:51:08 +000046 {
47 Fail("%s: Setting of run time pool infos from Hidl Memories has failed.", __func__);
48 m_ConversionResult = ConversionResult::ErrorMappingPools;
49 return;
50 }
51
52 uint32_t totalPoolSize = 0;
53 for (auto&& pool : m_Model.pools)
54 {
55 totalPoolSize += pool.size();
56 }
57
58 // Create armnn::INetwork
arovir01b0717b52018-09-05 17:03:25 +010059 m_Data.m_Network = armnn::INetwork::Create();
telsoa015307bc12018-03-09 13:51:08 +000060
61 // add operations to it
62 // track which layer outputs each operand
arovir01b0717b52018-09-05 17:03:25 +010063 m_Data.m_OutputSlotForOperand = std::vector<armnn::IOutputSlot*>(m_Model.operands.size(), nullptr);
telsoa015307bc12018-03-09 13:51:08 +000064
65 try
66 {
67 for (uint32_t i = 0; i < m_Model.inputIndexes.size(); i++)
68 {
69 // inputs in android nn are represented by operands
70 uint32_t inputIndex = m_Model.inputIndexes[i];
71 const Operand& operand = m_Model.operands[inputIndex];
72 const armnn::TensorInfo& tensor = GetTensorInfoForOperand(operand);
arovir01b0717b52018-09-05 17:03:25 +010073 armnn::IConnectableLayer* layer = m_Data.m_Network->AddInputLayer(i);
telsoa015307bc12018-03-09 13:51:08 +000074
75 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
76 outputSlot.SetTensorInfo(GetTensorInfoForOperand(operand));
77
78 // store for later layers
arovir01b0717b52018-09-05 17:03:25 +010079 m_Data.m_OutputSlotForOperand[inputIndex] = &outputSlot;
telsoa015307bc12018-03-09 13:51:08 +000080 }
81 }
82 catch (UnsupportedOperand& e)
83 {
84 Fail("%s: Operand type %s not supported in ArmnnDriver", __func__, toString(e.m_type).c_str());
85 m_ConversionResult = ConversionResult::UnsupportedFeature;
86 }
87 catch (const armnn::InvalidArgumentException& e)
88 {
89 Fail("%s: Failed to convert input operand to TensorShape: %s", __func__, e.what());
90 m_ConversionResult = ConversionResult::UnsupportedFeature;
91 }
92
93 for (uint32_t operationIdx = 0; operationIdx < m_Model.operations.size(); operationIdx++)
94 {
95 const auto& operation = m_Model.operations[operationIdx];
96
97 bool ok = true;
98 if (m_ForcedUnsupportedOperations.find(operationIdx) != m_ForcedUnsupportedOperations.end())
99 {
100 Fail("%s: Operation at index %i has been forced to be unsupported.", __func__, operationIdx);
101 ok = false;
102 }
103
104 if (ok)
105 {
106 try
107 {
arovir01b0717b52018-09-05 17:03:25 +0100108 ok = HalPolicy::ConvertOperation(operation, m_Model, m_Data);
telsoa015307bc12018-03-09 13:51:08 +0000109 }
110 catch (UnsupportedOperand& e)
111 {
112 Fail("%s: Operand type %s not supported in ArmnnDriver", __func__, toString(e.m_type).c_str());
113 ok = false;
114 }
115 catch (const armnn::InvalidArgumentException& e)
116 {
117 Fail("%s: Failed to convert operation in %s", __func__, e.what());
118 ok = false;
119 }
120 }
121
122 // Store whether this operation was successfully converted.
123 m_OperationSupported.emplace(operationIdx, ok);
124
125 // Any single operation failing will fail the entire conversion.
126 // We still need to continue and check the other ones.
127 if (!ok)
128 {
129 m_ConversionResult = ConversionResult::UnsupportedFeature;
130 }
131 }
132 try
133 {
134 if (m_ConversionResult == ConversionResult::Success)
135 {
136 for (uint32_t i = 0; i < m_Model.outputIndexes.size(); i++)
137 {
138 // outputs in android nn are represented by operands
139 uint32_t outputIndex = m_Model.outputIndexes[i];
140 const Operand& operand = m_Model.operands[outputIndex];
141 const armnn::TensorInfo& tensor = GetTensorInfoForOperand(operand);
arovir01b0717b52018-09-05 17:03:25 +0100142 armnn::IConnectableLayer* layer = m_Data.m_Network->AddOutputLayer(i);
telsoa015307bc12018-03-09 13:51:08 +0000143
arovir01b0717b52018-09-05 17:03:25 +0100144 assert(m_Data.m_OutputSlotForOperand[outputIndex]);
145 m_Data.m_OutputSlotForOperand[outputIndex]->Connect(layer->GetInputSlot(0));
telsoa015307bc12018-03-09 13:51:08 +0000146 }
147 }
148 }
149 catch (const armnn::InvalidArgumentException& e)
150 {
151 Fail("%s: Failed to convert output operand to TensorShape: %s", __func__, e.what());
152 m_ConversionResult = ConversionResult::UnsupportedFeature;
153 }
154}
155
arovir01b0717b52018-09-05 17:03:25 +0100156template<typename HalPolicy>
157bool ModelToINetworkConverter<HalPolicy>::IsOperationSupported(uint32_t operationIndex) const
telsoa015307bc12018-03-09 13:51:08 +0000158{
159 std::map<uint32_t, bool>::const_iterator it = m_OperationSupported.find(operationIndex);
160 assert(it != m_OperationSupported.end());
161 return it->second;
162}
163
arovir01b0717b52018-09-05 17:03:25 +0100164///
165/// Class template specializations
166///
telsoa015307bc12018-03-09 13:51:08 +0000167
arovir01b0717b52018-09-05 17:03:25 +0100168template class ModelToINetworkConverter<hal_1_0::HalPolicy>;
169
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100170#ifdef ARMNN_ANDROID_NN_V1_1
arovir01b0717b52018-09-05 17:03:25 +0100171template class ModelToINetworkConverter<hal_1_1::HalPolicy>;
kevmay01bc5f7842018-08-30 12:34:39 +0100172#endif
173
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100174} // armnn_driver