blob: d59af994bff9d22937b5d65a8931cb34829cb5d7 [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 "ConversionUtils.hpp"
Mike Kelly4a956582020-02-28 10:32:09 +00007#include <armnnUtils/Permute.hpp>
arovir01b0717b52018-09-05 17:03:25 +01008
9///
10/// Helper classes
11///
12
13namespace armnn_driver
14{
15
16LayerInputHandle::LayerInputHandle()
17 : m_OutputSlot(nullptr)
18 , m_Valid(false)
19{}
20
21LayerInputHandle::LayerInputHandle(bool valid, armnn::IOutputSlot* outputSlot, armnn::TensorInfo tensorInfo)
22 : m_OutputSlot(outputSlot)
23 , m_Valid(valid)
24 , m_TensorInfo(tensorInfo)
25{}
26
27bool LayerInputHandle::IsValid() const
28{
29 return m_Valid;
30}
31
32void LayerInputHandle::Connect(armnn::IInputSlot& inputSlot)
33{
Narumol Prangnawarat4d07e5e2020-04-06 16:46:21 +010034 ARMNN_ASSERT(IsValid());
arovir01b0717b52018-09-05 17:03:25 +010035 if (m_OutputSlot)
36 {
37 m_OutputSlot->Connect(inputSlot);
38 }
39}
40
Finn Williamsa4983ce2020-07-23 12:55:12 +010041void LayerInputHandle::Disconnect(armnn::IInputSlot& inputSlot)
42{
43 ARMNN_ASSERT(IsValid());
44 if (m_OutputSlot)
45 {
46 m_OutputSlot->Disconnect(inputSlot);
47 }
48}
49
arovir01b0717b52018-09-05 17:03:25 +010050const armnn::TensorInfo& LayerInputHandle::GetTensorInfo() const
51{
52 return m_TensorInfo;
53}
54
55ConstTensorPin::ConstTensorPin(bool optional)
56 : m_Optional(optional)
57{}
58
Jan Eilersa71c0632021-04-12 13:12:19 +010059ConstTensorPin::ConstTensorPin(armnn::TensorInfo& tensorInfo,
arovir01b0717b52018-09-05 17:03:25 +010060 const void* valueStart,
61 uint32_t numBytes,
62 const armnn::PermutationVector& mappings)
Jim Flynn8920cae2021-05-13 15:48:45 +010063 : m_Optional(false)
arovir01b0717b52018-09-05 17:03:25 +010064{
Jan Eilers0b7a4192020-03-09 18:20:42 +000065 armnn::IgnoreUnused(numBytes);
Colm Donelanccfeb5e2021-03-30 15:30:13 +010066 if (tensorInfo.GetNumBytes() != numBytes)
67 {
68 ALOGW("The size of ConstTensor does not match its TensorInfo.");
69 }
arovir01b0717b52018-09-05 17:03:25 +010070
71 const bool needsSwizzling = (mappings.GetSize() > 0);
72 if (needsSwizzling)
73 {
74 m_SwizzledTensorData.resize(tensorInfo.GetNumBytes());
75 SwizzleAndroidNn4dTensorToArmNn(tensorInfo, valueStart, m_SwizzledTensorData.data(), mappings);
76
Jan Eilersa71c0632021-04-12 13:12:19 +010077 m_ConstTensor = armnn::ConstTensor(tensorInfo, m_SwizzledTensorData.data());
arovir01b0717b52018-09-05 17:03:25 +010078 }
79 else
80 {
81 m_ConstTensor = armnn::ConstTensor(tensorInfo, valueStart);
82 }
83}
84
85bool ConstTensorPin::IsValid() const
86{
87 return m_ConstTensor.GetMemoryArea() != nullptr;
88}
89
90bool ConstTensorPin::IsOptional() const
91{
92 return m_Optional;
93}
94
95const armnn::ConstTensor& ConstTensorPin::GetConstTensor() const
96{
97 return m_ConstTensor;
98}
99
100const armnn::ConstTensor* ConstTensorPin::GetConstTensorPtr() const
101{
102 if (IsValid() && m_ConstTensor.GetNumElements() > 0)
103 {
104 return &m_ConstTensor;
105 }
106 // tensor is either invalid, or has no elements (indicating an optional tensor that was not provided)
107 return nullptr;
108}
109
110///
111/// Utility functions
112///
113
114armnn::IConnectableLayer* ProcessActivation(const armnn::TensorInfo& tensorInfo,
115 ActivationFn activation,
116 armnn::IConnectableLayer* prevLayer,
117 ConversionData& data)
118{
Narumol Prangnawarat4d07e5e2020-04-06 16:46:21 +0100119 ARMNN_ASSERT(prevLayer->GetNumOutputSlots() == 1);
arovir01b0717b52018-09-05 17:03:25 +0100120
121 prevLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
122
123 armnn::IConnectableLayer* activationLayer = prevLayer;
124
125 if (activation != ActivationFn::kActivationNone)
126 {
127 armnn::ActivationDescriptor activationDesc;
128 switch (activation)
129 {
130 case ActivationFn::kActivationRelu:
131 {
132 activationDesc.m_Function = armnn::ActivationFunction::ReLu;
133 break;
134 }
135 case ActivationFn::kActivationRelu1:
136 {
137 activationDesc.m_Function = armnn::ActivationFunction::BoundedReLu;
138 activationDesc.m_A = 1.0f;
139 activationDesc.m_B = -1.0f;
140 break;
141 }
142 case ActivationFn::kActivationRelu6:
143 {
144 activationDesc.m_Function = armnn::ActivationFunction::BoundedReLu;
145 activationDesc.m_A = 6.0f;
146 break;
147 }
148 case ActivationFn::kActivationSigmoid:
149 {
150 activationDesc.m_Function = armnn::ActivationFunction::Sigmoid;
151 break;
152 }
153 case ActivationFn::kActivationTanh:
154 {
155 activationDesc.m_Function = armnn::ActivationFunction::TanH;
156 activationDesc.m_A = 1.0f;
157 activationDesc.m_B = 1.0f;
158 break;
159 }
160 default:
161 {
162 Fail("%s: Invalid activation enum value %i", __func__, activation);
163 return nullptr;
164 }
165 }
166
Ferran Balaguerd30093c2019-07-09 17:04:47 +0100167 bool isSupported = false;
168 FORWARD_LAYER_SUPPORT_FUNC(__func__,
169 IsActivationSupported,
170 data.m_Backends,
171 isSupported,
172 prevLayer->GetOutputSlot(0).GetTensorInfo(),
173 tensorInfo,
174 activationDesc);
175 if (!isSupported)
arovir01b0717b52018-09-05 17:03:25 +0100176 {
177 return nullptr;
178 }
179
180 activationLayer = data.m_Network->AddActivationLayer(activationDesc);
181
182 prevLayer->GetOutputSlot(0).Connect(activationLayer->GetInputSlot(0));
183 activationLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
184 }
185
186 return activationLayer;
187}
188
Nattapat Chaimanowongd5fd9762019-04-04 13:33:10 +0100189} // namespace armnn_driver