blob: 5f9ca131987a24978682a9a6ac0ae40b98b116e9 [file] [log] [blame]
Mike Kelly8c1701a2019-02-11 17:01:27 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "Serializer.hpp"
Saoirse Stewart3166c3e2019-02-18 15:24:53 +00007
8#include "SerializerUtils.hpp"
9
Mike Kelly8c1701a2019-02-11 17:01:27 +000010#include <armnn/ArmNN.hpp>
Saoirse Stewart3166c3e2019-02-18 15:24:53 +000011
Mike Kelly8c1701a2019-02-11 17:01:27 +000012#include <iostream>
Saoirse Stewart3166c3e2019-02-18 15:24:53 +000013
Matthew Bentham268509a2019-02-25 13:58:24 +000014#include <ArmnnSchema_generated.h>
Saoirse Stewart3166c3e2019-02-18 15:24:53 +000015
Mike Kelly8c1701a2019-02-11 17:01:27 +000016#include <flatbuffers/util.h>
17
18using namespace armnn;
19namespace fb = flatbuffers;
Derek Lamberti0028d1b2019-02-20 13:57:42 +000020namespace serializer = armnnSerializer;
Mike Kelly8c1701a2019-02-11 17:01:27 +000021
22namespace armnnSerializer
23{
24
Mike Kellyaf484012019-02-20 16:53:11 +000025serializer::ActivationFunction GetFlatBufferActivationFunction(armnn::ActivationFunction function)
26{
27 switch (function)
28 {
29 case armnn::ActivationFunction::Sigmoid:
30 return serializer::ActivationFunction::ActivationFunction_Sigmoid;
31 case armnn::ActivationFunction::TanH:
32 return serializer::ActivationFunction::ActivationFunction_TanH;
33 case armnn::ActivationFunction::Linear:
34 return serializer::ActivationFunction::ActivationFunction_Linear;
35 case armnn::ActivationFunction::ReLu:
36 return serializer::ActivationFunction::ActivationFunction_ReLu;
37 case armnn::ActivationFunction::BoundedReLu:
38 return serializer::ActivationFunction::ActivationFunction_BoundedReLu;
39 case armnn::ActivationFunction::LeakyReLu:
40 return serializer::ActivationFunction::ActivationFunction_LeakyReLu;
41 case armnn::ActivationFunction::Abs:
42 return serializer::ActivationFunction::ActivationFunction_Abs;
43 case armnn::ActivationFunction::Sqrt:
44 return serializer::ActivationFunction::ActivationFunction_Sqrt;
45 case armnn::ActivationFunction::Square:
46 return serializer::ActivationFunction::ActivationFunction_Square;
47 default:
48 return serializer::ActivationFunction::ActivationFunction_Sigmoid;
49 }
50}
51
Saoirse Stewartcb8a3212019-02-14 15:46:10 +000052uint32_t SerializerVisitor::GetSerializedId(unsigned int guid)
53{
54 std::pair<unsigned int, uint32_t> guidPair(guid, m_layerId);
55
56 if (m_guidMap.empty())
57 {
58 m_guidMap.insert(guidPair);
59 }
60 else if (m_guidMap.find(guid) == m_guidMap.end())
61 {
62 guidPair.second = ++m_layerId;
63 m_guidMap.insert(guidPair);
64 return m_layerId;
65 }
Saoirse Stewart30211042019-02-18 17:19:16 +000066 return m_guidMap[guid];
Saoirse Stewartcb8a3212019-02-14 15:46:10 +000067}
68
Mike Kelly8c1701a2019-02-11 17:01:27 +000069// Build FlatBuffer for Input Layer
Derek Lamberti0028d1b2019-02-20 13:57:42 +000070void SerializerVisitor::VisitInputLayer(const armnn::IConnectableLayer* layer, LayerBindingId id, const char* name)
Mike Kelly8c1701a2019-02-11 17:01:27 +000071{
72 // Create FlatBuffer BaseLayer
73 auto flatBufferInputBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Input);
74
75 // Create FlatBuffer BindableBaseLayer
76 auto flatBufferInputBindableBaseLayer = serializer::CreateBindableLayerBase(m_flatBufferBuilder,
77 flatBufferInputBaseLayer,
78 id);
Mike Kelly8c1701a2019-02-11 17:01:27 +000079 // Push layer Guid to outputIds.
Saoirse Stewartcb8a3212019-02-14 15:46:10 +000080 m_inputIds.push_back(GetSerializedId(layer->GetGuid()));
Mike Kelly8c1701a2019-02-11 17:01:27 +000081
82 // Create the FlatBuffer InputLayer
83 auto flatBufferInputLayer = serializer::CreateInputLayer(m_flatBufferBuilder, flatBufferInputBindableBaseLayer);
84
85 // Add the AnyLayer to the FlatBufferLayers
86 CreateAnyLayer(flatBufferInputLayer.o, serializer::Layer::Layer_InputLayer);
87}
88
89// Build FlatBuffer for Output Layer
Derek Lamberti0028d1b2019-02-20 13:57:42 +000090void SerializerVisitor::VisitOutputLayer(const armnn::IConnectableLayer* layer, LayerBindingId id, const char* name)
Mike Kelly8c1701a2019-02-11 17:01:27 +000091{
92 // Create FlatBuffer BaseLayer
93 auto flatBufferOutputBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Output);
94
95 // Create FlatBuffer BindableBaseLayer
96 auto flatBufferOutputBindableBaseLayer = serializer::CreateBindableLayerBase(m_flatBufferBuilder,
97 flatBufferOutputBaseLayer,
98 id);
99 // Push layer Guid to outputIds.
Saoirse Stewartcb8a3212019-02-14 15:46:10 +0000100 m_outputIds.push_back(GetSerializedId(layer->GetGuid()));
Mike Kelly8c1701a2019-02-11 17:01:27 +0000101
102 // Create the FlatBuffer OutputLayer
103 auto flatBufferOutputLayer = serializer::CreateOutputLayer(m_flatBufferBuilder, flatBufferOutputBindableBaseLayer);
104 // Add the AnyLayer to the FlatBufferLayers
105 CreateAnyLayer(flatBufferOutputLayer.o, serializer::Layer::Layer_OutputLayer);
106}
107
Mike Kellyaf484012019-02-20 16:53:11 +0000108// Build FlatBuffer for Activation Layer
109void SerializerVisitor::VisitActivationLayer(const armnn::IConnectableLayer* layer,
110 const armnn::ActivationDescriptor& descriptor,
111 const char* name)
112{
113 // Create FlatBuffer BaseLayer
114 auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Activation);
115
116 // Create the FlatBuffer ActivationDescriptor
117 auto flatBufferDescriptor = CreateActivationDescriptor(m_flatBufferBuilder,
118 GetFlatBufferActivationFunction(descriptor.m_Function),
119 descriptor.m_A,
120 descriptor.m_B);
121
122 // Create the FlatBuffer ActivationLayer
123 auto flatBufferAdditionLayer = CreateActivationLayer(m_flatBufferBuilder,
124 flatBufferBaseLayer,
125 flatBufferDescriptor);
126
127 // Add the AnyLayer to the FlatBufferLayers
128 CreateAnyLayer(flatBufferAdditionLayer.o, serializer::Layer::Layer_ActivationLayer);
129}
130
Mike Kelly8c1701a2019-02-11 17:01:27 +0000131// Build FlatBuffer for Addition Layer
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000132void SerializerVisitor::VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000133{
134 // Create FlatBuffer BaseLayer
135 auto flatBufferAdditionBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Addition);
136
137 // Create the FlatBuffer AdditionLayer
138 auto flatBufferAdditionLayer = serializer::CreateAdditionLayer(m_flatBufferBuilder, flatBufferAdditionBaseLayer);
139
140 // Add the AnyLayer to the FlatBufferLayers
141 CreateAnyLayer(flatBufferAdditionLayer.o, serializer::Layer::Layer_AdditionLayer);
142}
143
Nattapat Chaimanowong6b4ed982019-02-26 17:24:13 +0000144// Build FlatBuffer for BatchToSpaceNd Layer
145void SerializerVisitor::VisitBatchToSpaceNdLayer(const armnn::IConnectableLayer* layer,
146 const armnn::BatchToSpaceNdDescriptor& descriptor,
147 const char* name)
148{
149 // Create FlatBuffer BaseLayer
150 auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_BatchToSpaceNd);
151
152 std::vector<unsigned int> crops;
153 crops.reserve(descriptor.m_Crops.size() * 2);
154 for (auto& crop : descriptor.m_Crops)
155 {
156 crops.push_back(crop.first);
157 crops.push_back(crop.second);
158 }
159
160 auto flatBufferDescriptor =
161 CreateBatchToSpaceNdDescriptor(m_flatBufferBuilder,
162 m_flatBufferBuilder.CreateVector(descriptor.m_BlockShape),
163 m_flatBufferBuilder.CreateVector(crops),
164 GetFlatBufferDataLayout(descriptor.m_DataLayout));
165
166 auto flatBufferLayer = serializer::CreateBatchToSpaceNdLayer(m_flatBufferBuilder,
167 flatBufferBaseLayer,
168 flatBufferDescriptor);
169
170 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_BatchToSpaceNdLayer);
171}
172
Conor Kennedy76277882019-02-26 08:29:54 +0000173// Build FlatBuffer for Constant Layer
174void SerializerVisitor::VisitConstantLayer(const armnn::IConnectableLayer* layer,
175 const armnn::ConstTensor& input,
176 const char* name)
177{
178 // Create FlatBuffer BaseLayer
179 auto flatBufferConstantBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Constant);
180
181 auto flatBufferConstTensorInfo = CreateConstTensorInfo(input);
182
183 // Create the FlatBuffer ConstantLayer
184 auto flatBufferLayer = CreateConstantLayer(m_flatBufferBuilder,
185 flatBufferConstantBaseLayer,
186 flatBufferConstTensorInfo);
187
188 // Add the AnyLayer to the FlatBufferLayers
189 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_ConstantLayer);
190}
191
Mike Kellya0766c32019-02-19 17:22:07 +0000192// Build FlatBuffer for Convolution2dLayer
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000193void SerializerVisitor::VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
194 const armnn::Convolution2dDescriptor& descriptor,
195 const armnn::ConstTensor& weights,
196 const armnn::Optional<armnn::ConstTensor>& biases,
Mike Kellya0766c32019-02-19 17:22:07 +0000197 const char* name)
198{
199 // Create FlatBuffer BaseLayer
200 auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Convolution2d);
201
202 auto flatBufferDescriptor = CreateConvolution2dDescriptor(m_flatBufferBuilder,
203 descriptor.m_PadLeft,
204 descriptor.m_PadRight,
205 descriptor.m_PadTop,
206 descriptor.m_PadBottom,
207 descriptor.m_StrideX,
208 descriptor.m_StrideY,
209 descriptor.m_BiasEnabled,
210 GetFlatBufferDataLayout(descriptor.m_DataLayout));
211 auto flatBufferWeightsConstTensorInfo = CreateConstTensorInfo(weights);
212 flatbuffers::Offset<serializer::ConstTensor> flatBufferBiasesConstTensorInfo;
213
214 if (biases.has_value())
215 {
216 flatBufferBiasesConstTensorInfo = CreateConstTensorInfo(biases.value());
217 }
218
219 // Create the FlatBuffer Convolution2dLayer
220 auto flatBufferLayer = CreateConvolution2dLayer(m_flatBufferBuilder,
221 flatBufferBaseLayer,
222 flatBufferDescriptor,
223 flatBufferWeightsConstTensorInfo,
224 flatBufferBiasesConstTensorInfo);
225
226 // Add the AnyLayer to the FlatBufferLayers
227 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_Convolution2dLayer);
228}
229
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000230void SerializerVisitor::VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
231 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
232 const armnn::ConstTensor& weights,
233 const armnn::Optional<armnn::ConstTensor>& biases,
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000234 const char* name)
235{
236 auto fbBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_DepthwiseConvolution2d);
237 auto fbDescriptor = CreateDepthwiseConvolution2dDescriptor(m_flatBufferBuilder,
238 descriptor.m_PadLeft,
239 descriptor.m_PadRight,
240 descriptor.m_PadTop,
241 descriptor.m_PadBottom,
242 descriptor.m_StrideX,
243 descriptor.m_StrideY,
244 descriptor.m_BiasEnabled,
245 GetFlatBufferDataLayout(descriptor.m_DataLayout));
246
247 flatbuffers::Offset<serializer::ConstTensor> fbWeightsConstTensorInfo = CreateConstTensorInfo(weights);
248 flatbuffers::Offset<serializer::ConstTensor> fbBiasesConstTensorInfo;
249 if (biases.has_value())
250 {
251 fbBiasesConstTensorInfo = CreateConstTensorInfo(biases.value());
252 }
253
254 auto flatBufferLayer = CreateDepthwiseConvolution2dLayer(m_flatBufferBuilder,
255 fbBaseLayer,
256 fbDescriptor,
257 fbWeightsConstTensorInfo,
258 fbBiasesConstTensorInfo);
259
260 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_DepthwiseConvolution2dLayer);
261}
262
Éanna Ó Catháin58885892019-02-27 16:16:39 +0000263void SerializerVisitor::VisitDivisionLayer(const armnn::IConnectableLayer* layer, const char* name)
264{
Aron Virginas-Tar0fe32452019-02-28 13:12:47 +0000265 auto fbDivisionBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Division);
266 auto fbDivisionLayer = serializer::CreateDivisionLayer(m_flatBufferBuilder, fbDivisionBaseLayer);
Éanna Ó Catháin58885892019-02-27 16:16:39 +0000267
Aron Virginas-Tar0fe32452019-02-28 13:12:47 +0000268 CreateAnyLayer(fbDivisionLayer.o, serializer::Layer::Layer_DivisionLayer);
269}
Éanna Ó Catháin58885892019-02-27 16:16:39 +0000270
Aron Virginas-Tar377351e2019-02-27 14:42:31 +0000271void SerializerVisitor::VisitEqualLayer(const armnn::IConnectableLayer* layer, const char* name)
272{
273 auto fbBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Equal);
274 auto fbEqualLayer = serializer::CreateEqualLayer(m_flatBufferBuilder, fbBaseLayer);
275
276 CreateAnyLayer(fbEqualLayer.o, serializer::Layer::Layer_EqualLayer);
277}
278
Aron Virginas-Tar0fe32452019-02-28 13:12:47 +0000279void SerializerVisitor::VisitMinimumLayer(const armnn::IConnectableLayer* layer, const char* name)
280{
281 auto fbMinimumBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Minimum);
282 auto fbMinimumLayer = serializer::CreateMinimumLayer(m_flatBufferBuilder, fbMinimumBaseLayer);
283
284 CreateAnyLayer(fbMinimumLayer.o, serializer::Layer::Layer_MinimumLayer);
Éanna Ó Catháin58885892019-02-27 16:16:39 +0000285}
286
Aron Virginas-Tar377351e2019-02-27 14:42:31 +0000287void SerializerVisitor::VisitMaximumLayer(const armnn::IConnectableLayer* layer, const char* name)
Nattapat Chaimanowong235cea52019-02-28 16:27:30 +0000288{
Aron Virginas-Tar377351e2019-02-27 14:42:31 +0000289 auto fbMaximumBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Maximum);
290 auto fbMaximumLayer = serializer::CreateMaximumLayer(m_flatBufferBuilder, fbMaximumBaseLayer);
Nattapat Chaimanowong235cea52019-02-28 16:27:30 +0000291
Aron Virginas-Tar377351e2019-02-27 14:42:31 +0000292 CreateAnyLayer(fbMaximumLayer.o, serializer::Layer::Layer_MaximumLayer);
Nattapat Chaimanowong235cea52019-02-28 16:27:30 +0000293}
294
Sadik Armagan5f450272019-02-12 14:31:45 +0000295// Build FlatBuffer for Multiplication Layer
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000296void SerializerVisitor::VisitMultiplicationLayer(const armnn::IConnectableLayer* layer, const char* name)
Sadik Armagan5f450272019-02-12 14:31:45 +0000297{
298 // Create FlatBuffer BaseLayer
299 auto flatBufferMultiplicationBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Multiplication);
300
301 // Create the FlatBuffer MultiplicationLayer
302 auto flatBufferMultiplicationLayer =
303 serializer::CreateMultiplicationLayer(m_flatBufferBuilder, flatBufferMultiplicationBaseLayer);
304
305 // Add the AnyLayer to the FlatBufferLayers
306 CreateAnyLayer(flatBufferMultiplicationLayer.o, serializer::Layer::Layer_MultiplicationLayer);
307}
308
Nattapat Chaimanowongebb0f9c2019-03-01 12:14:06 +0000309void SerializerVisitor::VisitPadLayer(const armnn::IConnectableLayer* layer,
310 const armnn::PadDescriptor& padDescriptor,
311 const char* name)
312{
313 auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Pad);
314
315 std::vector<unsigned int> padList;
316 for (auto& p: padDescriptor.m_PadList)
317 {
318 padList.push_back(p.first);
319 padList.push_back(p.second);
320 }
321
322 auto flatBufferPadDesc = serializer::CreatePadDescriptor(m_flatBufferBuilder,
323 m_flatBufferBuilder.CreateVector(padList));
324
325 auto flatBufferPadLayer = serializer::CreatePadLayer(m_flatBufferBuilder,
326 flatBufferBaseLayer,
327 flatBufferPadDesc);
328
329 CreateAnyLayer(flatBufferPadLayer.o, serializer::Layer::Layer_PadLayer);
330}
331
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +0000332void SerializerVisitor::VisitPermuteLayer(const armnn::IConnectableLayer* layer,
333 const armnn::PermuteDescriptor& permuteDescriptor,
334 const char* name)
335{
336 // Create FlatBuffer BaseLayer
337 auto flatBufferPermuteBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Permute);
338
339 std::vector<unsigned int> dimMappings;
340 for (auto& v: permuteDescriptor.m_DimMappings)
341 {
342 dimMappings.push_back(v);
343 }
344
345 auto flatBufferPermuteDesc = serializer::CreatePermuteDescriptor(m_flatBufferBuilder,
346 m_flatBufferBuilder.CreateVector(dimMappings));
347
348 // Create the FlatBuffer PermuteLayer
349 auto flatBufferPermuteLayer = serializer::CreatePermuteLayer(m_flatBufferBuilder,
350 flatBufferPermuteBaseLayer,
351 flatBufferPermuteDesc);
352
353 // Add the AnyLayer to the FlatBufferLayers
354 CreateAnyLayer(flatBufferPermuteLayer.o, serializer::Layer::Layer_PermuteLayer);
355}
356
Saoirse Stewart263829c2019-02-19 15:54:14 +0000357// Build FlatBuffer for Reshape Layer
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000358void SerializerVisitor::VisitReshapeLayer(const armnn::IConnectableLayer* layer,
Saoirse Stewart263829c2019-02-19 15:54:14 +0000359 const armnn::ReshapeDescriptor& reshapeDescriptor,
360 const char* name)
361{
362 // Create FlatBuffer BaseLayer
363 auto flatBufferReshapeBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Reshape);
364
365 std::vector<unsigned int> targetShape;
366 for (unsigned int i =0; i < reshapeDescriptor.m_TargetShape.GetNumDimensions(); i++)
367 {
368 targetShape.push_back(reshapeDescriptor.m_TargetShape[i]);
369 }
370
371 auto flatBufferReshapeDesc = serializer::CreateReshapeDescriptor(m_flatBufferBuilder,
372 m_flatBufferBuilder.CreateVector(targetShape));
373
374 // Create the FlatBuffer ReshapeLayer
375 auto flatBufferReshapeLayer = serializer::CreateReshapeLayer(m_flatBufferBuilder, flatBufferReshapeBaseLayer,
376 flatBufferReshapeDesc);
377
378 // Add the AnyLayer to the FlatBufferLayers
379 CreateAnyLayer(flatBufferReshapeLayer.o, serializer::Layer::Layer_ReshapeLayer);
380}
381
Sadik Armagan8b42a382019-03-01 14:24:49 +0000382void SerializerVisitor::VisitRsqrtLayer(const armnn::IConnectableLayer* layer, const char* name)
383{
384 auto fbRsqrtBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Rsqrt);
385 auto fbRsqrtLayer = serializer::CreateRsqrtLayer(m_flatBufferBuilder, fbRsqrtBaseLayer);
386
387 CreateAnyLayer(fbRsqrtLayer.o, serializer::Layer::Layer_RsqrtLayer);
388}
389
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000390// Build FlatBuffer for Softmax Layer
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000391void SerializerVisitor::VisitSoftmaxLayer(const armnn::IConnectableLayer* layer,
392 const armnn::SoftmaxDescriptor& softmaxDescriptor,
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000393 const char* name)
394{
395 // Create FlatBuffer BaseLayer
396 auto flatBufferSoftmaxBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Softmax);
397
398 // Create the FlatBuffer SoftmaxDescriptor
399 auto flatBufferSoftmaxDesc =
400 serializer::CreateSoftmaxDescriptor(m_flatBufferBuilder, softmaxDescriptor.m_Beta);
401
402 // Create the FlatBuffer SoftmaxLayer
403 auto flatBufferSoftmaxLayer =
404 serializer::CreateSoftmaxLayer(m_flatBufferBuilder,
405 flatBufferSoftmaxBaseLayer,
406 flatBufferSoftmaxDesc);
407
408 CreateAnyLayer(flatBufferSoftmaxLayer.o, serializer::Layer::Layer_SoftmaxLayer);
409}
410
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000411void SerializerVisitor::VisitPooling2dLayer(const armnn::IConnectableLayer* layer,
412 const armnn::Pooling2dDescriptor& pooling2dDescriptor,
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000413 const char* name)
414{
415 auto fbPooling2dBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Pooling2d);
416 auto fbPooling2dDescriptor = serializer::CreatePooling2dDescriptor(
417 m_flatBufferBuilder,
418 GetFlatBufferPoolingAlgorithm(pooling2dDescriptor.m_PoolType),
419 pooling2dDescriptor.m_PadLeft,
420 pooling2dDescriptor.m_PadRight,
421 pooling2dDescriptor.m_PadTop,
422 pooling2dDescriptor.m_PadBottom,
423 pooling2dDescriptor.m_PoolWidth,
424 pooling2dDescriptor.m_PoolHeight,
425 pooling2dDescriptor.m_StrideX,
426 pooling2dDescriptor.m_StrideY,
427 GetFlatBufferOutputShapeRounding(pooling2dDescriptor.m_OutputShapeRounding),
428 GetFlatBufferPaddingMethod(pooling2dDescriptor.m_PaddingMethod),
429 GetFlatBufferDataLayout(pooling2dDescriptor.m_DataLayout));
430
431 auto fbPooling2dLayer = serializer::CreatePooling2dLayer(m_flatBufferBuilder,
432 fbPooling2dBaseLayer,
433 fbPooling2dDescriptor);
434
435 CreateAnyLayer(fbPooling2dLayer.o, serializer::Layer::Layer_Pooling2dLayer);
436}
437
Sadik Armagandbb0c0c2019-02-21 09:01:41 +0000438// Build FlatBuffer for FullyConnected Layer
439void SerializerVisitor::VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
440 const armnn::FullyConnectedDescriptor& fullyConnectedDescriptor,
441 const armnn::ConstTensor& weights,
442 const armnn::Optional<armnn::ConstTensor>& biases,
443 const char* name)
444{
445 // Create FlatBuffer BaseLayer
446 auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_FullyConnected);
447
448 // Create FlatBuffer FullyConnectedDescriptor
449 auto flatBufferDescriptor =
450 serializer::CreateFullyConnectedDescriptor(m_flatBufferBuilder,
451 fullyConnectedDescriptor.m_BiasEnabled,
452 fullyConnectedDescriptor.m_TransposeWeightMatrix);
453
454 // Create FlatBuffer weights data
455 auto flatBufferWeights = CreateConstTensorInfo(weights);
456
457 // Create FlatBuffer bias data
458 flatbuffers::Offset<serializer::ConstTensor> flatBufferBiases;
459 if (fullyConnectedDescriptor.m_BiasEnabled)
460 {
461 flatBufferBiases = CreateConstTensorInfo(biases.value());
462 }
463
464 // Create FlatBuffer FullyConnectedLayer
465 auto flatBufferLayer = serializer::CreateFullyConnectedLayer(m_flatBufferBuilder,
466 flatBufferBaseLayer,
467 flatBufferDescriptor,
468 flatBufferWeights,
469 flatBufferBiases);
470
471 // Add created FullyConnectedLayer to the FlatBufferLayers
472 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_FullyConnectedLayer);
473}
474
Nattapat Chaimanowong45286992019-02-26 15:53:02 +0000475// Build FlatBuffer for SpaceToBatchNd Layer
476void SerializerVisitor::VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer* layer,
477 const armnn::SpaceToBatchNdDescriptor& spaceToBatchNdDescriptor,
478 const char* name)
479{
480 // Create FlatBuffer BaseLayer
481 auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_SpaceToBatchNd);
482
483 std::vector<unsigned int> padList;
484 padList.reserve(spaceToBatchNdDescriptor.m_PadList.size()*2);
485 for (auto& pad : spaceToBatchNdDescriptor.m_PadList)
486 {
487 padList.push_back(pad.first);
488 padList.push_back(pad.second);
489 }
490
491 auto flatBufferDescriptor =
492 CreateSpaceToBatchNdDescriptor(m_flatBufferBuilder,
493 m_flatBufferBuilder.CreateVector(spaceToBatchNdDescriptor.m_BlockShape),
494 m_flatBufferBuilder.CreateVector(padList),
495 GetFlatBufferDataLayout(spaceToBatchNdDescriptor.m_DataLayout));
496
497 auto flatBufferLayer = serializer::CreateSpaceToBatchNdLayer(m_flatBufferBuilder,
498 flatBufferBaseLayer,
499 flatBufferDescriptor);
500
501 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_SpaceToBatchNdLayer);
502}
503
Nina Drozd57728782019-02-27 10:53:27 +0000504void SerializerVisitor::VisitNormalizationLayer(const armnn::IConnectableLayer* layer,
505 const armnn::NormalizationDescriptor& descriptor,
506 const char* name)
507{
508 auto fbNormalizationBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Normalization);
509
510 auto fbNormalizationDescriptor = serializer::CreateNormalizationDescriptor(
511 m_flatBufferBuilder,
512 GetFlatBufferNormalizationAlgorithmChannel(descriptor.m_NormChannelType),
513 GetFlatBufferNormalizationAlgorithmMethod(descriptor.m_NormMethodType),
514 descriptor.m_NormSize,
515 descriptor.m_Alpha,
516 descriptor.m_Beta,
517 descriptor.m_K,
518 GetFlatBufferDataLayout(descriptor.m_DataLayout));
519
520 auto flatBufferLayer = serializer::CreateNormalizationLayer(m_flatBufferBuilder,
521 fbNormalizationBaseLayer,
522 fbNormalizationDescriptor);
523
524 CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_NormalizationLayer);
525}
526
Sadik Armagandbb0c0c2019-02-21 09:01:41 +0000527fb::Offset<serializer::LayerBase> SerializerVisitor::CreateLayerBase(const IConnectableLayer* layer,
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000528 const serializer::LayerType layerType)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000529{
530 std::vector<fb::Offset<serializer::InputSlot>> inputSlots = CreateInputSlots(layer);
531 std::vector<fb::Offset<serializer::OutputSlot>> outputSlots = CreateOutputSlots(layer);
532
533 return serializer::CreateLayerBase(m_flatBufferBuilder,
Saoirse Stewartcb8a3212019-02-14 15:46:10 +0000534 GetSerializedId(layer->GetGuid()),
Mike Kelly8c1701a2019-02-11 17:01:27 +0000535 m_flatBufferBuilder.CreateString(layer->GetName()),
536 layerType,
537 m_flatBufferBuilder.CreateVector(inputSlots),
538 m_flatBufferBuilder.CreateVector(outputSlots));
539}
540
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000541void SerializerVisitor::CreateAnyLayer(const flatbuffers::Offset<void>& layer, const serializer::Layer serializerLayer)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000542{
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000543 auto anyLayer = armnnSerializer::CreateAnyLayer(m_flatBufferBuilder, serializerLayer, layer);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000544 m_serializedLayers.push_back(anyLayer);
545}
546
Mike Kellya0766c32019-02-19 17:22:07 +0000547template <typename T>
548flatbuffers::Offset<flatbuffers::Vector<T>> SerializerVisitor::CreateDataVector(const void* memory, unsigned int size)
549{
550 const T* buffer = reinterpret_cast<const T*>(memory);
551 std::vector<T> vector(buffer, buffer + (size / sizeof(T)));
552 auto fbVector = m_flatBufferBuilder.CreateVector(vector);
553 return fbVector;
554}
555
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000556flatbuffers::Offset<serializer::ConstTensor>
557 SerializerVisitor::CreateConstTensorInfo(const armnn::ConstTensor& constTensor)
Mike Kellya0766c32019-02-19 17:22:07 +0000558{
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000559 armnn::TensorInfo tensorInfo = constTensor.GetInfo();
Mike Kellya0766c32019-02-19 17:22:07 +0000560
561 // Get the dimensions
562 std::vector<unsigned int> shape;
563
564 for(unsigned int dim = 0; dim < tensorInfo.GetShape().GetNumDimensions(); ++dim)
565 {
566 shape.push_back(tensorInfo.GetShape()[dim]);
567 }
568
569 // Create FlatBuffer TensorInfo
570 auto flatBufferTensorInfo = serializer::CreateTensorInfo(m_flatBufferBuilder,
571 m_flatBufferBuilder.CreateVector(shape),
572 GetFlatBufferDataType(tensorInfo.GetDataType()),
573 tensorInfo.GetQuantizationScale(),
574 tensorInfo.GetQuantizationOffset());
575 flatbuffers::Offset<void> fbPayload;
576
577 switch (tensorInfo.GetDataType())
578 {
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000579 case armnn::DataType::Float32:
580 case armnn::DataType::Signed32:
Mike Kellya0766c32019-02-19 17:22:07 +0000581 {
582 auto fbVector = CreateDataVector<int32_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
583 flatbuffers::Offset<serializer::IntData> flatBuffersData = serializer::CreateIntData(
584 m_flatBufferBuilder,
585 fbVector);
586 fbPayload = flatBuffersData.o;
587 break;
588 }
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000589 case armnn::DataType::Float16:
Mike Kellya0766c32019-02-19 17:22:07 +0000590 {
591 auto fbVector = CreateDataVector<int16_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
592 flatbuffers::Offset<serializer::ShortData> flatBuffersData = serializer::CreateShortData(
593 m_flatBufferBuilder,
594 fbVector);
595 fbPayload = flatBuffersData.o;
596 break;
597 }
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000598 case armnn::DataType::QuantisedAsymm8:
599 case armnn::DataType::Boolean:
Mike Kellya0766c32019-02-19 17:22:07 +0000600 default:
601 {
602 auto fbVector = CreateDataVector<int8_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
603 flatbuffers::Offset<serializer::ByteData> flatBuffersData = serializer::CreateByteData(
604 m_flatBufferBuilder,
605 fbVector);
606 fbPayload = flatBuffersData.o;
607 }
608 }
609 flatbuffers::Offset<serializer::ConstTensor> flatBufferConstTensor = serializer::CreateConstTensor(
610 m_flatBufferBuilder,
611 flatBufferTensorInfo,
612 GetFlatBufferConstTensorData(tensorInfo.GetDataType()),
613 fbPayload);
614 return flatBufferConstTensor;
615}
616
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000617std::vector<fb::Offset<serializer::InputSlot>>
618 SerializerVisitor::CreateInputSlots(const armnn::IConnectableLayer* layer)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000619{
Mike Kellya0766c32019-02-19 17:22:07 +0000620 std::vector<fb::Offset<serializer::InputSlot>> inputSlots;
Mike Kelly8c1701a2019-02-11 17:01:27 +0000621
622 // Get the InputSlots
623 for (unsigned int slotIndex = 0; slotIndex<layer->GetNumInputSlots(); ++slotIndex)
624 {
625 const IInputSlot& inputSlot = layer->GetInputSlot(slotIndex);
626
627 // Get the Connection for the InputSlot
628 const IOutputSlot* connection = inputSlot.GetConnection();
629
630 // Create FlatBuffer Connection
Saoirse Stewartcb8a3212019-02-14 15:46:10 +0000631 serializer::Connection conn(GetSerializedId(inputSlot.GetConnection()->GetOwningLayerGuid()),
632 connection->CalculateIndexOnOwner());
Mike Kelly8c1701a2019-02-11 17:01:27 +0000633 // Create FlatBuffer InputSlot
634 inputSlots.push_back(serializer::CreateInputSlot(m_flatBufferBuilder, slotIndex, &conn));
635 }
636 return inputSlots;
637}
638
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000639std::vector<fb::Offset<serializer::OutputSlot>>
640 SerializerVisitor::CreateOutputSlots(const armnn::IConnectableLayer* layer)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000641{
642 std::vector<fb::Offset<serializer::OutputSlot>> outputSlots;
643
644 // Get the OutputSlots
645 for (unsigned int slotIndex = 0; slotIndex < layer->GetNumOutputSlots(); ++slotIndex)
646 {
647 const IOutputSlot& outputSlot = layer->GetOutputSlot(slotIndex);
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000648 const armnn::TensorInfo& tensorInfo = outputSlot.GetTensorInfo();
Mike Kelly8c1701a2019-02-11 17:01:27 +0000649
650 // Get the dimensions
651 std::vector<unsigned int> shape;
652 for(unsigned int dim = 0; dim < tensorInfo.GetShape().GetNumDimensions(); ++dim)
653 {
654 shape.push_back(tensorInfo.GetShape()[dim]);
655 }
656
657 // Create FlatBuffer TensorInfo
658 auto flatBufferTensorInfo = serializer::CreateTensorInfo(m_flatBufferBuilder,
659 m_flatBufferBuilder.CreateVector(shape),
660 GetFlatBufferDataType(tensorInfo.GetDataType()),
661 tensorInfo.GetQuantizationScale(),
662 tensorInfo.GetQuantizationOffset());
663
664 // Create FlatBuffer Outputslot
665 outputSlots.push_back(serializer::CreateOutputSlot(m_flatBufferBuilder,
666 slotIndex,
667 flatBufferTensorInfo));
668 }
669 return outputSlots;
670}
671
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000672
673ISerializer* ISerializer::CreateRaw()
674{
675 return new Serializer();
676}
677
678ISerializerPtr ISerializer::Create()
679{
680 return ISerializerPtr(CreateRaw(), &ISerializer::Destroy);
681}
682
683void ISerializer::Destroy(ISerializer* serializer)
684{
685 delete serializer;
686}
687
688void Serializer::Serialize(const INetwork& inNetwork)
689{
690 // Iterate through to network
691 inNetwork.Accept(m_SerializerVisitor);
692 flatbuffers::FlatBufferBuilder& fbBuilder = m_SerializerVisitor.GetFlatBufferBuilder();
693
694 // Create FlatBuffer SerializedGraph
695 auto serializedGraph = serializer::CreateSerializedGraph(
696 fbBuilder,
697 fbBuilder.CreateVector(m_SerializerVisitor.GetSerializedLayers()),
698 fbBuilder.CreateVector(m_SerializerVisitor.GetInputIds()),
699 fbBuilder.CreateVector(m_SerializerVisitor.GetOutputIds()));
700
701 // Serialize the graph
702 fbBuilder.Finish(serializedGraph);
703}
704
705bool Serializer::SaveSerializedToStream(std::ostream& stream)
706{
707 flatbuffers::FlatBufferBuilder& fbBuilder = m_SerializerVisitor.GetFlatBufferBuilder();
708
Nattapat Chaimanowong7b53b692019-02-12 14:38:31 +0000709 auto bytesToWrite = boost::numeric_cast<std::streamsize>(fbBuilder.GetSize());
710 stream.write(reinterpret_cast<const char*>(fbBuilder.GetBufferPointer()), bytesToWrite);
Nattapat Chaimanowongac9cadc2019-02-13 15:52:41 +0000711 return !stream.bad();
712}
713
Matteo Martincighec333912019-02-13 15:12:39 +0000714} // namespace armnnSerializer