blob: a94f30581326246c9aad62210bb77f3399e6f057 [file] [log] [blame]
arovir01b0717b52018-09-05 17:03:25 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "HalPolicy.hpp"
7
8#include "../1.0/HalPolicy.hpp"
9
10namespace armnn_driver
11{
12namespace hal_1_1
13{
14
15bool HalPolicy::ConvertOperation(const Operation& operation, const Model& model, ConversionData& data)
16{
17 if (compliantWithV1_0(operation))
18 {
19 hal_1_0::HalPolicy::Operation v10Operation = convertToV1_0(operation);
20 hal_1_0::HalPolicy::Model v10Model = convertToV1_0(model);
21
22 return hal_1_0::HalPolicy::ConvertOperation(v10Operation, v10Model, data);
23 }
24 else
25 {
26 switch (operation.type)
27 {
28 case V1_1::OperationType::DIV:
29 return ConvertDiv(operation, model, data);
David Beck38e12942018-09-12 16:02:24 +010030 case V1_1::OperationType::SUB:
31 return ConvertSub(operation, model, data);
narpra013c052562018-09-17 14:25:04 +010032 case V1_1::OperationType::MEAN:
33 return ConvertMean(operation, model, data);
Nina Drozd62a4a9f2018-10-01 14:20:25 +010034 case V1_1::OperationType::PAD:
35 return ConvertPad(operation, model, data);
arovir01b0717b52018-09-05 17:03:25 +010036 default:
37 return Fail("%s: Operation type %s not supported in ArmnnDriver",
38 __func__, toString(operation.type).c_str());
39 }
40 }
41}
42
43bool HalPolicy::ConvertDiv(const Operation& operation, const Model& model, ConversionData& data)
44{
45 LayerInputHandle input0 = ConvertToLayerInputHandle(operation, 0, model, data);
46 LayerInputHandle input1 = ConvertToLayerInputHandle(operation, 1, model, data);
47
48 if (!input0.IsValid() || !input1.IsValid())
49 {
50 return Fail("%s: Operation has invalid inputs", __func__);
51 }
52
53 // The FuseActivation parameter is always the input index 2
54 // and it should be optional
55 ActivationFn activationFunction;
56 if (!GetOptionalInputActivation(operation, 2, activationFunction, model, data))
57 {
58 return Fail("%s: Operation has invalid inputs", __func__);
59 }
60
61 const Operand* outputOperand = GetOutputOperand(operation, 0, model);
62 if (!outputOperand)
63 {
64 return false;
65 }
66
67 const armnn::TensorInfo& outInfo = GetTensorInfoForOperand(*outputOperand);
68
69 if (!IsLayerSupported(__func__,
70 armnn::IsDivisionSupported,
71 data.m_Compute,
72 input0.GetTensorInfo(),
73 input1.GetTensorInfo(),
74 outInfo))
75 {
76 return false;
77 }
78
79 armnn::IConnectableLayer* const startLayer = data.m_Network->AddDivisionLayer();
80 armnn::IConnectableLayer* const endLayer = ProcessActivation(outInfo, activationFunction, startLayer, data);
81
82 const armnn::TensorInfo& inputTensorInfo0 = input0.GetTensorInfo();
83 const armnn::TensorInfo& inputTensorInfo1 = input1.GetTensorInfo();
84
85 if (endLayer)
86 {
87 BroadcastTensor(input0, input1, startLayer, *data.m_Network);
88 return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data);
89 }
90
91 return Fail("%s: ProcessActivation failed", __func__);
92}
93
David Beck38e12942018-09-12 16:02:24 +010094bool HalPolicy::ConvertSub(const Operation& operation, const Model& model, ConversionData& data)
95{
96 LayerInputHandle input0 = ConvertToLayerInputHandle(operation, 0, model, data);
97 LayerInputHandle input1 = ConvertToLayerInputHandle(operation, 1, model, data);
98
99 if (!input0.IsValid() || !input1.IsValid())
100 {
101 return Fail("%s: Operation has invalid inputs", __func__);
102 }
103
104 // The FuseActivation parameter is always the input index 2
105 // and it should be optional
106 ActivationFn activationFunction;
107 if (!GetOptionalInputActivation(operation, 2, activationFunction, model, data))
108 {
109 return Fail("%s: Operation has invalid inputs", __func__);
110 }
111
112 const Operand* outputOperand = GetOutputOperand(operation, 0, model);
113 if (!outputOperand)
114 {
115 return false;
116 }
117
118 const armnn::TensorInfo& outInfo = GetTensorInfoForOperand(*outputOperand);
119
120 if (!IsLayerSupported(__func__,
121 armnn::IsSubtractionSupported,
122 data.m_Compute,
123 input0.GetTensorInfo(),
124 input1.GetTensorInfo(),
125 outInfo))
126 {
127 return false;
128 }
129
130 armnn::IConnectableLayer* const startLayer = data.m_Network->AddSubtractionLayer();
131 armnn::IConnectableLayer* const endLayer = ProcessActivation(outInfo, activationFunction, startLayer, data);
132
133 const armnn::TensorInfo& inputTensorInfo0 = input0.GetTensorInfo();
134 const armnn::TensorInfo& inputTensorInfo1 = input1.GetTensorInfo();
135
136 if (endLayer)
137 {
138 BroadcastTensor(input0, input1, startLayer, *data.m_Network);
139 return SetupAndTrackLayerOutputSlot(operation, 0, *endLayer, model, data);
140 }
141
142 return Fail("%s: ProcessActivation failed", __func__);
143}
144
narpra013c052562018-09-17 14:25:04 +0100145bool HalPolicy::ConvertMean(const Operation& operation, const Model& model, ConversionData& data)
146{
147 LayerInputHandle input = ConvertToLayerInputHandle(operation, 0, model, data);
148
149 if (!input.IsValid())
150 {
151 return Fail("%s: Operation has invalid inputs", __func__);
152 }
153
154 const armnn::TensorInfo& inputInfo = input.GetTensorInfo();
155
156 armnn::MeanDescriptor descriptor;
157
158 const Operand* axisOperand = GetInputOperand(operation, 1, model);
159 if (axisOperand)
160 {
161 std::vector<int32_t> axis;
162 GetTensorInt32Values(*axisOperand, axis, model, data);
163 unsigned int rank = inputInfo.GetNumDimensions();
164 // convert the axis to unsigned int.
165 for (auto& i : axis)
166 {
167 unsigned int unsignedAxis = (i + rank) % rank;
168 if (std::find(descriptor.m_Axis.begin(), descriptor.m_Axis.end(), unsignedAxis) == descriptor.m_Axis.end())
169 {
170 descriptor.m_Axis.push_back(unsignedAxis);
171 }
172 }
173 }
174
175 int32_t keepDims;
176 GetInputInt32(operation, 2, keepDims, model, data);
177 if (keepDims > 0)
178 {
179 descriptor.m_KeepDims = true;
180 }
181
182 const Operand* output = GetOutputOperand(operation, 0, model);
183 if (!output)
184 {
185 return Fail("%s: Could not read output 0", __func__);
186 }
187
188 const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output);
189
190 if (!IsLayerSupported(__func__,
191 armnn::IsMeanSupported,
192 data.m_Compute,
193 inputInfo,
194 outputInfo,
195 descriptor))
196 {
197 return false;
198 }
199
200 armnn::IConnectableLayer* const layer = data.m_Network->AddMeanLayer(descriptor);
narpra0196bedf02018-09-26 16:57:28 +0100201 assert(layer != nullptr);
202 input.Connect(layer->GetInputSlot(0));
203 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
narpra013c052562018-09-17 14:25:04 +0100204
205 return SetupAndTrackLayerOutputSlot(operation, 0, *layer, model, data);
206}
207
Nina Drozd62a4a9f2018-10-01 14:20:25 +0100208bool HalPolicy::ConvertPad(const Operation& operation, const Model& model, ConversionData& data)
209{
210 LayerInputHandle input = ConvertToLayerInputHandle(operation, 0, model, data);
211
212 if (!input.IsValid())
213 {
214 return Fail("%s: Operation has invalid inputs", __func__);
215 }
216
217 const armnn::TensorInfo& inputInfo = input.GetTensorInfo();
218
219 const Operand* paddingsOperand = GetInputOperand(operation, 1, model);
220
221 if (!paddingsOperand)
222 {
223 return Fail("%s: Could not read paddings operand", __func__);
224 }
225
226 unsigned int rank = inputInfo.GetNumDimensions();
227 armnn::TensorShape paddingsOperandShape = GetTensorShapeForOperand(*paddingsOperand);
228 if (paddingsOperandShape.GetNumDimensions() != rank || paddingsOperandShape.GetNumElements() != 2)
229 {
230 return Fail("%s: Operation has invalid paddings operand: expected shape [%d, 2]", __func__, rank);
231 }
232
233 std::vector<int32_t> paddings;
234 GetTensorInt32Values(*paddingsOperand, paddings, model, data);
235
236 // add padding for each dimension of input tensor.
237 armnn::PadDescriptor descriptor;
238 for (unsigned int i = 0; i < paddings.size() - 1; i += 2)
239 {
240 int paddingBeforeInput = paddings[i];
241 int paddingAfterInput = paddings[i + 1];
242 if (paddingBeforeInput < 0 || paddingAfterInput < 0)
243 {
244 return Fail("%s: Operation has invalid paddings operand, invalid padding values.", __func__);
245 }
246 descriptor.m_PadList.emplace_back((unsigned int) paddingBeforeInput, (unsigned int) paddingAfterInput);
247 }
248
249 const Operand* output = GetOutputOperand(operation, 0, model);
250 if (!output)
251 {
252 return Fail("%s: Could not read output 0", __func__);
253 }
254
255 const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output);
256
257 if (!IsLayerSupported(__func__,
258 armnn::IsPadSupported,
259 data.m_Compute,
260 inputInfo,
261 outputInfo,
262 descriptor))
263 {
264 return false;
265 }
266
267 armnn::IConnectableLayer* const layer = data.m_Network->AddPadLayer(descriptor);
268 assert(layer != nullptr);
269 input.Connect(layer->GetInputSlot(0));
270 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
271
272 return SetupAndTrackLayerOutputSlot(operation, 0, *layer, model, data);
273}
274
arovir01b0717b52018-09-05 17:03:25 +0100275} // namespace hal_1_1
276} // namespace armnn_driver