blob: 704b6c35c11ba514b148c6fea233eadf0b8d9c24 [file] [log] [blame]
Kevin May43a799c2019-02-08 16:31:42 +00001//
Finn Williams2605b232020-06-10 15:53:46 +01002// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
Kevin May43a799c2019-02-08 16:31:42 +00003// SPDX-License-Identifier: MIT
4//
5
Derek Lamberti0028d1b2019-02-20 13:57:42 +00006#include "Deserializer.hpp"
Kevin May43a799c2019-02-08 16:31:42 +00007
Matthew Benthamff130e22020-01-17 11:47:42 +00008#include <armnn/Descriptors.hpp>
Kevin May43a799c2019-02-08 16:31:42 +00009#include <armnn/Exceptions.hpp>
Matthew Benthamff130e22020-01-17 11:47:42 +000010#include <armnn/TypesUtils.hpp>
11#include <armnn/LstmParams.hpp>
12#include <armnn/QuantizedLstmParams.hpp>
Simon Obutedb5804e2022-04-14 15:49:52 +010013#include <armnn/Logging.hpp>
Kevin May43a799c2019-02-08 16:31:42 +000014
Matteo Martincighe011d202019-11-28 11:35:47 +000015#include <armnnUtils/Permute.hpp>
Mike Kellyc9ea45a2020-02-28 18:11:58 +000016#include <armnnUtils/Transpose.hpp>
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010017#include <armnn/utility/Assert.hpp>
Jan Eilers8eb25602020-03-09 12:13:48 +000018#include <armnn/utility/IgnoreUnused.hpp>
Matthew Sloyan0663d662020-09-14 11:47:26 +010019#include <armnn/utility/NumericCast.hpp>
Matteo Martincighe011d202019-11-28 11:35:47 +000020
Kevin May43a799c2019-02-08 16:31:42 +000021#include <ParserHelper.hpp>
Kevin May43a799c2019-02-08 16:31:42 +000022#include <VerificationHelpers.hpp>
23
Colm Donelan5b5c2222020-09-09 12:48:16 +010024#include <fmt/format.h>
Kevin May43a799c2019-02-08 16:31:42 +000025
Kevin May43a799c2019-02-08 16:31:42 +000026#include <fstream>
Saoirse Stewart263829c2019-02-19 15:54:14 +000027#include <algorithm>
28#include <limits>
29#include <numeric>
Kevin May43a799c2019-02-08 16:31:42 +000030
31using armnn::ParseException;
32using namespace armnn;
Derek Lamberti0028d1b2019-02-20 13:57:42 +000033using namespace armnnSerializer;
Kevin May43a799c2019-02-08 16:31:42 +000034
Derek Lamberti0028d1b2019-02-20 13:57:42 +000035namespace armnnDeserializer
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000036{
Kevin May43a799c2019-02-08 16:31:42 +000037
Finn Williams85d36712021-01-26 22:30:06 +000038IDeserializer::IDeserializer() : pDeserializerImpl(new DeserializerImpl()){}
39
40IDeserializer::~IDeserializer() = default;
41
42IDeserializer *IDeserializer::CreateRaw()
43{
44 return new IDeserializer();
45}
46
47IDeserializerPtr IDeserializer::Create()
48{
49 return IDeserializerPtr(CreateRaw(), &IDeserializer::Destroy);
50}
51
52void IDeserializer::Destroy(IDeserializer *parser)
53{
54 delete parser;
55}
56
57armnn::INetworkPtr IDeserializer::CreateNetworkFromBinary(const std::vector<uint8_t> &binaryContent)
58{
59 return pDeserializerImpl->CreateNetworkFromBinary(binaryContent);
60}
61
62armnn::INetworkPtr IDeserializer::CreateNetworkFromBinary(std::istream &binaryContent)
63{
64 return pDeserializerImpl->CreateNetworkFromBinary(binaryContent);
65}
66
67BindingPointInfo IDeserializer::GetNetworkInputBindingInfo(unsigned int layerId, const std::string &name) const
68{
69 return pDeserializerImpl->GetNetworkInputBindingInfo(layerId, name);
70}
71
72BindingPointInfo IDeserializer::GetNetworkOutputBindingInfo(unsigned int layerId, const std::string &name) const
73{
74 return pDeserializerImpl->GetNetworkOutputBindingInfo(layerId, name);
75}
76
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000077namespace
78{
Kevin May43a799c2019-02-08 16:31:42 +000079
80const uint32_t VIRTUAL_LAYER_ID = std::numeric_limits<uint32_t>::max();
81
Finn Williams85d36712021-01-26 22:30:06 +000082 void CheckGraph(const GraphPtr& graph,
Kevin May43a799c2019-02-08 16:31:42 +000083 unsigned int layersIndex,
84 const CheckLocation& location)
85{
86 if (graph->layers() == nullptr)
87 {
Colm Donelan5b5c2222020-09-09 12:48:16 +010088 throw ParseException(fmt::format("{0} was called with invalid (null) graph. "
89 "Possible reason is that the graph is not yet loaded and Unpack(ed). "
90 "layers:{1} at {2}",
91 location.m_Function,
92 layersIndex,
93 location.FileLine()));
Kevin May43a799c2019-02-08 16:31:42 +000094 }
95 else if (layersIndex >= graph->layers()->size())
96 {
Colm Donelan5b5c2222020-09-09 12:48:16 +010097 throw ParseException(fmt::format("{0} was called with an invalid layers index. layers:{1} at {2}",
98 location.m_Function,
99 layersIndex,
100 location.FileLine()));
Kevin May43a799c2019-02-08 16:31:42 +0000101 }
102}
103
Finn Williams85d36712021-01-26 22:30:06 +0000104void CheckLayers(const GraphPtr& graph,
Kevin May43a799c2019-02-08 16:31:42 +0000105 unsigned int layersIndex,
106 unsigned int layerIndex,
107 const CheckLocation& location)
108{
109 if (graph->layers() == nullptr)
110 {
Colm Donelan5b5c2222020-09-09 12:48:16 +0100111 throw ParseException(fmt::format("{0} was called with invalid (null) graph. "
112 "Possible reason is that the graph is not yet loaded and Unpack(ed). "
113 "layers:{1} at {2}",
114 location.m_Function,
115 layersIndex,
116 location.FileLine()));
Kevin May43a799c2019-02-08 16:31:42 +0000117 }
118 else if (layersIndex >= graph->layers()->size())
119 {
Colm Donelan5b5c2222020-09-09 12:48:16 +0100120 throw ParseException(fmt::format("{0} was called with an invalid layers index. "
121 "layers:{1} at {2}",
122 location.m_Function,
123 layersIndex,
124 location.FileLine()));
Kevin May43a799c2019-02-08 16:31:42 +0000125 }
126 else if (layerIndex >= graph->layers()[layersIndex].size()
127 && layerIndex != VIRTUAL_LAYER_ID)
128 {
Colm Donelan5b5c2222020-09-09 12:48:16 +0100129 throw ParseException(fmt::format("{0} was called with an invalid layer index. "
130 "layers:{1} layer:{2} at {3}",
131 location.m_Function,
132 layersIndex,
133 layerIndex,
134 location.FileLine()));
Kevin May43a799c2019-02-08 16:31:42 +0000135 }
136}
137
Finn Williams85d36712021-01-26 22:30:06 +0000138void CheckTensorPtr(TensorRawPtr rawPtr,
Kevin May43a799c2019-02-08 16:31:42 +0000139 const CheckLocation& location)
140{
141 if (rawPtr == nullptr)
142 {
Colm Donelan5b5c2222020-09-09 12:48:16 +0100143 throw ParseException(fmt::format("{0} was called with a null tensor pointer. at {1}",
144 location.m_Function,
145 location.FileLine()));
Kevin May43a799c2019-02-08 16:31:42 +0000146 }
147}
148
Finn Williams85d36712021-01-26 22:30:06 +0000149void CheckConstTensorPtr(ConstTensorRawPtr rawPtr,
Mike Kellya0766c32019-02-19 17:22:07 +0000150 const CheckLocation& location)
151{
152 if (rawPtr == nullptr)
153 {
Colm Donelan5b5c2222020-09-09 12:48:16 +0100154 throw ParseException(fmt::format("{0} was called with a null const tensor pointer. at {1}",
155 location.m_Function,
156 location.FileLine()));
Mike Kellya0766c32019-02-19 17:22:07 +0000157 }
158}
159
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000160void CheckConstTensorSize(const unsigned int constTensorSize,
161 const unsigned int tensorSize,
162 const CheckLocation& location)
163{
164 if (constTensorSize != tensorSize)
165 {
Colm Donelan5b5c2222020-09-09 12:48:16 +0100166 throw ParseException(fmt::format("{0} wrong number of components supplied to tensor. at:{1}",
167 location.m_Function,
168 location.FileLine()));
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000169 }
170}
171
Kevin May43a799c2019-02-08 16:31:42 +0000172#define CHECK_TENSOR_PTR(TENSOR_PTR) \
173 CheckTensorPtr(TENSOR_PTR, CHECK_LOCATION())
174
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000175#define CHECK_CONST_TENSOR_SIZE(CONST_TENSOR_SIZE, TENSOR_SIZE) \
176 CheckConstTensorSize(CONST_TENSOR_SIZE, TENSOR_SIZE, CHECK_LOCATION())
177
Mike Kellya0766c32019-02-19 17:22:07 +0000178#define CHECK_CONST_TENSOR_PTR(TENSOR_PTR) \
179 CheckConstTensorPtr(TENSOR_PTR, CHECK_LOCATION())
180
Kevin May43a799c2019-02-08 16:31:42 +0000181#define CHECK_LAYERS(GRAPH, LAYERS_INDEX, LAYER_INDEX) \
182 CheckLayers(GRAPH, LAYERS_INDEX, LAYER_INDEX, CHECK_LOCATION())
183
184#define CHECK_GRAPH(GRAPH, LAYERS_INDEX) \
185 CheckGraph(GRAPH, LAYERS_INDEX, CHECK_LOCATION())
186}
187
Saoirse Stewart263829c2019-02-19 15:54:14 +0000188bool CheckShape(const armnn::TensorShape& actual, const std::vector<uint32_t>& expected)
189{
190 const unsigned int actualSize = actual.GetNumDimensions();
191 if (actualSize != expected.size())
192 {
193 return false;
194 }
195
196 for (unsigned int i = 0u; i < actualSize; i++)
197 {
198 if (actual[i] != static_cast<unsigned int>(expected[i]))
199 {
200 return false;
201 }
202 }
203
204 return true;
205}
206
Finn Williams85d36712021-01-26 22:30:06 +0000207IDeserializer::DeserializerImpl::DeserializerImpl()
Kevin May43a799c2019-02-08 16:31:42 +0000208: m_Network(nullptr, nullptr),
209//May require LayerType_Max to be included
Finn Williams85d36712021-01-26 22:30:06 +0000210m_ParserFunctions(Layer_MAX+1, &IDeserializer::DeserializerImpl::ParseUnsupportedLayer)
Kevin May43a799c2019-02-08 16:31:42 +0000211{
212 // register supported layers
Finn Williams85d36712021-01-26 22:30:06 +0000213 m_ParserFunctions[Layer_AbsLayer] = &DeserializerImpl::ParseAbs;
214 m_ParserFunctions[Layer_ActivationLayer] = &DeserializerImpl::ParseActivation;
215 m_ParserFunctions[Layer_AdditionLayer] = &DeserializerImpl::ParseAdd;
216 m_ParserFunctions[Layer_ArgMinMaxLayer] = &DeserializerImpl::ParseArgMinMax;
217 m_ParserFunctions[Layer_BatchToSpaceNdLayer] = &DeserializerImpl::ParseBatchToSpaceNd;
218 m_ParserFunctions[Layer_BatchNormalizationLayer] = &DeserializerImpl::ParseBatchNormalization;
mathad01b392e982021-04-07 12:07:30 +0100219 m_ParserFunctions[Layer_CastLayer] = &DeserializerImpl::ParseCast;
Simon Obute51f67772021-09-03 15:50:13 +0100220 m_ParserFunctions[Layer_ChannelShuffleLayer] = &DeserializerImpl::ParseChannelShuffle;
221 m_ParserFunctions[Layer_ComparisonLayer] = &DeserializerImpl::ParseComparison;
Finn Williams85d36712021-01-26 22:30:06 +0000222 m_ParserFunctions[Layer_ConcatLayer] = &DeserializerImpl::ParseConcat;
223 m_ParserFunctions[Layer_ConstantLayer] = &DeserializerImpl::ParseConstant;
224 m_ParserFunctions[Layer_Convolution2dLayer] = &DeserializerImpl::ParseConvolution2d;
Matthew Sloyanb63a3112021-09-08 13:05:51 +0100225 m_ParserFunctions[Layer_Convolution3dLayer] = &DeserializerImpl::ParseConvolution3d;
Finn Williams85d36712021-01-26 22:30:06 +0000226 m_ParserFunctions[Layer_DepthToSpaceLayer] = &DeserializerImpl::ParseDepthToSpace;
227 m_ParserFunctions[Layer_DepthwiseConvolution2dLayer] = &DeserializerImpl::ParseDepthwiseConvolution2d;
228 m_ParserFunctions[Layer_DequantizeLayer] = &DeserializerImpl::ParseDequantize;
229 m_ParserFunctions[Layer_DetectionPostProcessLayer] = &DeserializerImpl::ParseDetectionPostProcess;
230 m_ParserFunctions[Layer_DivisionLayer] = &DeserializerImpl::ParseDivision;
231 m_ParserFunctions[Layer_ElementwiseUnaryLayer] = &DeserializerImpl::ParseElementwiseUnary;
232 m_ParserFunctions[Layer_EqualLayer] = &DeserializerImpl::ParseEqual;
233 m_ParserFunctions[Layer_FullyConnectedLayer] = &DeserializerImpl::ParseFullyConnected;
234 m_ParserFunctions[Layer_FillLayer] = &DeserializerImpl::ParseFill;
235 m_ParserFunctions[Layer_FloorLayer] = &DeserializerImpl::ParseFloor;
236 m_ParserFunctions[Layer_GatherLayer] = &DeserializerImpl::ParseGather;
Teresa Charlin6966bfa2022-04-25 17:14:50 +0100237 m_ParserFunctions[Layer_GatherNdLayer] = &DeserializerImpl::ParseGatherNd;
Finn Williams85d36712021-01-26 22:30:06 +0000238 m_ParserFunctions[Layer_GreaterLayer] = &DeserializerImpl::ParseGreater;
239 m_ParserFunctions[Layer_InstanceNormalizationLayer] = &DeserializerImpl::ParseInstanceNormalization;
240 m_ParserFunctions[Layer_L2NormalizationLayer] = &DeserializerImpl::ParseL2Normalization;
241 m_ParserFunctions[Layer_LogicalBinaryLayer] = &DeserializerImpl::ParseLogicalBinary;
242 m_ParserFunctions[Layer_LogSoftmaxLayer] = &DeserializerImpl::ParseLogSoftmax;
243 m_ParserFunctions[Layer_LstmLayer] = &DeserializerImpl::ParseLstm;
244 m_ParserFunctions[Layer_MaximumLayer] = &DeserializerImpl::ParseMaximum;
245 m_ParserFunctions[Layer_MeanLayer] = &DeserializerImpl::ParseMean;
246 m_ParserFunctions[Layer_MinimumLayer] = &DeserializerImpl::ParseMinimum;
247 m_ParserFunctions[Layer_MergeLayer] = &DeserializerImpl::ParseMerge;
248 m_ParserFunctions[Layer_MergerLayer] = &DeserializerImpl::ParseConcat;
249 m_ParserFunctions[Layer_MultiplicationLayer] = &DeserializerImpl::ParseMultiplication;
250 m_ParserFunctions[Layer_NormalizationLayer] = &DeserializerImpl::ParseNormalization;
251 m_ParserFunctions[Layer_PadLayer] = &DeserializerImpl::ParsePad;
252 m_ParserFunctions[Layer_PermuteLayer] = &DeserializerImpl::ParsePermute;
253 m_ParserFunctions[Layer_Pooling2dLayer] = &DeserializerImpl::ParsePooling2d;
Tamas Nyirid998a1c2021-11-05 14:55:33 +0000254 m_ParserFunctions[Layer_Pooling3dLayer] = &DeserializerImpl::ParsePooling3d;
Finn Williams85d36712021-01-26 22:30:06 +0000255 m_ParserFunctions[Layer_PreluLayer] = &DeserializerImpl::ParsePrelu;
256 m_ParserFunctions[Layer_QLstmLayer] = &DeserializerImpl::ParseQLstm;
257 m_ParserFunctions[Layer_QuantizeLayer] = &DeserializerImpl::ParseQuantize;
258 m_ParserFunctions[Layer_QuantizedLstmLayer] = &DeserializerImpl::ParseQuantizedLstm;
259 m_ParserFunctions[Layer_RankLayer] = &DeserializerImpl::ParseRank;
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +0000260 m_ParserFunctions[Layer_ReduceLayer] = &DeserializerImpl::ParseReduce;
Finn Williams85d36712021-01-26 22:30:06 +0000261 m_ParserFunctions[Layer_ReshapeLayer] = &DeserializerImpl::ParseReshape;
262 m_ParserFunctions[Layer_ResizeBilinearLayer] = &DeserializerImpl::ParseResizeBilinear;
263 m_ParserFunctions[Layer_ResizeLayer] = &DeserializerImpl::ParseResize;
264 m_ParserFunctions[Layer_RsqrtLayer] = &DeserializerImpl::ParseRsqrt;
Keith Davis3ae3f972021-05-21 16:33:48 +0100265 m_ParserFunctions[Layer_ShapeLayer] = &DeserializerImpl::ParseShape;
Finn Williams85d36712021-01-26 22:30:06 +0000266 m_ParserFunctions[Layer_SliceLayer] = &DeserializerImpl::ParseSlice;
267 m_ParserFunctions[Layer_SoftmaxLayer] = &DeserializerImpl::ParseSoftmax;
268 m_ParserFunctions[Layer_SpaceToBatchNdLayer] = &DeserializerImpl::ParseSpaceToBatchNd;
269 m_ParserFunctions[Layer_SpaceToDepthLayer] = &DeserializerImpl::ParseSpaceToDepth;
270 m_ParserFunctions[Layer_SplitterLayer] = &DeserializerImpl::ParseSplitter;
271 m_ParserFunctions[Layer_StackLayer] = &DeserializerImpl::ParseStack;
272 m_ParserFunctions[Layer_StandInLayer] = &DeserializerImpl::ParseStandIn;
273 m_ParserFunctions[Layer_StridedSliceLayer] = &DeserializerImpl::ParseStridedSlice;
274 m_ParserFunctions[Layer_SubtractionLayer] = &DeserializerImpl::ParseSubtraction;
275 m_ParserFunctions[Layer_SwitchLayer] = &DeserializerImpl::ParseSwitch;
276 m_ParserFunctions[Layer_TransposeConvolution2dLayer] = &DeserializerImpl::ParseTransposeConvolution2d;
277 m_ParserFunctions[Layer_TransposeLayer] = &DeserializerImpl::ParseTranspose;
Narumol Prangnawarata0162e12021-07-23 14:47:49 +0100278 m_ParserFunctions[Layer_UnidirectionalSequenceLstmLayer] = &DeserializerImpl::ParseUnidirectionalSequenceLstm;
Kevin May43a799c2019-02-08 16:31:42 +0000279}
280
Finn Williams85d36712021-01-26 22:30:06 +0000281LayerBaseRawPtr IDeserializer::DeserializerImpl::GetBaseLayer(const GraphPtr& graphPtr, unsigned int layerIndex)
Kevin May43a799c2019-02-08 16:31:42 +0000282{
283 auto layerType = graphPtr->layers()->Get(layerIndex)->layer_type();
284
285 switch(layerType)
286 {
FinnWilliamsArm4ffcc8f2019-09-05 14:34:20 +0100287 case Layer::Layer_AbsLayer:
288 return graphPtr->layers()->Get(layerIndex)->layer_as_AbsLayer()->base();
Mike Kellyaf484012019-02-20 16:53:11 +0000289 case Layer::Layer_ActivationLayer:
290 return graphPtr->layers()->Get(layerIndex)->layer_as_ActivationLayer()->base();
Kevin May43a799c2019-02-08 16:31:42 +0000291 case Layer::Layer_AdditionLayer:
292 return graphPtr->layers()->Get(layerIndex)->layer_as_AdditionLayer()->base();
Narumol Prangnawarat0cfcf232019-09-09 17:16:24 +0100293 case Layer::Layer_ArgMinMaxLayer:
294 return graphPtr->layers()->Get(layerIndex)->layer_as_ArgMinMaxLayer()->base();
Nattapat Chaimanowong6b4ed982019-02-26 17:24:13 +0000295 case Layer::Layer_BatchToSpaceNdLayer:
296 return graphPtr->layers()->Get(layerIndex)->layer_as_BatchToSpaceNdLayer()->base();
ruoyan018e7fa232019-02-28 15:09:07 +0000297 case Layer::Layer_BatchNormalizationLayer:
298 return graphPtr->layers()->Get(layerIndex)->layer_as_BatchNormalizationLayer()->base();
mathad01b392e982021-04-07 12:07:30 +0100299 case Layer::Layer_CastLayer:
300 return graphPtr->layers()->Get(layerIndex)->layer_as_CastLayer()->base();
Simon Obute51f67772021-09-03 15:50:13 +0100301 case Layer::Layer_ChannelShuffleLayer:
302 return graphPtr->layers()->Get(layerIndex)->layer_as_ChannelShuffleLayer()->base();
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100303 case Layer::Layer_ComparisonLayer:
304 return graphPtr->layers()->Get(layerIndex)->layer_as_ComparisonLayer()->base();
Jim Flynne242f2d2019-05-22 14:24:13 +0100305 case Layer::Layer_ConcatLayer:
306 return graphPtr->layers()->Get(layerIndex)->layer_as_ConcatLayer()->base();
Conor Kennedy76277882019-02-26 08:29:54 +0000307 case Layer::Layer_ConstantLayer:
308 return graphPtr->layers()->Get(layerIndex)->layer_as_ConstantLayer()->base();
Mike Kellya0766c32019-02-19 17:22:07 +0000309 case Layer::Layer_Convolution2dLayer:
310 return graphPtr->layers()->Get(layerIndex)->layer_as_Convolution2dLayer()->base();
Matthew Sloyanb63a3112021-09-08 13:05:51 +0100311 case Layer::Layer_Convolution3dLayer:
312 return graphPtr->layers()->Get(layerIndex)->layer_as_Convolution3dLayer()->base();
Aron Virginas-Tarda9d2d32019-09-20 10:42:02 +0100313 case Layer::Layer_DepthToSpaceLayer:
314 return graphPtr->layers()->Get(layerIndex)->layer_as_DepthToSpaceLayer()->base();
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000315 case Layer::Layer_DepthwiseConvolution2dLayer:
316 return graphPtr->layers()->Get(layerIndex)->layer_as_DepthwiseConvolution2dLayer()->base();
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000317 case Layer::Layer_DequantizeLayer:
318 return graphPtr->layers()->Get(layerIndex)->layer_as_DequantizeLayer()->base();
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000319 case Layer::Layer_DetectionPostProcessLayer:
320 return graphPtr->layers()->Get(layerIndex)->layer_as_DetectionPostProcessLayer()->base();
Éanna Ó Catháin58885892019-02-27 16:16:39 +0000321 case Layer::Layer_DivisionLayer:
322 return graphPtr->layers()->Get(layerIndex)->layer_as_DivisionLayer()->base();
Nattapat Chaimanowong235cea52019-02-28 16:27:30 +0000323 case Layer::Layer_EqualLayer:
324 return graphPtr->layers()->Get(layerIndex)->layer_as_EqualLayer()->base();
James Conroyaba90cd2020-11-06 16:28:18 +0000325 case Layer::Layer_ElementwiseUnaryLayer:
326 return graphPtr->layers()->Get(layerIndex)->layer_as_ElementwiseUnaryLayer()->base();
Sadik Armagandbb0c0c2019-02-21 09:01:41 +0000327 case Layer::Layer_FullyConnectedLayer:
328 return graphPtr->layers()->Get(layerIndex)->layer_as_FullyConnectedLayer()->base();
Keith Davis300ad562020-06-04 16:34:23 +0100329 case Layer::Layer_FillLayer:
330 return graphPtr->layers()->Get(layerIndex)->layer_as_FillLayer()->base();
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000331 case Layer::Layer_FloorLayer:
332 return graphPtr->layers()->Get(layerIndex)->layer_as_FloorLayer()->base();
Saoirse Stewarta1ed73a2019-03-04 13:40:12 +0000333 case Layer::Layer_GatherLayer:
334 return graphPtr->layers()->Get(layerIndex)->layer_as_GatherLayer()->base();
Teresa Charlin6966bfa2022-04-25 17:14:50 +0100335 case Layer::Layer_GatherNdLayer:
336 return graphPtr->layers()->Get(layerIndex)->layer_as_GatherNdLayer()->base();
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000337 case Layer::Layer_GreaterLayer:
338 return graphPtr->layers()->Get(layerIndex)->layer_as_GreaterLayer()->base();
Kevin May43a799c2019-02-08 16:31:42 +0000339 case Layer::Layer_InputLayer:
Aron Virginas-Tar0fe32452019-02-28 13:12:47 +0000340 return graphPtr->layers()->Get(layerIndex)->layer_as_InputLayer()->base()->base();
Aron Virginas-Tar781ced92019-10-03 11:15:39 +0100341 case Layer::Layer_InstanceNormalizationLayer:
342 return graphPtr->layers()->Get(layerIndex)->layer_as_InstanceNormalizationLayer()->base();
Narumol Prangnawarat495701f2019-03-07 17:31:34 +0000343 case Layer::Layer_L2NormalizationLayer:
344 return graphPtr->layers()->Get(layerIndex)->layer_as_L2NormalizationLayer()->base();
James Conroyaba90cd2020-11-06 16:28:18 +0000345 case Layer::Layer_LogicalBinaryLayer:
346 return graphPtr->layers()->Get(layerIndex)->layer_as_LogicalBinaryLayer()->base();
Sadik Armagan26257852019-10-14 13:00:47 +0100347 case Layer::Layer_LogSoftmaxLayer:
348 return graphPtr->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->base();
Jim Flynn11af3752019-03-19 17:22:29 +0000349 case Layer::Layer_LstmLayer:
350 return graphPtr->layers()->Get(layerIndex)->layer_as_LstmLayer()->base();
Sadik Armaganac97c8c2019-03-04 17:44:21 +0000351 case Layer::Layer_MeanLayer:
352 return graphPtr->layers()->Get(layerIndex)->layer_as_MeanLayer()->base();
Aron Virginas-Tar0fe32452019-02-28 13:12:47 +0000353 case Layer::Layer_MinimumLayer:
354 return graphPtr->layers()->Get(layerIndex)->layer_as_MinimumLayer()->base();
Aron Virginas-Tar377351e2019-02-27 14:42:31 +0000355 case Layer::Layer_MaximumLayer:
356 return graphPtr->layers()->Get(layerIndex)->layer_as_MaximumLayer()->base();
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +0100357 case Layer::Layer_MergeLayer:
358 return graphPtr->layers()->Get(layerIndex)->layer_as_MergeLayer()->base();
Jim Flynnac25a1b2019-02-28 10:40:49 +0000359 case Layer::Layer_MergerLayer:
360 return graphPtr->layers()->Get(layerIndex)->layer_as_MergerLayer()->base();
Sadik Armagan5f450272019-02-12 14:31:45 +0000361 case Layer::Layer_MultiplicationLayer:
362 return graphPtr->layers()->Get(layerIndex)->layer_as_MultiplicationLayer()->base();
Nina Drozd57728782019-02-27 10:53:27 +0000363 case Layer::Layer_NormalizationLayer:
364 return graphPtr->layers()->Get(layerIndex)->layer_as_NormalizationLayer()->base();
Kevin May43a799c2019-02-08 16:31:42 +0000365 case Layer::Layer_OutputLayer:
366 return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->base();
Nattapat Chaimanowongebb0f9c2019-03-01 12:14:06 +0000367 case Layer::Layer_PadLayer:
368 return graphPtr->layers()->Get(layerIndex)->layer_as_PadLayer()->base();
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +0000369 case Layer::Layer_PermuteLayer:
370 return graphPtr->layers()->Get(layerIndex)->layer_as_PermuteLayer()->base();
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000371 case Layer::Layer_Pooling2dLayer:
372 return graphPtr->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->base();
Tamas Nyirid998a1c2021-11-05 14:55:33 +0000373 case Layer::Layer_Pooling3dLayer:
374 return graphPtr->layers()->Get(layerIndex)->layer_as_Pooling3dLayer()->base();
Ellen Norris-Thompson51982472019-06-19 11:46:21 +0100375 case Layer::Layer_PreluLayer:
376 return graphPtr->layers()->Get(layerIndex)->layer_as_PreluLayer()->base();
James Conroy8d333182020-05-13 10:27:58 +0100377 case Layer::Layer_QLstmLayer:
378 return graphPtr->layers()->Get(layerIndex)->layer_as_QLstmLayer()->base();
Derek Lamberti87acb272019-03-27 16:51:31 +0000379 case Layer::Layer_QuantizeLayer:
380 return graphPtr->layers()->Get(layerIndex)->layer_as_QuantizeLayer()->base();
Jan Eilers5b01a892019-07-23 09:47:43 +0100381 case Layer::Layer_QuantizedLstmLayer:
382 return graphPtr->layers()->Get(layerIndex)->layer_as_QuantizedLstmLayer()->base();
Finn Williams2605b232020-06-10 15:53:46 +0100383 case Layer::Layer_RankLayer:
384 return graphPtr->layers()->Get(layerIndex)->layer_as_RankLayer()->base();
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +0000385 case Layer::Layer_ReduceLayer:
386 return graphPtr->layers()->Get(layerIndex)->layer_as_ReduceLayer()->base();
Saoirse Stewart263829c2019-02-19 15:54:14 +0000387 case Layer::Layer_ReshapeLayer:
388 return graphPtr->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->base();
Nattapat Chaimanowong6522cdc2019-03-01 16:14:13 +0000389 case Layer::Layer_ResizeBilinearLayer:
390 return graphPtr->layers()->Get(layerIndex)->layer_as_ResizeBilinearLayer()->base();
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +0100391 case Layer::Layer_ResizeLayer:
392 return graphPtr->layers()->Get(layerIndex)->layer_as_ResizeLayer()->base();
Sadik Armagan8b42a382019-03-01 14:24:49 +0000393 case Layer::Layer_RsqrtLayer:
394 return graphPtr->layers()->Get(layerIndex)->layer_as_RsqrtLayer()->base();
Keith Davis3ae3f972021-05-21 16:33:48 +0100395 case Layer::Layer_ShapeLayer:
396 return graphPtr->layers()->Get(layerIndex)->layer_as_ShapeLayer()->base();
Aron Virginas-Tar2fda80b2019-09-18 13:36:52 +0100397 case Layer::Layer_SliceLayer:
398 return graphPtr->layers()->Get(layerIndex)->layer_as_SliceLayer()->base();
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000399 case Layer::Layer_SoftmaxLayer:
400 return graphPtr->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->base();
Nattapat Chaimanowong45286992019-02-26 15:53:02 +0000401 case Layer::Layer_SpaceToBatchNdLayer:
402 return graphPtr->layers()->Get(layerIndex)->layer_as_SpaceToBatchNdLayer()->base();
Aron Virginas-Taraa067142019-06-11 16:01:44 +0100403 case Layer::Layer_SpaceToDepthLayer:
404 return graphPtr->layers()->Get(layerIndex)->layer_as_SpaceToDepthLayer()->base();
Jim Flynn18ce3382019-03-08 11:08:30 +0000405 case Layer::Layer_SplitterLayer:
406 return graphPtr->layers()->Get(layerIndex)->layer_as_SplitterLayer()->base();
Matthew Jacksonb5433ee2019-07-11 15:54:20 +0100407 case Layer::Layer_StackLayer:
408 return graphPtr->layers()->Get(layerIndex)->layer_as_StackLayer()->base();
Aron Virginas-Tar85121a22019-10-23 10:41:35 +0100409 case Layer::Layer_StandInLayer:
410 return graphPtr->layers()->Get(layerIndex)->layer_as_StandInLayer()->base();
Nattapat Chaimanowongb3485212019-03-04 12:35:39 +0000411 case Layer::Layer_StridedSliceLayer:
412 return graphPtr->layers()->Get(layerIndex)->layer_as_StridedSliceLayer()->base();
Conor Kennedyda1f9752019-03-01 14:37:12 +0000413 case Layer::Layer_SubtractionLayer:
414 return graphPtr->layers()->Get(layerIndex)->layer_as_SubtractionLayer()->base();
Sadik Armaganeff363d2019-04-05 15:25:46 +0100415 case Layer::Layer_SwitchLayer:
416 return graphPtr->layers()->Get(layerIndex)->layer_as_SwitchLayer()->base();
Aron Virginas-Tarcb549302019-06-21 13:53:38 +0100417 case Layer::Layer_TransposeConvolution2dLayer:
418 return graphPtr->layers()->Get(layerIndex)->layer_as_TransposeConvolution2dLayer()->base();
Mike Kellyc9ea45a2020-02-28 18:11:58 +0000419 case Layer::Layer_TransposeLayer:
420 return graphPtr->layers()->Get(layerIndex)->layer_as_TransposeLayer()->base();
Narumol Prangnawarata0162e12021-07-23 14:47:49 +0100421 case Layer::Layer_UnidirectionalSequenceLstmLayer:
422 return graphPtr->layers()->Get(layerIndex)->layer_as_UnidirectionalSequenceLstmLayer()->base();
Kevin May43a799c2019-02-08 16:31:42 +0000423 case Layer::Layer_NONE:
424 default:
Colm Donelan5b5c2222020-09-09 12:48:16 +0100425 throw ParseException(fmt::format("Layer type {} not recognized", layerType));
Kevin May43a799c2019-02-08 16:31:42 +0000426 }
427}
428
Finn Williams85d36712021-01-26 22:30:06 +0000429std::string IDeserializer::DeserializerImpl::GetLayerName(const GraphPtr& graph, unsigned int index)
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000430{
431 auto layer = GetBaseLayer(graph, index);
432 assert(layer);
433 return layer->layerName()->str();
434}
435
Finn Williams85d36712021-01-26 22:30:06 +0000436int32_t IDeserializer::DeserializerImpl::GetBindingLayerInfo(const GraphPtr& graphPtr, unsigned int layerIndex)
Kevin May43a799c2019-02-08 16:31:42 +0000437{
438 auto layerType = graphPtr->layers()->Get(layerIndex)->layer_type();
439
440 if (layerType == Layer::Layer_InputLayer)
441 {
442 return graphPtr->layers()->Get(layerIndex)->layer_as_InputLayer()->base()->layerBindingId();
443 }
444 else if ( layerType == Layer::Layer_OutputLayer )
445 {
446 return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->layerBindingId();
447 }
448 return 0;
449}
450
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000451armnn::DataLayout ToDataLayout(armnnSerializer::DataLayout dataLayout)
Mike Kellya0766c32019-02-19 17:22:07 +0000452{
453 switch (dataLayout)
454 {
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000455 case armnnSerializer::DataLayout::DataLayout_NHWC:
Mike Kellya0766c32019-02-19 17:22:07 +0000456 return armnn::DataLayout::NHWC;
Matthew Sloyanb63a3112021-09-08 13:05:51 +0100457 case armnnSerializer::DataLayout::DataLayout_NDHWC:
458 return armnn::DataLayout::NDHWC;
Matthew Sloyan5d7b0a32021-10-18 13:07:49 +0100459 case armnnSerializer::DataLayout::DataLayout_NCDHW:
460 return armnn::DataLayout::NCDHW;
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000461 case armnnSerializer::DataLayout::DataLayout_NCHW:
Mike Kellya0766c32019-02-19 17:22:07 +0000462 default:
463 return armnn::DataLayout::NCHW;
464 }
465}
466
Mike Kellyaf484012019-02-20 16:53:11 +0000467armnn::ActivationFunction ToActivationFunction(armnnSerializer::ActivationFunction function)
468{
469 switch (function)
470 {
471 case armnnSerializer::ActivationFunction_Sigmoid:
472 return armnn::ActivationFunction::Sigmoid;
473 case armnnSerializer::ActivationFunction_TanH:
474 return armnn::ActivationFunction::TanH;
475 case armnnSerializer::ActivationFunction_Linear:
476 return armnn::ActivationFunction::Linear;
477 case armnnSerializer::ActivationFunction_ReLu:
478 return armnn::ActivationFunction::ReLu;
479 case armnnSerializer::ActivationFunction_BoundedReLu:
480 return armnn::ActivationFunction::BoundedReLu;
481 case armnnSerializer::ActivationFunction_LeakyReLu:
482 return armnn::ActivationFunction::LeakyReLu;
483 case armnnSerializer::ActivationFunction_Abs:
484 return armnn::ActivationFunction::Abs;
485 case armnnSerializer::ActivationFunction_Sqrt:
486 return armnn::ActivationFunction::Sqrt;
487 case armnnSerializer::ActivationFunction_Square:
488 return armnn::ActivationFunction::Square;
David Monahan3b3c3812020-02-25 09:03:29 +0000489 case armnnSerializer::ActivationFunction_Elu:
490 return armnn::ActivationFunction::Elu;
Colm Donelan03fbeaf2020-02-26 15:39:23 +0000491 case armnnSerializer::ActivationFunction_HardSwish:
492 return armnn::ActivationFunction::HardSwish;
Mike Kellyaf484012019-02-20 16:53:11 +0000493 default:
494 return armnn::ActivationFunction::Sigmoid;
495 }
496}
497
Narumol Prangnawarat0cfcf232019-09-09 17:16:24 +0100498armnn::ArgMinMaxFunction ToArgMinMaxFunction(armnnSerializer::ArgMinMaxFunction function)
499{
500 switch (function)
501 {
502 case armnnSerializer::ArgMinMaxFunction::ArgMinMaxFunction_Max:
503 return armnn::ArgMinMaxFunction::Max;
504 case armnnSerializer::ArgMinMaxFunction::ArgMinMaxFunction_Min:
505 default:
506 return armnn::ArgMinMaxFunction::Min;
507 }
508}
509
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100510armnn::ComparisonOperation ToComparisonOperation(armnnSerializer::ComparisonOperation operation)
511{
512 switch (operation)
513 {
514 case armnnSerializer::ComparisonOperation::ComparisonOperation_Equal:
515 return armnn::ComparisonOperation::Equal;
516 case armnnSerializer::ComparisonOperation::ComparisonOperation_Greater:
517 return armnn::ComparisonOperation::Greater;
518 case armnnSerializer::ComparisonOperation::ComparisonOperation_GreaterOrEqual:
519 return armnn::ComparisonOperation::GreaterOrEqual;
520 case armnnSerializer::ComparisonOperation::ComparisonOperation_Less:
521 return armnn::ComparisonOperation::Less;
522 case armnnSerializer::ComparisonOperation::ComparisonOperation_LessOrEqual:
523 return armnn::ComparisonOperation::LessOrEqual;
524 case armnnSerializer::ComparisonOperation::ComparisonOperation_NotEqual:
525 default:
526 return armnn::ComparisonOperation::NotEqual;
527 }
528}
529
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +0000530armnn::ReduceOperation ToReduceOperation(armnnSerializer::ReduceOperation operation)
531{
532 switch (operation)
533 {
534 case armnnSerializer::ReduceOperation::ReduceOperation_Sum:
535 return armnn::ReduceOperation::Sum;
536 case armnnSerializer::ReduceOperation::ReduceOperation_Max:
537 return armnn::ReduceOperation::Max;
538 case armnnSerializer::ReduceOperation::ReduceOperation_Mean:
539 return armnn::ReduceOperation::Mean;
540 case armnnSerializer::ReduceOperation::ReduceOperation_Min:
541 return armnn::ReduceOperation::Min;
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100542 case armnnSerializer::ReduceOperation::ReduceOperation_Prod:
543 return armnn::ReduceOperation::Prod;
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +0000544 default:
545 return armnn::ReduceOperation::Sum;
546 }
547}
548
James Conroyaba90cd2020-11-06 16:28:18 +0000549armnn::LogicalBinaryOperation ToLogicalBinaryOperation(armnnSerializer::LogicalBinaryOperation operation)
550{
551 switch (operation)
552 {
553 case armnnSerializer::LogicalBinaryOperation::LogicalBinaryOperation_LogicalAnd:
554 return armnn::LogicalBinaryOperation::LogicalAnd;
555 case armnnSerializer::LogicalBinaryOperation::LogicalBinaryOperation_LogicalOr:
556 return armnn::LogicalBinaryOperation::LogicalOr;
557 default:
558 throw armnn::InvalidArgumentException("Logical Binary operation unknown");
559 }
560}
561
josh minor4a3c6102020-01-06 16:40:46 -0600562armnn::UnaryOperation ToUnaryOperation(armnnSerializer::UnaryOperation operation)
563{
564 switch (operation)
565 {
566 case armnnSerializer::UnaryOperation::UnaryOperation_Abs:
567 return armnn::UnaryOperation::Abs;
568 case armnnSerializer::UnaryOperation::UnaryOperation_Rsqrt:
569 return armnn::UnaryOperation::Rsqrt;
570 case armnnSerializer::UnaryOperation::UnaryOperation_Sqrt:
571 return armnn::UnaryOperation::Sqrt;
572 case armnnSerializer::UnaryOperation::UnaryOperation_Exp:
573 return armnn::UnaryOperation::Exp;
574 case armnnSerializer::UnaryOperation::UnaryOperation_Neg:
575 return armnn::UnaryOperation::Neg;
James Conroyaba90cd2020-11-06 16:28:18 +0000576 case armnnSerializer::UnaryOperation::UnaryOperation_LogicalNot:
577 return armnn::UnaryOperation::LogicalNot;
Teresa Charlin50de4fa2021-05-31 18:47:33 +0100578 case armnnSerializer::UnaryOperation::UnaryOperation_Log:
579 return armnn::UnaryOperation::Log;
580 case armnnSerializer::UnaryOperation::UnaryOperation_Sin:
581 return armnn::UnaryOperation::Sin;
josh minor4a3c6102020-01-06 16:40:46 -0600582 default:
583 throw armnn::InvalidArgumentException("Unary operation unknown");
584 }
585}
586
Matthew Sloyan2e5d0b22021-10-21 14:05:31 +0100587armnn::PaddingMode ToPaddingMode(armnnSerializer::PaddingMode paddingMode)
588{
589 switch (paddingMode)
590 {
591 case armnnSerializer::PaddingMode::PaddingMode_Reflect:
592 return armnn::PaddingMode::Reflect;
593 case armnnSerializer::PaddingMode::PaddingMode_Symmetric:
594 return armnn::PaddingMode::Symmetric;
595 default:
596 return armnn::PaddingMode::Constant;
597 }
598}
599
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +0100600armnn::ResizeMethod ToResizeMethod(armnnSerializer::ResizeMethod method)
601{
602 switch (method)
603 {
604 case armnnSerializer::ResizeMethod_NearestNeighbor:
605 return armnn::ResizeMethod::NearestNeighbor;
606 case armnnSerializer::ResizeMethod_Bilinear:
Aron Virginas-Tar3c9b2702019-10-31 13:45:16 +0000607 return armnn::ResizeMethod::Bilinear;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +0100608 default:
609 return armnn::ResizeMethod::NearestNeighbor;
610 }
611}
612
Finn Williams85d36712021-01-26 22:30:06 +0000613armnn::TensorInfo ToTensorInfo(TensorRawPtr tensorPtr)
Kevin May43a799c2019-02-08 16:31:42 +0000614{
615 armnn::DataType type;
616 CHECK_TENSOR_PTR(tensorPtr);
617
618 switch (tensorPtr->dataType())
619 {
Francis Murtaghddb1d062020-03-10 13:51:45 +0000620 case DataType_QAsymmS8:
621 type = armnn::DataType::QAsymmS8;
622 break;
Sadik Armagan1a84fe32020-03-27 15:56:57 +0000623 case DataType_QSymmS8:
624 type = armnn::DataType::QSymmS8;
625 break;
Kevin May43a799c2019-02-08 16:31:42 +0000626 case DataType_QuantisedAsymm8:
Derek Lambertif90c56d2020-01-10 17:14:08 +0000627 case DataType_QAsymmU8:
628 type = armnn::DataType::QAsymmU8;
Kevin May43a799c2019-02-08 16:31:42 +0000629 break;
Derek Lambertif90c56d2020-01-10 17:14:08 +0000630 case DataType_QSymmS16:
Nattapat Chaimanowongcd5ac232019-03-19 12:26:36 +0000631 case DataType_QuantisedSymm16:
Derek Lambertif90c56d2020-01-10 17:14:08 +0000632 type = armnn::DataType::QSymmS16;
Nattapat Chaimanowongcd5ac232019-03-19 12:26:36 +0000633 break;
Mike Kellya0766c32019-02-19 17:22:07 +0000634 case DataType_Signed32:
635 type = armnn::DataType::Signed32;
636 break;
Mike Kelly1f140f72021-04-06 12:25:55 +0100637 case DataType_Signed64:
638 type = armnn::DataType::Signed64;
639 break;
Kevin May43a799c2019-02-08 16:31:42 +0000640 case DataType_Float32:
641 type = armnn::DataType::Float32;
642 break;
643 case DataType_Float16:
644 type = armnn::DataType::Float16;
645 break;
646 case DataType_Boolean:
647 type = armnn::DataType::Boolean;
648 break;
649 default:
650 {
651 CheckLocation location = CHECK_LOCATION();
Colm Donelan5b5c2222020-09-09 12:48:16 +0100652 throw ParseException(fmt::format("Unsupported data type {0} = {1}. {2}",
653 tensorPtr->dataType(),
654 EnumNameDataType(tensorPtr->dataType()),
655 location.AsString()));
Kevin May43a799c2019-02-08 16:31:42 +0000656 }
657 }
Sadik Armagan1a84fe32020-03-27 15:56:57 +0000658
Colm Donelan800b2812021-02-12 12:43:35 +0000659 float quantizationScale = tensorPtr->quantizationScale();
660 int32_t quantizationOffset = tensorPtr->quantizationOffset();
661
Finn Williams2605b232020-06-10 15:53:46 +0100662 if (tensorPtr->dimensionality() == static_cast<unsigned int>(Dimensionality::Scalar))
663 {
Colm Donelan800b2812021-02-12 12:43:35 +0000664 return armnn::TensorInfo(TensorShape{armnn::Dimensionality::Scalar},
Finn Williams2605b232020-06-10 15:53:46 +0100665 type,
666 quantizationScale,
667 quantizationOffset);
668 }
Colm Donelan800b2812021-02-12 12:43:35 +0000669 else if (tensorPtr->dimensionality() == static_cast<unsigned int>(Dimensionality::NotSpecified))
670 {
671 armnn::TensorInfo result(TensorShape{Dimensionality::NotSpecified},
672 type,
673 quantizationScale,
674 quantizationOffset);
675 return result;
676 }
Kevin May43a799c2019-02-08 16:31:42 +0000677
678 auto dimensions = tensorPtr->dimensions();
679 unsigned int size = dimensions->size();
680 std::vector<unsigned int> outputDims(dimensions->begin(), dimensions->begin() + size);
Colm Donelan800b2812021-02-12 12:43:35 +0000681 bool dimensionsSpecificity[armnn::MaxNumOfTensorDimensions];
682 std::fill_n(dimensionsSpecificity, armnn::MaxNumOfTensorDimensions, true);
683 // For backwards compatibility check if the dimensionSpecificity vector is present first.
684 // The default is to have dimensionSpecificity set to all true's anyway.
685 if (tensorPtr->dimensionSpecificity() != nullptr)
686 {
687 auto dimensionSpecificity = tensorPtr->dimensionSpecificity();
688 size = dimensionSpecificity->size();
689 for (unsigned int i = 0; i < size; ++i)
690 {
691 dimensionsSpecificity[i] = dimensionSpecificity->Get(i);
692 }
693 }
694 // Construct a TensorShape
695 TensorShape shape(size, outputDims.data(), dimensionsSpecificity);
Kevin May43a799c2019-02-08 16:31:42 +0000696
Sadik Armagan1a84fe32020-03-27 15:56:57 +0000697 auto quantizationScales = tensorPtr->quantizationScales();
Sadik Armagan1a84fe32020-03-27 15:56:57 +0000698 if (quantizationScales)
699 {
700 unsigned int quantizationScalesSize = quantizationScales->size();
701 std::vector<float> scales(quantizationScales->begin(), quantizationScales->begin() + quantizationScalesSize);
702 unsigned int quantizationDim = tensorPtr->quantizationDim();
Colm Donelan800b2812021-02-12 12:43:35 +0000703 armnn::TensorInfo result(shape,
Sadik Armagan1a84fe32020-03-27 15:56:57 +0000704 type,
705 scales,
706 quantizationDim);
707 return result;
708 }
709
Kevin May43a799c2019-02-08 16:31:42 +0000710 // two statements (on purpose) for easier debugging:
Colm Donelan800b2812021-02-12 12:43:35 +0000711 armnn::TensorInfo result(shape,
Kevin May43a799c2019-02-08 16:31:42 +0000712 type,
713 quantizationScale,
714 quantizationOffset);
Colm Donelan800b2812021-02-12 12:43:35 +0000715
Kevin May43a799c2019-02-08 16:31:42 +0000716 return result;
717}
718
Finn Williams85d36712021-01-26 22:30:06 +0000719armnn::ConstTensor ToConstTensor(ConstTensorRawPtr constTensorPtr)
Mike Kellya0766c32019-02-19 17:22:07 +0000720{
721 CHECK_CONST_TENSOR_PTR(constTensorPtr);
722 armnn::TensorInfo tensorInfo = ToTensorInfo(constTensorPtr->info());
Matthew Sloyan81beae32021-07-13 19:46:11 +0100723 tensorInfo.SetConstant();
Mike Kellya0766c32019-02-19 17:22:07 +0000724
725 switch (constTensorPtr->data_type())
726 {
727 case ConstTensorData_ByteData:
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000728 {
729 auto byteData = constTensorPtr->data_as_ByteData()->data();
730 CHECK_CONST_TENSOR_SIZE(byteData->size(), tensorInfo.GetNumElements());
731 return armnn::ConstTensor(tensorInfo, byteData->data());
732 }
Mike Kellya0766c32019-02-19 17:22:07 +0000733 case ConstTensorData_ShortData:
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000734 {
735 auto shortData = constTensorPtr->data_as_ShortData()->data();
736 CHECK_CONST_TENSOR_SIZE(shortData->size(), tensorInfo.GetNumElements());
737 return armnn::ConstTensor(tensorInfo, shortData->data());
738 }
Mike Kellya0766c32019-02-19 17:22:07 +0000739 case ConstTensorData_IntData:
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000740 {
741 auto intData = constTensorPtr->data_as_IntData()->data();
742 CHECK_CONST_TENSOR_SIZE(intData->size(), tensorInfo.GetNumElements());
743 return armnn::ConstTensor(tensorInfo, intData->data());
744 }
Mike Kellya0766c32019-02-19 17:22:07 +0000745 case ConstTensorData_LongData:
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000746 {
747 auto longData = constTensorPtr->data_as_LongData()->data();
748 CHECK_CONST_TENSOR_SIZE(longData->size(), tensorInfo.GetNumElements());
749 return armnn::ConstTensor(tensorInfo, longData->data());
750 }
Mike Kellya0766c32019-02-19 17:22:07 +0000751 default:
752 {
753 CheckLocation location = CHECK_LOCATION();
Colm Donelan5b5c2222020-09-09 12:48:16 +0100754 throw ParseException(fmt::format("Unsupported data type {0} = {1}. {2}",
755 constTensorPtr->data_type(),
756 EnumNameConstTensorData(constTensorPtr->data_type()),
757 location.AsString()));
Mike Kellya0766c32019-02-19 17:22:07 +0000758 }
759 }
760}
761
Finn Williams85d36712021-01-26 22:30:06 +0000762TensorRawPtrVector IDeserializer::DeserializerImpl::GetInputs(const GraphPtr& graphPtr, unsigned int layerIndex)
Kevin May43a799c2019-02-08 16:31:42 +0000763{
764 CHECK_LAYERS(graphPtr, 0, layerIndex);
765 auto layer = GetBaseLayer(graphPtr, layerIndex);
766 const auto& numInputs = layer->inputSlots()->size();
767
768 TensorRawPtrVector result(numInputs);
769
770 for (unsigned int i=0; i<numInputs; ++i)
771 {
772 auto inputId = CHECKED_NON_NEGATIVE(static_cast<int32_t>
773 (layer->inputSlots()->Get(i)->connection()->sourceLayerIndex()));
774 result[i] = GetBaseLayer(graphPtr, inputId)->outputSlots()->Get(0)->tensorInfo();
775 }
776 return result;
777}
778
Finn Williams85d36712021-01-26 22:30:06 +0000779TensorRawPtrVector IDeserializer::DeserializerImpl::GetOutputs(const GraphPtr& graphPtr, unsigned int layerIndex)
Kevin May43a799c2019-02-08 16:31:42 +0000780{
781 CHECK_LAYERS(graphPtr, 0, layerIndex);
782 auto layer = GetBaseLayer(graphPtr, layerIndex);
783 const auto& numOutputs = layer->outputSlots()->size();
784
785 TensorRawPtrVector result(numOutputs);
786
787 for (unsigned int i=0; i<numOutputs; ++i)
788 {
789 result[i] = layer->outputSlots()->Get(i)->tensorInfo();
790 }
791 return result;
792}
793
Finn Williams85d36712021-01-26 22:30:06 +0000794void IDeserializer::DeserializerImpl::ParseUnsupportedLayer(GraphPtr graph, unsigned int layerIndex)
Kevin May43a799c2019-02-08 16:31:42 +0000795{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000796 CHECK_LAYERS(graph, 0, layerIndex);
797 const auto layerName = GetBaseLayer(graph, layerIndex)->layerName()->c_str();
Colm Donelan5b5c2222020-09-09 12:48:16 +0100798 throw ParseException(fmt::format("Layer not supported. layerIndex: {0} "
799 "layerName: {1} / {2}",
800 layerIndex,
801 layerName,
802 CHECK_LOCATION().AsString()));
Kevin May43a799c2019-02-08 16:31:42 +0000803}
804
Finn Williams85d36712021-01-26 22:30:06 +0000805void IDeserializer::DeserializerImpl::ResetParser()
Kevin May43a799c2019-02-08 16:31:42 +0000806{
807 m_Network = armnn::INetworkPtr(nullptr, nullptr);
Derek Lamberti8ddae332019-02-21 16:29:43 +0000808 m_InputBindings.clear();
809 m_OutputBindings.clear();
Kevin May43a799c2019-02-08 16:31:42 +0000810}
811
Kevin May43a799c2019-02-08 16:31:42 +0000812
Finn Williams85d36712021-01-26 22:30:06 +0000813INetworkPtr IDeserializer::DeserializerImpl::CreateNetworkFromBinary(const std::vector<uint8_t>& binaryContent)
Kevin May43a799c2019-02-08 16:31:42 +0000814{
815 ResetParser();
Derek Lamberti8ddae332019-02-21 16:29:43 +0000816 GraphPtr graph = LoadGraphFromBinary(binaryContent.data(), binaryContent.size());
817 return CreateNetworkFromGraph(graph);
Kevin May43a799c2019-02-08 16:31:42 +0000818}
819
Finn Williams85d36712021-01-26 22:30:06 +0000820armnn::INetworkPtr IDeserializer::DeserializerImpl::CreateNetworkFromBinary(std::istream& binaryContent)
Kevin May43a799c2019-02-08 16:31:42 +0000821{
Derek Lamberti2b183fb2019-02-18 16:36:57 +0000822 ResetParser();
Simon Obutedb5804e2022-04-14 15:49:52 +0100823 if (binaryContent.fail()) {
824 ARMNN_LOG(error) << (std::string("Cannot read input"));
825 throw ParseException("Unable to read Input stream data");
826 }
827 binaryContent.seekg(0, std::ios::end);
828 const std::streamoff size = binaryContent.tellg();
829 std::vector<char> content(static_cast<size_t>(size));
830 binaryContent.seekg(0);
831 binaryContent.read(content.data(), static_cast<std::streamsize>(size));
832 GraphPtr graph = LoadGraphFromBinary(reinterpret_cast<uint8_t*>(content.data()), static_cast<size_t>(size));
Derek Lamberti8ddae332019-02-21 16:29:43 +0000833 return CreateNetworkFromGraph(graph);
Kevin May43a799c2019-02-08 16:31:42 +0000834}
835
Finn Williams85d36712021-01-26 22:30:06 +0000836GraphPtr IDeserializer::DeserializerImpl::LoadGraphFromBinary(const uint8_t* binaryContent, size_t len)
Kevin May43a799c2019-02-08 16:31:42 +0000837{
838 if (binaryContent == nullptr)
839 {
Colm Donelan5b5c2222020-09-09 12:48:16 +0100840 throw InvalidArgumentException(fmt::format("Invalid (null) binary content {}",
841 CHECK_LOCATION().AsString()));
Kevin May43a799c2019-02-08 16:31:42 +0000842 }
843 flatbuffers::Verifier verifier(binaryContent, len);
844 if (verifier.VerifyBuffer<SerializedGraph>() == false)
845 {
Colm Donelan5b5c2222020-09-09 12:48:16 +0100846 throw ParseException(fmt::format("Buffer doesn't conform to the expected Armnn "
847 "flatbuffers format. size:{0} {1}",
848 len,
849 CHECK_LOCATION().AsString()));
Kevin May43a799c2019-02-08 16:31:42 +0000850 }
851 return GetSerializedGraph(binaryContent);
852}
853
Finn Williams85d36712021-01-26 22:30:06 +0000854INetworkPtr IDeserializer::DeserializerImpl::CreateNetworkFromGraph(GraphPtr graph)
Kevin May43a799c2019-02-08 16:31:42 +0000855{
856 m_Network = INetwork::Create();
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100857 ARMNN_ASSERT(graph != nullptr);
Kevin May43a799c2019-02-08 16:31:42 +0000858 unsigned int layerIndex = 0;
Derek Lamberti8ddae332019-02-21 16:29:43 +0000859 for (AnyLayer const* layer : *graph->layers())
Kevin May43a799c2019-02-08 16:31:42 +0000860 {
861 if (layer->layer_type() != Layer_InputLayer &&
862 layer->layer_type() != Layer_OutputLayer)
863 {
864 // lookup and call the parser function
865 auto& parserFunction = m_ParserFunctions[layer->layer_type()];
Derek Lamberti8ddae332019-02-21 16:29:43 +0000866 (this->*parserFunction)(graph, layerIndex);
Kevin May43a799c2019-02-08 16:31:42 +0000867 }
868 ++layerIndex;
869 }
870
Derek Lamberti8ddae332019-02-21 16:29:43 +0000871 SetupInputLayers(graph);
872 SetupOutputLayers(graph);
Kevin May43a799c2019-02-08 16:31:42 +0000873
874 // establish the connections from the layer outputs to the inputs of the subsequent layers
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +0100875 for (auto&& graphIt : m_GraphConnections)
Kevin May43a799c2019-02-08 16:31:42 +0000876 {
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +0100877 Connections& connections = graphIt.second;
878 for (auto&& outputIt : connections.outputSlots)
Kevin May43a799c2019-02-08 16:31:42 +0000879 {
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +0100880 const unsigned int outputSlotIndex = outputIt.first;
881 IOutputSlot* outputSlot = outputIt.second;
882 if (connections.inputSlots.find(outputSlotIndex) != connections.inputSlots.end())
Kevin May43a799c2019-02-08 16:31:42 +0000883 {
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +0100884 for (IInputSlot* inputSlot : connections.inputSlots[outputSlotIndex])
Nattapat Chaimanowongd469faf2019-03-04 17:10:40 +0000885 {
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +0100886 outputSlot->Connect(*inputSlot);
Nattapat Chaimanowongd469faf2019-03-04 17:10:40 +0000887 }
Kevin May43a799c2019-02-08 16:31:42 +0000888 }
889 }
890 }
891
892 return std::move(m_Network);
893}
894
Finn Williams85d36712021-01-26 22:30:06 +0000895BindingPointInfo IDeserializer::DeserializerImpl::GetNetworkInputBindingInfo(unsigned int layerIndex,
Saoirse Stewarta1ed73a2019-03-04 13:40:12 +0000896 const std::string& name) const
Kevin May43a799c2019-02-08 16:31:42 +0000897{
Jan Eilers8eb25602020-03-09 12:13:48 +0000898 IgnoreUnused(layerIndex);
Derek Lamberti8ddae332019-02-21 16:29:43 +0000899 for (auto inputBinding : m_InputBindings)
Kevin May43a799c2019-02-08 16:31:42 +0000900 {
Derek Lamberti8ddae332019-02-21 16:29:43 +0000901 if (inputBinding.first == name)
Kevin May43a799c2019-02-08 16:31:42 +0000902 {
Derek Lamberti8ddae332019-02-21 16:29:43 +0000903 return inputBinding.second;
Kevin May43a799c2019-02-08 16:31:42 +0000904 }
905 }
Colm Donelan5b5c2222020-09-09 12:48:16 +0100906 throw ParseException(fmt::format("No input binding found for layer:{0} / {1}",
907 name,
908 CHECK_LOCATION().AsString()));
Kevin May43a799c2019-02-08 16:31:42 +0000909}
910
Finn Williams85d36712021-01-26 22:30:06 +0000911BindingPointInfo IDeserializer::DeserializerImpl::GetNetworkOutputBindingInfo(unsigned int layerIndex,
Kevin May43a799c2019-02-08 16:31:42 +0000912 const std::string& name) const
913{
Jan Eilers8eb25602020-03-09 12:13:48 +0000914 IgnoreUnused(layerIndex);
Derek Lamberti8ddae332019-02-21 16:29:43 +0000915 for (auto outputBinding : m_OutputBindings)
Kevin May43a799c2019-02-08 16:31:42 +0000916 {
Derek Lamberti8ddae332019-02-21 16:29:43 +0000917 if (outputBinding.first == name)
Kevin May43a799c2019-02-08 16:31:42 +0000918 {
Derek Lamberti8ddae332019-02-21 16:29:43 +0000919 return outputBinding.second;
Kevin May43a799c2019-02-08 16:31:42 +0000920 }
921 }
Colm Donelan5b5c2222020-09-09 12:48:16 +0100922 throw ParseException(fmt::format("No output binding found for layer:{0} / {1}",
923 name,
924 CHECK_LOCATION().AsString()));
Kevin May43a799c2019-02-08 16:31:42 +0000925}
926
Finn Williams85d36712021-01-26 22:30:06 +0000927unsigned int IDeserializer::DeserializerImpl::GetInputLayerInVector(GraphPtr graph, int targetId)
Tee Jungaa920c52019-11-05 10:48:25 +0000928{
929 for (unsigned int i = 0; i < graph->layers()->size(); i++)
930 {
931 auto layer = graph->layers()->Get(i);
932 if (layer->layer_type() == Layer::Layer_InputLayer)
933 {
934 auto layerBindingId = layer->layer_as_InputLayer()->base()->layerBindingId();
935 if (layerBindingId == targetId)
936 {
937 return i;
938 }
939 }
940 }
941 throw ParseException("Input layer with given layerBindingId not found");
942}
943
Finn Williams85d36712021-01-26 22:30:06 +0000944unsigned int IDeserializer::DeserializerImpl::GetOutputLayerInVector(GraphPtr graph, int targetId)
Tee Jungaa920c52019-11-05 10:48:25 +0000945{
946 for (unsigned int i = 0; i < graph->layers()->size(); i++)
947 {
948 auto layer = graph->layers()->Get(i);
949 if (layer->layer_type() == Layer::Layer_OutputLayer)
950 {
951 auto layerBindingId = layer->layer_as_OutputLayer()->base()->layerBindingId();
952 if (layerBindingId == targetId)
953 {
954 return i;
955 }
956 }
957 }
958 throw ParseException("Output layer with given layerBindingId not found");
959}
960
Finn Williams85d36712021-01-26 22:30:06 +0000961unsigned int IDeserializer::DeserializerImpl::GetLayerIndexInVector(GraphPtr graph, unsigned int targetIndex)
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +0100962{
963 for (unsigned int i = 0; i < graph->layers()->size(); i++)
964 {
965 LayerBaseRawPtr layer = GetBaseLayer(graph, i);
966 if (layer->index() == targetIndex)
967 {
968 return i;
969 }
970 }
971 throw ParseException("Layer with given index not found");
972}
973
Finn Williams85d36712021-01-26 22:30:06 +0000974IDeserializer::DeserializerImpl::FeatureVersions IDeserializer::DeserializerImpl::GetFeatureVersions(GraphPtr graph)
Tee Jungaa920c52019-11-05 10:48:25 +0000975{
Finn Williams85d36712021-01-26 22:30:06 +0000976 IDeserializer::DeserializerImpl::FeatureVersions versions;
Tee Jungaa920c52019-11-05 10:48:25 +0000977
978 if (graph->featureVersions())
979 {
980 versions.m_BindingIdScheme = graph->featureVersions()->bindingIdsScheme();
Jan Eilers53ef7952021-06-02 12:01:25 +0100981 versions.m_WeightsLayoutScheme = graph->featureVersions()->weightsLayoutScheme();
Matthew Sloyan81beae32021-07-13 19:46:11 +0100982 versions.m_ConstTensorsAsInputs = graph->featureVersions()->constantTensorsAsInputs();
Tee Jungaa920c52019-11-05 10:48:25 +0000983 }
984
985 return versions;
986}
987
Finn Williams85d36712021-01-26 22:30:06 +0000988void IDeserializer::DeserializerImpl::SetupInputLayers(GraphPtr graph)
Kevin May43a799c2019-02-08 16:31:42 +0000989{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000990 CHECK_GRAPH(graph, 0);
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +0100991 const unsigned int numInputs = graph->inputIds()->size();
Derek Lamberti8ddae332019-02-21 16:29:43 +0000992 m_InputBindings.clear();
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +0100993 m_InputBindings.reserve(numInputs);
994
995 for (unsigned int i = 0; i < numInputs; i++)
Kevin May43a799c2019-02-08 16:31:42 +0000996 {
Tee Jungaa920c52019-11-05 10:48:25 +0000997 unsigned int inputLayerIndex = 0xFFFFFFFF;
998 if (GetFeatureVersions(graph).m_BindingIdScheme == 0)
999 {
Matthew Sloyan0663d662020-09-14 11:47:26 +01001000 const unsigned int inputId = armnn::numeric_cast<unsigned int>(graph->inputIds()->Get(i));
Tee Jungaa920c52019-11-05 10:48:25 +00001001 inputLayerIndex = GetLayerIndexInVector(graph, inputId);
1002 }
1003 else
1004 {
1005 const int inputId = graph->inputIds()->Get(i);
1006 inputLayerIndex = GetInputLayerInVector(graph, inputId);
1007 }
1008
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001009 LayerBaseRawPtr baseLayer = GetBaseLayer(graph, inputLayerIndex);
Kevin May43a799c2019-02-08 16:31:42 +00001010
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001011 // GetBindingLayerInfo expect the index to be index in the vector not index property on each layer base
1012 LayerBindingId bindingId = GetBindingLayerInfo(graph, inputLayerIndex);
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01001013 ARMNN_ASSERT_MSG(baseLayer->layerName()->c_str(), "Input has no name.");
Kevin May43a799c2019-02-08 16:31:42 +00001014
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001015 IConnectableLayer* inputLayer =
1016 m_Network->AddInputLayer(bindingId, baseLayer->layerName()->c_str());
Derek Lamberti8ddae332019-02-21 16:29:43 +00001017
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001018 const armnn::TensorInfo& tensorInfo = ToTensorInfo(baseLayer->outputSlots()->Get(0)->tensorInfo());
1019 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1020 RegisterOutputSlots(graph, inputLayerIndex, inputLayer);
1021
Derek Lamberti8ddae332019-02-21 16:29:43 +00001022 BindingPointInfo bindingInfo = {bindingId, tensorInfo};
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001023 m_InputBindings.push_back(std::make_pair(baseLayer->layerName()->c_str(), bindingInfo));
Kevin May43a799c2019-02-08 16:31:42 +00001024 }
1025}
1026
Finn Williams85d36712021-01-26 22:30:06 +00001027void IDeserializer::DeserializerImpl::SetupOutputLayers(GraphPtr graph)
Kevin May43a799c2019-02-08 16:31:42 +00001028{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001029 CHECK_GRAPH(graph, 0);
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001030 const unsigned int numOutputs = graph->outputIds()->size();
Derek Lamberti8ddae332019-02-21 16:29:43 +00001031 m_OutputBindings.clear();
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001032 m_OutputBindings.reserve(numOutputs);
1033
1034 for (unsigned int i = 0; i < numOutputs; i++)
Kevin May43a799c2019-02-08 16:31:42 +00001035 {
Tee Jungaa920c52019-11-05 10:48:25 +00001036 unsigned int outputLayerIndex = 0xFFFFFFFF;
1037 if (GetFeatureVersions(graph).m_BindingIdScheme == 0)
1038 {
Matthew Sloyan0663d662020-09-14 11:47:26 +01001039 const unsigned int outputId = armnn::numeric_cast<unsigned int>(graph->outputIds()->Get(i));
Tee Jungaa920c52019-11-05 10:48:25 +00001040 outputLayerIndex = GetLayerIndexInVector(graph, outputId);
1041 }
1042 else
1043 {
1044 const int outputId = graph->outputIds()->Get(i);
1045 outputLayerIndex = GetOutputLayerInVector(graph, outputId);
1046 }
1047
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001048 LayerBaseRawPtr baseLayer = GetBaseLayer(graph, outputLayerIndex);
Kevin May43a799c2019-02-08 16:31:42 +00001049
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001050 // GetBindingLayerInfo expect the index to be index in the vector not index property on each layer base
1051 LayerBindingId bindingId = GetBindingLayerInfo(graph, outputLayerIndex);
Colm Donelan30aa3712021-04-07 17:28:01 +01001052 ARMNN_ASSERT_MSG(baseLayer->layerName()->c_str(), "Output has no name.");
Derek Lamberti8ddae332019-02-21 16:29:43 +00001053
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001054 IConnectableLayer* outputLayer =
1055 m_Network->AddOutputLayer(bindingId, baseLayer->layerName()->c_str());
Derek Lamberti8ddae332019-02-21 16:29:43 +00001056
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001057 RegisterInputSlots(graph, outputLayerIndex, outputLayer);
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001058 unsigned int sourceLayerIndex =
1059 GetLayerIndexInVector(graph, baseLayer->inputSlots()->Get(0)->connection()->sourceLayerIndex());
Colm Donelan30aa3712021-04-07 17:28:01 +01001060 unsigned int outputSlotIndex =
1061 GetLayerIndexInVector(graph, baseLayer->inputSlots()->Get(0)->connection()->outputSlotIndex());
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001062 LayerBaseRawPtr sourceBaseLayer = GetBaseLayer(graph, sourceLayerIndex);
Colm Donelan30aa3712021-04-07 17:28:01 +01001063 const armnn::TensorInfo& tensorInfo = ToTensorInfo(
1064 sourceBaseLayer->outputSlots()->Get(outputSlotIndex)->tensorInfo());
Derek Lamberti8ddae332019-02-21 16:29:43 +00001065 BindingPointInfo bindingInfo = {bindingId, tensorInfo};
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001066 m_OutputBindings.push_back(std::make_pair(baseLayer->layerName()->c_str(), bindingInfo));
Kevin May43a799c2019-02-08 16:31:42 +00001067 }
1068}
1069
Finn Williams85d36712021-01-26 22:30:06 +00001070void IDeserializer::DeserializerImpl::RegisterOutputSlots(GraphPtr graph,
Derek Lamberti8ddae332019-02-21 16:29:43 +00001071 uint32_t layerIndex,
1072 IConnectableLayer* layer)
Kevin May43a799c2019-02-08 16:31:42 +00001073{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001074 CHECK_LAYERS(graph, 0, layerIndex);
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01001075 ARMNN_ASSERT(layer != nullptr);
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001076 LayerBaseRawPtr baseLayer = GetBaseLayer(graph, layerIndex);
1077 if (baseLayer->outputSlots()->size() != layer->GetNumOutputSlots())
Kevin May43a799c2019-02-08 16:31:42 +00001078 {
Colm Donelan5b5c2222020-09-09 12:48:16 +01001079 throw ParseException(fmt::format("The number of outputslots ({0}) does not match the number expected ({1})"
1080 " for layer index: {2} {3}",
1081 baseLayer->outputSlots()->size(),
1082 layer->GetNumOutputSlots(),
1083 layerIndex,
1084 CHECK_LOCATION().AsString()));
Kevin May43a799c2019-02-08 16:31:42 +00001085 }
1086
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001087 for (unsigned int i = 0; i < layer->GetNumOutputSlots(); ++i)
Kevin May43a799c2019-02-08 16:31:42 +00001088 {
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001089 const unsigned int slotIndex = baseLayer->outputSlots()->Get(i)->index();
1090 armnn::IOutputSlot* outputSlot = &(layer->GetOutputSlot(slotIndex));
1091 // layerIndex is not necessarily the same as baseLayer->index(). The latter is needed here
1092 RegisterOutputSlotOfConnection(baseLayer->index(), slotIndex, outputSlot);
Kevin May43a799c2019-02-08 16:31:42 +00001093 }
1094}
1095
Finn Williams85d36712021-01-26 22:30:06 +00001096void IDeserializer::DeserializerImpl::RegisterInputSlots(GraphPtr graph,
Matthew Sloyan81beae32021-07-13 19:46:11 +01001097 uint32_t layerIndex,
1098 armnn::IConnectableLayer* layer,
1099 std::vector<unsigned int> ignoreSlots)
Kevin May43a799c2019-02-08 16:31:42 +00001100{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001101 CHECK_LAYERS(graph, 0, layerIndex);
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01001102 ARMNN_ASSERT(layer != nullptr);
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001103 LayerBaseRawPtr baseLayer = GetBaseLayer(graph, layerIndex);
Matthew Sloyan81beae32021-07-13 19:46:11 +01001104
1105 if (baseLayer->inputSlots()->size() != (layer->GetNumInputSlots() - ignoreSlots.size()))
Kevin May43a799c2019-02-08 16:31:42 +00001106 {
Colm Donelan5b5c2222020-09-09 12:48:16 +01001107 throw ParseException(fmt::format("The number of inputslots ({0}) does not match the number expected ({1})"
1108 " for layer index:{2} {3}",
1109 baseLayer->inputSlots()->size(),
1110 layer->GetNumInputSlots(),
1111 layerIndex,
1112 CHECK_LOCATION().AsString()));
Kevin May43a799c2019-02-08 16:31:42 +00001113 }
1114
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001115 for (unsigned int i = 0; i < layer->GetNumInputSlots(); ++i)
Kevin May43a799c2019-02-08 16:31:42 +00001116 {
Matthew Sloyan81beae32021-07-13 19:46:11 +01001117 // Check if slot should be ignored.
1118 if (std::find(ignoreSlots.begin(), ignoreSlots.end(), i) == ignoreSlots.end())
1119 {
1120 auto fbInputSlot = baseLayer->inputSlots()->Get(i);
1121 auto fbConnection = fbInputSlot->connection();
1122 armnn::IInputSlot* inputSlot = &(layer->GetInputSlot(fbInputSlot->index()));
1123 RegisterInputSlotOfConnection(fbConnection->sourceLayerIndex(), fbConnection->outputSlotIndex(), inputSlot);
1124 }
Kevin May43a799c2019-02-08 16:31:42 +00001125 }
1126}
1127
Finn Williams85d36712021-01-26 22:30:06 +00001128void IDeserializer::DeserializerImpl::RegisterInputSlotOfConnection(uint32_t sourceLayerIndex,
Nattapat Chaimanowongd469faf2019-03-04 17:10:40 +00001129 uint32_t outputSlotIndex,
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001130 armnn::IInputSlot* inputSlot)
Kevin May43a799c2019-02-08 16:31:42 +00001131{
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001132 if (m_GraphConnections.find(sourceLayerIndex) == m_GraphConnections.end())
Kevin May43a799c2019-02-08 16:31:42 +00001133 {
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001134 m_GraphConnections[sourceLayerIndex] = Connections();
1135 }
1136
1137 Connections& connections = m_GraphConnections[sourceLayerIndex];
1138 if (connections.inputSlots.find(outputSlotIndex) == connections.inputSlots.end())
1139 {
1140 connections.inputSlots[outputSlotIndex] = {inputSlot};
Kevin May43a799c2019-02-08 16:31:42 +00001141 }
Nattapat Chaimanowongd469faf2019-03-04 17:10:40 +00001142 else
1143 {
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001144 connections.inputSlots[outputSlotIndex].push_back(inputSlot);
Nattapat Chaimanowongd469faf2019-03-04 17:10:40 +00001145 }
1146}
Kevin May43a799c2019-02-08 16:31:42 +00001147
Finn Williams85d36712021-01-26 22:30:06 +00001148void IDeserializer::DeserializerImpl::RegisterOutputSlotOfConnection(uint32_t sourceLayerIndex,
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001149 uint32_t outputSlotIndex,
1150 armnn::IOutputSlot* outputSlot)
Nattapat Chaimanowongd469faf2019-03-04 17:10:40 +00001151{
Nattapat Chaimanowongaf000a92019-05-16 16:32:35 +01001152 if (m_GraphConnections.find(sourceLayerIndex) == m_GraphConnections.end())
1153 {
1154 m_GraphConnections[sourceLayerIndex] = Connections();
1155 }
1156
1157 Connections& connections = m_GraphConnections[sourceLayerIndex];
1158 if (connections.outputSlots.find(outputSlotIndex) != connections.outputSlots.end())
1159 {
1160 throw ParseException("Same output slot index processed twice");
1161 }
1162
1163 connections.outputSlots[outputSlotIndex] = outputSlot;
Kevin May43a799c2019-02-08 16:31:42 +00001164}
1165
Finn Williams85d36712021-01-26 22:30:06 +00001166void IDeserializer::DeserializerImpl::ParseAbs(GraphPtr graph, unsigned int layerIndex)
FinnWilliamsArm4ffcc8f2019-09-05 14:34:20 +01001167{
1168 CHECK_LAYERS(graph, 0, layerIndex);
1169 auto inputs = GetInputs(graph, layerIndex);
1170 CHECK_LOCATION();
1171 CHECK_VALID_SIZE(inputs.size(), 1);
1172
1173 auto outputs = GetOutputs(graph, layerIndex);
1174 CHECK_VALID_SIZE(outputs.size(), 1);
1175
1176 auto layerName = GetLayerName(graph, layerIndex);
1177
josh minor4a3c6102020-01-06 16:40:46 -06001178 armnn::ElementwiseUnaryDescriptor descriptor(armnn::UnaryOperation::Abs);
1179 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
FinnWilliamsArm4ffcc8f2019-09-05 14:34:20 +01001180 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1181 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1182
1183 RegisterInputSlots(graph, layerIndex, layer);
1184 RegisterOutputSlots(graph, layerIndex, layer);
1185}
1186
Finn Williams85d36712021-01-26 22:30:06 +00001187void IDeserializer::DeserializerImpl::ParseActivation(GraphPtr graph, unsigned int layerIndex)
Mike Kellyaf484012019-02-20 16:53:11 +00001188{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001189 CHECK_LAYERS(graph, 0, layerIndex);
1190 auto inputs = GetInputs(graph, layerIndex);
Mike Kellyaf484012019-02-20 16:53:11 +00001191 CHECK_LOCATION();
1192 CHECK_VALID_SIZE(inputs.size(), 1);
1193
Derek Lamberti8ddae332019-02-21 16:29:43 +00001194 auto outputs = GetOutputs(graph, layerIndex);
Mike Kellyaf484012019-02-20 16:53:11 +00001195 CHECK_VALID_SIZE(outputs.size(), 1);
1196
Derek Lamberti8ddae332019-02-21 16:29:43 +00001197 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ActivationLayer();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00001198 auto layerName = GetLayerName(graph, layerIndex);
Mike Kellyaf484012019-02-20 16:53:11 +00001199 auto serializerDescriptor = serializerLayer->descriptor();
1200
1201 armnn::ActivationDescriptor descriptor;
Tee Jung86bc3d82019-10-01 11:25:56 +09001202 descriptor.m_Function = ToActivationFunction(serializerDescriptor->activationFunction());
Mike Kellyaf484012019-02-20 16:53:11 +00001203 descriptor.m_A = serializerDescriptor->a();
1204 descriptor.m_B = serializerDescriptor->b();
1205
1206 IConnectableLayer* layer = m_Network->AddActivationLayer(descriptor,
1207 layerName.c_str());
1208 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1209 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1210
Derek Lamberti8ddae332019-02-21 16:29:43 +00001211 RegisterInputSlots(graph, layerIndex, layer);
1212 RegisterOutputSlots(graph, layerIndex, layer);
Mike Kellyaf484012019-02-20 16:53:11 +00001213}
1214
Finn Williams85d36712021-01-26 22:30:06 +00001215void IDeserializer::DeserializerImpl::ParseAdd(GraphPtr graph, unsigned int layerIndex)
Kevin May43a799c2019-02-08 16:31:42 +00001216{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001217 CHECK_LAYERS(graph, 0, layerIndex);
1218 auto inputs = GetInputs(graph, layerIndex);
Kevin May43a799c2019-02-08 16:31:42 +00001219 CHECK_LOCATION();
1220 CHECK_VALID_SIZE(inputs.size(), 2);
1221
Derek Lamberti8ddae332019-02-21 16:29:43 +00001222 auto outputs = GetOutputs(graph, layerIndex);
Kevin May43a799c2019-02-08 16:31:42 +00001223 CHECK_VALID_SIZE(outputs.size(), 1);
1224
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00001225 auto layerName = GetLayerName(graph, layerIndex);
1226 IConnectableLayer* layer = m_Network->AddAdditionLayer(layerName.c_str());
Kevin May43a799c2019-02-08 16:31:42 +00001227
1228 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1229 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1230
Derek Lamberti8ddae332019-02-21 16:29:43 +00001231 RegisterInputSlots(graph, layerIndex, layer);
1232 RegisterOutputSlots(graph, layerIndex, layer);
Kevin May43a799c2019-02-08 16:31:42 +00001233}
1234
Finn Williams85d36712021-01-26 22:30:06 +00001235void IDeserializer::DeserializerImpl::ParseArgMinMax(GraphPtr graph, unsigned int layerIndex)
Narumol Prangnawarat0cfcf232019-09-09 17:16:24 +01001236{
1237 CHECK_LAYERS(graph, 0, layerIndex);
1238 auto inputs = GetInputs(graph, layerIndex);
1239 CHECK_LOCATION();
1240 CHECK_VALID_SIZE(inputs.size(), 1);
1241
1242 auto outputs = GetOutputs(graph, layerIndex);
1243 CHECK_VALID_SIZE(outputs.size(), 1);
1244
1245 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ArgMinMaxLayer();
1246 auto serializerDescriptor = serializerLayer->descriptor();
1247
1248 armnn::ArgMinMaxDescriptor descriptor;
Tee Jung86bc3d82019-10-01 11:25:56 +09001249 descriptor.m_Function = ToArgMinMaxFunction(serializerDescriptor->argMinMaxFunction());
Narumol Prangnawarat0cfcf232019-09-09 17:16:24 +01001250 descriptor.m_Axis = serializerDescriptor->axis();
1251 auto layerName = GetLayerName(graph, layerIndex);
1252 IConnectableLayer* layer = m_Network->AddArgMinMaxLayer(descriptor, layerName.c_str());
1253
1254 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1255 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1256
1257 RegisterInputSlots(graph, layerIndex, layer);
1258 RegisterOutputSlots(graph, layerIndex, layer);
1259}
1260
Finn Williams85d36712021-01-26 22:30:06 +00001261void IDeserializer::DeserializerImpl::ParseBatchToSpaceNd(GraphPtr graph, unsigned int layerIndex)
Nattapat Chaimanowong6b4ed982019-02-26 17:24:13 +00001262{
1263 CHECK_LAYERS(graph, 0, layerIndex);
1264
Finn Williams85d36712021-01-26 22:30:06 +00001265 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Nattapat Chaimanowong6b4ed982019-02-26 17:24:13 +00001266 CHECK_VALID_SIZE(inputs.size(), 1);
1267
Finn Williams85d36712021-01-26 22:30:06 +00001268 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Nattapat Chaimanowong6b4ed982019-02-26 17:24:13 +00001269 CHECK_VALID_SIZE(outputs.size(), 1);
1270
1271 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_BatchToSpaceNdLayer()->descriptor();
1272 auto flatBufferCrops = flatBufferDescriptor->crops();
1273 auto flatBufferBlockShape = flatBufferDescriptor->blockShape();
1274
1275 if (flatBufferCrops->Length() % 2 != 0)
1276 {
Colm Donelan5b5c2222020-09-09 12:48:16 +01001277 throw ParseException(fmt::format("The size of crops must be divisible by 2 {}", CHECK_LOCATION().AsString()));
Nattapat Chaimanowong6b4ed982019-02-26 17:24:13 +00001278 }
1279
1280 std::vector<std::pair<unsigned int, unsigned int>> crops;
1281 crops.reserve(flatBufferCrops->Length() / 2);
1282 for (unsigned int i = 0; i < flatBufferCrops->Length() - 1; i += 2)
1283 {
1284 crops.emplace_back(flatBufferCrops->Get(i), flatBufferCrops->Get(i+1));
1285 }
1286
1287 armnn::BatchToSpaceNdDescriptor descriptor;
1288 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
1289 descriptor.m_BlockShape =
1290 std::vector<unsigned int>(flatBufferBlockShape->begin(), flatBufferBlockShape->end());
1291 descriptor.m_Crops = crops;
1292
1293 auto layerName = GetLayerName(graph, layerIndex);
1294 IConnectableLayer* layer = m_Network->AddBatchToSpaceNdLayer(descriptor, layerName.c_str());
1295
1296 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1297 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1298
1299 RegisterInputSlots(graph, layerIndex, layer);
1300 RegisterOutputSlots(graph, layerIndex, layer);
1301}
1302
Finn Williams85d36712021-01-26 22:30:06 +00001303void IDeserializer::DeserializerImpl::ParseBatchNormalization(GraphPtr graph, unsigned int layerIndex)
ruoyan018e7fa232019-02-28 15:09:07 +00001304{
1305 CHECK_LAYERS(graph, 0, layerIndex);
1306
1307 auto inputs = GetInputs(graph, layerIndex);
1308 CHECK_VALID_SIZE(inputs.size(), 1);
1309
1310 auto outputs = GetOutputs(graph, layerIndex);
1311 CHECK_VALID_SIZE(outputs.size(), 1);
1312 auto outputInfo = ToTensorInfo(outputs[0]);
1313
ruoyan015c7ab052019-03-04 14:48:02 +00001314 auto layerName = GetLayerName(graph, layerIndex);
ruoyan018e7fa232019-02-28 15:09:07 +00001315
1316 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_BatchNormalizationLayer();
1317 auto serializerDescriptor = serializerLayer->descriptor();
1318
1319 armnn::BatchNormalizationDescriptor descriptor;
1320 descriptor.m_Eps = serializerDescriptor->eps();
1321 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1322
1323 armnn::ConstTensor mean = ToConstTensor(serializerLayer->mean());
1324 armnn::ConstTensor variance = ToConstTensor(serializerLayer->variance());
1325 armnn::ConstTensor beta = ToConstTensor(serializerLayer->beta());
1326 armnn::ConstTensor gamma = ToConstTensor(serializerLayer->gamma());
1327
1328 IConnectableLayer* layer = m_Network->AddBatchNormalizationLayer(descriptor,
1329 mean,
1330 variance,
1331 beta,
1332 gamma,
1333 layerName.c_str());
1334 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1335
1336 RegisterInputSlots(graph, layerIndex, layer);
1337 RegisterOutputSlots(graph, layerIndex, layer);
1338}
1339
mathad01b392e982021-04-07 12:07:30 +01001340void IDeserializer::DeserializerImpl::ParseCast(GraphPtr graph, unsigned int layerIndex)
1341{
1342 CHECK_LAYERS(graph, 0, layerIndex);
1343 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1344 CHECK_LOCATION();
1345 CHECK_VALID_SIZE(inputs.size(), 1);
1346
1347 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1348 CHECK_VALID_SIZE(outputs.size(), 1);
1349
1350 auto layerName = GetLayerName(graph, layerIndex);
1351
1352 IConnectableLayer* layer = m_Network->AddCastLayer(layerName.c_str());
1353
1354 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1355 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1356
1357 RegisterInputSlots(graph, layerIndex, layer);
1358 RegisterOutputSlots(graph, layerIndex, layer);
1359}
1360
Finn Williams85d36712021-01-26 22:30:06 +00001361void IDeserializer::DeserializerImpl::ParseConstant(GraphPtr graph, unsigned int layerIndex)
Conor Kennedy76277882019-02-26 08:29:54 +00001362{
1363 CHECK_LAYERS(graph, 0, layerIndex);
1364 CHECK_LOCATION();
1365
1366 auto outputs = GetOutputs(graph, layerIndex);
1367 CHECK_VALID_SIZE(outputs.size(), 1);
1368
1369 auto layerName = GetLayerName(graph, layerIndex);
1370
1371 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ConstantLayer();
1372 auto serializerInput = serializerLayer->input();
1373
1374 armnn::ConstTensor input = ToConstTensor(serializerInput);
Cathal Corbett06902652022-04-14 17:55:11 +01001375 IConnectableLayer* layer;
Conor Kennedy76277882019-02-26 08:29:54 +00001376
Cathal Corbett06902652022-04-14 17:55:11 +01001377 // Required for when Constant Layer is used as an inputs to DepthwiseConvolution2d Layer.
1378 // Running a model that was created before weights layout scheme version was added to our flatbuffers
1379 // file ensuring older models can still be read and executed. featureVersion weights layout scheme 1
1380 // indicates a change in the depthwise weights layout within ArmNN from [M,I,H,W] --> [1,H,W,I*M]
1381 if (this->GetFeatureVersions(graph).m_WeightsLayoutScheme <= 0)
1382 {
1383 // Permute weights [ H, W, M, I ] --> [ 1, H, W, I*M ]
1384 // Step1: [ M, I, H, W ] --> [ H, W, I, M]
1385 PermutationVector permutationVector = { 3, 2, 0, 1 };
1386 armnn::TensorInfo weightsInfo = input.GetInfo();
1387 std::unique_ptr<unsigned char[]> permuteBuffer(new unsigned char[weightsInfo.GetNumBytes()]);
1388 weightsInfo = armnnUtils::Permuted(weightsInfo, permutationVector);
1389 armnnUtils::Permute(weightsInfo.GetShape(), permutationVector,
1390 input.GetMemoryArea(), permuteBuffer.get(),
1391 GetDataTypeSize(weightsInfo.GetDataType()));
Conor Kennedy76277882019-02-26 08:29:54 +00001392
Cathal Corbett06902652022-04-14 17:55:11 +01001393 // Step2: Reshape [ H, W, I, M] --> [ 1, H, W, I*M ]
1394 auto weightsShape = weightsInfo.GetShape();
1395 weightsInfo.SetShape({1,
1396 weightsShape[0],
1397 weightsShape[1],
1398 weightsShape[2]*weightsShape[3]});
1399
1400 armnn::ConstTensor weightsPermuted(weightsInfo, permuteBuffer.get());
1401
1402 layer = m_Network->AddConstantLayer(weightsPermuted, layerName.c_str());
1403
1404 layer->GetOutputSlot(0).SetTensorInfo(weightsPermuted.GetInfo());
1405
1406 RegisterOutputSlots(graph, layerIndex, layer);
1407
1408 return;
1409 }
1410 else
1411 {
1412 layer = m_Network->AddConstantLayer(input, layerName.c_str());
1413
1414 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1415 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1416 }
Conor Kennedy76277882019-02-26 08:29:54 +00001417
1418 RegisterOutputSlots(graph, layerIndex, layer);
1419}
1420
Finn Williams85d36712021-01-26 22:30:06 +00001421void IDeserializer::DeserializerImpl::ParseConvolution2d(GraphPtr graph, unsigned int layerIndex)
Mike Kellya0766c32019-02-19 17:22:07 +00001422{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001423 CHECK_LAYERS(graph, 0, layerIndex);
1424 auto inputs = GetInputs(graph, layerIndex);
Mike Kellya0766c32019-02-19 17:22:07 +00001425 CHECK_LOCATION();
1426 CHECK_VALID_SIZE(inputs.size(), 1);
1427
Derek Lamberti8ddae332019-02-21 16:29:43 +00001428 auto outputs = GetOutputs(graph, layerIndex);
Mike Kellya0766c32019-02-19 17:22:07 +00001429 CHECK_VALID_SIZE(outputs.size(), 1);
1430
Derek Lamberti8ddae332019-02-21 16:29:43 +00001431 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_Convolution2dLayer();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00001432 auto layerName = GetLayerName(graph, layerIndex);
Mike Kellya0766c32019-02-19 17:22:07 +00001433 auto serializerDescriptor = serializerLayer->descriptor();
1434
1435 armnn::Convolution2dDescriptor descriptor;
1436 descriptor.m_PadLeft = serializerDescriptor->padLeft();
1437 descriptor.m_PadRight = serializerDescriptor->padRight();
1438 descriptor.m_PadTop = serializerDescriptor->padTop();
1439 descriptor.m_PadBottom = serializerDescriptor->padBottom();
1440 descriptor.m_StrideX = serializerDescriptor->strideX();
1441 descriptor.m_StrideY = serializerDescriptor->strideY();;
Matthew Benthamacad04e2019-05-13 10:02:45 +01001442 descriptor.m_DilationX = serializerDescriptor->dilationX();
1443 descriptor.m_DilationY = serializerDescriptor->dilationY();;
Mike Kellya0766c32019-02-19 17:22:07 +00001444 descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
1445 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1446
1447 armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
1448 armnn::ConstTensor biases;
1449
Matteo Martincighfc598e12019-05-14 10:36:13 +01001450 armnn::Optional<armnn::ConstTensor> optionalBiases = armnn::EmptyOptional();
Mike Kellya0766c32019-02-19 17:22:07 +00001451 if (descriptor.m_BiasEnabled)
1452 {
1453 biases = ToConstTensor(serializerLayer->biases());
Matteo Martincighfc598e12019-05-14 10:36:13 +01001454 optionalBiases = armnn::Optional<armnn::ConstTensor>(biases);
Mike Kellya0766c32019-02-19 17:22:07 +00001455 }
1456 IConnectableLayer* layer = m_Network->AddConvolution2dLayer(descriptor,
1457 weights,
Matteo Martincighfc598e12019-05-14 10:36:13 +01001458 optionalBiases,
Mike Kellya0766c32019-02-19 17:22:07 +00001459 layerName.c_str());
1460 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1461 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1462
Derek Lamberti8ddae332019-02-21 16:29:43 +00001463 RegisterInputSlots(graph, layerIndex, layer);
1464 RegisterOutputSlots(graph, layerIndex, layer);
Mike Kellya0766c32019-02-19 17:22:07 +00001465}
1466
Matthew Sloyanb63a3112021-09-08 13:05:51 +01001467void IDeserializer::DeserializerImpl::ParseConvolution3d(GraphPtr graph, unsigned int layerIndex)
1468{
1469 CHECK_LAYERS(graph, 0, layerIndex);
1470 auto inputs = GetInputs(graph, layerIndex);
1471 CHECK_LOCATION();
Matthew Sloyanb63a3112021-09-08 13:05:51 +01001472
1473 auto outputs = GetOutputs(graph, layerIndex);
1474 CHECK_VALID_SIZE(outputs.size(), 1);
1475
1476 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_Convolution3dLayer();
1477 auto layerName = GetLayerName(graph, layerIndex);
1478 auto serializerDescriptor = serializerLayer->descriptor();
1479
1480 armnn::Convolution3dDescriptor descriptor;
1481 descriptor.m_PadLeft = serializerDescriptor->padLeft();
1482 descriptor.m_PadRight = serializerDescriptor->padRight();
1483 descriptor.m_PadTop = serializerDescriptor->padTop();
1484 descriptor.m_PadBottom = serializerDescriptor->padBottom();
1485 descriptor.m_PadFront = serializerDescriptor->padFront();
1486 descriptor.m_PadBack = serializerDescriptor->padBack();
1487 descriptor.m_StrideX = serializerDescriptor->strideX();
1488 descriptor.m_StrideY = serializerDescriptor->strideY();
1489 descriptor.m_StrideZ = serializerDescriptor->strideZ();
1490 descriptor.m_DilationX = serializerDescriptor->dilationX();
1491 descriptor.m_DilationY = serializerDescriptor->dilationY();
1492 descriptor.m_DilationZ = serializerDescriptor->dilationZ();
Matthew Sloyan5d7b0a32021-10-18 13:07:49 +01001493 descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();
Matthew Sloyanb63a3112021-09-08 13:05:51 +01001494 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1495
Matthew Sloyan5d7b0a32021-10-18 13:07:49 +01001496 uint32_t numInputs = descriptor.GetNumInputs();
1497 CHECK_VALID_SIZE(inputs.size(), numInputs);
Matthew Sloyanb63a3112021-09-08 13:05:51 +01001498
Matthew Sloyan5d7b0a32021-10-18 13:07:49 +01001499 IConnectableLayer* layer = m_Network->AddConvolution3dLayer(descriptor, layerName.c_str());
1500
Matthew Sloyanb63a3112021-09-08 13:05:51 +01001501 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1502 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1503
1504 RegisterInputSlots(graph, layerIndex, layer);
1505 RegisterOutputSlots(graph, layerIndex, layer);
1506}
1507
Finn Williams85d36712021-01-26 22:30:06 +00001508void IDeserializer::DeserializerImpl::ParseDepthToSpace(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Tarda9d2d32019-09-20 10:42:02 +01001509{
1510 CHECK_LAYERS(graph, 0, layerIndex);
1511
1512 auto inputs = GetInputs(graph, layerIndex);
1513 CHECK_VALID_SIZE(inputs.size(), 1);
1514
1515 auto outputs = GetOutputs(graph, layerIndex);
1516 CHECK_VALID_SIZE(outputs.size(), 1);
1517
1518 auto fbDescriptor = graph->layers()->Get(layerIndex)->layer_as_DepthToSpaceLayer()->descriptor();
1519
1520 armnn::DepthToSpaceDescriptor descriptor;
1521 descriptor.m_BlockSize = fbDescriptor->blockSize();
1522 descriptor.m_DataLayout = ToDataLayout(fbDescriptor->dataLayout());
1523
1524 auto layerName = GetLayerName(graph, layerIndex);
1525 IConnectableLayer* layer = m_Network->AddDepthToSpaceLayer(descriptor, layerName.c_str());
1526
1527 armnn::TensorInfo outputInfo = ToTensorInfo(outputs[0]);
1528 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1529
1530 RegisterInputSlots(graph, layerIndex, layer);
1531 RegisterOutputSlots(graph, layerIndex, layer);
1532}
1533
Finn Williams85d36712021-01-26 22:30:06 +00001534void IDeserializer::DeserializerImpl::ParseDepthwiseConvolution2d(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +00001535{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001536 CHECK_LAYERS(graph, 0, layerIndex);
1537 auto inputs = GetInputs(graph, layerIndex);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +00001538 CHECK_LOCATION();
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +00001539
Derek Lamberti8ddae332019-02-21 16:29:43 +00001540 auto outputs = GetOutputs(graph, layerIndex);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +00001541 CHECK_VALID_SIZE(outputs.size(), 1);
1542
Derek Lamberti8ddae332019-02-21 16:29:43 +00001543 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_DepthwiseConvolution2dLayer();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00001544 auto layerName = GetLayerName(graph, layerIndex);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +00001545 auto serializerDescriptor = serializerLayer->descriptor();
1546
1547 armnn::DepthwiseConvolution2dDescriptor descriptor;
Cathal Corbett06902652022-04-14 17:55:11 +01001548 descriptor.m_PadLeft = serializerDescriptor->padLeft();
1549 descriptor.m_PadRight = serializerDescriptor->padRight();
1550 descriptor.m_PadTop = serializerDescriptor->padTop();
1551 descriptor.m_PadBottom = serializerDescriptor->padBottom();
1552 descriptor.m_StrideX = serializerDescriptor->strideX();
1553 descriptor.m_StrideY = serializerDescriptor->strideY();
1554 descriptor.m_DilationX = serializerDescriptor->dilationX();
1555 descriptor.m_DilationY = serializerDescriptor->dilationY();
1556 descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();
1557 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +00001558
Jan Eilers53ef7952021-06-02 12:01:25 +01001559 IConnectableLayer* layer;
Cathal Corbett06902652022-04-14 17:55:11 +01001560 std::vector<unsigned int> ignoreSlots {};
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +00001561
Cathal Corbett06902652022-04-14 17:55:11 +01001562 // Weights and biases used to be always constant and were stored as members of the layer. This has changed and
1563 // they are now passed as inputs. If they are constant then they will be stored in a ConstantLayer.
1564 if (this->GetFeatureVersions(graph).m_ConstTensorsAsInputs <= 0)
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +00001565 {
Cathal Corbett06902652022-04-14 17:55:11 +01001566 CHECK_VALID_SIZE(inputs.size(), 1);
Jan Eilers53ef7952021-06-02 12:01:25 +01001567
Cathal Corbett06902652022-04-14 17:55:11 +01001568 // If the model stores weights and biases as members of the layer we have to read them from there
1569 // but add them to their own ConstantLayer for compatibility
1570 armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
1571 ignoreSlots.emplace_back(1u);
Jan Eilers53ef7952021-06-02 12:01:25 +01001572
1573 layer = m_Network->AddDepthwiseConvolution2dLayer(descriptor,
Jan Eilers53ef7952021-06-02 12:01:25 +01001574 layerName.c_str());
Cathal Corbett06902652022-04-14 17:55:11 +01001575
1576 armnn::Optional<armnn::ConstTensor> optionalBiases = armnn::EmptyOptional();
1577 if (descriptor.m_BiasEnabled)
1578 {
1579 armnn::ConstTensor biases = ToConstTensor(serializerLayer->biases());
1580 ignoreSlots.emplace_back(2u);
1581
1582 auto biasLayer = m_Network->AddConstantLayer(biases);
1583 biasLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(2u));
1584 biasLayer->GetOutputSlot(0).SetTensorInfo(biases.GetInfo());
1585 }
1586
1587 if (this->GetFeatureVersions(graph).m_WeightsLayoutScheme <= 0)
1588 {
1589 // Permute weights [ H, W, M, I ] --> [ 1, H, W, I*M ]
1590 // Step1: [ M, I, H, W ] --> [ H, W, I, M]
1591 PermutationVector permutationVector = { 3, 2, 0, 1 };
1592 armnn::TensorInfo weightsInfo = weights.GetInfo();
1593 std::unique_ptr<unsigned char[]> permuteBuffer(new unsigned char[weightsInfo.GetNumBytes()]);
1594 weightsInfo = armnnUtils::Permuted(weightsInfo, permutationVector);
1595 armnnUtils::Permute(weightsInfo.GetShape(), permutationVector,
1596 weights.GetMemoryArea(), permuteBuffer.get(),
1597 GetDataTypeSize(weightsInfo.GetDataType()));
1598
1599 // Step2: Reshape [ H, W, I, M] --> [ 1, H, W, I*M ]
1600 auto weightsShape = weightsInfo.GetShape();
1601 weightsInfo.SetShape({1,
1602 weightsShape[0],
1603 weightsShape[1],
1604 weightsShape[2]*weightsShape[3]});
1605
1606 armnn::ConstTensor weightsPermuted(weightsInfo, permuteBuffer.get());
1607
1608 auto weightsLayer = m_Network->AddConstantLayer(weightsPermuted);
1609 weightsLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(1u));
1610 weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsPermuted.GetInfo());
1611 }
1612 else
1613 {
1614 auto weightsLayer = m_Network->AddConstantLayer(weights);
1615 weightsLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(1u));
1616 weightsLayer->GetOutputSlot(0).SetTensorInfo(weights.GetInfo());
1617 }
Jan Eilers53ef7952021-06-02 12:01:25 +01001618 }
1619 else
1620 {
1621 layer = m_Network->AddDepthwiseConvolution2dLayer(descriptor,
Jan Eilers53ef7952021-06-02 12:01:25 +01001622 layerName.c_str());
Cathal Corbett06902652022-04-14 17:55:11 +01001623 uint32_t numInputs = descriptor.GetNumInputs();
1624 CHECK_VALID_SIZE(inputs.size(), numInputs);
Jan Eilers53ef7952021-06-02 12:01:25 +01001625 }
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +00001626
1627 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1628 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1629
Cathal Corbett06902652022-04-14 17:55:11 +01001630 RegisterInputSlots(graph, layerIndex, layer, ignoreSlots);
Derek Lamberti8ddae332019-02-21 16:29:43 +00001631 RegisterOutputSlots(graph, layerIndex, layer);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +00001632}
1633
Finn Williams85d36712021-01-26 22:30:06 +00001634void IDeserializer::DeserializerImpl::ParseDetectionPostProcess(GraphPtr graph, unsigned int layerIndex)
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +00001635{
1636 CHECK_LAYERS(graph, 0, layerIndex);
1637 auto inputs = GetInputs(graph, layerIndex);
1638 CHECK_LOCATION();
1639 CHECK_VALID_SIZE(inputs.size(), 2);
1640
1641 auto outputs = GetOutputs(graph, layerIndex);
1642 CHECK_VALID_SIZE(outputs.size(), 4);
1643
1644 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_DetectionPostProcessLayer();
1645 auto layerName = GetLayerName(graph, layerIndex);
1646 auto flatBufferDescriptor = flatBufferLayer->descriptor();
1647
1648 armnn::DetectionPostProcessDescriptor descriptor;
1649 descriptor.m_MaxDetections = flatBufferDescriptor->maxDetections();
1650 descriptor.m_MaxClassesPerDetection = flatBufferDescriptor->maxClassesPerDetection();
1651 descriptor.m_DetectionsPerClass = flatBufferDescriptor->detectionsPerClass();
1652 descriptor.m_NmsScoreThreshold = flatBufferDescriptor->nmsScoreThreshold();
1653 descriptor.m_NmsIouThreshold = flatBufferDescriptor->nmsIouThreshold();
1654 descriptor.m_NumClasses = flatBufferDescriptor->numClasses();
1655 descriptor.m_UseRegularNms = flatBufferDescriptor->useRegularNms();
1656 descriptor.m_ScaleX = flatBufferDescriptor->scaleX();
1657 descriptor.m_ScaleY = flatBufferDescriptor->scaleY();
1658 descriptor.m_ScaleW = flatBufferDescriptor->scaleW();
1659 descriptor.m_ScaleH = flatBufferDescriptor->scaleH();
1660
1661 armnn::ConstTensor anchors = ToConstTensor(flatBufferLayer->anchors());
1662
1663 IConnectableLayer* layer = m_Network->AddDetectionPostProcessLayer(descriptor,
1664 anchors,
1665 layerName.c_str());
1666
1667 for (unsigned int i = 0; i < 4; i++)
1668 {
1669 layer->GetOutputSlot(i).SetTensorInfo(ToTensorInfo(outputs[i]));
1670 }
1671
1672 RegisterInputSlots(graph, layerIndex, layer);
1673 RegisterOutputSlots(graph, layerIndex, layer);
1674}
1675
Finn Williams85d36712021-01-26 22:30:06 +00001676void IDeserializer::DeserializerImpl::ParseDivision(GraphPtr graph, unsigned int layerIndex)
Éanna Ó Catháin58885892019-02-27 16:16:39 +00001677{
1678 CHECK_LAYERS(graph, 0, layerIndex);
1679 auto inputs = GetInputs(graph, layerIndex);
1680 CHECK_LOCATION();
1681 CHECK_VALID_SIZE(inputs.size(), 2);
1682
1683 auto outputs = GetOutputs(graph, layerIndex);
1684 CHECK_VALID_SIZE(outputs.size(), 1);
1685
1686 auto layerName = GetLayerName(graph, layerIndex);
1687 IConnectableLayer* layer = m_Network->AddDivisionLayer(layerName.c_str());
1688
1689 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1690 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1691
1692 RegisterInputSlots(graph, layerIndex, layer);
1693 RegisterOutputSlots(graph, layerIndex, layer);
1694}
1695
Finn Williams85d36712021-01-26 22:30:06 +00001696void IDeserializer::DeserializerImpl::ParseEqual(GraphPtr graph, unsigned int layerIndex)
Nattapat Chaimanowong235cea52019-02-28 16:27:30 +00001697{
1698 CHECK_LAYERS(graph, 0, layerIndex);
1699 auto inputs = GetInputs(graph, layerIndex);
1700 CHECK_LOCATION();
1701 CHECK_VALID_SIZE(inputs.size(), 2);
1702
1703 auto outputs = GetOutputs(graph, layerIndex);
1704 CHECK_VALID_SIZE(outputs.size(), 1);
1705
1706 auto layerName = GetLayerName(graph, layerIndex);
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +01001707 armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::Equal);
1708 IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
Nattapat Chaimanowong235cea52019-02-28 16:27:30 +00001709
1710 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1711 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1712
1713 RegisterInputSlots(graph, layerIndex, layer);
1714 RegisterOutputSlots(graph, layerIndex, layer);
1715}
1716
Finn Williams85d36712021-01-26 22:30:06 +00001717void IDeserializer::DeserializerImpl::ParseFill(GraphPtr graph, unsigned int layerIndex)
Keith Davis300ad562020-06-04 16:34:23 +01001718{
1719 CHECK_LAYERS(graph, 0, layerIndex);
1720 auto inputs = GetInputs(graph, layerIndex);
1721 CHECK_LOCATION();
1722 CHECK_VALID_SIZE(inputs.size(), 1);
1723
1724 auto outputs = GetOutputs(graph, layerIndex);
1725 CHECK_VALID_SIZE(outputs.size(), 1);
1726
1727 auto layerName = GetLayerName(graph, layerIndex);
Sadik Armaganfd0cae32021-11-08 17:18:31 +00001728 armnn::FillDescriptor descriptor;
1729 descriptor.m_Value = graph->layers()->Get(layerIndex)->layer_as_FillLayer()->descriptor()->value();
Keith Davis300ad562020-06-04 16:34:23 +01001730 IConnectableLayer* layer = m_Network->AddFillLayer(descriptor, layerName.c_str());
1731
1732 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1733 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1734
1735 RegisterInputSlots(graph, layerIndex, layer);
1736 RegisterOutputSlots(graph, layerIndex, layer);
1737}
1738
Finn Williams85d36712021-01-26 22:30:06 +00001739void IDeserializer::DeserializerImpl::ParseGreater(GraphPtr graph, unsigned int layerIndex)
Conor Kennedy79ffdf52019-03-01 14:24:54 +00001740{
1741 CHECK_LAYERS(graph, 0, layerIndex);
1742 auto inputs = GetInputs(graph, layerIndex);
1743 CHECK_LOCATION();
1744 CHECK_VALID_SIZE(inputs.size(), 2);
1745
1746 auto outputs = GetOutputs(graph, layerIndex);
1747 CHECK_VALID_SIZE(outputs.size(), 1);
1748
1749 auto layerName = GetLayerName(graph, layerIndex);
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +01001750 armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::Greater);
1751 IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
Conor Kennedy79ffdf52019-03-01 14:24:54 +00001752
1753 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1754 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1755
1756 RegisterInputSlots(graph, layerIndex, layer);
1757 RegisterOutputSlots(graph, layerIndex, layer);
1758}
1759
Finn Williams85d36712021-01-26 22:30:06 +00001760void IDeserializer::DeserializerImpl::ParseInstanceNormalization(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Tar781ced92019-10-03 11:15:39 +01001761{
1762 CHECK_LAYERS(graph, 0, layerIndex);
1763
1764 auto inputs = GetInputs(graph, layerIndex);
1765 CHECK_VALID_SIZE(inputs.size(), 1);
1766
1767 auto outputs = GetOutputs(graph, layerIndex);
1768 CHECK_VALID_SIZE(outputs.size(), 1);
1769
1770 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_InstanceNormalizationLayer();
1771 auto fbDescriptor = fbLayer->descriptor();
1772
1773 armnn::InstanceNormalizationDescriptor descriptor;
1774 descriptor.m_Gamma = fbDescriptor->gamma();
1775 descriptor.m_Beta = fbDescriptor->beta();
1776 descriptor.m_Eps = fbDescriptor->eps();
1777 descriptor.m_DataLayout = ToDataLayout(fbDescriptor->dataLayout());
1778
1779 const std::string layerName = GetLayerName(graph, layerIndex);
1780 const armnn::TensorInfo outputInfo = ToTensorInfo(outputs[0]);
1781
1782 IConnectableLayer* layer = m_Network->AddInstanceNormalizationLayer(descriptor, layerName.c_str());
1783 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1784
1785 RegisterInputSlots(graph, layerIndex, layer);
1786 RegisterOutputSlots(graph, layerIndex, layer);
1787}
1788
Finn Williams85d36712021-01-26 22:30:06 +00001789void IDeserializer::DeserializerImpl::ParseL2Normalization(GraphPtr graph, unsigned int layerIndex)
Narumol Prangnawarat495701f2019-03-07 17:31:34 +00001790{
1791 CHECK_LAYERS(graph, 0, layerIndex);
1792
1793 auto inputs = GetInputs(graph, layerIndex);
1794 CHECK_VALID_SIZE(inputs.size(), 1);
1795
1796 auto outputs = GetOutputs(graph, layerIndex);
1797 CHECK_VALID_SIZE(outputs.size(), 1);
1798 auto outputInfo = ToTensorInfo(outputs[0]);
1799
1800 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_L2NormalizationLayer();
1801 auto flatBufferDescriptor = flatBufferLayer->descriptor();
1802
1803 auto layerName = GetLayerName(graph, layerIndex);
1804 armnn::L2NormalizationDescriptor descriptor;
1805 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001806 descriptor.m_Eps = flatBufferDescriptor->eps();
Narumol Prangnawarat495701f2019-03-07 17:31:34 +00001807
1808 IConnectableLayer* layer = m_Network->AddL2NormalizationLayer(descriptor, layerName.c_str());
1809 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1810
1811 RegisterInputSlots(graph, layerIndex, layer);
1812 RegisterOutputSlots(graph, layerIndex, layer);
1813}
1814
Finn Williams85d36712021-01-26 22:30:06 +00001815void IDeserializer::DeserializerImpl::ParseLogicalBinary(GraphPtr graph, unsigned int layerIndex)
James Conroyaba90cd2020-11-06 16:28:18 +00001816{
1817 CHECK_LAYERS(graph, 0, layerIndex);
1818 CHECK_LOCATION();
1819
1820 auto inputs = GetInputs(graph, layerIndex);
1821 CHECK_VALID_SIZE(inputs.size(), 2);
1822
1823 auto outputs = GetOutputs(graph, layerIndex);
1824 CHECK_VALID_SIZE(outputs.size(), 1);
1825
1826 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_LogicalBinaryLayer();
1827 auto fbDescriptor = fbLayer->descriptor();
1828
1829 armnn::LogicalBinaryDescriptor descriptor;
1830 descriptor.m_Operation = ToLogicalBinaryOperation(fbDescriptor->operation());
1831
1832 const std::string& layerName = GetLayerName(graph, layerIndex);
1833 IConnectableLayer* layer = m_Network->AddLogicalBinaryLayer(descriptor, layerName.c_str());
1834
1835 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1836 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1837
1838 RegisterInputSlots(graph, layerIndex, layer);
1839 RegisterOutputSlots(graph, layerIndex, layer);
1840}
1841
Finn Williams85d36712021-01-26 22:30:06 +00001842void IDeserializer::DeserializerImpl::ParseLogSoftmax(GraphPtr graph, unsigned int layerIndex)
Sadik Armagan26257852019-10-14 13:00:47 +01001843{
1844 CHECK_LAYERS(graph, 0, layerIndex);
1845
Finn Williams85d36712021-01-26 22:30:06 +00001846 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Sadik Armagan26257852019-10-14 13:00:47 +01001847 CHECK_VALID_SIZE(inputs.size(), 1);
1848
Finn Williams85d36712021-01-26 22:30:06 +00001849 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Sadik Armagan26257852019-10-14 13:00:47 +01001850 CHECK_VALID_SIZE(outputs.size(), 1);
1851
1852 armnn::LogSoftmaxDescriptor descriptor;
1853 descriptor.m_Beta = graph->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->descriptor()->beta();
1854 descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->descriptor()->axis();
1855 auto layerName = GetLayerName(graph, layerIndex);
1856
1857 IConnectableLayer* layer = m_Network->AddLogSoftmaxLayer(descriptor, layerName.c_str());
1858
1859 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1860 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1861
1862 RegisterInputSlots(graph, layerIndex, layer);
1863 RegisterOutputSlots(graph, layerIndex, layer);
1864}
1865
Finn Williams85d36712021-01-26 22:30:06 +00001866void IDeserializer::DeserializerImpl::ParseMinimum(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Tar0fe32452019-02-28 13:12:47 +00001867{
1868 CHECK_LAYERS(graph, 0, layerIndex);
1869 auto inputs = GetInputs(graph, layerIndex);
1870 CHECK_LOCATION();
1871 CHECK_VALID_SIZE(inputs.size(), 2);
1872
1873 auto outputs = GetOutputs(graph, layerIndex);
1874 CHECK_VALID_SIZE(outputs.size(), 1);
1875
1876 auto layerName = GetLayerName(graph, layerIndex);
1877 IConnectableLayer* layer = m_Network->AddMinimumLayer(layerName.c_str());
1878
1879 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1880 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1881
1882 RegisterInputSlots(graph, layerIndex, layer);
1883 RegisterOutputSlots(graph, layerIndex, layer);
1884}
1885
Finn Williams85d36712021-01-26 22:30:06 +00001886void IDeserializer::DeserializerImpl::ParseMaximum(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Tar377351e2019-02-27 14:42:31 +00001887{
1888 CHECK_LAYERS(graph, 0, layerIndex);
1889 auto inputs = GetInputs(graph, layerIndex);
1890 CHECK_LOCATION();
1891 CHECK_VALID_SIZE(inputs.size(), 2);
1892
1893 auto outputs = GetOutputs(graph, layerIndex);
1894 CHECK_VALID_SIZE(outputs.size(), 1);
1895
1896 auto layerName = GetLayerName(graph, layerIndex);
1897 IConnectableLayer* layer = m_Network->AddMaximumLayer(layerName.c_str());
1898
1899 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1900 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1901
1902 RegisterInputSlots(graph, layerIndex, layer);
1903 RegisterOutputSlots(graph, layerIndex, layer);
1904}
1905
Jim Flynne242f2d2019-05-22 14:24:13 +01001906const armnnSerializer::OriginsDescriptor* GetOriginsDescriptor(const armnnSerializer::SerializedGraph* graph,
1907 unsigned int layerIndex)
1908{
1909 auto layerType = graph->layers()->Get(layerIndex)->layer_type();
1910
1911 switch (layerType)
1912 {
1913 case Layer::Layer_ConcatLayer:
1914 return graph->layers()->Get(layerIndex)->layer_as_ConcatLayer()->descriptor();
1915 case Layer::Layer_MergerLayer:
1916 return graph->layers()->Get(layerIndex)->layer_as_MergerLayer()->descriptor();
1917 default:
1918 throw armnn::Exception("unknown layer type, should be concat or merger");
1919 }
1920}
Simon Obute51f67772021-09-03 15:50:13 +01001921void IDeserializer::DeserializerImpl::ParseChannelShuffle(GraphPtr graph, unsigned int layerIndex)
1922{
1923 CHECK_LAYERS(graph, 0, layerIndex);
Jim Flynne242f2d2019-05-22 14:24:13 +01001924
Simon Obute51f67772021-09-03 15:50:13 +01001925 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1926 CHECK_VALID_SIZE(inputs.size(), 1);
1927
1928 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1929 CHECK_VALID_SIZE(outputs.size(), 1);
1930
1931 armnn::ChannelShuffleDescriptor descriptor;
1932 descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_ChannelShuffleLayer()->descriptor()->axis();
1933 descriptor.m_NumGroups =
1934 graph->layers()->Get(layerIndex)->layer_as_ChannelShuffleLayer()->descriptor()->numGroups();
1935
1936 auto layerName = GetLayerName(graph, layerIndex);
1937 IConnectableLayer* layer = m_Network->AddChannelShuffleLayer(descriptor, layerName.c_str());
1938
1939 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1940 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1941
1942 RegisterInputSlots(graph, layerIndex, layer);
1943 RegisterOutputSlots(graph, layerIndex, layer);
1944}
Finn Williams85d36712021-01-26 22:30:06 +00001945void IDeserializer::DeserializerImpl::ParseComparison(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001946{
1947 CHECK_LAYERS(graph, 0, layerIndex);
1948 CHECK_LOCATION();
1949
1950 auto inputs = GetInputs(graph, layerIndex);
1951 CHECK_VALID_SIZE(inputs.size(), 2);
1952
1953 auto outputs = GetOutputs(graph, layerIndex);
1954 CHECK_VALID_SIZE(outputs.size(), 1);
1955
1956 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_ComparisonLayer();
1957 auto fbDescriptor = fbLayer->descriptor();
1958
1959 armnn::ComparisonDescriptor descriptor;
1960 descriptor.m_Operation = ToComparisonOperation(fbDescriptor->operation());
1961
1962 const std::string& layerName = GetLayerName(graph, layerIndex);
1963 IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1964
1965 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1966 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1967
1968 RegisterInputSlots(graph, layerIndex, layer);
1969 RegisterOutputSlots(graph, layerIndex, layer);
1970}
1971
Finn Williams85d36712021-01-26 22:30:06 +00001972void IDeserializer::DeserializerImpl::ParseElementwiseUnary(GraphPtr graph, unsigned int layerIndex)
josh minor4a3c6102020-01-06 16:40:46 -06001973{
1974 CHECK_LAYERS(graph, 0, layerIndex);
1975 CHECK_LOCATION();
1976
1977 auto inputs = GetInputs(graph, layerIndex);
1978 CHECK_VALID_SIZE(inputs.size(), 1);
1979
1980 auto outputs = GetOutputs(graph, layerIndex);
1981 CHECK_VALID_SIZE(outputs.size(), 1);
1982
1983 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_ElementwiseUnaryLayer();
1984 auto fbDescriptor = fbLayer->descriptor();
1985
1986 armnn::ElementwiseUnaryDescriptor descriptor;
1987 descriptor.m_Operation = ToUnaryOperation(fbDescriptor->operation());
1988
1989 const std::string& layerName = GetLayerName(graph, layerIndex);
1990 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1991
1992 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1993 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1994
1995 RegisterInputSlots(graph, layerIndex, layer);
1996 RegisterOutputSlots(graph, layerIndex, layer);
1997}
1998
Finn Williams85d36712021-01-26 22:30:06 +00001999void IDeserializer::DeserializerImpl::ParseConcat(GraphPtr graph, unsigned int layerIndex)
Jim Flynnac25a1b2019-02-28 10:40:49 +00002000{
2001 CHECK_LAYERS(graph, 0, layerIndex);
2002 CHECK_LOCATION();
2003
2004 auto outputs = GetOutputs(graph, layerIndex);
2005 CHECK_VALID_SIZE(outputs.size(), 1);
2006
Jim Flynnac25a1b2019-02-28 10:40:49 +00002007 auto layerName = GetLayerName(graph, layerIndex);
Jim Flynne242f2d2019-05-22 14:24:13 +01002008 auto originsDescriptor = GetOriginsDescriptor(graph, layerIndex);
2009 unsigned int numViews = originsDescriptor->numViews();
2010 unsigned int numDimensions = originsDescriptor->numDimensions();
Jim Flynnac25a1b2019-02-28 10:40:49 +00002011
2012 // can now check the number of inputs == number of views
2013 auto inputs = GetInputs(graph, layerIndex);
2014 CHECK_VALID_SIZE(inputs.size(), numViews);
2015
2016 armnn::OriginsDescriptor descriptor(numViews, numDimensions);
Jim Flynne242f2d2019-05-22 14:24:13 +01002017 auto originsPtr = originsDescriptor->viewOrigins();
Jim Flynnac25a1b2019-02-28 10:40:49 +00002018 for (unsigned int v = 0; v < numViews; ++v)
2019 {
2020 auto originPtr = originsPtr->Get(v);
2021 for (unsigned int d = 0; d < numDimensions; ++d)
2022 {
2023 uint32_t value = originPtr->data()->Get(d);
2024 descriptor.SetViewOriginCoord(v, d, value);
2025 }
2026 }
Jim Flynne242f2d2019-05-22 14:24:13 +01002027 descriptor.SetConcatAxis(originsDescriptor->concatAxis());
Jim Flynnac25a1b2019-02-28 10:40:49 +00002028
Jim Flynn906f9462019-05-10 13:55:21 +01002029 IConnectableLayer* layer = m_Network->AddConcatLayer(descriptor, layerName.c_str());
Jim Flynnac25a1b2019-02-28 10:40:49 +00002030 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2031 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2032
2033 RegisterInputSlots(graph, layerIndex, layer);
2034 RegisterOutputSlots(graph, layerIndex, layer);
2035}
2036
Finn Williams85d36712021-01-26 22:30:06 +00002037void IDeserializer::DeserializerImpl::ParseMultiplication(GraphPtr graph, unsigned int layerIndex)
Sadik Armagan5f450272019-02-12 14:31:45 +00002038{
Derek Lamberti8ddae332019-02-21 16:29:43 +00002039 CHECK_LAYERS(graph, 0, layerIndex);
2040 auto inputs = GetInputs(graph, layerIndex);
Sadik Armagan5f450272019-02-12 14:31:45 +00002041 CHECK_LOCATION();
2042 CHECK_VALID_SIZE(inputs.size(), 2);
2043
Derek Lamberti8ddae332019-02-21 16:29:43 +00002044 auto outputs = GetOutputs(graph, layerIndex);
Sadik Armagan5f450272019-02-12 14:31:45 +00002045 CHECK_VALID_SIZE(outputs.size(), 1);
2046
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00002047 auto layerName = GetLayerName(graph, layerIndex);
2048 IConnectableLayer* layer = m_Network->AddMultiplicationLayer(layerName.c_str());
Sadik Armagan5f450272019-02-12 14:31:45 +00002049
2050 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2051 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2052
Derek Lamberti8ddae332019-02-21 16:29:43 +00002053 RegisterInputSlots(graph, layerIndex, layer);
2054 RegisterOutputSlots(graph, layerIndex, layer);
Sadik Armagan5f450272019-02-12 14:31:45 +00002055}
2056
Finn Williams85d36712021-01-26 22:30:06 +00002057void IDeserializer::DeserializerImpl::ParseFloor(GraphPtr graph, unsigned int layerIndex)
Finn Williamsdd2ba7e2019-03-01 11:51:52 +00002058{
2059 CHECK_LAYERS(graph, 0, layerIndex);
2060 CHECK_LOCATION();
2061
2062 auto inputs = GetInputs(graph, layerIndex);
2063 CHECK_VALID_SIZE(inputs.size(), 1);
2064
2065 auto outputs = GetOutputs(graph, layerIndex);
2066 CHECK_VALID_SIZE(outputs.size(), 1);
2067
2068 auto layerName = GetLayerName(graph, layerIndex);
2069
2070 armnn::IConnectableLayer* layer;
2071
Nattapat Chaimanowongc192f352019-03-05 17:35:28 +00002072 layer = m_Network->AddFloorLayer(layerName.c_str());
Finn Williamsdd2ba7e2019-03-01 11:51:52 +00002073
2074 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2075 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2076
2077 RegisterInputSlots(graph, layerIndex, layer);
2078 RegisterOutputSlots(graph, layerIndex, layer);
2079}
2080
Finn Williams85d36712021-01-26 22:30:06 +00002081void IDeserializer::DeserializerImpl::ParseFullyConnected(GraphPtr graph, unsigned int layerIndex)
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00002082{
Derek Lamberti8ddae332019-02-21 16:29:43 +00002083 CHECK_LAYERS(graph, 0, layerIndex);
2084 auto inputs = GetInputs(graph, layerIndex);
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00002085 CHECK_LOCATION();
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00002086
Derek Lamberti8ddae332019-02-21 16:29:43 +00002087 auto outputs = GetOutputs(graph, layerIndex);
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00002088 CHECK_VALID_SIZE(outputs.size(), 1);
2089
Derek Lamberti8ddae332019-02-21 16:29:43 +00002090 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_FullyConnectedLayer();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00002091 auto layerName = GetLayerName(graph, layerIndex);
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00002092 auto flatBufferDescriptor = flatBufferLayer->descriptor();
2093
2094 armnn::FullyConnectedDescriptor fullyConnectedDescriptor;
2095 fullyConnectedDescriptor.m_BiasEnabled = flatBufferDescriptor->biasEnabled();
2096 fullyConnectedDescriptor.m_TransposeWeightMatrix = flatBufferDescriptor->transposeWeightsMatrix();
Sadik Armaganf0a6dec2021-03-25 07:46:55 +00002097 fullyConnectedDescriptor.m_ConstantWeights = flatBufferDescriptor->constantWeights();
Matthew Sloyan81beae32021-07-13 19:46:11 +01002098
2099 armnn::IConnectableLayer* layer;
2100 std::vector<unsigned int> ignoreSlots {};
2101
2102 // Weights and biases used to be always constant and were stored as members of the layer. This has changed and
2103 // they are now passed as inputs. If they are constant then they will be stored in a ConstantLayer.
2104 if (this->GetFeatureVersions(graph).m_ConstTensorsAsInputs <= 0)
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00002105 {
Matthew Sloyan81beae32021-07-13 19:46:11 +01002106 // If the model stores weights and biases as members of the layer we have to read them from there
2107 // but add them to their own ConstantLayer for compatibility
2108 CHECK_VALID_SIZE(inputs.size(), 1);
2109 layer = m_Network->AddFullyConnectedLayer(fullyConnectedDescriptor,
2110 layerName.c_str());
2111
2112 armnn::ConstTensor weightsTensor = ToConstTensor(flatBufferLayer->weights());
2113 auto weightsLayer = m_Network->AddConstantLayer(weightsTensor);
2114 weightsLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(1u));
2115 weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsTensor.GetInfo());
2116 ignoreSlots.emplace_back(1u);
2117
Sadik Armaganf0a6dec2021-03-25 07:46:55 +00002118 if (fullyConnectedDescriptor.m_BiasEnabled)
2119 {
Matthew Sloyan81beae32021-07-13 19:46:11 +01002120 armnn::ConstTensor biasTensor = ToConstTensor(flatBufferLayer->biases());
2121 auto biasLayer = m_Network->AddConstantLayer(biasTensor);
2122 biasLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(2u));
2123 biasLayer->GetOutputSlot(0).SetTensorInfo(biasTensor.GetInfo());
2124 ignoreSlots.emplace_back(2u);
Sadik Armaganf0a6dec2021-03-25 07:46:55 +00002125 }
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00002126 }
Matthew Sloyan81beae32021-07-13 19:46:11 +01002127 else
Sadik Armaganf0a6dec2021-03-25 07:46:55 +00002128 {
Matthew Sloyan81beae32021-07-13 19:46:11 +01002129 layer = m_Network->AddFullyConnectedLayer(fullyConnectedDescriptor,
2130 layerName.c_str());
2131 uint32_t numInputs = fullyConnectedDescriptor.GetNumInputs();
2132 CHECK_VALID_SIZE(inputs.size(), numInputs);
Sadik Armaganf0a6dec2021-03-25 07:46:55 +00002133 }
2134
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00002135 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2136 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2137
Matthew Sloyan81beae32021-07-13 19:46:11 +01002138 RegisterInputSlots(graph, layerIndex, layer, ignoreSlots);
Derek Lamberti8ddae332019-02-21 16:29:43 +00002139 RegisterOutputSlots(graph, layerIndex, layer);
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00002140}
2141
Finn Williams85d36712021-01-26 22:30:06 +00002142void IDeserializer::DeserializerImpl::ParsePad(GraphPtr graph, unsigned int layerIndex)
Nattapat Chaimanowongebb0f9c2019-03-01 12:14:06 +00002143{
2144 CHECK_LAYERS(graph, 0, layerIndex);
2145
Finn Williams85d36712021-01-26 22:30:06 +00002146 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Nattapat Chaimanowongebb0f9c2019-03-01 12:14:06 +00002147 CHECK_VALID_SIZE(inputs.size(), 1);
2148
Finn Williams85d36712021-01-26 22:30:06 +00002149 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Nattapat Chaimanowongebb0f9c2019-03-01 12:14:06 +00002150 CHECK_VALID_SIZE(outputs.size(), 1);
2151
2152 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_PadLayer()->descriptor();
2153 auto flatBufferPadList = flatBufferDescriptor->padList();
Matthew Sloyan2e5d0b22021-10-21 14:05:31 +01002154 auto paddingMode = flatBufferDescriptor->paddingMode();
David Monahan34757812019-06-19 11:47:21 +01002155 float padValue = flatBufferDescriptor->padValue();
Nattapat Chaimanowongebb0f9c2019-03-01 12:14:06 +00002156
2157 if (flatBufferPadList->Length() % 2 != 0)
2158 {
Colm Donelan5b5c2222020-09-09 12:48:16 +01002159 throw ParseException(fmt::format("The size of the pad list must be divisible by 2 {}",
2160 CHECK_LOCATION().AsString()));
Nattapat Chaimanowongebb0f9c2019-03-01 12:14:06 +00002161 }
2162
2163 std::vector<std::pair<unsigned int, unsigned int>> padList;
2164 padList.reserve(flatBufferPadList->Length() / 2);
2165 for (unsigned int i = 0; i < flatBufferPadList->Length() - 1; i += 2)
2166 {
2167 padList.emplace_back(flatBufferPadList->Get(i), flatBufferPadList->Get(i+1));
2168 }
2169
Matthew Sloyan2e5d0b22021-10-21 14:05:31 +01002170 armnn::PadDescriptor descriptor(padList, padValue, ToPaddingMode(paddingMode));
Nattapat Chaimanowongebb0f9c2019-03-01 12:14:06 +00002171
2172 auto layerName = GetLayerName(graph, layerIndex);
2173 IConnectableLayer* layer = m_Network->AddPadLayer(descriptor, layerName.c_str());
2174
2175 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2176 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2177
2178 RegisterInputSlots(graph, layerIndex, layer);
2179 RegisterOutputSlots(graph, layerIndex, layer);
2180}
2181
Finn Williams85d36712021-01-26 22:30:06 +00002182void IDeserializer::DeserializerImpl::ParsePermute(GraphPtr graph, unsigned int layerIndex)
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002183{
Derek Lamberti8ddae332019-02-21 16:29:43 +00002184 CHECK_LAYERS(graph, 0, layerIndex);
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002185
2186 auto dimsMapping =
Derek Lamberti8ddae332019-02-21 16:29:43 +00002187 graph->layers()->Get(layerIndex)->layer_as_PermuteLayer()->descriptor()->dimMappings();
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002188
Derek Lamberti8ddae332019-02-21 16:29:43 +00002189 auto inputs = GetInputs(graph, layerIndex);
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002190 CHECK_VALID_SIZE(inputs.size(), 1);
2191
Derek Lamberti8ddae332019-02-21 16:29:43 +00002192 auto outputs = GetOutputs(graph, layerIndex);
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002193 CHECK_VALID_SIZE(outputs.size(), 1);
2194 auto outputInfo = ToTensorInfo(outputs[0]);
2195
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00002196 auto layerName = GetLayerName(graph, layerIndex);
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002197 const armnn::PermuteDescriptor descriptor(armnn::PermutationVector(dimsMapping->data(), dimsMapping->Length()));
2198
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00002199 IConnectableLayer* layer = m_Network->AddPermuteLayer(descriptor, layerName.c_str());
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002200 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2201
Derek Lamberti8ddae332019-02-21 16:29:43 +00002202 RegisterInputSlots(graph, layerIndex, layer);
2203 RegisterOutputSlots(graph, layerIndex, layer);
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002204}
2205
Tamas Nyirid998a1c2021-11-05 14:55:33 +00002206armnn::Pooling2dDescriptor IDeserializer::DeserializerImpl::GetPooling2dDescriptor(Pooling2dDescriptor pooling2dDesc,
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002207 unsigned int layerIndex)
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002208{
Jan Eilers8eb25602020-03-09 12:13:48 +00002209 IgnoreUnused(layerIndex);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002210 armnn::Pooling2dDescriptor desc;
2211
2212 switch (pooling2dDesc->poolType())
2213 {
2214 case PoolingAlgorithm_Average:
2215 {
2216 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002217 break;
2218 }
2219 case PoolingAlgorithm_Max:
2220 {
2221 desc.m_PoolType = armnn::PoolingAlgorithm::Max;
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002222 break;
2223 }
Teresa Charlin4c600de2021-03-11 21:59:43 +00002224 case PoolingAlgorithm_L2:
2225 {
2226 desc.m_PoolType = armnn::PoolingAlgorithm::L2;
2227 break;
2228 }
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002229 default:
2230 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01002231 ARMNN_ASSERT_MSG(false, "Unsupported pooling algorithm");
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002232 }
2233 }
2234
2235 switch (pooling2dDesc->outputShapeRounding())
2236 {
2237 case OutputShapeRounding_Floor:
2238 {
2239 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
2240 break;
2241 }
2242 case OutputShapeRounding_Ceiling:
2243 {
2244 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Ceiling;
2245 break;
2246 }
2247 default:
2248 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01002249 ARMNN_ASSERT_MSG(false, "Unsupported output shape rounding");
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002250 }
2251 }
2252
2253 switch (pooling2dDesc->paddingMethod())
2254 {
2255 case PaddingMethod_Exclude:
2256 {
2257 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
2258 break;
2259 }
2260 case PaddingMethod_IgnoreValue:
2261 {
2262 desc.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
2263 break;
2264 }
2265 default:
2266 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01002267 ARMNN_ASSERT_MSG(false, "Unsupported padding method");
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002268 }
2269 }
2270
2271 switch (pooling2dDesc->dataLayout())
2272 {
2273 case DataLayout_NCHW:
2274 {
2275 desc.m_DataLayout = armnn::DataLayout::NCHW;
2276 break;
2277 }
2278 case DataLayout_NHWC:
2279 {
2280 desc.m_DataLayout = armnn::DataLayout::NHWC;
2281 break;
2282 }
2283 default:
2284 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01002285 ARMNN_ASSERT_MSG(false, "Unsupported data layout");
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002286 }
2287 }
2288
2289 desc.m_PadRight = pooling2dDesc->padRight();
2290 desc.m_PadLeft = pooling2dDesc->padLeft();
2291 desc.m_PadBottom = pooling2dDesc->padBottom();
2292 desc.m_PadTop = pooling2dDesc->padTop();
2293 desc.m_StrideX = pooling2dDesc->strideX();
2294 desc.m_StrideY = pooling2dDesc->strideY();
2295 desc.m_PoolWidth = pooling2dDesc->poolWidth();
2296 desc.m_PoolHeight = pooling2dDesc->poolHeight();
2297
2298 return desc;
2299}
2300
Tamas Nyirid998a1c2021-11-05 14:55:33 +00002301armnn::Pooling3dDescriptor IDeserializer::DeserializerImpl::GetPooling3dDescriptor(Pooling3dDescriptor pooling3dDesc,
2302 unsigned int layerIndex)
2303{
2304 IgnoreUnused(layerIndex);
2305 armnn::Pooling3dDescriptor desc;
Finn Williams85d36712021-01-26 22:30:06 +00002306
Tamas Nyirid998a1c2021-11-05 14:55:33 +00002307 switch (pooling3dDesc->poolType())
2308 {
2309 case PoolingAlgorithm_Average:
2310 {
2311 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
2312 break;
2313 }
2314 case PoolingAlgorithm_Max:
2315 {
2316 desc.m_PoolType = armnn::PoolingAlgorithm::Max;
2317 break;
2318 }
2319 case PoolingAlgorithm_L2:
2320 {
2321 desc.m_PoolType = armnn::PoolingAlgorithm::L2;
2322 break;
2323 }
2324 default:
2325 {
2326 ARMNN_ASSERT_MSG(false, "Unsupported pooling algorithm");
2327 }
2328 }
2329
2330 switch (pooling3dDesc->outputShapeRounding())
2331 {
2332 case OutputShapeRounding_Floor:
2333 {
2334 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
2335 break;
2336 }
2337 case OutputShapeRounding_Ceiling:
2338 {
2339 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Ceiling;
2340 break;
2341 }
2342 default:
2343 {
2344 ARMNN_ASSERT_MSG(false, "Unsupported output shape rounding");
2345 }
2346 }
2347
2348 switch (pooling3dDesc->paddingMethod())
2349 {
2350 case PaddingMethod_Exclude:
2351 {
2352 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
2353 break;
2354 }
2355 case PaddingMethod_IgnoreValue:
2356 {
2357 desc.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
2358 break;
2359 }
2360 default:
2361 {
2362 ARMNN_ASSERT_MSG(false, "Unsupported padding method");
2363 }
2364 }
2365
2366 switch (pooling3dDesc->dataLayout())
2367 {
2368 case DataLayout_NCDHW:
2369 {
2370 desc.m_DataLayout = armnn::DataLayout::NCDHW;
2371 break;
2372 }
2373 case DataLayout_NDHWC:
2374 {
2375 desc.m_DataLayout = armnn::DataLayout::NDHWC;
2376 break;
2377 }
2378 default:
2379 {
2380 ARMNN_ASSERT_MSG(false, "Unsupported data layout");
2381 }
2382 }
2383
2384 desc.m_PadRight = pooling3dDesc->padRight();
2385 desc.m_PadLeft = pooling3dDesc->padLeft();
2386 desc.m_PadBottom = pooling3dDesc->padBottom();
2387 desc.m_PadTop = pooling3dDesc->padTop();
2388 desc.m_PadFront = pooling3dDesc->padFront();
2389 desc.m_PadBack = pooling3dDesc->padBack();
2390 desc.m_StrideX = pooling3dDesc->strideX();
2391 desc.m_StrideY = pooling3dDesc->strideY();
2392 desc.m_StrideZ = pooling3dDesc->strideZ();
2393 desc.m_PoolWidth = pooling3dDesc->poolWidth();
2394 desc.m_PoolHeight = pooling3dDesc->poolHeight();
2395 desc.m_PoolDepth = pooling3dDesc->poolDepth();
2396
2397 return desc;
2398}
Finn Williams85d36712021-01-26 22:30:06 +00002399
2400void IDeserializer::DeserializerImpl::ParsePooling2d(GraphPtr graph, unsigned int layerIndex)
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002401{
Derek Lamberti8ddae332019-02-21 16:29:43 +00002402 CHECK_LAYERS(graph, 0, layerIndex);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002403
Derek Lamberti8ddae332019-02-21 16:29:43 +00002404 auto pooling2dDes = graph->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->descriptor();
Derek Lamberti8ddae332019-02-21 16:29:43 +00002405 auto inputs = GetInputs(graph, layerIndex);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002406 CHECK_VALID_SIZE(inputs.size(), 1);
2407
Derek Lamberti8ddae332019-02-21 16:29:43 +00002408 auto outputs = GetOutputs(graph, layerIndex);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002409 CHECK_VALID_SIZE(outputs.size(), 1);
2410 auto outputInfo = ToTensorInfo(outputs[0]);
2411
Tamas Nyirid998a1c2021-11-05 14:55:33 +00002412 auto pooling2dDescriptor = GetPooling2dDescriptor(pooling2dDes, layerIndex);
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00002413 auto layerName = GetLayerName(graph, layerIndex);
2414 IConnectableLayer* layer = m_Network->AddPooling2dLayer(pooling2dDescriptor, layerName.c_str());
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002415 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2416
Derek Lamberti8ddae332019-02-21 16:29:43 +00002417 RegisterInputSlots(graph, layerIndex, layer);
2418 RegisterOutputSlots(graph, layerIndex, layer);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00002419}
2420
Tamas Nyirid998a1c2021-11-05 14:55:33 +00002421void IDeserializer::DeserializerImpl::ParsePooling3d(GraphPtr graph, unsigned int layerIndex)
2422{
2423 CHECK_LAYERS(graph, 0, layerIndex);
2424
2425 auto pooling3dDes = graph->layers()->Get(layerIndex)->layer_as_Pooling3dLayer()->descriptor();
2426 auto inputs = GetInputs(graph, layerIndex);
2427 CHECK_VALID_SIZE(inputs.size(), 1);
2428
2429 auto outputs = GetOutputs(graph, layerIndex);
2430 CHECK_VALID_SIZE(outputs.size(), 1);
2431 auto outputInfo = ToTensorInfo(outputs[0]);
2432
2433 auto pooling3dDescriptor = GetPooling3dDescriptor(pooling3dDes, layerIndex);
2434 auto layerName = GetLayerName(graph, layerIndex);
2435 IConnectableLayer* layer = m_Network->AddPooling3dLayer(pooling3dDescriptor, layerName.c_str());
2436 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2437
2438 RegisterInputSlots(graph, layerIndex, layer);
2439 RegisterOutputSlots(graph, layerIndex, layer);
2440}
2441
Finn Williams85d36712021-01-26 22:30:06 +00002442void IDeserializer::DeserializerImpl::ParseQuantize(GraphPtr graph, unsigned int layerIndex)
Derek Lamberti87acb272019-03-27 16:51:31 +00002443{
2444 CHECK_LAYERS(graph, 0, layerIndex);
2445
2446 auto inputs = GetInputs(graph, layerIndex);
2447 CHECK_VALID_SIZE(inputs.size(), 1);
2448
2449 auto outputs = GetOutputs(graph, layerIndex);
2450 CHECK_VALID_SIZE(outputs.size(), 1);
2451 auto outputInfo = ToTensorInfo(outputs[0]);
2452
2453 auto layerName = GetLayerName(graph, layerIndex);
2454 IConnectableLayer* layer = m_Network->AddQuantizeLayer(layerName.c_str());
2455 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2456
2457 RegisterInputSlots(graph, layerIndex, layer);
2458 RegisterOutputSlots(graph, layerIndex, layer);
2459}
2460
Finn Williams85d36712021-01-26 22:30:06 +00002461armnn::TensorInfo IDeserializer::DeserializerImpl::OutputShapeOfReshape(const armnn::TensorInfo& inputTensorInfo,
Saoirse Stewart263829c2019-02-19 15:54:14 +00002462 const std::vector<uint32_t>& targetDimsIn)
2463{
2464 std::vector<unsigned int> outputDims(targetDimsIn.begin(), targetDimsIn.end());
2465 const auto stretchDim = std::find(targetDimsIn.begin(), targetDimsIn.end(), -1);
2466
2467 if (stretchDim != targetDimsIn.end())
2468 {
2469 if (std::find(std::next(stretchDim), targetDimsIn.end(), -1) != targetDimsIn.end())
2470 {
Colm Donelan5b5c2222020-09-09 12:48:16 +01002471 throw ParseException(fmt::format("At most one component of shape can be -1 {}",
2472 CHECK_LOCATION().AsString()));
Saoirse Stewart263829c2019-02-19 15:54:14 +00002473 }
2474
2475 auto targetNumElements =
Matthew Sloyan0663d662020-09-14 11:47:26 +01002476 armnn::numeric_cast<unsigned int>(
Saoirse Stewart263829c2019-02-19 15:54:14 +00002477 std::accumulate(targetDimsIn.begin(), targetDimsIn.end(), -1, std::multiplies<int32_t>()));
2478
2479 auto stretchIndex = static_cast<size_t>(std::distance(targetDimsIn.begin(), stretchDim));
2480 outputDims[stretchIndex] = inputTensorInfo.GetNumElements() / targetNumElements;
2481 }
2482
2483 TensorShape outputShape = TensorShape(static_cast<unsigned int>(outputDims.size()), outputDims.data());
2484
2485 armnn::TensorInfo reshapeInfo = inputTensorInfo;
2486 reshapeInfo.SetShape(outputShape);
2487
2488 return reshapeInfo;
2489}
2490
Finn Williams85d36712021-01-26 22:30:06 +00002491void IDeserializer::DeserializerImpl::ParseRank(GraphPtr graph, unsigned int layerIndex)
Finn Williams2605b232020-06-10 15:53:46 +01002492{
2493 CHECK_LAYERS(graph, 0, layerIndex);
2494
Finn Williams85d36712021-01-26 22:30:06 +00002495 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Finn Williams2605b232020-06-10 15:53:46 +01002496 CHECK_VALID_SIZE(inputs.size(), 1);
2497
Finn Williams85d36712021-01-26 22:30:06 +00002498 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Finn Williams2605b232020-06-10 15:53:46 +01002499 CHECK_VALID_SIZE(outputs.size(), 1);
2500
2501 auto layerName = GetLayerName(graph, layerIndex);
2502 IConnectableLayer* layer = m_Network->AddRankLayer( layerName.c_str());
2503
2504 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2505 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2506
2507 RegisterInputSlots(graph, layerIndex, layer);
2508 RegisterOutputSlots(graph, layerIndex, layer);
2509}
2510
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +00002511void IDeserializer::DeserializerImpl::ParseReduce(GraphPtr graph, unsigned int layerIndex)
2512{
2513 CHECK_LAYERS(graph, 0, layerIndex);
2514 CHECK_LOCATION();
2515
2516 auto inputs = GetInputs(graph, layerIndex);
2517 CHECK_VALID_SIZE(inputs.size(), 1);
2518
2519 auto outputs = GetOutputs(graph, layerIndex);
2520 CHECK_VALID_SIZE(outputs.size(), 1);
2521
2522 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_ReduceLayer();
2523 auto fbDescriptor = fbLayer->descriptor();
2524 auto flatBufferAxis = fbDescriptor->axis();
2525
2526 armnn::ReduceDescriptor descriptor;
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +00002527 descriptor.m_KeepDims = fbDescriptor->keepDims();
2528 descriptor.m_vAxis = std::vector<unsigned int>(flatBufferAxis->begin(), flatBufferAxis->end());
2529 descriptor.m_ReduceOperation = ToReduceOperation(fbDescriptor->reduceOperation());
2530
2531 const std::string& layerName = GetLayerName(graph, layerIndex);
2532 IConnectableLayer* layer = m_Network->AddReduceLayer(descriptor, layerName.c_str());
2533
2534 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2535 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2536
2537 RegisterInputSlots(graph, layerIndex, layer);
2538 RegisterOutputSlots(graph, layerIndex, layer);
2539}
2540
Finn Williams85d36712021-01-26 22:30:06 +00002541void IDeserializer::DeserializerImpl::ParseReshape(GraphPtr graph, unsigned int layerIndex)
Saoirse Stewart263829c2019-02-19 15:54:14 +00002542{
Derek Lamberti8ddae332019-02-21 16:29:43 +00002543 CHECK_LAYERS(graph, 0, layerIndex);
2544 auto inputs = GetInputs(graph, layerIndex);
Saoirse Stewart263829c2019-02-19 15:54:14 +00002545
Derek Lamberti8ddae332019-02-21 16:29:43 +00002546 auto outputs = GetOutputs(graph, layerIndex);
Saoirse Stewart263829c2019-02-19 15:54:14 +00002547 CHECK_VALID_SIZE(outputs.size(), 1);
2548
2549 armnn::TensorInfo inputTensorInfo = ToTensorInfo(inputs[0]);
2550 armnn::TensorInfo actualOutputTensorInfo = ToTensorInfo(outputs[0]);
2551
Derek Lamberti8ddae332019-02-21 16:29:43 +00002552 const auto targetDims = graph->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->descriptor()->targetShape();
Saoirse Stewart263829c2019-02-19 15:54:14 +00002553 std::vector<uint32_t> outputDims(targetDims->begin(), targetDims->begin() + targetDims->size());
2554
Finn Williams85d36712021-01-26 22:30:06 +00002555 armnn::TensorInfo reshapeOutputTensorInfo = DeserializerImpl::OutputShapeOfReshape(inputTensorInfo, outputDims);
Saoirse Stewart263829c2019-02-19 15:54:14 +00002556 const armnn::TensorShape& reshapeOutputTensorShape = reshapeOutputTensorInfo.GetShape();
2557
2558 const std::vector<uint32_t> expectedDims(outputs[0]->dimensions()->begin(),
2559 outputs[0]->dimensions()->begin() + outputs[0]->dimensions()->size());
2560
2561 if (inputs.size() > 1 && !CheckShape(reshapeOutputTensorShape, expectedDims))
2562 {
2563 std::stringstream ss;
2564 ss << "New shape defined in reshape parameters "
2565 << reshapeOutputTensorShape
2566 << " does not equal output shape "
2567 << actualOutputTensorInfo.GetShape()
2568 << ": "
2569 << CHECK_LOCATION().AsString();
2570 throw ParseException(ss.str());
2571 }
2572
2573 armnn::ReshapeDescriptor reshapeDesc;
2574 reshapeDesc.m_TargetShape = reshapeOutputTensorShape;
2575
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00002576 auto layerName = GetLayerName(graph, layerIndex);
Saoirse Stewart263829c2019-02-19 15:54:14 +00002577 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
2578 layer->GetOutputSlot(0).SetTensorInfo(reshapeOutputTensorInfo);
2579
Derek Lamberti8ddae332019-02-21 16:29:43 +00002580 RegisterInputSlots(graph, layerIndex, layer);
2581 RegisterOutputSlots(graph, layerIndex, layer);
Saoirse Stewart263829c2019-02-19 15:54:14 +00002582}
2583
Finn Williams85d36712021-01-26 22:30:06 +00002584void IDeserializer::DeserializerImpl::ParseResize(GraphPtr graph, unsigned int layerIndex)
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002585{
2586 CHECK_LAYERS(graph, 0, layerIndex);
2587
Finn Williams85d36712021-01-26 22:30:06 +00002588 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002589 CHECK_VALID_SIZE(inputs.size(), 1);
2590
Finn Williams85d36712021-01-26 22:30:06 +00002591 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002592 CHECK_VALID_SIZE(outputs.size(), 1);
2593
2594 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_ResizeLayer()->descriptor();
2595
2596 armnn::ResizeDescriptor descriptor;
2597 descriptor.m_TargetWidth = flatBufferDescriptor->targetWidth();
2598 descriptor.m_TargetHeight = flatBufferDescriptor->targetHeight();
2599 descriptor.m_Method = ToResizeMethod(flatBufferDescriptor->method());
2600 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
David Monahan4a0c9b92020-05-30 09:48:39 +01002601 descriptor.m_AlignCorners = flatBufferDescriptor->alignCorners();
2602 descriptor.m_HalfPixelCenters = flatBufferDescriptor->halfPixelCenters();
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002603
2604 auto layerName = GetLayerName(graph, layerIndex);
2605 IConnectableLayer* layer = m_Network->AddResizeLayer(descriptor, layerName.c_str());
2606
2607 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2608 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2609
2610 RegisterInputSlots(graph, layerIndex, layer);
2611 RegisterOutputSlots(graph, layerIndex, layer);
2612}
2613
Jan Eilers1b2654f2021-09-24 15:45:46 +01002614
2615/// @Note The ResizeBiliniar operation was deprecated and removed in favor of the Resize operation.
2616/// This function is kept for backwards compatibility.
Finn Williams85d36712021-01-26 22:30:06 +00002617void IDeserializer::DeserializerImpl::ParseResizeBilinear(GraphPtr graph, unsigned int layerIndex)
Nattapat Chaimanowong6522cdc2019-03-01 16:14:13 +00002618{
2619 CHECK_LAYERS(graph, 0, layerIndex);
2620
Finn Williams85d36712021-01-26 22:30:06 +00002621 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Nattapat Chaimanowong6522cdc2019-03-01 16:14:13 +00002622 CHECK_VALID_SIZE(inputs.size(), 1);
2623
Finn Williams85d36712021-01-26 22:30:06 +00002624 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Nattapat Chaimanowong6522cdc2019-03-01 16:14:13 +00002625 CHECK_VALID_SIZE(outputs.size(), 1);
2626
2627 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_ResizeBilinearLayer()->descriptor();
2628
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002629 armnn::ResizeDescriptor descriptor;
2630 descriptor.m_TargetWidth = flatBufferDescriptor->targetWidth();
Nattapat Chaimanowong6522cdc2019-03-01 16:14:13 +00002631 descriptor.m_TargetHeight = flatBufferDescriptor->targetHeight();
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002632 descriptor.m_Method = armnn::ResizeMethod::Bilinear;
2633 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
David Monahan4a0c9b92020-05-30 09:48:39 +01002634 descriptor.m_AlignCorners = flatBufferDescriptor->alignCorners();
2635 descriptor.m_HalfPixelCenters = flatBufferDescriptor->halfPixelCenters();
Nattapat Chaimanowong6522cdc2019-03-01 16:14:13 +00002636
2637 auto layerName = GetLayerName(graph, layerIndex);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002638 IConnectableLayer* layer = m_Network->AddResizeLayer(descriptor, layerName.c_str());
Nattapat Chaimanowong6522cdc2019-03-01 16:14:13 +00002639
2640 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2641 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2642
2643 RegisterInputSlots(graph, layerIndex, layer);
2644 RegisterOutputSlots(graph, layerIndex, layer);
2645}
2646
Keith Davis3ae3f972021-05-21 16:33:48 +01002647void IDeserializer::DeserializerImpl::ParseShape(GraphPtr graph, unsigned int layerIndex)
2648{
2649 CHECK_LAYERS(graph, 0, layerIndex);
2650
2651 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2652 CHECK_VALID_SIZE(inputs.size(), 1);
2653
2654 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2655 CHECK_VALID_SIZE(outputs.size(), 1);
2656
2657 auto layerName = GetLayerName(graph, layerIndex);
2658 IConnectableLayer* layer = m_Network->AddShapeLayer( layerName.c_str());
2659
2660 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2661 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2662
2663 RegisterInputSlots(graph, layerIndex, layer);
2664 RegisterOutputSlots(graph, layerIndex, layer);
2665}
2666
Finn Williams85d36712021-01-26 22:30:06 +00002667void IDeserializer::DeserializerImpl::ParseSoftmax(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00002668{
Derek Lamberti8ddae332019-02-21 16:29:43 +00002669 CHECK_LAYERS(graph, 0, layerIndex);
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00002670
Finn Williams85d36712021-01-26 22:30:06 +00002671 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00002672 CHECK_VALID_SIZE(inputs.size(), 1);
2673
Finn Williams85d36712021-01-26 22:30:06 +00002674 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00002675 CHECK_VALID_SIZE(outputs.size(), 1);
2676
2677 armnn::SoftmaxDescriptor descriptor;
Derek Lamberti8ddae332019-02-21 16:29:43 +00002678 descriptor.m_Beta = graph->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->descriptor()->beta();
Sadik Armaganfd0cae32021-11-08 17:18:31 +00002679 descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->descriptor()->axis();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00002680 auto layerName = GetLayerName(graph, layerIndex);
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00002681
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00002682 IConnectableLayer* layer = m_Network->AddSoftmaxLayer(descriptor, layerName.c_str());
2683
2684 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2685 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2686
Derek Lamberti8ddae332019-02-21 16:29:43 +00002687 RegisterInputSlots(graph, layerIndex, layer);
2688 RegisterOutputSlots(graph, layerIndex, layer);
Kevin May43a799c2019-02-08 16:31:42 +00002689}
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00002690
Finn Williams85d36712021-01-26 22:30:06 +00002691void IDeserializer::DeserializerImpl::ParseSpaceToBatchNd(GraphPtr graph, unsigned int layerIndex)
Nattapat Chaimanowong45286992019-02-26 15:53:02 +00002692{
2693 CHECK_LAYERS(graph, 0, layerIndex);
2694
Finn Williams85d36712021-01-26 22:30:06 +00002695 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Nattapat Chaimanowong45286992019-02-26 15:53:02 +00002696 CHECK_VALID_SIZE(inputs.size(), 1);
2697
Finn Williams85d36712021-01-26 22:30:06 +00002698 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Nattapat Chaimanowong45286992019-02-26 15:53:02 +00002699 CHECK_VALID_SIZE(outputs.size(), 1);
2700
2701 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_SpaceToBatchNdLayer()->descriptor();
2702 auto flatBufferPadList = flatBufferDescriptor->padList();
2703 auto flatBufferBlockShape = flatBufferDescriptor->blockShape();
2704
2705 if (flatBufferPadList->Length() % 2 != 0)
2706 {
Colm Donelan5b5c2222020-09-09 12:48:16 +01002707 throw ParseException(fmt::format("The size of the pad list must be divisible by 2 {}",
2708 CHECK_LOCATION().AsString()));
Nattapat Chaimanowong45286992019-02-26 15:53:02 +00002709 }
2710
2711 std::vector<std::pair<unsigned int, unsigned int>> padList;
2712 padList.reserve(flatBufferPadList->Length() / 2);
2713 for (unsigned int i = 0; i < flatBufferPadList->Length() - 1; i += 2)
2714 {
2715 padList.emplace_back(flatBufferPadList->Get(i), flatBufferPadList->Get(i+1));
2716 }
2717
2718 armnn::SpaceToBatchNdDescriptor descriptor;
2719 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2720 descriptor.m_BlockShape =
2721 std::vector<unsigned int>(flatBufferBlockShape->begin(), flatBufferBlockShape->end());
2722 descriptor.m_PadList = padList;
2723
2724 auto layerName = GetLayerName(graph, layerIndex);
2725 IConnectableLayer* layer = m_Network->AddSpaceToBatchNdLayer(descriptor, layerName.c_str());
2726
2727 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2728 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2729
2730 RegisterInputSlots(graph, layerIndex, layer);
2731 RegisterOutputSlots(graph, layerIndex, layer);
2732}
2733
Finn Williams85d36712021-01-26 22:30:06 +00002734void IDeserializer::DeserializerImpl::ParseSpaceToDepth(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002735{
2736 CHECK_LAYERS(graph, 0, layerIndex);
2737
Finn Williams85d36712021-01-26 22:30:06 +00002738 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002739 CHECK_VALID_SIZE(inputs.size(), 1);
2740
Finn Williams85d36712021-01-26 22:30:06 +00002741 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002742 CHECK_VALID_SIZE(outputs.size(), 1);
2743
2744 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_SpaceToDepthLayer()->descriptor();
2745
2746 armnn::SpaceToDepthDescriptor descriptor;
2747 descriptor.m_BlockSize = flatBufferDescriptor->blockSize();
2748 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2749
2750 auto layerName = GetLayerName(graph, layerIndex);
2751 IConnectableLayer* layer = m_Network->AddSpaceToDepthLayer(descriptor, layerName.c_str());
2752
2753 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2754 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2755
2756 RegisterInputSlots(graph, layerIndex, layer);
2757 RegisterOutputSlots(graph, layerIndex, layer);
2758}
2759
Finn Williams85d36712021-01-26 22:30:06 +00002760armnn::NormalizationDescriptor IDeserializer::DeserializerImpl::GetNormalizationDescriptor(
2761 NormalizationDescriptorPtr normalizationDescriptor,
Nina Drozd57728782019-02-27 10:53:27 +00002762 unsigned int layerIndex)
2763{
Jan Eilers8eb25602020-03-09 12:13:48 +00002764 IgnoreUnused(layerIndex);
Nina Drozd57728782019-02-27 10:53:27 +00002765 armnn::NormalizationDescriptor desc;
2766
2767 switch (normalizationDescriptor->normChannelType())
2768 {
2769 case NormalizationAlgorithmChannel_Across:
2770 {
2771 desc.m_NormChannelType = armnn::NormalizationAlgorithmChannel::Across;
2772 break;
2773 }
2774 case NormalizationAlgorithmChannel_Within:
2775 {
2776 desc.m_NormChannelType = armnn::NormalizationAlgorithmChannel::Within;
2777 break;
2778 }
2779 default:
2780 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01002781 ARMNN_ASSERT_MSG(false, "Unsupported normalization channel type");
Nina Drozd57728782019-02-27 10:53:27 +00002782 }
2783 }
2784
2785 switch (normalizationDescriptor->normMethodType())
2786 {
2787 case NormalizationAlgorithmMethod_LocalBrightness:
2788 {
2789 desc.m_NormMethodType = armnn::NormalizationAlgorithmMethod::LocalBrightness;
2790 break;
2791 }
2792 case NormalizationAlgorithmMethod_LocalContrast:
2793 {
2794 desc.m_NormMethodType = armnn::NormalizationAlgorithmMethod::LocalContrast;
2795 break;
2796 }
2797 default:
2798 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01002799 ARMNN_ASSERT_MSG(false, "Unsupported normalization method type");
Nina Drozd57728782019-02-27 10:53:27 +00002800 }
2801 }
2802
2803 switch (normalizationDescriptor->dataLayout())
2804 {
2805 case DataLayout_NCHW:
2806 {
2807 desc.m_DataLayout = armnn::DataLayout::NCHW;
2808 break;
2809 }
2810 case DataLayout_NHWC:
2811 {
2812 desc.m_DataLayout = armnn::DataLayout::NHWC;
2813 break;
2814 }
2815 default:
2816 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01002817 ARMNN_ASSERT_MSG(false, "Unsupported data layout");
Nina Drozd57728782019-02-27 10:53:27 +00002818 }
2819 }
2820
2821 desc.m_Alpha = normalizationDescriptor->alpha();
2822 desc.m_Beta = normalizationDescriptor->beta();
2823 desc.m_K = normalizationDescriptor->k();
2824 desc.m_NormSize = normalizationDescriptor->normSize();
2825
2826 return desc;
2827}
2828
Finn Williams85d36712021-01-26 22:30:06 +00002829void IDeserializer::DeserializerImpl::ParseNormalization(GraphPtr graph, unsigned int layerIndex)
Nina Drozd57728782019-02-27 10:53:27 +00002830{
2831 CHECK_LAYERS(graph, 0, layerIndex);
2832
2833 auto normalizationDes = graph->layers()->Get(layerIndex)->layer_as_NormalizationLayer()->descriptor();
2834
Finn Williams85d36712021-01-26 22:30:06 +00002835 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Nina Drozd57728782019-02-27 10:53:27 +00002836 CHECK_VALID_SIZE(inputs.size(), 1);
2837
Finn Williams85d36712021-01-26 22:30:06 +00002838 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Nina Drozd57728782019-02-27 10:53:27 +00002839 CHECK_VALID_SIZE(outputs.size(), 1);
2840
2841 auto outputInfo = ToTensorInfo(outputs[0]);
2842
2843 auto normalizationDescriptor = GetNormalizationDescriptor(normalizationDes, layerIndex);
2844 auto layerName = GetLayerName(graph, layerIndex);
2845
2846 IConnectableLayer* layer = m_Network->AddNormalizationLayer(normalizationDescriptor, layerName.c_str());
2847 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2848
2849 RegisterInputSlots(graph, layerIndex, layer);
2850 RegisterOutputSlots(graph, layerIndex, layer);
2851}
2852
Finn Williams85d36712021-01-26 22:30:06 +00002853void IDeserializer::DeserializerImpl::ParseRsqrt(GraphPtr graph, unsigned int layerIndex)
Sadik Armagan8b42a382019-03-01 14:24:49 +00002854{
2855 CHECK_LAYERS(graph, 0, layerIndex);
2856 auto inputs = GetInputs(graph, layerIndex);
2857 CHECK_LOCATION();
2858 CHECK_VALID_SIZE(inputs.size(), 1);
2859
2860 auto outputs = GetOutputs(graph, layerIndex);
2861 CHECK_VALID_SIZE(outputs.size(), 1);
2862
2863 auto layerName = GetLayerName(graph, layerIndex);
Sadik Armagan8b42a382019-03-01 14:24:49 +00002864
josh minor4a3c6102020-01-06 16:40:46 -06002865 armnn::ElementwiseUnaryDescriptor descriptor(armnn::UnaryOperation::Rsqrt);
2866 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
Sadik Armagan8b42a382019-03-01 14:24:49 +00002867 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2868 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2869
2870 RegisterInputSlots(graph, layerIndex, layer);
2871 RegisterOutputSlots(graph, layerIndex, layer);
2872}
2873
Finn Williams85d36712021-01-26 22:30:06 +00002874void IDeserializer::DeserializerImpl::ParseSlice(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Tar2fda80b2019-09-18 13:36:52 +01002875{
2876 CHECK_LAYERS(graph, 0, layerIndex);
2877
2878 auto inputs = GetInputs(graph, layerIndex);
2879 CHECK_VALID_SIZE(inputs.size(), 1);
2880
2881 auto outputs = GetOutputs(graph, layerIndex);
2882 CHECK_VALID_SIZE(outputs.size(), 1);
2883
2884 auto fbDescriptor = graph->layers()->Get(layerIndex)->layer_as_SliceLayer()->descriptor();
2885
2886 auto fbBegin = fbDescriptor->begin();
2887 auto fbSize = fbDescriptor->size();
2888
2889 if (fbBegin->Length() != fbSize->Length())
2890 {
Colm Donelan5b5c2222020-09-09 12:48:16 +01002891 throw ParseException(fmt::format("Begin and size descriptors must have the same length {}",
2892 CHECK_LOCATION().AsString()));
Aron Virginas-Tar2fda80b2019-09-18 13:36:52 +01002893 }
2894
2895 armnn::SliceDescriptor descriptor;
2896 descriptor.m_Begin.insert(descriptor.m_Begin.end(), fbBegin->begin(), fbBegin->end());
2897 descriptor.m_Size.insert(descriptor.m_Size.end(), fbSize->begin(), fbSize->end());
2898
2899 auto layerName = GetLayerName(graph, layerIndex);
2900 IConnectableLayer* layer = m_Network->AddSliceLayer(descriptor, layerName.c_str());
2901
2902 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2903 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2904
2905 RegisterInputSlots(graph, layerIndex, layer);
2906 RegisterOutputSlots(graph, layerIndex, layer);
2907}
2908
Finn Williams85d36712021-01-26 22:30:06 +00002909void IDeserializer::DeserializerImpl::ParseStridedSlice(GraphPtr graph, unsigned int layerIndex)
Nattapat Chaimanowongb3485212019-03-04 12:35:39 +00002910{
2911 CHECK_LAYERS(graph, 0, layerIndex);
2912
Finn Williams85d36712021-01-26 22:30:06 +00002913 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Nattapat Chaimanowongb3485212019-03-04 12:35:39 +00002914 CHECK_VALID_SIZE(inputs.size(), 1);
2915
Finn Williams85d36712021-01-26 22:30:06 +00002916 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Nattapat Chaimanowongb3485212019-03-04 12:35:39 +00002917 CHECK_VALID_SIZE(outputs.size(), 1);
2918
2919 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_StridedSliceLayer()->descriptor();
2920
2921 auto flatBufferBegin = flatBufferDescriptor->begin();
2922 auto flatBufferEnd = flatBufferDescriptor->end();
2923 auto flatBufferStride = flatBufferDescriptor->stride();
2924
2925 if (!(flatBufferBegin->Length() == flatBufferEnd->Length() &&
2926 flatBufferBegin->Length() == flatBufferStride->Length()))
2927 {
Colm Donelan5b5c2222020-09-09 12:48:16 +01002928 throw ParseException(fmt::format("The size of the begin, end, and stride must be equal {}",
2929 CHECK_LOCATION().AsString()));
Nattapat Chaimanowongb3485212019-03-04 12:35:39 +00002930 }
2931
2932 std::vector<int> begin(flatBufferBegin->begin(), flatBufferBegin->end());
2933 std::vector<int> end(flatBufferEnd->begin(), flatBufferEnd->end());
2934 std::vector<int> stride(flatBufferStride->begin(), flatBufferStride->end());
2935
2936 armnn::StridedSliceDescriptor descriptor(begin, end, stride);
2937 descriptor.m_BeginMask = flatBufferDescriptor->beginMask();
2938 descriptor.m_EndMask = flatBufferDescriptor->endMask();
2939 descriptor.m_ShrinkAxisMask = flatBufferDescriptor->shrinkAxisMask();
2940 descriptor.m_EllipsisMask = flatBufferDescriptor->ellipsisMask();
2941 descriptor.m_NewAxisMask = flatBufferDescriptor->newAxisMask();
2942 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2943
2944 auto layerName = GetLayerName(graph, layerIndex);
2945 IConnectableLayer* layer = m_Network->AddStridedSliceLayer(descriptor, layerName.c_str());
2946
2947 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2948 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2949
2950 RegisterInputSlots(graph, layerIndex, layer);
2951 RegisterOutputSlots(graph, layerIndex, layer);
2952}
2953
Finn Williams85d36712021-01-26 22:30:06 +00002954void IDeserializer::DeserializerImpl::ParseSubtraction(GraphPtr graph, unsigned int layerIndex)
Conor Kennedyda1f9752019-03-01 14:37:12 +00002955{
2956 CHECK_LAYERS(graph, 0, layerIndex);
2957 auto inputs = GetInputs(graph, layerIndex);
2958 CHECK_LOCATION();
2959 CHECK_VALID_SIZE(inputs.size(), 2);
2960
2961 auto outputs = GetOutputs(graph, layerIndex);
2962 CHECK_VALID_SIZE(outputs.size(), 1);
2963
2964 auto layerName = GetLayerName(graph, layerIndex);
2965 IConnectableLayer* layer = m_Network->AddSubtractionLayer(layerName.c_str());
2966
2967 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2968 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2969
2970 RegisterInputSlots(graph, layerIndex, layer);
2971 RegisterOutputSlots(graph, layerIndex, layer);
2972}
2973
Finn Williams85d36712021-01-26 22:30:06 +00002974void IDeserializer::DeserializerImpl::ParseGather(GraphPtr graph, unsigned int layerIndex)
Saoirse Stewarta1ed73a2019-03-04 13:40:12 +00002975{
2976 CHECK_LAYERS(graph, 0, layerIndex);
2977
Finn Williams85d36712021-01-26 22:30:06 +00002978 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Saoirse Stewarta1ed73a2019-03-04 13:40:12 +00002979 CHECK_VALID_SIZE(inputs.size(), 2);
2980
Finn Williams85d36712021-01-26 22:30:06 +00002981 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Saoirse Stewarta1ed73a2019-03-04 13:40:12 +00002982 CHECK_VALID_SIZE(outputs.size(), 1);
2983
Teresa Charlin52664732020-06-29 16:27:03 +01002984 armnn::GatherDescriptor descriptor;
2985 descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_GatherLayer()->descriptor()->axis();
2986
Saoirse Stewarta1ed73a2019-03-04 13:40:12 +00002987 auto layerName = GetLayerName(graph, layerIndex);
Teresa Charlin52664732020-06-29 16:27:03 +01002988 IConnectableLayer* layer = m_Network->AddGatherLayer(descriptor, layerName.c_str());
Saoirse Stewarta1ed73a2019-03-04 13:40:12 +00002989
2990 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
Saoirse Stewarta1ed73a2019-03-04 13:40:12 +00002991 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2992
2993 RegisterInputSlots(graph, layerIndex, layer);
2994 RegisterOutputSlots(graph, layerIndex, layer);
Saoirse Stewarta1ed73a2019-03-04 13:40:12 +00002995}
2996
Teresa Charlin6966bfa2022-04-25 17:14:50 +01002997void IDeserializer::DeserializerImpl::ParseGatherNd(GraphPtr graph, unsigned int layerIndex)
2998{
2999 CHECK_LAYERS(graph, 0, layerIndex);
3000
3001 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
3002 CHECK_VALID_SIZE(inputs.size(), 2);
3003
3004 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
3005 CHECK_VALID_SIZE(outputs.size(), 1);
3006
3007 auto layerName = GetLayerName(graph, layerIndex);
3008 IConnectableLayer* layer = m_Network->AddGatherNdLayer(layerName.c_str());
3009
3010 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3011 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3012
3013 RegisterInputSlots(graph, layerIndex, layer);
3014 RegisterOutputSlots(graph, layerIndex, layer);
3015}
3016
Finn Williams85d36712021-01-26 22:30:06 +00003017void IDeserializer::DeserializerImpl::ParseMean(GraphPtr graph, unsigned int layerIndex)
Sadik Armaganac97c8c2019-03-04 17:44:21 +00003018{
3019 CHECK_LAYERS(graph, 0, layerIndex);
3020
Finn Williams85d36712021-01-26 22:30:06 +00003021 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Sadik Armaganac97c8c2019-03-04 17:44:21 +00003022 CHECK_VALID_SIZE(inputs.size(), 1);
3023
Finn Williams85d36712021-01-26 22:30:06 +00003024 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Sadik Armaganac97c8c2019-03-04 17:44:21 +00003025 CHECK_VALID_SIZE(outputs.size(), 1);
3026
3027 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_MeanLayer()->descriptor();
3028 auto flatBufferAxis = flatBufferDescriptor->axis();
3029 auto flatBufferKeepDims = flatBufferDescriptor->keepDims();
3030
3031 armnn::MeanDescriptor descriptor;
3032 descriptor.m_Axis = std::vector<unsigned int>(flatBufferAxis->begin(), flatBufferAxis->end());
3033 descriptor.m_KeepDims = flatBufferKeepDims;
3034
3035 auto layerName = GetLayerName(graph, layerIndex);
3036 IConnectableLayer* layer = m_Network->AddMeanLayer(descriptor, layerName.c_str());
3037
3038 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3039 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3040
3041 RegisterInputSlots(graph, layerIndex, layer);
3042 RegisterOutputSlots(graph, layerIndex, layer);
3043}
3044
Finn Williams85d36712021-01-26 22:30:06 +00003045void IDeserializer::DeserializerImpl::ParseSplitter(GraphPtr graph, unsigned int layerIndex)
Jim Flynn18ce3382019-03-08 11:08:30 +00003046{
3047 CHECK_LAYERS(graph, 0, layerIndex);
3048
Finn Williams85d36712021-01-26 22:30:06 +00003049 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Jim Flynn18ce3382019-03-08 11:08:30 +00003050 CHECK_VALID_SIZE(inputs.size(), 1);
3051
Finn Williams85d36712021-01-26 22:30:06 +00003052 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Jim Flynn18ce3382019-03-08 11:08:30 +00003053
3054 auto flatBufferViewsDescriptor = graph->layers()->Get(layerIndex)->layer_as_SplitterLayer()->descriptor();
3055 auto flatBufferViewSizes = flatBufferViewsDescriptor->viewSizes();
3056 auto flatBufferOriginsDescriptor = flatBufferViewsDescriptor->origins();
3057 auto flatBufferViewOrigins = flatBufferOriginsDescriptor->viewOrigins();
3058 uint32_t numViews = flatBufferOriginsDescriptor->numViews();
3059 uint32_t numDimensions = flatBufferOriginsDescriptor->numDimensions();
3060
3061 // Check numViews and numDimensions corresponds to the ones already serialized ...
3062 // numViews == flatBufferViewSizes.size();
3063 // foreach: numDimensions == flatBufferViewSizes[x].size();
3064
3065 armnn::ViewsDescriptor viewsDescriptor(numViews, numDimensions);
3066 for(unsigned int vIdx = 0; vIdx < numViews; ++vIdx)
3067 {
3068 for (unsigned int dIdx = 0; dIdx < numDimensions; ++dIdx)
3069 {
3070 viewsDescriptor.SetViewSize(vIdx, dIdx, flatBufferViewSizes->Get(vIdx)->data()->Get(dIdx));
3071 viewsDescriptor.SetViewOriginCoord(vIdx, dIdx, flatBufferViewOrigins->Get(vIdx)->data()->Get(dIdx));
3072 }
3073 }
3074
3075 auto layerName = GetLayerName(graph, layerIndex);
3076 IConnectableLayer* layer = m_Network->AddSplitterLayer(viewsDescriptor, layerName.c_str());
3077
3078 // I could have as many outputs as views ...
3079 for(unsigned int vIdx = 0; vIdx < numViews; ++vIdx)
3080 {
3081 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[vIdx]);
3082 layer->GetOutputSlot(vIdx).SetTensorInfo(outputTensorInfo);
3083 }
3084
3085 RegisterInputSlots(graph, layerIndex, layer);
3086 RegisterOutputSlots(graph, layerIndex, layer);
3087}
3088
Finn Williams85d36712021-01-26 22:30:06 +00003089armnn::LstmDescriptor IDeserializer::DeserializerImpl::GetLstmDescriptor(LstmDescriptorPtr lstmDescriptor)
Jim Flynn11af3752019-03-19 17:22:29 +00003090{
3091 armnn::LstmDescriptor desc;
3092
3093 desc.m_ActivationFunc = lstmDescriptor->activationFunc();
3094 desc.m_ClippingThresCell = lstmDescriptor->clippingThresCell();
3095 desc.m_ClippingThresProj = lstmDescriptor->clippingThresProj();
3096 desc.m_CifgEnabled = lstmDescriptor->cifgEnabled();
3097 desc.m_PeepholeEnabled = lstmDescriptor->peepholeEnabled();
3098 desc.m_ProjectionEnabled = lstmDescriptor->projectionEnabled();
Jan Eilersf8c62972019-07-17 11:07:49 +01003099 desc.m_LayerNormEnabled = lstmDescriptor->layerNormEnabled();
Jim Flynn11af3752019-03-19 17:22:29 +00003100
3101 return desc;
3102}
3103
Finn Williams85d36712021-01-26 22:30:06 +00003104void IDeserializer::DeserializerImpl::ParseLstm(GraphPtr graph, unsigned int layerIndex)
Jim Flynn11af3752019-03-19 17:22:29 +00003105{
3106 CHECK_LAYERS(graph, 0, layerIndex);
3107
3108 auto inputs = GetInputs(graph, layerIndex);
3109 CHECK_VALID_SIZE(inputs.size(), 3);
3110
3111 auto outputs = GetOutputs(graph, layerIndex);
3112 CHECK_VALID_SIZE(outputs.size(), 4);
3113
3114 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_LstmLayer();
3115 auto layerName = GetLayerName(graph, layerIndex);
3116 auto flatBufferDescriptor = flatBufferLayer->descriptor();
3117 auto flatBufferInputParams = flatBufferLayer->inputParams();
3118
3119 auto lstmDescriptor = GetLstmDescriptor(flatBufferDescriptor);
3120
3121 armnn::LstmInputParams lstmInputParams;
3122
3123 armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
3124 armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
3125 armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
3126 armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
3127 armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
3128 armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
3129 armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
3130 armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
3131 armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
3132
3133 lstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
3134 lstmInputParams.m_InputToCellWeights = &inputToCellWeights;
3135 lstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
3136 lstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3137 lstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
3138 lstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3139 lstmInputParams.m_ForgetGateBias = &forgetGateBias;
3140 lstmInputParams.m_CellBias = &cellBias;
3141 lstmInputParams.m_OutputGateBias = &outputGateBias;
3142
3143 armnn::ConstTensor inputToInputWeights;
3144 armnn::ConstTensor recurrentToInputWeights;
3145 armnn::ConstTensor cellToInputWeights;
3146 armnn::ConstTensor inputGateBias;
3147 if (!lstmDescriptor.m_CifgEnabled)
3148 {
3149 inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
3150 recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
3151 cellToInputWeights = ToConstTensor(flatBufferInputParams->cellToInputWeights());
3152 inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
3153
3154 lstmInputParams.m_InputToInputWeights = &inputToInputWeights;
3155 lstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
3156 lstmInputParams.m_CellToInputWeights = &cellToInputWeights;
3157 lstmInputParams.m_InputGateBias = &inputGateBias;
3158 }
3159
3160 armnn::ConstTensor projectionWeights;
3161 armnn::ConstTensor projectionBias;
3162 if (lstmDescriptor.m_ProjectionEnabled)
3163 {
3164 projectionWeights = ToConstTensor(flatBufferInputParams->projectionWeights());
3165 projectionBias = ToConstTensor(flatBufferInputParams->projectionBias());
3166
3167 lstmInputParams.m_ProjectionWeights = &projectionWeights;
3168 lstmInputParams.m_ProjectionBias = &projectionBias;
3169 }
3170
3171 armnn::ConstTensor cellToForgetWeights;
3172 armnn::ConstTensor cellToOutputWeights;
3173 if (lstmDescriptor.m_PeepholeEnabled)
3174 {
3175 cellToForgetWeights = ToConstTensor(flatBufferInputParams->cellToForgetWeights());
3176 cellToOutputWeights = ToConstTensor(flatBufferInputParams->cellToOutputWeights());
3177
3178 lstmInputParams.m_CellToForgetWeights = &cellToForgetWeights;
3179 lstmInputParams.m_CellToOutputWeights = &cellToOutputWeights;
3180 }
3181
Jan Eilersf8c62972019-07-17 11:07:49 +01003182 armnn::ConstTensor inputLayerNormWeights;
3183 armnn::ConstTensor forgetLayerNormWeights;
3184 armnn::ConstTensor cellLayerNormWeights;
3185 armnn::ConstTensor outputLayerNormWeights;
3186 if (lstmDescriptor.m_LayerNormEnabled)
3187 {
3188 if (!lstmDescriptor.m_CifgEnabled)
3189 {
3190 inputLayerNormWeights = ToConstTensor(flatBufferInputParams->inputLayerNormWeights());
3191 lstmInputParams.m_InputLayerNormWeights = &inputLayerNormWeights;
3192 }
3193 forgetLayerNormWeights = ToConstTensor(flatBufferInputParams->forgetLayerNormWeights());
3194 cellLayerNormWeights = ToConstTensor(flatBufferInputParams->cellLayerNormWeights());
3195 outputLayerNormWeights = ToConstTensor(flatBufferInputParams->outputLayerNormWeights());
3196
3197 lstmInputParams.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
3198 lstmInputParams.m_CellLayerNormWeights = &cellLayerNormWeights;
3199 lstmInputParams.m_OutputLayerNormWeights = &outputLayerNormWeights;
3200 }
3201
Jim Flynn11af3752019-03-19 17:22:29 +00003202 IConnectableLayer* layer = m_Network->AddLstmLayer(lstmDescriptor, lstmInputParams, layerName.c_str());
3203
3204 armnn::TensorInfo outputTensorInfo1 = ToTensorInfo(outputs[0]);
3205 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo1);
3206
3207 armnn::TensorInfo outputTensorInfo2 = ToTensorInfo(outputs[1]);
3208 layer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo2);
3209
3210 armnn::TensorInfo outputTensorInfo3 = ToTensorInfo(outputs[2]);
3211 layer->GetOutputSlot(2).SetTensorInfo(outputTensorInfo3);
3212
3213 armnn::TensorInfo outputTensorInfo4 = ToTensorInfo(outputs[3]);
3214 layer->GetOutputSlot(3).SetTensorInfo(outputTensorInfo4);
3215
3216 RegisterInputSlots(graph, layerIndex, layer);
3217 RegisterOutputSlots(graph, layerIndex, layer);
3218}
3219
Finn Williams85d36712021-01-26 22:30:06 +00003220armnn::QLstmDescriptor IDeserializer::DeserializerImpl::GetQLstmDescriptor(QLstmDescriptorPtr qLstmDescriptor)
James Conroy8d333182020-05-13 10:27:58 +01003221{
3222 armnn::QLstmDescriptor desc;
3223
3224 desc.m_CifgEnabled = qLstmDescriptor->cifgEnabled();
3225 desc.m_PeepholeEnabled = qLstmDescriptor->peepholeEnabled();
3226 desc.m_ProjectionEnabled = qLstmDescriptor->projectionEnabled();
3227 desc.m_LayerNormEnabled = qLstmDescriptor->layerNormEnabled();
3228
3229 desc.m_CellClip = qLstmDescriptor->cellClip();
3230 desc.m_ProjectionClip = qLstmDescriptor->projectionClip();
3231
3232 desc.m_InputIntermediateScale = qLstmDescriptor->inputIntermediateScale();
3233 desc.m_ForgetIntermediateScale = qLstmDescriptor->forgetIntermediateScale();
3234 desc.m_CellIntermediateScale = qLstmDescriptor->cellIntermediateScale();
3235 desc.m_OutputIntermediateScale = qLstmDescriptor->outputIntermediateScale();
3236
3237 desc.m_HiddenStateScale = qLstmDescriptor->hiddenStateScale();
3238 desc.m_HiddenStateZeroPoint = qLstmDescriptor->hiddenStateZeroPoint();
3239
3240 return desc;
3241}
3242
Finn Williams85d36712021-01-26 22:30:06 +00003243void IDeserializer::DeserializerImpl::ParseQLstm(GraphPtr graph, unsigned int layerIndex)
James Conroy8d333182020-05-13 10:27:58 +01003244{
3245 CHECK_LAYERS(graph, 0, layerIndex);
3246
3247 auto inputs = GetInputs(graph, layerIndex);
3248 CHECK_VALID_SIZE(inputs.size(), 3);
3249
3250 auto outputs = GetOutputs(graph, layerIndex);
3251 CHECK_VALID_SIZE(outputs.size(), 3);
3252
3253 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_QLstmLayer();
3254 auto layerName = GetLayerName(graph, layerIndex);
3255 auto flatBufferDescriptor = flatBufferLayer->descriptor();
3256 auto flatBufferInputParams = flatBufferLayer->inputParams();
3257
3258 auto qLstmDescriptor = GetQLstmDescriptor(flatBufferDescriptor);
3259 armnn::LstmInputParams qLstmInputParams;
3260
3261 // Mandatory params
3262 armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
3263 armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
3264 armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
3265 armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
3266 armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
3267 armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
3268 armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
3269 armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
3270 armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
3271
3272 qLstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
3273 qLstmInputParams.m_InputToCellWeights = &inputToCellWeights;
3274 qLstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
3275 qLstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3276 qLstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
3277 qLstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3278 qLstmInputParams.m_ForgetGateBias = &forgetGateBias;
3279 qLstmInputParams.m_CellBias = &cellBias;
3280 qLstmInputParams.m_OutputGateBias = &outputGateBias;
3281
3282 // Optional CIFG params
3283 armnn::ConstTensor inputToInputWeights;
3284 armnn::ConstTensor recurrentToInputWeights;
3285 armnn::ConstTensor inputGateBias;
3286
3287 if (!qLstmDescriptor.m_CifgEnabled)
3288 {
3289 inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
3290 recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
3291 inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
3292
3293 qLstmInputParams.m_InputToInputWeights = &inputToInputWeights;
3294 qLstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
3295 qLstmInputParams.m_InputGateBias = &inputGateBias;
3296 }
3297
3298 // Optional projection params
3299 armnn::ConstTensor projectionWeights;
3300 armnn::ConstTensor projectionBias;
3301
3302 if (qLstmDescriptor.m_ProjectionEnabled)
3303 {
3304 projectionWeights = ToConstTensor(flatBufferInputParams->projectionWeights());
3305 projectionBias = ToConstTensor(flatBufferInputParams->projectionBias());
3306
3307 qLstmInputParams.m_ProjectionWeights = &projectionWeights;
3308 qLstmInputParams.m_ProjectionBias = &projectionBias;
3309 }
3310
3311 // Optional peephole params
3312 armnn::ConstTensor cellToInputWeights;
3313 armnn::ConstTensor cellToForgetWeights;
3314 armnn::ConstTensor cellToOutputWeights;
3315
3316 if (qLstmDescriptor.m_PeepholeEnabled)
3317 {
3318 if (!qLstmDescriptor.m_CifgEnabled)
3319 {
3320 cellToInputWeights = ToConstTensor(flatBufferInputParams->cellToInputWeights());
3321 qLstmInputParams.m_CellToInputWeights = &cellToInputWeights;
3322 }
3323
3324 cellToForgetWeights = ToConstTensor(flatBufferInputParams->cellToForgetWeights());
3325 cellToOutputWeights = ToConstTensor(flatBufferInputParams->cellToOutputWeights());
3326
3327 qLstmInputParams.m_CellToForgetWeights = &cellToForgetWeights;
3328 qLstmInputParams.m_CellToOutputWeights = &cellToOutputWeights;
3329 }
3330
3331 // Optional layer norm params
3332 armnn::ConstTensor inputLayerNormWeights;
3333 armnn::ConstTensor forgetLayerNormWeights;
3334 armnn::ConstTensor cellLayerNormWeights;
3335 armnn::ConstTensor outputLayerNormWeights;
3336
3337 if (qLstmDescriptor.m_LayerNormEnabled)
3338 {
3339 if (!qLstmDescriptor.m_CifgEnabled)
3340 {
3341 inputLayerNormWeights = ToConstTensor(flatBufferInputParams->inputLayerNormWeights());
3342 qLstmInputParams.m_InputLayerNormWeights = &inputLayerNormWeights;
3343 }
3344
3345 forgetLayerNormWeights = ToConstTensor(flatBufferInputParams->forgetLayerNormWeights());
3346 cellLayerNormWeights = ToConstTensor(flatBufferInputParams->cellLayerNormWeights());
3347 outputLayerNormWeights = ToConstTensor(flatBufferInputParams->outputLayerNormWeights());
3348
3349 qLstmInputParams.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
3350 qLstmInputParams.m_CellLayerNormWeights = &cellLayerNormWeights;
3351 qLstmInputParams.m_OutputLayerNormWeights = &outputLayerNormWeights;
3352 }
3353
3354 IConnectableLayer* layer = m_Network->AddQLstmLayer(qLstmDescriptor, qLstmInputParams, layerName.c_str());
3355
3356 armnn::TensorInfo outputStateOutInfo = ToTensorInfo(outputs[0]);
3357 layer->GetOutputSlot(0).SetTensorInfo(outputStateOutInfo);
3358
3359 armnn::TensorInfo cellStateOutInfo = ToTensorInfo(outputs[1]);
3360 layer->GetOutputSlot(1).SetTensorInfo(cellStateOutInfo);
3361
3362 armnn::TensorInfo outputInfo = ToTensorInfo(outputs[2]);
3363 layer->GetOutputSlot(2).SetTensorInfo(outputInfo);
3364
3365 RegisterInputSlots(graph, layerIndex, layer);
3366 RegisterOutputSlots(graph, layerIndex, layer);
3367}
3368
Finn Williams85d36712021-01-26 22:30:06 +00003369void IDeserializer::DeserializerImpl::ParseQuantizedLstm(GraphPtr graph, unsigned int layerIndex)
Jan Eilers5b01a892019-07-23 09:47:43 +01003370{
3371 CHECK_LAYERS(graph, 0, layerIndex);
3372
3373 auto inputs = GetInputs(graph, layerIndex);
3374 CHECK_VALID_SIZE(inputs.size(), 3);
3375
3376 auto outputs = GetOutputs(graph, layerIndex);
3377 CHECK_VALID_SIZE(outputs.size(), 2);
3378
3379 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_QuantizedLstmLayer();
3380 auto layerName = GetLayerName(graph, layerIndex);
3381 auto flatBufferInputParams = flatBufferLayer->inputParams();
3382
3383 armnn::QuantizedLstmInputParams lstmInputParams;
3384
3385 armnn::ConstTensor inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
3386 armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
3387 armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
3388 armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
3389 armnn::ConstTensor recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
3390 armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
3391 armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
3392 armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
3393 armnn::ConstTensor inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
3394 armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
3395 armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
3396 armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
3397
3398 lstmInputParams.m_InputToInputWeights = &inputToInputWeights;
3399 lstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
3400 lstmInputParams.m_InputToCellWeights = &inputToCellWeights;
3401 lstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
3402 lstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
3403 lstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3404 lstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
3405 lstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3406 lstmInputParams.m_InputGateBias = &inputGateBias;
3407 lstmInputParams.m_ForgetGateBias = &forgetGateBias;
3408 lstmInputParams.m_CellBias = &cellBias;
3409 lstmInputParams.m_OutputGateBias = &outputGateBias;
3410
3411 IConnectableLayer* layer = m_Network->AddQuantizedLstmLayer(lstmInputParams, layerName.c_str());
3412
3413 armnn::TensorInfo outputTensorInfo1 = ToTensorInfo(outputs[0]);
3414 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo1);
3415
3416 armnn::TensorInfo outputTensorInfo2 = ToTensorInfo(outputs[1]);
3417 layer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo2);
3418
3419 RegisterInputSlots(graph, layerIndex, layer);
3420 RegisterOutputSlots(graph, layerIndex, layer);
3421}
3422
Finn Williams85d36712021-01-26 22:30:06 +00003423void IDeserializer::DeserializerImpl::ParseDequantize(GraphPtr graph, unsigned int layerIndex)
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +00003424{
3425 CHECK_LAYERS(graph, 0, layerIndex);
3426
Finn Williams85d36712021-01-26 22:30:06 +00003427 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +00003428 CHECK_VALID_SIZE(inputs.size(), 1);
3429
Finn Williams85d36712021-01-26 22:30:06 +00003430 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +00003431 CHECK_VALID_SIZE(outputs.size(), 1);
3432
3433 const std::string layerName = GetLayerName(graph, layerIndex);
3434 IConnectableLayer* layer = m_Network->AddDequantizeLayer(layerName.c_str());
3435
3436 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3437 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3438
3439 RegisterInputSlots(graph, layerIndex, layer);
3440 RegisterOutputSlots(graph, layerIndex, layer);
3441}
3442
Finn Williams85d36712021-01-26 22:30:06 +00003443void IDeserializer::DeserializerImpl::ParseMerge(GraphPtr graph, unsigned int layerIndex)
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01003444{
3445 CHECK_LAYERS(graph, 0, layerIndex);
3446
Finn Williams85d36712021-01-26 22:30:06 +00003447 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01003448 CHECK_VALID_SIZE(inputs.size(), 2);
3449
Finn Williams85d36712021-01-26 22:30:06 +00003450 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01003451 CHECK_VALID_SIZE(outputs.size(), 1);
3452
3453 const std::string layerName = GetLayerName(graph, layerIndex);
3454 IConnectableLayer* layer = m_Network->AddMergeLayer(layerName.c_str());
3455
3456 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3457 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3458
3459 RegisterInputSlots(graph, layerIndex, layer);
3460 RegisterOutputSlots(graph, layerIndex, layer);
3461}
3462
Finn Williams85d36712021-01-26 22:30:06 +00003463void IDeserializer::DeserializerImpl::ParseSwitch(GraphPtr graph, unsigned int layerIndex)
Sadik Armaganeff363d2019-04-05 15:25:46 +01003464{
3465 CHECK_LAYERS(graph, 0, layerIndex);
3466 auto inputs = GetInputs(graph, layerIndex);
3467 CHECK_LOCATION();
3468 CHECK_VALID_SIZE(inputs.size(), 2);
3469
3470 auto outputs = GetOutputs(graph, layerIndex);
3471 CHECK_VALID_SIZE(outputs.size(), 2);
3472
3473 auto layerName = GetLayerName(graph, layerIndex);
3474 IConnectableLayer* layer = m_Network->AddSwitchLayer(layerName.c_str());
3475
3476 armnn::TensorInfo output0TensorInfo = ToTensorInfo(outputs[0]);
3477 layer->GetOutputSlot(0).SetTensorInfo(output0TensorInfo);
3478
3479 armnn::TensorInfo output1TensorInfo = ToTensorInfo(outputs[1]);
3480 layer->GetOutputSlot(1).SetTensorInfo(output1TensorInfo);
3481
3482 RegisterInputSlots(graph, layerIndex, layer);
3483 RegisterOutputSlots(graph, layerIndex, layer);
3484}
3485
Finn Williams85d36712021-01-26 22:30:06 +00003486void IDeserializer::DeserializerImpl::ParsePrelu(GraphPtr graph, unsigned int layerIndex)
Ellen Norris-Thompson51982472019-06-19 11:46:21 +01003487{
3488 CHECK_LAYERS(graph, 0, layerIndex);
3489 auto inputs = GetInputs(graph, layerIndex);
3490 CHECK_LOCATION();
3491 CHECK_VALID_SIZE(inputs.size(), 2);
3492
3493 auto outputs = GetOutputs(graph, layerIndex);
3494 CHECK_VALID_SIZE(outputs.size(), 1);
3495
3496 auto layerName = GetLayerName(graph, layerIndex);
3497 IConnectableLayer* layer = m_Network->AddPreluLayer(layerName.c_str());
3498
3499 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3500 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3501
3502 RegisterInputSlots(graph, layerIndex, layer);
3503 RegisterOutputSlots(graph, layerIndex, layer);
3504}
3505
Finn Williams85d36712021-01-26 22:30:06 +00003506void IDeserializer::DeserializerImpl::ParseTranspose(GraphPtr graph, unsigned int layerIndex)
Mike Kellyc9ea45a2020-02-28 18:11:58 +00003507{
3508 CHECK_LAYERS(graph, 0, layerIndex);
3509
3510 auto dimsMapping = graph->layers()->Get(layerIndex)->layer_as_TransposeLayer()->descriptor()->dimMappings();
3511
3512 auto inputs = GetInputs(graph, layerIndex);
3513 CHECK_VALID_SIZE(inputs.size(), 1);
3514
3515 auto outputs = GetOutputs(graph, layerIndex);
3516 CHECK_VALID_SIZE(outputs.size(), 1);
3517 auto outputInfo = ToTensorInfo(outputs[0]);
3518
3519 auto layerName = GetLayerName(graph, layerIndex);
3520 const armnn::TransposeDescriptor descriptor(armnn::PermutationVector(dimsMapping->data(), dimsMapping->Length()));
3521
3522 IConnectableLayer* layer = m_Network->AddTransposeLayer(descriptor, layerName.c_str());
3523 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
3524
3525 RegisterInputSlots(graph, layerIndex, layer);
3526 RegisterOutputSlots(graph, layerIndex, layer);
3527}
3528
Finn Williams85d36712021-01-26 22:30:06 +00003529void IDeserializer::DeserializerImpl::ParseTransposeConvolution2d(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01003530{
3531 CHECK_LAYERS(graph, 0, layerIndex);
3532
3533 auto inputs = GetInputs(graph, layerIndex);
3534 CHECK_VALID_SIZE(inputs.size(), 1);
3535
3536 auto outputs = GetOutputs(graph, layerIndex);
3537 CHECK_VALID_SIZE(outputs.size(), 1);
3538
3539 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_TransposeConvolution2dLayer();
3540 auto layerName = GetLayerName(graph, layerIndex);
3541 auto serializerDescriptor = serializerLayer->descriptor();
3542
3543 armnn::TransposeConvolution2dDescriptor descriptor;
3544 descriptor.m_PadLeft = serializerDescriptor->padLeft();
3545 descriptor.m_PadRight = serializerDescriptor->padRight();
3546 descriptor.m_PadTop = serializerDescriptor->padTop();
3547 descriptor.m_PadBottom = serializerDescriptor->padBottom();
3548 descriptor.m_StrideX = serializerDescriptor->strideX();
3549 descriptor.m_StrideY = serializerDescriptor->strideY();;
3550 descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
3551 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
3552
3553 // weights & biases
3554 armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
3555 armnn::Optional<armnn::ConstTensor> optionalBiases;
3556 if (descriptor.m_BiasEnabled)
3557 {
3558 armnn::ConstTensor biases = ToConstTensor(serializerLayer->biases());
3559 optionalBiases = armnn::MakeOptional<armnn::ConstTensor>(biases);
3560 }
3561
3562 IConnectableLayer* layer = m_Network->AddTransposeConvolution2dLayer(descriptor,
3563 weights,
3564 optionalBiases,
3565 layerName.c_str());
3566
3567 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3568 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3569
3570 RegisterInputSlots(graph, layerIndex, layer);
3571 RegisterOutputSlots(graph, layerIndex, layer);
3572}
3573
Finn Williams85d36712021-01-26 22:30:06 +00003574void IDeserializer::DeserializerImpl::ParseStack(GraphPtr graph, unsigned int layerIndex)
Matthew Jacksonb5433ee2019-07-11 15:54:20 +01003575{
3576 CHECK_LAYERS(graph, 0, layerIndex);
3577 auto inputs = GetInputs(graph, layerIndex);
3578
3579 auto outputs = GetOutputs(graph, layerIndex);
3580 CHECK_VALID_SIZE(outputs.size(), 1);
3581
3582 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_StackLayer()->descriptor();
3583 unsigned int axis = flatBufferDescriptor->axis();
3584 unsigned int numInputs = flatBufferDescriptor->numInputs();
3585 CHECK_VALID_SIZE(inputs.size(), numInputs);
3586
3587 auto flatBufferInputShape = flatBufferDescriptor->inputShape();
3588 std::vector<uint32_t> vectorInputShape(flatBufferInputShape->begin(),
3589 flatBufferInputShape->begin() + flatBufferInputShape->size());
3590
3591 TensorShape inputShape(static_cast<unsigned int>(vectorInputShape.size()), vectorInputShape.data());
3592 armnn::StackDescriptor descriptor(axis, numInputs, inputShape);
3593
3594 for (unsigned int i=0; i<inputs.size(); ++i)
3595 {
Matthew Bentham75ae2b02019-09-19 12:04:13 +01003596 armnn::TensorShape inputShape = ToTensorInfo(inputs[i]).GetShape();
Matthew Jacksonb5433ee2019-07-11 15:54:20 +01003597 if (descriptor.m_InputShape != inputShape)
3598 {
3599 std::stringstream ss;
3600 ss << "Shape of input "
3601 << i
3602 << " "
3603 << inputShape
3604 << " does not equal defined input shape "
3605 << descriptor.m_InputShape
3606 << ": "
3607 << CHECK_LOCATION().AsString();
3608 throw ParseException(ss.str());
3609 }
3610 }
3611
3612 auto layerName = GetLayerName(graph, layerIndex);
3613 IConnectableLayer* layer = m_Network->AddStackLayer(descriptor, layerName.c_str());
3614
3615 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3616 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3617
3618 RegisterInputSlots(graph, layerIndex, layer);
3619 RegisterOutputSlots(graph, layerIndex, layer);
3620}
3621
Finn Williams85d36712021-01-26 22:30:06 +00003622void IDeserializer::DeserializerImpl::ParseStandIn(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Tar85121a22019-10-23 10:41:35 +01003623{
3624 CHECK_LAYERS(graph, 0, layerIndex);
3625
3626 auto inputs = GetInputs(graph, layerIndex);
3627 auto outputs = GetOutputs(graph, layerIndex);
3628
3629 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_StandInLayer();
3630 auto fbDescriptor = fbLayer->descriptor();
3631
3632 armnn::StandInDescriptor descriptor;
3633 descriptor.m_NumInputs = fbDescriptor->numInputs();
3634 descriptor.m_NumOutputs = fbDescriptor->numOutputs();
3635
3636 CHECK_VALID_SIZE(inputs.size(), descriptor.m_NumInputs);
3637 CHECK_VALID_SIZE(outputs.size(), descriptor.m_NumOutputs);
3638
3639 const std::string layerName = GetLayerName(graph, layerIndex);
3640 armnn::IConnectableLayer* layer = m_Network->AddStandInLayer(descriptor, layerName.c_str());
3641
3642 for (unsigned int i = 0u; i < descriptor.m_NumOutputs; ++i)
3643 {
3644 armnn::TensorInfo outputInfo = ToTensorInfo(outputs[i]);
3645 layer->GetOutputSlot(i).SetTensorInfo(outputInfo);
3646 }
3647
3648 RegisterInputSlots(graph, layerIndex, layer);
3649 RegisterOutputSlots(graph, layerIndex, layer);
3650}
3651
Narumol Prangnawarata0162e12021-07-23 14:47:49 +01003652armnn::UnidirectionalSequenceLstmDescriptor IDeserializer::DeserializerImpl::GetUnidirectionalSequenceLstmDescriptor(
3653 UnidirectionalSequenceLstmDescriptorPtr descriptor)
3654{
3655 armnn::UnidirectionalSequenceLstmDescriptor desc;
3656
3657 desc.m_ActivationFunc = descriptor->activationFunc();
3658 desc.m_ClippingThresCell = descriptor->clippingThresCell();
3659 desc.m_ClippingThresProj = descriptor->clippingThresProj();
3660 desc.m_CifgEnabled = descriptor->cifgEnabled();
3661 desc.m_PeepholeEnabled = descriptor->peepholeEnabled();
3662 desc.m_ProjectionEnabled = descriptor->projectionEnabled();
3663 desc.m_LayerNormEnabled = descriptor->layerNormEnabled();
3664 desc.m_TimeMajor = descriptor->timeMajor();
3665
3666 return desc;
3667}
3668
3669void IDeserializer::DeserializerImpl::ParseUnidirectionalSequenceLstm(GraphPtr graph, unsigned int layerIndex)
3670{
3671 CHECK_LAYERS(graph, 0, layerIndex);
3672
3673 auto inputs = GetInputs(graph, layerIndex);
3674 CHECK_VALID_SIZE(inputs.size(), 3);
3675
3676 auto outputs = GetOutputs(graph, layerIndex);
Mike Kelly12994962022-04-21 11:57:09 +01003677 CHECK_VALID_SIZE(outputs.size(), 3);
Narumol Prangnawarata0162e12021-07-23 14:47:49 +01003678
3679 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_UnidirectionalSequenceLstmLayer();
3680 auto layerName = GetLayerName(graph, layerIndex);
3681 auto flatBufferDescriptor = flatBufferLayer->descriptor();
3682 auto flatBufferInputParams = flatBufferLayer->inputParams();
3683
3684 auto descriptor = GetUnidirectionalSequenceLstmDescriptor(flatBufferDescriptor);
3685
3686 armnn::LstmInputParams lstmInputParams;
3687
3688 armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
3689 armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
3690 armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
3691 armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
3692 armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
3693 armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
3694 armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
3695 armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
3696 armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
3697
3698 lstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
3699 lstmInputParams.m_InputToCellWeights = &inputToCellWeights;
3700 lstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
3701 lstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3702 lstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
3703 lstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3704 lstmInputParams.m_ForgetGateBias = &forgetGateBias;
3705 lstmInputParams.m_CellBias = &cellBias;
3706 lstmInputParams.m_OutputGateBias = &outputGateBias;
3707
3708 armnn::ConstTensor inputToInputWeights;
3709 armnn::ConstTensor recurrentToInputWeights;
3710 armnn::ConstTensor cellToInputWeights;
3711 armnn::ConstTensor inputGateBias;
3712 if (!descriptor.m_CifgEnabled)
3713 {
3714 inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
3715 recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
3716 inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
3717
3718 lstmInputParams.m_InputToInputWeights = &inputToInputWeights;
3719 lstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
3720 lstmInputParams.m_InputGateBias = &inputGateBias;
3721
3722 if (descriptor.m_PeepholeEnabled)
3723 {
3724 cellToInputWeights = ToConstTensor(flatBufferInputParams->cellToInputWeights());
3725 lstmInputParams.m_CellToInputWeights = &cellToInputWeights;
3726 }
3727 }
3728
3729 armnn::ConstTensor projectionWeights;
3730 armnn::ConstTensor projectionBias;
3731 if (descriptor.m_ProjectionEnabled)
3732 {
3733 projectionWeights = ToConstTensor(flatBufferInputParams->projectionWeights());
3734 projectionBias = ToConstTensor(flatBufferInputParams->projectionBias());
3735
3736 lstmInputParams.m_ProjectionWeights = &projectionWeights;
3737 lstmInputParams.m_ProjectionBias = &projectionBias;
3738 }
3739
3740 armnn::ConstTensor cellToForgetWeights;
3741 armnn::ConstTensor cellToOutputWeights;
3742 if (descriptor.m_PeepholeEnabled)
3743 {
3744 cellToForgetWeights = ToConstTensor(flatBufferInputParams->cellToForgetWeights());
3745 cellToOutputWeights = ToConstTensor(flatBufferInputParams->cellToOutputWeights());
3746
3747 lstmInputParams.m_CellToForgetWeights = &cellToForgetWeights;
3748 lstmInputParams.m_CellToOutputWeights = &cellToOutputWeights;
3749 }
3750
3751 armnn::ConstTensor inputLayerNormWeights;
3752 armnn::ConstTensor forgetLayerNormWeights;
3753 armnn::ConstTensor cellLayerNormWeights;
3754 armnn::ConstTensor outputLayerNormWeights;
3755 if (descriptor.m_LayerNormEnabled)
3756 {
3757 if (!descriptor.m_CifgEnabled)
3758 {
3759 inputLayerNormWeights = ToConstTensor(flatBufferInputParams->inputLayerNormWeights());
3760 lstmInputParams.m_InputLayerNormWeights = &inputLayerNormWeights;
3761 }
3762 forgetLayerNormWeights = ToConstTensor(flatBufferInputParams->forgetLayerNormWeights());
3763 cellLayerNormWeights = ToConstTensor(flatBufferInputParams->cellLayerNormWeights());
3764 outputLayerNormWeights = ToConstTensor(flatBufferInputParams->outputLayerNormWeights());
3765
3766 lstmInputParams.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
3767 lstmInputParams.m_CellLayerNormWeights = &cellLayerNormWeights;
3768 lstmInputParams.m_OutputLayerNormWeights = &outputLayerNormWeights;
3769 }
3770
3771 IConnectableLayer* layer = m_Network->AddUnidirectionalSequenceLstmLayer(descriptor,
3772 lstmInputParams,
3773 layerName.c_str());
3774
Mike Kelly12994962022-04-21 11:57:09 +01003775 armnn::TensorInfo outputTensorInfo0 = ToTensorInfo(outputs[0]);
3776 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo0);
3777
3778 armnn::TensorInfo outputTensorInfo1 = ToTensorInfo(outputs[1]);
3779 layer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo1);
3780
3781 armnn::TensorInfo outputTensorInfo2 = ToTensorInfo(outputs[2]);
3782 layer->GetOutputSlot(2).SetTensorInfo(outputTensorInfo2);
Narumol Prangnawarata0162e12021-07-23 14:47:49 +01003783
3784 RegisterInputSlots(graph, layerIndex, layer);
3785 RegisterOutputSlots(graph, layerIndex, layer);
3786}
3787
Derek Lamberti0028d1b2019-02-20 13:57:42 +00003788} // namespace armnnDeserializer