ArmNN
 23.05
ConversionUtils.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #pragma once
7 
8 #include "CanonicalUtils.hpp"
9 
10 #include <armnn/ArmNN.hpp>
11 #include <armnn/BackendHelper.hpp>
12 #include <armnn/utility/Assert.hpp>
15 
17 #include <armnnUtils/Transpose.hpp>
18 
19 #include <ActivationFunctor.h>
20 #include <CpuExecutor.h>
21 #include <OperationsUtils.h>
22 
24 
25 #include <log/log.h>
26 #include <vector>
27 
28 inline const android::nn::Model::Subgraph& getMainModel(const android::nn::Model& model) { return model.main; }
29 
30 namespace armnn_driver
31 {
32 
33 ///
34 /// Helper classes
35 ///
36 
37 #include <nnapi/OperandTypes.h>
38 #include <nnapi/Result.h>
39 #include <nnapi/TypeUtils.h>
40 #include <nnapi/Types.h>
41 #include <nnapi/Validation.h>
42 
45 using OperandLifeTime = ::android::nn::Operand::LifeTime;
50 
52 {
53  ConversionData(const std::vector<armnn::BackendId>& backends)
54  : m_Backends(backends)
55  , m_Network(nullptr, nullptr)
57  {}
58 
59  const std::vector<armnn::BackendId> m_Backends;
61  std::vector<armnn::IOutputSlot*> m_OutputSlotForOperand;
62  std::vector<::android::nn::RunTimePoolInfo> m_MemPools;
64 };
65 
67 {
68 public:
70  LayerInputHandle(bool valid, armnn::IOutputSlot* outputSlot, armnn::TensorInfo tensorInfo);
71 
72  bool IsValid() const;
73 
74  void Connect(armnn::IInputSlot& inputSlot);
75 
76  void Disconnect(armnn::IInputSlot& inputSlot);
77 
78  const armnn::TensorInfo& GetTensorInfo() const;
79 
81 
83 
84 private:
85  armnn::IOutputSlot* m_OutputSlot;
86  bool m_Valid;
87  armnn::TensorInfo m_TensorInfo;
88 };
89 
91 {
92 public:
93  // Creates an invalid tensor pin (can be used to signal errors)
94  // The optional flag can be set to indicate the tensor values were missing, but it was otherwise valid
95  ConstTensorPin(bool optional = false);
96 
97  // @param tensorInfo TensorInfo associated with the tensor.
98  // @param valueStart Start address of tensor data. Belongs to one of the memory pools associated with
99  // the model being converted.
100  // @param numBytes Number of bytes for the tensor data.
101  ConstTensorPin(armnn::TensorInfo& tensorInfo, const void* valueStart, uint32_t numBytes,
102  const armnn::PermutationVector& mappings);
103 
104  ConstTensorPin(const ConstTensorPin& other) = delete;
105  ConstTensorPin(ConstTensorPin&& other) = default;
106 
107  bool IsValid() const;
108  bool IsOptional() const;
109 
110  const armnn::ConstTensor& GetConstTensor() const;
111  const armnn::ConstTensor* GetConstTensorPtr() const;
112 
113 private:
114  armnn::ConstTensor m_ConstTensor;
115 
116  // Owned memory for swizzled tensor data, only required if the tensor needed
117  // swizzling. Otherwise, @ref m_ConstTensor will reference memory from one of
118  // the pools associated with the model being converted.
119  std::vector<uint8_t> m_SwizzledTensorData;
120 
121  // optional flag to indicate that an invalid tensor pin is not an error, but the optional values were not given
122  bool m_Optional;
123 };
124 
126 {
127  Success,
130 };
131 
132 } // namespace armnn_driver
133 
134 ///
135 /// Utility functions
136 ///
137 
138 namespace
139 {
140 using namespace armnn_driver;
141 
142 // Convenience function to log the reason for failing to convert a model.
143 // @return Always returns false (so that it can be used by callers as a quick way to signal an error and return)
144 template<class... Args>
145 static bool Fail(const char* formatStr, Args&&... args)
146 {
147  ALOGD(formatStr, std::forward<Args>(args)...);
148  return false;
149 }
150 
151 // Convenience macro to call an Is*Supported function and log caller name together with reason for lack of support.
152 // Called as: FORWARD_LAYER_SUPPORT_FUNC(__func__, Is*Supported, backends, a, b, c, d, e)
153 #define FORWARD_LAYER_SUPPORT_FUNC(funcName, func, backends, supported, setBackend, ...) \
154 try \
155 { \
156  for (auto&& backendId : backends) \
157  { \
158  auto layerSupportObject = armnn::GetILayerSupportByBackendId(backendId); \
159  if (layerSupportObject.IsBackendRegistered()) \
160  { \
161  std::string reasonIfUnsupported; \
162  supported = \
163  layerSupportObject.func(__VA_ARGS__, armnn::Optional<std::string&>(reasonIfUnsupported)); \
164  if (supported) \
165  { \
166  setBackend = backendId; \
167  break; \
168  } \
169  else \
170  { \
171  if (reasonIfUnsupported.size() > 0) \
172  { \
173  VLOG(DRIVER) << funcName << ": not supported by armnn: " << reasonIfUnsupported.c_str(); \
174  } \
175  else \
176  { \
177  VLOG(DRIVER) << funcName << ": not supported by armnn"; \
178  } \
179  } \
180  } \
181  else \
182  { \
183  VLOG(DRIVER) << funcName << ": backend not registered: " << backendId.Get().c_str(); \
184  } \
185  } \
186  if (!supported) \
187  { \
188  VLOG(DRIVER) << funcName << ": not supported by any specified backend"; \
189  } \
190 } \
191 catch (const armnn::InvalidArgumentException &e) \
192 { \
193  throw armnn::InvalidArgumentException(e, "Failed to check layer support", CHECK_LOCATION()); \
194 }
195 
196 inline armnn::TensorShape GetTensorShapeForOperand(const Operand& operand)
197 {
198  return armnn::TensorShape(operand.dimensions.size(), operand.dimensions.data());
199 }
200 
201 // Support within the 1.3 driver for specific tensor data types
202 inline bool IsOperandTypeSupportedForTensors(OperandType type)
203 {
204  return type == OperandType::BOOL ||
205  type == OperandType::TENSOR_BOOL8 ||
206  type == OperandType::TENSOR_FLOAT16 ||
207  type == OperandType::TENSOR_FLOAT32 ||
208  type == OperandType::TENSOR_QUANT8_ASYMM ||
209  type == OperandType::TENSOR_QUANT8_ASYMM_SIGNED ||
210  type == OperandType::TENSOR_QUANT8_SYMM ||
211  type == OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL ||
212  type == OperandType::TENSOR_QUANT16_SYMM ||
213  type == OperandType::TENSOR_INT32;
214 }
215 
216 inline bool IsBool(Operand operand)
217 {
218  return operand.type == OperandType::BOOL;
219 }
220 
221 inline bool Is12OrLaterOperand(Operand)
222 {
223  return true;
224 }
225 
226 
227 template<typename LayerHandleType>
228 armnn::IConnectableLayer& AddReshapeLayer(armnn::INetwork& network,
229  LayerHandleType& inputLayer,
230  armnn::TensorInfo reshapeInfo)
231 {
232  armnn::ReshapeDescriptor reshapeDescriptor;
233  reshapeDescriptor.m_TargetShape = reshapeInfo.GetShape();
234 
235  armnn::IConnectableLayer* reshapeLayer = network.AddReshapeLayer(reshapeDescriptor);
236  ARMNN_ASSERT(reshapeLayer != nullptr);
237 
238  // Attach the input layer to the reshape layer
239  inputLayer.Connect(reshapeLayer->GetInputSlot(0));
240  reshapeLayer->GetOutputSlot(0).SetTensorInfo(reshapeInfo);
241 
242  return *reshapeLayer;
243 }
244 
245 
246  armnn::TensorShape FlattenFullyConnectedInput(const armnn::TensorShape& inputShape,
247  const armnn::TensorShape& weightsShape)
248 {
249  if (inputShape.GetNumDimensions() > 2U)
250  {
251  unsigned int totalInputElements = inputShape.GetNumElements();
252  unsigned int inputSize = weightsShape[1];
253 
254  unsigned int batchSize = totalInputElements / inputSize;
255 
256  if(totalInputElements % batchSize != 0)
257  {
258  throw std::runtime_error("Failed to deduce tensor shape");
259  }
260 
261  return armnn::TensorShape({batchSize, inputSize});
262  }
263  else
264  {
265  return inputShape;
266  }
267 }
268 
269 inline bool VerifyFullyConnectedShapes(const armnn::TensorShape& inputShape,
270  const armnn::TensorShape& weightsShape,
271  const armnn::TensorShape& outputShape,
272  bool transposeWeightMatrix)
273 {
274  unsigned int dimIdx = transposeWeightMatrix ? 0 : 1;
275  return (inputShape[0] == outputShape[0] && weightsShape[dimIdx] == outputShape[1]);
276 }
277 
278 bool BroadcastTensor(LayerInputHandle& input0,
279  LayerInputHandle& input1,
280  armnn::IConnectableLayer* startLayer,
281  ConversionData& data)
282 {
283  ARMNN_ASSERT(startLayer != nullptr);
284 
285  const armnn::TensorInfo& inputInfo0 = input0.GetTensorInfo();
286  const armnn::TensorInfo& inputInfo1 = input1.GetTensorInfo();
287 
288  unsigned int inputDimensions0 = inputInfo0.GetNumDimensions();
289  unsigned int inputDimensions1 = inputInfo1.GetNumDimensions();
290 
291  if (inputDimensions0 == inputDimensions1)
292  {
293  // The inputs have the same number of dimensions, simply connect them to the given layer as they are
294  input0.Connect(startLayer->GetInputSlot(0));
295  input1.Connect(startLayer->GetInputSlot(1));
296 
297  return true;
298  }
299 
300  // Since the number of dimensions do not match then we need to add degenerate dimensions
301  // to the "smaller" tensor using a reshape, while keeping the order of the inputs.
302 
303  unsigned int maxInputDimensions = std::max(inputDimensions0, inputDimensions1);
304  unsigned int sizeDifference = std::abs(armnn::numeric_cast<int>(inputDimensions0) -
305  armnn::numeric_cast<int>(inputDimensions1));
306 
307  bool input0IsSmaller = inputDimensions0 < inputDimensions1;
308  LayerInputHandle& smallInputHandle = input0IsSmaller ? input0 : input1;
309  const armnn::TensorInfo& smallInfo = smallInputHandle.GetTensorInfo();
310 
311  const armnn::TensorShape& smallShape = smallInfo.GetShape();
312  std::vector<unsigned int> reshapedDimensions(maxInputDimensions, 1);
313  for (unsigned int i = sizeDifference; i < maxInputDimensions; i++)
314  {
315  reshapedDimensions[i] = smallShape[i - sizeDifference];
316  }
317 
318  armnn::TensorInfo reshapedInfo = smallInfo;
319  reshapedInfo.SetShape(armnn::TensorShape{ armnn::numeric_cast<unsigned int>(reshapedDimensions.size()),
320  reshapedDimensions.data() });
321 
322  // RehsapeDescriptor that is ignored in the IsReshapeSupported function
323  armnn::ReshapeDescriptor reshapeDescriptor;
324 
325  bool isSupported = false;
326  armnn::BackendId setBackend;
329  data.m_Backends,
330  isSupported,
331  setBackend,
332  smallInfo,
333  reshapedInfo,
334  reshapeDescriptor);
335  if (!isSupported)
336  {
337  return false;
338  }
339 
340  ARMNN_ASSERT(data.m_Network != nullptr);
341  armnn::IConnectableLayer& reshapeLayer = AddReshapeLayer(*data.m_Network, smallInputHandle, reshapedInfo);
342  reshapeLayer.SetBackendId(setBackend);
343 
344  if (input0IsSmaller)
345  {
346  // Input0 is the "smaller" tensor, connect the reshape layer as follows:
347  //
348  // Input0 Input1
349  // | |
350  // Reshape |
351  // \ /
352  // StartLayer
353 
354  reshapeLayer.GetOutputSlot(0).Connect(startLayer->GetInputSlot(0));
355  input1.Connect(startLayer->GetInputSlot(1));
356  }
357  else
358  {
359  // Input1 is the "smaller" tensor, connect the reshape layer as follows:
360  //
361  // Input0 Input1
362  // | |
363  // | Reshape
364  // \ /
365  // StartLayer
366 
367  input0.Connect(startLayer->GetInputSlot(0));
368  reshapeLayer.GetOutputSlot(0).Connect(startLayer->GetInputSlot(1));
369  }
370 
371  return true;
372 }
373 
374 void CalcPadding(uint32_t input,
375  uint32_t kernel,
376  uint32_t stride,
377  uint32_t& outPadHead,
378  uint32_t& outPadTail,
379  PaddingScheme scheme)
380 {
381  int32_t padHead;
382  int32_t padTail;
383  calculateExplicitPadding(input, stride, kernel, scheme, &padHead, &padTail);
384  outPadHead = armnn::numeric_cast<uint32_t>(padHead);
385  outPadTail = armnn::numeric_cast<uint32_t>(padTail);
386 }
387 
388 void CalcPadding(uint32_t input, uint32_t kernel, uint32_t stride, uint32_t dilation, uint32_t& outPadHead,
389  uint32_t& outPadTail, ::android::nn::PaddingScheme scheme)
390 {
391  int32_t padHead;
392  int32_t padTail;
393  calculateExplicitPadding(input, stride, dilation, kernel, scheme, &padHead, &padTail);
394  outPadHead = armnn::numeric_cast<uint32_t>(padHead);
395  outPadTail = armnn::numeric_cast<uint32_t>(padTail);
396 }
397 
398 inline void CalcPaddingTransposeConv(uint32_t output, uint32_t kernel, int32_t stride, int32_t& outPadHead,
399  int32_t& outPadTail, ::android::nn::PaddingScheme scheme)
400 {
401  calculateExplicitPaddingTransposeConv(output, stride, kernel, scheme, &outPadHead, &outPadTail);
402 }
403 
404 Shape GetOperandShape(const Operand& operand)
405 {
406  Shape shape;
407  shape.type = OperandType(operand.type);
408  shape.dimensions = operand.dimensions;
409  shape.scale = operand.scale;
410  shape.offset = operand.zeroPoint;
411  return shape;
412 }
413 
414 
415 // ArmNN requires the bias scale to be equal to the product of the weight and input scales, which is also
416 // what AndroidNN requires. However for some of the AndroidNN tests the values don't exactly match so
417 // we accept some tolerance. We don't want ArmNN itself to accept these inconsistencies as it is up to the
418 // user (us, in this case) to ensure they match.
419 void SanitizeBiasQuantizationScale(armnn::TensorInfo& biasInfo,
420  const armnn::TensorInfo& weightInfo,
421  const armnn::TensorInfo& inputInfo)
422 {
423  if (weightInfo.HasPerAxisQuantization())
424  {
425  // NOTE: Bias scale is always set to 0 for per-axis quantization and
426  // it needs to be calculated: scale[i] = input_scale * weight_scale[i]
427  auto UpdateBiasScaleValue = [&inputInfo](float biasScale) -> float
428  {
429  return biasScale * inputInfo.GetQuantizationScale();
430  };
431 
432  std::vector<float> biasScales(weightInfo.GetQuantizationScales());
433  std::transform(biasScales.begin(), biasScales.end(), biasScales.begin(), UpdateBiasScaleValue);
434 
435  biasInfo.SetQuantizationScales(biasScales);
436  // bias is expected to be a 1d tensor, set qdim=0
437  biasInfo.SetQuantizationDim(0);
438 
439  VLOG(DRIVER) << "Bias quantization params have been updated for per-axis quantization";
440  }
441  else
442  {
443  const float expectedBiasScale = weightInfo.GetQuantizationScale() * inputInfo.GetQuantizationScale();
444  if (biasInfo.GetQuantizationScale() != expectedBiasScale)
445  {
446  if (armnnUtils::within_percentage_tolerance(biasInfo.GetQuantizationScale(), expectedBiasScale, 1.0f))
447  {
448  VLOG(DRIVER) << "Bias quantization scale has been modified to match input * weights";
449  biasInfo.SetQuantizationScale(expectedBiasScale);
450  }
451  }
452  }
453 }
454 
455 // 4D Tensor Permutations
456 const armnn::PermutationVector IdentityPermutation4D({ 0U, 1U, 2U, 3U });
457 const armnn::PermutationVector IdentityPermutation3D({ 0U, 1U, 2U });
458 const armnn::PermutationVector SwapDim1And2({ 0U, 2U, 1U, 3U });
459 
460 // 3D Permutation Vectors
461 const armnn::PermutationVector RotateTensorLeft({ 1U, 2U, 0U });
462 const armnn::PermutationVector RotateTensorRight({ 2U, 0U, 1U });
463 
464 template<typename OSlot>
465 armnn::IConnectableLayer& AddTransposeLayer(armnn::INetwork& network, OSlot& input,
466  const armnn::PermutationVector& mappings)
467 {
468  // Add swizzle layer
469  armnn::IConnectableLayer* const layer = network.AddTransposeLayer(mappings);
470 
471  ARMNN_ASSERT(layer != nullptr);
472 
473  // Connect input to swizzle layer
474  input.Connect(layer->GetInputSlot(0));
475 
476  // Setup swizzled output
477  const armnn::TensorInfo outInfo = armnnUtils::TransposeTensorShape(input.GetTensorInfo(), mappings);
478  layer->GetOutputSlot(0).SetTensorInfo(outInfo);
479 
480  return *layer;
481 }
482 
483 bool ValidateConcatOutputShape(const std::vector<armnn::TensorShape> & inputShapes,
484  const armnn::TensorShape & outputShape,
485  uint32_t concatDim)
486 {
487  // Validate the output shape is correct given the input shapes (which have just been validated)
488  unsigned int numDimensions = inputShapes[0].GetNumDimensions();
489  if (outputShape.GetNumDimensions() != numDimensions)
490  {
491  return Fail("%s: Output shape has wrong number of dimensions", __func__);
492  }
493 
494  unsigned int outputSizeAlongConcatenatedDimension = 0;
495  for (unsigned int i = 0; i < inputShapes.size(); i++)
496  {
497  outputSizeAlongConcatenatedDimension += inputShapes[i][concatDim];
498  }
499 
500  for (unsigned int i = 0; i < numDimensions; ++i)
501  {
502  if (i == concatDim)
503  {
504  if (outputShape[i] != outputSizeAlongConcatenatedDimension)
505  {
506  return Fail(
507  "%s: Invalid output shape for dimension %d (%d != %d)",
508  __func__,
509  i,
510  outputShape[i],
511  outputSizeAlongConcatenatedDimension);
512  }
513  }
514  else
515  {
516  if (outputShape[i] != inputShapes[0][i])
517  {
518  return Fail("%s: Invalid output shape", __func__);
519  }
520  }
521  }
522 
523  return true;
524 }
525 
526 inline bool RequiresReshape(armnn::TensorShape & inputShape)
527 {
528  return inputShape.GetNumDimensions() < 3;
529 }
530 
531 inline void SwizzleInputs(armnn::INetwork& network,
532  std::vector<LayerInputHandle>& inputs,
533  std::vector<armnn::TensorShape>& inputShapes,
534  const armnn::PermutationVector& mapping,
535  std::vector<armnn::BackendId>& setBackends)
536 {
537  if (!mapping.IsEqual(IdentityPermutation4D))
538  {
539  size_t nInputs = inputs.size();
540  for (size_t i=0; i<nInputs; ++i)
541  {
542  // add swizzle layer
543  armnn::IConnectableLayer& swizzleLayer = AddTransposeLayer(network, inputs[i], mapping);
544  swizzleLayer.SetBackendId(setBackends[i]);
545  auto& outputSlot = swizzleLayer.GetOutputSlot(0);
546  auto& outputInfo = outputSlot.GetTensorInfo();
547  // replace inputs with the swizzled ones
548  inputs[i] = LayerInputHandle(true, &outputSlot, outputInfo);
549  inputShapes[i] = inputs[i].GetTensorInfo().GetShape();
550  }
551  }
552 }
553 
554 bool TransposeInputTensors(ConversionData& data,
555  std::vector<LayerInputHandle>& inputs,
556  std::vector<armnn::TensorShape>& inputShapes,
557  const armnn::PermutationVector& mapping)
558 {
559  // If we have a IdentityPermutation4D or IdentityPermutation3D then we are not permuting
560  if (!mapping.IsEqual(IdentityPermutation4D) && !mapping.IsEqual(IdentityPermutation3D))
561  {
562  std::vector<armnn::BackendId> setBackendsVec;
563  armnn::TensorInfo outputTransposeInfo;
564  size_t nInputs = inputs.size();
565  for (size_t i=0; i<nInputs; ++i)
566  {
567  // check permute layer
568  armnn::TransposeDescriptor transposeDesc;
569  transposeDesc.m_DimMappings = mapping;
570  outputTransposeInfo = armnnUtils::TransposeTensorShape(inputs[i].GetTensorInfo(), mapping);
571 
572  bool isSupported = false;
573  armnn::BackendId setBackend;
575  IsTransposeSupported,
576  data.m_Backends,
577  isSupported,
578  setBackend,
579  inputs[i].GetTensorInfo(),
580  outputTransposeInfo,
581  transposeDesc);
582  setBackendsVec.push_back(setBackend);
583  if (!isSupported)
584  {
585  return false;
586  }
587 
588  }
589  SwizzleInputs(*data.m_Network, inputs, inputShapes, mapping, setBackendsVec);
590  }
591  return true;
592 }
593 
594 bool CreateConcatPermutationParameters(const unsigned int numberOfDimensions,
595  int32_t & concatDimension,
596  std::pair<armnn::PermutationVector, armnn::PermutationVector> & permutationPair)
597 {
598  bool needPermute = false;
599  ARMNN_ASSERT(numberOfDimensions >= 3);
600 
601  // ArmNN uses Compute Library subtensors to perform concatenation
602  // This only works when concatenating along dimension 0, 1 or 3 for a 4-D tensor,
603  // or along dimension 0 or 2 for a 3-D tensor.
604  if (numberOfDimensions == 4 && concatDimension == 2)
605  {
606  concatDimension = 1;
607  permutationPair = std::make_pair(SwapDim1And2, SwapDim1And2);
608  needPermute = true;
609  }
610  else if (numberOfDimensions == 3 && concatDimension == 1)
611  {
612  concatDimension = 0;
613  permutationPair = std::make_pair(RotateTensorLeft, RotateTensorRight);
614  needPermute = true;
615  }
616  // If the tensor is 3-D and the concat dimension is 2 then we don't need to permute but we do need to change the
617  // permutation identity to only have 3 dimensions
618  else if (numberOfDimensions == 3 && concatDimension == 2)
619  {
620  permutationPair = std::make_pair(IdentityPermutation3D, IdentityPermutation3D);
621  }
622  return needPermute;
623 }
624 
625 } // anonymous namespace
626 
627 namespace armnn_driver
628 {
629 using namespace android::nn;
630 
631 //// Creates an ArmNN activation layer and connects it to the given layer, if the
632 //// passed in AndroidNN activation function requires so.
633 //// @return The end layer of the sequence of layers built for the given AndroidNN
634 //// activation function or nullptr if an error occurred (e.g. unsupported activation).
635 //// Note that the end layer matches the input layer if no activation is required
636 //// (the sequence of layers has length 1).
638  ActivationFn activation,
639  armnn::IConnectableLayer* prevLayer,
640  ConversionData& data);
641 
642 
643 inline const Operand* GetInputOperand(const Operation& operation,
644  uint32_t inputIndex,
645  const Model& model,
646  bool failOnIndexOutOfBounds = true)
647 {
648  if (inputIndex >= operation.inputs.size())
649  {
650  if (failOnIndexOutOfBounds)
651  {
652  Fail("%s: invalid input index: %i out of %i", __func__, inputIndex, operation.inputs.size());
653  }
654  return nullptr;
655  }
656 
657  // Model should have been validated beforehand
658  ARMNN_ASSERT(operation.inputs[inputIndex] < getMainModel(model).operands.size());
659  return &getMainModel(model).operands[operation.inputs[inputIndex]];
660 }
661 
662 inline const Operand* GetOutputOperand(const Operation& operation,
663  uint32_t outputIndex,
664  const Model& model)
665 {
666  if (outputIndex >= operation.outputs.size())
667  {
668  Fail("%s: invalid output index: %i out of %i", __func__, outputIndex, operation.outputs.size());
669  return nullptr;
670  }
671 
672  // Model should have been validated beforehand
673  ARMNN_ASSERT(operation.outputs[outputIndex] < getMainModel(model).operands.size());
674 
675  return &getMainModel(model).operands[operation.outputs[outputIndex]];
676 }
677 
678 const void* GetOperandValueReadOnlyAddress(const Operand& operand,
679  const Model& model,
680  const ConversionData& data,
681  bool optional = false);
682 
683 inline bool GetOperandType(const Operation& operation,
684  uint32_t inputIndex,
685  const Model& model,
686  OperandType& type)
687 {
688  const Operand* operand = GetInputOperand(operation, inputIndex, model);
689  if (!operand)
690  {
691  return Fail("%s: invalid input operand at index %i", __func__, inputIndex);
692  }
693 
694  type = operand->type;
695  return true;
696 }
697 
698 inline bool IsOperandConstant(const Operand& operand)
699 {
700  OperandLifeTime lifetime = operand.lifetime;
701 
702  return lifetime == OperandLifeTime::CONSTANT_COPY ||
703  lifetime == OperandLifeTime::CONSTANT_REFERENCE ||
704  lifetime == OperandLifeTime::POINTER ||
705  lifetime == OperandLifeTime::NO_VALUE;
706 }
707 
708 bool IsWeightsValid(const Operation& operation, uint32_t inputIndex, const Model& model);
709 
711  const Model& model,
712  const ConversionData& data,
713  const armnn::PermutationVector& dimensionMappings = g_DontPermute,
714  const armnn::TensorShape* overrideTensorShape = nullptr,
715  bool optional = false,
716  const armnn::DataType* overrideDataType = nullptr);
717 
719  const Operation& operation,
720  uint32_t inputIndex,
721  const Model& model,
722  const ConversionData& data,
723  const armnn::PermutationVector& dimensionMappings = g_DontPermute,
724  const armnn::TensorShape* overrideTensorShape = nullptr,
725  bool optional = false)
726 {
727  const Operand* operand = GetInputOperand(operation, inputIndex, model);
728  if (!operand)
729  {
730  Fail("%s: failed to get input operand: index=%u", __func__, inputIndex);
731  return ConstTensorPin();
732  }
733  return ConvertOperandToConstTensorPin(*operand,
734  model,
735  data,
736  dimensionMappings,
737  overrideTensorShape,
738  optional);
739 }
740 
741 template <typename OutputType>
742 bool GetInputScalar(const Operation& operation,
743  uint32_t inputIndex,
744  OperandType type,
745  OutputType& outValue,
746  const Model& model,
747  const ConversionData& data,
748  bool optional = false)
749 {
750  const Operand* operand = GetInputOperand(operation, inputIndex, model);
751  if (!optional && !operand)
752  {
753  return Fail("%s: invalid input operand at index %i", __func__, inputIndex);
754  }
755 
756  if (!optional && operand->type != type)
757  {
758  VLOG(DRIVER) << __func__ << ": unexpected operand type: " << operand->type << " should be: " << type;
759  return false;
760  }
761 
762  if (!optional && operand->location.length != sizeof(OutputType))
763  {
764  return Fail("%s: incorrect operand location length: %i (should be %i)",
765  __func__, operand->location.length, sizeof(OutputType));
766  }
767 
768  const void* valueAddress = GetOperandValueReadOnlyAddress(*operand, model, data);
769  if (!optional && !valueAddress)
770  {
771  return Fail("%s: failed to get address for operand", __func__);
772  }
773 
774  if(!optional)
775  {
776  outValue = *(static_cast<const OutputType*>(valueAddress));
777  }
778 
779  return true;
780 }
781 
782 inline bool GetInputInt32(const Operation& operation,
783  uint32_t inputIndex,
784  int32_t& outValue,
785  const Model& model,
786  const ConversionData& data)
787 {
788  return GetInputScalar(operation, inputIndex, OperandType::INT32, outValue, model, data);
789 }
790 
791 inline bool GetInputFloat32(const Operation& operation,
792  uint32_t inputIndex,
793  float& outValue,
794  const Model& model,
795  const ConversionData& data)
796 {
797  return GetInputScalar(operation, inputIndex, OperandType::FLOAT32, outValue, model, data);
798 }
799 
800 inline bool GetInputActivationFunctionImpl(const Operation& operation,
801  uint32_t inputIndex,
802  OperandType type,
803  ActivationFn& outActivationFunction,
804  const Model& model,
805  const ConversionData& data)
806 {
807  if (type != OperandType::INT32 && type != OperandType::TENSOR_INT32)
808  {
809  VLOG(DRIVER) << __func__ << ": unexpected operand type: " << type
810  << " should be OperandType::INT32 or OperandType::TENSOR_INT32";
811  return false;
812  }
813 
814  int32_t activationFunctionAsInt;
815  if (!GetInputScalar(operation, inputIndex, type, activationFunctionAsInt, model, data))
816  {
817  return Fail("%s: failed to get activation input value", __func__);
818  }
819  outActivationFunction = static_cast<ActivationFn>(activationFunctionAsInt);
820  return true;
821 }
822 
823 inline bool GetInputActivationFunction(const Operation& operation,
824  uint32_t inputIndex,
825  ActivationFn& outActivationFunction,
826  const Model& model,
827  const ConversionData& data)
828 {
829  return GetInputActivationFunctionImpl(operation,
830  inputIndex,
831  OperandType::INT32,
832  outActivationFunction,
833  model,
834  data);
835 }
836 
837 inline bool GetInputActivationFunctionFromTensor(const Operation& operation,
838  uint32_t inputIndex,
839  ActivationFn& outActivationFunction,
840  const Model& model,
841  const ConversionData& data)
842 {
843  // This only accepts a 1-D tensor of size 1
844  return GetInputActivationFunctionImpl(operation,
845  inputIndex,
846  OperandType::INT32,
847  outActivationFunction,
848  model,
849  data);
850 }
851 
852 
853 inline bool GetOptionalInputActivation(const Operation& operation,
854  uint32_t inputIndex,
855  ActivationFn& activationFunction,
856  const Model& model,
857  const ConversionData& data)
858 {
859  if (operation.inputs.size() <= inputIndex)
860  {
861  activationFunction = ActivationFn::kActivationNone;
862  }
863  else
864  {
865  if (!GetInputActivationFunction(operation, inputIndex, activationFunction, model, data))
866  {
867  return Fail("%s: Operation has invalid inputs", __func__);
868  }
869  }
870  return true;
871 }
872 
873 template<typename ConvolutionDescriptor>
875  uint32_t dilationXIndex,
876  ConvolutionDescriptor& descriptor,
877  const Model& model,
878  const ConversionData& data)
879 {
880  bool success = true;
881  if (operation.inputs.size() >= dilationXIndex + 2)
882  {
883  success &= GetInputScalar(operation,
884  dilationXIndex,
885  OperandType::INT32,
886  descriptor.m_DilationX,
887  model,
888  data);
889  success &= GetInputScalar(operation,
890  dilationXIndex + 1,
891  OperandType::INT32,
892  descriptor.m_DilationY,
893  model,
894  data);
895  }
896 
897  return success;
898 }
899 
900 inline bool GetOptionalBool(const Operation& operation,
901  uint32_t inputIndex,
902  const Model& model,
903  const ConversionData& data)
904 {
905  const Operand* operand = GetInputOperand(operation, inputIndex, model);
906  if (!operand)
907  {
908  return false;
909  }
910 
911  if (!IsBool(*operand))
912  {
913  return false;
914  }
915 
916  const void* valueAddress = GetOperandValueReadOnlyAddress(*operand, model, data);
917  if (!valueAddress)
918  {
919  return false;
920  }
921 
922  return *(static_cast<const bool*>(valueAddress));
923 }
924 
925 bool GetTensorInt32Values(const Operand& operand,
926  std::vector<int32_t>& outValues,
927  const Model& model,
928  const ConversionData& data);
929 
930 bool GetInputPaddingScheme(const Operation& operation,
931  uint32_t inputIndex,
932  PaddingScheme& outPaddingScheme,
933  const Model& model,
934  const ConversionData& data);
935 
937  uint32_t inputIndex,
938  const Model& model,
939  ConversionData& data,
940  const armnn::PermutationVector& dimensionMappings = g_DontPermute,
941  const LayerInputHandle* inputHandle = nullptr);
942 
943 bool SetupAndTrackLayerOutputSlot(const Operation& operation,
944  uint32_t operationOutputIndex,
946  uint32_t layerOutputIndex,
947  const Model& model,
948  ConversionData& data,
949  const armnn::TensorInfo* overrideOutputInfo = nullptr,
950  const std::function <void (const armnn::TensorInfo&, bool&)>& validateFunc = nullptr,
951  const ActivationFn& activationFunction = ActivationFn::kActivationNone,
952  bool inferOutputShapes = false);
953 
955  uint32_t inputIndex,
956  const Model& model,
957  ConversionData& data);
958 
960  const Operation& operation,
961  uint32_t outputIndex,
963  const Model& model,
964  ConversionData& data,
965  const armnn::TensorInfo* overrideOutputInfo = nullptr,
966  const std::function <void (const armnn::TensorInfo&, bool&)>& validateFunc = nullptr,
967  const ActivationFn& activationFunction = ActivationFn::kActivationNone)
968 {
969  return SetupAndTrackLayerOutputSlot(operation,
970  outputIndex,
971  layer,
972  outputIndex,
973  model,
974  data,
975  overrideOutputInfo,
976  validateFunc,
977  activationFunction);
978 }
979 
980 bool ConvertToActivation(const Operation& operation,
981  const char* operationName,
982  const armnn::ActivationDescriptor& activationDesc,
983  const Model& model,
984  ConversionData& data);
985 
986 bool ConvertPaddings(const Operation& operation,
987  const Model& model,
988  ConversionData& data,
989  unsigned int rank,
990  armnn::PadDescriptor& padDescriptor);
991 bool ConvertReduce(const Operation& operation,
992  const Model& model,
993  ConversionData& data,
994  armnn::ReduceOperation reduceOperation);
995 
996 bool ConvertPooling2d(const Operation& operation,
997  const char* operationName,
998  armnn::PoolingAlgorithm poolType,
999  const Model& model,
1000  ConversionData& data);
1001 
1002 inline bool IsQSymm8(const Operand& operand)
1003 {
1004  return operand.type == OperandType::TENSOR_QUANT8_SYMM;
1005 }
1006 
1008 {
1009  SUCCESS,
1010  NOT_REQUIRED,
1012 };
1013 
1014 using DequantizeResult = std::tuple<std::unique_ptr<float[]>, size_t, armnn::TensorInfo, DequantizeStatus>;
1015 
1016 DequantizeResult DequantizeIfRequired(size_t operand_index,
1017  const Operation& operation,
1018  const Model& model,
1019  const ConversionData& data);
1020 
1022  const Model& model,
1023  const ConversionData& data,
1024  size_t operandIndex,
1025  bool optional = false);
1026 
1027 bool IsConnectedToDequantize(armnn::IOutputSlot* ioutputSlot);
1028 
1029 } // namespace armnn_driver
armnn_driver::GetOutputOperand
const Operand * GetOutputOperand(const Operation &operation, uint32_t outputIndex, const Model &model)
Definition: ConversionUtils.hpp:662
armnn_driver::IsWeightsValid
bool IsWeightsValid(const Operation &operation, uint32_t inputIndex, const Model &model)
Utility functions.
Definition: ConversionUtils.cpp:134
armnn_driver::IsQSymm8
bool IsQSymm8(const Operand &operand)
Definition: ConversionUtils.hpp:1002
armnn_driver::Operation
::android::nn::Operation Operation
Definition: ConversionUtils.hpp:47
armnn_driver::GetInputActivationFunctionImpl
bool GetInputActivationFunctionImpl(const Operation &operation, uint32_t inputIndex, OperandType type, ActivationFn &outActivationFunction, const Model &model, const ConversionData &data)
Definition: ConversionUtils.hpp:800
armnn_driver::DequantizeStatus::INVALID_OPERAND
@ INVALID_OPERAND
armnn::BackendId
Definition: BackendId.hpp:75
armnn::TensorInfo::GetQuantizationScale
float GetQuantizationScale() const
Definition: Tensor.cpp:461
armnn_driver::IsConnectedToDequantize
bool IsConnectedToDequantize(armnn::IOutputSlot *ioutputSlot)
Definition: ConversionUtils.cpp:1040
armnn_driver::OperationType
::android::nn::OperationType OperationType
Definition: ConversionUtils.hpp:48
armnn_driver
Helper classes.
Definition: ArmnnDevice.cpp:37
armnn::TransposeDescriptor
A TransposeDescriptor for the TransposeLayer.
Definition: Descriptors.hpp:1457
armnn_driver::ConvertPaddings
bool ConvertPaddings(const Operation &operation, const Model &model, ConversionData &data, unsigned int rank, armnn::PadDescriptor &padDescriptor)
Definition: ConversionUtils.cpp:338
armnn_driver::DequantizeStatus::NOT_REQUIRED
@ NOT_REQUIRED
armnn::PadDescriptor
A PadDescriptor for the PadLayer.
Definition: Descriptors.hpp:1163
armnn::DataLayout
DataLayout
Definition: Types.hpp:62
DataLayoutIndexed.hpp
armnn::TensorInfo::SetQuantizationScale
void SetQuantizationScale(float scale)
Definition: Tensor.cpp:473
armnn_driver::ConversionData::m_OutputSlotForOperand
std::vector< armnn::IOutputSlot * > m_OutputSlotForOperand
Definition: ConversionUtils.hpp:61
armnn_driver::ConversionData::ConversionData
ConversionData(const std::vector< armnn::BackendId > &backends)
Definition: ConversionUtils.hpp:53
armnn::ActivationDescriptor
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:36
armnn::IConnectableLayer
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:68
armnn::TensorShape::GetNumElements
unsigned int GetNumElements() const
Function that calculates the tensor elements by multiplying all dimension size which are Specified.
Definition: Tensor.cpp:181
armnn_driver::ConvertToLayerInputHandle
LayerInputHandle ConvertToLayerInputHandle(const Operation &operation, uint32_t inputIndex, const Model &model, ConversionData &data, const armnn::PermutationVector &dimensionMappings, const LayerInputHandle *inputHandle)
Definition: ConversionUtils.cpp:204
armnn_driver::ConstTensorPin::GetConstTensorPtr
const armnn::ConstTensor * GetConstTensorPtr() const
Definition: ConversionUtils.cpp:120
armnn_driver::GetOperandValueReadOnlyAddress
const void * GetOperandValueReadOnlyAddress(const Operand &operand, const Model &model, const ConversionData &data, bool optional)
Definition: ConversionUtils.cpp:777
BackendHelper.hpp
ArmNN.hpp
armnn_driver::ConversionData::m_DynamicInputsEncountered
bool m_DynamicInputsEncountered
Definition: ConversionUtils.hpp:63
armnn_driver::GetOptionalBool
bool GetOptionalBool(const Operation &operation, uint32_t inputIndex, const Model &model, const ConversionData &data)
Definition: ConversionUtils.hpp:900
armnn::ConstTensor
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:327
armnn::TensorInfo::SetQuantizationDim
void SetQuantizationDim(const Optional< unsigned int > &quantizationDim)
Definition: Tensor.cpp:499
armnn::LayerType::Shape
@ Shape
armnn_driver::GetTensorInt32Values
bool GetTensorInt32Values(const Operand &operand, std::vector< int32_t > &outValues, const Model &model, const ConversionData &data)
Definition: ConversionUtils.cpp:822
armnn_driver::Model
::android::nn::Model Model
Helper classes.
Definition: ConversionUtils.hpp:43
Assert.hpp
armnn_driver::ConversionResult
ConversionResult
Definition: ConversionUtils.hpp:125
armnn_driver::GetInputActivationFunctionFromTensor
bool GetInputActivationFunctionFromTensor(const Operation &operation, uint32_t inputIndex, ActivationFn &outActivationFunction, const Model &model, const ConversionData &data)
Definition: ConversionUtils.hpp:837
armnn_driver::DequantizeAndMakeConstTensorPin
ConstTensorPin DequantizeAndMakeConstTensorPin(const Operation &operation, const Model &model, const ConversionData &data, size_t operandIndex, bool optional)
Definition: ConversionUtils.cpp:731
armnn::IConnectableLayer::GetOutputSlot
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
FloatingPointComparison.hpp
armnnUtils::within_percentage_tolerance
bool within_percentage_tolerance(float a, float b, float tolerancePercent=1.0f)
Compare two floats and return true if their values are within a specified tolerance of each other.
Definition: FloatingPointComparison.hpp:20
armnnUtils::TransposeTensorShape
armnn::TensorShape TransposeTensorShape(const armnn::TensorShape &srcShape, const armnn::PermutationVector &mappings)
Definition: Transpose.cpp:98
armnn_driver::ConversionData
Definition: ConversionUtils.hpp:51
armnn::IOutputSlot::Connect
virtual int Connect(IInputSlot &destination)=0
armnn::IsReshapeSupported
bool IsReshapeSupported(const BackendId &backend, const TensorInfo &input, const ReshapeDescriptor &descriptor, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.
armnn::IInputSlot
An input connection slot for a layer.
Definition: INetwork.hpp:25
armnnUtils::GetTensorInfo
armnn::TensorInfo GetTensorInfo(unsigned int numberOfBatches, unsigned int numberOfChannels, unsigned int height, unsigned int width, const armnn::DataLayout dataLayout, const armnn::DataType dataType)
Definition: TensorUtils.cpp:38
armnn::TensorInfo::SetQuantizationScales
void SetQuantizationScales(const std::vector< float > &scales)
Definition: Tensor.cpp:456
armnn_driver::Operand
::android::nn::Operand Operand
Definition: ConversionUtils.hpp:44
armnn::IConnectableLayer::GetInputSlot
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
armnn_driver::ConversionData::m_Network
armnn::INetworkPtr m_Network
Definition: ConversionUtils.hpp:60
armnn_driver::DequantizeResult
std::tuple< std::unique_ptr< float[]>, size_t, armnn::TensorInfo, DequantizeStatus > DequantizeResult
Definition: ConversionUtils.hpp:1014
armnn::TensorShape
Definition: Tensor.hpp:20
armnn_driver::ConstTensorPin
Definition: ConversionUtils.hpp:90
armnn::PoolingAlgorithm
PoolingAlgorithm
Definition: Types.hpp:147
armnn_driver::ConversionResult::ErrorMappingPools
@ ErrorMappingPools
armnn_driver::LayerInputHandle
Definition: ConversionUtils.hpp:66
armnn::IOutputSlot::GetTensorInfo
virtual const TensorInfo & GetTensorInfo() const =0
armnn::INetwork::AddTransposeLayer
IConnectableLayer * AddTransposeLayer(const TransposeDescriptor &transposeDescriptor, const char *name=nullptr)
Adds a transpose layer to the network.
Definition: Network.cpp:580
armnn::ReduceOperation
ReduceOperation
Definition: Types.hpp:154
armnn_driver::ConvertPooling2d
bool ConvertPooling2d(const Operation &operation, const char *operationName, armnn::PoolingAlgorithm poolType, const Model &model, ConversionData &data)
Definition: ConversionUtils.cpp:380
armnn::TensorInfo::GetNumDimensions
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:195
armnn_driver::GetInputInt32
bool GetInputInt32(const Operation &operation, uint32_t inputIndex, int32_t &outValue, const Model &model, const ConversionData &data)
Definition: ConversionUtils.hpp:782
armnn_driver::LayerInputHandle::GetOutputSlot
armnn::IOutputSlot * GetOutputSlot() const
Definition: ConversionUtils.cpp:70
armnn::IOutputSlot
An output connection slot for a layer.
Definition: INetwork.hpp:41
armnn_driver::GetOptionalConvolutionDilationParams
bool GetOptionalConvolutionDilationParams(const Operation &operation, uint32_t dilationXIndex, ConvolutionDescriptor &descriptor, const Model &model, const ConversionData &data)
Definition: ConversionUtils.hpp:874
armnn::TensorInfo
Definition: Tensor.hpp:152
armnn_driver::GetOperandType
bool GetOperandType(const Operation &operation, uint32_t inputIndex, const Model &model, OperandType &type)
Definition: ConversionUtils.hpp:683
armnn_driver::LayerInputHandle::Connect
void Connect(armnn::IInputSlot &inputSlot)
Definition: ConversionUtils.cpp:32
armnn_driver::LayerInputHandle::SanitizeQuantizationScale
void SanitizeQuantizationScale(LayerInputHandle &weight, LayerInputHandle &input)
Definition: ConversionUtils.cpp:55
armnn_driver::GetOptionalInputActivation
bool GetOptionalInputActivation(const Operation &operation, uint32_t inputIndex, ActivationFn &activationFunction, const Model &model, const ConversionData &data)
Definition: ConversionUtils.hpp:853
armnn::TensorInfo::HasPerAxisQuantization
bool HasPerAxisQuantization() const
Definition: Tensor.cpp:446
armnn_driver::GetInputOperand
const Operand * GetInputOperand(const Operation &operation, uint32_t inputIndex, const Model &model, bool failOnIndexOutOfBounds=true)
Definition: ConversionUtils.hpp:643
armnn_driver::GetInputPaddingScheme
bool GetInputPaddingScheme(const Operation &operation, uint32_t inputIndex, PaddingScheme &outPaddingScheme, const Model &model, const ConversionData &data)
Definition: ConversionUtils.cpp:761
armnn::TensorInfo::GetShape
const TensorShape & GetShape() const
Definition: Tensor.hpp:191
armnn::TransposeDescriptor::m_DimMappings
PermutationVector m_DimMappings
Indicates how to translate tensor elements from a given source into the target destination,...
Definition: Descriptors.hpp:1481
armnn_driver::ConstTensorPin::ConstTensorPin
ConstTensorPin(bool optional=false)
Definition: ConversionUtils.cpp:75
armnn_driver::ErrorStatus
::android::nn::ErrorStatus ErrorStatus
Definition: ConversionUtils.hpp:49
armnn_driver::ConversionResult::UnsupportedFeature
@ UnsupportedFeature
armnn_driver::DequantizeIfRequired
DequantizeResult DequantizeIfRequired(size_t operand_index, const Operation &operation, const Model &model, const ConversionData &data)
Definition: ConversionUtils.cpp:648
armnn::PermutationVector
Definition: Types.hpp:306
armnn_driver::LayerInputHandle::IsValid
bool IsValid() const
Definition: ConversionUtils.cpp:27
CanonicalUtils.hpp
armnn::IConnectableLayer::SetBackendId
virtual void SetBackendId(const BackendId &id)=0
Set the backend of the IConnectableLayer.
armnn::ReshapeDescriptor
A ReshapeDescriptor for the ReshapeLayer.
Definition: Descriptors.hpp:990
armnn::TensorShape::GetNumDimensions
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
Definition: Tensor.cpp:174
armnn::DataType
DataType
Definition: Types.hpp:48
armnn_driver::ConversionData::m_MemPools
std::vector<::android::nn::RunTimePoolInfo > m_MemPools
Definition: ConversionUtils.hpp:62
armnn::PermutationVector::IsEqual
bool IsEqual(const PermutationVector &other) const
Definition: Types.hpp:358
ARMNN_ASSERT
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
armnn_driver::ConstTensorPin::IsOptional
bool IsOptional() const
Definition: ConversionUtils.cpp:110
armnn::IOutputSlot::SetTensorInfo
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
armnn_driver::LayerInputHandle::LayerInputHandle
LayerInputHandle()
Definition: ConversionUtils.cpp:16
armnn_driver::LayerInputHandle::GetTensorInfo
const armnn::TensorInfo & GetTensorInfo() const
Definition: ConversionUtils.cpp:50
armnn_driver::ProcessActivation
armnn::IConnectableLayer * ProcessActivation(const armnn::TensorInfo &tensorInfo, ActivationFn activation, armnn::IConnectableLayer *prevLayer, ConversionData &data)
Definition: ConversionUtils.cpp:885
armnn_driver::ConvertOperationInputToConstTensorPin
ConstTensorPin ConvertOperationInputToConstTensorPin(const Operation &operation, uint32_t inputIndex, const Model &model, const ConversionData &data, const armnn::PermutationVector &dimensionMappings=g_DontPermute, const armnn::TensorShape *overrideTensorShape=nullptr, bool optional=false)
Definition: ConversionUtils.hpp:718
armnn::INetwork
Main network class which provides the interface for building up a neural network.
Definition: INetwork.hpp:335
armnn_driver::g_DontPermute
const armnn::PermutationVector g_DontPermute
Definition: CanonicalUtils.cpp:38
armnn_driver::OperandLifeTime
::android::nn::Operand::LifeTime OperandLifeTime
Definition: ConversionUtils.hpp:45
armnn_driver::OptionalDataLayout
armnn::DataLayout OptionalDataLayout(const Operation &operation, uint32_t inputIndex, const Model &model, ConversionData &data)
Definition: ConversionUtils.cpp:853
armnn_driver::GetInputActivationFunction
bool GetInputActivationFunction(const Operation &operation, uint32_t inputIndex, ActivationFn &outActivationFunction, const Model &model, const ConversionData &data)
Definition: ConversionUtils.hpp:823
getMainModel
const android::nn::Model::Subgraph & getMainModel(const android::nn::Model &model)
Definition: ConversionUtils.hpp:28
armnn_driver::ConstTensorPin::GetConstTensor
const armnn::ConstTensor & GetConstTensor() const
Definition: ConversionUtils.cpp:115
armnn_driver::ConvertOperandToConstTensorPin
ConstTensorPin ConvertOperandToConstTensorPin(const Operand &operand, const Model &model, const ConversionData &data, const armnn::PermutationVector &dimensionMappings, const armnn::TensorShape *overrideTensorShape, bool optional, const armnn::DataType *overrideDataType)
Definition: ConversionUtils.cpp:154
armnn_driver::ConversionResult::Success
@ Success
armnn_driver::ConstTensorPin::IsValid
bool IsValid() const
Definition: ConversionUtils.cpp:105
NumericCast.hpp
armnn::INetworkPtr
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:327
armnn::TensorInfo::SetShape
void SetShape(const TensorShape &newShape)
Definition: Tensor.hpp:193
armnn_driver::ConvertReduce
bool ConvertReduce(const Operation &operation, const Model &model, ConversionData &data, armnn::ReduceOperation reduceOperation)
Definition: ConversionUtils.cpp:508
armnn_driver::DequantizeStatus
DequantizeStatus
Definition: ConversionUtils.hpp:1007
IgnoreUnused.hpp
armnn_driver::SetupAndTrackLayerOutputSlot
bool SetupAndTrackLayerOutputSlot(const Operation &operation, uint32_t operationOutputIndex, armnn::IConnectableLayer &layer, uint32_t layerOutputIndex, const Model &model, ConversionData &data, const armnn::TensorInfo *overrideOutputInfo, const std::function< void(const armnn::TensorInfo &, bool &)> &validateFunc, const ActivationFn &activationFunction, bool inferOutputShapes)
Definition: ConversionUtils.cpp:963
armnn::TensorInfo::GetQuantizationScales
std::vector< float > GetQuantizationScales() const
Definition: Tensor.cpp:451
armnn::ReshapeDescriptor::m_TargetShape
TensorShape m_TargetShape
Target shape value.
Definition: Descriptors.hpp:1006
armnn_driver::GetInputFloat32
bool GetInputFloat32(const Operation &operation, uint32_t inputIndex, float &outValue, const Model &model, const ConversionData &data)
Definition: ConversionUtils.hpp:791
armnn_driver::OperandType
::android::nn::OperandType OperandType
Definition: ConversionUtils.hpp:46
armnn_driver::IsOperandConstant
bool IsOperandConstant(const Operand &operand)
Definition: ConversionUtils.hpp:698
armnn_driver::GetInputScalar
bool GetInputScalar(const Operation &operation, uint32_t inputIndex, OperandType type, OutputType &outValue, const Model &model, const ConversionData &data, bool optional=false)
Definition: ConversionUtils.hpp:742
FORWARD_LAYER_SUPPORT_FUNC
#define FORWARD_LAYER_SUPPORT_FUNC(funcName, func, backends, supported, setBackend,...)
Definition: ConversionUtils.hpp:153
Transpose.hpp
armnn_driver::ConversionData::m_Backends
const std::vector< armnn::BackendId > m_Backends
Definition: ConversionUtils.hpp:59
armnn_driver::LayerInputHandle::Disconnect
void Disconnect(armnn::IInputSlot &inputSlot)
Definition: ConversionUtils.cpp:41
armnn::INetwork::AddReshapeLayer
IConnectableLayer * AddReshapeLayer(const ReshapeDescriptor &reshapeDescriptor, const char *name=nullptr)
Adds a reshape layer to the network.
Definition: Network.cpp:467
armnn_driver::ConvertToActivation
bool ConvertToActivation(const Operation &operation, const char *operationName, const armnn::ActivationDescriptor &activationDesc, const Model &model, ConversionData &data)
Definition: ConversionUtils.cpp:592
armnn_driver::DequantizeStatus::SUCCESS
@ SUCCESS
android::nn
Definition: support_library_service.cpp:10