blob: 317269ebd00aa35e47fff872f610026c2badaeaa [file] [log] [blame]
Kevin May43a799c2019-02-08 16:31:42 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// 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
8#include <armnn/ArmNN.hpp>
9#include <armnn/Exceptions.hpp>
10
11#include <ParserHelper.hpp>
12#include <Permute.hpp>
13#include <VerificationHelpers.hpp>
14
15#include <boost/filesystem.hpp>
16#include <boost/format.hpp>
17#include <boost/core/ignore_unused.hpp>
18#include <boost/assert.hpp>
19#include <boost/format.hpp>
20#include <boost/log/trivial.hpp>
21
22// The generated code based on the Serialize schema:
Matthew Bentham268509a2019-02-25 13:58:24 +000023#include <ArmnnSchema_generated.h>
Kevin May43a799c2019-02-08 16:31:42 +000024
25#include <fstream>
Saoirse Stewart263829c2019-02-19 15:54:14 +000026#include <algorithm>
27#include <limits>
28#include <numeric>
Kevin May43a799c2019-02-08 16:31:42 +000029
30using armnn::ParseException;
31using namespace armnn;
Derek Lamberti0028d1b2019-02-20 13:57:42 +000032using namespace armnnSerializer;
Kevin May43a799c2019-02-08 16:31:42 +000033
Derek Lamberti0028d1b2019-02-20 13:57:42 +000034namespace armnnDeserializer
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000035{
Kevin May43a799c2019-02-08 16:31:42 +000036
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000037namespace
38{
Kevin May43a799c2019-02-08 16:31:42 +000039
40const uint32_t VIRTUAL_LAYER_ID = std::numeric_limits<uint32_t>::max();
41
Derek Lamberti0028d1b2019-02-20 13:57:42 +000042 void CheckGraph(const Deserializer::GraphPtr& graph,
Kevin May43a799c2019-02-08 16:31:42 +000043 unsigned int layersIndex,
44 const CheckLocation& location)
45{
46 if (graph->layers() == nullptr)
47 {
48 throw ParseException(
49 boost::str(
50 boost::format("%1% was called with invalid (null) graph. "
51 "Possible reason is that the graph is not yet loaded and Unpack(ed). "
52 "layers:%2% at %3%") %
53 location.m_Function %
54 layersIndex %
55 location.FileLine()));
56 }
57 else if (layersIndex >= graph->layers()->size())
58 {
59 throw ParseException(
60 boost::str(
61 boost::format("%1% was called with an invalid layers index. "
62 "layers:%2% at %3%") %
63 location.m_Function %
64 layersIndex %
65 location.FileLine()));
66 }
67}
68
Derek Lamberti0028d1b2019-02-20 13:57:42 +000069void CheckLayers(const Deserializer::GraphPtr& graph,
Kevin May43a799c2019-02-08 16:31:42 +000070 unsigned int layersIndex,
71 unsigned int layerIndex,
72 const CheckLocation& location)
73{
74 if (graph->layers() == nullptr)
75 {
76 throw ParseException(
77 boost::str(
78 boost::format("%1% was called with invalid (null) graph. "
79 "Possible reason is that the graph is not yet loaded and Unpack(ed). "
Nattapat Chaimanowong43e78642019-02-13 15:56:24 +000080 "layers:%2% at %3%") %
Kevin May43a799c2019-02-08 16:31:42 +000081 location.m_Function %
82 layersIndex %
83 location.FileLine()));
84 }
85 else if (layersIndex >= graph->layers()->size())
86 {
87 throw ParseException(
88 boost::str(
89 boost::format("%1% was called with an invalid layers index. "
Nattapat Chaimanowong43e78642019-02-13 15:56:24 +000090 "layers:%2% at %3%") %
Kevin May43a799c2019-02-08 16:31:42 +000091 location.m_Function %
92 layersIndex %
93 location.FileLine()));
94 }
95 else if (layerIndex >= graph->layers()[layersIndex].size()
96 && layerIndex != VIRTUAL_LAYER_ID)
97 {
98 throw ParseException(
99 boost::str(
100 boost::format("%1% was called with an invalid layer index. "
101 "layers:%2% layer:%3% at %4%") %
102 location.m_Function %
103 layersIndex %
104 layerIndex %
105 location.FileLine()));
106 }
107}
108
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000109void CheckTensorPtr(Deserializer::TensorRawPtr rawPtr,
Kevin May43a799c2019-02-08 16:31:42 +0000110 const CheckLocation& location)
111{
112 if (rawPtr == nullptr)
113 {
114 throw ParseException(
115 boost::str(
116 boost::format("%1% was called with a null tensor pointer. "
117 "at %2%") %
118 location.m_Function %
119 location.FileLine()));
120
121 }
122}
123
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000124void CheckConstTensorPtr(Deserializer::ConstTensorRawPtr rawPtr,
Mike Kellya0766c32019-02-19 17:22:07 +0000125 const CheckLocation& location)
126{
127 if (rawPtr == nullptr)
128 {
129 throw ParseException(boost::str(boost::format("%1% was called with a null const tensor pointer. at %2%") %
130 location.m_Function %
131 location.FileLine()));
132 }
133}
134
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000135void CheckConstTensorSize(const unsigned int constTensorSize,
136 const unsigned int tensorSize,
137 const CheckLocation& location)
138{
139 if (constTensorSize != tensorSize)
140 {
141 throw ParseException(boost::str(boost::format("%1% wrong number of components supplied to tensor. at:%2%") %
142 location.m_Function %
143 location.FileLine()));
144 }
145}
146
Kevin May43a799c2019-02-08 16:31:42 +0000147#define CHECK_TENSOR_PTR(TENSOR_PTR) \
148 CheckTensorPtr(TENSOR_PTR, CHECK_LOCATION())
149
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000150#define CHECK_CONST_TENSOR_SIZE(CONST_TENSOR_SIZE, TENSOR_SIZE) \
151 CheckConstTensorSize(CONST_TENSOR_SIZE, TENSOR_SIZE, CHECK_LOCATION())
152
Mike Kellya0766c32019-02-19 17:22:07 +0000153#define CHECK_CONST_TENSOR_PTR(TENSOR_PTR) \
154 CheckConstTensorPtr(TENSOR_PTR, CHECK_LOCATION())
155
Kevin May43a799c2019-02-08 16:31:42 +0000156#define CHECK_LAYERS(GRAPH, LAYERS_INDEX, LAYER_INDEX) \
157 CheckLayers(GRAPH, LAYERS_INDEX, LAYER_INDEX, CHECK_LOCATION())
158
159#define CHECK_GRAPH(GRAPH, LAYERS_INDEX) \
160 CheckGraph(GRAPH, LAYERS_INDEX, CHECK_LOCATION())
161}
162
Saoirse Stewart263829c2019-02-19 15:54:14 +0000163bool CheckShape(const armnn::TensorShape& actual, const std::vector<uint32_t>& expected)
164{
165 const unsigned int actualSize = actual.GetNumDimensions();
166 if (actualSize != expected.size())
167 {
168 return false;
169 }
170
171 for (unsigned int i = 0u; i < actualSize; i++)
172 {
173 if (actual[i] != static_cast<unsigned int>(expected[i]))
174 {
175 return false;
176 }
177 }
178
179 return true;
180}
181
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000182Deserializer::Deserializer()
Kevin May43a799c2019-02-08 16:31:42 +0000183: m_Network(nullptr, nullptr),
184//May require LayerType_Max to be included
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000185m_ParserFunctions(Layer_MAX+1, &Deserializer::ParseUnsupportedLayer)
Kevin May43a799c2019-02-08 16:31:42 +0000186{
187 // register supported layers
Mike Kellyaf484012019-02-20 16:53:11 +0000188 m_ParserFunctions[Layer_ActivationLayer] = &Deserializer::ParseActivation;
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000189 m_ParserFunctions[Layer_AdditionLayer] = &Deserializer::ParseAdd;
Nattapat Chaimanowong6b4ed982019-02-26 17:24:13 +0000190 m_ParserFunctions[Layer_BatchToSpaceNdLayer] = &Deserializer::ParseBatchToSpaceNd;
Conor Kennedy76277882019-02-26 08:29:54 +0000191 m_ParserFunctions[Layer_ConstantLayer] = &Deserializer::ParseConstant;
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000192 m_ParserFunctions[Layer_Convolution2dLayer] = &Deserializer::ParseConvolution2d;
193 m_ParserFunctions[Layer_DepthwiseConvolution2dLayer] = &Deserializer::ParseDepthwiseConvolution2d;
Éanna Ó Catháin58885892019-02-27 16:16:39 +0000194 m_ParserFunctions[Layer_DivisionLayer] = &Deserializer::ParseDivision;
Nattapat Chaimanowong235cea52019-02-28 16:27:30 +0000195 m_ParserFunctions[Layer_EqualLayer] = &Deserializer::ParseEqual;
Sadik Armagandbb0c0c2019-02-21 09:01:41 +0000196 m_ParserFunctions[Layer_FullyConnectedLayer] = &Deserializer::ParseFullyConnected;
Aron Virginas-Tar0fe32452019-02-28 13:12:47 +0000197 m_ParserFunctions[Layer_MinimumLayer] = &Deserializer::ParseMinimum;
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000198 m_ParserFunctions[Layer_MultiplicationLayer] = &Deserializer::ParseMultiplication;
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +0000199 m_ParserFunctions[Layer_PermuteLayer] = &Deserializer::ParsePermute;
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000200 m_ParserFunctions[Layer_Pooling2dLayer] = &Deserializer::ParsePooling2d;
201 m_ParserFunctions[Layer_ReshapeLayer] = &Deserializer::ParseReshape;
202 m_ParserFunctions[Layer_SoftmaxLayer] = &Deserializer::ParseSoftmax;
Nattapat Chaimanowong45286992019-02-26 15:53:02 +0000203 m_ParserFunctions[Layer_SpaceToBatchNdLayer] = &Deserializer::ParseSpaceToBatchNd;
Kevin May43a799c2019-02-08 16:31:42 +0000204}
205
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000206Deserializer::LayerBaseRawPtr Deserializer::GetBaseLayer(const GraphPtr& graphPtr, unsigned int layerIndex)
Kevin May43a799c2019-02-08 16:31:42 +0000207{
208 auto layerType = graphPtr->layers()->Get(layerIndex)->layer_type();
209
210 switch(layerType)
211 {
Mike Kellyaf484012019-02-20 16:53:11 +0000212 case Layer::Layer_ActivationLayer:
213 return graphPtr->layers()->Get(layerIndex)->layer_as_ActivationLayer()->base();
Kevin May43a799c2019-02-08 16:31:42 +0000214 case Layer::Layer_AdditionLayer:
215 return graphPtr->layers()->Get(layerIndex)->layer_as_AdditionLayer()->base();
Nattapat Chaimanowong6b4ed982019-02-26 17:24:13 +0000216 case Layer::Layer_BatchToSpaceNdLayer:
217 return graphPtr->layers()->Get(layerIndex)->layer_as_BatchToSpaceNdLayer()->base();
Conor Kennedy76277882019-02-26 08:29:54 +0000218 case Layer::Layer_ConstantLayer:
219 return graphPtr->layers()->Get(layerIndex)->layer_as_ConstantLayer()->base();
Mike Kellya0766c32019-02-19 17:22:07 +0000220 case Layer::Layer_Convolution2dLayer:
221 return graphPtr->layers()->Get(layerIndex)->layer_as_Convolution2dLayer()->base();
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000222 case Layer::Layer_DepthwiseConvolution2dLayer:
223 return graphPtr->layers()->Get(layerIndex)->layer_as_DepthwiseConvolution2dLayer()->base();
Éanna Ó Catháin58885892019-02-27 16:16:39 +0000224 case Layer::Layer_DivisionLayer:
225 return graphPtr->layers()->Get(layerIndex)->layer_as_DivisionLayer()->base();
Nattapat Chaimanowong235cea52019-02-28 16:27:30 +0000226 case Layer::Layer_EqualLayer:
227 return graphPtr->layers()->Get(layerIndex)->layer_as_EqualLayer()->base();
Sadik Armagandbb0c0c2019-02-21 09:01:41 +0000228 case Layer::Layer_FullyConnectedLayer:
229 return graphPtr->layers()->Get(layerIndex)->layer_as_FullyConnectedLayer()->base();
Kevin May43a799c2019-02-08 16:31:42 +0000230 case Layer::Layer_InputLayer:
Aron Virginas-Tar0fe32452019-02-28 13:12:47 +0000231 return graphPtr->layers()->Get(layerIndex)->layer_as_InputLayer()->base()->base();
232 case Layer::Layer_MinimumLayer:
233 return graphPtr->layers()->Get(layerIndex)->layer_as_MinimumLayer()->base();
Sadik Armagan5f450272019-02-12 14:31:45 +0000234 case Layer::Layer_MultiplicationLayer:
235 return graphPtr->layers()->Get(layerIndex)->layer_as_MultiplicationLayer()->base();
Kevin May43a799c2019-02-08 16:31:42 +0000236 case Layer::Layer_OutputLayer:
237 return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->base();
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +0000238 case Layer::Layer_PermuteLayer:
239 return graphPtr->layers()->Get(layerIndex)->layer_as_PermuteLayer()->base();
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000240 case Layer::Layer_Pooling2dLayer:
241 return graphPtr->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->base();
Saoirse Stewart263829c2019-02-19 15:54:14 +0000242 case Layer::Layer_ReshapeLayer:
243 return graphPtr->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->base();
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000244 case Layer::Layer_SoftmaxLayer:
245 return graphPtr->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->base();
Nattapat Chaimanowong45286992019-02-26 15:53:02 +0000246 case Layer::Layer_SpaceToBatchNdLayer:
247 return graphPtr->layers()->Get(layerIndex)->layer_as_SpaceToBatchNdLayer()->base();
Kevin May43a799c2019-02-08 16:31:42 +0000248 case Layer::Layer_NONE:
249 default:
250 throw ParseException(boost::str(
251 boost::format("Layer must have a type %1%") %
252 Layer::Layer_NONE));
253 }
254}
255
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000256std::string Deserializer::GetLayerName(const GraphPtr& graph, unsigned int index)
257{
258 auto layer = GetBaseLayer(graph, index);
259 assert(layer);
260 return layer->layerName()->str();
261}
262
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000263int32_t Deserializer::GetBindingLayerInfo(const GraphPtr& graphPtr, unsigned int layerIndex)
Kevin May43a799c2019-02-08 16:31:42 +0000264{
265 auto layerType = graphPtr->layers()->Get(layerIndex)->layer_type();
266
267 if (layerType == Layer::Layer_InputLayer)
268 {
269 return graphPtr->layers()->Get(layerIndex)->layer_as_InputLayer()->base()->layerBindingId();
270 }
271 else if ( layerType == Layer::Layer_OutputLayer )
272 {
273 return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->layerBindingId();
274 }
275 return 0;
276}
277
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000278armnn::DataLayout ToDataLayout(armnnSerializer::DataLayout dataLayout)
Mike Kellya0766c32019-02-19 17:22:07 +0000279{
280 switch (dataLayout)
281 {
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000282 case armnnSerializer::DataLayout::DataLayout_NHWC:
Mike Kellya0766c32019-02-19 17:22:07 +0000283 return armnn::DataLayout::NHWC;
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000284 case armnnSerializer::DataLayout::DataLayout_NCHW:
Mike Kellya0766c32019-02-19 17:22:07 +0000285 default:
286 return armnn::DataLayout::NCHW;
287 }
288}
289
Mike Kellyaf484012019-02-20 16:53:11 +0000290armnn::ActivationFunction ToActivationFunction(armnnSerializer::ActivationFunction function)
291{
292 switch (function)
293 {
294 case armnnSerializer::ActivationFunction_Sigmoid:
295 return armnn::ActivationFunction::Sigmoid;
296 case armnnSerializer::ActivationFunction_TanH:
297 return armnn::ActivationFunction::TanH;
298 case armnnSerializer::ActivationFunction_Linear:
299 return armnn::ActivationFunction::Linear;
300 case armnnSerializer::ActivationFunction_ReLu:
301 return armnn::ActivationFunction::ReLu;
302 case armnnSerializer::ActivationFunction_BoundedReLu:
303 return armnn::ActivationFunction::BoundedReLu;
304 case armnnSerializer::ActivationFunction_LeakyReLu:
305 return armnn::ActivationFunction::LeakyReLu;
306 case armnnSerializer::ActivationFunction_Abs:
307 return armnn::ActivationFunction::Abs;
308 case armnnSerializer::ActivationFunction_Sqrt:
309 return armnn::ActivationFunction::Sqrt;
310 case armnnSerializer::ActivationFunction_Square:
311 return armnn::ActivationFunction::Square;
312 default:
313 return armnn::ActivationFunction::Sigmoid;
314 }
315}
316
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000317armnn::TensorInfo ToTensorInfo(Deserializer::TensorRawPtr tensorPtr)
Kevin May43a799c2019-02-08 16:31:42 +0000318{
319 armnn::DataType type;
320 CHECK_TENSOR_PTR(tensorPtr);
321
322 switch (tensorPtr->dataType())
323 {
324 case DataType_QuantisedAsymm8:
325 type = armnn::DataType::QuantisedAsymm8;
326 break;
Mike Kellya0766c32019-02-19 17:22:07 +0000327 case DataType_Signed32:
328 type = armnn::DataType::Signed32;
329 break;
Kevin May43a799c2019-02-08 16:31:42 +0000330 case DataType_Float32:
331 type = armnn::DataType::Float32;
332 break;
333 case DataType_Float16:
334 type = armnn::DataType::Float16;
335 break;
336 case DataType_Boolean:
337 type = armnn::DataType::Boolean;
338 break;
339 default:
340 {
341 CheckLocation location = CHECK_LOCATION();
342 throw ParseException(
343 boost::str(
344 boost::format("Unsupported data type %1% = %2%. %3%") %
345 tensorPtr->dataType() %
346 EnumNameDataType(tensorPtr->dataType()) %
347 location.AsString()));
348 }
349 }
350 float quantizationScale = tensorPtr->quantizationScale();
351 int32_t quantizationOffset = tensorPtr->quantizationOffset();
352
353 auto dimensions = tensorPtr->dimensions();
354 unsigned int size = dimensions->size();
355 std::vector<unsigned int> outputDims(dimensions->begin(), dimensions->begin() + size);
356
357 // two statements (on purpose) for easier debugging:
358 armnn::TensorInfo result(size,
359 outputDims.data(),
360 type,
361 quantizationScale,
362 quantizationOffset);
363 return result;
364}
365
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000366armnn::ConstTensor ToConstTensor(Deserializer::ConstTensorRawPtr constTensorPtr)
Mike Kellya0766c32019-02-19 17:22:07 +0000367{
368 CHECK_CONST_TENSOR_PTR(constTensorPtr);
369 armnn::TensorInfo tensorInfo = ToTensorInfo(constTensorPtr->info());
370
371 switch (constTensorPtr->data_type())
372 {
373 case ConstTensorData_ByteData:
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000374 {
375 auto byteData = constTensorPtr->data_as_ByteData()->data();
376 CHECK_CONST_TENSOR_SIZE(byteData->size(), tensorInfo.GetNumElements());
377 return armnn::ConstTensor(tensorInfo, byteData->data());
378 }
Mike Kellya0766c32019-02-19 17:22:07 +0000379 case ConstTensorData_ShortData:
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000380 {
381 auto shortData = constTensorPtr->data_as_ShortData()->data();
382 CHECK_CONST_TENSOR_SIZE(shortData->size(), tensorInfo.GetNumElements());
383 return armnn::ConstTensor(tensorInfo, shortData->data());
384 }
Mike Kellya0766c32019-02-19 17:22:07 +0000385 case ConstTensorData_IntData:
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000386 {
387 auto intData = constTensorPtr->data_as_IntData()->data();
388 CHECK_CONST_TENSOR_SIZE(intData->size(), tensorInfo.GetNumElements());
389 return armnn::ConstTensor(tensorInfo, intData->data());
390 }
Mike Kellya0766c32019-02-19 17:22:07 +0000391 case ConstTensorData_LongData:
Saoirse Stewartf11bab52019-02-25 09:22:58 +0000392 {
393 auto longData = constTensorPtr->data_as_LongData()->data();
394 CHECK_CONST_TENSOR_SIZE(longData->size(), tensorInfo.GetNumElements());
395 return armnn::ConstTensor(tensorInfo, longData->data());
396 }
Mike Kellya0766c32019-02-19 17:22:07 +0000397 default:
398 {
399 CheckLocation location = CHECK_LOCATION();
400 throw ParseException(
401 boost::str(boost::format("Unsupported data type %1% = %2%. %3%") %
402 constTensorPtr->data_type() %
403 EnumNameConstTensorData(constTensorPtr->data_type()) %
404 location.AsString()));
405 }
406 }
407}
408
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000409Deserializer::LayerBaseRawPtrVector Deserializer::GetGraphInputs(const GraphPtr& graphPtr)
Kevin May43a799c2019-02-08 16:31:42 +0000410{
411
412 CHECK_GRAPH(graphPtr, 0);
413 const auto& numInputs = graphPtr->inputIds()->size();
414
415 LayerBaseRawPtrVector result(numInputs);
416
417 for (unsigned int i=0; i<numInputs; ++i)
418 {
Mike Kelly8c1701a2019-02-11 17:01:27 +0000419 uint32_t inputId = graphPtr->inputIds()->Get(i);
Kevin May43a799c2019-02-08 16:31:42 +0000420 result[i] = GetBaseLayer(graphPtr, static_cast<uint32_t>(inputId));
421 }
422 return result;
423}
424
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000425Deserializer::LayerBaseRawPtrVector Deserializer::GetGraphOutputs(const GraphPtr& graphPtr)
Kevin May43a799c2019-02-08 16:31:42 +0000426{
427 CHECK_GRAPH(graphPtr, 0);
428 const auto& numOutputs = graphPtr->outputIds()->size();
Kevin May43a799c2019-02-08 16:31:42 +0000429 LayerBaseRawPtrVector result(numOutputs);
430
431 for (unsigned int i=0; i<numOutputs; ++i)
432 {
Mike Kelly8c1701a2019-02-11 17:01:27 +0000433 uint32_t outputId = graphPtr->outputIds()->Get(i);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000434
Kevin May43a799c2019-02-08 16:31:42 +0000435 result[i] = GetBaseLayer(graphPtr, static_cast<uint32_t>(outputId));
436 }
437 return result;
438}
439
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000440Deserializer::TensorRawPtrVector Deserializer::GetInputs(const GraphPtr& graphPtr,
Kevin May43a799c2019-02-08 16:31:42 +0000441 unsigned int layerIndex)
442{
443 CHECK_LAYERS(graphPtr, 0, layerIndex);
444 auto layer = GetBaseLayer(graphPtr, layerIndex);
445 const auto& numInputs = layer->inputSlots()->size();
446
447 TensorRawPtrVector result(numInputs);
448
449 for (unsigned int i=0; i<numInputs; ++i)
450 {
451 auto inputId = CHECKED_NON_NEGATIVE(static_cast<int32_t>
452 (layer->inputSlots()->Get(i)->connection()->sourceLayerIndex()));
453 result[i] = GetBaseLayer(graphPtr, inputId)->outputSlots()->Get(0)->tensorInfo();
454 }
455 return result;
456}
457
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000458Deserializer::TensorRawPtrVector Deserializer::GetOutputs(const GraphPtr& graphPtr,
Kevin May43a799c2019-02-08 16:31:42 +0000459 unsigned int layerIndex)
460{
461 CHECK_LAYERS(graphPtr, 0, layerIndex);
462 auto layer = GetBaseLayer(graphPtr, layerIndex);
463 const auto& numOutputs = layer->outputSlots()->size();
464
465 TensorRawPtrVector result(numOutputs);
466
467 for (unsigned int i=0; i<numOutputs; ++i)
468 {
469 result[i] = layer->outputSlots()->Get(i)->tensorInfo();
470 }
471 return result;
472}
473
Derek Lamberti8ddae332019-02-21 16:29:43 +0000474void Deserializer::ParseUnsupportedLayer(GraphPtr graph, unsigned int layerIndex)
Kevin May43a799c2019-02-08 16:31:42 +0000475{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000476 CHECK_LAYERS(graph, 0, layerIndex);
477 const auto layerName = GetBaseLayer(graph, layerIndex)->layerName()->c_str();
Kevin May43a799c2019-02-08 16:31:42 +0000478 throw ParseException(
479 boost::str(
480 boost::format("Layer not supported. "
481 "layerIndex: %1% "
482 "layerName: %2% / %3%") %
483 layerIndex %
484 layerName %
485 CHECK_LOCATION().AsString()));
486}
487
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000488void Deserializer::ResetParser()
Kevin May43a799c2019-02-08 16:31:42 +0000489{
490 m_Network = armnn::INetworkPtr(nullptr, nullptr);
Derek Lamberti8ddae332019-02-21 16:29:43 +0000491 m_InputBindings.clear();
492 m_OutputBindings.clear();
Kevin May43a799c2019-02-08 16:31:42 +0000493}
494
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000495IDeserializer* IDeserializer::CreateRaw()
Kevin May43a799c2019-02-08 16:31:42 +0000496{
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000497 return new Deserializer();
Kevin May43a799c2019-02-08 16:31:42 +0000498}
499
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000500IDeserializerPtr IDeserializer::Create()
Kevin May43a799c2019-02-08 16:31:42 +0000501{
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000502 return IDeserializerPtr(CreateRaw(), &IDeserializer::Destroy);
Kevin May43a799c2019-02-08 16:31:42 +0000503}
504
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000505void IDeserializer::Destroy(IDeserializer* parser)
Kevin May43a799c2019-02-08 16:31:42 +0000506{
507 delete parser;
508}
509
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000510INetworkPtr Deserializer::CreateNetworkFromBinary(const std::vector<uint8_t>& binaryContent)
Kevin May43a799c2019-02-08 16:31:42 +0000511{
512 ResetParser();
Derek Lamberti8ddae332019-02-21 16:29:43 +0000513 GraphPtr graph = LoadGraphFromBinary(binaryContent.data(), binaryContent.size());
514 return CreateNetworkFromGraph(graph);
Kevin May43a799c2019-02-08 16:31:42 +0000515}
516
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000517armnn::INetworkPtr Deserializer::CreateNetworkFromBinary(std::istream& binaryContent)
Kevin May43a799c2019-02-08 16:31:42 +0000518{
Derek Lamberti2b183fb2019-02-18 16:36:57 +0000519 ResetParser();
Derek Lamberti8ddae332019-02-21 16:29:43 +0000520 std::vector<uint8_t> content((std::istreambuf_iterator<char>(binaryContent)), std::istreambuf_iterator<char>());
521 GraphPtr graph = LoadGraphFromBinary(content.data(), content.size());
522 return CreateNetworkFromGraph(graph);
Kevin May43a799c2019-02-08 16:31:42 +0000523}
524
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000525Deserializer::GraphPtr Deserializer::LoadGraphFromBinary(const uint8_t* binaryContent, size_t len)
Kevin May43a799c2019-02-08 16:31:42 +0000526{
527 if (binaryContent == nullptr)
528 {
529 throw InvalidArgumentException(boost::str(boost::format("Invalid (null) binary content %1%") %
530 CHECK_LOCATION().AsString()));
531 }
532 flatbuffers::Verifier verifier(binaryContent, len);
533 if (verifier.VerifyBuffer<SerializedGraph>() == false)
534 {
535 throw ParseException(
536 boost::str(boost::format("Buffer doesn't conform to the expected Armnn "
537 "flatbuffers format. size:%1% %2%") %
538 len %
539 CHECK_LOCATION().AsString()));
540 }
541 return GetSerializedGraph(binaryContent);
542}
543
Derek Lamberti8ddae332019-02-21 16:29:43 +0000544INetworkPtr Deserializer::CreateNetworkFromGraph(GraphPtr graph)
Kevin May43a799c2019-02-08 16:31:42 +0000545{
546 m_Network = INetwork::Create();
Derek Lamberti8ddae332019-02-21 16:29:43 +0000547 BOOST_ASSERT(graph != nullptr);
Kevin May43a799c2019-02-08 16:31:42 +0000548 unsigned int layerIndex = 0;
Derek Lamberti8ddae332019-02-21 16:29:43 +0000549 m_GraphConnections.emplace_back(graph->layers()->size());
550 for (AnyLayer const* layer : *graph->layers())
Kevin May43a799c2019-02-08 16:31:42 +0000551 {
552 if (layer->layer_type() != Layer_InputLayer &&
553 layer->layer_type() != Layer_OutputLayer)
554 {
555 // lookup and call the parser function
556 auto& parserFunction = m_ParserFunctions[layer->layer_type()];
Derek Lamberti8ddae332019-02-21 16:29:43 +0000557 (this->*parserFunction)(graph, layerIndex);
Kevin May43a799c2019-02-08 16:31:42 +0000558 }
559 ++layerIndex;
560 }
561
Derek Lamberti8ddae332019-02-21 16:29:43 +0000562 SetupInputLayers(graph);
563 SetupOutputLayers(graph);
Kevin May43a799c2019-02-08 16:31:42 +0000564
565 // establish the connections from the layer outputs to the inputs of the subsequent layers
566 for (size_t connectionIndex = 0; connectionIndex < m_GraphConnections[0].size(); ++connectionIndex)
567 {
568 if (m_GraphConnections[0][connectionIndex].outputSlot != nullptr)
569 {
570 for (size_t inputSlotIdx = 0;
571 inputSlotIdx < m_GraphConnections[0][connectionIndex].inputSlots.size();
572 ++inputSlotIdx)
573 {
574 m_GraphConnections[0][connectionIndex].outputSlot->Connect(
575 *(m_GraphConnections[0][connectionIndex].inputSlots[inputSlotIdx]));
576 }
577 }
578 }
579
580 return std::move(m_Network);
581}
582
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000583BindingPointInfo Deserializer::GetNetworkInputBindingInfo(unsigned int layerIndex,
Kevin May43a799c2019-02-08 16:31:42 +0000584 const std::string& name) const
585{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000586 for (auto inputBinding : m_InputBindings)
Kevin May43a799c2019-02-08 16:31:42 +0000587 {
Derek Lamberti8ddae332019-02-21 16:29:43 +0000588 if (inputBinding.first == name)
Kevin May43a799c2019-02-08 16:31:42 +0000589 {
Derek Lamberti8ddae332019-02-21 16:29:43 +0000590 return inputBinding.second;
Kevin May43a799c2019-02-08 16:31:42 +0000591 }
592 }
593 throw ParseException(
594 boost::str(
595 boost::format("No input binding found for layer:%1% / %2%") %
596 name %
597 CHECK_LOCATION().AsString()));
598}
599
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000600BindingPointInfo Deserializer::GetNetworkOutputBindingInfo(unsigned int layerIndex,
Kevin May43a799c2019-02-08 16:31:42 +0000601 const std::string& name) const
602{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000603 for (auto outputBinding : m_OutputBindings)
Kevin May43a799c2019-02-08 16:31:42 +0000604 {
Derek Lamberti8ddae332019-02-21 16:29:43 +0000605 if (outputBinding.first == name)
Kevin May43a799c2019-02-08 16:31:42 +0000606 {
Derek Lamberti8ddae332019-02-21 16:29:43 +0000607 return outputBinding.second;
Kevin May43a799c2019-02-08 16:31:42 +0000608 }
609 }
610 throw ParseException(
611 boost::str(
612 boost::format("No output binding found for layer:%1% / %2%") %
613 name %
614 CHECK_LOCATION().AsString()));
615}
616
Derek Lamberti8ddae332019-02-21 16:29:43 +0000617void Deserializer::SetupInputLayers(GraphPtr graph)
Kevin May43a799c2019-02-08 16:31:42 +0000618{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000619 CHECK_GRAPH(graph, 0);
620 auto inputs = GetGraphInputs(graph);
621 m_InputBindings.clear();
622 m_InputBindings.reserve(inputs.size());
Kevin May43a799c2019-02-08 16:31:42 +0000623 for (auto const& input : inputs)
624 {
Derek Lamberti8ddae332019-02-21 16:29:43 +0000625 LayerBindingId bindingId = GetBindingLayerInfo(graph, input->index());
Kevin May43a799c2019-02-08 16:31:42 +0000626 IConnectableLayer* layer =
Derek Lamberti8ddae332019-02-21 16:29:43 +0000627 m_Network->AddInputLayer(bindingId, input->layerName()->c_str());
Kevin May43a799c2019-02-08 16:31:42 +0000628
629 auto tensorInfo = ToTensorInfo(input->outputSlots()->Get(0)->tensorInfo());
630 layer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
631
Derek Lamberti8ddae332019-02-21 16:29:43 +0000632 RegisterOutputSlots(graph, input->index(), layer);
633
634 BOOST_ASSERT_MSG(input->layerName()->c_str(), "Input has no name.");
635 BindingPointInfo bindingInfo = {bindingId, tensorInfo};
636 m_InputBindings.push_back(std::make_pair(input->layerName()->c_str(), bindingInfo));
Kevin May43a799c2019-02-08 16:31:42 +0000637 }
638}
639
Derek Lamberti8ddae332019-02-21 16:29:43 +0000640void Deserializer::SetupOutputLayers(GraphPtr graph)
Kevin May43a799c2019-02-08 16:31:42 +0000641{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000642 CHECK_GRAPH(graph, 0);
643 auto outputs = GetGraphOutputs(graph);
644 m_OutputBindings.clear();
645 m_OutputBindings.reserve(outputs.size());
Kevin May43a799c2019-02-08 16:31:42 +0000646 for (auto const& output : outputs)
647 {
Derek Lamberti8ddae332019-02-21 16:29:43 +0000648 LayerBindingId bindingId = GetBindingLayerInfo(graph, output->index());
Kevin May43a799c2019-02-08 16:31:42 +0000649 IConnectableLayer* layer =
Derek Lamberti8ddae332019-02-21 16:29:43 +0000650 m_Network->AddOutputLayer(bindingId, output->layerName()->c_str());
Kevin May43a799c2019-02-08 16:31:42 +0000651
Derek Lamberti8ddae332019-02-21 16:29:43 +0000652 RegisterInputSlots(graph, output->index(), layer);
653
654 auto baseLayer = GetBaseLayer(graph, output->index());
655 auto sourceLayerIndex = baseLayer->inputSlots()->Get(0)->connection()->sourceLayerIndex();
656 auto sourceLayer = GetBaseLayer(graph, sourceLayerIndex);
657 auto tensorInfo = ToTensorInfo(sourceLayer->outputSlots()->Get(0)->tensorInfo());
658
659 BOOST_ASSERT_MSG(output->layerName()->c_str(), "Output has no name.");
660 BindingPointInfo bindingInfo = {bindingId, tensorInfo};
661 m_OutputBindings.push_back(std::make_pair(output->layerName()->c_str(), bindingInfo));
Kevin May43a799c2019-02-08 16:31:42 +0000662 }
663}
664
Derek Lamberti8ddae332019-02-21 16:29:43 +0000665void Deserializer::RegisterOutputSlots(GraphPtr graph,
666 uint32_t layerIndex,
667 IConnectableLayer* layer)
Kevin May43a799c2019-02-08 16:31:42 +0000668{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000669 CHECK_LAYERS(graph, 0, layerIndex);
Kevin May43a799c2019-02-08 16:31:42 +0000670 BOOST_ASSERT(layer != nullptr);
Derek Lamberti8ddae332019-02-21 16:29:43 +0000671 auto parsedLayer = GetBaseLayer(graph, layerIndex);
Kevin May43a799c2019-02-08 16:31:42 +0000672 if (parsedLayer->outputSlots()->size() != layer->GetNumOutputSlots())
673 {
674 throw ParseException(
675 boost::str(boost::format("The number of outputslots (%1%) does not match the number expected (%2%)"
676 " for layer index: %3% %4%") %
677 parsedLayer->outputSlots()->size() %
678 layer->GetNumOutputSlots() %
679 layerIndex %
680 CHECK_LOCATION().AsString()));
681 }
682
683 for (unsigned int slotIndex = 0; slotIndex < layer->GetNumOutputSlots(); ++slotIndex)
684 {
685 armnn::IOutputSlot* slot = &(layer->GetOutputSlot(slotIndex));
686 RegisterOutputSlotOfConnection(layerIndex, slot);
687 }
688}
689
Derek Lamberti8ddae332019-02-21 16:29:43 +0000690void Deserializer::RegisterInputSlots(GraphPtr graph,
691 uint32_t layerIndex,
692 armnn::IConnectableLayer* layer)
Kevin May43a799c2019-02-08 16:31:42 +0000693{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000694 CHECK_LAYERS(graph, 0, layerIndex);
Kevin May43a799c2019-02-08 16:31:42 +0000695 BOOST_ASSERT(layer != nullptr);
Derek Lamberti8ddae332019-02-21 16:29:43 +0000696 auto parsedLayer = GetBaseLayer(graph, layerIndex);
Kevin May43a799c2019-02-08 16:31:42 +0000697 if (parsedLayer->inputSlots()->size() != layer->GetNumInputSlots())
698 {
699 throw ParseException(
700 boost::str(boost::format("The number of inputslots (%1%) does not match the number expected (%2%)"
701 " for layer index:%3% %4%") %
702 parsedLayer->inputSlots()->size() %
703 layer->GetNumInputSlots() %
704 layerIndex %
705 CHECK_LOCATION().AsString()));
706 }
707
708 for (unsigned int slotIndex = 0; slotIndex < layer->GetNumInputSlots(); ++slotIndex)
709 {
710 armnn::IInputSlot* slot = &(layer->GetInputSlot(slotIndex));
711 uint32_t sourceLayerIndex = parsedLayer->inputSlots()->Get(slotIndex)->connection()->sourceLayerIndex();
712 RegisterInputSlotOfConnection(sourceLayerIndex, slot);
713 }
714}
715
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000716void Deserializer::RegisterInputSlotOfConnection(uint32_t connectionIndex,
Kevin May43a799c2019-02-08 16:31:42 +0000717 armnn::IInputSlot* slot)
718{
719 BOOST_ASSERT(m_GraphConnections[0].size() > connectionIndex);
720
721 Slots& slots = m_GraphConnections[0][connectionIndex];
722 slots.inputSlots.push_back(slot);
723}
724
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000725void Deserializer::RegisterOutputSlotOfConnection(uint32_t connectionIndex,
Kevin May43a799c2019-02-08 16:31:42 +0000726 armnn::IOutputSlot* slot)
727{
728 BOOST_ASSERT(m_GraphConnections[0].size() > connectionIndex);
729
730 Slots& slots = m_GraphConnections[0][connectionIndex];
731
732 // assuming there is only one producer for that tensor
733 if (slots.outputSlot != nullptr)
734 {
735 throw ParseException(boost::str(
736 boost::format("Another layer has already registered itself as the producer of "
737 "connection:%1% / %2%") %
738 connectionIndex %
739 CHECK_LOCATION().AsString()));
740 }
741
742 slots.outputSlot = slot;
743}
744
Derek Lamberti8ddae332019-02-21 16:29:43 +0000745void Deserializer::ParseActivation(GraphPtr graph, unsigned int layerIndex)
Mike Kellyaf484012019-02-20 16:53:11 +0000746{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000747 CHECK_LAYERS(graph, 0, layerIndex);
748 auto inputs = GetInputs(graph, layerIndex);
Mike Kellyaf484012019-02-20 16:53:11 +0000749 CHECK_LOCATION();
750 CHECK_VALID_SIZE(inputs.size(), 1);
751
Derek Lamberti8ddae332019-02-21 16:29:43 +0000752 auto outputs = GetOutputs(graph, layerIndex);
Mike Kellyaf484012019-02-20 16:53:11 +0000753 CHECK_VALID_SIZE(outputs.size(), 1);
754
Derek Lamberti8ddae332019-02-21 16:29:43 +0000755 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ActivationLayer();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000756 auto layerName = GetLayerName(graph, layerIndex);
Mike Kellyaf484012019-02-20 16:53:11 +0000757 auto serializerDescriptor = serializerLayer->descriptor();
758
759 armnn::ActivationDescriptor descriptor;
760 descriptor.m_Function = ToActivationFunction(serializerDescriptor->function());
761 descriptor.m_A = serializerDescriptor->a();
762 descriptor.m_B = serializerDescriptor->b();
763
764 IConnectableLayer* layer = m_Network->AddActivationLayer(descriptor,
765 layerName.c_str());
766 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
767 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
768
Derek Lamberti8ddae332019-02-21 16:29:43 +0000769 RegisterInputSlots(graph, layerIndex, layer);
770 RegisterOutputSlots(graph, layerIndex, layer);
Mike Kellyaf484012019-02-20 16:53:11 +0000771}
772
Derek Lamberti8ddae332019-02-21 16:29:43 +0000773void Deserializer::ParseAdd(GraphPtr graph, unsigned int layerIndex)
Kevin May43a799c2019-02-08 16:31:42 +0000774{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000775 CHECK_LAYERS(graph, 0, layerIndex);
776 auto inputs = GetInputs(graph, layerIndex);
Kevin May43a799c2019-02-08 16:31:42 +0000777 CHECK_LOCATION();
778 CHECK_VALID_SIZE(inputs.size(), 2);
779
Derek Lamberti8ddae332019-02-21 16:29:43 +0000780 auto outputs = GetOutputs(graph, layerIndex);
Kevin May43a799c2019-02-08 16:31:42 +0000781 CHECK_VALID_SIZE(outputs.size(), 1);
782
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000783 auto layerName = GetLayerName(graph, layerIndex);
784 IConnectableLayer* layer = m_Network->AddAdditionLayer(layerName.c_str());
Kevin May43a799c2019-02-08 16:31:42 +0000785
786 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
787 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
788
Derek Lamberti8ddae332019-02-21 16:29:43 +0000789 RegisterInputSlots(graph, layerIndex, layer);
790 RegisterOutputSlots(graph, layerIndex, layer);
Kevin May43a799c2019-02-08 16:31:42 +0000791}
792
Nattapat Chaimanowong6b4ed982019-02-26 17:24:13 +0000793void Deserializer::ParseBatchToSpaceNd(GraphPtr graph, unsigned int layerIndex)
794{
795 CHECK_LAYERS(graph, 0, layerIndex);
796
797 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
798 CHECK_VALID_SIZE(inputs.size(), 1);
799
800 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
801 CHECK_VALID_SIZE(outputs.size(), 1);
802
803 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_BatchToSpaceNdLayer()->descriptor();
804 auto flatBufferCrops = flatBufferDescriptor->crops();
805 auto flatBufferBlockShape = flatBufferDescriptor->blockShape();
806
807 if (flatBufferCrops->Length() % 2 != 0)
808 {
809 throw ParseException(boost::str(
810 boost::format("The size of crops must be divisible by 2 %1%") % CHECK_LOCATION().AsString()));
811 }
812
813 std::vector<std::pair<unsigned int, unsigned int>> crops;
814 crops.reserve(flatBufferCrops->Length() / 2);
815 for (unsigned int i = 0; i < flatBufferCrops->Length() - 1; i += 2)
816 {
817 crops.emplace_back(flatBufferCrops->Get(i), flatBufferCrops->Get(i+1));
818 }
819
820 armnn::BatchToSpaceNdDescriptor descriptor;
821 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
822 descriptor.m_BlockShape =
823 std::vector<unsigned int>(flatBufferBlockShape->begin(), flatBufferBlockShape->end());
824 descriptor.m_Crops = crops;
825
826 auto layerName = GetLayerName(graph, layerIndex);
827 IConnectableLayer* layer = m_Network->AddBatchToSpaceNdLayer(descriptor, layerName.c_str());
828
829 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
830 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
831
832 RegisterInputSlots(graph, layerIndex, layer);
833 RegisterOutputSlots(graph, layerIndex, layer);
834}
835
Conor Kennedy76277882019-02-26 08:29:54 +0000836void Deserializer::ParseConstant(GraphPtr graph, unsigned int layerIndex)
837{
838 CHECK_LAYERS(graph, 0, layerIndex);
839 CHECK_LOCATION();
840
841 auto outputs = GetOutputs(graph, layerIndex);
842 CHECK_VALID_SIZE(outputs.size(), 1);
843
844 auto layerName = GetLayerName(graph, layerIndex);
845
846 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ConstantLayer();
847 auto serializerInput = serializerLayer->input();
848
849 armnn::ConstTensor input = ToConstTensor(serializerInput);
850
851 IConnectableLayer* layer = m_Network->AddConstantLayer(input, layerName.c_str());
852
853 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
854 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
855
856 RegisterOutputSlots(graph, layerIndex, layer);
857}
858
Derek Lamberti8ddae332019-02-21 16:29:43 +0000859void Deserializer::ParseConvolution2d(GraphPtr graph, unsigned int layerIndex)
Mike Kellya0766c32019-02-19 17:22:07 +0000860{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000861 CHECK_LAYERS(graph, 0, layerIndex);
862 auto inputs = GetInputs(graph, layerIndex);
Mike Kellya0766c32019-02-19 17:22:07 +0000863 CHECK_LOCATION();
864 CHECK_VALID_SIZE(inputs.size(), 1);
865
Derek Lamberti8ddae332019-02-21 16:29:43 +0000866 auto outputs = GetOutputs(graph, layerIndex);
Mike Kellya0766c32019-02-19 17:22:07 +0000867 CHECK_VALID_SIZE(outputs.size(), 1);
868
Derek Lamberti8ddae332019-02-21 16:29:43 +0000869 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_Convolution2dLayer();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000870 auto layerName = GetLayerName(graph, layerIndex);
Mike Kellya0766c32019-02-19 17:22:07 +0000871 auto serializerDescriptor = serializerLayer->descriptor();
872
873 armnn::Convolution2dDescriptor descriptor;
874 descriptor.m_PadLeft = serializerDescriptor->padLeft();
875 descriptor.m_PadRight = serializerDescriptor->padRight();
876 descriptor.m_PadTop = serializerDescriptor->padTop();
877 descriptor.m_PadBottom = serializerDescriptor->padBottom();
878 descriptor.m_StrideX = serializerDescriptor->strideX();
879 descriptor.m_StrideY = serializerDescriptor->strideY();;
880 descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
881 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
882
883 armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
884 armnn::ConstTensor biases;
885
886 if (descriptor.m_BiasEnabled)
887 {
888 biases = ToConstTensor(serializerLayer->biases());
889 }
890 IConnectableLayer* layer = m_Network->AddConvolution2dLayer(descriptor,
891 weights,
892 biases,
893 layerName.c_str());
894 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
895 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
896
Derek Lamberti8ddae332019-02-21 16:29:43 +0000897 RegisterInputSlots(graph, layerIndex, layer);
898 RegisterOutputSlots(graph, layerIndex, layer);
Mike Kellya0766c32019-02-19 17:22:07 +0000899}
900
Derek Lamberti8ddae332019-02-21 16:29:43 +0000901void Deserializer::ParseDepthwiseConvolution2d(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000902{
Derek Lamberti8ddae332019-02-21 16:29:43 +0000903 CHECK_LAYERS(graph, 0, layerIndex);
904 auto inputs = GetInputs(graph, layerIndex);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000905 CHECK_LOCATION();
906 CHECK_VALID_SIZE(inputs.size(), 1);
907
Derek Lamberti8ddae332019-02-21 16:29:43 +0000908 auto outputs = GetOutputs(graph, layerIndex);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000909 CHECK_VALID_SIZE(outputs.size(), 1);
910
Derek Lamberti8ddae332019-02-21 16:29:43 +0000911 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_DepthwiseConvolution2dLayer();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000912 auto layerName = GetLayerName(graph, layerIndex);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000913 auto serializerDescriptor = serializerLayer->descriptor();
914
915 armnn::DepthwiseConvolution2dDescriptor descriptor;
916 descriptor.m_PadLeft = serializerDescriptor->padLeft();
917 descriptor.m_PadRight = serializerDescriptor->padRight();
918 descriptor.m_PadTop = serializerDescriptor->padTop();
919 descriptor.m_PadBottom = serializerDescriptor->padBottom();
920 descriptor.m_StrideX = serializerDescriptor->strideX();
921 descriptor.m_StrideY = serializerDescriptor->strideY();;
922 descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
923 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
924
925 armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
926 armnn::ConstTensor biases;
927
928 if (descriptor.m_BiasEnabled)
929 {
930 biases = ToConstTensor(serializerLayer->biases());
931 }
932 IConnectableLayer* layer = m_Network->AddDepthwiseConvolution2dLayer(descriptor,
933 weights,
934 biases,
935 layerName.c_str());
936
937 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
938 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
939
Derek Lamberti8ddae332019-02-21 16:29:43 +0000940 RegisterInputSlots(graph, layerIndex, layer);
941 RegisterOutputSlots(graph, layerIndex, layer);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000942}
943
Éanna Ó Catháin58885892019-02-27 16:16:39 +0000944void Deserializer::ParseDivision(GraphPtr graph, unsigned int layerIndex)
945{
946 CHECK_LAYERS(graph, 0, layerIndex);
947 auto inputs = GetInputs(graph, layerIndex);
948 CHECK_LOCATION();
949 CHECK_VALID_SIZE(inputs.size(), 2);
950
951 auto outputs = GetOutputs(graph, layerIndex);
952 CHECK_VALID_SIZE(outputs.size(), 1);
953
954 auto layerName = GetLayerName(graph, layerIndex);
955 IConnectableLayer* layer = m_Network->AddDivisionLayer(layerName.c_str());
956
957 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
958 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
959
960 RegisterInputSlots(graph, layerIndex, layer);
961 RegisterOutputSlots(graph, layerIndex, layer);
962}
963
Nattapat Chaimanowong235cea52019-02-28 16:27:30 +0000964void Deserializer::ParseEqual(GraphPtr graph, unsigned int layerIndex)
965{
966 CHECK_LAYERS(graph, 0, layerIndex);
967 auto inputs = GetInputs(graph, layerIndex);
968 CHECK_LOCATION();
969 CHECK_VALID_SIZE(inputs.size(), 2);
970
971 auto outputs = GetOutputs(graph, layerIndex);
972 CHECK_VALID_SIZE(outputs.size(), 1);
973
974 auto layerName = GetLayerName(graph, layerIndex);
975 IConnectableLayer* layer = m_Network->AddEqualLayer(layerName.c_str());
976
977 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
978 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
979
980 RegisterInputSlots(graph, layerIndex, layer);
981 RegisterOutputSlots(graph, layerIndex, layer);
982}
983
Aron Virginas-Tar0fe32452019-02-28 13:12:47 +0000984void Deserializer::ParseMinimum(GraphPtr graph, unsigned int layerIndex)
985{
986 CHECK_LAYERS(graph, 0, layerIndex);
987 auto inputs = GetInputs(graph, layerIndex);
988 CHECK_LOCATION();
989 CHECK_VALID_SIZE(inputs.size(), 2);
990
991 auto outputs = GetOutputs(graph, layerIndex);
992 CHECK_VALID_SIZE(outputs.size(), 1);
993
994 auto layerName = GetLayerName(graph, layerIndex);
995 IConnectableLayer* layer = m_Network->AddMinimumLayer(layerName.c_str());
996
997 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
998 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
999
1000 RegisterInputSlots(graph, layerIndex, layer);
1001 RegisterOutputSlots(graph, layerIndex, layer);
1002}
1003
Derek Lamberti8ddae332019-02-21 16:29:43 +00001004void Deserializer::ParseMultiplication(GraphPtr graph, unsigned int layerIndex)
Sadik Armagan5f450272019-02-12 14:31:45 +00001005{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001006 CHECK_LAYERS(graph, 0, layerIndex);
1007 auto inputs = GetInputs(graph, layerIndex);
Sadik Armagan5f450272019-02-12 14:31:45 +00001008 CHECK_LOCATION();
1009 CHECK_VALID_SIZE(inputs.size(), 2);
1010
Derek Lamberti8ddae332019-02-21 16:29:43 +00001011 auto outputs = GetOutputs(graph, layerIndex);
Sadik Armagan5f450272019-02-12 14:31:45 +00001012 CHECK_VALID_SIZE(outputs.size(), 1);
1013
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00001014 auto layerName = GetLayerName(graph, layerIndex);
1015 IConnectableLayer* layer = m_Network->AddMultiplicationLayer(layerName.c_str());
Sadik Armagan5f450272019-02-12 14:31:45 +00001016
1017 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1018 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1019
Derek Lamberti8ddae332019-02-21 16:29:43 +00001020 RegisterInputSlots(graph, layerIndex, layer);
1021 RegisterOutputSlots(graph, layerIndex, layer);
Sadik Armagan5f450272019-02-12 14:31:45 +00001022}
1023
Derek Lamberti8ddae332019-02-21 16:29:43 +00001024void Deserializer::ParseFullyConnected(GraphPtr graph, unsigned int layerIndex)
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00001025{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001026 CHECK_LAYERS(graph, 0, layerIndex);
1027 auto inputs = GetInputs(graph, layerIndex);
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00001028 CHECK_LOCATION();
1029 CHECK_VALID_SIZE(inputs.size(), 1);
1030
Derek Lamberti8ddae332019-02-21 16:29:43 +00001031 auto outputs = GetOutputs(graph, layerIndex);
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00001032 CHECK_VALID_SIZE(outputs.size(), 1);
1033
Derek Lamberti8ddae332019-02-21 16:29:43 +00001034 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_FullyConnectedLayer();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00001035 auto layerName = GetLayerName(graph, layerIndex);
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00001036 auto flatBufferDescriptor = flatBufferLayer->descriptor();
1037
1038 armnn::FullyConnectedDescriptor fullyConnectedDescriptor;
1039 fullyConnectedDescriptor.m_BiasEnabled = flatBufferDescriptor->biasEnabled();
1040 fullyConnectedDescriptor.m_TransposeWeightMatrix = flatBufferDescriptor->transposeWeightsMatrix();
1041
1042 armnn::ConstTensor weightsTensor = ToConstTensor(flatBufferLayer->weights());
1043
1044 armnn::IConnectableLayer* layer;
1045 if (flatBufferDescriptor->biasEnabled())
1046 {
1047 armnn::ConstTensor biasTensorData = ToConstTensor(flatBufferLayer->biases());
1048 layer = m_Network->AddFullyConnectedLayer(fullyConnectedDescriptor,
1049 weightsTensor,
1050 biasTensorData,
1051 layerName.c_str());
1052 }
1053 else
1054 {
1055 layer = m_Network->AddFullyConnectedLayer(fullyConnectedDescriptor,
1056 weightsTensor,
1057 layerName.c_str());
1058 }
1059
1060 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1061 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1062
Derek Lamberti8ddae332019-02-21 16:29:43 +00001063 RegisterInputSlots(graph, layerIndex, layer);
1064 RegisterOutputSlots(graph, layerIndex, layer);
Sadik Armagandbb0c0c2019-02-21 09:01:41 +00001065}
1066
Derek Lamberti8ddae332019-02-21 16:29:43 +00001067void Deserializer::ParsePermute(GraphPtr graph, unsigned int layerIndex)
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00001068{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001069 CHECK_LAYERS(graph, 0, layerIndex);
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00001070
1071 auto dimsMapping =
Derek Lamberti8ddae332019-02-21 16:29:43 +00001072 graph->layers()->Get(layerIndex)->layer_as_PermuteLayer()->descriptor()->dimMappings();
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00001073
Derek Lamberti8ddae332019-02-21 16:29:43 +00001074 auto inputs = GetInputs(graph, layerIndex);
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00001075 CHECK_VALID_SIZE(inputs.size(), 1);
1076
Derek Lamberti8ddae332019-02-21 16:29:43 +00001077 auto outputs = GetOutputs(graph, layerIndex);
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00001078 CHECK_VALID_SIZE(outputs.size(), 1);
1079 auto outputInfo = ToTensorInfo(outputs[0]);
1080
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00001081 auto layerName = GetLayerName(graph, layerIndex);
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00001082 const armnn::PermuteDescriptor descriptor(armnn::PermutationVector(dimsMapping->data(), dimsMapping->Length()));
1083
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00001084 IConnectableLayer* layer = m_Network->AddPermuteLayer(descriptor, layerName.c_str());
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00001085 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1086
Derek Lamberti8ddae332019-02-21 16:29:43 +00001087 RegisterInputSlots(graph, layerIndex, layer);
1088 RegisterOutputSlots(graph, layerIndex, layer);
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00001089}
1090
Derek Lamberti0028d1b2019-02-20 13:57:42 +00001091armnn::Pooling2dDescriptor Deserializer::GetPoolingDescriptor(Deserializer::PoolingDescriptor pooling2dDesc,
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00001092 unsigned int layerIndex)
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00001093{
1094 armnn::Pooling2dDescriptor desc;
1095
1096 switch (pooling2dDesc->poolType())
1097 {
1098 case PoolingAlgorithm_Average:
1099 {
1100 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00001101 break;
1102 }
1103 case PoolingAlgorithm_Max:
1104 {
1105 desc.m_PoolType = armnn::PoolingAlgorithm::Max;
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00001106 break;
1107 }
1108 default:
1109 {
1110 BOOST_ASSERT_MSG(false, "Unsupported pooling algorithm");
1111 }
1112 }
1113
1114 switch (pooling2dDesc->outputShapeRounding())
1115 {
1116 case OutputShapeRounding_Floor:
1117 {
1118 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1119 break;
1120 }
1121 case OutputShapeRounding_Ceiling:
1122 {
1123 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Ceiling;
1124 break;
1125 }
1126 default:
1127 {
1128 BOOST_ASSERT_MSG(false, "Unsupported output shape rounding");
1129 }
1130 }
1131
1132 switch (pooling2dDesc->paddingMethod())
1133 {
1134 case PaddingMethod_Exclude:
1135 {
1136 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1137 break;
1138 }
1139 case PaddingMethod_IgnoreValue:
1140 {
1141 desc.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1142 break;
1143 }
1144 default:
1145 {
1146 BOOST_ASSERT_MSG(false, "Unsupported padding method");
1147 }
1148 }
1149
1150 switch (pooling2dDesc->dataLayout())
1151 {
1152 case DataLayout_NCHW:
1153 {
1154 desc.m_DataLayout = armnn::DataLayout::NCHW;
1155 break;
1156 }
1157 case DataLayout_NHWC:
1158 {
1159 desc.m_DataLayout = armnn::DataLayout::NHWC;
1160 break;
1161 }
1162 default:
1163 {
1164 BOOST_ASSERT_MSG(false, "Unsupported data layout");
1165 }
1166 }
1167
1168 desc.m_PadRight = pooling2dDesc->padRight();
1169 desc.m_PadLeft = pooling2dDesc->padLeft();
1170 desc.m_PadBottom = pooling2dDesc->padBottom();
1171 desc.m_PadTop = pooling2dDesc->padTop();
1172 desc.m_StrideX = pooling2dDesc->strideX();
1173 desc.m_StrideY = pooling2dDesc->strideY();
1174 desc.m_PoolWidth = pooling2dDesc->poolWidth();
1175 desc.m_PoolHeight = pooling2dDesc->poolHeight();
1176
1177 return desc;
1178}
1179
Derek Lamberti8ddae332019-02-21 16:29:43 +00001180void Deserializer::ParsePooling2d(GraphPtr graph, unsigned int layerIndex)
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00001181{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001182 CHECK_LAYERS(graph, 0, layerIndex);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00001183
Derek Lamberti8ddae332019-02-21 16:29:43 +00001184 auto pooling2dDes = graph->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->descriptor();
Derek Lamberti8ddae332019-02-21 16:29:43 +00001185 auto inputs = GetInputs(graph, layerIndex);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00001186 CHECK_VALID_SIZE(inputs.size(), 1);
1187
Derek Lamberti8ddae332019-02-21 16:29:43 +00001188 auto outputs = GetOutputs(graph, layerIndex);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00001189 CHECK_VALID_SIZE(outputs.size(), 1);
1190 auto outputInfo = ToTensorInfo(outputs[0]);
1191
1192 auto pooling2dDescriptor = GetPoolingDescriptor(pooling2dDes, layerIndex);
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00001193 auto layerName = GetLayerName(graph, layerIndex);
1194 IConnectableLayer* layer = m_Network->AddPooling2dLayer(pooling2dDescriptor, layerName.c_str());
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00001195 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1196
Derek Lamberti8ddae332019-02-21 16:29:43 +00001197 RegisterInputSlots(graph, layerIndex, layer);
1198 RegisterOutputSlots(graph, layerIndex, layer);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00001199}
1200
Derek Lamberti0028d1b2019-02-20 13:57:42 +00001201armnn::TensorInfo Deserializer::OutputShapeOfReshape(const armnn::TensorInfo& inputTensorInfo,
Saoirse Stewart263829c2019-02-19 15:54:14 +00001202 const std::vector<uint32_t>& targetDimsIn)
1203{
1204 std::vector<unsigned int> outputDims(targetDimsIn.begin(), targetDimsIn.end());
1205 const auto stretchDim = std::find(targetDimsIn.begin(), targetDimsIn.end(), -1);
1206
1207 if (stretchDim != targetDimsIn.end())
1208 {
1209 if (std::find(std::next(stretchDim), targetDimsIn.end(), -1) != targetDimsIn.end())
1210 {
1211 throw ParseException(boost::str(
1212 boost::format("At most one component of shape can be -1 %1%") % CHECK_LOCATION().AsString()));
1213 }
1214
1215 auto targetNumElements =
1216 boost::numeric_cast<unsigned int>(
1217 std::accumulate(targetDimsIn.begin(), targetDimsIn.end(), -1, std::multiplies<int32_t>()));
1218
1219 auto stretchIndex = static_cast<size_t>(std::distance(targetDimsIn.begin(), stretchDim));
1220 outputDims[stretchIndex] = inputTensorInfo.GetNumElements() / targetNumElements;
1221 }
1222
1223 TensorShape outputShape = TensorShape(static_cast<unsigned int>(outputDims.size()), outputDims.data());
1224
1225 armnn::TensorInfo reshapeInfo = inputTensorInfo;
1226 reshapeInfo.SetShape(outputShape);
1227
1228 return reshapeInfo;
1229}
1230
Derek Lamberti8ddae332019-02-21 16:29:43 +00001231void Deserializer::ParseReshape(GraphPtr graph, unsigned int layerIndex)
Saoirse Stewart263829c2019-02-19 15:54:14 +00001232{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001233 CHECK_LAYERS(graph, 0, layerIndex);
1234 auto inputs = GetInputs(graph, layerIndex);
Saoirse Stewart263829c2019-02-19 15:54:14 +00001235
Derek Lamberti8ddae332019-02-21 16:29:43 +00001236 auto outputs = GetOutputs(graph, layerIndex);
Saoirse Stewart263829c2019-02-19 15:54:14 +00001237 CHECK_VALID_SIZE(outputs.size(), 1);
1238
1239 armnn::TensorInfo inputTensorInfo = ToTensorInfo(inputs[0]);
1240 armnn::TensorInfo actualOutputTensorInfo = ToTensorInfo(outputs[0]);
1241
Derek Lamberti8ddae332019-02-21 16:29:43 +00001242 const auto targetDims = graph->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->descriptor()->targetShape();
Saoirse Stewart263829c2019-02-19 15:54:14 +00001243 std::vector<uint32_t> outputDims(targetDims->begin(), targetDims->begin() + targetDims->size());
1244
Derek Lamberti0028d1b2019-02-20 13:57:42 +00001245 armnn::TensorInfo reshapeOutputTensorInfo = Deserializer::OutputShapeOfReshape(inputTensorInfo, outputDims);
Saoirse Stewart263829c2019-02-19 15:54:14 +00001246 const armnn::TensorShape& reshapeOutputTensorShape = reshapeOutputTensorInfo.GetShape();
1247
1248 const std::vector<uint32_t> expectedDims(outputs[0]->dimensions()->begin(),
1249 outputs[0]->dimensions()->begin() + outputs[0]->dimensions()->size());
1250
1251 if (inputs.size() > 1 && !CheckShape(reshapeOutputTensorShape, expectedDims))
1252 {
1253 std::stringstream ss;
1254 ss << "New shape defined in reshape parameters "
1255 << reshapeOutputTensorShape
1256 << " does not equal output shape "
1257 << actualOutputTensorInfo.GetShape()
1258 << ": "
1259 << CHECK_LOCATION().AsString();
1260 throw ParseException(ss.str());
1261 }
1262
1263 armnn::ReshapeDescriptor reshapeDesc;
1264 reshapeDesc.m_TargetShape = reshapeOutputTensorShape;
1265
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00001266 auto layerName = GetLayerName(graph, layerIndex);
Saoirse Stewart263829c2019-02-19 15:54:14 +00001267 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
1268 layer->GetOutputSlot(0).SetTensorInfo(reshapeOutputTensorInfo);
1269
Derek Lamberti8ddae332019-02-21 16:29:43 +00001270 RegisterInputSlots(graph, layerIndex, layer);
1271 RegisterOutputSlots(graph, layerIndex, layer);
Saoirse Stewart263829c2019-02-19 15:54:14 +00001272}
1273
Derek Lamberti8ddae332019-02-21 16:29:43 +00001274void Deserializer::ParseSoftmax(GraphPtr graph, unsigned int layerIndex)
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00001275{
Derek Lamberti8ddae332019-02-21 16:29:43 +00001276 CHECK_LAYERS(graph, 0, layerIndex);
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00001277
Derek Lamberti8ddae332019-02-21 16:29:43 +00001278 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00001279 CHECK_VALID_SIZE(inputs.size(), 1);
1280
Derek Lamberti8ddae332019-02-21 16:29:43 +00001281 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00001282 CHECK_VALID_SIZE(outputs.size(), 1);
1283
1284 armnn::SoftmaxDescriptor descriptor;
Derek Lamberti8ddae332019-02-21 16:29:43 +00001285 descriptor.m_Beta = graph->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->descriptor()->beta();
Éanna Ó Catháin633f8592019-02-25 16:26:29 +00001286 auto layerName = GetLayerName(graph, layerIndex);
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00001287
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00001288 IConnectableLayer* layer = m_Network->AddSoftmaxLayer(descriptor, layerName.c_str());
1289
1290 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1291 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1292
Derek Lamberti8ddae332019-02-21 16:29:43 +00001293 RegisterInputSlots(graph, layerIndex, layer);
1294 RegisterOutputSlots(graph, layerIndex, layer);
Kevin May43a799c2019-02-08 16:31:42 +00001295}
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00001296
Nattapat Chaimanowong45286992019-02-26 15:53:02 +00001297void Deserializer::ParseSpaceToBatchNd(GraphPtr graph, unsigned int layerIndex)
1298{
1299 CHECK_LAYERS(graph, 0, layerIndex);
1300
1301 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1302 CHECK_VALID_SIZE(inputs.size(), 1);
1303
1304 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1305 CHECK_VALID_SIZE(outputs.size(), 1);
1306
1307 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_SpaceToBatchNdLayer()->descriptor();
1308 auto flatBufferPadList = flatBufferDescriptor->padList();
1309 auto flatBufferBlockShape = flatBufferDescriptor->blockShape();
1310
1311 if (flatBufferPadList->Length() % 2 != 0)
1312 {
1313 throw ParseException(boost::str(
1314 boost::format("The size of the pad list must be divisible by 2 %1%") % CHECK_LOCATION().AsString()));
1315 }
1316
1317 std::vector<std::pair<unsigned int, unsigned int>> padList;
1318 padList.reserve(flatBufferPadList->Length() / 2);
1319 for (unsigned int i = 0; i < flatBufferPadList->Length() - 1; i += 2)
1320 {
1321 padList.emplace_back(flatBufferPadList->Get(i), flatBufferPadList->Get(i+1));
1322 }
1323
1324 armnn::SpaceToBatchNdDescriptor descriptor;
1325 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
1326 descriptor.m_BlockShape =
1327 std::vector<unsigned int>(flatBufferBlockShape->begin(), flatBufferBlockShape->end());
1328 descriptor.m_PadList = padList;
1329
1330 auto layerName = GetLayerName(graph, layerIndex);
1331 IConnectableLayer* layer = m_Network->AddSpaceToBatchNdLayer(descriptor, layerName.c_str());
1332
1333 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1334 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1335
1336 RegisterInputSlots(graph, layerIndex, layer);
1337 RegisterOutputSlots(graph, layerIndex, layer);
1338}
1339
Derek Lamberti0028d1b2019-02-20 13:57:42 +00001340} // namespace armnnDeserializer