2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
6 #include "../Serializer.hpp"
8 #include <armnn/Descriptors.hpp>
9 #include <armnn/INetwork.hpp>
10 #include <armnn/TypesUtils.hpp>
11 #include <armnn/LstmParams.hpp>
12 #include <armnn/QuantizedLstmParams.hpp>
13 #include <armnnDeserializer/IDeserializer.hpp>
18 #include <boost/test/unit_test.hpp>
20 using armnnDeserializer::IDeserializer;
25 #define DECLARE_LAYER_VERIFIER_CLASS(name) \
26 class name##LayerVerifier : public LayerVerifierBase \
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) {} \
34 void Visit##name##Layer(const armnn::IConnectableLayer* layer, const char* name) override \
36 VerifyNameAndConnections(layer, name); \
40 #define DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(name) \
41 class name##LayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::name##Descriptor> \
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) {} \
51 void Visit##name##Layer(const armnn::IConnectableLayer* layer, \
52 const armnn::name##Descriptor& descriptor, \
53 const char* name) override \
55 VerifyNameAndConnections(layer, name); \
56 VerifyDescriptor(descriptor); \
60 struct DefaultLayerVerifierPolicy
62 static void Apply(const std::string)
64 BOOST_TEST_MESSAGE("Unexpected layer found in network");
69 class LayerVerifierBase : public armnn::LayerVisitorBase<DefaultLayerVerifierPolicy>
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) {}
79 void VisitInputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId, const char*) override {}
81 void VisitOutputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId, const char*) override {}
84 void VerifyNameAndConnections(const armnn::IConnectableLayer* layer, const char* name)
86 BOOST_TEST(name == m_LayerName.c_str());
88 BOOST_TEST(layer->GetNumInputSlots() == m_InputTensorInfos.size());
89 BOOST_TEST(layer->GetNumOutputSlots() == m_OutputTensorInfos.size());
91 for (unsigned int i = 0; i < m_InputTensorInfos.size(); i++)
93 const armnn::IOutputSlot* connectedOutput = layer->GetInputSlot(i).GetConnection();
94 BOOST_CHECK(connectedOutput);
96 const armnn::TensorInfo& connectedInfo = connectedOutput->GetTensorInfo();
97 BOOST_TEST(connectedInfo.GetShape() == m_InputTensorInfos[i].GetShape());
99 GetDataTypeName(connectedInfo.GetDataType()) == GetDataTypeName(m_InputTensorInfos[i].GetDataType()));
101 BOOST_TEST(connectedInfo.GetQuantizationScale() == m_InputTensorInfos[i].GetQuantizationScale());
102 BOOST_TEST(connectedInfo.GetQuantizationOffset() == m_InputTensorInfos[i].GetQuantizationOffset());
105 for (unsigned int i = 0; i < m_OutputTensorInfos.size(); i++)
107 const armnn::TensorInfo& outputInfo = layer->GetOutputSlot(i).GetTensorInfo();
108 BOOST_TEST(outputInfo.GetShape() == m_OutputTensorInfos[i].GetShape());
110 GetDataTypeName(outputInfo.GetDataType()) == GetDataTypeName(m_OutputTensorInfos[i].GetDataType()));
112 BOOST_TEST(outputInfo.GetQuantizationScale() == m_OutputTensorInfos[i].GetQuantizationScale());
113 BOOST_TEST(outputInfo.GetQuantizationOffset() == m_OutputTensorInfos[i].GetQuantizationOffset());
117 void VerifyConstTensors(const std::string& tensorName,
118 const armnn::ConstTensor* expectedPtr,
119 const armnn::ConstTensor* actualPtr)
121 if (expectedPtr == nullptr)
123 BOOST_CHECK_MESSAGE(actualPtr == nullptr, tensorName + " should not exist");
127 BOOST_CHECK_MESSAGE(actualPtr != nullptr, tensorName + " should have been set");
128 if (actualPtr != nullptr)
130 const armnn::TensorInfo& expectedInfo = expectedPtr->GetInfo();
131 const armnn::TensorInfo& actualInfo = actualPtr->GetInfo();
133 BOOST_CHECK_MESSAGE(expectedInfo.GetShape() == actualInfo.GetShape(),
134 tensorName + " shapes don't match");
136 GetDataTypeName(expectedInfo.GetDataType()) == GetDataTypeName(actualInfo.GetDataType()),
137 tensorName + " data types don't match");
139 BOOST_CHECK_MESSAGE(expectedPtr->GetNumBytes() == actualPtr->GetNumBytes(),
140 tensorName + " (GetNumBytes) data sizes do not match");
141 if (expectedPtr->GetNumBytes() == actualPtr->GetNumBytes())
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());
147 for (unsigned int i = 0; i < expectedPtr->GetNumBytes(); ++i)
149 same = expectedData[i] == actualData[i];
155 BOOST_CHECK_MESSAGE(same, tensorName + " data does not match");
162 std::string m_LayerName;
163 std::vector<armnn::TensorInfo> m_InputTensorInfos;
164 std::vector<armnn::TensorInfo> m_OutputTensorInfos;
167 template<typename Descriptor>
168 class LayerVerifierBaseWithDescriptor : public LayerVerifierBase
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) {}
179 void VerifyDescriptor(const Descriptor& descriptor)
181 BOOST_CHECK(descriptor == m_Descriptor);
184 Descriptor m_Descriptor;
188 void CompareConstTensorData(const void* data1, const void* data2, unsigned int numElements)
190 T typedData1 = static_cast<T>(data1);
191 T typedData2 = static_cast<T>(data2);
192 BOOST_CHECK(typedData1);
193 BOOST_CHECK(typedData2);
195 for (unsigned int i = 0; i < numElements; i++)
197 BOOST_TEST(typedData1[i] == typedData2[i]);
201 void CompareConstTensor(const armnn::ConstTensor& tensor1, const armnn::ConstTensor& tensor2)
203 BOOST_TEST(tensor1.GetShape() == tensor2.GetShape());
204 BOOST_TEST(GetDataTypeName(tensor1.GetDataType()) == GetDataTypeName(tensor2.GetDataType()));
206 switch (tensor1.GetDataType())
208 case armnn::DataType::Float32:
209 CompareConstTensorData<const float*>(
210 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
212 case armnn::DataType::QAsymmU8:
213 case armnn::DataType::Boolean:
214 CompareConstTensorData<const uint8_t*>(
215 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
217 case armnn::DataType::QSymmS8:
218 CompareConstTensorData<const int8_t*>(
219 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
221 case armnn::DataType::Signed32:
222 CompareConstTensorData<const int32_t*>(
223 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
226 // Note that Float16 is not yet implemented
227 BOOST_TEST_MESSAGE("Unexpected datatype");
232 armnn::INetworkPtr DeserializeNetwork(const std::string& serializerString)
234 std::vector<std::uint8_t> const serializerVector{serializerString.begin(), serializerString.end()};
235 return IDeserializer::Create()->CreateNetworkFromBinary(serializerVector);
238 std::string SerializeNetwork(const armnn::INetwork& network)
240 armnnSerializer::ISerializerPtr serializer = armnnSerializer::ISerializer::Create();
242 serializer->Serialize(network);
244 std::stringstream stream;
245 serializer->SaveSerializedToStream(stream);
247 std::string serializerString{stream.str()};
248 return serializerString;
251 template<typename DataType>
252 static std::vector<DataType> GenerateRandomData(size_t size)
254 constexpr bool isIntegerType = std::is_integral<DataType>::value;
256 typename std::conditional<isIntegerType,
257 std::uniform_int_distribution<DataType>,
258 std::uniform_real_distribution<DataType>>::type;
260 static constexpr DataType lowerLimit = std::numeric_limits<DataType>::min();
261 static constexpr DataType upperLimit = std::numeric_limits<DataType>::max();
263 static Distribution distribution(lowerLimit, upperLimit);
264 static std::default_random_engine generator;
266 std::vector<DataType> randomData(size);
267 std::generate(randomData.begin(), randomData.end(), []() { return distribution(generator); });
272 } // anonymous namespace
274 BOOST_AUTO_TEST_SUITE(SerializerTests)
276 BOOST_AUTO_TEST_CASE(SerializeAddition)
278 DECLARE_LAYER_VERIFIER_CLASS(Addition)
280 const std::string layerName("addition");
281 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
283 armnn::INetworkPtr network = armnn::INetwork::Create();
284 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
285 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
286 armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer(layerName.c_str());
287 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
289 inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
290 inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1));
291 additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
293 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
294 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
295 additionLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
297 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
298 BOOST_CHECK(deserializedNetwork);
300 AdditionLayerVerifier verifier(layerName, {tensorInfo, tensorInfo}, {tensorInfo});
301 deserializedNetwork->Accept(verifier);
304 BOOST_AUTO_TEST_CASE(SerializeArgMinMax)
306 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(ArgMinMax)
308 const std::string layerName("argminmax");
309 const armnn::TensorInfo inputInfo({1, 2, 3}, armnn::DataType::Float32);
310 const armnn::TensorInfo outputInfo({1, 3}, armnn::DataType::Signed32);
312 armnn::ArgMinMaxDescriptor descriptor;
313 descriptor.m_Function = armnn::ArgMinMaxFunction::Max;
314 descriptor.m_Axis = 1;
316 armnn::INetworkPtr network = armnn::INetwork::Create();
317 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
318 armnn::IConnectableLayer* const argMinMaxLayer = network->AddArgMinMaxLayer(descriptor, layerName.c_str());
319 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
321 inputLayer->GetOutputSlot(0).Connect(argMinMaxLayer->GetInputSlot(0));
322 argMinMaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
324 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
325 argMinMaxLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
327 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
328 BOOST_CHECK(deserializedNetwork);
330 ArgMinMaxLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
331 deserializedNetwork->Accept(verifier);
334 BOOST_AUTO_TEST_CASE(SerializeBatchNormalization)
336 using Descriptor = armnn::BatchNormalizationDescriptor;
337 class BatchNormalizationLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
340 BatchNormalizationLayerVerifier(const std::string& layerName,
341 const std::vector<armnn::TensorInfo>& inputInfos,
342 const std::vector<armnn::TensorInfo>& outputInfos,
343 const Descriptor& descriptor,
344 const armnn::ConstTensor& mean,
345 const armnn::ConstTensor& variance,
346 const armnn::ConstTensor& beta,
347 const armnn::ConstTensor& gamma)
348 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
350 , m_Variance(variance)
354 void VisitBatchNormalizationLayer(const armnn::IConnectableLayer* layer,
355 const Descriptor& descriptor,
356 const armnn::ConstTensor& mean,
357 const armnn::ConstTensor& variance,
358 const armnn::ConstTensor& beta,
359 const armnn::ConstTensor& gamma,
360 const char* name) override
362 VerifyNameAndConnections(layer, name);
363 VerifyDescriptor(descriptor);
365 CompareConstTensor(mean, m_Mean);
366 CompareConstTensor(variance, m_Variance);
367 CompareConstTensor(beta, m_Beta);
368 CompareConstTensor(gamma, m_Gamma);
372 armnn::ConstTensor m_Mean;
373 armnn::ConstTensor m_Variance;
374 armnn::ConstTensor m_Beta;
375 armnn::ConstTensor m_Gamma;
378 const std::string layerName("batchNormalization");
379 const armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32);
380 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
382 const armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32);
383 const armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32);
384 const armnn::TensorInfo betaInfo({1}, armnn::DataType::Float32);
385 const armnn::TensorInfo gammaInfo({1}, armnn::DataType::Float32);
387 armnn::BatchNormalizationDescriptor descriptor;
388 descriptor.m_Eps = 0.0010000000475f;
389 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
391 std::vector<float> meanData({5.0});
392 std::vector<float> varianceData({2.0});
393 std::vector<float> betaData({1.0});
394 std::vector<float> gammaData({0.0});
396 armnn::ConstTensor mean(meanInfo, meanData);
397 armnn::ConstTensor variance(varianceInfo, varianceData);
398 armnn::ConstTensor beta(betaInfo, betaData);
399 armnn::ConstTensor gamma(gammaInfo, gammaData);
401 armnn::INetworkPtr network = armnn::INetwork::Create();
402 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
403 armnn::IConnectableLayer* const batchNormalizationLayer =
404 network->AddBatchNormalizationLayer(descriptor, mean, variance, beta, gamma, layerName.c_str());
405 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
407 inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0));
408 batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
410 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
411 batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
413 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
414 BOOST_CHECK(deserializedNetwork);
416 BatchNormalizationLayerVerifier verifier(
417 layerName, {inputInfo}, {outputInfo}, descriptor, mean, variance, beta, gamma);
418 deserializedNetwork->Accept(verifier);
421 BOOST_AUTO_TEST_CASE(SerializeBatchToSpaceNd)
423 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(BatchToSpaceNd)
425 const std::string layerName("spaceToBatchNd");
426 const armnn::TensorInfo inputInfo({4, 1, 2, 2}, armnn::DataType::Float32);
427 const armnn::TensorInfo outputInfo({1, 1, 4, 4}, armnn::DataType::Float32);
429 armnn::BatchToSpaceNdDescriptor desc;
430 desc.m_DataLayout = armnn::DataLayout::NCHW;
431 desc.m_BlockShape = {2, 2};
432 desc.m_Crops = {{0, 0}, {0, 0}};
434 armnn::INetworkPtr network = armnn::INetwork::Create();
435 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
436 armnn::IConnectableLayer* const batchToSpaceNdLayer = network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
437 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
439 inputLayer->GetOutputSlot(0).Connect(batchToSpaceNdLayer->GetInputSlot(0));
440 batchToSpaceNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
442 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
443 batchToSpaceNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
445 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
446 BOOST_CHECK(deserializedNetwork);
448 BatchToSpaceNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
449 deserializedNetwork->Accept(verifier);
452 BOOST_AUTO_TEST_CASE(SerializeComparison)
454 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Comparison)
456 const std::string layerName("comparison");
458 const armnn::TensorShape shape{2, 1, 2, 4};
460 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
461 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
463 armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::NotEqual);
465 armnn::INetworkPtr network = armnn::INetwork::Create();
466 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
467 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
468 armnn::IConnectableLayer* const comparisonLayer = network->AddComparisonLayer(descriptor, layerName.c_str());
469 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
471 inputLayer0->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(0));
472 inputLayer1->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(1));
473 comparisonLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
475 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
476 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
477 comparisonLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
479 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
480 BOOST_CHECK(deserializedNetwork);
482 ComparisonLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo }, descriptor);
483 deserializedNetwork->Accept(verifier);
486 BOOST_AUTO_TEST_CASE(SerializeConstant)
488 class ConstantLayerVerifier : public LayerVerifierBase
491 ConstantLayerVerifier(const std::string& layerName,
492 const std::vector<armnn::TensorInfo>& inputInfos,
493 const std::vector<armnn::TensorInfo>& outputInfos,
494 const armnn::ConstTensor& layerInput)
495 : LayerVerifierBase(layerName, inputInfos, outputInfos)
496 , m_LayerInput(layerInput) {}
498 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
499 const armnn::ConstTensor& input,
500 const char* name) override
502 VerifyNameAndConnections(layer, name);
503 CompareConstTensor(input, m_LayerInput);
506 void VisitAdditionLayer(const armnn::IConnectableLayer*, const char*) override {}
509 armnn::ConstTensor m_LayerInput;
512 const std::string layerName("constant");
513 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
515 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
516 armnn::ConstTensor constTensor(info, constantData);
518 armnn::INetworkPtr network(armnn::INetwork::Create());
519 armnn::IConnectableLayer* input = network->AddInputLayer(0);
520 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
521 armnn::IConnectableLayer* add = network->AddAdditionLayer();
522 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
524 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
525 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
526 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
528 input->GetOutputSlot(0).SetTensorInfo(info);
529 constant->GetOutputSlot(0).SetTensorInfo(info);
530 add->GetOutputSlot(0).SetTensorInfo(info);
532 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
533 BOOST_CHECK(deserializedNetwork);
535 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
536 deserializedNetwork->Accept(verifier);
539 BOOST_AUTO_TEST_CASE(SerializeConvolution2d)
541 using Descriptor = armnn::Convolution2dDescriptor;
542 class Convolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
545 Convolution2dLayerVerifier(const std::string& layerName,
546 const std::vector<armnn::TensorInfo>& inputInfos,
547 const std::vector<armnn::TensorInfo>& outputInfos,
548 const Descriptor& descriptor,
549 const armnn::ConstTensor& weights,
550 const armnn::Optional<armnn::ConstTensor>& biases)
551 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
553 , m_Biases(biases) {}
555 void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
556 const Descriptor& descriptor,
557 const armnn::ConstTensor& weights,
558 const armnn::Optional<armnn::ConstTensor>& biases,
559 const char* name) override
561 VerifyNameAndConnections(layer, name);
562 VerifyDescriptor(descriptor);
565 CompareConstTensor(weights, m_Weights);
568 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
569 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
571 if (biases.has_value() && m_Biases.has_value())
573 CompareConstTensor(biases.value(), m_Biases.value());
578 armnn::ConstTensor m_Weights;
579 armnn::Optional<armnn::ConstTensor> m_Biases;
582 const std::string layerName("convolution2d");
583 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
584 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
586 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
587 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
589 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
590 armnn::ConstTensor weights(weightsInfo, weightsData);
592 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
593 armnn::ConstTensor biases(biasesInfo, biasesData);
595 armnn::Convolution2dDescriptor descriptor;
596 descriptor.m_PadLeft = 1;
597 descriptor.m_PadRight = 1;
598 descriptor.m_PadTop = 1;
599 descriptor.m_PadBottom = 1;
600 descriptor.m_StrideX = 2;
601 descriptor.m_StrideY = 2;
602 descriptor.m_DilationX = 2;
603 descriptor.m_DilationY = 2;
604 descriptor.m_BiasEnabled = true;
605 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
607 armnn::INetworkPtr network = armnn::INetwork::Create();
608 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
609 armnn::IConnectableLayer* const convLayer =
610 network->AddConvolution2dLayer(descriptor,
612 armnn::Optional<armnn::ConstTensor>(biases),
614 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
616 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
617 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
619 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
620 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
622 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
623 BOOST_CHECK(deserializedNetwork);
625 Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
626 deserializedNetwork->Accept(verifier);
629 BOOST_AUTO_TEST_CASE(SerializeConvolution2dWithPerAxisParams)
631 using Descriptor = armnn::Convolution2dDescriptor;
632 class Convolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
635 Convolution2dLayerVerifier(const std::string& layerName,
636 const std::vector<armnn::TensorInfo>& inputInfos,
637 const std::vector<armnn::TensorInfo>& outputInfos,
638 const Descriptor& descriptor,
639 const armnn::ConstTensor& weights,
640 const armnn::Optional<armnn::ConstTensor>& biases)
641 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
643 , m_Biases(biases) {}
645 void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
646 const Descriptor& descriptor,
647 const armnn::ConstTensor& weights,
648 const armnn::Optional<armnn::ConstTensor>& biases,
649 const char* name) override
651 VerifyNameAndConnections(layer, name);
652 VerifyDescriptor(descriptor);
655 CompareConstTensor(weights, m_Weights);
658 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
659 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
661 if (biases.has_value() && m_Biases.has_value())
663 CompareConstTensor(biases.value(), m_Biases.value());
668 armnn::ConstTensor m_Weights;
669 armnn::Optional<armnn::ConstTensor> m_Biases;
672 using namespace armnn;
674 const std::string layerName("convolution2dWithPerAxis");
675 const TensorInfo inputInfo ({ 1, 3, 1, 2 }, DataType::QAsymmU8, 0.55f, 128);
676 const TensorInfo outputInfo({ 1, 3, 1, 3 }, DataType::QAsymmU8, 0.75f, 128);
678 const std::vector<float> quantScales{ 0.75f, 0.65f, 0.85f };
679 constexpr unsigned int quantDimension = 0;
681 const TensorInfo kernelInfo({ 3, 1, 1, 2 }, DataType::QSymmS8, quantScales, quantDimension);
683 const std::vector<float> biasQuantScales{ 0.25f, 0.50f, 0.75f };
684 const TensorInfo biasInfo({ 3 }, DataType::Signed32, biasQuantScales, quantDimension);
686 std::vector<int8_t> kernelData = GenerateRandomData<int8_t>(kernelInfo.GetNumElements());
687 armnn::ConstTensor weights(kernelInfo, kernelData);
688 std::vector<int32_t> biasData = GenerateRandomData<int32_t>(biasInfo.GetNumElements());
689 armnn::ConstTensor biases(biasInfo, biasData);
691 Convolution2dDescriptor descriptor;
692 descriptor.m_StrideX = 1;
693 descriptor.m_StrideY = 1;
694 descriptor.m_PadLeft = 0;
695 descriptor.m_PadRight = 0;
696 descriptor.m_PadTop = 0;
697 descriptor.m_PadBottom = 0;
698 descriptor.m_BiasEnabled = true;
699 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
701 armnn::INetworkPtr network = armnn::INetwork::Create();
702 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
703 armnn::IConnectableLayer* const convLayer =
704 network->AddConvolution2dLayer(descriptor,
706 armnn::Optional<armnn::ConstTensor>(biases),
708 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
710 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
711 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
713 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
714 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
716 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
717 BOOST_CHECK(deserializedNetwork);
719 Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
720 deserializedNetwork->Accept(verifier);
723 BOOST_AUTO_TEST_CASE(SerializeDepthToSpace)
725 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(DepthToSpace)
727 const std::string layerName("depthToSpace");
729 const armnn::TensorInfo inputInfo ({ 1, 8, 4, 12 }, armnn::DataType::Float32);
730 const armnn::TensorInfo outputInfo({ 1, 16, 8, 3 }, armnn::DataType::Float32);
732 armnn::DepthToSpaceDescriptor desc;
733 desc.m_BlockSize = 2;
734 desc.m_DataLayout = armnn::DataLayout::NHWC;
736 armnn::INetworkPtr network = armnn::INetwork::Create();
737 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
738 armnn::IConnectableLayer* const depthToSpaceLayer = network->AddDepthToSpaceLayer(desc, layerName.c_str());
739 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
741 inputLayer->GetOutputSlot(0).Connect(depthToSpaceLayer->GetInputSlot(0));
742 depthToSpaceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
744 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
745 depthToSpaceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
747 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
748 BOOST_CHECK(deserializedNetwork);
750 DepthToSpaceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
751 deserializedNetwork->Accept(verifier);
754 BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d)
756 using Descriptor = armnn::DepthwiseConvolution2dDescriptor;
757 class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
760 DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
761 const std::vector<armnn::TensorInfo>& inputInfos,
762 const std::vector<armnn::TensorInfo>& outputInfos,
763 const Descriptor& descriptor,
764 const armnn::ConstTensor& weights,
765 const armnn::Optional<armnn::ConstTensor>& biases) :
766 LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor),
770 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
771 const Descriptor& descriptor,
772 const armnn::ConstTensor& weights,
773 const armnn::Optional<armnn::ConstTensor>& biases,
774 const char* name) override
776 VerifyNameAndConnections(layer, name);
777 VerifyDescriptor(descriptor);
780 CompareConstTensor(weights, m_Weights);
783 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
784 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
786 if (biases.has_value() && m_Biases.has_value())
788 CompareConstTensor(biases.value(), m_Biases.value());
793 armnn::ConstTensor m_Weights;
794 armnn::Optional<armnn::ConstTensor> m_Biases;
797 const std::string layerName("depwiseConvolution2d");
798 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
799 const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
801 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
802 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
804 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
805 armnn::ConstTensor weights(weightsInfo, weightsData);
807 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
808 armnn::ConstTensor biases(biasesInfo, biasesData);
810 armnn::DepthwiseConvolution2dDescriptor descriptor;
811 descriptor.m_PadLeft = 1;
812 descriptor.m_PadRight = 1;
813 descriptor.m_PadTop = 1;
814 descriptor.m_PadBottom = 1;
815 descriptor.m_StrideX = 2;
816 descriptor.m_StrideY = 2;
817 descriptor.m_DilationX = 2;
818 descriptor.m_DilationY = 2;
819 descriptor.m_BiasEnabled = true;
820 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
822 armnn::INetworkPtr network = armnn::INetwork::Create();
823 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
824 armnn::IConnectableLayer* const depthwiseConvLayer =
825 network->AddDepthwiseConvolution2dLayer(descriptor,
827 armnn::Optional<armnn::ConstTensor>(biases),
829 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
831 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
832 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
834 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
835 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
837 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
838 BOOST_CHECK(deserializedNetwork);
840 DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
841 deserializedNetwork->Accept(verifier);
844 BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2dWithPerAxisParams)
846 using Descriptor = armnn::DepthwiseConvolution2dDescriptor;
847 class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
850 DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
851 const std::vector<armnn::TensorInfo>& inputInfos,
852 const std::vector<armnn::TensorInfo>& outputInfos,
853 const Descriptor& descriptor,
854 const armnn::ConstTensor& weights,
855 const armnn::Optional<armnn::ConstTensor>& biases) :
856 LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor),
860 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
861 const Descriptor& descriptor,
862 const armnn::ConstTensor& weights,
863 const armnn::Optional<armnn::ConstTensor>& biases,
864 const char* name) override
866 VerifyNameAndConnections(layer, name);
867 VerifyDescriptor(descriptor);
870 CompareConstTensor(weights, m_Weights);
873 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
874 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
876 if (biases.has_value() && m_Biases.has_value())
878 CompareConstTensor(biases.value(), m_Biases.value());
883 armnn::ConstTensor m_Weights;
884 armnn::Optional<armnn::ConstTensor> m_Biases;
887 using namespace armnn;
889 const std::string layerName("depwiseConvolution2dWithPerAxis");
890 const TensorInfo inputInfo ({ 1, 3, 3, 2 }, DataType::QAsymmU8, 0.55f, 128);
891 const TensorInfo outputInfo({ 1, 2, 2, 4 }, DataType::QAsymmU8, 0.75f, 128);
893 const std::vector<float> quantScales{ 0.75f, 0.80f, 0.90f, 0.95f };
894 const unsigned int quantDimension = 0;
895 TensorInfo kernelInfo({ 2, 2, 2, 2 }, DataType::QSymmS8, quantScales, quantDimension);
897 const std::vector<float> biasQuantScales{ 0.25f, 0.35f, 0.45f, 0.55f };
898 constexpr unsigned int biasQuantDimension = 0;
899 TensorInfo biasInfo({ 4 }, DataType::Signed32, biasQuantScales, biasQuantDimension);
901 std::vector<int8_t> kernelData = GenerateRandomData<int8_t>(kernelInfo.GetNumElements());
902 armnn::ConstTensor weights(kernelInfo, kernelData);
903 std::vector<int32_t> biasData = GenerateRandomData<int32_t>(biasInfo.GetNumElements());
904 armnn::ConstTensor biases(biasInfo, biasData);
906 DepthwiseConvolution2dDescriptor descriptor;
907 descriptor.m_StrideX = 1;
908 descriptor.m_StrideY = 1;
909 descriptor.m_PadLeft = 0;
910 descriptor.m_PadRight = 0;
911 descriptor.m_PadTop = 0;
912 descriptor.m_PadBottom = 0;
913 descriptor.m_DilationX = 1;
914 descriptor.m_DilationY = 1;
915 descriptor.m_BiasEnabled = true;
916 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
918 armnn::INetworkPtr network = armnn::INetwork::Create();
919 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
920 armnn::IConnectableLayer* const depthwiseConvLayer =
921 network->AddDepthwiseConvolution2dLayer(descriptor,
923 armnn::Optional<armnn::ConstTensor>(biases),
925 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
927 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
928 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
930 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
931 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
933 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
934 BOOST_CHECK(deserializedNetwork);
936 DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
937 deserializedNetwork->Accept(verifier);
940 BOOST_AUTO_TEST_CASE(SerializeDequantize)
942 DECLARE_LAYER_VERIFIER_CLASS(Dequantize)
944 const std::string layerName("dequantize");
945 const armnn::TensorInfo inputInfo({ 1, 5, 2, 3 }, armnn::DataType::QAsymmU8, 0.5f, 1);
946 const armnn::TensorInfo outputInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
948 armnn::INetworkPtr network = armnn::INetwork::Create();
949 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
950 armnn::IConnectableLayer* const dequantizeLayer = network->AddDequantizeLayer(layerName.c_str());
951 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
953 inputLayer->GetOutputSlot(0).Connect(dequantizeLayer->GetInputSlot(0));
954 dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
956 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
957 dequantizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
959 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
960 BOOST_CHECK(deserializedNetwork);
962 DequantizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
963 deserializedNetwork->Accept(verifier);
966 BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess)
968 using Descriptor = armnn::DetectionPostProcessDescriptor;
969 class DetectionPostProcessLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
972 DetectionPostProcessLayerVerifier(const std::string& layerName,
973 const std::vector<armnn::TensorInfo>& inputInfos,
974 const std::vector<armnn::TensorInfo>& outputInfos,
975 const Descriptor& descriptor,
976 const armnn::ConstTensor& anchors)
977 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
978 , m_Anchors(anchors) {}
980 void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
981 const Descriptor& descriptor,
982 const armnn::ConstTensor& anchors,
983 const char* name) override
985 VerifyNameAndConnections(layer, name);
986 VerifyDescriptor(descriptor);
988 CompareConstTensor(anchors, m_Anchors);
992 armnn::ConstTensor m_Anchors;
995 const std::string layerName("detectionPostProcess");
997 const std::vector<armnn::TensorInfo> inputInfos({
998 armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32),
999 armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32)
1002 const std::vector<armnn::TensorInfo> outputInfos({
1003 armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32),
1004 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
1005 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
1006 armnn::TensorInfo({ 1 }, armnn::DataType::Float32)
1009 armnn::DetectionPostProcessDescriptor descriptor;
1010 descriptor.m_UseRegularNms = true;
1011 descriptor.m_MaxDetections = 3;
1012 descriptor.m_MaxClassesPerDetection = 1;
1013 descriptor.m_DetectionsPerClass =1;
1014 descriptor.m_NmsScoreThreshold = 0.0;
1015 descriptor.m_NmsIouThreshold = 0.5;
1016 descriptor.m_NumClasses = 2;
1017 descriptor.m_ScaleY = 10.0;
1018 descriptor.m_ScaleX = 10.0;
1019 descriptor.m_ScaleH = 5.0;
1020 descriptor.m_ScaleW = 5.0;
1022 const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
1023 const std::vector<float> anchorsData({
1024 0.5f, 0.5f, 1.0f, 1.0f,
1025 0.5f, 0.5f, 1.0f, 1.0f,
1026 0.5f, 0.5f, 1.0f, 1.0f,
1027 0.5f, 10.5f, 1.0f, 1.0f,
1028 0.5f, 10.5f, 1.0f, 1.0f,
1029 0.5f, 100.5f, 1.0f, 1.0f
1031 armnn::ConstTensor anchors(anchorsInfo, anchorsData);
1033 armnn::INetworkPtr network = armnn::INetwork::Create();
1034 armnn::IConnectableLayer* const detectionLayer =
1035 network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
1037 for (unsigned int i = 0; i < 2; i++)
1039 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
1040 inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
1041 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
1044 for (unsigned int i = 0; i < 4; i++)
1046 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
1047 detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
1048 detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
1051 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1052 BOOST_CHECK(deserializedNetwork);
1054 DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors);
1055 deserializedNetwork->Accept(verifier);
1058 BOOST_AUTO_TEST_CASE(SerializeDivision)
1060 DECLARE_LAYER_VERIFIER_CLASS(Division)
1062 const std::string layerName("division");
1063 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1065 armnn::INetworkPtr network = armnn::INetwork::Create();
1066 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1067 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1068 armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
1069 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1071 inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
1072 inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
1073 divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1075 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1076 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1077 divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
1079 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1080 BOOST_CHECK(deserializedNetwork);
1082 DivisionLayerVerifier verifier(layerName, {info, info}, {info});
1083 deserializedNetwork->Accept(verifier);
1086 class EqualLayerVerifier : public LayerVerifierBase
1089 EqualLayerVerifier(const std::string& layerName,
1090 const std::vector<armnn::TensorInfo>& inputInfos,
1091 const std::vector<armnn::TensorInfo>& outputInfos)
1092 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1094 void VisitComparisonLayer(const armnn::IConnectableLayer* layer,
1095 const armnn::ComparisonDescriptor& descriptor,
1096 const char* name) override
1098 VerifyNameAndConnections(layer, name);
1099 BOOST_CHECK(descriptor.m_Operation == armnn::ComparisonOperation::Equal);
1102 void VisitEqualLayer(const armnn::IConnectableLayer*, const char*) override
1104 throw armnn::Exception("EqualLayer should have translated to ComparisonLayer");
1108 // NOTE: Until the deprecated AddEqualLayer disappears this test checks that calling
1109 // AddEqualLayer places a ComparisonLayer into the serialized format and that
1110 // when this deserialises we have a ComparisonLayer
1111 BOOST_AUTO_TEST_CASE(SerializeEqual)
1113 const std::string layerName("equal");
1115 const armnn::TensorShape shape{2, 1, 2, 4};
1117 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1118 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1120 armnn::INetworkPtr network = armnn::INetwork::Create();
1121 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1122 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1123 ARMNN_NO_DEPRECATE_WARN_BEGIN
1124 armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str());
1125 ARMNN_NO_DEPRECATE_WARN_END
1126 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1128 inputLayer0->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
1129 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
1130 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1132 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
1133 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
1134 equalLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1136 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1137 BOOST_CHECK(deserializedNetwork);
1139 EqualLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo });
1140 deserializedNetwork->Accept(verifier);
1143 BOOST_AUTO_TEST_CASE(EnsureEqualBackwardCompatibility)
1145 // The hex data below is a flat buffer containing a simple network with two inputs,
1146 // an EqualLayer (now deprecated) and an output
1148 // This test verifies that we can still deserialize this old-style model by replacing
1149 // the EqualLayer with an equivalent ComparisonLayer
1150 const std::vector<uint8_t> equalModel =
1152 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1153 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1154 0xCC, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1156 0x60, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1157 0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xEA, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1158 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1160 0x64, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1161 0x00, 0x13, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1162 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1163 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x65, 0x71, 0x75, 0x61, 0x6C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1164 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1165 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00,
1166 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
1167 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1168 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1169 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1170 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1171 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1172 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1173 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1174 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1176 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1177 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1178 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
1179 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1180 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1181 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1182 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1183 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1184 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1185 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1186 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1187 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1188 0x04, 0x00, 0x00, 0x00
1191 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(equalModel.begin(), equalModel.end()));
1192 BOOST_CHECK(deserializedNetwork);
1194 const armnn::TensorShape shape{ 2, 1, 2, 4 };
1196 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1197 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1199 EqualLayerVerifier verifier("equal", { inputInfo, inputInfo }, { outputInfo });
1200 deserializedNetwork->Accept(verifier);
1203 BOOST_AUTO_TEST_CASE(SerializeFill)
1205 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Fill)
1207 const std::string layerName("fill");
1208 const armnn::TensorInfo inputInfo({4}, armnn::DataType::Signed32);
1209 const armnn::TensorInfo outputInfo({1, 3, 3, 1}, armnn::DataType::Float32);
1211 armnn::FillDescriptor descriptor(1.0f);
1213 armnn::INetworkPtr network = armnn::INetwork::Create();
1214 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1215 armnn::IConnectableLayer* const fillLayer = network->AddFillLayer(descriptor, layerName.c_str());
1216 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1218 inputLayer->GetOutputSlot(0).Connect(fillLayer->GetInputSlot(0));
1219 fillLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1221 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1222 fillLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1224 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1225 BOOST_CHECK(deserializedNetwork);
1227 FillLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1229 deserializedNetwork->Accept(verifier);
1232 BOOST_AUTO_TEST_CASE(SerializeFloor)
1234 DECLARE_LAYER_VERIFIER_CLASS(Floor)
1236 const std::string layerName("floor");
1237 const armnn::TensorInfo info({4,4}, armnn::DataType::Float32);
1239 armnn::INetworkPtr network = armnn::INetwork::Create();
1240 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1241 armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
1242 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1244 inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
1245 floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1247 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1248 floorLayer->GetOutputSlot(0).SetTensorInfo(info);
1250 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1251 BOOST_CHECK(deserializedNetwork);
1253 FloorLayerVerifier verifier(layerName, {info}, {info});
1254 deserializedNetwork->Accept(verifier);
1257 BOOST_AUTO_TEST_CASE(SerializeFullyConnected)
1259 using Descriptor = armnn::FullyConnectedDescriptor;
1260 class FullyConnectedLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
1263 FullyConnectedLayerVerifier(const std::string& layerName,
1264 const std::vector<armnn::TensorInfo>& inputInfos,
1265 const std::vector<armnn::TensorInfo>& outputInfos,
1266 const Descriptor& descriptor,
1267 const armnn::ConstTensor& weight,
1268 const armnn::Optional<armnn::ConstTensor>& bias)
1269 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
1273 void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
1274 const Descriptor& descriptor,
1275 const armnn::ConstTensor& weight,
1276 const armnn::Optional<armnn::ConstTensor>& bias,
1277 const char* name) override
1279 VerifyNameAndConnections(layer, name);
1280 VerifyDescriptor(descriptor);
1282 CompareConstTensor(weight, m_Weight);
1284 BOOST_TEST(bias.has_value() == descriptor.m_BiasEnabled);
1285 BOOST_TEST(bias.has_value() == m_Bias.has_value());
1287 if (bias.has_value() && m_Bias.has_value())
1289 CompareConstTensor(bias.value(), m_Bias.value());
1294 armnn::ConstTensor m_Weight;
1295 armnn::Optional<armnn::ConstTensor> m_Bias;
1298 const std::string layerName("fullyConnected");
1299 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
1300 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
1302 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
1303 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
1304 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
1305 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
1306 armnn::ConstTensor weights(weightsInfo, weightsData);
1307 armnn::ConstTensor biases(biasesInfo, biasesData);
1309 armnn::FullyConnectedDescriptor descriptor;
1310 descriptor.m_BiasEnabled = true;
1311 descriptor.m_TransposeWeightMatrix = false;
1313 armnn::INetworkPtr network = armnn::INetwork::Create();
1314 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1315 armnn::IConnectableLayer* const fullyConnectedLayer =
1316 network->AddFullyConnectedLayer(descriptor,
1318 armnn::Optional<armnn::ConstTensor>(biases),
1320 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1322 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
1323 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1325 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1326 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1328 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1329 BOOST_CHECK(deserializedNetwork);
1331 FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
1332 deserializedNetwork->Accept(verifier);
1335 BOOST_AUTO_TEST_CASE(SerializeGather)
1337 using GatherDescriptor = armnn::GatherDescriptor;
1338 class GatherLayerVerifier : public LayerVerifierBaseWithDescriptor<GatherDescriptor>
1341 GatherLayerVerifier(const std::string& layerName,
1342 const std::vector<armnn::TensorInfo>& inputInfos,
1343 const std::vector<armnn::TensorInfo>& outputInfos,
1344 const GatherDescriptor& descriptor)
1345 : LayerVerifierBaseWithDescriptor<GatherDescriptor>(layerName, inputInfos, outputInfos, descriptor) {}
1347 void VisitGatherLayer(const armnn::IConnectableLayer* layer,
1348 const GatherDescriptor& descriptor,
1349 const char *name) override
1351 VerifyNameAndConnections(layer, name);
1352 BOOST_CHECK(descriptor.m_Axis == m_Descriptor.m_Axis);
1355 void VisitConstantLayer(const armnn::IConnectableLayer*,
1356 const armnn::ConstTensor&,
1357 const char*) override {}
1360 const std::string layerName("gather");
1361 armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QAsymmU8);
1362 armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QAsymmU8);
1363 const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
1364 GatherDescriptor descriptor;
1365 descriptor.m_Axis = 1;
1367 paramsInfo.SetQuantizationScale(1.0f);
1368 paramsInfo.SetQuantizationOffset(0);
1369 outputInfo.SetQuantizationScale(1.0f);
1370 outputInfo.SetQuantizationOffset(0);
1372 const std::vector<int32_t>& indicesData = {7, 6, 5};
1374 armnn::INetworkPtr network = armnn::INetwork::Create();
1375 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
1376 armnn::IConnectableLayer *const constantLayer =
1377 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
1378 armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(descriptor, layerName.c_str());
1379 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
1381 inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
1382 constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
1383 gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1385 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
1386 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
1387 gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1389 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1390 BOOST_CHECK(deserializedNetwork);
1392 GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo}, descriptor);
1393 deserializedNetwork->Accept(verifier);
1396 class GreaterLayerVerifier : public LayerVerifierBase
1399 GreaterLayerVerifier(const std::string& layerName,
1400 const std::vector<armnn::TensorInfo>& inputInfos,
1401 const std::vector<armnn::TensorInfo>& outputInfos)
1402 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1404 void VisitComparisonLayer(const armnn::IConnectableLayer* layer,
1405 const armnn::ComparisonDescriptor& descriptor,
1406 const char* name) override
1408 VerifyNameAndConnections(layer, name);
1409 BOOST_CHECK(descriptor.m_Operation == armnn::ComparisonOperation::Greater);
1412 void VisitGreaterLayer(const armnn::IConnectableLayer*, const char*) override
1414 throw armnn::Exception("GreaterLayer should have translated to ComparisonLayer");
1418 // NOTE: Until the deprecated AddGreaterLayer disappears this test checks that calling
1419 // AddGreaterLayer places a ComparisonLayer into the serialized format and that
1420 // when this deserialises we have a ComparisonLayer
1421 BOOST_AUTO_TEST_CASE(SerializeGreater)
1423 const std::string layerName("greater");
1425 const armnn::TensorShape shape{2, 1, 2, 4};
1427 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1428 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1430 armnn::INetworkPtr network = armnn::INetwork::Create();
1431 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1432 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1433 ARMNN_NO_DEPRECATE_WARN_BEGIN
1434 armnn::IConnectableLayer* const equalLayer = network->AddGreaterLayer(layerName.c_str());
1435 ARMNN_NO_DEPRECATE_WARN_END
1436 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1438 inputLayer0->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
1439 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
1440 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1442 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
1443 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
1444 equalLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1446 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1447 BOOST_CHECK(deserializedNetwork);
1449 GreaterLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo });
1450 deserializedNetwork->Accept(verifier);
1453 BOOST_AUTO_TEST_CASE(EnsureGreaterBackwardCompatibility)
1455 // The hex data below is a flat buffer containing a simple network with two inputs,
1456 // an GreaterLayer (now deprecated) and an output
1458 // This test verifies that we can still deserialize this old-style model by replacing
1459 // the GreaterLayer with an equivalent ComparisonLayer
1460 const std::vector<uint8_t> greaterModel =
1462 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1463 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1464 0xCC, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1466 0x60, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1467 0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xEA, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1468 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1470 0x64, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1471 0x00, 0x19, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1472 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1473 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00,
1474 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1475 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00,
1476 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1477 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1478 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1479 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1480 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1481 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1482 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1483 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1484 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1486 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1487 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1488 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1489 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1490 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1491 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1492 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1493 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1494 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1495 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1496 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1497 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1498 0x02, 0x00, 0x00, 0x00
1501 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(greaterModel.begin(), greaterModel.end()));
1502 BOOST_CHECK(deserializedNetwork);
1504 const armnn::TensorShape shape{ 1, 2, 2, 2 };
1506 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1507 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1509 GreaterLayerVerifier verifier("greater", { inputInfo, inputInfo }, { outputInfo });
1510 deserializedNetwork->Accept(verifier);
1513 BOOST_AUTO_TEST_CASE(SerializeInstanceNormalization)
1515 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(InstanceNormalization)
1517 const std::string layerName("instanceNormalization");
1518 const armnn::TensorInfo info({ 1, 2, 1, 5 }, armnn::DataType::Float32);
1520 armnn::InstanceNormalizationDescriptor descriptor;
1521 descriptor.m_Gamma = 1.1f;
1522 descriptor.m_Beta = 0.1f;
1523 descriptor.m_Eps = 0.0001f;
1524 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
1526 armnn::INetworkPtr network = armnn::INetwork::Create();
1527 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1528 armnn::IConnectableLayer* const instanceNormLayer =
1529 network->AddInstanceNormalizationLayer(descriptor, layerName.c_str());
1530 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1532 inputLayer->GetOutputSlot(0).Connect(instanceNormLayer->GetInputSlot(0));
1533 instanceNormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1535 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1536 instanceNormLayer->GetOutputSlot(0).SetTensorInfo(info);
1538 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1539 BOOST_CHECK(deserializedNetwork);
1541 InstanceNormalizationLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1542 deserializedNetwork->Accept(verifier);
1545 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(L2Normalization)
1547 BOOST_AUTO_TEST_CASE(SerializeL2Normalization)
1549 const std::string l2NormLayerName("l2Normalization");
1550 const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1552 armnn::L2NormalizationDescriptor desc;
1553 desc.m_DataLayout = armnn::DataLayout::NCHW;
1554 desc.m_Eps = 0.0001f;
1556 armnn::INetworkPtr network = armnn::INetwork::Create();
1557 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1558 armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1559 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1561 inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1562 l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1564 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1565 l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1567 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1568 BOOST_CHECK(deserializedNetwork);
1570 L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc);
1571 deserializedNetwork->Accept(verifier);
1574 BOOST_AUTO_TEST_CASE(EnsureL2NormalizationBackwardCompatibility)
1576 // The hex data below is a flat buffer containing a simple network with one input
1577 // a L2Normalization layer and an output layer with dimensions as per the tensor infos below.
1579 // This test verifies that we can still read back these old style
1580 // models without the normalization epsilon value.
1581 const std::vector<uint8_t> l2NormalizationModel =
1583 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1584 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1585 0x3C, 0x01, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1586 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xE8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
1587 0x04, 0x00, 0x00, 0x00, 0xD6, 0xFE, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
1588 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
1589 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1591 0x4C, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
1592 0x00, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1593 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1594 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1595 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x20, 0x00,
1596 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x6C, 0x32, 0x4E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x69, 0x7A, 0x61, 0x74,
1597 0x69, 0x6F, 0x6E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00,
1598 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1599 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
1600 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1601 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1602 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1603 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1604 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1605 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1606 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1607 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1608 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1609 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1610 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1611 0x05, 0x00, 0x00, 0x00, 0x00
1614 armnn::INetworkPtr deserializedNetwork =
1615 DeserializeNetwork(std::string(l2NormalizationModel.begin(), l2NormalizationModel.end()));
1616 BOOST_CHECK(deserializedNetwork);
1618 const std::string layerName("l2Normalization");
1619 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 2, 1, 5}, armnn::DataType::Float32);
1621 armnn::L2NormalizationDescriptor desc;
1622 desc.m_DataLayout = armnn::DataLayout::NCHW;
1623 // Since this variable does not exist in the l2NormalizationModel dump, the default value will be loaded
1624 desc.m_Eps = 1e-12f;
1626 L2NormalizationLayerVerifier verifier(layerName, {inputInfo}, {inputInfo}, desc);
1627 deserializedNetwork->Accept(verifier);
1630 BOOST_AUTO_TEST_CASE(SerializeLogicalBinary)
1632 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(LogicalBinary)
1634 const std::string layerName("logicalBinaryAnd");
1636 const armnn::TensorShape shape{2, 1, 2, 2};
1638 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1639 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1641 armnn::LogicalBinaryDescriptor descriptor(armnn::LogicalBinaryOperation::LogicalAnd);
1643 armnn::INetworkPtr network = armnn::INetwork::Create();
1644 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1645 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1646 armnn::IConnectableLayer* const logicalBinaryLayer = network->AddLogicalBinaryLayer(descriptor, layerName.c_str());
1647 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1649 inputLayer0->GetOutputSlot(0).Connect(logicalBinaryLayer->GetInputSlot(0));
1650 inputLayer1->GetOutputSlot(0).Connect(logicalBinaryLayer->GetInputSlot(1));
1651 logicalBinaryLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1653 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
1654 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
1655 logicalBinaryLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1657 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1658 BOOST_CHECK(deserializedNetwork);
1660 LogicalBinaryLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo }, descriptor);
1661 deserializedNetwork->Accept(verifier);
1664 BOOST_AUTO_TEST_CASE(SerializeLogicalUnary)
1666 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(ElementwiseUnary)
1668 const std::string layerName("elementwiseUnaryLogicalNot");
1670 const armnn::TensorShape shape{2, 1, 2, 2};
1672 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1673 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1675 armnn::ElementwiseUnaryDescriptor descriptor(armnn::UnaryOperation::LogicalNot);
1677 armnn::INetworkPtr network = armnn::INetwork::Create();
1678 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1679 armnn::IConnectableLayer* const elementwiseUnaryLayer =
1680 network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1681 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1683 inputLayer->GetOutputSlot(0).Connect(elementwiseUnaryLayer->GetInputSlot(0));
1684 elementwiseUnaryLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1686 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1687 elementwiseUnaryLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1689 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1691 BOOST_CHECK(deserializedNetwork);
1693 ElementwiseUnaryLayerVerifier verifier(layerName, { inputInfo }, { outputInfo }, descriptor);
1695 deserializedNetwork->Accept(verifier);
1698 BOOST_AUTO_TEST_CASE(SerializeLogSoftmax)
1700 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(LogSoftmax)
1702 const std::string layerName("log_softmax");
1703 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
1705 armnn::LogSoftmaxDescriptor descriptor;
1706 descriptor.m_Beta = 1.0f;
1707 descriptor.m_Axis = -1;
1709 armnn::INetworkPtr network = armnn::INetwork::Create();
1710 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1711 armnn::IConnectableLayer* const logSoftmaxLayer = network->AddLogSoftmaxLayer(descriptor, layerName.c_str());
1712 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1714 inputLayer->GetOutputSlot(0).Connect(logSoftmaxLayer->GetInputSlot(0));
1715 logSoftmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1717 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1718 logSoftmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
1720 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1721 BOOST_CHECK(deserializedNetwork);
1723 LogSoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1724 deserializedNetwork->Accept(verifier);
1727 BOOST_AUTO_TEST_CASE(SerializeMaximum)
1729 DECLARE_LAYER_VERIFIER_CLASS(Maximum)
1731 const std::string layerName("maximum");
1732 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1734 armnn::INetworkPtr network = armnn::INetwork::Create();
1735 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1736 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1737 armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1738 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1740 inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1741 inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1742 maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1744 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1745 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1746 maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1748 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1749 BOOST_CHECK(deserializedNetwork);
1751 MaximumLayerVerifier verifier(layerName, {info, info}, {info});
1752 deserializedNetwork->Accept(verifier);
1755 BOOST_AUTO_TEST_CASE(SerializeMean)
1757 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Mean)
1759 const std::string layerName("mean");
1760 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1761 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1763 armnn::MeanDescriptor descriptor;
1764 descriptor.m_Axis = { 2 };
1765 descriptor.m_KeepDims = true;
1767 armnn::INetworkPtr network = armnn::INetwork::Create();
1768 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1769 armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1770 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1772 inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1773 meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1775 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1776 meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1778 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1779 BOOST_CHECK(deserializedNetwork);
1781 MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1782 deserializedNetwork->Accept(verifier);
1785 BOOST_AUTO_TEST_CASE(SerializeMerge)
1787 DECLARE_LAYER_VERIFIER_CLASS(Merge)
1789 const std::string layerName("merge");
1790 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1792 armnn::INetworkPtr network = armnn::INetwork::Create();
1793 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1794 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1795 armnn::IConnectableLayer* const mergeLayer = network->AddMergeLayer(layerName.c_str());
1796 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1798 inputLayer0->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(0));
1799 inputLayer1->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(1));
1800 mergeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1802 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1803 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1804 mergeLayer->GetOutputSlot(0).SetTensorInfo(info);
1806 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1807 BOOST_CHECK(deserializedNetwork);
1809 MergeLayerVerifier verifier(layerName, {info, info}, {info});
1810 deserializedNetwork->Accept(verifier);
1813 class MergerLayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::OriginsDescriptor>
1816 MergerLayerVerifier(const std::string& layerName,
1817 const std::vector<armnn::TensorInfo>& inputInfos,
1818 const std::vector<armnn::TensorInfo>& outputInfos,
1819 const armnn::OriginsDescriptor& descriptor)
1820 : LayerVerifierBaseWithDescriptor<armnn::OriginsDescriptor>(layerName, inputInfos, outputInfos, descriptor) {}
1822 void VisitMergerLayer(const armnn::IConnectableLayer*,
1823 const armnn::OriginsDescriptor&,
1824 const char*) override
1826 throw armnn::Exception("MergerLayer should have translated to ConcatLayer");
1829 void VisitConcatLayer(const armnn::IConnectableLayer* layer,
1830 const armnn::OriginsDescriptor& descriptor,
1831 const char* name) override
1833 VerifyNameAndConnections(layer, name);
1834 VerifyDescriptor(descriptor);
1838 // NOTE: Until the deprecated AddMergerLayer disappears this test checks that calling
1839 // AddMergerLayer places a ConcatLayer into the serialized format and that
1840 // when this deserialises we have a ConcatLayer
1841 BOOST_AUTO_TEST_CASE(SerializeMerger)
1843 const std::string layerName("merger");
1844 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1845 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1847 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1849 armnn::OriginsDescriptor descriptor =
1850 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1852 armnn::INetworkPtr network = armnn::INetwork::Create();
1853 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1854 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1855 ARMNN_NO_DEPRECATE_WARN_BEGIN
1856 armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str());
1857 ARMNN_NO_DEPRECATE_WARN_END
1858 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1860 inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
1861 inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
1862 mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1864 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1865 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1866 mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1868 std::string mergerLayerNetwork = SerializeNetwork(*network);
1869 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
1870 BOOST_CHECK(deserializedNetwork);
1872 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1873 deserializedNetwork->Accept(verifier);
1876 BOOST_AUTO_TEST_CASE(EnsureMergerLayerBackwardCompatibility)
1878 // The hex data below is a flat buffer containing a simple network with two inputs
1879 // a merger layer (now deprecated) and an output layer with dimensions as per the tensor infos below.
1881 // This test verifies that we can still read back these old style
1882 // models replacing the MergerLayers with ConcatLayers with the same parameters.
1883 const std::vector<uint8_t> mergerModel =
1885 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1886 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1887 0x38, 0x02, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1888 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1889 0xF4, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1890 0x00, 0x00, 0x9A, 0xFE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1891 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1892 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1893 0xF8, 0xFE, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1894 0x00, 0x1F, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1895 0x68, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
1896 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1897 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0x04, 0x00,
1898 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1899 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1900 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1901 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1902 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6D, 0x65, 0x72, 0x67, 0x65, 0x72, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1903 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1904 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
1905 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00,
1906 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1907 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1908 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1909 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1910 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1911 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1912 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1913 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1914 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1915 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1916 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1917 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1918 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1919 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1920 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1921 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1922 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1923 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1924 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1925 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1926 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1927 0x02, 0x00, 0x00, 0x00
1930 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(mergerModel.begin(), mergerModel.end()));
1931 BOOST_CHECK(deserializedNetwork);
1933 const armnn::TensorInfo inputInfo = armnn::TensorInfo({ 2, 3, 2, 2 }, armnn::DataType::Float32);
1934 const armnn::TensorInfo outputInfo = armnn::TensorInfo({ 4, 3, 2, 2 }, armnn::DataType::Float32);
1936 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1938 armnn::OriginsDescriptor descriptor =
1939 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1941 MergerLayerVerifier verifier("merger", { inputInfo, inputInfo }, { outputInfo }, descriptor);
1942 deserializedNetwork->Accept(verifier);
1945 BOOST_AUTO_TEST_CASE(SerializeConcat)
1947 const std::string layerName("concat");
1948 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1949 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1951 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1953 armnn::OriginsDescriptor descriptor =
1954 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1956 armnn::INetworkPtr network = armnn::INetwork::Create();
1957 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1958 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1959 armnn::IConnectableLayer* const concatLayer = network->AddConcatLayer(descriptor, layerName.c_str());
1960 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1962 inputLayerOne->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
1963 inputLayerTwo->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
1964 concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1966 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1967 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1968 concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1970 std::string concatLayerNetwork = SerializeNetwork(*network);
1971 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(concatLayerNetwork);
1972 BOOST_CHECK(deserializedNetwork);
1974 // NOTE: using the MergerLayerVerifier to ensure that it is a concat layer and not a
1975 // merger layer that gets placed into the graph.
1976 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1977 deserializedNetwork->Accept(verifier);
1980 BOOST_AUTO_TEST_CASE(SerializeMinimum)
1982 DECLARE_LAYER_VERIFIER_CLASS(Minimum)
1984 const std::string layerName("minimum");
1985 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1987 armnn::INetworkPtr network = armnn::INetwork::Create();
1988 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1989 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1990 armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1991 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1993 inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1994 inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1995 minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1997 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1998 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1999 minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
2001 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2002 BOOST_CHECK(deserializedNetwork);
2004 MinimumLayerVerifier verifier(layerName, {info, info}, {info});
2005 deserializedNetwork->Accept(verifier);
2008 BOOST_AUTO_TEST_CASE(SerializeMultiplication)
2010 DECLARE_LAYER_VERIFIER_CLASS(Multiplication)
2012 const std::string layerName("multiplication");
2013 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
2015 armnn::INetworkPtr network = armnn::INetwork::Create();
2016 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2017 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2018 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
2019 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2021 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
2022 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
2023 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2025 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2026 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2027 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
2029 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2030 BOOST_CHECK(deserializedNetwork);
2032 MultiplicationLayerVerifier verifier(layerName, {info, info}, {info});
2033 deserializedNetwork->Accept(verifier);
2036 BOOST_AUTO_TEST_CASE(SerializePrelu)
2038 DECLARE_LAYER_VERIFIER_CLASS(Prelu)
2040 const std::string layerName("prelu");
2042 armnn::TensorInfo inputTensorInfo ({ 4, 1, 2 }, armnn::DataType::Float32);
2043 armnn::TensorInfo alphaTensorInfo ({ 5, 4, 3, 1 }, armnn::DataType::Float32);
2044 armnn::TensorInfo outputTensorInfo({ 5, 4, 3, 2 }, armnn::DataType::Float32);
2046 armnn::INetworkPtr network = armnn::INetwork::Create();
2047 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2048 armnn::IConnectableLayer* const alphaLayer = network->AddInputLayer(1);
2049 armnn::IConnectableLayer* const preluLayer = network->AddPreluLayer(layerName.c_str());
2050 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2052 inputLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(0));
2053 alphaLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(1));
2054 preluLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2056 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2057 alphaLayer->GetOutputSlot(0).SetTensorInfo(alphaTensorInfo);
2058 preluLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2060 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2061 BOOST_CHECK(deserializedNetwork);
2063 PreluLayerVerifier verifier(layerName, {inputTensorInfo, alphaTensorInfo}, {outputTensorInfo});
2064 deserializedNetwork->Accept(verifier);
2067 BOOST_AUTO_TEST_CASE(SerializeNormalization)
2069 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Normalization)
2071 const std::string layerName("normalization");
2072 const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
2074 armnn::NormalizationDescriptor desc;
2075 desc.m_DataLayout = armnn::DataLayout::NCHW;
2076 desc.m_NormSize = 3;
2081 armnn::INetworkPtr network = armnn::INetwork::Create();
2082 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2083 armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
2084 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2086 inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
2087 normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2089 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2090 normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
2092 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2093 BOOST_CHECK(deserializedNetwork);
2095 NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc);
2096 deserializedNetwork->Accept(verifier);
2099 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Pad)
2101 BOOST_AUTO_TEST_CASE(SerializePad)
2103 const std::string layerName("pad");
2104 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
2105 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
2107 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
2109 armnn::INetworkPtr network = armnn::INetwork::Create();
2110 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2111 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
2112 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2114 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
2115 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2117 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2118 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2120 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2121 BOOST_CHECK(deserializedNetwork);
2123 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
2124 deserializedNetwork->Accept(verifier);
2127 BOOST_AUTO_TEST_CASE(EnsurePadBackwardCompatibility)
2129 // The PadDescriptor is being extended with a float PadValue (so a value other than 0
2130 // can be used to pad the tensor.
2132 // This test contains a binary representation of a simple input->pad->output network
2133 // prior to this change to test that the descriptor has been updated in a backward
2134 // compatible way with respect to Deserialization of older binary dumps
2135 const std::vector<uint8_t> padModel =
2137 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
2138 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2139 0x54, 0x01, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2140 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD0, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
2141 0x04, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x04, 0x00,
2142 0x00, 0x00, 0x72, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2143 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2144 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00,
2145 0x00, 0x00, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x16, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00,
2146 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
2147 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00,
2148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2149 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
2150 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
2151 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00,
2152 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
2153 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
2154 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
2155 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00,
2156 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
2157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00,
2158 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00,
2159 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
2160 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00,
2161 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
2162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
2163 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
2164 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
2165 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
2166 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00
2169 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(padModel.begin(), padModel.end()));
2170 BOOST_CHECK(deserializedNetwork);
2172 const armnn::TensorInfo inputInfo = armnn::TensorInfo({ 1, 2, 3, 4 }, armnn::DataType::Float32);
2173 const armnn::TensorInfo outputInfo = armnn::TensorInfo({ 1, 3, 5, 7 }, armnn::DataType::Float32);
2175 armnn::PadDescriptor descriptor({{ 0, 0 }, { 1, 0 }, { 1, 1 }, { 1, 2 }});
2177 PadLayerVerifier verifier("pad", { inputInfo }, { outputInfo }, descriptor);
2178 deserializedNetwork->Accept(verifier);
2181 BOOST_AUTO_TEST_CASE(SerializePermute)
2183 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Permute)
2185 const std::string layerName("permute");
2186 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
2187 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
2189 armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
2191 armnn::INetworkPtr network = armnn::INetwork::Create();
2192 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2193 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
2194 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2196 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
2197 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2199 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2200 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2202 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2203 BOOST_CHECK(deserializedNetwork);
2205 PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
2206 deserializedNetwork->Accept(verifier);
2209 BOOST_AUTO_TEST_CASE(SerializePooling2d)
2211 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Pooling2d)
2213 const std::string layerName("pooling2d");
2214 const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
2215 const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
2217 armnn::Pooling2dDescriptor desc;
2218 desc.m_DataLayout = armnn::DataLayout::NHWC;
2220 desc.m_PadBottom = 0;
2222 desc.m_PadRight = 0;
2223 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
2224 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
2225 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
2226 desc.m_PoolHeight = 2;
2227 desc.m_PoolWidth = 2;
2231 armnn::INetworkPtr network = armnn::INetwork::Create();
2232 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2233 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
2234 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2236 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
2237 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2239 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2240 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2242 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2243 BOOST_CHECK(deserializedNetwork);
2245 Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2246 deserializedNetwork->Accept(verifier);
2249 BOOST_AUTO_TEST_CASE(SerializeQuantize)
2251 DECLARE_LAYER_VERIFIER_CLASS(Quantize)
2253 const std::string layerName("quantize");
2254 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
2256 armnn::INetworkPtr network = armnn::INetwork::Create();
2257 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2258 armnn::IConnectableLayer* const quantizeLayer = network->AddQuantizeLayer(layerName.c_str());
2259 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2261 inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
2262 quantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2264 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2265 quantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
2267 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2268 BOOST_CHECK(deserializedNetwork);
2270 QuantizeLayerVerifier verifier(layerName, {info}, {info});
2271 deserializedNetwork->Accept(verifier);
2274 BOOST_AUTO_TEST_CASE(SerializeRank)
2276 DECLARE_LAYER_VERIFIER_CLASS(Rank)
2278 const std::string layerName("rank");
2279 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
2280 const armnn::TensorInfo outputInfo({1}, armnn::DataType::Signed32);
2282 armnn::INetworkPtr network = armnn::INetwork::Create();
2283 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2284 armnn::IConnectableLayer* const rankLayer = network->AddRankLayer(layerName.c_str());
2285 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2287 inputLayer->GetOutputSlot(0).Connect(rankLayer->GetInputSlot(0));
2288 rankLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2290 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2291 rankLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2293 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2294 BOOST_CHECK(deserializedNetwork);
2296 RankLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
2297 deserializedNetwork->Accept(verifier);
2300 BOOST_AUTO_TEST_CASE(SerializeReshape)
2302 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Reshape)
2304 const std::string layerName("reshape");
2305 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
2306 const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
2308 armnn::ReshapeDescriptor descriptor({3, 3});
2310 armnn::INetworkPtr network = armnn::INetwork::Create();
2311 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2312 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
2313 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2315 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
2316 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2318 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2319 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2321 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2322 BOOST_CHECK(deserializedNetwork);
2324 ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2325 deserializedNetwork->Accept(verifier);
2328 BOOST_AUTO_TEST_CASE(SerializeResize)
2330 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Resize)
2332 const std::string layerName("resize");
2333 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2334 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2336 armnn::ResizeDescriptor desc;
2337 desc.m_TargetWidth = 4;
2338 desc.m_TargetHeight = 2;
2339 desc.m_Method = armnn::ResizeMethod::NearestNeighbor;
2340 desc.m_AlignCorners = true;
2341 desc.m_HalfPixelCenters = true;
2343 armnn::INetworkPtr network = armnn::INetwork::Create();
2344 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2345 armnn::IConnectableLayer* const resizeLayer = network->AddResizeLayer(desc, layerName.c_str());
2346 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2348 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2349 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2351 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2352 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2354 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2355 BOOST_CHECK(deserializedNetwork);
2357 ResizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2358 deserializedNetwork->Accept(verifier);
2361 class ResizeBilinearLayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::ResizeBilinearDescriptor>
2364 ResizeBilinearLayerVerifier(const std::string& layerName,
2365 const std::vector<armnn::TensorInfo>& inputInfos,
2366 const std::vector<armnn::TensorInfo>& outputInfos,
2367 const armnn::ResizeBilinearDescriptor& descriptor)
2368 : LayerVerifierBaseWithDescriptor<armnn::ResizeBilinearDescriptor>(
2369 layerName, inputInfos, outputInfos, descriptor) {}
2371 void VisitResizeLayer(const armnn::IConnectableLayer* layer,
2372 const armnn::ResizeDescriptor& descriptor,
2373 const char* name) override
2375 VerifyNameAndConnections(layer, name);
2377 BOOST_CHECK(descriptor.m_Method == armnn::ResizeMethod::Bilinear);
2378 BOOST_CHECK(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
2379 BOOST_CHECK(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
2380 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2381 BOOST_CHECK(descriptor.m_AlignCorners == m_Descriptor.m_AlignCorners);
2382 BOOST_CHECK(descriptor.m_HalfPixelCenters == m_Descriptor.m_HalfPixelCenters);
2385 void VisitResizeBilinearLayer(const armnn::IConnectableLayer*,
2386 const armnn::ResizeBilinearDescriptor&,
2387 const char*) override
2389 throw armnn::Exception("ResizeBilinearLayer should have translated to ResizeLayer");
2393 // NOTE: Until the deprecated AddResizeBilinearLayer disappears this test checks that
2394 // calling AddResizeBilinearLayer places a ResizeLayer into the serialized format
2395 // and that when this deserialises we have a ResizeLayer
2396 BOOST_AUTO_TEST_CASE(SerializeResizeBilinear)
2398 const std::string layerName("resizeBilinear");
2399 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2400 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2402 armnn::ResizeBilinearDescriptor desc;
2403 desc.m_TargetWidth = 4u;
2404 desc.m_TargetHeight = 2u;
2405 desc.m_AlignCorners = true;
2406 desc.m_HalfPixelCenters = true;
2408 armnn::INetworkPtr network = armnn::INetwork::Create();
2409 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2410 ARMNN_NO_DEPRECATE_WARN_BEGIN
2411 armnn::IConnectableLayer* const resizeLayer = network->AddResizeBilinearLayer(desc, layerName.c_str());
2412 ARMNN_NO_DEPRECATE_WARN_END
2413 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2415 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2416 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2418 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2419 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2421 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2422 BOOST_CHECK(deserializedNetwork);
2424 ResizeBilinearLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2425 deserializedNetwork->Accept(verifier);
2428 BOOST_AUTO_TEST_CASE(EnsureResizeBilinearBackwardCompatibility)
2430 // The hex data below is a flat buffer containing a simple network with an input,
2431 // a ResizeBilinearLayer (now deprecated) and an output
2433 // This test verifies that we can still deserialize this old-style model by replacing
2434 // the ResizeBilinearLayer with an equivalent ResizeLayer
2435 const std::vector<uint8_t> resizeBilinearModel =
2437 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
2438 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2439 0x50, 0x01, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2440 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD4, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
2441 0x04, 0x00, 0x00, 0x00, 0xC2, 0xFE, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
2442 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8A, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
2443 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
2444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2445 0x38, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
2446 0x00, 0x1A, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
2447 0x34, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x12, 0x00, 0x08, 0x00, 0x0C, 0x00,
2448 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2449 0x00, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00,
2450 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
2451 0x20, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x69, 0x7A, 0x65, 0x42, 0x69, 0x6C, 0x69,
2452 0x6E, 0x65, 0x61, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2453 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
2454 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2455 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
2456 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2457 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
2458 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
2459 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00,
2460 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
2461 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00,
2463 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
2464 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
2465 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00,
2466 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
2469 armnn::INetworkPtr deserializedNetwork =
2470 DeserializeNetwork(std::string(resizeBilinearModel.begin(), resizeBilinearModel.end()));
2471 BOOST_CHECK(deserializedNetwork);
2473 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2474 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2476 armnn::ResizeBilinearDescriptor descriptor;
2477 descriptor.m_TargetWidth = 4u;
2478 descriptor.m_TargetHeight = 2u;
2480 ResizeBilinearLayerVerifier verifier("resizeBilinear", { inputInfo }, { outputInfo }, descriptor);
2481 deserializedNetwork->Accept(verifier);
2484 BOOST_AUTO_TEST_CASE(SerializeSlice)
2486 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Slice)
2488 const std::string layerName{"slice"};
2490 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2491 const armnn::TensorInfo outputInfo = armnn::TensorInfo({2, 2, 2, 1}, armnn::DataType::Float32);
2493 armnn::SliceDescriptor descriptor({ 0, 0, 1, 0}, {2, 2, 2, 1});
2495 armnn::INetworkPtr network = armnn::INetwork::Create();
2497 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2498 armnn::IConnectableLayer* const sliceLayer = network->AddSliceLayer(descriptor, layerName.c_str());
2499 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2501 inputLayer->GetOutputSlot(0).Connect(sliceLayer->GetInputSlot(0));
2502 sliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2504 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2505 sliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2507 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2508 BOOST_CHECK(deserializedNetwork);
2510 SliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2511 deserializedNetwork->Accept(verifier);
2514 BOOST_AUTO_TEST_CASE(SerializeSoftmax)
2516 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Softmax)
2518 const std::string layerName("softmax");
2519 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
2521 armnn::SoftmaxDescriptor descriptor;
2522 descriptor.m_Beta = 1.0f;
2524 armnn::INetworkPtr network = armnn::INetwork::Create();
2525 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2526 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
2527 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2529 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
2530 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2532 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2533 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
2535 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2536 BOOST_CHECK(deserializedNetwork);
2538 SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
2539 deserializedNetwork->Accept(verifier);
2542 BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
2544 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(SpaceToBatchNd)
2546 const std::string layerName("spaceToBatchNd");
2547 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
2548 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
2550 armnn::SpaceToBatchNdDescriptor desc;
2551 desc.m_DataLayout = armnn::DataLayout::NCHW;
2552 desc.m_BlockShape = {2, 2};
2553 desc.m_PadList = {{0, 0}, {2, 0}};
2555 armnn::INetworkPtr network = armnn::INetwork::Create();
2556 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2557 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2558 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2560 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
2561 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2563 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2564 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2566 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2567 BOOST_CHECK(deserializedNetwork);
2569 SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2570 deserializedNetwork->Accept(verifier);
2573 BOOST_AUTO_TEST_CASE(SerializeSpaceToDepth)
2575 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(SpaceToDepth)
2577 const std::string layerName("spaceToDepth");
2579 const armnn::TensorInfo inputInfo ({ 1, 16, 8, 3 }, armnn::DataType::Float32);
2580 const armnn::TensorInfo outputInfo({ 1, 8, 4, 12 }, armnn::DataType::Float32);
2582 armnn::SpaceToDepthDescriptor desc;
2583 desc.m_BlockSize = 2;
2584 desc.m_DataLayout = armnn::DataLayout::NHWC;
2586 armnn::INetworkPtr network = armnn::INetwork::Create();
2587 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2588 armnn::IConnectableLayer* const spaceToDepthLayer = network->AddSpaceToDepthLayer(desc, layerName.c_str());
2589 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2591 inputLayer->GetOutputSlot(0).Connect(spaceToDepthLayer->GetInputSlot(0));
2592 spaceToDepthLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2594 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2595 spaceToDepthLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2597 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2598 BOOST_CHECK(deserializedNetwork);
2600 SpaceToDepthLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2601 deserializedNetwork->Accept(verifier);
2604 BOOST_AUTO_TEST_CASE(SerializeSplitter)
2606 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Splitter)
2608 const unsigned int numViews = 3;
2609 const unsigned int numDimensions = 4;
2610 const unsigned int inputShape[] = {1, 18, 4, 4};
2611 const unsigned int outputShape[] = {1, 6, 4, 4};
2613 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
2614 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
2615 static_cast<unsigned int>(inputShape[1]),
2616 static_cast<unsigned int>(inputShape[2]),
2617 static_cast<unsigned int>(inputShape[3])};
2618 splitterDimSizes[1] /= numViews;
2619 armnn::ViewsDescriptor desc(numViews, numDimensions);
2621 for (unsigned int g = 0; g < numViews; ++g)
2623 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
2625 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
2627 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
2631 const std::string layerName("splitter");
2632 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
2633 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
2635 armnn::INetworkPtr network = armnn::INetwork::Create();
2636 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2637 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
2638 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2639 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2640 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
2642 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
2643 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2644 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2645 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
2647 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2648 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2649 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
2650 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2652 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2653 BOOST_CHECK(deserializedNetwork);
2655 SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
2656 deserializedNetwork->Accept(verifier);
2659 BOOST_AUTO_TEST_CASE(SerializeStack)
2661 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Stack)
2663 const std::string layerName("stack");
2665 armnn::TensorInfo inputTensorInfo ({4, 3, 5}, armnn::DataType::Float32);
2666 armnn::TensorInfo outputTensorInfo({4, 3, 2, 5}, armnn::DataType::Float32);
2668 armnn::StackDescriptor descriptor(2, 2, {4, 3, 5});
2670 armnn::INetworkPtr network = armnn::INetwork::Create();
2671 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
2672 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
2673 armnn::IConnectableLayer* const stackLayer = network->AddStackLayer(descriptor, layerName.c_str());
2674 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2676 inputLayer1->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(0));
2677 inputLayer2->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(1));
2678 stackLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2680 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2681 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2682 stackLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2684 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2685 BOOST_CHECK(deserializedNetwork);
2687 StackLayerVerifier verifier(layerName, {inputTensorInfo, inputTensorInfo}, {outputTensorInfo}, descriptor);
2688 deserializedNetwork->Accept(verifier);
2691 BOOST_AUTO_TEST_CASE(SerializeStandIn)
2693 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(StandIn)
2695 const std::string layerName("standIn");
2697 armnn::TensorInfo tensorInfo({ 1u }, armnn::DataType::Float32);
2698 armnn::StandInDescriptor descriptor(2u, 2u);
2700 armnn::INetworkPtr network = armnn::INetwork::Create();
2701 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2702 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2703 armnn::IConnectableLayer* const standInLayer = network->AddStandInLayer(descriptor, layerName.c_str());
2704 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2705 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2707 inputLayer0->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(0));
2708 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2710 inputLayer1->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(1));
2711 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2713 standInLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2714 standInLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2716 standInLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2717 standInLayer->GetOutputSlot(1).SetTensorInfo(tensorInfo);
2719 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2720 BOOST_CHECK(deserializedNetwork);
2722 StandInLayerVerifier verifier(layerName, { tensorInfo, tensorInfo }, { tensorInfo, tensorInfo }, descriptor);
2723 deserializedNetwork->Accept(verifier);
2726 BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
2728 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(StridedSlice)
2730 const std::string layerName("stridedSlice");
2731 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2732 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2734 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2735 desc.m_EndMask = (1 << 4) - 1;
2736 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2737 desc.m_DataLayout = armnn::DataLayout::NCHW;
2739 armnn::INetworkPtr network = armnn::INetwork::Create();
2740 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2741 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2742 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2744 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2745 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2747 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2748 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2750 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2751 BOOST_CHECK(deserializedNetwork);
2753 StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2754 deserializedNetwork->Accept(verifier);
2757 BOOST_AUTO_TEST_CASE(SerializeSubtraction)
2759 DECLARE_LAYER_VERIFIER_CLASS(Subtraction)
2761 const std::string layerName("subtraction");
2762 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2764 armnn::INetworkPtr network = armnn::INetwork::Create();
2765 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2766 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2767 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2768 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2770 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2771 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2772 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2774 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2775 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2776 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2778 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2779 BOOST_CHECK(deserializedNetwork);
2781 SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
2782 deserializedNetwork->Accept(verifier);
2785 BOOST_AUTO_TEST_CASE(SerializeSwitch)
2787 class SwitchLayerVerifier : public LayerVerifierBase
2790 SwitchLayerVerifier(const std::string& layerName,
2791 const std::vector<armnn::TensorInfo>& inputInfos,
2792 const std::vector<armnn::TensorInfo>& outputInfos)
2793 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2795 void VisitSwitchLayer(const armnn::IConnectableLayer* layer, const char* name) override
2797 VerifyNameAndConnections(layer, name);
2800 void VisitConstantLayer(const armnn::IConnectableLayer*,
2801 const armnn::ConstTensor&,
2802 const char*) override {}
2805 const std::string layerName("switch");
2806 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2808 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2809 armnn::ConstTensor constTensor(info, constantData);
2811 armnn::INetworkPtr network = armnn::INetwork::Create();
2812 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2813 armnn::IConnectableLayer* const constantLayer = network->AddConstantLayer(constTensor, "constant");
2814 armnn::IConnectableLayer* const switchLayer = network->AddSwitchLayer(layerName.c_str());
2815 armnn::IConnectableLayer* const trueOutputLayer = network->AddOutputLayer(0);
2816 armnn::IConnectableLayer* const falseOutputLayer = network->AddOutputLayer(1);
2818 inputLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(0));
2819 constantLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(1));
2820 switchLayer->GetOutputSlot(0).Connect(trueOutputLayer->GetInputSlot(0));
2821 switchLayer->GetOutputSlot(1).Connect(falseOutputLayer->GetInputSlot(0));
2823 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2824 constantLayer->GetOutputSlot(0).SetTensorInfo(info);
2825 switchLayer->GetOutputSlot(0).SetTensorInfo(info);
2826 switchLayer->GetOutputSlot(1).SetTensorInfo(info);
2828 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2829 BOOST_CHECK(deserializedNetwork);
2831 SwitchLayerVerifier verifier(layerName, {info, info}, {info, info});
2832 deserializedNetwork->Accept(verifier);
2835 BOOST_AUTO_TEST_CASE(SerializeTranspose)
2837 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Transpose)
2839 const std::string layerName("transpose");
2840 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
2841 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
2843 armnn::TransposeDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
2845 armnn::INetworkPtr network = armnn::INetwork::Create();
2846 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2847 armnn::IConnectableLayer* const transposeLayer = network->AddTransposeLayer(descriptor, layerName.c_str());
2848 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2850 inputLayer->GetOutputSlot(0).Connect(transposeLayer->GetInputSlot(0));
2851 transposeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2853 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2854 transposeLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2856 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2857 BOOST_CHECK(deserializedNetwork);
2859 TransposeLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
2860 deserializedNetwork->Accept(verifier);
2863 BOOST_AUTO_TEST_CASE(SerializeTransposeConvolution2d)
2865 using Descriptor = armnn::TransposeConvolution2dDescriptor;
2866 class TransposeConvolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
2869 TransposeConvolution2dLayerVerifier(const std::string& layerName,
2870 const std::vector<armnn::TensorInfo>& inputInfos,
2871 const std::vector<armnn::TensorInfo>& outputInfos,
2872 const Descriptor& descriptor,
2873 const armnn::ConstTensor& weights,
2874 const armnn::Optional<armnn::ConstTensor>& biases)
2875 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
2876 , m_Weights(weights)
2880 void VisitTransposeConvolution2dLayer(const armnn::IConnectableLayer* layer,
2881 const Descriptor& descriptor,
2882 const armnn::ConstTensor& weights,
2883 const armnn::Optional<armnn::ConstTensor>& biases,
2884 const char* name) override
2886 VerifyNameAndConnections(layer, name);
2887 VerifyDescriptor(descriptor);
2890 CompareConstTensor(weights, m_Weights);
2893 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
2894 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
2896 if (biases.has_value() && m_Biases.has_value())
2898 CompareConstTensor(biases.value(), m_Biases.value());
2903 armnn::ConstTensor m_Weights;
2904 armnn::Optional<armnn::ConstTensor> m_Biases;
2907 const std::string layerName("transposeConvolution2d");
2908 const armnn::TensorInfo inputInfo ({ 1, 7, 7, 1 }, armnn::DataType::Float32);
2909 const armnn::TensorInfo outputInfo({ 1, 9, 9, 1 }, armnn::DataType::Float32);
2911 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
2912 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
2914 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
2915 armnn::ConstTensor weights(weightsInfo, weightsData);
2917 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
2918 armnn::ConstTensor biases(biasesInfo, biasesData);
2920 armnn::TransposeConvolution2dDescriptor descriptor;
2921 descriptor.m_PadLeft = 1;
2922 descriptor.m_PadRight = 1;
2923 descriptor.m_PadTop = 1;
2924 descriptor.m_PadBottom = 1;
2925 descriptor.m_StrideX = 1;
2926 descriptor.m_StrideY = 1;
2927 descriptor.m_BiasEnabled = true;
2928 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
2930 armnn::INetworkPtr network = armnn::INetwork::Create();
2931 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2932 armnn::IConnectableLayer* const convLayer =
2933 network->AddTransposeConvolution2dLayer(descriptor,
2935 armnn::Optional<armnn::ConstTensor>(biases),
2937 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2939 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
2940 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2942 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2943 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2945 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2946 BOOST_CHECK(deserializedNetwork);
2948 TransposeConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
2949 deserializedNetwork->Accept(verifier);
2952 BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
2954 class ConstantLayerVerifier : public LayerVerifierBase
2957 ConstantLayerVerifier(const std::string& layerName,
2958 const std::vector<armnn::TensorInfo>& inputInfos,
2959 const std::vector<armnn::TensorInfo>& outputInfos,
2960 const armnn::ConstTensor& layerInput)
2961 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2962 , m_LayerInput(layerInput) {}
2964 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2965 const armnn::ConstTensor& input,
2966 const char* name) override
2968 VerifyNameAndConnections(layer, name);
2969 CompareConstTensor(input, m_LayerInput);
2972 void VisitAdditionLayer(const armnn::IConnectableLayer*, const char*) override {}
2975 armnn::ConstTensor m_LayerInput;
2978 const std::string layerName("constant");
2979 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
2981 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2982 armnn::ConstTensor constTensor(info, constantData);
2984 armnn::INetworkPtr network(armnn::INetwork::Create());
2985 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2986 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2987 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2988 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2990 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2991 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2992 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2994 input->GetOutputSlot(0).SetTensorInfo(info);
2995 constant->GetOutputSlot(0).SetTensorInfo(info);
2996 add->GetOutputSlot(0).SetTensorInfo(info);
2998 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2999 BOOST_CHECK(deserializedNetwork);
3001 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
3002 deserializedNetwork->Accept(verifier);
3005 class VerifyLstmLayer : public LayerVerifierBaseWithDescriptor<armnn::LstmDescriptor>
3008 VerifyLstmLayer(const std::string& layerName,
3009 const std::vector<armnn::TensorInfo>& inputInfos,
3010 const std::vector<armnn::TensorInfo>& outputInfos,
3011 const armnn::LstmDescriptor& descriptor,
3012 const armnn::LstmInputParams& inputParams)
3013 : LayerVerifierBaseWithDescriptor<armnn::LstmDescriptor>(layerName, inputInfos, outputInfos, descriptor)
3014 , m_InputParams(inputParams) {}
3016 void VisitLstmLayer(const armnn::IConnectableLayer* layer,
3017 const armnn::LstmDescriptor& descriptor,
3018 const armnn::LstmInputParams& params,
3021 VerifyNameAndConnections(layer, name);
3022 VerifyDescriptor(descriptor);
3023 VerifyInputParameters(params);
3027 void VerifyInputParameters(const armnn::LstmInputParams& params)
3030 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
3032 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
3034 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
3036 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
3038 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
3040 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
3042 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
3044 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
3046 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
3048 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
3050 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
3052 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
3054 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
3056 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
3058 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
3060 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
3062 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
3064 "m_InputLayerNormWeights", m_InputParams.m_InputLayerNormWeights, params.m_InputLayerNormWeights);
3066 "m_ForgetLayerNormWeights", m_InputParams.m_ForgetLayerNormWeights, params.m_ForgetLayerNormWeights);
3068 "m_CellLayerNormWeights", m_InputParams.m_CellLayerNormWeights, params.m_CellLayerNormWeights);
3070 "m_OutputLayerNormWeights", m_InputParams.m_OutputLayerNormWeights, params.m_OutputLayerNormWeights);
3074 armnn::LstmInputParams m_InputParams;
3077 BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
3079 armnn::LstmDescriptor descriptor;
3080 descriptor.m_ActivationFunc = 4;
3081 descriptor.m_ClippingThresProj = 0.0f;
3082 descriptor.m_ClippingThresCell = 0.0f;
3083 descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
3084 descriptor.m_ProjectionEnabled = false;
3085 descriptor.m_PeepholeEnabled = true;
3087 const uint32_t batchSize = 1;
3088 const uint32_t inputSize = 2;
3089 const uint32_t numUnits = 4;
3090 const uint32_t outputSize = numUnits;
3092 armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
3093 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
3094 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
3096 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
3097 armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
3099 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
3100 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
3102 armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
3103 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
3104 armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
3106 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
3107 armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
3109 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
3110 armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
3112 armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
3113 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
3114 armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
3116 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
3117 armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
3119 std::vector<float> forgetGateBiasData(numUnits, 1.0f);
3120 armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
3122 std::vector<float> cellBiasData(numUnits, 0.0f);
3123 armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
3125 std::vector<float> outputGateBiasData(numUnits, 0.0f);
3126 armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
3128 armnn::LstmInputParams params;
3129 params.m_InputToForgetWeights = &inputToForgetWeights;
3130 params.m_InputToCellWeights = &inputToCellWeights;
3131 params.m_InputToOutputWeights = &inputToOutputWeights;
3132 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3133 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3134 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3135 params.m_ForgetGateBias = &forgetGateBias;
3136 params.m_CellBias = &cellBias;
3137 params.m_OutputGateBias = &outputGateBias;
3138 params.m_CellToForgetWeights = &cellToForgetWeights;
3139 params.m_CellToOutputWeights = &cellToOutputWeights;
3141 armnn::INetworkPtr network = armnn::INetwork::Create();
3142 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3143 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3144 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3145 const std::string layerName("lstm");
3146 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3147 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3148 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3149 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3150 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3153 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3154 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3155 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3156 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
3158 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3159 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3161 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3162 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3164 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3165 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3167 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3168 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3170 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3171 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3173 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3174 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3176 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3177 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3179 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3180 BOOST_CHECK(deserializedNetwork);
3182 VerifyLstmLayer checker(
3184 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3185 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3188 deserializedNetwork->Accept(checker);
3191 BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
3193 armnn::LstmDescriptor descriptor;
3194 descriptor.m_ActivationFunc = 4;
3195 descriptor.m_ClippingThresProj = 0.0f;
3196 descriptor.m_ClippingThresCell = 0.0f;
3197 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
3198 descriptor.m_ProjectionEnabled = true;
3199 descriptor.m_PeepholeEnabled = true;
3201 const uint32_t batchSize = 2;
3202 const uint32_t inputSize = 5;
3203 const uint32_t numUnits = 20;
3204 const uint32_t outputSize = 16;
3206 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3207 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3208 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3210 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3211 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3213 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3214 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3216 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3217 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3219 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3220 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3221 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3223 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3224 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3226 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3227 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3229 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3230 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3232 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3233 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3234 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3236 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3237 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3239 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3240 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3242 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3243 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3245 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3246 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3248 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3249 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3251 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3252 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3254 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3255 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
3256 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3258 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3259 std::vector<float> projectionBiasData(outputSize, 0.f);
3260 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3262 armnn::LstmInputParams params;
3263 params.m_InputToForgetWeights = &inputToForgetWeights;
3264 params.m_InputToCellWeights = &inputToCellWeights;
3265 params.m_InputToOutputWeights = &inputToOutputWeights;
3266 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3267 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3268 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3269 params.m_ForgetGateBias = &forgetGateBias;
3270 params.m_CellBias = &cellBias;
3271 params.m_OutputGateBias = &outputGateBias;
3273 // additional params because: descriptor.m_CifgEnabled = false
3274 params.m_InputToInputWeights = &inputToInputWeights;
3275 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3276 params.m_CellToInputWeights = &cellToInputWeights;
3277 params.m_InputGateBias = &inputGateBias;
3279 // additional params because: descriptor.m_ProjectionEnabled = true
3280 params.m_ProjectionWeights = &projectionWeights;
3281 params.m_ProjectionBias = &projectionBias;
3283 // additional params because: descriptor.m_PeepholeEnabled = true
3284 params.m_CellToForgetWeights = &cellToForgetWeights;
3285 params.m_CellToOutputWeights = &cellToOutputWeights;
3287 armnn::INetworkPtr network = armnn::INetwork::Create();
3288 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3289 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3290 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3291 const std::string layerName("lstm");
3292 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3293 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3294 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3295 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3296 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3299 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3300 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3301 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3302 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3304 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3305 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3307 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3308 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3310 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3311 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3313 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3314 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3316 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3317 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3319 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3320 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3322 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3323 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3325 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3326 BOOST_CHECK(deserializedNetwork);
3328 VerifyLstmLayer checker(
3330 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3331 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3334 deserializedNetwork->Accept(checker);
3337 BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeWithProjectionWithLayerNorm)
3339 armnn::LstmDescriptor descriptor;
3340 descriptor.m_ActivationFunc = 4;
3341 descriptor.m_ClippingThresProj = 0.0f;
3342 descriptor.m_ClippingThresCell = 0.0f;
3343 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
3344 descriptor.m_ProjectionEnabled = true;
3345 descriptor.m_PeepholeEnabled = true;
3346 descriptor.m_LayerNormEnabled = true;
3348 const uint32_t batchSize = 2;
3349 const uint32_t inputSize = 5;
3350 const uint32_t numUnits = 20;
3351 const uint32_t outputSize = 16;
3353 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3354 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3355 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3357 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3358 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3360 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3361 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3363 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3364 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3366 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3367 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3368 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3370 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3371 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3373 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3374 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3376 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3377 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3379 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3380 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3381 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3383 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3384 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3386 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3387 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3389 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3390 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3392 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3393 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3395 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3396 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3398 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3399 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3401 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3402 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
3403 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3405 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3406 std::vector<float> projectionBiasData(outputSize, 0.f);
3407 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3409 std::vector<float> inputLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3410 armnn::ConstTensor inputLayerNormWeights(tensorInfo20, forgetGateBiasData);
3412 std::vector<float> forgetLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3413 armnn::ConstTensor forgetLayerNormWeights(tensorInfo20, forgetGateBiasData);
3415 std::vector<float> cellLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3416 armnn::ConstTensor cellLayerNormWeights(tensorInfo20, forgetGateBiasData);
3418 std::vector<float> outLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3419 armnn::ConstTensor outLayerNormWeights(tensorInfo20, forgetGateBiasData);
3421 armnn::LstmInputParams params;
3422 params.m_InputToForgetWeights = &inputToForgetWeights;
3423 params.m_InputToCellWeights = &inputToCellWeights;
3424 params.m_InputToOutputWeights = &inputToOutputWeights;
3425 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3426 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3427 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3428 params.m_ForgetGateBias = &forgetGateBias;
3429 params.m_CellBias = &cellBias;
3430 params.m_OutputGateBias = &outputGateBias;
3432 // additional params because: descriptor.m_CifgEnabled = false
3433 params.m_InputToInputWeights = &inputToInputWeights;
3434 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3435 params.m_CellToInputWeights = &cellToInputWeights;
3436 params.m_InputGateBias = &inputGateBias;
3438 // additional params because: descriptor.m_ProjectionEnabled = true
3439 params.m_ProjectionWeights = &projectionWeights;
3440 params.m_ProjectionBias = &projectionBias;
3442 // additional params because: descriptor.m_PeepholeEnabled = true
3443 params.m_CellToForgetWeights = &cellToForgetWeights;
3444 params.m_CellToOutputWeights = &cellToOutputWeights;
3446 // additional params because: despriptor.m_LayerNormEnabled = true
3447 params.m_InputLayerNormWeights = &inputLayerNormWeights;
3448 params.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
3449 params.m_CellLayerNormWeights = &cellLayerNormWeights;
3450 params.m_OutputLayerNormWeights = &outLayerNormWeights;
3452 armnn::INetworkPtr network = armnn::INetwork::Create();
3453 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3454 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3455 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3456 const std::string layerName("lstm");
3457 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3458 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3459 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3460 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3461 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3464 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3465 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3466 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3467 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3469 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3470 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3472 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3473 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3475 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3476 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3478 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3479 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3481 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3482 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3484 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3485 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3487 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3488 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3490 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3491 BOOST_CHECK(deserializedNetwork);
3493 VerifyLstmLayer checker(
3495 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3496 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3499 deserializedNetwork->Accept(checker);
3502 BOOST_AUTO_TEST_CASE(EnsureLstmLayersBackwardCompatibility)
3504 // The hex data below is a flat buffer containing a lstm layer with no Cifg, with peephole and projection
3505 // enabled. That data was obtained before additional layer normalization parameters where added to the
3506 // lstm serializer. That way it can be tested if a lstm model with the old parameter configuration can
3508 const std::vector<uint8_t> lstmNoCifgWithPeepholeAndProjectionModel =
3510 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
3511 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
3512 0xDC, 0x29, 0x00, 0x00, 0x38, 0x29, 0x00, 0x00, 0xB4, 0x28, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x3C, 0x01,
3513 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
3514 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
3515 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x70, 0xD6, 0xFF, 0xFF,
3516 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x06, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x88, 0xD7,
3517 0xFF, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF6, 0xD6, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,
3518 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
3519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3520 0xE8, 0xD7, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xC8, 0xD6, 0xFF, 0xFF, 0x00, 0x00,
3521 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x5E, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xE0, 0xD7, 0xFF, 0xFF,
3522 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4E, 0xD7, 0xFF, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
3523 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3524 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xD8,
3525 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
3526 0x04, 0x00, 0x00, 0x00, 0xB6, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x38, 0xD8, 0xFF, 0xFF, 0x08, 0x00,
3527 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA6, 0xD7, 0xFF, 0xFF, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3528 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3529 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xD8, 0xFF, 0xFF,
3530 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00,
3531 0x00, 0x00, 0x0E, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x16, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
3532 0xFA, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00,
3533 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3534 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xD8, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
3535 0x00, 0x00, 0x6C, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
3536 0x12, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xE0, 0x25, 0x00, 0x00, 0xD0, 0x25,
3537 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x48, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00,
3538 0x10, 0x00, 0x14, 0x00, 0x18, 0x00, 0x1C, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2C, 0x00, 0x30, 0x00,
3539 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x40, 0x00, 0x44, 0x00, 0x26, 0x00, 0x00, 0x00, 0xC4, 0x23, 0x00, 0x00,
3540 0xF8, 0x21, 0x00, 0x00, 0x2C, 0x20, 0x00, 0x00, 0xF0, 0x1A, 0x00, 0x00, 0xB4, 0x15, 0x00, 0x00, 0x78, 0x10,
3541 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x68, 0x0F, 0x00, 0x00, 0xE0, 0x0E, 0x00, 0x00, 0x14, 0x0D, 0x00, 0x00,
3542 0xD8, 0x07, 0x00, 0x00, 0x50, 0x07, 0x00, 0x00, 0xC8, 0x06, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x14, 0x01,
3543 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xEE, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3544 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3550 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x72, 0xD8,
3551 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x82, 0xD9, 0xFF, 0xFF,
3552 0x04, 0x00, 0x00, 0x00, 0x14, 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, 0x00, 0x00,
3556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xD8,
3557 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3558 0x14, 0x00, 0x00, 0x00, 0xF6, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x54, 0x00, 0x00, 0x00, 0x04, 0x00,
3559 0x00, 0x00, 0x06, 0xDA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x10, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xD9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3564 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6A, 0xD9, 0xFF, 0xFF, 0x00, 0x00,
3565 0x00, 0x03, 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7A, 0xDA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
3566 0x40, 0x01, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xDE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3638 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xA2, 0xDE,
3639 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB2, 0xDF, 0xFF, 0xFF,
3640 0x04, 0x00, 0x00, 0x00, 0x14, 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, 0x00, 0x00,
3644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xDF,
3645 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3646 0x14, 0x00, 0x00, 0x00, 0x26, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00,
3647 0x00, 0x00, 0x36, 0xE0, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3652 0x00, 0x00, 0x00, 0x00, 0x92, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3653 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xAA, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3654 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xBA, 0xE0, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01,
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3726 0x00, 0x00, 0x00, 0x00, 0xC6, 0xE4, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3727 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xE2, 0xE4, 0xFF, 0xFF,
3728 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xE5, 0xFF, 0xFF, 0x04, 0x00,
3729 0x00, 0x00, 0x64, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xE6, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3752 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00,
3753 0x00, 0x00, 0xAA, 0xE6, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3754 0xBA, 0xE7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3759 0x00, 0x00, 0x16, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3760 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x2E, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00,
3761 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3E, 0xE8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xB2, 0xE7, 0xFF, 0xFF,
3768 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC2, 0xE8, 0xFF, 0xFF, 0x04, 0x00,
3769 0x00, 0x00, 0x14, 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, 0x00, 0x00, 0x00, 0x00,
3773 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xE8, 0xFF, 0xFF,
3774 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00,
3775 0x00, 0x00, 0x36, 0xE8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3776 0x46, 0xE9, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01, 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, 0x00, 0x00, 0x00, 0x00,
3847 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xED, 0xFF, 0xFF,
3848 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00,
3849 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6E, 0xED, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x14, 0x05, 0x00, 0x00,
3850 0x04, 0x00, 0x00, 0x00, 0x7E, 0xEE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3922 0x8A, 0xF2, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3923 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xA6, 0xF2, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3924 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB6, 0xF3, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01,
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3996 0x00, 0x00, 0x00, 0x00, 0xC2, 0xF7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3997 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xDE, 0xF7, 0xFF, 0xFF,
3998 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xEE, 0xF8, 0xFF, 0xFF, 0x04, 0x00,
3999 0x00, 0x00, 0x64, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4021 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xF9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
4022 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00,
4023 0x00, 0x00, 0xA6, 0xF9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
4024 0xB6, 0xFA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x64, 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, 0x00, 0x00,
4046 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xFB,
4047 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
4048 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x6E, 0xFB, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01,
4049 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7E, 0xFC, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x64, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4072 0x00, 0x00, 0x00, 0x00, 0x1A, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
4073 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0C, 0x00,
4074 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
4075 0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x2E, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
4076 0x22, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6C, 0x73,
4077 0x74, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00,
4078 0xB4, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x30, 0x00,
4079 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
4080 0xA6, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
4081 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3C, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
4082 0x04, 0x00, 0x00, 0x00, 0xCE, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
4083 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x64, 0xFF, 0xFF, 0xFF,
4084 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
4085 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
4086 0xB4, 0xFE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x1A, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
4087 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
4088 0xF0, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
4089 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
4090 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
4091 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00,
4092 0x7E, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00,
4093 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x76, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
4094 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
4095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
4096 0x68, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xCE, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
4097 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
4098 0x08, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00,
4099 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
4100 0x08, 0x00, 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00,
4101 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00,
4102 0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
4103 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4104 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
4105 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6E, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
4106 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00,
4107 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00,
4108 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00,
4109 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
4110 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
4111 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4112 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
4113 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00,
4114 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
4115 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00
4118 armnn::INetworkPtr deserializedNetwork =
4119 DeserializeNetwork(std::string(lstmNoCifgWithPeepholeAndProjectionModel.begin(),
4120 lstmNoCifgWithPeepholeAndProjectionModel.end()));
4122 BOOST_CHECK(deserializedNetwork);
4124 // generating the same model parameters which where used to serialize the model (Layer norm is not specified)
4125 armnn::LstmDescriptor descriptor;
4126 descriptor.m_ActivationFunc = 4;
4127 descriptor.m_ClippingThresProj = 0.0f;
4128 descriptor.m_ClippingThresCell = 0.0f;
4129 descriptor.m_CifgEnabled = false;
4130 descriptor.m_ProjectionEnabled = true;
4131 descriptor.m_PeepholeEnabled = true;
4133 const uint32_t batchSize = 2u;
4134 const uint32_t inputSize = 5u;
4135 const uint32_t numUnits = 20u;
4136 const uint32_t outputSize = 16u;
4138 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
4139 std::vector<float> inputToInputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
4140 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
4142 std::vector<float> inputToForgetWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
4143 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
4145 std::vector<float> inputToCellWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
4146 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
4148 std::vector<float> inputToOutputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
4149 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
4151 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
4152 std::vector<float> inputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
4153 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
4155 std::vector<float> forgetGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
4156 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
4158 std::vector<float> cellBiasData(tensorInfo20.GetNumElements(), 0.0f);
4159 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
4161 std::vector<float> outputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
4162 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
4164 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
4165 std::vector<float> recurrentToInputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
4166 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
4168 std::vector<float> recurrentToForgetWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
4169 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
4171 std::vector<float> recurrentToCellWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
4172 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
4174 std::vector<float> recurrentToOutputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
4175 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
4177 std::vector<float> cellToInputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
4178 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
4180 std::vector<float> cellToForgetWeightsData(tensorInfo20.GetNumElements(), 0.0f);
4181 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
4183 std::vector<float> cellToOutputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
4184 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
4186 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
4187 std::vector<float> projectionWeightsData(tensorInfo16x20.GetNumElements(), 0.0f);
4188 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
4190 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
4191 std::vector<float> projectionBiasData(outputSize, 0.0f);
4192 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
4194 armnn::LstmInputParams params;
4195 params.m_InputToForgetWeights = &inputToForgetWeights;
4196 params.m_InputToCellWeights = &inputToCellWeights;
4197 params.m_InputToOutputWeights = &inputToOutputWeights;
4198 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4199 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4200 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4201 params.m_ForgetGateBias = &forgetGateBias;
4202 params.m_CellBias = &cellBias;
4203 params.m_OutputGateBias = &outputGateBias;
4205 // additional params because: descriptor.m_CifgEnabled = false
4206 params.m_InputToInputWeights = &inputToInputWeights;
4207 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
4208 params.m_CellToInputWeights = &cellToInputWeights;
4209 params.m_InputGateBias = &inputGateBias;
4211 // additional params because: descriptor.m_ProjectionEnabled = true
4212 params.m_ProjectionWeights = &projectionWeights;
4213 params.m_ProjectionBias = &projectionBias;
4215 // additional params because: descriptor.m_PeepholeEnabled = true
4216 params.m_CellToForgetWeights = &cellToForgetWeights;
4217 params.m_CellToOutputWeights = &cellToOutputWeights;
4219 const std::string layerName("lstm");
4220 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
4221 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
4222 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
4223 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
4225 VerifyLstmLayer checker(
4227 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
4228 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
4231 deserializedNetwork->Accept(checker);
4233 class VerifyQuantizedLstmLayer : public LayerVerifierBase
4237 VerifyQuantizedLstmLayer(const std::string& layerName,
4238 const std::vector<armnn::TensorInfo>& inputInfos,
4239 const std::vector<armnn::TensorInfo>& outputInfos,
4240 const armnn::QuantizedLstmInputParams& inputParams)
4241 : LayerVerifierBase(layerName, inputInfos, outputInfos), m_InputParams(inputParams) {}
4243 void VisitQuantizedLstmLayer(const armnn::IConnectableLayer* layer,
4244 const armnn::QuantizedLstmInputParams& params,
4247 VerifyNameAndConnections(layer, name);
4248 VerifyInputParameters(params);
4252 void VerifyInputParameters(const armnn::QuantizedLstmInputParams& params)
4254 VerifyConstTensors("m_InputToInputWeights",
4255 m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
4256 VerifyConstTensors("m_InputToForgetWeights",
4257 m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
4258 VerifyConstTensors("m_InputToCellWeights",
4259 m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
4260 VerifyConstTensors("m_InputToOutputWeights",
4261 m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
4262 VerifyConstTensors("m_RecurrentToInputWeights",
4263 m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
4264 VerifyConstTensors("m_RecurrentToForgetWeights",
4265 m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
4266 VerifyConstTensors("m_RecurrentToCellWeights",
4267 m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
4268 VerifyConstTensors("m_RecurrentToOutputWeights",
4269 m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
4270 VerifyConstTensors("m_InputGateBias",
4271 m_InputParams.m_InputGateBias, params.m_InputGateBias);
4272 VerifyConstTensors("m_ForgetGateBias",
4273 m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
4274 VerifyConstTensors("m_CellBias",
4275 m_InputParams.m_CellBias, params.m_CellBias);
4276 VerifyConstTensors("m_OutputGateBias",
4277 m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
4281 armnn::QuantizedLstmInputParams m_InputParams;
4284 BOOST_AUTO_TEST_CASE(SerializeDeserializeQuantizedLstm)
4286 const uint32_t batchSize = 1;
4287 const uint32_t inputSize = 2;
4288 const uint32_t numUnits = 4;
4289 const uint32_t outputSize = numUnits;
4291 // Scale/Offset for input/output, cellState In/Out, weights, bias
4292 float inputOutputScale = 0.0078125f;
4293 int32_t inputOutputOffset = 128;
4295 float cellStateScale = 0.00048828125f;
4296 int32_t cellStateOffset = 0;
4298 float weightsScale = 0.00408021f;
4299 int32_t weightsOffset = 100;
4301 float biasScale = 3.1876640625e-05f;
4302 int32_t biasOffset = 0;
4304 // The shape of weight data is {outputSize, inputSize} = {4, 2}
4305 armnn::TensorShape inputToInputWeightsShape = {4, 2};
4306 std::vector<uint8_t> inputToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4307 armnn::TensorInfo inputToInputWeightsInfo(inputToInputWeightsShape,
4308 armnn::DataType::QAsymmU8,
4311 armnn::ConstTensor inputToInputWeights(inputToInputWeightsInfo, inputToInputWeightsData);
4313 armnn::TensorShape inputToForgetWeightsShape = {4, 2};
4314 std::vector<uint8_t> inputToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4315 armnn::TensorInfo inputToForgetWeightsInfo(inputToForgetWeightsShape,
4316 armnn::DataType::QAsymmU8,
4319 armnn::ConstTensor inputToForgetWeights(inputToForgetWeightsInfo, inputToForgetWeightsData);
4321 armnn::TensorShape inputToCellWeightsShape = {4, 2};
4322 std::vector<uint8_t> inputToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4323 armnn::TensorInfo inputToCellWeightsInfo(inputToCellWeightsShape,
4324 armnn::DataType::QAsymmU8,
4327 armnn::ConstTensor inputToCellWeights(inputToCellWeightsInfo, inputToCellWeightsData);
4329 armnn::TensorShape inputToOutputWeightsShape = {4, 2};
4330 std::vector<uint8_t> inputToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4331 armnn::TensorInfo inputToOutputWeightsInfo(inputToOutputWeightsShape,
4332 armnn::DataType::QAsymmU8,
4335 armnn::ConstTensor inputToOutputWeights(inputToOutputWeightsInfo, inputToOutputWeightsData);
4337 // The shape of recurrent weight data is {outputSize, outputSize} = {4, 4}
4338 armnn::TensorShape recurrentToInputWeightsShape = {4, 4};
4339 std::vector<uint8_t> recurrentToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4340 armnn::TensorInfo recurrentToInputWeightsInfo(recurrentToInputWeightsShape,
4341 armnn::DataType::QAsymmU8,
4344 armnn::ConstTensor recurrentToInputWeights(recurrentToInputWeightsInfo, recurrentToInputWeightsData);
4346 armnn::TensorShape recurrentToForgetWeightsShape = {4, 4};
4347 std::vector<uint8_t> recurrentToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4348 armnn::TensorInfo recurrentToForgetWeightsInfo(recurrentToForgetWeightsShape,
4349 armnn::DataType::QAsymmU8,
4352 armnn::ConstTensor recurrentToForgetWeights(recurrentToForgetWeightsInfo, recurrentToForgetWeightsData);
4354 armnn::TensorShape recurrentToCellWeightsShape = {4, 4};
4355 std::vector<uint8_t> recurrentToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4356 armnn::TensorInfo recurrentToCellWeightsInfo(recurrentToCellWeightsShape,
4357 armnn::DataType::QAsymmU8,
4360 armnn::ConstTensor recurrentToCellWeights(recurrentToCellWeightsInfo, recurrentToCellWeightsData);
4362 armnn::TensorShape recurrentToOutputWeightsShape = {4, 4};
4363 std::vector<uint8_t> recurrentToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4364 armnn::TensorInfo recurrentToOutputWeightsInfo(recurrentToOutputWeightsShape,
4365 armnn::DataType::QAsymmU8,
4368 armnn::ConstTensor recurrentToOutputWeights(recurrentToOutputWeightsInfo, recurrentToOutputWeightsData);
4370 // The shape of bias data is {outputSize} = {4}
4371 armnn::TensorShape inputGateBiasShape = {4};
4372 std::vector<int32_t> inputGateBiasData = {1, 2, 3, 4};
4373 armnn::TensorInfo inputGateBiasInfo(inputGateBiasShape,
4374 armnn::DataType::Signed32,
4377 armnn::ConstTensor inputGateBias(inputGateBiasInfo, inputGateBiasData);
4379 armnn::TensorShape forgetGateBiasShape = {4};
4380 std::vector<int32_t> forgetGateBiasData = {1, 2, 3, 4};
4381 armnn::TensorInfo forgetGateBiasInfo(forgetGateBiasShape,
4382 armnn::DataType::Signed32,
4385 armnn::ConstTensor forgetGateBias(forgetGateBiasInfo, forgetGateBiasData);
4387 armnn::TensorShape cellBiasShape = {4};
4388 std::vector<int32_t> cellBiasData = {1, 2, 3, 4};
4389 armnn::TensorInfo cellBiasInfo(cellBiasShape,
4390 armnn::DataType::Signed32,
4393 armnn::ConstTensor cellBias(cellBiasInfo, cellBiasData);
4395 armnn::TensorShape outputGateBiasShape = {4};
4396 std::vector<int32_t> outputGateBiasData = {1, 2, 3, 4};
4397 armnn::TensorInfo outputGateBiasInfo(outputGateBiasShape,
4398 armnn::DataType::Signed32,
4401 armnn::ConstTensor outputGateBias(outputGateBiasInfo, outputGateBiasData);
4403 armnn::QuantizedLstmInputParams params;
4404 params.m_InputToInputWeights = &inputToInputWeights;
4405 params.m_InputToForgetWeights = &inputToForgetWeights;
4406 params.m_InputToCellWeights = &inputToCellWeights;
4407 params.m_InputToOutputWeights = &inputToOutputWeights;
4408 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
4409 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4410 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4411 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4412 params.m_InputGateBias = &inputGateBias;
4413 params.m_ForgetGateBias = &forgetGateBias;
4414 params.m_CellBias = &cellBias;
4415 params.m_OutputGateBias = &outputGateBias;
4417 armnn::INetworkPtr network = armnn::INetwork::Create();
4418 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
4419 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
4420 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
4421 const std::string layerName("QuantizedLstm");
4422 armnn::IConnectableLayer* const quantizedLstmLayer = network->AddQuantizedLstmLayer(params, layerName.c_str());
4423 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(0);
4424 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(1);
4427 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize },
4428 armnn::DataType::QAsymmU8,
4431 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits },
4432 armnn::DataType::QSymmS16,
4435 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize },
4436 armnn::DataType::QAsymmU8,
4440 inputLayer->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(0));
4441 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
4443 cellStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(1));
4444 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
4446 outputStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(2));
4447 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
4449 quantizedLstmLayer->GetOutputSlot(0).Connect(cellStateOut->GetInputSlot(0));
4450 quantizedLstmLayer->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
4452 quantizedLstmLayer->GetOutputSlot(1).Connect(outputLayer->GetInputSlot(0));
4453 quantizedLstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
4455 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
4456 BOOST_CHECK(deserializedNetwork);
4458 VerifyQuantizedLstmLayer checker(layerName,
4459 {inputTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
4460 {cellStateTensorInfo, outputStateTensorInfo},
4463 deserializedNetwork->Accept(checker);
4466 class VerifyQLstmLayer : public LayerVerifierBaseWithDescriptor<armnn::QLstmDescriptor>
4469 VerifyQLstmLayer(const std::string& layerName,
4470 const std::vector<armnn::TensorInfo>& inputInfos,
4471 const std::vector<armnn::TensorInfo>& outputInfos,
4472 const armnn::QLstmDescriptor& descriptor,
4473 const armnn::LstmInputParams& inputParams)
4474 : LayerVerifierBaseWithDescriptor<armnn::QLstmDescriptor>(layerName, inputInfos, outputInfos, descriptor)
4475 , m_InputParams(inputParams) {}
4477 void VisitQLstmLayer(const armnn::IConnectableLayer* layer,
4478 const armnn::QLstmDescriptor& descriptor,
4479 const armnn::LstmInputParams& params,
4482 VerifyNameAndConnections(layer, name);
4483 VerifyDescriptor(descriptor);
4484 VerifyInputParameters(params);
4488 void VerifyInputParameters(const armnn::LstmInputParams& params)
4491 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
4493 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
4495 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
4497 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
4499 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
4501 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
4503 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
4505 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
4507 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
4509 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
4511 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
4513 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
4515 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
4517 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
4519 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
4521 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
4523 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
4525 "m_InputLayerNormWeights", m_InputParams.m_InputLayerNormWeights, params.m_InputLayerNormWeights);
4527 "m_ForgetLayerNormWeights", m_InputParams.m_ForgetLayerNormWeights, params.m_ForgetLayerNormWeights);
4529 "m_CellLayerNormWeights", m_InputParams.m_CellLayerNormWeights, params.m_CellLayerNormWeights);
4531 "m_OutputLayerNormWeights", m_InputParams.m_OutputLayerNormWeights, params.m_OutputLayerNormWeights);
4535 armnn::LstmInputParams m_InputParams;
4538 BOOST_AUTO_TEST_CASE(SerializeDeserializeQLstmBasic)
4540 armnn::QLstmDescriptor descriptor;
4542 descriptor.m_CifgEnabled = true;
4543 descriptor.m_ProjectionEnabled = false;
4544 descriptor.m_PeepholeEnabled = false;
4545 descriptor.m_LayerNormEnabled = false;
4547 descriptor.m_CellClip = 0.0f;
4548 descriptor.m_ProjectionClip = 0.0f;
4550 descriptor.m_InputIntermediateScale = 0.00001f;
4551 descriptor.m_ForgetIntermediateScale = 0.00001f;
4552 descriptor.m_CellIntermediateScale = 0.00001f;
4553 descriptor.m_OutputIntermediateScale = 0.00001f;
4555 descriptor.m_HiddenStateScale = 0.07f;
4556 descriptor.m_HiddenStateZeroPoint = 0;
4558 const unsigned int numBatches = 2;
4559 const unsigned int inputSize = 5;
4560 const unsigned int outputSize = 4;
4561 const unsigned int numUnits = 4;
4563 // Scale/Offset quantization info
4564 float inputScale = 0.0078f;
4565 int32_t inputOffset = 0;
4567 float outputScale = 0.0078f;
4568 int32_t outputOffset = 0;
4570 float cellStateScale = 3.5002e-05f;
4571 int32_t cellStateOffset = 0;
4573 float weightsScale = 0.007f;
4574 int32_t weightsOffset = 0;
4576 float biasScale = 3.5002e-05f / 1024;
4577 int32_t biasOffset = 0;
4579 // Weights and bias tensor and quantization info
4580 armnn::TensorInfo inputWeightsInfo({numUnits, inputSize},
4581 armnn::DataType::QSymmS8,
4585 armnn::TensorInfo recurrentWeightsInfo({numUnits, outputSize},
4586 armnn::DataType::QSymmS8,
4590 armnn::TensorInfo biasInfo({numUnits}, armnn::DataType::Signed32, biasScale, biasOffset);
4592 std::vector<int8_t> inputToForgetWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4593 std::vector<int8_t> inputToCellWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4594 std::vector<int8_t> inputToOutputWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4596 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo, inputToForgetWeightsData);
4597 armnn::ConstTensor inputToCellWeights(inputWeightsInfo, inputToCellWeightsData);
4598 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo, inputToOutputWeightsData);
4600 std::vector<int8_t> recurrentToForgetWeightsData =
4601 GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4602 std::vector<int8_t> recurrentToCellWeightsData =
4603 GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4604 std::vector<int8_t> recurrentToOutputWeightsData =
4605 GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4607 armnn::ConstTensor recurrentToForgetWeights(recurrentWeightsInfo, recurrentToForgetWeightsData);
4608 armnn::ConstTensor recurrentToCellWeights(recurrentWeightsInfo, recurrentToCellWeightsData);
4609 armnn::ConstTensor recurrentToOutputWeights(recurrentWeightsInfo, recurrentToOutputWeightsData);
4611 std::vector<int32_t> forgetGateBiasData(numUnits, 1);
4612 std::vector<int32_t> cellBiasData(numUnits, 0);
4613 std::vector<int32_t> outputGateBiasData(numUnits, 0);
4615 armnn::ConstTensor forgetGateBias(biasInfo, forgetGateBiasData);
4616 armnn::ConstTensor cellBias(biasInfo, cellBiasData);
4617 armnn::ConstTensor outputGateBias(biasInfo, outputGateBiasData);
4620 armnn::LstmInputParams params;
4621 params.m_InputToForgetWeights = &inputToForgetWeights;
4622 params.m_InputToCellWeights = &inputToCellWeights;
4623 params.m_InputToOutputWeights = &inputToOutputWeights;
4625 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4626 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4627 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4629 params.m_ForgetGateBias = &forgetGateBias;
4630 params.m_CellBias = &cellBias;
4631 params.m_OutputGateBias = &outputGateBias;
4634 armnn::INetworkPtr network = armnn::INetwork::Create();
4635 const std::string layerName("qLstm");
4637 armnn::IConnectableLayer* const input = network->AddInputLayer(0);
4638 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(1);
4639 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(2);
4641 armnn::IConnectableLayer* const qLstmLayer = network->AddQLstmLayer(descriptor, params, layerName.c_str());
4643 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(0);
4644 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(1);
4645 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(2);
4647 // Input/Output tensor info
4648 armnn::TensorInfo inputInfo({numBatches , inputSize},
4649 armnn::DataType::QAsymmS8,
4653 armnn::TensorInfo cellStateInfo({numBatches , numUnits},
4654 armnn::DataType::QSymmS16,
4658 armnn::TensorInfo outputStateInfo({numBatches , outputSize},
4659 armnn::DataType::QAsymmS8,
4663 // Connect input/output slots
4664 input->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(0));
4665 input->GetOutputSlot(0).SetTensorInfo(inputInfo);
4667 outputStateIn->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(1));
4668 outputStateIn->GetOutputSlot(0).SetTensorInfo(cellStateInfo);
4670 cellStateIn->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(2));
4671 cellStateIn->GetOutputSlot(0).SetTensorInfo(outputStateInfo);
4673 qLstmLayer->GetOutputSlot(0).Connect(outputStateOut->GetInputSlot(0));
4674 qLstmLayer->GetOutputSlot(0).SetTensorInfo(outputStateInfo);
4676 qLstmLayer->GetOutputSlot(1).Connect(cellStateOut->GetInputSlot(0));
4677 qLstmLayer->GetOutputSlot(1).SetTensorInfo(cellStateInfo);
4679 qLstmLayer->GetOutputSlot(2).Connect(outputLayer->GetInputSlot(0));
4680 qLstmLayer->GetOutputSlot(2).SetTensorInfo(outputStateInfo);
4682 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
4683 BOOST_CHECK(deserializedNetwork);
4685 VerifyQLstmLayer checker(layerName,
4686 {inputInfo, cellStateInfo, outputStateInfo},
4687 {outputStateInfo, cellStateInfo, outputStateInfo},
4691 deserializedNetwork->Accept(checker);
4694 BOOST_AUTO_TEST_CASE(SerializeDeserializeQLstmCifgLayerNorm)
4696 armnn::QLstmDescriptor descriptor;
4698 // CIFG params are used when CIFG is disabled
4699 descriptor.m_CifgEnabled = true;
4700 descriptor.m_ProjectionEnabled = false;
4701 descriptor.m_PeepholeEnabled = false;
4702 descriptor.m_LayerNormEnabled = true;
4704 descriptor.m_CellClip = 0.0f;
4705 descriptor.m_ProjectionClip = 0.0f;
4707 descriptor.m_InputIntermediateScale = 0.00001f;
4708 descriptor.m_ForgetIntermediateScale = 0.00001f;
4709 descriptor.m_CellIntermediateScale = 0.00001f;
4710 descriptor.m_OutputIntermediateScale = 0.00001f;
4712 descriptor.m_HiddenStateScale = 0.07f;
4713 descriptor.m_HiddenStateZeroPoint = 0;
4715 const unsigned int numBatches = 2;
4716 const unsigned int inputSize = 5;
4717 const unsigned int outputSize = 4;
4718 const unsigned int numUnits = 4;
4720 // Scale/Offset quantization info
4721 float inputScale = 0.0078f;
4722 int32_t inputOffset = 0;
4724 float outputScale = 0.0078f;
4725 int32_t outputOffset = 0;
4727 float cellStateScale = 3.5002e-05f;
4728 int32_t cellStateOffset = 0;
4730 float weightsScale = 0.007f;
4731 int32_t weightsOffset = 0;
4733 float layerNormScale = 3.5002e-05f;
4734 int32_t layerNormOffset = 0;
4736 float biasScale = layerNormScale / 1024;
4737 int32_t biasOffset = 0;
4739 // Weights and bias tensor and quantization info
4740 armnn::TensorInfo inputWeightsInfo({numUnits, inputSize},
4741 armnn::DataType::QSymmS8,
4745 armnn::TensorInfo recurrentWeightsInfo({numUnits, outputSize},
4746 armnn::DataType::QSymmS8,
4750 armnn::TensorInfo biasInfo({numUnits},
4751 armnn::DataType::Signed32,
4755 armnn::TensorInfo layerNormWeightsInfo({numUnits},
4756 armnn::DataType::QSymmS16,
4761 std::vector<int8_t> inputToForgetWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4762 std::vector<int8_t> inputToCellWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4763 std::vector<int8_t> inputToOutputWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4765 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo, inputToForgetWeightsData);
4766 armnn::ConstTensor inputToCellWeights(inputWeightsInfo, inputToCellWeightsData);
4767 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo, inputToOutputWeightsData);
4769 std::vector<int8_t> recurrentToForgetWeightsData =
4770 GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4771 std::vector<int8_t> recurrentToCellWeightsData =
4772 GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4773 std::vector<int8_t> recurrentToOutputWeightsData =
4774 GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4776 armnn::ConstTensor recurrentToForgetWeights(recurrentWeightsInfo, recurrentToForgetWeightsData);
4777 armnn::ConstTensor recurrentToCellWeights(recurrentWeightsInfo, recurrentToCellWeightsData);
4778 armnn::ConstTensor recurrentToOutputWeights(recurrentWeightsInfo, recurrentToOutputWeightsData);
4780 std::vector<int32_t> forgetGateBiasData(numUnits, 1);
4781 std::vector<int32_t> cellBiasData(numUnits, 0);
4782 std::vector<int32_t> outputGateBiasData(numUnits, 0);
4784 armnn::ConstTensor forgetGateBias(biasInfo, forgetGateBiasData);
4785 armnn::ConstTensor cellBias(biasInfo, cellBiasData);
4786 armnn::ConstTensor outputGateBias(biasInfo, outputGateBiasData);
4789 std::vector<int16_t> forgetLayerNormWeightsData =
4790 GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
4791 std::vector<int16_t> cellLayerNormWeightsData =
4792 GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
4793 std::vector<int16_t> outputLayerNormWeightsData =
4794 GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
4796 armnn::ConstTensor forgetLayerNormWeights(layerNormWeightsInfo, forgetLayerNormWeightsData);
4797 armnn::ConstTensor cellLayerNormWeights(layerNormWeightsInfo, cellLayerNormWeightsData);
4798 armnn::ConstTensor outputLayerNormWeights(layerNormWeightsInfo, outputLayerNormWeightsData);
4801 armnn::LstmInputParams params;
4804 params.m_InputToForgetWeights = &inputToForgetWeights;
4805 params.m_InputToCellWeights = &inputToCellWeights;
4806 params.m_InputToOutputWeights = &inputToOutputWeights;
4808 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4809 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4810 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4812 params.m_ForgetGateBias = &forgetGateBias;
4813 params.m_CellBias = &cellBias;
4814 params.m_OutputGateBias = &outputGateBias;
4817 params.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
4818 params.m_CellLayerNormWeights = &cellLayerNormWeights;
4819 params.m_OutputLayerNormWeights = &outputLayerNormWeights;
4822 armnn::INetworkPtr network = armnn::INetwork::Create();
4823 const std::string layerName("qLstm");
4825 armnn::IConnectableLayer* const input = network->AddInputLayer(0);
4826 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(1);
4827 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(2);
4829 armnn::IConnectableLayer* const qLstmLayer = network->AddQLstmLayer(descriptor, params, layerName.c_str());
4831 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(0);
4832 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(1);
4833 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(2);
4835 // Input/Output tensor info
4836 armnn::TensorInfo inputInfo({numBatches , inputSize},
4837 armnn::DataType::QAsymmS8,
4841 armnn::TensorInfo cellStateInfo({numBatches , numUnits},
4842 armnn::DataType::QSymmS16,
4846 armnn::TensorInfo outputStateInfo({numBatches , outputSize},
4847 armnn::DataType::QAsymmS8,
4851 // Connect input/output slots
4852 input->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(0));
4853 input->GetOutputSlot(0).SetTensorInfo(inputInfo);
4855 outputStateIn->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(1));
4856 outputStateIn->GetOutputSlot(0).SetTensorInfo(cellStateInfo);
4858 cellStateIn->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(2));
4859 cellStateIn->GetOutputSlot(0).SetTensorInfo(outputStateInfo);
4861 qLstmLayer->GetOutputSlot(0).Connect(outputStateOut->GetInputSlot(0));
4862 qLstmLayer->GetOutputSlot(0).SetTensorInfo(outputStateInfo);
4864 qLstmLayer->GetOutputSlot(1).Connect(cellStateOut->GetInputSlot(0));
4865 qLstmLayer->GetOutputSlot(1).SetTensorInfo(cellStateInfo);
4867 qLstmLayer->GetOutputSlot(2).Connect(outputLayer->GetInputSlot(0));
4868 qLstmLayer->GetOutputSlot(2).SetTensorInfo(outputStateInfo);
4870 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
4871 BOOST_CHECK(deserializedNetwork);
4873 VerifyQLstmLayer checker(layerName,
4874 {inputInfo, cellStateInfo, outputStateInfo},
4875 {outputStateInfo, cellStateInfo, outputStateInfo},
4879 deserializedNetwork->Accept(checker);
4882 BOOST_AUTO_TEST_CASE(SerializeDeserializeQLstmAdvanced)
4884 armnn::QLstmDescriptor descriptor;
4886 descriptor.m_CifgEnabled = false;
4887 descriptor.m_ProjectionEnabled = true;
4888 descriptor.m_PeepholeEnabled = true;
4889 descriptor.m_LayerNormEnabled = true;
4891 descriptor.m_CellClip = 0.1f;
4892 descriptor.m_ProjectionClip = 0.1f;
4894 descriptor.m_InputIntermediateScale = 0.00001f;
4895 descriptor.m_ForgetIntermediateScale = 0.00001f;
4896 descriptor.m_CellIntermediateScale = 0.00001f;
4897 descriptor.m_OutputIntermediateScale = 0.00001f;
4899 descriptor.m_HiddenStateScale = 0.07f;
4900 descriptor.m_HiddenStateZeroPoint = 0;
4902 const unsigned int numBatches = 2;
4903 const unsigned int inputSize = 5;
4904 const unsigned int outputSize = 4;
4905 const unsigned int numUnits = 4;
4907 // Scale/Offset quantization info
4908 float inputScale = 0.0078f;
4909 int32_t inputOffset = 0;
4911 float outputScale = 0.0078f;
4912 int32_t outputOffset = 0;
4914 float cellStateScale = 3.5002e-05f;
4915 int32_t cellStateOffset = 0;
4917 float weightsScale = 0.007f;
4918 int32_t weightsOffset = 0;
4920 float layerNormScale = 3.5002e-05f;
4921 int32_t layerNormOffset = 0;
4923 float biasScale = layerNormScale / 1024;
4924 int32_t biasOffset = 0;
4926 // Weights and bias tensor and quantization info
4927 armnn::TensorInfo inputWeightsInfo({numUnits, inputSize},
4928 armnn::DataType::QSymmS8,
4932 armnn::TensorInfo recurrentWeightsInfo({numUnits, outputSize},
4933 armnn::DataType::QSymmS8,
4937 armnn::TensorInfo biasInfo({numUnits},
4938 armnn::DataType::Signed32,
4942 armnn::TensorInfo peepholeWeightsInfo({numUnits},
4943 armnn::DataType::QSymmS16,
4947 armnn::TensorInfo layerNormWeightsInfo({numUnits},
4948 armnn::DataType::QSymmS16,
4952 armnn::TensorInfo projectionWeightsInfo({outputSize, numUnits},
4953 armnn::DataType::QSymmS8,
4958 std::vector<int8_t> inputToForgetWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4959 std::vector<int8_t> inputToCellWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4960 std::vector<int8_t> inputToOutputWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4962 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo, inputToForgetWeightsData);
4963 armnn::ConstTensor inputToCellWeights(inputWeightsInfo, inputToCellWeightsData);
4964 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo, inputToOutputWeightsData);
4966 std::vector<int8_t> recurrentToForgetWeightsData =
4967 GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4968 std::vector<int8_t> recurrentToCellWeightsData =
4969 GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4970 std::vector<int8_t> recurrentToOutputWeightsData =
4971 GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4973 armnn::ConstTensor recurrentToForgetWeights(recurrentWeightsInfo, recurrentToForgetWeightsData);
4974 armnn::ConstTensor recurrentToCellWeights(recurrentWeightsInfo, recurrentToCellWeightsData);
4975 armnn::ConstTensor recurrentToOutputWeights(recurrentWeightsInfo, recurrentToOutputWeightsData);
4977 std::vector<int32_t> forgetGateBiasData(numUnits, 1);
4978 std::vector<int32_t> cellBiasData(numUnits, 0);
4979 std::vector<int32_t> outputGateBiasData(numUnits, 0);
4981 armnn::ConstTensor forgetGateBias(biasInfo, forgetGateBiasData);
4982 armnn::ConstTensor cellBias(biasInfo, cellBiasData);
4983 armnn::ConstTensor outputGateBias(biasInfo, outputGateBiasData);
4986 std::vector<int8_t> inputToInputWeightsData = GenerateRandomData<int8_t>(inputWeightsInfo.GetNumElements());
4987 std::vector<int8_t> recurrentToInputWeightsData =
4988 GenerateRandomData<int8_t>(recurrentWeightsInfo.GetNumElements());
4989 std::vector<int32_t> inputGateBiasData(numUnits, 1);
4991 armnn::ConstTensor inputToInputWeights(inputWeightsInfo, inputToInputWeightsData);
4992 armnn::ConstTensor recurrentToInputWeights(recurrentWeightsInfo, recurrentToInputWeightsData);
4993 armnn::ConstTensor inputGateBias(biasInfo, inputGateBiasData);
4996 std::vector<int16_t> cellToInputWeightsData = GenerateRandomData<int16_t>(peepholeWeightsInfo.GetNumElements());
4997 std::vector<int16_t> cellToForgetWeightsData = GenerateRandomData<int16_t>(peepholeWeightsInfo.GetNumElements());
4998 std::vector<int16_t> cellToOutputWeightsData = GenerateRandomData<int16_t>(peepholeWeightsInfo.GetNumElements());
5000 armnn::ConstTensor cellToInputWeights(peepholeWeightsInfo, cellToInputWeightsData);
5001 armnn::ConstTensor cellToForgetWeights(peepholeWeightsInfo, cellToForgetWeightsData);
5002 armnn::ConstTensor cellToOutputWeights(peepholeWeightsInfo, cellToOutputWeightsData);
5005 std::vector<int8_t> projectionWeightsData = GenerateRandomData<int8_t>(projectionWeightsInfo.GetNumElements());
5006 std::vector<int32_t> projectionBiasData(outputSize, 1);
5008 armnn::ConstTensor projectionWeights(projectionWeightsInfo, projectionWeightsData);
5009 armnn::ConstTensor projectionBias(biasInfo, projectionBiasData);
5012 std::vector<int16_t> inputLayerNormWeightsData =
5013 GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
5014 std::vector<int16_t> forgetLayerNormWeightsData =
5015 GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
5016 std::vector<int16_t> cellLayerNormWeightsData =
5017 GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
5018 std::vector<int16_t> outputLayerNormWeightsData =
5019 GenerateRandomData<int16_t>(layerNormWeightsInfo.GetNumElements());
5021 armnn::ConstTensor inputLayerNormWeights(layerNormWeightsInfo, inputLayerNormWeightsData);
5022 armnn::ConstTensor forgetLayerNormWeights(layerNormWeightsInfo, forgetLayerNormWeightsData);
5023 armnn::ConstTensor cellLayerNormWeights(layerNormWeightsInfo, cellLayerNormWeightsData);
5024 armnn::ConstTensor outputLayerNormWeights(layerNormWeightsInfo, outputLayerNormWeightsData);
5027 armnn::LstmInputParams params;
5030 params.m_InputToForgetWeights = &inputToForgetWeights;
5031 params.m_InputToCellWeights = &inputToCellWeights;
5032 params.m_InputToOutputWeights = &inputToOutputWeights;
5034 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
5035 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
5036 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
5038 params.m_ForgetGateBias = &forgetGateBias;
5039 params.m_CellBias = &cellBias;
5040 params.m_OutputGateBias = &outputGateBias;
5043 params.m_InputToInputWeights = &inputToInputWeights;
5044 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
5045 params.m_InputGateBias = &inputGateBias;
5048 params.m_CellToInputWeights = &cellToInputWeights;
5049 params.m_CellToForgetWeights = &cellToForgetWeights;
5050 params.m_CellToOutputWeights = &cellToOutputWeights;
5053 params.m_ProjectionWeights = &projectionWeights;
5054 params.m_ProjectionBias = &projectionBias;
5057 params.m_InputLayerNormWeights = &inputLayerNormWeights;
5058 params.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
5059 params.m_CellLayerNormWeights = &cellLayerNormWeights;
5060 params.m_OutputLayerNormWeights = &outputLayerNormWeights;
5063 armnn::INetworkPtr network = armnn::INetwork::Create();
5064 const std::string layerName("qLstm");
5066 armnn::IConnectableLayer* const input = network->AddInputLayer(0);
5067 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(1);
5068 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(2);
5070 armnn::IConnectableLayer* const qLstmLayer = network->AddQLstmLayer(descriptor, params, layerName.c_str());
5072 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(0);
5073 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(1);
5074 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(2);
5076 // Input/Output tensor info
5077 armnn::TensorInfo inputInfo({numBatches , inputSize},
5078 armnn::DataType::QAsymmS8,
5082 armnn::TensorInfo cellStateInfo({numBatches , numUnits},
5083 armnn::DataType::QSymmS16,
5087 armnn::TensorInfo outputStateInfo({numBatches , outputSize},
5088 armnn::DataType::QAsymmS8,
5092 // Connect input/output slots
5093 input->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(0));
5094 input->GetOutputSlot(0).SetTensorInfo(inputInfo);
5096 outputStateIn->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(1));
5097 outputStateIn->GetOutputSlot(0).SetTensorInfo(cellStateInfo);
5099 cellStateIn->GetOutputSlot(0).Connect(qLstmLayer->GetInputSlot(2));
5100 cellStateIn->GetOutputSlot(0).SetTensorInfo(outputStateInfo);
5102 qLstmLayer->GetOutputSlot(0).Connect(outputStateOut->GetInputSlot(0));
5103 qLstmLayer->GetOutputSlot(0).SetTensorInfo(outputStateInfo);
5105 qLstmLayer->GetOutputSlot(1).Connect(cellStateOut->GetInputSlot(0));
5106 qLstmLayer->GetOutputSlot(1).SetTensorInfo(cellStateInfo);
5108 qLstmLayer->GetOutputSlot(2).Connect(outputLayer->GetInputSlot(0));
5109 qLstmLayer->GetOutputSlot(2).SetTensorInfo(outputStateInfo);
5111 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
5112 BOOST_CHECK(deserializedNetwork);
5114 VerifyQLstmLayer checker(layerName,
5115 {inputInfo, cellStateInfo, outputStateInfo},
5116 {outputStateInfo, cellStateInfo, outputStateInfo},
5120 deserializedNetwork->Accept(checker);
5123 BOOST_AUTO_TEST_SUITE_END()