blob: 7eb7343e42134d5edbc238f83a82f1ee7221d3d3 [file] [log] [blame]
arovir01b0717b52018-09-05 17:03:25 +01001//
Mike Kellye2d611e2021-10-14 12:35:58 +01002// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
arovir01b0717b52018-09-05 17:03:25 +01003// 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{
Mike Kellye2d611e2021-10-14 12:35:58 +010034 if (!IsValid())
35 {
36 throw armnn::RuntimeException("LayerInputHandle is invalid");
37 }
38
arovir01b0717b52018-09-05 17:03:25 +010039 if (m_OutputSlot)
40 {
41 m_OutputSlot->Connect(inputSlot);
42 }
43}
44
Finn Williamsa4983ce2020-07-23 12:55:12 +010045void LayerInputHandle::Disconnect(armnn::IInputSlot& inputSlot)
46{
Mike Kellye2d611e2021-10-14 12:35:58 +010047 if (!IsValid())
48 {
49 throw armnn::RuntimeException("LayerInputHandle is invalid");
50 }
Finn Williamsa4983ce2020-07-23 12:55:12 +010051 if (m_OutputSlot)
52 {
53 m_OutputSlot->Disconnect(inputSlot);
54 }
55}
56
arovir01b0717b52018-09-05 17:03:25 +010057const armnn::TensorInfo& LayerInputHandle::GetTensorInfo() const
58{
59 return m_TensorInfo;
60}
61
62ConstTensorPin::ConstTensorPin(bool optional)
63 : m_Optional(optional)
64{}
65
Jan Eilersa71c0632021-04-12 13:12:19 +010066ConstTensorPin::ConstTensorPin(armnn::TensorInfo& tensorInfo,
arovir01b0717b52018-09-05 17:03:25 +010067 const void* valueStart,
68 uint32_t numBytes,
69 const armnn::PermutationVector& mappings)
Jim Flynn8920cae2021-05-13 15:48:45 +010070 : m_Optional(false)
arovir01b0717b52018-09-05 17:03:25 +010071{
Jan Eilers0b7a4192020-03-09 18:20:42 +000072 armnn::IgnoreUnused(numBytes);
Colm Donelanccfeb5e2021-03-30 15:30:13 +010073 if (tensorInfo.GetNumBytes() != numBytes)
74 {
75 ALOGW("The size of ConstTensor does not match its TensorInfo.");
76 }
arovir01b0717b52018-09-05 17:03:25 +010077
78 const bool needsSwizzling = (mappings.GetSize() > 0);
79 if (needsSwizzling)
80 {
81 m_SwizzledTensorData.resize(tensorInfo.GetNumBytes());
82 SwizzleAndroidNn4dTensorToArmNn(tensorInfo, valueStart, m_SwizzledTensorData.data(), mappings);
83
Jan Eilersa71c0632021-04-12 13:12:19 +010084 m_ConstTensor = armnn::ConstTensor(tensorInfo, m_SwizzledTensorData.data());
arovir01b0717b52018-09-05 17:03:25 +010085 }
86 else
87 {
88 m_ConstTensor = armnn::ConstTensor(tensorInfo, valueStart);
89 }
90}
91
92bool ConstTensorPin::IsValid() const
93{
94 return m_ConstTensor.GetMemoryArea() != nullptr;
95}
96
97bool ConstTensorPin::IsOptional() const
98{
99 return m_Optional;
100}
101
102const armnn::ConstTensor& ConstTensorPin::GetConstTensor() const
103{
104 return m_ConstTensor;
105}
106
107const armnn::ConstTensor* ConstTensorPin::GetConstTensorPtr() const
108{
109 if (IsValid() && m_ConstTensor.GetNumElements() > 0)
110 {
111 return &m_ConstTensor;
112 }
113 // tensor is either invalid, or has no elements (indicating an optional tensor that was not provided)
114 return nullptr;
115}
116
117///
118/// Utility functions
119///
120
121armnn::IConnectableLayer* ProcessActivation(const armnn::TensorInfo& tensorInfo,
122 ActivationFn activation,
123 armnn::IConnectableLayer* prevLayer,
124 ConversionData& data)
125{
Mike Kellye2d611e2021-10-14 12:35:58 +0100126 if (prevLayer->GetNumOutputSlots() != 1)
127 {
128 Fail("%s: Incorrect Number of OutputSlots expected 1 was %i", __func__, prevLayer->GetNumOutputSlots());
129 return nullptr;
130 }
arovir01b0717b52018-09-05 17:03:25 +0100131 prevLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
132
133 armnn::IConnectableLayer* activationLayer = prevLayer;
134
135 if (activation != ActivationFn::kActivationNone)
136 {
137 armnn::ActivationDescriptor activationDesc;
138 switch (activation)
139 {
140 case ActivationFn::kActivationRelu:
141 {
142 activationDesc.m_Function = armnn::ActivationFunction::ReLu;
143 break;
144 }
145 case ActivationFn::kActivationRelu1:
146 {
147 activationDesc.m_Function = armnn::ActivationFunction::BoundedReLu;
148 activationDesc.m_A = 1.0f;
149 activationDesc.m_B = -1.0f;
150 break;
151 }
152 case ActivationFn::kActivationRelu6:
153 {
154 activationDesc.m_Function = armnn::ActivationFunction::BoundedReLu;
155 activationDesc.m_A = 6.0f;
156 break;
157 }
158 case ActivationFn::kActivationSigmoid:
159 {
160 activationDesc.m_Function = armnn::ActivationFunction::Sigmoid;
161 break;
162 }
163 case ActivationFn::kActivationTanh:
164 {
165 activationDesc.m_Function = armnn::ActivationFunction::TanH;
166 activationDesc.m_A = 1.0f;
167 activationDesc.m_B = 1.0f;
168 break;
169 }
170 default:
171 {
172 Fail("%s: Invalid activation enum value %i", __func__, activation);
173 return nullptr;
174 }
175 }
176
Ferran Balaguerd30093c2019-07-09 17:04:47 +0100177 bool isSupported = false;
178 FORWARD_LAYER_SUPPORT_FUNC(__func__,
179 IsActivationSupported,
180 data.m_Backends,
181 isSupported,
182 prevLayer->GetOutputSlot(0).GetTensorInfo(),
183 tensorInfo,
184 activationDesc);
185 if (!isSupported)
arovir01b0717b52018-09-05 17:03:25 +0100186 {
187 return nullptr;
188 }
189
190 activationLayer = data.m_Network->AddActivationLayer(activationDesc);
191
192 prevLayer->GetOutputSlot(0).Connect(activationLayer->GetInputSlot(0));
193 activationLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
194 }
195
196 return activationLayer;
197}
198
Nattapat Chaimanowongd5fd9762019-04-04 13:33:10 +0100199} // namespace armnn_driver