ArmNN
 20.11
SerializerTests.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "../Serializer.hpp"
7 
8 #include <armnn/Descriptors.hpp>
9 #include <armnn/INetwork.hpp>
10 #include <armnn/TypesUtils.hpp>
11 #include <armnn/LstmParams.hpp>
14 
15 #include <random>
16 #include <vector>
17 
18 #include <boost/test/unit_test.hpp>
19 
21 
22 namespace
23 {
24 
25 #define DECLARE_LAYER_VERIFIER_CLASS(name) \
26 class name##LayerVerifier : public LayerVerifierBase \
27 { \
28 public: \
29  name##LayerVerifier(const std::string& layerName, \
30  const std::vector<armnn::TensorInfo>& inputInfos, \
31  const std::vector<armnn::TensorInfo>& outputInfos) \
32  : LayerVerifierBase(layerName, inputInfos, outputInfos) {} \
33 \
34  void Visit##name##Layer(const armnn::IConnectableLayer* layer, const char* name) override \
35  { \
36  VerifyNameAndConnections(layer, name); \
37  } \
38 };
39 
40 #define DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(name) \
41 class name##LayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::name##Descriptor> \
42 { \
43 public: \
44  name##LayerVerifier(const std::string& layerName, \
45  const std::vector<armnn::TensorInfo>& inputInfos, \
46  const std::vector<armnn::TensorInfo>& outputInfos, \
47  const armnn::name##Descriptor& descriptor) \
48  : LayerVerifierBaseWithDescriptor<armnn::name##Descriptor>( \
49  layerName, inputInfos, outputInfos, descriptor) {} \
50 \
51  void Visit##name##Layer(const armnn::IConnectableLayer* layer, \
52  const armnn::name##Descriptor& descriptor, \
53  const char* name) override \
54  { \
55  VerifyNameAndConnections(layer, name); \
56  VerifyDescriptor(descriptor); \
57  } \
58 };
59 
60 struct DefaultLayerVerifierPolicy
61 {
62  static void Apply(const std::string)
63  {
64  BOOST_TEST_MESSAGE("Unexpected layer found in network");
65  BOOST_TEST(false);
66  }
67 };
68 
69 class LayerVerifierBase : public armnn::LayerVisitorBase<DefaultLayerVerifierPolicy>
70 {
71 public:
72  LayerVerifierBase(const std::string& layerName,
73  const std::vector<armnn::TensorInfo>& inputInfos,
74  const std::vector<armnn::TensorInfo>& outputInfos)
75  : m_LayerName(layerName)
76  , m_InputTensorInfos(inputInfos)
77  , m_OutputTensorInfos(outputInfos) {}
78 
79  void VisitInputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId, const char*) override {}
80 
81  void VisitOutputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId, const char*) override {}
82 
83 protected:
84  void VerifyNameAndConnections(const armnn::IConnectableLayer* layer, const char* name)
85  {
86  BOOST_TEST(name == m_LayerName.c_str());
87 
88  BOOST_TEST(layer->GetNumInputSlots() == m_InputTensorInfos.size());
89  BOOST_TEST(layer->GetNumOutputSlots() == m_OutputTensorInfos.size());
90 
91  for (unsigned int i = 0; i < m_InputTensorInfos.size(); i++)
92  {
93  const armnn::IOutputSlot* connectedOutput = layer->GetInputSlot(i).GetConnection();
94  BOOST_CHECK(connectedOutput);
95 
96  const armnn::TensorInfo& connectedInfo = connectedOutput->GetTensorInfo();
97  BOOST_TEST(connectedInfo.GetShape() == m_InputTensorInfos[i].GetShape());
98  BOOST_TEST(
99  GetDataTypeName(connectedInfo.GetDataType()) == GetDataTypeName(m_InputTensorInfos[i].GetDataType()));
100 
101  BOOST_TEST(connectedInfo.GetQuantizationScale() == m_InputTensorInfos[i].GetQuantizationScale());
102  BOOST_TEST(connectedInfo.GetQuantizationOffset() == m_InputTensorInfos[i].GetQuantizationOffset());
103  }
104 
105  for (unsigned int i = 0; i < m_OutputTensorInfos.size(); i++)
106  {
107  const armnn::TensorInfo& outputInfo = layer->GetOutputSlot(i).GetTensorInfo();
108  BOOST_TEST(outputInfo.GetShape() == m_OutputTensorInfos[i].GetShape());
109  BOOST_TEST(
110  GetDataTypeName(outputInfo.GetDataType()) == GetDataTypeName(m_OutputTensorInfos[i].GetDataType()));
111 
112  BOOST_TEST(outputInfo.GetQuantizationScale() == m_OutputTensorInfos[i].GetQuantizationScale());
113  BOOST_TEST(outputInfo.GetQuantizationOffset() == m_OutputTensorInfos[i].GetQuantizationOffset());
114  }
115  }
116 
117  void VerifyConstTensors(const std::string& tensorName,
118  const armnn::ConstTensor* expectedPtr,
119  const armnn::ConstTensor* actualPtr)
120  {
121  if (expectedPtr == nullptr)
122  {
123  BOOST_CHECK_MESSAGE(actualPtr == nullptr, tensorName + " should not exist");
124  }
125  else
126  {
127  BOOST_CHECK_MESSAGE(actualPtr != nullptr, tensorName + " should have been set");
128  if (actualPtr != nullptr)
129  {
130  const armnn::TensorInfo& expectedInfo = expectedPtr->GetInfo();
131  const armnn::TensorInfo& actualInfo = actualPtr->GetInfo();
132 
133  BOOST_CHECK_MESSAGE(expectedInfo.GetShape() == actualInfo.GetShape(),
134  tensorName + " shapes don't match");
135  BOOST_CHECK_MESSAGE(
136  GetDataTypeName(expectedInfo.GetDataType()) == GetDataTypeName(actualInfo.GetDataType()),
137  tensorName + " data types don't match");
138 
139  BOOST_CHECK_MESSAGE(expectedPtr->GetNumBytes() == actualPtr->GetNumBytes(),
140  tensorName + " (GetNumBytes) data sizes do not match");
141  if (expectedPtr->GetNumBytes() == actualPtr->GetNumBytes())
142  {
143  //check the data is identical
144  const char* expectedData = static_cast<const char*>(expectedPtr->GetMemoryArea());
145  const char* actualData = static_cast<const char*>(actualPtr->GetMemoryArea());
146  bool same = true;
147  for (unsigned int i = 0; i < expectedPtr->GetNumBytes(); ++i)
148  {
149  same = expectedData[i] == actualData[i];
150  if (!same)
151  {
152  break;
153  }
154  }
155  BOOST_CHECK_MESSAGE(same, tensorName + " data does not match");
156  }
157  }
158  }
159  }
160 
161 private:
162  std::string m_LayerName;
163  std::vector<armnn::TensorInfo> m_InputTensorInfos;
164  std::vector<armnn::TensorInfo> m_OutputTensorInfos;
165 };
166 
167 template<typename Descriptor>
168 class LayerVerifierBaseWithDescriptor : public LayerVerifierBase
169 {
170 public:
171  LayerVerifierBaseWithDescriptor(const std::string& layerName,
172  const std::vector<armnn::TensorInfo>& inputInfos,
173  const std::vector<armnn::TensorInfo>& outputInfos,
174  const Descriptor& descriptor)
175  : LayerVerifierBase(layerName, inputInfos, outputInfos)
176  , m_Descriptor(descriptor) {}
177 
178 protected:
179  void VerifyDescriptor(const Descriptor& descriptor)
180  {
181  BOOST_CHECK(descriptor == m_Descriptor);
182  }
183 
184  Descriptor m_Descriptor;
185 };
186 
187 template<typename T>
188 void CompareConstTensorData(const void* data1, const void* data2, unsigned int numElements)
189 {
190  T typedData1 = static_cast<T>(data1);
191  T typedData2 = static_cast<T>(data2);
192  BOOST_CHECK(typedData1);
193  BOOST_CHECK(typedData2);
194 
195  for (unsigned int i = 0; i < numElements; i++)
196  {
197  BOOST_TEST(typedData1[i] == typedData2[i]);
198  }
199 }
200 
201 void CompareConstTensor(const armnn::ConstTensor& tensor1, const armnn::ConstTensor& tensor2)
202 {
203  BOOST_TEST(tensor1.GetShape() == tensor2.GetShape());
204  BOOST_TEST(GetDataTypeName(tensor1.GetDataType()) == GetDataTypeName(tensor2.GetDataType()));
205 
206  switch (tensor1.GetDataType())
207  {
209  CompareConstTensorData<const float*>(
210  tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
211  break;
214  CompareConstTensorData<const uint8_t*>(
215  tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
216  break;
218  CompareConstTensorData<const int8_t*>(
219  tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
220  break;
222  CompareConstTensorData<const int32_t*>(
223  tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
224  break;
225  default:
226  // Note that Float16 is not yet implemented
227  BOOST_TEST_MESSAGE("Unexpected datatype");
228  BOOST_TEST(false);
229  }
230 }
231 
232 armnn::INetworkPtr DeserializeNetwork(const std::string& serializerString)
233 {
234  std::vector<std::uint8_t> const serializerVector{serializerString.begin(), serializerString.end()};
235  return IDeserializer::Create()->CreateNetworkFromBinary(serializerVector);
236 }
237 
238 std::string SerializeNetwork(const armnn::INetwork& network)
239 {
241  serializer.Serialize(network);
242 
243  std::stringstream stream;
244  serializer.SaveSerializedToStream(stream);
245 
246  std::string serializerString{stream.str()};
247  return serializerString;
248 }
249 
250 template<typename DataType>
251 static std::vector<DataType> GenerateRandomData(size_t size)
252 {
253  constexpr bool isIntegerType = std::is_integral<DataType>::value;
254  using Distribution =
255  typename std::conditional<isIntegerType,
256  std::uniform_int_distribution<DataType>,
257  std::uniform_real_distribution<DataType>>::type;
258 
259  static constexpr DataType lowerLimit = std::numeric_limits<DataType>::min();
260  static constexpr DataType upperLimit = std::numeric_limits<DataType>::max();
261 
262  static Distribution distribution(lowerLimit, upperLimit);
263  static std::default_random_engine generator;
264 
265  std::vector<DataType> randomData(size);
266  std::generate(randomData.begin(), randomData.end(), []() { return distribution(generator); });
267 
268  return randomData;
269 }
270 
271 } // anonymous namespace
272 
273 BOOST_AUTO_TEST_SUITE(SerializerTests)
274 
275 BOOST_AUTO_TEST_CASE(SerializeAddition)
276 {
278 
279  const std::string layerName("addition");
280  const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
281 
283  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
284  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
285  armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer(layerName.c_str());
286  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
287 
288  inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
289  inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1));
290  additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
291 
292  inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
293  inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
294  additionLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
295 
296  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
297  BOOST_CHECK(deserializedNetwork);
298 
299  AdditionLayerVerifier verifier(layerName, {tensorInfo, tensorInfo}, {tensorInfo});
300  deserializedNetwork->Accept(verifier);
301 }
302 
303 BOOST_AUTO_TEST_CASE(SerializeArgMinMax)
304 {
306 
307  const std::string layerName("argminmax");
308  const armnn::TensorInfo inputInfo({1, 2, 3}, armnn::DataType::Float32);
309  const armnn::TensorInfo outputInfo({1, 3}, armnn::DataType::Signed32);
310 
311  armnn::ArgMinMaxDescriptor descriptor;
313  descriptor.m_Axis = 1;
314 
316  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
317  armnn::IConnectableLayer* const argMinMaxLayer = network->AddArgMinMaxLayer(descriptor, layerName.c_str());
318  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
319 
320  inputLayer->GetOutputSlot(0).Connect(argMinMaxLayer->GetInputSlot(0));
321  argMinMaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
322 
323  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
324  argMinMaxLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
325 
326  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
327  BOOST_CHECK(deserializedNetwork);
328 
329  ArgMinMaxLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
330  deserializedNetwork->Accept(verifier);
331 }
332 
333 BOOST_AUTO_TEST_CASE(SerializeBatchNormalization)
334 {
335  using Descriptor = armnn::BatchNormalizationDescriptor;
336  class BatchNormalizationLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
337  {
338  public:
339  BatchNormalizationLayerVerifier(const std::string& layerName,
340  const std::vector<armnn::TensorInfo>& inputInfos,
341  const std::vector<armnn::TensorInfo>& outputInfos,
342  const Descriptor& descriptor,
343  const armnn::ConstTensor& mean,
344  const armnn::ConstTensor& variance,
345  const armnn::ConstTensor& beta,
346  const armnn::ConstTensor& gamma)
347  : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
348  , m_Mean(mean)
349  , m_Variance(variance)
350  , m_Beta(beta)
351  , m_Gamma(gamma) {}
352 
353  void VisitBatchNormalizationLayer(const armnn::IConnectableLayer* layer,
354  const Descriptor& descriptor,
355  const armnn::ConstTensor& mean,
356  const armnn::ConstTensor& variance,
357  const armnn::ConstTensor& beta,
358  const armnn::ConstTensor& gamma,
359  const char* name) override
360  {
361  VerifyNameAndConnections(layer, name);
362  VerifyDescriptor(descriptor);
363 
364  CompareConstTensor(mean, m_Mean);
365  CompareConstTensor(variance, m_Variance);
366  CompareConstTensor(beta, m_Beta);
367  CompareConstTensor(gamma, m_Gamma);
368  }
369 
370  private:
371  armnn::ConstTensor m_Mean;
372  armnn::ConstTensor m_Variance;
373  armnn::ConstTensor m_Beta;
374  armnn::ConstTensor m_Gamma;
375  };
376 
377  const std::string layerName("batchNormalization");
378  const armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32);
379  const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
380 
381  const armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32);
382  const armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32);
383  const armnn::TensorInfo betaInfo({1}, armnn::DataType::Float32);
384  const armnn::TensorInfo gammaInfo({1}, armnn::DataType::Float32);
385 
387  descriptor.m_Eps = 0.0010000000475f;
388  descriptor.m_DataLayout = armnn::DataLayout::NHWC;
389 
390  std::vector<float> meanData({5.0});
391  std::vector<float> varianceData({2.0});
392  std::vector<float> betaData({1.0});
393  std::vector<float> gammaData({0.0});
394 
395  armnn::ConstTensor mean(meanInfo, meanData);
396  armnn::ConstTensor variance(varianceInfo, varianceData);
397  armnn::ConstTensor beta(betaInfo, betaData);
398  armnn::ConstTensor gamma(gammaInfo, gammaData);
399 
401  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
402  armnn::IConnectableLayer* const batchNormalizationLayer =
403  network->AddBatchNormalizationLayer(descriptor, mean, variance, beta, gamma, layerName.c_str());
404  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
405 
406  inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0));
407  batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
408 
409  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
410  batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
411 
412  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
413  BOOST_CHECK(deserializedNetwork);
414 
415  BatchNormalizationLayerVerifier verifier(
416  layerName, {inputInfo}, {outputInfo}, descriptor, mean, variance, beta, gamma);
417  deserializedNetwork->Accept(verifier);
418 }
419 
420 BOOST_AUTO_TEST_CASE(SerializeBatchToSpaceNd)
421 {
423 
424  const std::string layerName("spaceToBatchNd");
425  const armnn::TensorInfo inputInfo({4, 1, 2, 2}, armnn::DataType::Float32);
426  const armnn::TensorInfo outputInfo({1, 1, 4, 4}, armnn::DataType::Float32);
427 
430  desc.m_BlockShape = {2, 2};
431  desc.m_Crops = {{0, 0}, {0, 0}};
432 
434  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
435  armnn::IConnectableLayer* const batchToSpaceNdLayer = network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
436  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
437 
438  inputLayer->GetOutputSlot(0).Connect(batchToSpaceNdLayer->GetInputSlot(0));
439  batchToSpaceNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
440 
441  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
442  batchToSpaceNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
443 
444  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
445  BOOST_CHECK(deserializedNetwork);
446 
447  BatchToSpaceNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
448  deserializedNetwork->Accept(verifier);
449 }
450 
451 BOOST_AUTO_TEST_CASE(SerializeComparison)
452 {
454 
455  const std::string layerName("comparison");
456 
457  const armnn::TensorShape shape{2, 1, 2, 4};
458 
461 
463 
465  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
466  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
467  armnn::IConnectableLayer* const comparisonLayer = network->AddComparisonLayer(descriptor, layerName.c_str());
468  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
469 
470  inputLayer0->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(0));
471  inputLayer1->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(1));
472  comparisonLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
473 
474  inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
475  inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
476  comparisonLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
477 
478  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
479  BOOST_CHECK(deserializedNetwork);
480 
481  ComparisonLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo }, descriptor);
482  deserializedNetwork->Accept(verifier);
483 }
484 
485 BOOST_AUTO_TEST_CASE(SerializeConstant)
486 {
487  class ConstantLayerVerifier : public LayerVerifierBase
488  {
489  public:
490  ConstantLayerVerifier(const std::string& layerName,
491  const std::vector<armnn::TensorInfo>& inputInfos,
492  const std::vector<armnn::TensorInfo>& outputInfos,
493  const armnn::ConstTensor& layerInput)
494  : LayerVerifierBase(layerName, inputInfos, outputInfos)
495  , m_LayerInput(layerInput) {}
496 
497  void VisitConstantLayer(const armnn::IConnectableLayer* layer,
498  const armnn::ConstTensor& input,
499  const char* name) override
500  {
501  VerifyNameAndConnections(layer, name);
502  CompareConstTensor(input, m_LayerInput);
503  }
504 
505  void VisitAdditionLayer(const armnn::IConnectableLayer*, const char*) override {}
506 
507  private:
508  armnn::ConstTensor m_LayerInput;
509  };
510 
511  const std::string layerName("constant");
512  const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
513 
514  std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
515  armnn::ConstTensor constTensor(info, constantData);
516 
518  armnn::IConnectableLayer* input = network->AddInputLayer(0);
519  armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
520  armnn::IConnectableLayer* add = network->AddAdditionLayer();
521  armnn::IConnectableLayer* output = network->AddOutputLayer(0);
522 
523  input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
524  constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
525  add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
526 
527  input->GetOutputSlot(0).SetTensorInfo(info);
528  constant->GetOutputSlot(0).SetTensorInfo(info);
529  add->GetOutputSlot(0).SetTensorInfo(info);
530 
531  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
532  BOOST_CHECK(deserializedNetwork);
533 
534  ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
535  deserializedNetwork->Accept(verifier);
536 }
537 
538 BOOST_AUTO_TEST_CASE(SerializeConvolution2d)
539 {
540  using Descriptor = armnn::Convolution2dDescriptor;
541  class Convolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
542  {
543  public:
544  Convolution2dLayerVerifier(const std::string& layerName,
545  const std::vector<armnn::TensorInfo>& inputInfos,
546  const std::vector<armnn::TensorInfo>& outputInfos,
547  const Descriptor& descriptor,
548  const armnn::ConstTensor& weights,
550  : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
551  , m_Weights(weights)
552  , m_Biases(biases) {}
553 
554  void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
555  const Descriptor& descriptor,
556  const armnn::ConstTensor& weights,
558  const char* name) override
559  {
560  VerifyNameAndConnections(layer, name);
561  VerifyDescriptor(descriptor);
562 
563  // check weights
564  CompareConstTensor(weights, m_Weights);
565 
566  // check biases
567  BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
568  BOOST_CHECK(biases.has_value() == m_Biases.has_value());
569 
570  if (biases.has_value() && m_Biases.has_value())
571  {
572  CompareConstTensor(biases.value(), m_Biases.value());
573  }
574  }
575 
576  private:
577  armnn::ConstTensor m_Weights;
579  };
580 
581  const std::string layerName("convolution2d");
582  const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
583  const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
584 
585  const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
586  const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
587 
588  std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
589  armnn::ConstTensor weights(weightsInfo, weightsData);
590 
591  std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
592  armnn::ConstTensor biases(biasesInfo, biasesData);
593 
595  descriptor.m_PadLeft = 1;
596  descriptor.m_PadRight = 1;
597  descriptor.m_PadTop = 1;
598  descriptor.m_PadBottom = 1;
599  descriptor.m_StrideX = 2;
600  descriptor.m_StrideY = 2;
601  descriptor.m_DilationX = 2;
602  descriptor.m_DilationY = 2;
603  descriptor.m_BiasEnabled = true;
605 
607  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
608  armnn::IConnectableLayer* const convLayer =
609  network->AddConvolution2dLayer(descriptor,
610  weights,
612  layerName.c_str());
613  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
614 
615  inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
616  convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
617 
618  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
619  convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
620 
621  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
622  BOOST_CHECK(deserializedNetwork);
623 
624  Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
625  deserializedNetwork->Accept(verifier);
626 }
627 
628 BOOST_AUTO_TEST_CASE(SerializeConvolution2dWithPerAxisParams)
629 {
630  using Descriptor = armnn::Convolution2dDescriptor;
631  class Convolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
632  {
633  public:
634  Convolution2dLayerVerifier(const std::string& layerName,
635  const std::vector<armnn::TensorInfo>& inputInfos,
636  const std::vector<armnn::TensorInfo>& outputInfos,
637  const Descriptor& descriptor,
638  const armnn::ConstTensor& weights,
640  : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
641  , m_Weights(weights)
642  , m_Biases(biases) {}
643 
644  void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
645  const Descriptor& descriptor,
646  const armnn::ConstTensor& weights,
648  const char* name) override
649  {
650  VerifyNameAndConnections(layer, name);
651  VerifyDescriptor(descriptor);
652 
653  // check weights
654  CompareConstTensor(weights, m_Weights);
655 
656  // check biases
657  BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
658  BOOST_CHECK(biases.has_value() == m_Biases.has_value());
659 
660  if (biases.has_value() && m_Biases.has_value())
661  {
662  CompareConstTensor(biases.value(), m_Biases.value());
663  }
664  }
665 
666  private:
667  armnn::ConstTensor m_Weights;
669  };
670 
671  using namespace armnn;
672 
673  const std::string layerName("convolution2dWithPerAxis");
674  const TensorInfo inputInfo ({ 1, 3, 1, 2 }, DataType::QAsymmU8, 0.55f, 128);
675  const TensorInfo outputInfo({ 1, 3, 1, 3 }, DataType::QAsymmU8, 0.75f, 128);
676 
677  const std::vector<float> quantScales{ 0.75f, 0.65f, 0.85f };
678  constexpr unsigned int quantDimension = 0;
679 
680  const TensorInfo kernelInfo({ 3, 1, 1, 2 }, DataType::QSymmS8, quantScales, quantDimension);
681 
682  const std::vector<float> biasQuantScales{ 0.25f, 0.50f, 0.75f };
683  const TensorInfo biasInfo({ 3 }, DataType::Signed32, biasQuantScales, quantDimension);
684 
685  std::vector<int8_t> kernelData = GenerateRandomData<int8_t>(kernelInfo.GetNumElements());
686  armnn::ConstTensor weights(kernelInfo, kernelData);
687  std::vector<int32_t> biasData = GenerateRandomData<int32_t>(biasInfo.GetNumElements());
688  armnn::ConstTensor biases(biasInfo, biasData);
689 
690  Convolution2dDescriptor descriptor;
691  descriptor.m_StrideX = 1;
692  descriptor.m_StrideY = 1;
693  descriptor.m_PadLeft = 0;
694  descriptor.m_PadRight = 0;
695  descriptor.m_PadTop = 0;
696  descriptor.m_PadBottom = 0;
697  descriptor.m_BiasEnabled = true;
699 
701  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
702  armnn::IConnectableLayer* const convLayer =
703  network->AddConvolution2dLayer(descriptor,
704  weights,
706  layerName.c_str());
707  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
708 
709  inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
710  convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
711 
712  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
713  convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
714 
715  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
716  BOOST_CHECK(deserializedNetwork);
717 
718  Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
719  deserializedNetwork->Accept(verifier);
720 }
721 
722 BOOST_AUTO_TEST_CASE(SerializeDepthToSpace)
723 {
725 
726  const std::string layerName("depthToSpace");
727 
728  const armnn::TensorInfo inputInfo ({ 1, 8, 4, 12 }, armnn::DataType::Float32);
729  const armnn::TensorInfo outputInfo({ 1, 16, 8, 3 }, armnn::DataType::Float32);
730 
732  desc.m_BlockSize = 2;
733  desc.m_DataLayout = armnn::DataLayout::NHWC;
734 
736  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
737  armnn::IConnectableLayer* const depthToSpaceLayer = network->AddDepthToSpaceLayer(desc, layerName.c_str());
738  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
739 
740  inputLayer->GetOutputSlot(0).Connect(depthToSpaceLayer->GetInputSlot(0));
741  depthToSpaceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
742 
743  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
744  depthToSpaceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
745 
746  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
747  BOOST_CHECK(deserializedNetwork);
748 
749  DepthToSpaceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
750  deserializedNetwork->Accept(verifier);
751 }
752 
753 BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d)
754 {
755  using Descriptor = armnn::DepthwiseConvolution2dDescriptor;
756  class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
757  {
758  public:
759  DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
760  const std::vector<armnn::TensorInfo>& inputInfos,
761  const std::vector<armnn::TensorInfo>& outputInfos,
762  const Descriptor& descriptor,
763  const armnn::ConstTensor& weights,
764  const armnn::Optional<armnn::ConstTensor>& biases) :
765  LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor),
766  m_Weights(weights),
767  m_Biases(biases) {}
768 
769  void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
770  const Descriptor& descriptor,
771  const armnn::ConstTensor& weights,
773  const char* name) override
774  {
775  VerifyNameAndConnections(layer, name);
776  VerifyDescriptor(descriptor);
777 
778  // check weights
779  CompareConstTensor(weights, m_Weights);
780 
781  // check biases
782  BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
783  BOOST_CHECK(biases.has_value() == m_Biases.has_value());
784 
785  if (biases.has_value() && m_Biases.has_value())
786  {
787  CompareConstTensor(biases.value(), m_Biases.value());
788  }
789  }
790 
791  private:
792  armnn::ConstTensor m_Weights;
794  };
795 
796  const std::string layerName("depwiseConvolution2d");
797  const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
798  const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
799 
800  const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
801  const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
802 
803  std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
804  armnn::ConstTensor weights(weightsInfo, weightsData);
805 
806  std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
807  armnn::ConstTensor biases(biasesInfo, biasesData);
808 
810  descriptor.m_PadLeft = 1;
811  descriptor.m_PadRight = 1;
812  descriptor.m_PadTop = 1;
813  descriptor.m_PadBottom = 1;
814  descriptor.m_StrideX = 2;
815  descriptor.m_StrideY = 2;
816  descriptor.m_DilationX = 2;
817  descriptor.m_DilationY = 2;
818  descriptor.m_BiasEnabled = true;
820 
822  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
823  armnn::IConnectableLayer* const depthwiseConvLayer =
824  network->AddDepthwiseConvolution2dLayer(descriptor,
825  weights,
827  layerName.c_str());
828  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
829 
830  inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
831  depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
832 
833  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
834  depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
835 
836  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
837  BOOST_CHECK(deserializedNetwork);
838 
839  DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
840  deserializedNetwork->Accept(verifier);
841 }
842 
843 BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2dWithPerAxisParams)
844 {
845  using Descriptor = armnn::DepthwiseConvolution2dDescriptor;
846  class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
847  {
848  public:
849  DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
850  const std::vector<armnn::TensorInfo>& inputInfos,
851  const std::vector<armnn::TensorInfo>& outputInfos,
852  const Descriptor& descriptor,
853  const armnn::ConstTensor& weights,
854  const armnn::Optional<armnn::ConstTensor>& biases) :
855  LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor),
856  m_Weights(weights),
857  m_Biases(biases) {}
858 
859  void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
860  const Descriptor& descriptor,
861  const armnn::ConstTensor& weights,
863  const char* name) override
864  {
865  VerifyNameAndConnections(layer, name);
866  VerifyDescriptor(descriptor);
867 
868  // check weights
869  CompareConstTensor(weights, m_Weights);
870 
871  // check biases
872  BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
873  BOOST_CHECK(biases.has_value() == m_Biases.has_value());
874 
875  if (biases.has_value() && m_Biases.has_value())
876  {
877  CompareConstTensor(biases.value(), m_Biases.value());
878  }
879  }
880 
881  private:
882  armnn::ConstTensor m_Weights;
884  };
885 
886  using namespace armnn;
887 
888  const std::string layerName("depwiseConvolution2dWithPerAxis");
889  const TensorInfo inputInfo ({ 1, 3, 3, 2 }, DataType::QAsymmU8, 0.55f, 128);
890  const TensorInfo outputInfo({ 1, 2, 2, 4 }, DataType::QAsymmU8, 0.75f, 128);
891 
892  const std::vector<float> quantScales{ 0.75f, 0.80f, 0.90f, 0.95f };
893  const unsigned int quantDimension = 0;
894  TensorInfo kernelInfo({ 2, 2, 2, 2 }, DataType::QSymmS8, quantScales, quantDimension);
895 
896  const std::vector<float> biasQuantScales{ 0.25f, 0.35f, 0.45f, 0.55f };
897  constexpr unsigned int biasQuantDimension = 0;
898  TensorInfo biasInfo({ 4 }, DataType::Signed32, biasQuantScales, biasQuantDimension);
899 
900  std::vector<int8_t> kernelData = GenerateRandomData<int8_t>(kernelInfo.GetNumElements());
901  armnn::ConstTensor weights(kernelInfo, kernelData);
902  std::vector<int32_t> biasData = GenerateRandomData<int32_t>(biasInfo.GetNumElements());
903  armnn::ConstTensor biases(biasInfo, biasData);
904 
906  descriptor.m_StrideX = 1;
907  descriptor.m_StrideY = 1;
908  descriptor.m_PadLeft = 0;
909  descriptor.m_PadRight = 0;
910  descriptor.m_PadTop = 0;
911  descriptor.m_PadBottom = 0;
912  descriptor.m_DilationX = 1;
913  descriptor.m_DilationY = 1;
914  descriptor.m_BiasEnabled = true;
916 
918  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
919  armnn::IConnectableLayer* const depthwiseConvLayer =
920  network->AddDepthwiseConvolution2dLayer(descriptor,
921  weights,
923  layerName.c_str());
924  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
925 
926  inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
927  depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
928 
929  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
930  depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
931 
932  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
933  BOOST_CHECK(deserializedNetwork);
934 
935  DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
936  deserializedNetwork->Accept(verifier);
937 }
938 
939 BOOST_AUTO_TEST_CASE(SerializeDequantize)
940 {
942 
943  const std::string layerName("dequantize");
944  const armnn::TensorInfo inputInfo({ 1, 5, 2, 3 }, armnn::DataType::QAsymmU8, 0.5f, 1);
945  const armnn::TensorInfo outputInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
946 
948  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
949  armnn::IConnectableLayer* const dequantizeLayer = network->AddDequantizeLayer(layerName.c_str());
950  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
951 
952  inputLayer->GetOutputSlot(0).Connect(dequantizeLayer->GetInputSlot(0));
953  dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
954 
955  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
956  dequantizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
957 
958  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
959  BOOST_CHECK(deserializedNetwork);
960 
961  DequantizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
962  deserializedNetwork->Accept(verifier);
963 }
964 
965 BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess)
966 {
967  using Descriptor = armnn::DetectionPostProcessDescriptor;
968  class DetectionPostProcessLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
969  {
970  public:
971  DetectionPostProcessLayerVerifier(const std::string& layerName,
972  const std::vector<armnn::TensorInfo>& inputInfos,
973  const std::vector<armnn::TensorInfo>& outputInfos,
974  const Descriptor& descriptor,
976  : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
977  , m_Anchors(anchors) {}
978 
979  void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
980  const Descriptor& descriptor,
981  const armnn::ConstTensor& anchors,
982  const char* name) override
983  {
984  VerifyNameAndConnections(layer, name);
985  VerifyDescriptor(descriptor);
986 
987  CompareConstTensor(anchors, m_Anchors);
988  }
989 
990  private:
991  armnn::ConstTensor m_Anchors;
992  };
993 
994  const std::string layerName("detectionPostProcess");
995 
996  const std::vector<armnn::TensorInfo> inputInfos({
999  });
1000 
1001  const std::vector<armnn::TensorInfo> outputInfos({
1006  });
1007 
1009  descriptor.m_UseRegularNms = true;
1010  descriptor.m_MaxDetections = 3;
1011  descriptor.m_MaxClassesPerDetection = 1;
1012  descriptor.m_DetectionsPerClass =1;
1013  descriptor.m_NmsScoreThreshold = 0.0;
1014  descriptor.m_NmsIouThreshold = 0.5;
1015  descriptor.m_NumClasses = 2;
1016  descriptor.m_ScaleY = 10.0;
1017  descriptor.m_ScaleX = 10.0;
1018  descriptor.m_ScaleH = 5.0;
1019  descriptor.m_ScaleW = 5.0;
1020 
1022  const std::vector<float> anchorsData({
1023  0.5f, 0.5f, 1.0f, 1.0f,
1024  0.5f, 0.5f, 1.0f, 1.0f,
1025  0.5f, 0.5f, 1.0f, 1.0f,
1026  0.5f, 10.5f, 1.0f, 1.0f,
1027  0.5f, 10.5f, 1.0f, 1.0f,
1028  0.5f, 100.5f, 1.0f, 1.0f
1029  });
1030  armnn::ConstTensor anchors(anchorsInfo, anchorsData);
1031 
1033  armnn::IConnectableLayer* const detectionLayer =
1034  network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
1035 
1036  for (unsigned int i = 0; i < 2; i++)
1037  {
1038  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
1039  inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
1040  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
1041  }
1042 
1043  for (unsigned int i = 0; i < 4; i++)
1044  {
1045  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
1046  detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
1047  detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
1048  }
1049 
1050  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1051  BOOST_CHECK(deserializedNetwork);
1052 
1053  DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors);
1054  deserializedNetwork->Accept(verifier);
1055 }
1056 
1057 BOOST_AUTO_TEST_CASE(SerializeDivision)
1058 {
1060 
1061  const std::string layerName("division");
1062  const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1063 
1065  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1066  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1067  armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
1068  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1069 
1070  inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
1071  inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
1072  divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1073 
1074  inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1075  inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1076  divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
1077 
1078  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1079  BOOST_CHECK(deserializedNetwork);
1080 
1081  DivisionLayerVerifier verifier(layerName, {info, info}, {info});
1082  deserializedNetwork->Accept(verifier);
1083 }
1084 
1085 class EqualLayerVerifier : public LayerVerifierBase
1086 {
1087 public:
1088  EqualLayerVerifier(const std::string& layerName,
1089  const std::vector<armnn::TensorInfo>& inputInfos,
1090  const std::vector<armnn::TensorInfo>& outputInfos)
1091  : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1092 
1093  void VisitComparisonLayer(const armnn::IConnectableLayer* layer,
1094  const armnn::ComparisonDescriptor& descriptor,
1095  const char* name) override
1096  {
1097  VerifyNameAndConnections(layer, name);
1098  BOOST_CHECK(descriptor.m_Operation == armnn::ComparisonOperation::Equal);
1099  }
1100 
1101  void VisitEqualLayer(const armnn::IConnectableLayer*, const char*) override
1102  {
1103  throw armnn::Exception("EqualLayer should have translated to ComparisonLayer");
1104  }
1105 };
1106 
1107 // NOTE: Until the deprecated AddEqualLayer disappears this test checks that calling
1108 // AddEqualLayer places a ComparisonLayer into the serialized format and that
1109 // when this deserialises we have a ComparisonLayer
1110 BOOST_AUTO_TEST_CASE(SerializeEqual)
1111 {
1112  const std::string layerName("equal");
1113 
1114  const armnn::TensorShape shape{2, 1, 2, 4};
1115 
1118 
1120  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1121  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1123  armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str());
1125  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1126 
1127  inputLayer0->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
1128  inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
1129  equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1130 
1131  inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
1132  inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
1133  equalLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1134 
1135  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1136  BOOST_CHECK(deserializedNetwork);
1137 
1138  EqualLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo });
1139  deserializedNetwork->Accept(verifier);
1140 }
1141 
1142 BOOST_AUTO_TEST_CASE(EnsureEqualBackwardCompatibility)
1143 {
1144  // The hex data below is a flat buffer containing a simple network with two inputs,
1145  // an EqualLayer (now deprecated) and an output
1146  //
1147  // This test verifies that we can still deserialize this old-style model by replacing
1148  // the EqualLayer with an equivalent ComparisonLayer
1149  const std::vector<uint8_t> equalModel =
1150  {
1151  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1152  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1153  0xCC, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1154  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1155  0x60, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1156  0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xEA, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1157  0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1158  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159  0x64, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1160  0x00, 0x13, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1161  0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1162  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x65, 0x71, 0x75, 0x61, 0x6C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1163  0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1164  0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00,
1165  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
1166  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1167  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1168  0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1169  0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1170  0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1171  0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1172  0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1173  0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1174  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1175  0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1176  0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
1178  0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1179  0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1180  0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1181  0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1182  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1183  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1184  0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1185  0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1186  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1187  0x04, 0x00, 0x00, 0x00
1188  };
1189 
1190  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(equalModel.begin(), equalModel.end()));
1191  BOOST_CHECK(deserializedNetwork);
1192 
1193  const armnn::TensorShape shape{ 2, 1, 2, 4 };
1194 
1197 
1198  EqualLayerVerifier verifier("equal", { inputInfo, inputInfo }, { outputInfo });
1199  deserializedNetwork->Accept(verifier);
1200 }
1201 
1202 BOOST_AUTO_TEST_CASE(SerializeFill)
1203 {
1205 
1206  const std::string layerName("fill");
1207  const armnn::TensorInfo inputInfo({4}, armnn::DataType::Signed32);
1208  const armnn::TensorInfo outputInfo({1, 3, 3, 1}, armnn::DataType::Float32);
1209 
1210  armnn::FillDescriptor descriptor(1.0f);
1211 
1213  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1214  armnn::IConnectableLayer* const fillLayer = network->AddFillLayer(descriptor, layerName.c_str());
1215  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1216 
1217  inputLayer->GetOutputSlot(0).Connect(fillLayer->GetInputSlot(0));
1218  fillLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1219 
1220  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1221  fillLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1222 
1223  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1224  BOOST_CHECK(deserializedNetwork);
1225 
1226  FillLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1227 
1228  deserializedNetwork->Accept(verifier);
1229 }
1230 
1231 BOOST_AUTO_TEST_CASE(SerializeFloor)
1232 {
1234 
1235  const std::string layerName("floor");
1237 
1239  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1240  armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
1241  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1242 
1243  inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
1244  floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1245 
1246  inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1247  floorLayer->GetOutputSlot(0).SetTensorInfo(info);
1248 
1249  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1250  BOOST_CHECK(deserializedNetwork);
1251 
1252  FloorLayerVerifier verifier(layerName, {info}, {info});
1253  deserializedNetwork->Accept(verifier);
1254 }
1255 
1256 BOOST_AUTO_TEST_CASE(SerializeFullyConnected)
1257 {
1258  using Descriptor = armnn::FullyConnectedDescriptor;
1259  class FullyConnectedLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
1260  {
1261  public:
1262  FullyConnectedLayerVerifier(const std::string& layerName,
1263  const std::vector<armnn::TensorInfo>& inputInfos,
1264  const std::vector<armnn::TensorInfo>& outputInfos,
1265  const Descriptor& descriptor,
1266  const armnn::ConstTensor& weight,
1268  : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
1269  , m_Weight(weight)
1270  , m_Bias(bias) {}
1271 
1272  void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
1273  const Descriptor& descriptor,
1274  const armnn::ConstTensor& weight,
1276  const char* name) override
1277  {
1278  VerifyNameAndConnections(layer, name);
1279  VerifyDescriptor(descriptor);
1280 
1281  CompareConstTensor(weight, m_Weight);
1282 
1283  BOOST_TEST(bias.has_value() == descriptor.m_BiasEnabled);
1284  BOOST_TEST(bias.has_value() == m_Bias.has_value());
1285 
1286  if (bias.has_value() && m_Bias.has_value())
1287  {
1288  CompareConstTensor(bias.value(), m_Bias.value());
1289  }
1290  }
1291 
1292  private:
1293  armnn::ConstTensor m_Weight;
1295  };
1296 
1297  const std::string layerName("fullyConnected");
1298  const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
1299  const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
1300 
1301  const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
1302  const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
1303  std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
1304  std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
1305  armnn::ConstTensor weights(weightsInfo, weightsData);
1306  armnn::ConstTensor biases(biasesInfo, biasesData);
1307 
1309  descriptor.m_BiasEnabled = true;
1310  descriptor.m_TransposeWeightMatrix = false;
1311 
1313  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1314  armnn::IConnectableLayer* const fullyConnectedLayer =
1315  network->AddFullyConnectedLayer(descriptor,
1316  weights,
1318  layerName.c_str());
1319  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1320 
1321  inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
1322  fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1323 
1324  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1325  fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1326 
1327  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1328  BOOST_CHECK(deserializedNetwork);
1329 
1330  FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
1331  deserializedNetwork->Accept(verifier);
1332 }
1333 
1334 BOOST_AUTO_TEST_CASE(SerializeGather)
1335 {
1337  class GatherLayerVerifier : public LayerVerifierBaseWithDescriptor<GatherDescriptor>
1338  {
1339  public:
1340  GatherLayerVerifier(const std::string& layerName,
1341  const std::vector<armnn::TensorInfo>& inputInfos,
1342  const std::vector<armnn::TensorInfo>& outputInfos,
1343  const GatherDescriptor& descriptor)
1344  : LayerVerifierBaseWithDescriptor<GatherDescriptor>(layerName, inputInfos, outputInfos, descriptor) {}
1345 
1346  void VisitGatherLayer(const armnn::IConnectableLayer* layer,
1347  const GatherDescriptor& descriptor,
1348  const char *name) override
1349  {
1350  VerifyNameAndConnections(layer, name);
1351  BOOST_CHECK(descriptor.m_Axis == m_Descriptor.m_Axis);
1352  }
1353 
1354  void VisitConstantLayer(const armnn::IConnectableLayer*,
1355  const armnn::ConstTensor&,
1356  const char*) override {}
1357  };
1358 
1359  const std::string layerName("gather");
1360  armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QAsymmU8);
1361  armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QAsymmU8);
1362  const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
1363  GatherDescriptor descriptor;
1364  descriptor.m_Axis = 1;
1365 
1366  paramsInfo.SetQuantizationScale(1.0f);
1367  paramsInfo.SetQuantizationOffset(0);
1368  outputInfo.SetQuantizationScale(1.0f);
1369  outputInfo.SetQuantizationOffset(0);
1370 
1371  const std::vector<int32_t>& indicesData = {7, 6, 5};
1372 
1374  armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
1375  armnn::IConnectableLayer *const constantLayer =
1376  network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
1377  armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(descriptor, layerName.c_str());
1378  armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
1379 
1380  inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
1381  constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
1382  gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1383 
1384  inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
1385  constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
1386  gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1387 
1388  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1389  BOOST_CHECK(deserializedNetwork);
1390 
1391  GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo}, descriptor);
1392  deserializedNetwork->Accept(verifier);
1393 }
1394 
1395 class GreaterLayerVerifier : public LayerVerifierBase
1396 {
1397 public:
1398  GreaterLayerVerifier(const std::string& layerName,
1399  const std::vector<armnn::TensorInfo>& inputInfos,
1400  const std::vector<armnn::TensorInfo>& outputInfos)
1401  : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1402 
1403  void VisitComparisonLayer(const armnn::IConnectableLayer* layer,
1404  const armnn::ComparisonDescriptor& descriptor,
1405  const char* name) override
1406  {
1407  VerifyNameAndConnections(layer, name);
1408  BOOST_CHECK(descriptor.m_Operation == armnn::ComparisonOperation::Greater);
1409  }
1410 
1411  void VisitGreaterLayer(const armnn::IConnectableLayer*, const char*) override
1412  {
1413  throw armnn::Exception("GreaterLayer should have translated to ComparisonLayer");
1414  }
1415 };
1416 
1417 // NOTE: Until the deprecated AddGreaterLayer disappears this test checks that calling
1418 // AddGreaterLayer places a ComparisonLayer into the serialized format and that
1419 // when this deserialises we have a ComparisonLayer
1420 BOOST_AUTO_TEST_CASE(SerializeGreater)
1421 {
1422  const std::string layerName("greater");
1423 
1424  const armnn::TensorShape shape{2, 1, 2, 4};
1425 
1428 
1430  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1431  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1433  armnn::IConnectableLayer* const equalLayer = network->AddGreaterLayer(layerName.c_str());
1435  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1436 
1437  inputLayer0->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
1438  inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
1439  equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1440 
1441  inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
1442  inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
1443  equalLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1444 
1445  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1446  BOOST_CHECK(deserializedNetwork);
1447 
1448  GreaterLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo });
1449  deserializedNetwork->Accept(verifier);
1450 }
1451 
1452 BOOST_AUTO_TEST_CASE(EnsureGreaterBackwardCompatibility)
1453 {
1454  // The hex data below is a flat buffer containing a simple network with two inputs,
1455  // an GreaterLayer (now deprecated) and an output
1456  //
1457  // This test verifies that we can still deserialize this old-style model by replacing
1458  // the GreaterLayer with an equivalent ComparisonLayer
1459  const std::vector<uint8_t> greaterModel =
1460  {
1461  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1462  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1463  0xCC, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1464  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1465  0x60, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1466  0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xEA, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1467  0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1468  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1469  0x64, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1470  0x00, 0x19, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1471  0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1472  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00,
1473  0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1474  0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00,
1475  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1476  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1477  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1478  0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1479  0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1480  0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1481  0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1482  0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1483  0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1484  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1485  0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1486  0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1487  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1488  0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1489  0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1490  0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1491  0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1492  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1493  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1494  0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1495  0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1496  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1497  0x02, 0x00, 0x00, 0x00
1498  };
1499 
1500  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(greaterModel.begin(), greaterModel.end()));
1501  BOOST_CHECK(deserializedNetwork);
1502 
1503  const armnn::TensorShape shape{ 1, 2, 2, 2 };
1504 
1507 
1508  GreaterLayerVerifier verifier("greater", { inputInfo, inputInfo }, { outputInfo });
1509  deserializedNetwork->Accept(verifier);
1510 }
1511 
1512 BOOST_AUTO_TEST_CASE(SerializeInstanceNormalization)
1513 {
1515 
1516  const std::string layerName("instanceNormalization");
1517  const armnn::TensorInfo info({ 1, 2, 1, 5 }, armnn::DataType::Float32);
1518 
1520  descriptor.m_Gamma = 1.1f;
1521  descriptor.m_Beta = 0.1f;
1522  descriptor.m_Eps = 0.0001f;
1523  descriptor.m_DataLayout = armnn::DataLayout::NHWC;
1524 
1526  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1527  armnn::IConnectableLayer* const instanceNormLayer =
1528  network->AddInstanceNormalizationLayer(descriptor, layerName.c_str());
1529  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1530 
1531  inputLayer->GetOutputSlot(0).Connect(instanceNormLayer->GetInputSlot(0));
1532  instanceNormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1533 
1534  inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1535  instanceNormLayer->GetOutputSlot(0).SetTensorInfo(info);
1536 
1537  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1538  BOOST_CHECK(deserializedNetwork);
1539 
1540  InstanceNormalizationLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1541  deserializedNetwork->Accept(verifier);
1542 }
1543 
1545 
1546 BOOST_AUTO_TEST_CASE(SerializeL2Normalization)
1547 {
1548  const std::string l2NormLayerName("l2Normalization");
1549  const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1550 
1553  desc.m_Eps = 0.0001f;
1554 
1556  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1557  armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1558  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1559 
1560  inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1561  l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1562 
1563  inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1564  l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1565 
1566  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1567  BOOST_CHECK(deserializedNetwork);
1568 
1569  L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc);
1570  deserializedNetwork->Accept(verifier);
1571 }
1572 
1573 BOOST_AUTO_TEST_CASE(EnsureL2NormalizationBackwardCompatibility)
1574 {
1575  // The hex data below is a flat buffer containing a simple network with one input
1576  // a L2Normalization layer and an output layer with dimensions as per the tensor infos below.
1577  //
1578  // This test verifies that we can still read back these old style
1579  // models without the normalization epsilon value.
1580  const std::vector<uint8_t> l2NormalizationModel =
1581  {
1582  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1583  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1584  0x3C, 0x01, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1585  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xE8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
1586  0x04, 0x00, 0x00, 0x00, 0xD6, 0xFE, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
1587  0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
1588  0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1589  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1590  0x4C, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
1591  0x00, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1592  0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1593  0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1594  0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x20, 0x00,
1595  0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x6C, 0x32, 0x4E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x69, 0x7A, 0x61, 0x74,
1596  0x69, 0x6F, 0x6E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00,
1597  0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1598  0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
1599  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1600  0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1601  0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1602  0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1603  0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1604  0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1605  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1606  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1607  0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1608  0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1609  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1610  0x05, 0x00, 0x00, 0x00, 0x00
1611  };
1612 
1613  armnn::INetworkPtr deserializedNetwork =
1614  DeserializeNetwork(std::string(l2NormalizationModel.begin(), l2NormalizationModel.end()));
1615  BOOST_CHECK(deserializedNetwork);
1616 
1617  const std::string layerName("l2Normalization");
1618  const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 2, 1, 5}, armnn::DataType::Float32);
1619 
1622  // Since this variable does not exist in the l2NormalizationModel dump, the default value will be loaded
1623  desc.m_Eps = 1e-12f;
1624 
1625  L2NormalizationLayerVerifier verifier(layerName, {inputInfo}, {inputInfo}, desc);
1626  deserializedNetwork->Accept(verifier);
1627 }
1628 
1629 BOOST_AUTO_TEST_CASE(SerializeLogicalBinary)
1630 {
1632 
1633  const std::string layerName("logicalBinaryAnd");
1634 
1635  const armnn::TensorShape shape{2, 1, 2, 2};
1636 
1639 
1641 
1643  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1644  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1645  armnn::IConnectableLayer* const logicalBinaryLayer = network->AddLogicalBinaryLayer(descriptor, layerName.c_str());
1646  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1647 
1648  inputLayer0->GetOutputSlot(0).Connect(logicalBinaryLayer->GetInputSlot(0));
1649  inputLayer1->GetOutputSlot(0).Connect(logicalBinaryLayer->GetInputSlot(1));
1650  logicalBinaryLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1651 
1652  inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
1653  inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
1654  logicalBinaryLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1655 
1656  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1657  BOOST_CHECK(deserializedNetwork);
1658 
1659  LogicalBinaryLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo }, descriptor);
1660  deserializedNetwork->Accept(verifier);
1661 }
1662 
1663 BOOST_AUTO_TEST_CASE(SerializeLogicalUnary)
1664 {
1666 
1667  const std::string layerName("elementwiseUnaryLogicalNot");
1668 
1669  const armnn::TensorShape shape{2, 1, 2, 2};
1670 
1673 
1675 
1677  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1678  armnn::IConnectableLayer* const elementwiseUnaryLayer =
1679  network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1680  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1681 
1682  inputLayer->GetOutputSlot(0).Connect(elementwiseUnaryLayer->GetInputSlot(0));
1683  elementwiseUnaryLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1684 
1685  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1686  elementwiseUnaryLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1687 
1688  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1689 
1690  BOOST_CHECK(deserializedNetwork);
1691 
1692  ElementwiseUnaryLayerVerifier verifier(layerName, { inputInfo }, { outputInfo }, descriptor);
1693 
1694  deserializedNetwork->Accept(verifier);
1695 }
1696 
1697 BOOST_AUTO_TEST_CASE(SerializeLogSoftmax)
1698 {
1700 
1701  const std::string layerName("log_softmax");
1703 
1704  armnn::LogSoftmaxDescriptor descriptor;
1705  descriptor.m_Beta = 1.0f;
1706  descriptor.m_Axis = -1;
1707 
1709  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1710  armnn::IConnectableLayer* const logSoftmaxLayer = network->AddLogSoftmaxLayer(descriptor, layerName.c_str());
1711  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1712 
1713  inputLayer->GetOutputSlot(0).Connect(logSoftmaxLayer->GetInputSlot(0));
1714  logSoftmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1715 
1716  inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1717  logSoftmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
1718 
1719  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1720  BOOST_CHECK(deserializedNetwork);
1721 
1722  LogSoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1723  deserializedNetwork->Accept(verifier);
1724 }
1725 
1726 BOOST_AUTO_TEST_CASE(SerializeMaximum)
1727 {
1729 
1730  const std::string layerName("maximum");
1731  const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1732 
1734  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1735  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1736  armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1737  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1738 
1739  inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1740  inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1741  maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1742 
1743  inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1744  inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1745  maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1746 
1747  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1748  BOOST_CHECK(deserializedNetwork);
1749 
1750  MaximumLayerVerifier verifier(layerName, {info, info}, {info});
1751  deserializedNetwork->Accept(verifier);
1752 }
1753 
1754 BOOST_AUTO_TEST_CASE(SerializeMean)
1755 {
1757 
1758  const std::string layerName("mean");
1759  const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1760  const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1761 
1762  armnn::MeanDescriptor descriptor;
1763  descriptor.m_Axis = { 2 };
1764  descriptor.m_KeepDims = true;
1765 
1767  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1768  armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1769  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1770 
1771  inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1772  meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1773 
1774  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1775  meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1776 
1777  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1778  BOOST_CHECK(deserializedNetwork);
1779 
1780  MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1781  deserializedNetwork->Accept(verifier);
1782 }
1783 
1784 BOOST_AUTO_TEST_CASE(SerializeMerge)
1785 {
1787 
1788  const std::string layerName("merge");
1789  const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1790 
1792  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1793  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1794  armnn::IConnectableLayer* const mergeLayer = network->AddMergeLayer(layerName.c_str());
1795  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1796 
1797  inputLayer0->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(0));
1798  inputLayer1->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(1));
1799  mergeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1800 
1801  inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1802  inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1803  mergeLayer->GetOutputSlot(0).SetTensorInfo(info);
1804 
1805  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1806  BOOST_CHECK(deserializedNetwork);
1807 
1808  MergeLayerVerifier verifier(layerName, {info, info}, {info});
1809  deserializedNetwork->Accept(verifier);
1810 }
1811 
1812 class MergerLayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::OriginsDescriptor>
1813 {
1814 public:
1815  MergerLayerVerifier(const std::string& layerName,
1816  const std::vector<armnn::TensorInfo>& inputInfos,
1817  const std::vector<armnn::TensorInfo>& outputInfos,
1818  const armnn::OriginsDescriptor& descriptor)
1819  : LayerVerifierBaseWithDescriptor<armnn::OriginsDescriptor>(layerName, inputInfos, outputInfos, descriptor) {}
1820 
1821  void VisitMergerLayer(const armnn::IConnectableLayer*,
1822  const armnn::OriginsDescriptor&,
1823  const char*) override
1824  {
1825  throw armnn::Exception("MergerLayer should have translated to ConcatLayer");
1826  }
1827 
1828  void VisitConcatLayer(const armnn::IConnectableLayer* layer,
1829  const armnn::OriginsDescriptor& descriptor,
1830  const char* name) override
1831  {
1832  VerifyNameAndConnections(layer, name);
1833  VerifyDescriptor(descriptor);
1834  }
1835 };
1836 
1837 // NOTE: Until the deprecated AddMergerLayer disappears this test checks that calling
1838 // AddMergerLayer places a ConcatLayer into the serialized format and that
1839 // when this deserialises we have a ConcatLayer
1840 BOOST_AUTO_TEST_CASE(SerializeMerger)
1841 {
1842  const std::string layerName("merger");
1843  const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1844  const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1845 
1846  const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1847 
1848  armnn::OriginsDescriptor descriptor =
1849  armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1850 
1852  armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1853  armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1855  armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str());
1857  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1858 
1859  inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
1860  inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
1861  mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1862 
1863  inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1864  inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1865  mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1866 
1867  std::string mergerLayerNetwork = SerializeNetwork(*network);
1868  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
1869  BOOST_CHECK(deserializedNetwork);
1870 
1871  MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1872  deserializedNetwork->Accept(verifier);
1873 }
1874 
1875 BOOST_AUTO_TEST_CASE(EnsureMergerLayerBackwardCompatibility)
1876 {
1877  // The hex data below is a flat buffer containing a simple network with two inputs
1878  // a merger layer (now deprecated) and an output layer with dimensions as per the tensor infos below.
1879  //
1880  // This test verifies that we can still read back these old style
1881  // models replacing the MergerLayers with ConcatLayers with the same parameters.
1882  const std::vector<uint8_t> mergerModel =
1883  {
1884  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1885  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1886  0x38, 0x02, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1887  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1888  0xF4, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1889  0x00, 0x00, 0x9A, 0xFE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1890  0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1891  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1892  0xF8, 0xFE, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1893  0x00, 0x1F, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1894  0x68, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
1895  0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1896  0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0x04, 0x00,
1897  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1898  0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1899  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1900  0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1901  0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6D, 0x65, 0x72, 0x67, 0x65, 0x72, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1902  0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1903  0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
1904  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00,
1905  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1906  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1907  0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1908  0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1909  0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1910  0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1911  0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1912  0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1913  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1914  0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1915  0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1916  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1917  0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1918  0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1919  0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1920  0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1921  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1922  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1923  0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1924  0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1925  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1926  0x02, 0x00, 0x00, 0x00
1927  };
1928 
1929  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(mergerModel.begin(), mergerModel.end()));
1930  BOOST_CHECK(deserializedNetwork);
1931 
1932  const armnn::TensorInfo inputInfo = armnn::TensorInfo({ 2, 3, 2, 2 }, armnn::DataType::Float32);
1933  const armnn::TensorInfo outputInfo = armnn::TensorInfo({ 4, 3, 2, 2 }, armnn::DataType::Float32);
1934 
1935  const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1936 
1937  armnn::OriginsDescriptor descriptor =
1938  armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1939 
1940  MergerLayerVerifier verifier("merger", { inputInfo, inputInfo }, { outputInfo }, descriptor);
1941  deserializedNetwork->Accept(verifier);
1942 }
1943 
1944 BOOST_AUTO_TEST_CASE(SerializeConcat)
1945 {
1946  const std::string layerName("concat");
1947  const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1948  const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1949 
1950  const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1951 
1952  armnn::OriginsDescriptor descriptor =
1953  armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1954 
1956  armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1957  armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1958  armnn::IConnectableLayer* const concatLayer = network->AddConcatLayer(descriptor, layerName.c_str());
1959  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1960 
1961  inputLayerOne->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
1962  inputLayerTwo->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
1963  concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1964 
1965  inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1966  inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1967  concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1968 
1969  std::string concatLayerNetwork = SerializeNetwork(*network);
1970  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(concatLayerNetwork);
1971  BOOST_CHECK(deserializedNetwork);
1972 
1973  // NOTE: using the MergerLayerVerifier to ensure that it is a concat layer and not a
1974  // merger layer that gets placed into the graph.
1975  MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1976  deserializedNetwork->Accept(verifier);
1977 }
1978 
1979 BOOST_AUTO_TEST_CASE(SerializeMinimum)
1980 {
1982 
1983  const std::string layerName("minimum");
1984  const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1985 
1987  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1988  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1989  armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1990  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1991 
1992  inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1993  inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1994  minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1995 
1996  inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1997  inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1998  minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
1999 
2000  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2001  BOOST_CHECK(deserializedNetwork);
2002 
2003  MinimumLayerVerifier verifier(layerName, {info, info}, {info});
2004  deserializedNetwork->Accept(verifier);
2005 }
2006 
2007 BOOST_AUTO_TEST_CASE(SerializeMultiplication)
2008 {
2010 
2011  const std::string layerName("multiplication");
2012  const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
2013 
2015  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2016  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2017  armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
2018  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2019 
2020  inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
2021  inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
2022  multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2023 
2024  inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2025  inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2026  multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
2027 
2028  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2029  BOOST_CHECK(deserializedNetwork);
2030 
2031  MultiplicationLayerVerifier verifier(layerName, {info, info}, {info});
2032  deserializedNetwork->Accept(verifier);
2033 }
2034 
2035 BOOST_AUTO_TEST_CASE(SerializePrelu)
2036 {
2038 
2039  const std::string layerName("prelu");
2040 
2041  armnn::TensorInfo inputTensorInfo ({ 4, 1, 2 }, armnn::DataType::Float32);
2042  armnn::TensorInfo alphaTensorInfo ({ 5, 4, 3, 1 }, armnn::DataType::Float32);
2043  armnn::TensorInfo outputTensorInfo({ 5, 4, 3, 2 }, armnn::DataType::Float32);
2044 
2046  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2047  armnn::IConnectableLayer* const alphaLayer = network->AddInputLayer(1);
2048  armnn::IConnectableLayer* const preluLayer = network->AddPreluLayer(layerName.c_str());
2049  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2050 
2051  inputLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(0));
2052  alphaLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(1));
2053  preluLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2054 
2055  inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2056  alphaLayer->GetOutputSlot(0).SetTensorInfo(alphaTensorInfo);
2057  preluLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2058 
2059  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2060  BOOST_CHECK(deserializedNetwork);
2061 
2062  PreluLayerVerifier verifier(layerName, {inputTensorInfo, alphaTensorInfo}, {outputTensorInfo});
2063  deserializedNetwork->Accept(verifier);
2064 }
2065 
2066 BOOST_AUTO_TEST_CASE(SerializeNormalization)
2067 {
2069 
2070  const std::string layerName("normalization");
2071  const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
2072 
2075  desc.m_NormSize = 3;
2076  desc.m_Alpha = 1;
2077  desc.m_Beta = 1;
2078  desc.m_K = 1;
2079 
2081  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2082  armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
2083  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2084 
2085  inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
2086  normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2087 
2088  inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2089  normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
2090 
2091  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2092  BOOST_CHECK(deserializedNetwork);
2093 
2094  NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc);
2095  deserializedNetwork->Accept(verifier);
2096 }
2097 
2099 
2101 {
2102  const std::string layerName("pad");
2103  const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
2104  const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
2105 
2106  armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
2107 
2109  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2110  armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
2111  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2112 
2113  inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
2114  padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2115 
2116  inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2117  padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2118 
2119  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2120  BOOST_CHECK(deserializedNetwork);
2121 
2122  PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
2123  deserializedNetwork->Accept(verifier);
2124 }
2125 
2126 BOOST_AUTO_TEST_CASE(EnsurePadBackwardCompatibility)
2127 {
2128  // The PadDescriptor is being extended with a float PadValue (so a value other than 0
2129  // can be used to pad the tensor.
2130  //
2131  // This test contains a binary representation of a simple input->pad->output network
2132  // prior to this change to test that the descriptor has been updated in a backward
2133  // compatible way with respect to Deserialization of older binary dumps
2134  const std::vector<uint8_t> padModel =
2135  {
2136  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
2137  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2138  0x54, 0x01, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2139  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD0, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
2140  0x04, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x04, 0x00,
2141  0x00, 0x00, 0x72, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2142  0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2143  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00,
2144  0x00, 0x00, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x16, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00,
2145  0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
2146  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00,
2147  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2148  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
2149  0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
2150  0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00,
2151  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
2152  0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
2153  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
2154  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00,
2155  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
2156  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00,
2157  0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00,
2158  0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
2159  0x0E, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00,
2160  0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
2161  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
2162  0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
2163  0x0A, 0x00, 0x10, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
2164  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
2165  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00
2166  };
2167 
2168  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(padModel.begin(), padModel.end()));
2169  BOOST_CHECK(deserializedNetwork);
2170 
2171  const armnn::TensorInfo inputInfo = armnn::TensorInfo({ 1, 2, 3, 4 }, armnn::DataType::Float32);
2172  const armnn::TensorInfo outputInfo = armnn::TensorInfo({ 1, 3, 5, 7 }, armnn::DataType::Float32);
2173 
2174  armnn::PadDescriptor descriptor({{ 0, 0 }, { 1, 0 }, { 1, 1 }, { 1, 2 }});
2175 
2176  PadLayerVerifier verifier("pad", { inputInfo }, { outputInfo }, descriptor);
2177  deserializedNetwork->Accept(verifier);
2178 }
2179 
2180 BOOST_AUTO_TEST_CASE(SerializePermute)
2181 {
2183 
2184  const std::string layerName("permute");
2185  const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
2186  const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
2187 
2188  armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
2189 
2191  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2192  armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
2193  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2194 
2195  inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
2196  permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2197 
2198  inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2199  permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2200 
2201  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2202  BOOST_CHECK(deserializedNetwork);
2203 
2204  PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
2205  deserializedNetwork->Accept(verifier);
2206 }
2207 
2208 BOOST_AUTO_TEST_CASE(SerializePooling2d)
2209 {
2211 
2212  const std::string layerName("pooling2d");
2213  const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
2214  const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
2215 
2218  desc.m_PadTop = 0;
2219  desc.m_PadBottom = 0;
2220  desc.m_PadLeft = 0;
2221  desc.m_PadRight = 0;
2222  desc.m_PoolType = armnn::PoolingAlgorithm::Average;
2223  desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
2224  desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
2225  desc.m_PoolHeight = 2;
2226  desc.m_PoolWidth = 2;
2227  desc.m_StrideX = 2;
2228  desc.m_StrideY = 2;
2229 
2231  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2232  armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
2233  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2234 
2235  inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
2236  pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2237 
2238  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2239  pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2240 
2241  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2242  BOOST_CHECK(deserializedNetwork);
2243 
2244  Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2245  deserializedNetwork->Accept(verifier);
2246 }
2247 
2248 BOOST_AUTO_TEST_CASE(SerializeQuantize)
2249 {
2251 
2252  const std::string layerName("quantize");
2253  const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
2254 
2256  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2257  armnn::IConnectableLayer* const quantizeLayer = network->AddQuantizeLayer(layerName.c_str());
2258  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2259 
2260  inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
2261  quantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2262 
2263  inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2264  quantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
2265 
2266  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2267  BOOST_CHECK(deserializedNetwork);
2268 
2269  QuantizeLayerVerifier verifier(layerName, {info}, {info});
2270  deserializedNetwork->Accept(verifier);
2271 }
2272 
2273 BOOST_AUTO_TEST_CASE(SerializeRank)
2274 {
2276 
2277  const std::string layerName("rank");
2278  const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
2279  const armnn::TensorInfo outputInfo({1}, armnn::DataType::Signed32);
2280 
2282  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2283  armnn::IConnectableLayer* const rankLayer = network->AddRankLayer(layerName.c_str());
2284  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2285 
2286  inputLayer->GetOutputSlot(0).Connect(rankLayer->GetInputSlot(0));
2287  rankLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2288 
2289  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2290  rankLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2291 
2292  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2293  BOOST_CHECK(deserializedNetwork);
2294 
2295  RankLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
2296  deserializedNetwork->Accept(verifier);
2297 }
2298 
2299 BOOST_AUTO_TEST_CASE(SerializeReshape)
2300 {
2302 
2303  const std::string layerName("reshape");
2304  const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
2305  const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
2306 
2307  armnn::ReshapeDescriptor descriptor({3, 3});
2308 
2310  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2311  armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
2312  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2313 
2314  inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
2315  reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2316 
2317  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2318  reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2319 
2320  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2321  BOOST_CHECK(deserializedNetwork);
2322 
2323  ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2324  deserializedNetwork->Accept(verifier);
2325 }
2326 
2327 BOOST_AUTO_TEST_CASE(SerializeResize)
2328 {
2330 
2331  const std::string layerName("resize");
2332  const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2333  const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2334 
2336  desc.m_TargetWidth = 4;
2337  desc.m_TargetHeight = 2;
2338  desc.m_Method = armnn::ResizeMethod::NearestNeighbor;
2339  desc.m_AlignCorners = true;
2340  desc.m_HalfPixelCenters = true;
2341 
2343  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2344  armnn::IConnectableLayer* const resizeLayer = network->AddResizeLayer(desc, layerName.c_str());
2345  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2346 
2347  inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2348  resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2349 
2350  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2351  resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2352 
2353  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2354  BOOST_CHECK(deserializedNetwork);
2355 
2356  ResizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2357  deserializedNetwork->Accept(verifier);
2358 }
2359 
2360 class ResizeBilinearLayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::ResizeBilinearDescriptor>
2361 {
2362 public:
2363  ResizeBilinearLayerVerifier(const std::string& layerName,
2364  const std::vector<armnn::TensorInfo>& inputInfos,
2365  const std::vector<armnn::TensorInfo>& outputInfos,
2366  const armnn::ResizeBilinearDescriptor& descriptor)
2367  : LayerVerifierBaseWithDescriptor<armnn::ResizeBilinearDescriptor>(
2368  layerName, inputInfos, outputInfos, descriptor) {}
2369 
2370  void VisitResizeLayer(const armnn::IConnectableLayer* layer,
2371  const armnn::ResizeDescriptor& descriptor,
2372  const char* name) override
2373  {
2374  VerifyNameAndConnections(layer, name);
2375 
2376  BOOST_CHECK(descriptor.m_Method == armnn::ResizeMethod::Bilinear);
2377  BOOST_CHECK(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
2378  BOOST_CHECK(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
2379  BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2380  BOOST_CHECK(descriptor.m_AlignCorners == m_Descriptor.m_AlignCorners);
2381  BOOST_CHECK(descriptor.m_HalfPixelCenters == m_Descriptor.m_HalfPixelCenters);
2382  }
2383 
2384  void VisitResizeBilinearLayer(const armnn::IConnectableLayer*,
2386  const char*) override
2387  {
2388  throw armnn::Exception("ResizeBilinearLayer should have translated to ResizeLayer");
2389  }
2390 };
2391 
2392 // NOTE: Until the deprecated AddResizeBilinearLayer disappears this test checks that
2393 // calling AddResizeBilinearLayer places a ResizeLayer into the serialized format
2394 // and that when this deserialises we have a ResizeLayer
2395 BOOST_AUTO_TEST_CASE(SerializeResizeBilinear)
2396 {
2397  const std::string layerName("resizeBilinear");
2398  const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2399  const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2400 
2402  desc.m_TargetWidth = 4u;
2403  desc.m_TargetHeight = 2u;
2404  desc.m_AlignCorners = true;
2405  desc.m_HalfPixelCenters = true;
2406 
2408  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2410  armnn::IConnectableLayer* const resizeLayer = network->AddResizeBilinearLayer(desc, layerName.c_str());
2412  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2413 
2414  inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2415  resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2416 
2417  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2418  resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2419 
2420  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2421  BOOST_CHECK(deserializedNetwork);
2422 
2423  ResizeBilinearLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2424  deserializedNetwork->Accept(verifier);
2425 }
2426 
2427 BOOST_AUTO_TEST_CASE(EnsureResizeBilinearBackwardCompatibility)
2428 {
2429  // The hex data below is a flat buffer containing a simple network with an input,
2430  // a ResizeBilinearLayer (now deprecated) and an output
2431  //
2432  // This test verifies that we can still deserialize this old-style model by replacing
2433  // the ResizeBilinearLayer with an equivalent ResizeLayer
2434  const std::vector<uint8_t> resizeBilinearModel =
2435  {
2436  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
2437  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2438  0x50, 0x01, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2439  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD4, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
2440  0x04, 0x00, 0x00, 0x00, 0xC2, 0xFE, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
2441  0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8A, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
2442  0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
2443  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2444  0x38, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
2445  0x00, 0x1A, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
2446  0x34, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x12, 0x00, 0x08, 0x00, 0x0C, 0x00,
2447  0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2448  0x00, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00,
2449  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
2450  0x20, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x69, 0x7A, 0x65, 0x42, 0x69, 0x6C, 0x69,
2451  0x6E, 0x65, 0x61, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2452  0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
2453  0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2454  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
2455  0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2456  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
2457  0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
2458  0x0A, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00,
2459  0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
2460  0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2461  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00,
2462  0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
2463  0x08, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
2464  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00,
2465  0x00, 0x00, 0x05, 0x00, 0x00, 0x00
2466  };
2467 
2468  armnn::INetworkPtr deserializedNetwork =
2469  DeserializeNetwork(std::string(resizeBilinearModel.begin(), resizeBilinearModel.end()));
2470  BOOST_CHECK(deserializedNetwork);
2471 
2472  const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2473  const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2474 
2476  descriptor.m_TargetWidth = 4u;
2477  descriptor.m_TargetHeight = 2u;
2478 
2479  ResizeBilinearLayerVerifier verifier("resizeBilinear", { inputInfo }, { outputInfo }, descriptor);
2480  deserializedNetwork->Accept(verifier);
2481 }
2482 
2483 BOOST_AUTO_TEST_CASE(SerializeSlice)
2484 {
2486 
2487  const std::string layerName{"slice"};
2488 
2489  const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2490  const armnn::TensorInfo outputInfo = armnn::TensorInfo({2, 2, 2, 1}, armnn::DataType::Float32);
2491 
2492  armnn::SliceDescriptor descriptor({ 0, 0, 1, 0}, {2, 2, 2, 1});
2493 
2495 
2496  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2497  armnn::IConnectableLayer* const sliceLayer = network->AddSliceLayer(descriptor, layerName.c_str());
2498  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2499 
2500  inputLayer->GetOutputSlot(0).Connect(sliceLayer->GetInputSlot(0));
2501  sliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2502 
2503  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2504  sliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2505 
2506  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2507  BOOST_CHECK(deserializedNetwork);
2508 
2509  SliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2510  deserializedNetwork->Accept(verifier);
2511 }
2512 
2513 BOOST_AUTO_TEST_CASE(SerializeSoftmax)
2514 {
2516 
2517  const std::string layerName("softmax");
2519 
2520  armnn::SoftmaxDescriptor descriptor;
2521  descriptor.m_Beta = 1.0f;
2522 
2524  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2525  armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
2526  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2527 
2528  inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
2529  softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2530 
2531  inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2532  softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
2533 
2534  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2535  BOOST_CHECK(deserializedNetwork);
2536 
2537  SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
2538  deserializedNetwork->Accept(verifier);
2539 }
2540 
2541 BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
2542 {
2544 
2545  const std::string layerName("spaceToBatchNd");
2546  const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
2547  const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
2548 
2551  desc.m_BlockShape = {2, 2};
2552  desc.m_PadList = {{0, 0}, {2, 0}};
2553 
2555  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2556  armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2557  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2558 
2559  inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
2560  spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2561 
2562  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2563  spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2564 
2565  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2566  BOOST_CHECK(deserializedNetwork);
2567 
2568  SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2569  deserializedNetwork->Accept(verifier);
2570 }
2571 
2572 BOOST_AUTO_TEST_CASE(SerializeSpaceToDepth)
2573 {
2575 
2576  const std::string layerName("spaceToDepth");
2577 
2578  const armnn::TensorInfo inputInfo ({ 1, 16, 8, 3 }, armnn::DataType::Float32);
2579  const armnn::TensorInfo outputInfo({ 1, 8, 4, 12 }, armnn::DataType::Float32);
2580 
2582  desc.m_BlockSize = 2;
2583  desc.m_DataLayout = armnn::DataLayout::NHWC;
2584 
2586  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2587  armnn::IConnectableLayer* const spaceToDepthLayer = network->AddSpaceToDepthLayer(desc, layerName.c_str());
2588  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2589 
2590  inputLayer->GetOutputSlot(0).Connect(spaceToDepthLayer->GetInputSlot(0));
2591  spaceToDepthLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2592 
2593  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2594  spaceToDepthLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2595 
2596  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2597  BOOST_CHECK(deserializedNetwork);
2598 
2599  SpaceToDepthLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2600  deserializedNetwork->Accept(verifier);
2601 }
2602 
2603 BOOST_AUTO_TEST_CASE(SerializeSplitter)
2604 {
2606 
2607  const unsigned int numViews = 3;
2608  const unsigned int numDimensions = 4;
2609  const unsigned int inputShape[] = {1, 18, 4, 4};
2610  const unsigned int outputShape[] = {1, 6, 4, 4};
2611 
2612  // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
2613  unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
2614  static_cast<unsigned int>(inputShape[1]),
2615  static_cast<unsigned int>(inputShape[2]),
2616  static_cast<unsigned int>(inputShape[3])};
2617  splitterDimSizes[1] /= numViews;
2618  armnn::ViewsDescriptor desc(numViews, numDimensions);
2619 
2620  for (unsigned int g = 0; g < numViews; ++g)
2621  {
2622  desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
2623 
2624  for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
2625  {
2626  desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
2627  }
2628  }
2629 
2630  const std::string layerName("splitter");
2631  const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
2632  const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
2633 
2635  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2636  armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
2637  armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2638  armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2639  armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
2640 
2641  inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
2642  splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2643  splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2644  splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
2645 
2646  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2647  splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2648  splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
2649  splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2650 
2651  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2652  BOOST_CHECK(deserializedNetwork);
2653 
2654  SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
2655  deserializedNetwork->Accept(verifier);
2656 }
2657 
2658 BOOST_AUTO_TEST_CASE(SerializeStack)
2659 {
2661 
2662  const std::string layerName("stack");
2663 
2664  armnn::TensorInfo inputTensorInfo ({4, 3, 5}, armnn::DataType::Float32);
2665  armnn::TensorInfo outputTensorInfo({4, 3, 2, 5}, armnn::DataType::Float32);
2666 
2667  armnn::StackDescriptor descriptor(2, 2, {4, 3, 5});
2668 
2670  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
2671  armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
2672  armnn::IConnectableLayer* const stackLayer = network->AddStackLayer(descriptor, layerName.c_str());
2673  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2674 
2675  inputLayer1->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(0));
2676  inputLayer2->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(1));
2677  stackLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2678 
2679  inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2680  inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2681  stackLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2682 
2683  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2684  BOOST_CHECK(deserializedNetwork);
2685 
2686  StackLayerVerifier verifier(layerName, {inputTensorInfo, inputTensorInfo}, {outputTensorInfo}, descriptor);
2687  deserializedNetwork->Accept(verifier);
2688 }
2689 
2690 BOOST_AUTO_TEST_CASE(SerializeStandIn)
2691 {
2693 
2694  const std::string layerName("standIn");
2695 
2696  armnn::TensorInfo tensorInfo({ 1u }, armnn::DataType::Float32);
2697  armnn::StandInDescriptor descriptor(2u, 2u);
2698 
2700  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2701  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2702  armnn::IConnectableLayer* const standInLayer = network->AddStandInLayer(descriptor, layerName.c_str());
2703  armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2704  armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2705 
2706  inputLayer0->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(0));
2707  inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2708 
2709  inputLayer1->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(1));
2710  inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2711 
2712  standInLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2713  standInLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2714 
2715  standInLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2716  standInLayer->GetOutputSlot(1).SetTensorInfo(tensorInfo);
2717 
2718  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2719  BOOST_CHECK(deserializedNetwork);
2720 
2721  StandInLayerVerifier verifier(layerName, { tensorInfo, tensorInfo }, { tensorInfo, tensorInfo }, descriptor);
2722  deserializedNetwork->Accept(verifier);
2723 }
2724 
2725 BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
2726 {
2728 
2729  const std::string layerName("stridedSlice");
2730  const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2731  const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2732 
2733  armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2734  desc.m_EndMask = (1 << 4) - 1;
2735  desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2736  desc.m_DataLayout = armnn::DataLayout::NCHW;
2737 
2739  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2740  armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2741  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2742 
2743  inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2744  stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2745 
2746  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2747  stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2748 
2749  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2750  BOOST_CHECK(deserializedNetwork);
2751 
2752  StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2753  deserializedNetwork->Accept(verifier);
2754 }
2755 
2756 BOOST_AUTO_TEST_CASE(SerializeSubtraction)
2757 {
2759 
2760  const std::string layerName("subtraction");
2762 
2764  armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2765  armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2766  armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2767  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2768 
2769  inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2770  inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2771  subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2772 
2773  inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2774  inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2775  subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2776 
2777  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2778  BOOST_CHECK(deserializedNetwork);
2779 
2780  SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
2781  deserializedNetwork->Accept(verifier);
2782 }
2783 
2784 BOOST_AUTO_TEST_CASE(SerializeSwitch)
2785 {
2786  class SwitchLayerVerifier : public LayerVerifierBase
2787  {
2788  public:
2789  SwitchLayerVerifier(const std::string& layerName,
2790  const std::vector<armnn::TensorInfo>& inputInfos,
2791  const std::vector<armnn::TensorInfo>& outputInfos)
2792  : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2793 
2794  void VisitSwitchLayer(const armnn::IConnectableLayer* layer, const char* name) override
2795  {
2796  VerifyNameAndConnections(layer, name);
2797  }
2798 
2799  void VisitConstantLayer(const armnn::IConnectableLayer*,
2800  const armnn::ConstTensor&,
2801  const char*) override {}
2802  };
2803 
2804  const std::string layerName("switch");
2806 
2807  std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2808  armnn::ConstTensor constTensor(info, constantData);
2809 
2811  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2812  armnn::IConnectableLayer* const constantLayer = network->AddConstantLayer(constTensor, "constant");
2813  armnn::IConnectableLayer* const switchLayer = network->AddSwitchLayer(layerName.c_str());
2814  armnn::IConnectableLayer* const trueOutputLayer = network->AddOutputLayer(0);
2815  armnn::IConnectableLayer* const falseOutputLayer = network->AddOutputLayer(1);
2816 
2817  inputLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(0));
2818  constantLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(1));
2819  switchLayer->GetOutputSlot(0).Connect(trueOutputLayer->GetInputSlot(0));
2820  switchLayer->GetOutputSlot(1).Connect(falseOutputLayer->GetInputSlot(0));
2821 
2822  inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2823  constantLayer->GetOutputSlot(0).SetTensorInfo(info);
2824  switchLayer->GetOutputSlot(0).SetTensorInfo(info);
2825  switchLayer->GetOutputSlot(1).SetTensorInfo(info);
2826 
2827  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2828  BOOST_CHECK(deserializedNetwork);
2829 
2830  SwitchLayerVerifier verifier(layerName, {info, info}, {info, info});
2831  deserializedNetwork->Accept(verifier);
2832 }
2833 
2834 BOOST_AUTO_TEST_CASE(SerializeTranspose)
2835 {
2837 
2838  const std::string layerName("transpose");
2839  const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
2840  const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
2841 
2842  armnn::TransposeDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
2843 
2845  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2846  armnn::IConnectableLayer* const transposeLayer = network->AddTransposeLayer(descriptor, layerName.c_str());
2847  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2848 
2849  inputLayer->GetOutputSlot(0).Connect(transposeLayer->GetInputSlot(0));
2850  transposeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2851 
2852  inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2853  transposeLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2854 
2855  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2856  BOOST_CHECK(deserializedNetwork);
2857 
2858  TransposeLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
2859  deserializedNetwork->Accept(verifier);
2860 }
2861 
2862 BOOST_AUTO_TEST_CASE(SerializeTransposeConvolution2d)
2863 {
2864  using Descriptor = armnn::TransposeConvolution2dDescriptor;
2865  class TransposeConvolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
2866  {
2867  public:
2868  TransposeConvolution2dLayerVerifier(const std::string& layerName,
2869  const std::vector<armnn::TensorInfo>& inputInfos,
2870  const std::vector<armnn::TensorInfo>& outputInfos,
2871  const Descriptor& descriptor,
2872  const armnn::ConstTensor& weights,
2874  : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
2875  , m_Weights(weights)
2876  , m_Biases(biases)
2877  {}
2878 
2879  void VisitTransposeConvolution2dLayer(const armnn::IConnectableLayer* layer,
2880  const Descriptor& descriptor,
2881  const armnn::ConstTensor& weights,
2883  const char* name) override
2884  {
2885  VerifyNameAndConnections(layer, name);
2886  VerifyDescriptor(descriptor);
2887 
2888  // check weights
2889  CompareConstTensor(weights, m_Weights);
2890 
2891  // check biases
2892  BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
2893  BOOST_CHECK(biases.has_value() == m_Biases.has_value());
2894 
2895  if (biases.has_value() && m_Biases.has_value())
2896  {
2897  CompareConstTensor(biases.value(), m_Biases.value());
2898  }
2899  }
2900 
2901  private:
2902  armnn::ConstTensor m_Weights;
2904  };
2905 
2906  const std::string layerName("transposeConvolution2d");
2907  const armnn::TensorInfo inputInfo ({ 1, 7, 7, 1 }, armnn::DataType::Float32);
2908  const armnn::TensorInfo outputInfo({ 1, 9, 9, 1 }, armnn::DataType::Float32);
2909 
2910  const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
2911  const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
2912 
2913  std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
2914  armnn::ConstTensor weights(weightsInfo, weightsData);
2915 
2916  std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
2917  armnn::ConstTensor biases(biasesInfo, biasesData);
2918 
2920  descriptor.m_PadLeft = 1;
2921  descriptor.m_PadRight = 1;
2922  descriptor.m_PadTop = 1;
2923  descriptor.m_PadBottom = 1;
2924  descriptor.m_StrideX = 1;
2925  descriptor.m_StrideY = 1;
2926  descriptor.m_BiasEnabled = true;
2928 
2930  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2931  armnn::IConnectableLayer* const convLayer =
2932  network->AddTransposeConvolution2dLayer(descriptor,
2933  weights,
2935  layerName.c_str());
2936  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2937 
2938  inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
2939  convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2940 
2941  inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2942  convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2943 
2944  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2945  BOOST_CHECK(deserializedNetwork);
2946 
2947  TransposeConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
2948  deserializedNetwork->Accept(verifier);
2949 }
2950 
2951 BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
2952 {
2953  class ConstantLayerVerifier : public LayerVerifierBase
2954  {
2955  public:
2956  ConstantLayerVerifier(const std::string& layerName,
2957  const std::vector<armnn::TensorInfo>& inputInfos,
2958  const std::vector<armnn::TensorInfo>& outputInfos,
2959  const armnn::ConstTensor& layerInput)
2960  : LayerVerifierBase(layerName, inputInfos, outputInfos)
2961  , m_LayerInput(layerInput) {}
2962 
2963  void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2964  const armnn::ConstTensor& input,
2965  const char* name) override
2966  {
2967  VerifyNameAndConnections(layer, name);
2968  CompareConstTensor(input, m_LayerInput);
2969  }
2970 
2971  void VisitAdditionLayer(const armnn::IConnectableLayer*, const char*) override {}
2972 
2973  private:
2974  armnn::ConstTensor m_LayerInput;
2975  };
2976 
2977  const std::string layerName("constant");
2979 
2980  std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2981  armnn::ConstTensor constTensor(info, constantData);
2982 
2984  armnn::IConnectableLayer* input = network->AddInputLayer(0);
2985  armnn::IConnectableLayer* add = network->AddAdditionLayer();
2986  armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2987  armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2988 
2989  input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2990  constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2991  add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2992 
2993  input->GetOutputSlot(0).SetTensorInfo(info);
2994  constant->GetOutputSlot(0).SetTensorInfo(info);
2995  add->GetOutputSlot(0).SetTensorInfo(info);
2996 
2997  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2998  BOOST_CHECK(deserializedNetwork);
2999 
3000  ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
3001  deserializedNetwork->Accept(verifier);
3002 }
3003 
3004 class VerifyLstmLayer : public LayerVerifierBaseWithDescriptor<armnn::LstmDescriptor>
3005 {
3006 public:
3007  VerifyLstmLayer(const std::string& layerName,
3008  const std::vector<armnn::TensorInfo>& inputInfos,
3009  const std::vector<armnn::TensorInfo>& outputInfos,
3010  const armnn::LstmDescriptor& descriptor,
3011  const armnn::LstmInputParams& inputParams)
3012  : LayerVerifierBaseWithDescriptor<armnn::LstmDescriptor>(layerName, inputInfos, outputInfos, descriptor)
3013  , m_InputParams(inputParams) {}
3014 
3015  void VisitLstmLayer(const armnn::IConnectableLayer* layer,
3016  const armnn::LstmDescriptor& descriptor,
3017  const armnn::LstmInputParams& params,
3018  const char* name)
3019  {
3020  VerifyNameAndConnections(layer, name);
3021  VerifyDescriptor(descriptor);
3022  VerifyInputParameters(params);
3023  }
3024 
3025 protected:
3026  void VerifyInputParameters(const armnn::LstmInputParams& params)
3027  {
3028  VerifyConstTensors(
3029  "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
3030  VerifyConstTensors(
3031  "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
3032  VerifyConstTensors(
3033  "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
3034  VerifyConstTensors(
3035  "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
3036  VerifyConstTensors(
3037  "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
3038  VerifyConstTensors(
3039  "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
3040  VerifyConstTensors(
3041  "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
3042  VerifyConstTensors(
3043  "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
3044  VerifyConstTensors(
3045  "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
3046  VerifyConstTensors(
3047  "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
3048  VerifyConstTensors(
3049  "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
3050  VerifyConstTensors(
3051  "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
3052  VerifyConstTensors(
3053  "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
3054  VerifyConstTensors(
3055  "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
3056  VerifyConstTensors(
3057  "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
3058  VerifyConstTensors(
3059  "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
3060  VerifyConstTensors(
3061  "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
3062  VerifyConstTensors(
3063  "m_InputLayerNormWeights", m_InputParams.m_InputLayerNormWeights, params.m_InputLayerNormWeights);
3064  VerifyConstTensors(
3065  "m_ForgetLayerNormWeights", m_InputParams.m_ForgetLayerNormWeights, params.m_ForgetLayerNormWeights);
3066  VerifyConstTensors(
3067  "m_CellLayerNormWeights", m_InputParams.m_CellLayerNormWeights, params.m_CellLayerNormWeights);
3068  VerifyConstTensors(
3069  "m_OutputLayerNormWeights", m_InputParams.m_OutputLayerNormWeights, params.m_OutputLayerNormWeights);
3070  }
3071 
3072 private:
3073  armnn::LstmInputParams m_InputParams;
3074 };
3075 
3076 BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
3077 {
3078  armnn::LstmDescriptor descriptor;
3079  descriptor.m_ActivationFunc = 4;
3080  descriptor.m_ClippingThresProj = 0.0f;
3081  descriptor.m_ClippingThresCell = 0.0f;
3082  descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
3083  descriptor.m_ProjectionEnabled = false;
3084  descriptor.m_PeepholeEnabled = true;
3085 
3086  const uint32_t batchSize = 1;
3087  const uint32_t inputSize = 2;
3088  const uint32_t numUnits = 4;
3089  const uint32_t outputSize = numUnits;
3090 
3091  armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
3092  std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
3093  armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
3094 
3095  std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
3096  armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
3097 
3098  std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
3099  armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
3100 
3101  armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
3102  std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
3103  armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
3104 
3105  std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
3106  armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
3107 
3108  std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
3109  armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
3110 
3111  armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
3112  std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
3113  armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
3114 
3115  std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
3116  armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
3117 
3118  std::vector<float> forgetGateBiasData(numUnits, 1.0f);
3119  armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
3120 
3121  std::vector<float> cellBiasData(numUnits, 0.0f);
3122  armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
3123 
3124  std::vector<float> outputGateBiasData(numUnits, 0.0f);
3125  armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
3126 
3127  armnn::LstmInputParams params;
3128  params.m_InputToForgetWeights = &inputToForgetWeights;
3129  params.m_InputToCellWeights = &inputToCellWeights;
3130  params.m_InputToOutputWeights = &inputToOutputWeights;
3131  params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3132  params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3133  params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3134  params.m_ForgetGateBias = &forgetGateBias;
3135  params.m_CellBias = &cellBias;
3136  params.m_OutputGateBias = &outputGateBias;
3137  params.m_CellToForgetWeights = &cellToForgetWeights;
3138  params.m_CellToOutputWeights = &cellToOutputWeights;
3139 
3141  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3142  armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3143  armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3144  const std::string layerName("lstm");
3145  armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3146  armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3147  armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3148  armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3149  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3150 
3151  // connect up
3152  armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3153  armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3154  armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3155  armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
3156 
3157  inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3158  inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3159 
3160  outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3161  outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3162 
3163  cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3164  cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3165 
3166  lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3167  lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3168 
3169  lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3170  lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3171 
3172  lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3173  lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3174 
3175  lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3176  lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3177 
3178  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3179  BOOST_CHECK(deserializedNetwork);
3180 
3181  VerifyLstmLayer checker(
3182  layerName,
3183  {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3184  {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3185  descriptor,
3186  params);
3187  deserializedNetwork->Accept(checker);
3188 }
3189 
3190 BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
3191 {
3192  armnn::LstmDescriptor descriptor;
3193  descriptor.m_ActivationFunc = 4;
3194  descriptor.m_ClippingThresProj = 0.0f;
3195  descriptor.m_ClippingThresCell = 0.0f;
3196  descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
3197  descriptor.m_ProjectionEnabled = true;
3198  descriptor.m_PeepholeEnabled = true;
3199 
3200  const uint32_t batchSize = 2;
3201  const uint32_t inputSize = 5;
3202  const uint32_t numUnits = 20;
3203  const uint32_t outputSize = 16;
3204 
3205  armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3206  std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3207  armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3208 
3209  std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3210  armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3211 
3212  std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3213  armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3214 
3215  std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3216  armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3217 
3218  armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3219  std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3220  armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3221 
3222  std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3223  armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3224 
3225  std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3226  armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3227 
3228  std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3229  armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3230 
3231  armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3232  std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3233  armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3234 
3235  std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3236  armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3237 
3238  std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3239  armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3240 
3241  std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3242  armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3243 
3244  std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3245  armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3246 
3247  std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3248  armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3249 
3250  std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3251  armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3252 
3253  armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3254  std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
3255  armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3256 
3257  armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3258  std::vector<float> projectionBiasData(outputSize, 0.f);
3259  armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3260 
3261  armnn::LstmInputParams params;
3262  params.m_InputToForgetWeights = &inputToForgetWeights;
3263  params.m_InputToCellWeights = &inputToCellWeights;
3264  params.m_InputToOutputWeights = &inputToOutputWeights;
3265  params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3266  params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3267  params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3268  params.m_ForgetGateBias = &forgetGateBias;
3269  params.m_CellBias = &cellBias;
3270  params.m_OutputGateBias = &outputGateBias;
3271 
3272  // additional params because: descriptor.m_CifgEnabled = false
3273  params.m_InputToInputWeights = &inputToInputWeights;
3274  params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3275  params.m_CellToInputWeights = &cellToInputWeights;
3276  params.m_InputGateBias = &inputGateBias;
3277 
3278  // additional params because: descriptor.m_ProjectionEnabled = true
3279  params.m_ProjectionWeights = &projectionWeights;
3280  params.m_ProjectionBias = &projectionBias;
3281 
3282  // additional params because: descriptor.m_PeepholeEnabled = true
3283  params.m_CellToForgetWeights = &cellToForgetWeights;
3284  params.m_CellToOutputWeights = &cellToOutputWeights;
3285 
3287  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3288  armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3289  armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3290  const std::string layerName("lstm");
3291  armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3292  armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3293  armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3294  armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3295  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3296 
3297  // connect up
3298  armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3299  armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3300  armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3301  armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3302 
3303  inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3304  inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3305 
3306  outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3307  outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3308 
3309  cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3310  cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3311 
3312  lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3313  lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3314 
3315  lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3316  lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3317 
3318  lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3319  lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3320 
3321  lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3322  lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3323 
3324  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3325  BOOST_CHECK(deserializedNetwork);
3326 
3327  VerifyLstmLayer checker(
3328  layerName,
3329  {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3330  {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3331  descriptor,
3332  params);
3333  deserializedNetwork->Accept(checker);
3334 }
3335 
3336 BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeWithProjectionWithLayerNorm)
3337 {
3338  armnn::LstmDescriptor descriptor;
3339  descriptor.m_ActivationFunc = 4;
3340  descriptor.m_ClippingThresProj = 0.0f;
3341  descriptor.m_ClippingThresCell = 0.0f;
3342  descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
3343  descriptor.m_ProjectionEnabled = true;
3344  descriptor.m_PeepholeEnabled = true;
3345  descriptor.m_LayerNormEnabled = true;
3346 
3347  const uint32_t batchSize = 2;
3348  const uint32_t inputSize = 5;
3349  const uint32_t numUnits = 20;
3350  const uint32_t outputSize = 16;
3351 
3352  armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3353  std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3354  armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3355 
3356  std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3357  armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3358 
3359  std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3360  armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3361 
3362  std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3363  armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3364 
3365  armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3366  std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3367  armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3368 
3369  std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3370  armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3371 
3372  std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3373  armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3374 
3375  std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3376  armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3377 
3378  armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3379  std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3380  armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3381 
3382  std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3383  armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3384 
3385  std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3386  armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3387 
3388  std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3389  armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3390 
3391  std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3392  armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3393 
3394  std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3395  armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3396 
3397  std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3398  armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3399 
3400  armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3401  std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
3402  armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3403 
3404  armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3405  std::vector<float> projectionBiasData(outputSize, 0.f);
3406  armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3407 
3408  std::vector<float> inputLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3409  armnn::ConstTensor inputLayerNormWeights(tensorInfo20, forgetGateBiasData);
3410 
3411  std::vector<float> forgetLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3412  armnn::ConstTensor forgetLayerNormWeights(tensorInfo20, forgetGateBiasData);
3413 
3414  std::vector<float> cellLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3415  armnn::ConstTensor cellLayerNormWeights(tensorInfo20, forgetGateBiasData);
3416 
3417  std::vector<float> outLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3418  armnn::ConstTensor outLayerNormWeights(tensorInfo20, forgetGateBiasData);
3419 
3420  armnn::LstmInputParams params;
3421  params.m_InputToForgetWeights = &inputToForgetWeights;
3422  params.m_InputToCellWeights = &inputToCellWeights;
3423  params.m_InputToOutputWeights = &inputToOutputWeights;
3424  params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3425  params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3426  params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3427  params.m_ForgetGateBias = &forgetGateBias;
3428  params.m_CellBias = &cellBias;
3429  params.m_OutputGateBias = &outputGateBias;
3430 
3431  // additional params because: descriptor.m_CifgEnabled = false
3432  params.m_InputToInputWeights = &inputToInputWeights;
3433  params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3434  params.m_CellToInputWeights = &cellToInputWeights;
3435  params.m_InputGateBias = &inputGateBias;
3436 
3437  // additional params because: descriptor.m_ProjectionEnabled = true
3438  params.m_ProjectionWeights = &projectionWeights;
3439  params.m_ProjectionBias = &projectionBias;
3440 
3441  // additional params because: descriptor.m_PeepholeEnabled = true
3442  params.m_CellToForgetWeights = &cellToForgetWeights;
3443  params.m_CellToOutputWeights = &cellToOutputWeights;
3444 
3445  // additional params because: despriptor.m_LayerNormEnabled = true
3446  params.m_InputLayerNormWeights = &inputLayerNormWeights;
3447  params.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
3448  params.m_CellLayerNormWeights = &cellLayerNormWeights;
3449  params.m_OutputLayerNormWeights = &outLayerNormWeights;
3450 
3452  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3453  armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3454  armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3455  const std::string layerName("lstm");
3456  armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3457  armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3458  armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3459  armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3460  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3461 
3462  // connect up
3463  armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3464  armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3465  armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3466  armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3467 
3468  inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3469  inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3470 
3471  outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3472  outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3473 
3474  cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3475  cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3476 
3477  lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3478  lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3479 
3480  lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3481  lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3482 
3483  lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3484  lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3485 
3486  lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3487  lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3488 
3489  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3490  BOOST_CHECK(deserializedNetwork);
3491 
3492  VerifyLstmLayer checker(
3493  layerName,
3494  {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3495  {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3496  descriptor,
3497  params);
3498  deserializedNetwork->Accept(checker);
3499 }
3500 
3501 BOOST_AUTO_TEST_CASE(EnsureLstmLayersBackwardCompatibility)
3502 {
3503  // The hex data below is a flat buffer containing a lstm layer with no Cifg, with peephole and projection
3504  // enabled. That data was obtained before additional layer normalization parameters where added to the
3505  // lstm serializer. That way it can be tested if a lstm model with the old parameter configuration can
3506  // still be loaded
3507  const std::vector<uint8_t> lstmNoCifgWithPeepholeAndProjectionModel =
3508  {
3509  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
3510  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
3511  0xDC, 0x29, 0x00, 0x00, 0x38, 0x29, 0x00, 0x00, 0xB4, 0x28, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x3C, 0x01,
3512  0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
3513  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
3514  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x70, 0xD6, 0xFF, 0xFF,
3515  0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x06, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x88, 0xD7,
3516  0xFF, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF6, 0xD6, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,
3517  0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
3518  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3519  0xE8, 0xD7, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xC8, 0xD6, 0xFF, 0xFF, 0x00, 0x00,
3520  0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x5E, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xE0, 0xD7, 0xFF, 0xFF,
3521  0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4E, 0xD7, 0xFF, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
3522  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3523  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xD8,
3524  0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
3525  0x04, 0x00, 0x00, 0x00, 0xB6, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x38, 0xD8, 0xFF, 0xFF, 0x08, 0x00,
3526  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA6, 0xD7, 0xFF, 0xFF, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3527  0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3528  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xD8, 0xFF, 0xFF,
3529  0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00,
3530  0x00, 0x00, 0x0E, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x16, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
3531  0xFA, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00,
3532  0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3533  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xD8, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
3534  0x00, 0x00, 0x6C, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
3535  0x12, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xE0, 0x25, 0x00, 0x00, 0xD0, 0x25,
3536  0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x48, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00,
3537  0x10, 0x00, 0x14, 0x00, 0x18, 0x00, 0x1C, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2C, 0x00, 0x30, 0x00,
3538  0x34, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x40, 0x00, 0x44, 0x00, 0x26, 0x00, 0x00, 0x00, 0xC4, 0x23, 0x00, 0x00,
3539  0xF8, 0x21, 0x00, 0x00, 0x2C, 0x20, 0x00, 0x00, 0xF0, 0x1A, 0x00, 0x00, 0xB4, 0x15, 0x00, 0x00, 0x78, 0x10,
3540  0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x68, 0x0F, 0x00, 0x00, 0xE0, 0x0E, 0x00, 0x00, 0x14, 0x0D, 0x00, 0x00,
3541  0xD8, 0x07, 0x00, 0x00, 0x50, 0x07, 0x00, 0x00, 0xC8, 0x06, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x14, 0x01,
3542  0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xEE, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3543  0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00,
3544  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3545  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3546  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3547  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3548  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3549  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x72, 0xD8,
3550  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x82, 0xD9, 0xFF, 0xFF,
3551  0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3552  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3553  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3554  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3555  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xD8,
3556  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3557  0x14, 0x00, 0x00, 0x00, 0xF6, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x54, 0x00, 0x00, 0x00, 0x04, 0x00,
3558  0x00, 0x00, 0x06, 0xDA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3559  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3560  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3561  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3562  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xD9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3563  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6A, 0xD9, 0xFF, 0xFF, 0x00, 0x00,
3564  0x00, 0x03, 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7A, 0xDA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
3565  0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3566  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3567  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3568  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3569  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3570  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3571  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3572  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3573  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3574  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3575  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3576  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3577  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3578  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3579  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3580  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3581  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3582  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3583  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3584  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3585  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3586  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3587  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3588  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3589  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3590  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3591  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3592  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3593  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3594  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3595  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3596  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3597  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3598  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3599  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3600  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3601  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3602  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3603  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3604  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3605  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3606  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3607  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3608  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3609  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3610  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3611  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3612  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3613  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3614  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3615  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3616  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3617  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3618  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3619  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3620  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3621  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3622  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3623  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3624  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3625  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3626  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3627  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3628  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3629  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3630  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3631  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3632  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3633  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3634  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3635  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3636  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xDE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3637  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xA2, 0xDE,
3638  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB2, 0xDF, 0xFF, 0xFF,
3639  0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3640  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3641  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3642  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3643  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xDF,
3644  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3645  0x14, 0x00, 0x00, 0x00, 0x26, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00,
3646  0x00, 0x00, 0x36, 0xE0, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3647  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3648  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3649  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3650  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3651  0x00, 0x00, 0x00, 0x00, 0x92, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3652  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xAA, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3653  0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xBA, 0xE0, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01,
3654  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3655  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3656  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3657  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3658  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3659  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3660  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3661  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3662  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3663  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3664  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3665  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3666  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3667  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3668  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3669  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3670  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3671  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3672  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3673  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3674  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3675  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3676  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3677  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3678  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3679  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3680  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3681  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3682  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3683  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3684  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3685  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3686  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3687  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3688  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3689  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3690  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3691  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3692  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3693  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3694  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3695  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3696  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3697  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3698  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3699  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3700  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3701  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3702  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3703  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3704  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3705  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3706  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3707  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3708  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3709  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3710  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3711  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3712  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3713  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3714  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3715  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3716  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3717  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3718  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3719  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3720  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3721  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3722  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3723  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3724  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3725  0x00, 0x00, 0x00, 0x00, 0xC6, 0xE4, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3726  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xE2, 0xE4, 0xFF, 0xFF,
3727  0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xE5, 0xFF, 0xFF, 0x04, 0x00,
3728  0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3729  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3730  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3731  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3732  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3733  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3734  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3735  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3736  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3737  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3738  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3739  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3740  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3741  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3742  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3743  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3744  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3745  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3746  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3747  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3748  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3749  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3750  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xE6, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3751  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00,
3752  0x00, 0x00, 0xAA, 0xE6, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3753  0xBA, 0xE7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3754  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3755  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3756  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3757  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3758  0x00, 0x00, 0x16, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3759  0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x2E, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00,
3760  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3E, 0xE8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
3761  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3762  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3763  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3764  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3765  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3766  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xB2, 0xE7, 0xFF, 0xFF,
3767  0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC2, 0xE8, 0xFF, 0xFF, 0x04, 0x00,
3768  0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3769  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3770  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3771  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3772  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xE8, 0xFF, 0xFF,
3773  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00,
3774  0x00, 0x00, 0x36, 0xE8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3775  0x46, 0xE9, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3776  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3777  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3778  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3779  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3780  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3781  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3782  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3783  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3784  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3785  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3786  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3787  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3788  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3789  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3790  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3791  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3792  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3793  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3794  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3795  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3796  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3797  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3798  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3799  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3800  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3801  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3802  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3803  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3804  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3805  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3806  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3807  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3808  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3809  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3810  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3811  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3812  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3813  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3814  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3815  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3816  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3817  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3818  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3819  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3820  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3821  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3822  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3823  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3824  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3825  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3826  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3827  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3828  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3829  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3830  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3831  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3832  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3833  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3834  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3835  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3836  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3837  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3838  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3839  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3840  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3841  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3842  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3843  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3844  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3845  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3846  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xED, 0xFF, 0xFF,
3847  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00,
3848  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6E, 0xED, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x14, 0x05, 0x00, 0x00,
3849  0x04, 0x00, 0x00, 0x00, 0x7E, 0xEE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00,
3850  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3851  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3852  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3853  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3854  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3855  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3856  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3857  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3858  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3859  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3860  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3861  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3862  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3863  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3864  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3865  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3866  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3867  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3868  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3869  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3870  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3871  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3872  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3873  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3874  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3875  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3876  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3877  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3878  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3879  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3880  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3881  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3882  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3883  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3884  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3885  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3886  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3887  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3888  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3889  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3890  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3891  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3892  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3893  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3894  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3895  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3896  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3897  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3898  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3899  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3900  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3901  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3902  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3903  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3904  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3905  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3906  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3907  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3908  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3909  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3910  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3911  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3912  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3913  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3914  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3915  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3916  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3917  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3918  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3919  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3920  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3921  0x8A, 0xF2, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3922  0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xA6, 0xF2, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3923  0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB6, 0xF3, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01,
3924  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3925  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3926  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3927  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3928  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3929  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3930  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3931  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3932  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3933  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3934  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3935  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3936  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3937  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3938  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3939  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3940  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3941  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3942  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3943  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3944  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3945  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3946  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3947  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3948  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3949  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3950  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3951  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3952  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3953  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3954  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3955  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3956  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3957  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3958  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3959  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3960  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3961  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3962  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3963  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3964  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3965  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3966  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3967  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3968  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3969  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3970  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3971  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3972  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3973  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3974  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3975  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3976  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3977  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3978  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3979  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3980  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3981  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3982  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3983  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3984  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3985  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3986  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3987  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3988  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3989  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3990  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3991  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3992  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3993  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3994  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3995  0x00, 0x00, 0x00, 0x00, 0xC2, 0xF7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3996  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xDE, 0xF7, 0xFF, 0xFF,
3997  0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xEE, 0xF8, 0xFF, 0xFF, 0x04, 0x00,
3998  0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3999  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4000  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4001  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4002  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4003  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4004  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4005  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4006  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4007  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4008  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4009  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4010  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4011  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4012  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4013  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4014  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4015  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4016  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4017  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4018  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4019  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4020  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xF9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
4021  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00,
4022  0x00, 0x00, 0xA6, 0xF9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
4023  0xB6, 0xFA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4024  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4025  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4026  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4027  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4028  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4029  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4030  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4031  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4032  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4033  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4034  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4035  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4036  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4037  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4038  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4039  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4040  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4041  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4042  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4043  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4044  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4045  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xFB,
4046  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
4047  0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x6E, 0xFB, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01,
4048  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7E, 0xFC, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
4049  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4050  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4051  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4052  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4053  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4054  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4055  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4056  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4057  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4058  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4059  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4060  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4061  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4062  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4063  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4064  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4065  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4066  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4067  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4068  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4069  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4070  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4071  0x00, 0x00, 0x00, 0x00, 0x1A, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
4072  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0C, 0x00,
4073  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
4074  0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x2E, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
4075  0x22, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6C, 0x73,
4076  0x74, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00,
4077  0xB4, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x30, 0x00,
4078  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
4079  0xA6, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
4080  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3C, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
4081  0x04, 0x00, 0x00, 0x00, 0xCE, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
4082  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x64, 0xFF, 0xFF, 0xFF,
4083  0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
4084  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
4085  0xB4, 0xFE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x1A, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
4086  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
4087  0xF0, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
4088  0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
4089  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
4090  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00,
4091  0x7E, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00,
4092  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x76, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
4093  0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
4094  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
4095  0x68, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xCE, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
4096  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
4097  0x08, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00,
4098  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
4099  0x08, 0x00, 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00,
4100  0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00,
4101  0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
4102  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4103  0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
4104  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6E, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
4105  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00,
4106  0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00,
4107  0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00,
4108  0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
4109  0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
4110  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4111  0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
4112  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00,
4113  0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
4114  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00
4115  };
4116 
4117  armnn::INetworkPtr deserializedNetwork =
4118  DeserializeNetwork(std::string(lstmNoCifgWithPeepholeAndProjectionModel.begin(),
4119  lstmNoCifgWithPeepholeAndProjectionModel.end()));
4120 
4121  BOOST_CHECK(deserializedNetwork);
4122 
4123  // generating the same model parameters which where used to serialize the model (Layer norm is not specified)
4124  armnn::LstmDescriptor descriptor;
4125  descriptor.m_ActivationFunc = 4;
4126  descriptor.m_ClippingThresProj = 0.0f;
4127  descriptor.m_ClippingThresCell = 0.0f;
4128  descriptor.m_CifgEnabled = false;
4129  descriptor.m_ProjectionEnabled = true;
4130  descriptor.m_PeepholeEnabled = true;
4131 
4132  const uint32_t batchSize = 2u;
4133  const uint32_t inputSize = 5u;
4134  const uint32_t numUnits = 20u;
4135  const uint32_t outputSize = 16u;
4136 
4137  armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
4138  std::vector<float> inputToInputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
4139  armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
4140 
4141  std::vector<float> inputToForgetWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
4142  armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
4143 
4144  std::vector<float> inputToCellWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
4145  armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
4146 
4147  std::vector<float> inputToOutputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
4148  armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
4149 
4150  armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
4151  std::vector<float> inputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
4152  armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
4153 
4154  std::vector<float> forgetGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
4155  armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
4156 
4157  std::vector<float> cellBiasData(tensorInfo20.GetNumElements(), 0.0f);
4158  armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
4159 
4160  std::vector<float> outputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
4161  armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
4162 
4163  armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
4164  std::vector<float> recurrentToInputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
4165  armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
4166 
4167  std::vector<float> recurrentToForgetWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
4168  armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
4169 
4170  std::vector<float> recurrentToCellWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
4171  armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
4172 
4173  std::vector<float> recurrentToOutputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
4174  armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
4175 
4176  std::vector<float> cellToInputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
4177  armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
4178 
4179  std::vector<float> cellToForgetWeightsData(tensorInfo20.GetNumElements(), 0.0f);
4180  armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
4181 
4182  std::vector<float> cellToOutputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
4183  armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
4184 
4185  armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
4186  std::vector<float> projectionWeightsData(tensorInfo16x20.GetNumElements(), 0.0f);
4187  armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
4188 
4189  armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
4190  std::vector<float> projectionBiasData(outputSize, 0.0f);
4191  armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
4192 
4193  armnn::LstmInputParams params;
4194  params.m_InputToForgetWeights = &inputToForgetWeights;
4195  params.m_InputToCellWeights = &inputToCellWeights;
4196  params.m_InputToOutputWeights = &inputToOutputWeights;
4197  params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4198  params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4199  params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4200  params.m_ForgetGateBias = &forgetGateBias;
4201  params.m_CellBias = &cellBias;
4202  params.m_OutputGateBias = &outputGateBias;
4203 
4204  // additional params because: descriptor.m_CifgEnabled = false
4205  params.m_InputToInputWeights = &inputToInputWeights;
4206  params.m_RecurrentToInputWeights = &recurrentToInputWeights;
4207  params.m_CellToInputWeights = &cellToInputWeights;
4208  params.m_InputGateBias = &inputGateBias;
4209 
4210  // additional params because: descriptor.m_ProjectionEnabled = true
4211  params.m_ProjectionWeights = &projectionWeights;
4212  params.m_ProjectionBias = &projectionBias;
4213 
4214  // additional params because: descriptor.m_PeepholeEnabled = true
4215  params.m_CellToForgetWeights = &cellToForgetWeights;
4216  params.m_CellToOutputWeights = &cellToOutputWeights;
4217 
4218  const std::string layerName("lstm");
4219  armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
4220  armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
4221  armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
4222  armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
4223 
4224  VerifyLstmLayer checker(
4225  layerName,
4226  {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
4227  {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
4228  descriptor,
4229  params);
4230  deserializedNetwork->Accept(checker);
4231 }
4232 class VerifyQuantizedLstmLayer : public LayerVerifierBase
4233 {
4234 
4235 public:
4236  VerifyQuantizedLstmLayer(const std::string& layerName,
4237  const std::vector<armnn::TensorInfo>& inputInfos,
4238  const std::vector<armnn::TensorInfo>& outputInfos,
4239  const armnn::QuantizedLstmInputParams& inputParams)
4240  : LayerVerifierBase(layerName, inputInfos, outputInfos), m_InputParams(inputParams) {}
4241 
4242  void VisitQuantizedLstmLayer(const armnn::IConnectableLayer* layer,
4243  const armnn::QuantizedLstmInputParams& params,
4244  const char* name)
4245  {
4246  VerifyNameAndConnections(layer, name);
4247  VerifyInputParameters(params);
4248  }
4249 
4250 protected:
4251  void VerifyInputParameters(const armnn::QuantizedLstmInputParams& params)
4252  {
4253  VerifyConstTensors("m_InputToInputWeights",
4254  m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
4255  VerifyConstTensors("m_InputToForgetWeights",
4256  m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
4257  VerifyConstTensors("m_InputToCellWeights",
4258  m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
4259  VerifyConstTensors("m_InputToOutputWeights",
4260  m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
4261  VerifyConstTensors("m_RecurrentToInputWeights",
4262  m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
4263  VerifyConstTensors("m_RecurrentToForgetWeights",
4264  m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
4265  VerifyConstTensors("m_RecurrentToCellWeights",
4266  m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
4267  VerifyConstTensors("m_RecurrentToOutputWeights",
4268  m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
4269  VerifyConstTensors("m_InputGateBias",
4270  m_InputParams.m_InputGateBias, params.m_InputGateBias);
4271  VerifyConstTensors("m_ForgetGateBias",
4272  m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
4273  VerifyConstTensors("m_CellBias",
4274  m_InputParams.m_CellBias, params.m_CellBias);
4275  VerifyConstTensors("m_OutputGateBias",
4276  m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
4277  }
4278 
4279 private:
4280  armnn::QuantizedLstmInputParams m_InputParams;
4281 };
4282 
4283 BOOST_AUTO_TEST_CASE(SerializeDeserializeQuantizedLstm)
4284 {
4285  const uint32_t batchSize = 1;
4286  const uint32_t inputSize = 2;
4287  const uint32_t numUnits = 4;
4288  const uint32_t outputSize = numUnits;
4289 
4290  // Scale/Offset for input/output, cellState In/Out, weights, bias
4291  float inputOutputScale = 0.0078125f;
4292  int32_t inputOutputOffset = 128;
4293 
4294  float cellStateScale = 0.00048828125f;
4295  int32_t cellStateOffset = 0;
4296 
4297  float weightsScale = 0.00408021f;
4298  int32_t weightsOffset = 100;
4299 
4300  float biasScale = 3.1876640625e-05f;
4301  int32_t biasOffset = 0;
4302 
4303  // The shape of weight data is {outputSize, inputSize} = {4, 2}
4304  armnn::TensorShape inputToInputWeightsShape = {4, 2};
4305  std::vector<uint8_t> inputToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4306  armnn::TensorInfo inputToInputWeightsInfo(inputToInputWeightsShape,
4308  weightsScale,
4309  weightsOffset);
4310  armnn::ConstTensor inputToInputWeights(inputToInputWeightsInfo, inputToInputWeightsData);
4311 
4312  armnn::TensorShape inputToForgetWeightsShape = {4, 2};
4313  std::vector<uint8_t> inputToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4314  armnn::TensorInfo inputToForgetWeightsInfo(inputToForgetWeightsShape,
4316  weightsScale,
4317  weightsOffset);
4318  armnn::ConstTensor inputToForgetWeights(inputToForgetWeightsInfo, inputToForgetWeightsData);
4319 
4320  armnn::TensorShape inputToCellWeightsShape = {4, 2};
4321  std::vector<uint8_t> inputToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4322  armnn::TensorInfo inputToCellWeightsInfo(inputToCellWeightsShape,
4324  weightsScale,
4325  weightsOffset);
4326  armnn::ConstTensor inputToCellWeights(inputToCellWeightsInfo, inputToCellWeightsData);
4327 
4328  armnn::TensorShape inputToOutputWeightsShape = {4, 2};
4329  std::vector<uint8_t> inputToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4330  armnn::TensorInfo inputToOutputWeightsInfo(inputToOutputWeightsShape,
4332  weightsScale,
4333  weightsOffset);
4334  armnn::ConstTensor inputToOutputWeights(inputToOutputWeightsInfo, inputToOutputWeightsData);
4335 
4336  // The shape of recurrent weight data is {outputSize, outputSize} = {4, 4}
4337  armnn::TensorShape recurrentToInputWeightsShape = {4, 4};
4338  std::vector<uint8_t> recurrentToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4339  armnn::TensorInfo recurrentToInputWeightsInfo(recurrentToInputWeightsShape,
4341  weightsScale,
4342  weightsOffset);
4343  armnn::ConstTensor recurrentToInputWeights(recurrentToInputWeightsInfo, recurrentToInputWeightsData);
4344 
4345  armnn::TensorShape recurrentToForgetWeightsShape = {4, 4};
4346  std::vector<uint8_t> recurrentToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4347  armnn::TensorInfo recurrentToForgetWeightsInfo(recurrentToForgetWeightsShape,
4349  weightsScale,
4350  weightsOffset);
4351  armnn::ConstTensor recurrentToForgetWeights(recurrentToForgetWeightsInfo, recurrentToForgetWeightsData);
4352 
4353  armnn::TensorShape recurrentToCellWeightsShape = {4, 4};
4354  std::vector<uint8_t> recurrentToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4355  armnn::TensorInfo recurrentToCellWeightsInfo(recurrentToCellWeightsShape,
4357  weightsScale,
4358  weightsOffset);
4359  armnn::ConstTensor recurrentToCellWeights(recurrentToCellWeightsInfo, recurrentToCellWeightsData);
4360 
4361  armnn::TensorShape recurrentToOutputWeightsShape = {4, 4};
4362  std::vector<uint8_t> recurrentToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4363  armnn::TensorInfo recurrentToOutputWeightsInfo(recurrentToOutputWeightsShape,
4365  weightsScale,
4366  weightsOffset);
4367  armnn::ConstTensor recurrentToOutputWeights(recurrentToOutputWeightsInfo, recurrentToOutputWeightsData);
4368 
4369  // The shape of bias data is {outputSize} = {4}
4370  armnn::TensorShape inputGateBiasShape = {4};
4371  std::vector<int32_t> inputGateBiasData = {1, 2, 3, 4};
4372  armnn::TensorInfo inputGateBiasInfo(inputGateBiasShape,
4374  biasScale,
4375  biasOffset);
4376  armnn::ConstTensor inputGateBias(inputGateBiasInfo, inputGateBiasData);
4377 
4378  armnn::TensorShape forgetGateBiasShape = {4};
4379  std::vector<int32_t> forgetGateBiasData = {1, 2, 3, 4};
4380  armnn::TensorInfo forgetGateBiasInfo(forgetGateBiasShape,
4382  biasScale,
4383  biasOffset);
4384  armnn::ConstTensor forgetGateBias(forgetGateBiasInfo, forgetGateBiasData);
4385 
4386  armnn::TensorShape cellBiasShape = {4};
4387  std::vector<int32_t> cellBiasData = {1, 2, 3, 4};
4388  armnn::TensorInfo cellBiasInfo(cellBiasShape,
4390  biasScale,
4391  biasOffset);
4392  armnn::ConstTensor cellBias(cellBiasInfo, cellBiasData);
4393 
4394  armnn::TensorShape outputGateBiasShape = {4};
4395  std::vector<int32_t> outputGateBiasData = {1, 2, 3, 4};
4396  armnn::TensorInfo outputGateBiasInfo(outputGateBiasShape,
4398  biasScale,
4399  biasOffset);
4400  armnn::ConstTensor outputGateBias(outputGateBiasInfo, outputGateBiasData);
4401 
4403  params.m_InputToInputWeights = &inputToInputWeights;
4404  params.m_InputToForgetWeights = &inputToForgetWeights;
4405  params.m_InputToCellWeights = &inputToCellWeights;
4406  params.m_InputToOutputWeights = &inputToOutputWeights;
4407  params.m_RecurrentToInputWeights = &recurrentToInputWeights;
4408  params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4409  params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4410  params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4411  params.m_InputGateBias = &inputGateBias;
4412  params.m_ForgetGateBias = &forgetGateBias;
4413  params.m_CellBias = &cellBias;
4414  params.m_OutputGateBias = &outputGateBias;
4415 
4417  armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
4418  armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
4419  armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
4420  const std::string layerName("QuantizedLstm");
4421  armnn::IConnectableLayer* const quantizedLstmLayer = network->AddQuantizedLstmLayer(params, layerName.c_str());
4422  armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(0);
4423  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(1);
4424 
4425  // Connect up
4426  armnn::TensorInfo inputTensorInfo({ batchSize, inputSize },
4428  inputOutputScale,
4429  inputOutputOffset);
4430  armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits },
4432  cellStateScale,
4433  cellStateOffset);
4434  armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize },
4436  inputOutputScale,
4437  inputOutputOffset);
4438 
4439  inputLayer->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(0));
4440  inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
4441 
4442  cellStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(1));
4443  cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
4444 
4445  outputStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(2));
4446  outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
4447 
4448  quantizedLstmLayer->GetOutputSlot(0).Connect(cellStateOut->GetInputSlot(0));
4449  quantizedLstmLayer->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
4450 
4451  quantizedLstmLayer->GetOutputSlot(1).Connect(outputLayer->GetInputSlot(0));
4452  quantizedLstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
4453 
4454  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
4455  BOOST_CHECK(deserializedNetwork);
4456 
4457  VerifyQuantizedLstmLayer checker(layerName,
4458  {inputTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
4459  {cellStateTensorInfo, outputStateTensorInfo},
4460  params);
4461 
4462  deserializedNetwork->Accept(checker);
4463 }
4464 
4465 class VerifyQLstmLayer : public LayerVerifierBaseWithDescriptor<armnn::QLstmDescriptor>
4466 {
4467 public:
4468  VerifyQLstmLayer(const std::string& layerName,
4469  const std::vector<armnn::TensorInfo>& inputInfos,
4470  const std::vector<armnn::TensorInfo>& outputInfos,
4471  const armnn::QLstmDescriptor& descriptor,
4472  const armnn::LstmInputParams& inputParams)
4473  : LayerVerifierBaseWithDescriptor<armnn::QLstmDescriptor>(layerName, inputInfos, outputInfos, descriptor)
4474  , m_InputParams(inputParams) {}
4475 
4476  void VisitQLstmLayer(const armnn::IConnectableLayer* layer,
4477  const armnn::QLstmDescriptor& descriptor,
4478  const armnn::LstmInputParams& params,
4479  const char* name)
4480  {
4481  VerifyNameAndConnections(layer, name);
4482  VerifyDescriptor(descriptor);
4483  VerifyInputParameters(params);
4484  }
4485 
4486 protected:
4487  void VerifyInputParameters(const armnn::LstmInputParams& params)
4488  {
4489  VerifyConstTensors(
4490  "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
4491  VerifyConstTensors(
4492  "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
4493  VerifyConstTensors(
4494  "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
4495  VerifyConstTensors(
4496  "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
4497  VerifyConstTensors(
4498  "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
4499  VerifyConstTensors(
4500  "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
4501  VerifyConstTensors(
4502  "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
4503  VerifyConstTensors(
4504  "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
4505  VerifyConstTensors(
4506  "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
4507  VerifyConstTensors(
4508  "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
4509  VerifyConstTensors(
4510  "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
4511  VerifyConstTensors(
4512  "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
4513  VerifyConstTensors(
4514  "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
4515  VerifyConstTensors(
4516  "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
4517  VerifyConstTensors(
4518  "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
4519  VerifyConstTensors(
4520  "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
4521  VerifyConstTensors(
4522  "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
4523  VerifyConstTensors(
4524  "m_InputLayerNormWeights", m_InputParams.m_InputLayerNormWeights, params.m_InputLayerNormWeights);
4525  VerifyConstTensors(
4526  "m_ForgetLayerNormWeights", m_InputParams.m_ForgetLayerNormWeights, params.m_ForgetLayerNormWeights);
4527  VerifyConstTensors(
4528  "m_CellLayerNormWeights", m_InputParams.m_CellLayerNormWeights, params.m_CellLayerNormWeights);
4529  VerifyConstTensors(
4530  "m_OutputLayerNormWeights", m_InputParams.m_OutputLayerNormWeights, params.m_OutputLayerNormWeights);
4531  }
4532 
4533 private:
4534  armnn::LstmInputParams m_InputParams;
4535 };
4536 
4537 BOOST_AUTO_TEST_CASE(SerializeDeserializeQLstmBasic)
4538 {
4539  armnn::QLstmDescriptor descriptor;
4540 
4541  descriptor.m_CifgEnabled = true;
4542  descriptor.m_ProjectionEnabled = false;
4543  descriptor.m_PeepholeEnabled = false;
4544  descriptor.m_LayerNormEnabled = false;
4545 
4546  descriptor.m_CellClip = 0.0f;
4547  descriptor.m_ProjectionClip = 0.0f;
4548 
4549  descriptor.m_InputIntermediateScale = 0.00001f;
4550  descriptor.m_ForgetIntermediateScale = 0.00001f;
4551  descriptor.m_CellIntermediateScale = 0.00001f;
4552  descriptor.m_OutputIntermediateScale = 0.00001f;
4553 
4554  descriptor.m_HiddenStateScale = 0.07f;
4555  descriptor.m_HiddenStateZeroPoint = 0;
4556 
4557  const unsigned int numBatches = 2;
4558  const unsigned int inputSize = 5;
4559  const unsigned int outputSize = 4;
4560  const unsigned int numUnits = 4;
4561 
4562  // Scale/Offset quantization info
4563  float inputScale = 0.0078f;
4564  int32_t inputOffset = 0;
4565 
4566  float outputScale = 0.0078f;
4567  int32_t outputOffset = 0;
4568 
4569  float cellStateScale = 3.5002e-05f;
4570  int32_t cellStateOffset = 0;
4571 
4572  float weightsScale = 0.007f;
4573  int32_t weightsOffset = 0;
4574 
4575  float biasScale = 3.5002e-05f / 1024;
4576  int32_t biasOffset = 0;
4577 
4578  // Weights and bias tensor and quantization info
4579  armnn::TensorInfo inputWeightsInfo({numUnits, inputSize},
4581  weightsScale,
4582  weightsOffset);
4583 
4584  armnn::TensorInfo recurrentWeightsInfo({numUnits, outputSize},
4586  weightsScale,
4587  weightsOffset);
4588 
4589  armnn::TensorInfo biasInfo({numUnits}, armnn::DataType::Signed32, biasScale, biasOffset);
4590 
4591  std::vector<int8_t> inputToForgetWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4592  std::vector<int8_t> inputToCellWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4593  std::vector<int8_t> inputToOutputWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4594 
4595  armnn::ConstTensor inputToForgetWeights(inputWeightsInfo, inputToForgetWeightsData);
4596  armnn::ConstTensor inputToCellWeights(inputWeightsInfo, inputToCellWeightsData);
4597  armnn::ConstTensor inputToOutputWeights(inputWeightsInfo, inputToOutputWeightsData);
4598 
4599  std::vector<int8_t> recurrentToForgetWeightsData =
4600  GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4601  std::vector<int8_t> recurrentToCellWeightsData =
4602  GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4603  std::vector<int8_t> recurrentToOutputWeightsData =
4604  GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4605 
4606  armnn::ConstTensor recurrentToForgetWeights(recurrentWeightsInfo, recurrentToForgetWeightsData);
4607  armnn::ConstTensor recurrentToCellWeights(recurrentWeightsInfo, recurrentToCellWeightsData);
4608  armnn::ConstTensor recurrentToOutputWeights(recurrentWeightsInfo, recurrentToOutputWeightsData);
4609 
4610  std::vector<int32_t> forgetGateBiasData(numUnits, 1);
4611  std::vector<int32_t> cellBiasData(numUnits, 0);
4612  std::vector<int32_t> outputGateBiasData(numUnits, 0);
4613 
4614  armnn::ConstTensor forgetGateBias(biasInfo, forgetGateBiasData);
4615  armnn::ConstTensor cellBias(biasInfo, cellBiasData);
4616  armnn::ConstTensor outputGateBias(biasInfo, outputGateBiasData);
4617 
4618  // Set up params
4619  armnn::LstmInputParams params;
4620  params.m_InputToForgetWeights = &inputToForgetWeights;
4621  params.m_InputToCellWeights = &inputToCellWeights;
4622  params.m_InputToOutputWeights = &inputToOutputWeights;
4623 
4624  params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4625  params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4626  params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4627 
4628  params.m_ForgetGateBias = &forgetGateBias;
4629  params.m_CellBias = &cellBias;
4630  params.m_OutputGateBias = &outputGateBias;
4631 
4632  // Create network
4634  const std::string layerName("qLstm");
4635 
4636  armnn::IConnectableLayer* const input = network->AddInputLayer(0);
4637  armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(1);
4638  armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(2);
4639 
4640  armnn::IConnectableLayer* const qLstmLayer = network->AddQLstmLayer(descriptor, params, layerName.c_str());
4641 
4642  armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(0);
4643  armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(1);
4644  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(2);
4645 
4646  // Input/Output tensor info
4647  armnn::TensorInfo inputInfo({numBatches , inputSize},
4649  inputScale,
4650  inputOffset);
4651 
4652  armnn::TensorInfo cellStateInfo({numBatches , numUnits},
4654  cellStateScale,
4655  cellStateOffset);
4656 
4657  armnn::TensorInfo outputStateInfo({numBatches , outputSize},
4659  outputScale,
4660  outputOffset);
4661 
4662  // Connect input/output slots
4663  input->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(0));
4664  input->GetOutputSlot(0).SetTensorInfo(inputInfo);
4665 
4666  outputStateIn->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(1));
4667  outputStateIn->GetOutputSlot(0).SetTensorInfo(cellStateInfo);
4668 
4669  cellStateIn->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(2));
4670  cellStateIn->GetOutputSlot(0).SetTensorInfo(outputStateInfo);
4671 
4672  qLstmLayer->GetOutputSlot(0).Connect(outputStateOut->GetInputSlot(0));
4673  qLstmLayer->GetOutputSlot(0).SetTensorInfo(outputStateInfo);
4674 
4675  qLstmLayer->GetOutputSlot(1).Connect(cellStateOut->GetInputSlot(0));
4676  qLstmLayer->GetOutputSlot(1).SetTensorInfo(cellStateInfo);
4677 
4678  qLstmLayer->GetOutputSlot(2).Connect(outputLayer->GetInputSlot(0));
4679  qLstmLayer->GetOutputSlot(2).SetTensorInfo(outputStateInfo);
4680 
4681  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
4682  BOOST_CHECK(deserializedNetwork);
4683 
4684  VerifyQLstmLayer checker(layerName,
4685  {inputInfo, cellStateInfo, outputStateInfo},
4686  {outputStateInfo, cellStateInfo, outputStateInfo},
4687  descriptor,
4688  params);
4689 
4690  deserializedNetwork->Accept(checker);
4691 }
4692 
4693 BOOST_AUTO_TEST_CASE(SerializeDeserializeQLstmCifgLayerNorm)
4694 {
4695  armnn::QLstmDescriptor descriptor;
4696 
4697  // CIFG params are used when CIFG is disabled
4698  descriptor.m_CifgEnabled = true;
4699  descriptor.m_ProjectionEnabled = false;
4700  descriptor.m_PeepholeEnabled = false;
4701  descriptor.m_LayerNormEnabled = true;
4702 
4703  descriptor.m_CellClip = 0.0f;
4704  descriptor.m_ProjectionClip = 0.0f;
4705 
4706  descriptor.m_InputIntermediateScale = 0.00001f;
4707  descriptor.m_ForgetIntermediateScale = 0.00001f;
4708  descriptor.m_CellIntermediateScale = 0.00001f;
4709  descriptor.m_OutputIntermediateScale = 0.00001f;
4710 
4711  descriptor.m_HiddenStateScale = 0.07f;
4712  descriptor.m_HiddenStateZeroPoint = 0;
4713 
4714  const unsigned int numBatches = 2;
4715  const unsigned int inputSize = 5;
4716  const unsigned int outputSize = 4;
4717  const unsigned int numUnits = 4;
4718 
4719  // Scale/Offset quantization info
4720  float inputScale = 0.0078f;
4721  int32_t inputOffset = 0;
4722 
4723  float outputScale = 0.0078f;
4724  int32_t outputOffset = 0;
4725 
4726  float cellStateScale = 3.5002e-05f;
4727  int32_t cellStateOffset = 0;
4728 
4729  float weightsScale = 0.007f;
4730  int32_t weightsOffset = 0;
4731 
4732  float layerNormScale = 3.5002e-05f;
4733  int32_t layerNormOffset = 0;
4734 
4735  float biasScale = layerNormScale / 1024;
4736  int32_t biasOffset = 0;
4737 
4738  // Weights and bias tensor and quantization info
4739  armnn::TensorInfo inputWeightsInfo({numUnits, inputSize},
4741  weightsScale,
4742  weightsOffset);
4743 
4744  armnn::TensorInfo recurrentWeightsInfo({numUnits, outputSize},
4746  weightsScale,
4747  weightsOffset);
4748 
4749  armnn::TensorInfo biasInfo({numUnits},
4751  biasScale,
4752  biasOffset);
4753 
4754  armnn::TensorInfo layerNormWeightsInfo({numUnits},
4756  layerNormScale,
4757  layerNormOffset);
4758 
4759  // Mandatory params
4760  std::vector<int8_t> inputToForgetWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4761  std::vector<int8_t> inputToCellWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4762  std::vector<int8_t> inputToOutputWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4763 
4764  armnn::ConstTensor inputToForgetWeights(inputWeightsInfo, inputToForgetWeightsData);
4765  armnn::ConstTensor inputToCellWeights(inputWeightsInfo, inputToCellWeightsData);
4766  armnn::ConstTensor inputToOutputWeights(inputWeightsInfo, inputToOutputWeightsData);
4767 
4768  std::vector<int8_t> recurrentToForgetWeightsData =
4769  GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4770  std::vector<int8_t> recurrentToCellWeightsData =
4771  GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4772  std::vector<int8_t> recurrentToOutputWeightsData =
4773  GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4774 
4775  armnn::ConstTensor recurrentToForgetWeights(recurrentWeightsInfo, recurrentToForgetWeightsData);
4776  armnn::ConstTensor recurrentToCellWeights(recurrentWeightsInfo, recurrentToCellWeightsData);
4777  armnn::ConstTensor recurrentToOutputWeights(recurrentWeightsInfo, recurrentToOutputWeightsData);
4778 
4779  std::vector<int32_t> forgetGateBiasData(numUnits, 1);
4780  std::vector<int32_t> cellBiasData(numUnits, 0);
4781  std::vector<int32_t> outputGateBiasData(numUnits, 0);
4782 
4783  armnn::ConstTensor forgetGateBias(biasInfo, forgetGateBiasData);
4784  armnn::ConstTensor cellBias(biasInfo, cellBiasData);
4785  armnn::ConstTensor outputGateBias(biasInfo, outputGateBiasData);
4786 
4787  // Layer Norm
4788  std::vector<int16_t> forgetLayerNormWeightsData =
4789  GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
4790  std::vector<int16_t> cellLayerNormWeightsData =
4791  GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
4792  std::vector<int16_t> outputLayerNormWeightsData =
4793  GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
4794 
4795  armnn::ConstTensor forgetLayerNormWeights(layerNormWeightsInfo, forgetLayerNormWeightsData);
4796  armnn::ConstTensor cellLayerNormWeights(layerNormWeightsInfo, cellLayerNormWeightsData);
4797  armnn::ConstTensor outputLayerNormWeights(layerNormWeightsInfo, outputLayerNormWeightsData);
4798 
4799  // Set up params
4800  armnn::LstmInputParams params;
4801 
4802  // Mandatory params
4803  params.m_InputToForgetWeights = &inputToForgetWeights;
4804  params.m_InputToCellWeights = &inputToCellWeights;
4805  params.m_InputToOutputWeights = &inputToOutputWeights;
4806 
4807  params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4808  params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4809  params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4810 
4811  params.m_ForgetGateBias = &forgetGateBias;
4812  params.m_CellBias = &cellBias;
4813  params.m_OutputGateBias = &outputGateBias;
4814 
4815  // Layer Norm
4816  params.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
4817  params.m_CellLayerNormWeights = &cellLayerNormWeights;
4818  params.m_OutputLayerNormWeights = &outputLayerNormWeights;
4819 
4820  // Create network
4822  const std::string layerName("qLstm");
4823 
4824  armnn::IConnectableLayer* const input = network->AddInputLayer(0);
4825  armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(1);
4826  armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(2);
4827 
4828  armnn::IConnectableLayer* const qLstmLayer = network->AddQLstmLayer(descriptor, params, layerName.c_str());
4829 
4830  armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(0);
4831  armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(1);
4832  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(2);
4833 
4834  // Input/Output tensor info
4835  armnn::TensorInfo inputInfo({numBatches , inputSize},
4837  inputScale,
4838  inputOffset);
4839 
4840  armnn::TensorInfo cellStateInfo({numBatches , numUnits},
4842  cellStateScale,
4843  cellStateOffset);
4844 
4845  armnn::TensorInfo outputStateInfo({numBatches , outputSize},
4847  outputScale,
4848  outputOffset);
4849 
4850  // Connect input/output slots
4851  input->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(0));
4852  input->GetOutputSlot(0).SetTensorInfo(inputInfo);
4853 
4854  outputStateIn->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(1));
4855  outputStateIn->GetOutputSlot(0).SetTensorInfo(cellStateInfo);
4856 
4857  cellStateIn->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(2));
4858  cellStateIn->GetOutputSlot(0).SetTensorInfo(outputStateInfo);
4859 
4860  qLstmLayer->GetOutputSlot(0).Connect(outputStateOut->GetInputSlot(0));
4861  qLstmLayer->GetOutputSlot(0).SetTensorInfo(outputStateInfo);
4862 
4863  qLstmLayer->GetOutputSlot(1).Connect(cellStateOut->GetInputSlot(0));
4864  qLstmLayer->GetOutputSlot(1).SetTensorInfo(cellStateInfo);
4865 
4866  qLstmLayer->GetOutputSlot(2).Connect(outputLayer->GetInputSlot(0));
4867  qLstmLayer->GetOutputSlot(2).SetTensorInfo(outputStateInfo);
4868 
4869  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
4870  BOOST_CHECK(deserializedNetwork);
4871 
4872  VerifyQLstmLayer checker(layerName,
4873  {inputInfo, cellStateInfo, outputStateInfo},
4874  {outputStateInfo, cellStateInfo, outputStateInfo},
4875  descriptor,
4876  params);
4877 
4878  deserializedNetwork->Accept(checker);
4879 }
4880 
4881 BOOST_AUTO_TEST_CASE(SerializeDeserializeQLstmAdvanced)
4882 {
4883  armnn::QLstmDescriptor descriptor;
4884 
4885  descriptor.m_CifgEnabled = false;
4886  descriptor.m_ProjectionEnabled = true;
4887  descriptor.m_PeepholeEnabled = true;
4888  descriptor.m_LayerNormEnabled = true;
4889 
4890  descriptor.m_CellClip = 0.1f;
4891  descriptor.m_ProjectionClip = 0.1f;
4892 
4893  descriptor.m_InputIntermediateScale = 0.00001f;
4894  descriptor.m_ForgetIntermediateScale = 0.00001f;
4895  descriptor.m_CellIntermediateScale = 0.00001f;
4896  descriptor.m_OutputIntermediateScale = 0.00001f;
4897 
4898  descriptor.m_HiddenStateScale = 0.07f;
4899  descriptor.m_HiddenStateZeroPoint = 0;
4900 
4901  const unsigned int numBatches = 2;
4902  const unsigned int inputSize = 5;
4903  const unsigned int outputSize = 4;
4904  const unsigned int numUnits = 4;
4905 
4906  // Scale/Offset quantization info
4907  float inputScale = 0.0078f;
4908  int32_t inputOffset = 0;
4909 
4910  float outputScale = 0.0078f;
4911  int32_t outputOffset = 0;
4912 
4913  float cellStateScale = 3.5002e-05f;
4914  int32_t cellStateOffset = 0;
4915 
4916  float weightsScale = 0.007f;
4917  int32_t weightsOffset = 0;
4918 
4919  float layerNormScale = 3.5002e-05f;
4920  int32_t layerNormOffset = 0;
4921 
4922  float biasScale = layerNormScale / 1024;
4923  int32_t biasOffset = 0;
4924 
4925  // Weights and bias tensor and quantization info
4926  armnn::TensorInfo inputWeightsInfo({numUnits, inputSize},
4928  weightsScale,
4929  weightsOffset);
4930 
4931  armnn::TensorInfo recurrentWeightsInfo({numUnits, outputSize},
4933  weightsScale,
4934  weightsOffset);
4935 
4936  armnn::TensorInfo biasInfo({numUnits},
4938  biasScale,
4939  biasOffset);
4940 
4941  armnn::TensorInfo peepholeWeightsInfo({numUnits},
4943  weightsScale,
4944  weightsOffset);
4945 
4946  armnn::TensorInfo layerNormWeightsInfo({numUnits},
4948  layerNormScale,
4949  layerNormOffset);
4950 
4951  armnn::TensorInfo projectionWeightsInfo({outputSize, numUnits},
4953  weightsScale,
4954  weightsOffset);
4955 
4956  // Mandatory params
4957  std::vector<int8_t> inputToForgetWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4958  std::vector<int8_t> inputToCellWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4959  std::vector<int8_t> inputToOutputWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4960 
4961  armnn::ConstTensor inputToForgetWeights(inputWeightsInfo, inputToForgetWeightsData);
4962  armnn::ConstTensor inputToCellWeights(inputWeightsInfo, inputToCellWeightsData);
4963  armnn::ConstTensor inputToOutputWeights(inputWeightsInfo, inputToOutputWeightsData);
4964 
4965  std::vector<int8_t> recurrentToForgetWeightsData =
4966  GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4967  std::vector<int8_t> recurrentToCellWeightsData =
4968  GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4969  std::vector<int8_t> recurrentToOutputWeightsData =
4970  GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4971 
4972  armnn::ConstTensor recurrentToForgetWeights(recurrentWeightsInfo, recurrentToForgetWeightsData);
4973  armnn::ConstTensor recurrentToCellWeights(recurrentWeightsInfo, recurrentToCellWeightsData);
4974  armnn::ConstTensor recurrentToOutputWeights(recurrentWeightsInfo, recurrentToOutputWeightsData);
4975 
4976  std::vector<int32_t> forgetGateBiasData(numUnits, 1);
4977  std::vector<int32_t> cellBiasData(numUnits, 0);
4978  std::vector<int32_t> outputGateBiasData(numUnits, 0);
4979 
4980  armnn::ConstTensor forgetGateBias(biasInfo, forgetGateBiasData);
4981  armnn::ConstTensor cellBias(biasInfo, cellBiasData);
4982  armnn::ConstTensor outputGateBias(biasInfo, outputGateBiasData);
4983 
4984  // CIFG
4985  std::vector<int8_t> inputToInputWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4986  std::vector<int8_t> recurrentToInputWeightsData =
4987  GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4988  std::vector<int32_t> inputGateBiasData(numUnits, 1);
4989 
4990  armnn::ConstTensor inputToInputWeights(inputWeightsInfo, inputToInputWeightsData);
4991  armnn::ConstTensor recurrentToInputWeights(recurrentWeightsInfo, recurrentToInputWeightsData);
4992  armnn::ConstTensor inputGateBias(biasInfo, inputGateBiasData);
4993 
4994  // Peephole
4995  std::vector<int16_t> cellToInputWeightsData = GenerateRandomData<int16_t>(peepholeWeightsInfo.GetNumElements());
4996  std::vector<int16_t> cellToForgetWeightsData = GenerateRandomData<int16_t>(peepholeWeightsInfo.GetNumElements());
4997  std::vector<int16_t> cellToOutputWeightsData = GenerateRandomData<int16_t>(peepholeWeightsInfo.GetNumElements());
4998 
4999  armnn::ConstTensor cellToInputWeights(peepholeWeightsInfo, cellToInputWeightsData);
5000  armnn::ConstTensor cellToForgetWeights(peepholeWeightsInfo, cellToForgetWeightsData);
5001  armnn::ConstTensor cellToOutputWeights(peepholeWeightsInfo, cellToOutputWeightsData);
5002 
5003  // Projection
5004  std::vector<int8_t> projectionWeightsData = GenerateRandomData<int8_t>(projectionWeightsInfo.GetNumElements());
5005  std::vector<int32_t> projectionBiasData(outputSize, 1);
5006 
5007  armnn::ConstTensor projectionWeights(projectionWeightsInfo, projectionWeightsData);
5008  armnn::ConstTensor projectionBias(biasInfo, projectionBiasData);
5009 
5010  // Layer Norm
5011  std::vector<int16_t> inputLayerNormWeightsData =
5012  GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
5013  std::vector<int16_t> forgetLayerNormWeightsData =
5014  GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
5015  std::vector<int16_t> cellLayerNormWeightsData =
5016  GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
5017  std::vector<int16_t> outputLayerNormWeightsData =
5018  GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
5019 
5020  armnn::ConstTensor inputLayerNormWeights(layerNormWeightsInfo, inputLayerNormWeightsData);
5021  armnn::ConstTensor forgetLayerNormWeights(layerNormWeightsInfo, forgetLayerNormWeightsData);
5022  armnn::ConstTensor cellLayerNormWeights(layerNormWeightsInfo, cellLayerNormWeightsData);
5023  armnn::ConstTensor outputLayerNormWeights(layerNormWeightsInfo, outputLayerNormWeightsData);
5024 
5025  // Set up params
5026  armnn::LstmInputParams params;
5027 
5028  // Mandatory params
5029  params.m_InputToForgetWeights = &inputToForgetWeights;
5030  params.m_InputToCellWeights = &inputToCellWeights;
5031  params.m_InputToOutputWeights = &inputToOutputWeights;
5032 
5033  params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
5034  params.m_RecurrentToCellWeights = &recurrentToCellWeights;
5035  params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
5036 
5037  params.m_ForgetGateBias = &forgetGateBias;
5038  params.m_CellBias = &cellBias;
5039  params.m_OutputGateBias = &outputGateBias;
5040 
5041  // CIFG
5042  params.m_InputToInputWeights = &inputToInputWeights;
5043  params.m_RecurrentToInputWeights = &recurrentToInputWeights;
5044  params.m_InputGateBias = &inputGateBias;
5045 
5046  // Peephole
5047  params.m_CellToInputWeights = &cellToInputWeights;
5048  params.m_CellToForgetWeights = &cellToForgetWeights;
5049  params.m_CellToOutputWeights = &cellToOutputWeights;
5050 
5051  // Projection
5052  params.m_ProjectionWeights = &projectionWeights;
5053  params.m_ProjectionBias = &projectionBias;
5054 
5055  // Layer Norm
5056  params.m_InputLayerNormWeights = &inputLayerNormWeights;
5057  params.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
5058  params.m_CellLayerNormWeights = &cellLayerNormWeights;
5059  params.m_OutputLayerNormWeights = &outputLayerNormWeights;
5060 
5061  // Create network
5063  const std::string layerName("qLstm");
5064 
5065  armnn::IConnectableLayer* const input = network->AddInputLayer(0);
5066  armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(1);
5067  armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(2);
5068 
5069  armnn::IConnectableLayer* const qLstmLayer = network->AddQLstmLayer(descriptor, params, layerName.c_str());
5070 
5071  armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(0);
5072  armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(1);
5073  armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(2);
5074 
5075  // Input/Output tensor info
5076  armnn::TensorInfo inputInfo({numBatches , inputSize},
5078  inputScale,
5079  inputOffset);
5080 
5081  armnn::TensorInfo cellStateInfo({numBatches , numUnits},
5083  cellStateScale,
5084  cellStateOffset);
5085 
5086  armnn::TensorInfo outputStateInfo({numBatches , outputSize},
5088  outputScale,
5089  outputOffset);
5090 
5091  // Connect input/output slots
5092  input->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(0));
5093  input->GetOutputSlot(0).SetTensorInfo(inputInfo);
5094 
5095  outputStateIn->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(1));
5096  outputStateIn->GetOutputSlot(0).SetTensorInfo(cellStateInfo);
5097 
5098  cellStateIn->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(2));
5099  cellStateIn->GetOutputSlot(0).SetTensorInfo(outputStateInfo);
5100 
5101  qLstmLayer->GetOutputSlot(0).Connect(outputStateOut->GetInputSlot(0));
5102  qLstmLayer->GetOutputSlot(0).SetTensorInfo(outputStateInfo);
5103 
5104  qLstmLayer->GetOutputSlot(1).Connect(cellStateOut->GetInputSlot(0));
5105  qLstmLayer->GetOutputSlot(1).SetTensorInfo(cellStateInfo);
5106 
5107  qLstmLayer->GetOutputSlot(2).Connect(outputLayer->GetInputSlot(0));
5108  qLstmLayer->GetOutputSlot(2).SetTensorInfo(outputStateInfo);
5109 
5110  armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
5111  BOOST_CHECK(deserializedNetwork);
5112 
5113  VerifyQLstmLayer checker(layerName,
5114  {inputInfo, cellStateInfo, outputStateInfo},
5115  {outputStateInfo, cellStateInfo, outputStateInfo},
5116  descriptor,
5117  params);
5118 
5119  deserializedNetwork->Accept(checker);
5120 }
5121 
BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
uint32_t m_PadBottom
Padding bottom value in the height dimension.
bool m_BiasEnabled
Enable/disable bias.
virtual unsigned int GetNumOutputSlots() const =0
Returns the number of connectable output slots.
bool m_ProjectionEnabled
Enable/disable the projection layer.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
const ConstTensor * m_ProjectionWeights
Definition: LstmParams.hpp:55
float Dequantize(QuantizedType value, float scale, int32_t offset)
Dequantize an 8-bit data type into a floating point data type.
Definition: TypesUtils.cpp:46
A ViewsDescriptor for the SplitterLayer.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:61
float m_ScaleW
Center size encoding scale weight.
const ConstTensor * m_CellBias
Definition: LstmParams.hpp:53
bool m_BiasEnabled
Enable/disable bias.
virtual unsigned int GetNumInputSlots() const =0
Returns the number of connectable input slots.
void Slice(const TensorInfo &inputInfo, const SliceDescriptor &descriptor, const void *inputData, void *outputData, unsigned int dataTypeSize)
Definition: Slice.cpp:14
A TransposeConvolution2dDescriptor for the TransposeConvolution2dLayer.
const TensorShape & GetShape() const
Definition: Tensor.hpp:187
const ConstTensor * m_RecurrentToOutputWeights
uint32_t m_PadBottom
Padding bottom value in the height dimension.
float m_ClippingThresProj
Clipping threshold value for the projection.
A ReshapeDescriptor for the ReshapeLayer.
const ConstTensor * m_CellToOutputWeights
Definition: LstmParams.hpp:50
#define ARMNN_NO_DEPRECATE_WARN_BEGIN
Definition: Deprecated.hpp:33
const ConstTensor * m_RecurrentToForgetWeights
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
void Fill(Encoder< float > &output, const TensorShape &desiredOutputShape, const float value)
Creates a tensor and fills it with a scalar value.
Definition: Fill.cpp:13
A ComparisonDescriptor for the ComparisonLayer.
Definition: Descriptors.hpp:73
float m_ScaleX
Center size encoding scale x.
uint32_t m_TargetWidth
Target width value.
bool m_TransposeWeightMatrix
Enable/disable transpose weight matrix.
bool m_PeepholeEnabled
Enable/disable peephole.
A Convolution2dDescriptor for the Convolution2dLayer.
uint32_t m_PadLeft
Padding left value in the width dimension.
float m_HiddenStateScale
Hidden State quantization scale.
bool m_BiasEnabled
Enable/disable bias.
const ConstTensor * m_CellToInputWeights
Definition: LstmParams.hpp:48
const TensorShape & GetShape() const
Definition: Tensor.hpp:284
float m_OutputIntermediateScale
Output intermediate quantization scale.
ResizeMethod m_Method
The Interpolation method to use (Bilinear, NearestNeighbor).
float m_Gamma
Gamma, the scale scalar value applied for the normalized tensor. Defaults to 1.0. ...
float m_Beta
Exponentiation value.
The padding fields don&#39;t count and are ignored.
float m_Eps
Value to add to the variance. Used to avoid dividing by zero.
const ConstTensor * m_InputGateBias
Definition: LstmParams.hpp:51
ArgMinMaxFunction m_Function
Specify if the function is to find Min or Max.
Definition: Descriptors.hpp:65
uint32_t m_DetectionsPerClass
Detections per classes, used in Regular NMS.
armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32)
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Main network class which provides the interface for building up a neural network. ...
Definition: INetwork.hpp:105
unsigned int GetNumElements() const
Definition: Tensor.hpp:290
const ConstTensor * m_RecurrentToCellWeights
Definition: LstmParams.hpp:46
A LogicalBinaryDescriptor for the LogicalBinaryLayer.
void Serialize(const armnn::INetwork &inNetwork) override
Serializes the network to ArmNN SerializedGraph.
void Transpose(const armnn::TensorShape &dstShape, const armnn::PermutationVector &mappings, const void *src, void *dst, size_t dataTypeSize)
Definition: Transpose.cpp:120
void DepthToSpace(const TensorInfo &inputInfo, const DepthToSpaceDescriptor &descriptor, const void *inputData, void *outputData, unsigned int dataTypeSize)
uint32_t m_PadRight
Padding right value in the width dimension.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
MemoryType GetMemoryArea() const
Definition: Tensor.hpp:292
const ConstTensor * m_ForgetLayerNormWeights
Definition: LstmParams.hpp:58
void ArgMinMax(Decoder< float > &in, OUT *out, const TensorInfo &inputTensorInfo, const TensorInfo &outputTensorInfo, ArgMinMaxFunction function, int axis)
Definition: ArgMinMax.cpp:16
const ConstTensor * m_CellToForgetWeights
Definition: LstmParams.hpp:49
Copyright (c) 2020 ARM Limited.
uint32_t m_PadBottom
Padding bottom value in the height dimension.
uint32_t m_DilationY
Dilation along y axis.
int32_t m_EndMask
End mask value.
A SpaceToDepthDescriptor for the SpaceToDepthLayer.
uint32_t m_DilationY
Dilation factor value for height dimension.
#define DECLARE_LAYER_VERIFIER_CLASS(name)
A BatchToSpaceNdDescriptor for the BatchToSpaceNdLayer.
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
Definition: Types.hpp:202
const ConstTensor * m_OutputGateBias
Definition: LstmParams.hpp:54
void Stack(const StackQueueDescriptor &data, std::vector< std::unique_ptr< Decoder< float >>> &inputs, Encoder< float > &output)
Definition: Stack.cpp:12
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
constexpr const char * GetDataTypeName(DataType dataType)
Definition: TypesUtils.hpp:180
A ResizeDescriptor for the ResizeLayer.
BOOST_AUTO_TEST_CASE(SerializeAddition)
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
uint32_t m_MaxClassesPerDetection
Maximum numbers of classes per detection, used in Fast NMS.
std::vector< unsigned int > m_Axis
Values for the dimensions to reduce.
A StackDescriptor for the StackLayer.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
uint32_t m_PadTop
Padding top value in the height dimension.
uint32_t m_MaxDetections
Maximum numbers of detections.
A PadDescriptor for the PadLayer.
void Permute(const armnn::TensorShape &dstShape, const armnn::PermutationVector &mappings, const void *src, void *dst, size_t dataTypeSize)
Definition: Permute.cpp:131
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
const ConstTensor * m_InputLayerNormWeights
Definition: LstmParams.hpp:57
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
bool m_LayerNormEnabled
Enable/disable layer normalization.
DataType
Definition: Types.hpp:32
float m_NmsIouThreshold
Intersection over union threshold.
const ConstTensor * m_RecurrentToOutputWeights
Definition: LstmParams.hpp:47
An LstmDescriptor for the LstmLayer.
#define ARMNN_NO_DEPRECATE_WARN_END
Definition: Deprecated.hpp:34
uint32_t m_DilationX
Dilation factor value for width dimension.
uint32_t m_PadTop
Padding top value in the height dimension.
Status SetViewSize(uint32_t view, uint32_t coord, uint32_t value)
Set the size of the views.
An output connection slot for a layer.
Definition: INetwork.hpp:37
A L2NormalizationDescriptor for the L2NormalizationLayer.
const ConstTensor * m_ProjectionBias
Definition: LstmParams.hpp:56
int32_t GetQuantizationOffset() const
Definition: Tensor.cpp:469
const ConstTensor * m_InputToForgetWeights
An ArgMinMaxDescriptor for ArgMinMaxLayer.
Definition: Descriptors.hpp:51
float GetQuantizationScale() const
Definition: Tensor.cpp:452
DataType GetDataType() const
Definition: Tensor.hpp:194
An OriginsDescriptor for the ConcatLayer.
float m_ProjectionClip
Clipping threshold value for the projection.
bool has_value() const noexcept
Definition: Optional.hpp:53
A FullyConnectedDescriptor for the FullyConnectedLayer.
bool m_BiasEnabled
Enable/disable bias.
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:314
float m_InputIntermediateScale
Input intermediate quantization scale.
uint32_t m_TargetWidth
Target width value.
A GatherDescriptor for the GatherLayer.
bool m_PeepholeEnabled
Enable/disable peephole.
uint32_t m_NumClasses
Number of classes.
bool m_HalfPixelCenters
Half Pixel Centers.
uint32_t m_PadTop
Padding top value in the height dimension.
A StandInDescriptor for the StandIn layer.
A QLstmDescriptor for the QLstmLayer.
QuantizedType Quantize(float value, float scale, int32_t offset)
Quantize a floating point data type into an 8-bit data type.
Definition: TypesUtils.cpp:30
bool m_UseRegularNms
Use Regular NMS.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
void LogSoftmax(Decoder< float > &input, Encoder< float > &output, const TensorInfo &inputInfo, const LogSoftmaxDescriptor &descriptor)
Definition: LogSoftmax.cpp:29
const TensorInfo & GetInfo() const
Definition: Tensor.hpp:282
uint32_t m_TargetHeight
Target height value.
uint32_t m_ActivationFunc
The activation function to use.
A SliceDescriptor for the SliceLayer.
Visitor base class with empty implementations.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
void SpaceToBatchNd(const TensorInfo &inputInfo, const TensorInfo &outputInfo, const SpaceToBatchNdDescriptor &params, Decoder< float > &inputData, Encoder< float > &outputData)
bool SaveSerializedToStream(std::ostream &stream) override
Serializes the SerializedGraph to the stream.
const ConstTensor * m_RecurrentToInputWeights
float m_ClippingThresCell
Clipping threshold value for the cell state.
unsigned int m_BlockSize
Scalar specifying the input block size. It must be >= 1.
float m_ForgetIntermediateScale
Forget intermediate quantization scale.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
float m_ScaleH
Center size encoding scale height.
ComparisonOperation m_Operation
Specifies the comparison operation to execute.
Definition: Descriptors.hpp:89
const ConstTensor * m_CellLayerNormWeights
Definition: LstmParams.hpp:59
const ConstTensor * m_ForgetGateBias
Definition: LstmParams.hpp:52
A SpaceToBatchNdDescriptor for the SpaceToBatchNdLayer.
const ConstTensor * m_InputToCellWeights
Definition: LstmParams.hpp:42
const ConstTensor * m_InputToOutputWeights
Definition: LstmParams.hpp:43
float m_CellClip
Clipping threshold value for the cell state.
uint32_t m_DilationX
Dilation along x axis.
BOOST_AUTO_TEST_SUITE_END()
bool m_CifgEnabled
Enable/disable cifg (coupled input & forget gate).
uint32_t m_PadLeft
Padding left value in the width dimension.
void StridedSlice(const TensorInfo &inputInfo, const StridedSliceDescriptor &params, const void *inputData, void *outputData, unsigned int dataTypeSize)
bool m_AlignCorners
Aligned corners.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
int32_t m_Axis
The axis in params to gather indices from.
A ElementwiseUnaryDescriptor for the ElementwiseUnaryLayer.
Definition: Descriptors.hpp:93
const ConstTensor * m_RecurrentToForgetWeights
Definition: LstmParams.hpp:45
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
Base class for all ArmNN exceptions so that users can filter to just those.
Definition: Exceptions.hpp:46
bool m_ProjectionEnabled
Enable/disable the projection layer.
const ConstTensor * m_RecurrentToCellWeights
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
const ConstTensor * m_RecurrentToInputWeights
Definition: LstmParams.hpp:44
A MeanDescriptor for the MeanLayer.
const ConstTensor * m_InputToOutputWeights
void Mean(const armnn::TensorInfo &inputInfo, const armnn::TensorInfo &outputInfo, const std::vector< unsigned int > &axis, Decoder< float > &input, Encoder< float > &output)
Definition: Mean.cpp:71
virtual const IOutputSlot * GetConnection() const =0
bool m_LayerNormEnabled
Enable/disable layer normalization.
uint32_t m_PadRight
Padding right value in the width dimension.
A TransposeDescriptor for the TransposeLayer.
A StridedSliceDescriptor for the StridedSliceLayer.
virtual const TensorInfo & GetTensorInfo() const =0
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
void SpaceToDepth(const TensorInfo &inputInfo, const TensorInfo &outputInfo, const SpaceToDepthDescriptor &params, Decoder< float > &inputData, Encoder< float > &outputData)
float m_ScaleY
Center size encoding scale y.
OriginsDescriptor CreateDescriptorForConcatenation(TensorShapeIt first, TensorShapeIt last, unsigned int concatenationDimension)
Convenience template to create an OriginsDescriptor to use when creating a ConcatLayer for performing...
#define DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(name)
float m_NmsScoreThreshold
NMS score threshold.
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:101
void BatchToSpaceNd(const DataLayoutIndexed &dataLayout, const TensorInfo &inputTensorInfo, const TensorInfo &outputTensorInfo, const std::vector< unsigned int > &blockShape, const std::vector< std::pair< unsigned int, unsigned int >> &cropsData, Decoder< float > &inputDecoder, Encoder< float > &outputEncoder)
void Pad(const TensorInfo &inputInfo, const TensorInfo &outputInfo, const PadQueueDescriptor &data)
Definition: Pad.cpp:39
virtual int Connect(IInputSlot &destination)=0
DataType GetDataType() const
Definition: Tensor.hpp:287
A Pooling2dDescriptor for the Pooling2dLayer.
const ConstTensor * m_OutputLayerNormWeights
Definition: LstmParams.hpp:60
A NormalizationDescriptor for the NormalizationLayer.
void Pooling2d(Decoder< float > &rInputDecoder, Encoder< float > &rOutputEncoder, const TensorInfo &inputInfo, const TensorInfo &outputInfo, const Pooling2dDescriptor &params)
Computes the Pooling2d operation.
Definition: Pooling2d.cpp:142
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
An InstanceNormalizationDescriptor for InstanceNormalizationLayer.
A ResizeBilinearDescriptor for the ResizeBilinearLayer.
void Splitter(const SplitterQueueDescriptor &data)
Definition: Splitter.hpp:17
float m_CellIntermediateScale
Cell intermediate quantization scale.
void Softmax(Decoder< float > &in, Encoder< float > &out, const TensorInfo &inputTensorInfo, float beta, int axis)
Computes the softmax function on some inputs, into outputs, with a shape given by tensorInfo...
Definition: Softmax.cpp:17
static INetworkPtr Create(NetworkOptions networkOptions={})
Definition: Network.cpp:46
A SoftmaxDescriptor for the SoftmaxLayer.
bool m_CifgEnabled
Enable/disable CIFG (coupled input & forget gate).
Status SetViewOriginCoord(uint32_t view, uint32_t coord, uint32_t value)
Set the view origin coordinates.
void Resize(Decoder< float > &in, const TensorInfo &inputInfo, Encoder< float > &out, const TensorInfo &outputInfo, DataLayoutIndexed dataLayout, armnn::ResizeMethod resizeMethod, bool alignCorners, bool halfPixelCenters)
Definition: Resize.cpp:65
A DepthwiseConvolution2dDescriptor for the DepthwiseConvolution2dLayer.
A FillDescriptor for the FillLayer.
A BatchNormalizationDescriptor for the BatchNormalizationLayer.
uint32_t m_PadLeft
Padding left value in the width dimension.
unsigned int GetNumBytes() const
Definition: Tensor.hpp:289
const ConstTensor * m_InputToForgetWeights
Definition: LstmParams.hpp:41
A PermuteDescriptor for the PermuteLayer.
uint32_t m_PadRight
Padding right value in the width dimension.
int32_t m_HiddenStateZeroPoint
Hidden State zero point.
const ConstTensor * m_InputToInputWeights
Definition: LstmParams.hpp:40
std::vector< float > anchors({ 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 10.5f, 1.0f, 1.0f, 0.5f, 10.5f, 1.0f, 1.0f, 0.5f, 100.5f, 1.0f, 1.0f })