blob: 3eb9e44b4f87149a2635f92ea40288c4f82135a2 [file] [log] [blame]
Mike Kelly8c1701a2019-02-11 17:01:27 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
Mike Kelly8c1701a2019-02-11 17:01:27 +00006#include "../Serializer.hpp"
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00007
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00008#include <armnn/ArmNN.hpp>
9#include <armnn/INetwork.hpp>
Derek Lamberti0028d1b2019-02-20 13:57:42 +000010#include <armnnDeserializer/IDeserializer.hpp>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000011
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +000012#include <random>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000013#include <vector>
14
Mike Kelly8c1701a2019-02-11 17:01:27 +000015#include <boost/test/unit_test.hpp>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000016
Derek Lamberti0028d1b2019-02-20 13:57:42 +000017using armnnDeserializer::IDeserializer;
Mike Kelly8c1701a2019-02-11 17:01:27 +000018
Saoirse Stewart3166c3e2019-02-18 15:24:53 +000019namespace
20{
21
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +010022#define DECLARE_LAYER_VERIFIER_CLASS(name) \
23class name##LayerVerifier : public LayerVerifierBase \
24{ \
25public: \
26 name##LayerVerifier(const std::string& layerName, \
27 const std::vector<armnn::TensorInfo>& inputInfos, \
28 const std::vector<armnn::TensorInfo>& outputInfos) \
29 : LayerVerifierBase(layerName, inputInfos, outputInfos) {} \
30\
31 void Visit##name##Layer(const armnn::IConnectableLayer* layer, const char* name) override \
32 { \
33 VerifyNameAndConnections(layer, name); \
34 } \
35};
36
37#define DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(name) \
38class name##LayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::name##Descriptor> \
39{ \
40public: \
41 name##LayerVerifier(const std::string& layerName, \
42 const std::vector<armnn::TensorInfo>& inputInfos, \
43 const std::vector<armnn::TensorInfo>& outputInfos, \
44 const armnn::name##Descriptor& descriptor) \
45 : LayerVerifierBaseWithDescriptor<armnn::name##Descriptor>( \
46 layerName, inputInfos, outputInfos, descriptor) {} \
47\
48 void Visit##name##Layer(const armnn::IConnectableLayer* layer, \
49 const armnn::name##Descriptor& descriptor, \
50 const char* name) override \
51 { \
52 VerifyNameAndConnections(layer, name); \
53 VerifyDescriptor(descriptor); \
54 } \
55};
56
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000057struct DefaultLayerVerifierPolicy
58{
Les Belle0ca8612019-05-17 16:17:12 +010059 static void Apply(const std::string s = "")
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000060 {
61 BOOST_TEST_MESSAGE("Unexpected layer found in network");
62 BOOST_TEST(false);
63 }
64};
65
66class LayerVerifierBase : public armnn::LayerVisitorBase<DefaultLayerVerifierPolicy>
67{
68public:
69 LayerVerifierBase(const std::string& layerName,
70 const std::vector<armnn::TensorInfo>& inputInfos,
71 const std::vector<armnn::TensorInfo>& outputInfos)
72 : m_LayerName(layerName)
73 , m_InputTensorInfos(inputInfos)
74 , m_OutputTensorInfos(outputInfos) {}
75
76 void VisitInputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId, const char*) override {}
77
78 void VisitOutputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId id, const char*) override {}
79
80protected:
81 void VerifyNameAndConnections(const armnn::IConnectableLayer* layer, const char* name)
82 {
83 BOOST_TEST(name == m_LayerName.c_str());
84
85 BOOST_TEST(layer->GetNumInputSlots() == m_InputTensorInfos.size());
86 BOOST_TEST(layer->GetNumOutputSlots() == m_OutputTensorInfos.size());
87
88 for (unsigned int i = 0; i < m_InputTensorInfos.size(); i++)
89 {
90 const armnn::IOutputSlot* connectedOutput = layer->GetInputSlot(i).GetConnection();
91 BOOST_CHECK(connectedOutput);
92
93 const armnn::TensorInfo& connectedInfo = connectedOutput->GetTensorInfo();
94 BOOST_TEST(connectedInfo.GetShape() == m_InputTensorInfos[i].GetShape());
95 BOOST_TEST(
96 GetDataTypeName(connectedInfo.GetDataType()) == GetDataTypeName(m_InputTensorInfos[i].GetDataType()));
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +000097
98 BOOST_TEST(connectedInfo.GetQuantizationScale() == m_InputTensorInfos[i].GetQuantizationScale());
99 BOOST_TEST(connectedInfo.GetQuantizationOffset() == m_InputTensorInfos[i].GetQuantizationOffset());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000100 }
101
102 for (unsigned int i = 0; i < m_OutputTensorInfos.size(); i++)
103 {
104 const armnn::TensorInfo& outputInfo = layer->GetOutputSlot(i).GetTensorInfo();
105 BOOST_TEST(outputInfo.GetShape() == m_OutputTensorInfos[i].GetShape());
106 BOOST_TEST(
107 GetDataTypeName(outputInfo.GetDataType()) == GetDataTypeName(m_OutputTensorInfos[i].GetDataType()));
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000108
109 BOOST_TEST(outputInfo.GetQuantizationScale() == m_OutputTensorInfos[i].GetQuantizationScale());
110 BOOST_TEST(outputInfo.GetQuantizationOffset() == m_OutputTensorInfos[i].GetQuantizationOffset());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000111 }
112 }
113
Jan Eilers5b01a892019-07-23 09:47:43 +0100114 void VerifyConstTensors(const std::string& tensorName,
115 const armnn::ConstTensor* expectedPtr,
116 const armnn::ConstTensor* actualPtr)
117 {
118 if (expectedPtr == nullptr)
119 {
120 BOOST_CHECK_MESSAGE(actualPtr == nullptr, tensorName + " should not exist");
121 }
122 else
123 {
124 BOOST_CHECK_MESSAGE(actualPtr != nullptr, tensorName + " should have been set");
125 if (actualPtr != nullptr)
126 {
127 const armnn::TensorInfo& expectedInfo = expectedPtr->GetInfo();
128 const armnn::TensorInfo& actualInfo = actualPtr->GetInfo();
129
130 BOOST_CHECK_MESSAGE(expectedInfo.GetShape() == actualInfo.GetShape(),
131 tensorName + " shapes don't match");
132 BOOST_CHECK_MESSAGE(
133 GetDataTypeName(expectedInfo.GetDataType()) == GetDataTypeName(actualInfo.GetDataType()),
134 tensorName + " data types don't match");
135
136 BOOST_CHECK_MESSAGE(expectedPtr->GetNumBytes() == actualPtr->GetNumBytes(),
137 tensorName + " (GetNumBytes) data sizes do not match");
138 if (expectedPtr->GetNumBytes() == actualPtr->GetNumBytes())
139 {
140 //check the data is identical
141 const char* expectedData = static_cast<const char*>(expectedPtr->GetMemoryArea());
142 const char* actualData = static_cast<const char*>(actualPtr->GetMemoryArea());
143 bool same = true;
144 for (unsigned int i = 0; i < expectedPtr->GetNumBytes(); ++i)
145 {
146 same = expectedData[i] == actualData[i];
147 if (!same)
148 {
149 break;
150 }
151 }
152 BOOST_CHECK_MESSAGE(same, tensorName + " data does not match");
153 }
154 }
155 }
156 }
157
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000158private:
159 std::string m_LayerName;
160 std::vector<armnn::TensorInfo> m_InputTensorInfos;
161 std::vector<armnn::TensorInfo> m_OutputTensorInfos;
162};
163
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100164template<typename Descriptor>
165class LayerVerifierBaseWithDescriptor : public LayerVerifierBase
166{
167public:
168 LayerVerifierBaseWithDescriptor(const std::string& layerName,
169 const std::vector<armnn::TensorInfo>& inputInfos,
170 const std::vector<armnn::TensorInfo>& outputInfos,
171 const Descriptor& descriptor)
172 : LayerVerifierBase(layerName, inputInfos, outputInfos)
173 , m_Descriptor(descriptor) {}
174
175protected:
176 void VerifyDescriptor(const Descriptor& descriptor)
177 {
178 BOOST_CHECK(descriptor == m_Descriptor);
179 }
180
181private:
182 Descriptor m_Descriptor;
183};
184
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000185template<typename T>
186void CompareConstTensorData(const void* data1, const void* data2, unsigned int numElements)
187{
188 T typedData1 = static_cast<T>(data1);
189 T typedData2 = static_cast<T>(data2);
190 BOOST_CHECK(typedData1);
191 BOOST_CHECK(typedData2);
192
193 for (unsigned int i = 0; i < numElements; i++)
194 {
195 BOOST_TEST(typedData1[i] == typedData2[i]);
196 }
197}
198
199void CompareConstTensor(const armnn::ConstTensor& tensor1, const armnn::ConstTensor& tensor2)
200{
201 BOOST_TEST(tensor1.GetShape() == tensor2.GetShape());
202 BOOST_TEST(GetDataTypeName(tensor1.GetDataType()) == GetDataTypeName(tensor2.GetDataType()));
203
204 switch (tensor1.GetDataType())
205 {
206 case armnn::DataType::Float32:
207 CompareConstTensorData<const float*>(
208 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
209 break;
210 case armnn::DataType::QuantisedAsymm8:
211 case armnn::DataType::Boolean:
212 CompareConstTensorData<const uint8_t*>(
213 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
214 break;
215 case armnn::DataType::Signed32:
216 CompareConstTensorData<const int32_t*>(
217 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
218 break;
219 default:
220 // Note that Float16 is not yet implemented
221 BOOST_TEST_MESSAGE("Unexpected datatype");
222 BOOST_TEST(false);
223 }
224}
225
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000226armnn::INetworkPtr DeserializeNetwork(const std::string& serializerString)
227{
228 std::vector<std::uint8_t> const serializerVector{serializerString.begin(), serializerString.end()};
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000229 return IDeserializer::Create()->CreateNetworkFromBinary(serializerVector);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000230}
231
232std::string SerializeNetwork(const armnn::INetwork& network)
233{
234 armnnSerializer::Serializer serializer;
235 serializer.Serialize(network);
236
237 std::stringstream stream;
238 serializer.SaveSerializedToStream(stream);
239
240 std::string serializerString{stream.str()};
241 return serializerString;
242}
243
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000244template<typename DataType>
245static std::vector<DataType> GenerateRandomData(size_t size)
246{
247 constexpr bool isIntegerType = std::is_integral<DataType>::value;
248 using Distribution =
249 typename std::conditional<isIntegerType,
250 std::uniform_int_distribution<DataType>,
251 std::uniform_real_distribution<DataType>>::type;
252
253 static constexpr DataType lowerLimit = std::numeric_limits<DataType>::min();
254 static constexpr DataType upperLimit = std::numeric_limits<DataType>::max();
255
256 static Distribution distribution(lowerLimit, upperLimit);
257 static std::default_random_engine generator;
258
259 std::vector<DataType> randomData(size);
260 std::generate(randomData.begin(), randomData.end(), []() { return distribution(generator); });
261
262 return randomData;
263}
264
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000265} // anonymous namespace
266
267BOOST_AUTO_TEST_SUITE(SerializerTests)
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000268
FinnWilliamsArm4ffcc8f2019-09-05 14:34:20 +0100269BOOST_AUTO_TEST_CASE(SerializeAbs)
270{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100271 DECLARE_LAYER_VERIFIER_CLASS(Abs)
FinnWilliamsArm4ffcc8f2019-09-05 14:34:20 +0100272
273 const std::string layerName("abs");
274 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
275
276 armnn::INetworkPtr network = armnn::INetwork::Create();
277 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
278
279 armnn::IConnectableLayer* const absLayer = network->AddAbsLayer(layerName.c_str());
280 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
281
282 inputLayer->GetOutputSlot(0).Connect(absLayer->GetInputSlot(0));
283 absLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
284
285 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
286 absLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
287
288 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
289 BOOST_CHECK(deserializedNetwork);
290
291 AbsLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
292 deserializedNetwork->Accept(verifier);
293}
294
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000295BOOST_AUTO_TEST_CASE(SerializeAddition)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000296{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100297 DECLARE_LAYER_VERIFIER_CLASS(Addition)
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000298
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000299 const std::string layerName("addition");
300 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
301
Mike Kelly8c1701a2019-02-11 17:01:27 +0000302 armnn::INetworkPtr network = armnn::INetwork::Create();
303 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
304 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000305 armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer(layerName.c_str());
306 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000307
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000308 inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
309 inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000310 additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Mike Kelly8c1701a2019-02-11 17:01:27 +0000311
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000312 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
313 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
314 additionLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
Jim Flynn3091b062019-02-15 14:45:04 +0000315
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000316 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000317 BOOST_CHECK(deserializedNetwork);
318
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000319 AdditionLayerVerifier verifier(layerName, {tensorInfo, tensorInfo}, {tensorInfo});
320 deserializedNetwork->Accept(verifier);
321}
Jim Flynnac25a1b2019-02-28 10:40:49 +0000322
Narumol Prangnawarat0cfcf232019-09-09 17:16:24 +0100323BOOST_AUTO_TEST_CASE(SerializeArgMinMax)
324{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100325 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(ArgMinMax)
Narumol Prangnawarat0cfcf232019-09-09 17:16:24 +0100326
327 const std::string layerName("argminmax");
328 const armnn::TensorInfo inputInfo({1, 2, 3}, armnn::DataType::Float32);
329 const armnn::TensorInfo outputInfo({1, 3}, armnn::DataType::Signed32);
330
331 armnn::ArgMinMaxDescriptor descriptor;
332 descriptor.m_Function = armnn::ArgMinMaxFunction::Max;
333 descriptor.m_Axis = 1;
334
335 armnn::INetworkPtr network = armnn::INetwork::Create();
336 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
337 armnn::IConnectableLayer* const argMinMaxLayer = network->AddArgMinMaxLayer(descriptor, layerName.c_str());
338 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
339
340 inputLayer->GetOutputSlot(0).Connect(argMinMaxLayer->GetInputSlot(0));
341 argMinMaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
342
343 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
344 argMinMaxLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
345
346 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
347 BOOST_CHECK(deserializedNetwork);
348
349 ArgMinMaxLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
350 deserializedNetwork->Accept(verifier);
351}
352
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000353BOOST_AUTO_TEST_CASE(SerializeBatchNormalization)
354{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100355 using Descriptor = armnn::BatchNormalizationDescriptor;
356 class BatchNormalizationLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000357 {
358 public:
359 BatchNormalizationLayerVerifier(const std::string& layerName,
360 const std::vector<armnn::TensorInfo>& inputInfos,
361 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100362 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000363 const armnn::ConstTensor& mean,
364 const armnn::ConstTensor& variance,
365 const armnn::ConstTensor& beta,
366 const armnn::ConstTensor& gamma)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100367 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
368 , m_Mean(mean)
369 , m_Variance(variance)
370 , m_Beta(beta)
371 , m_Gamma(gamma) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000372
373 void VisitBatchNormalizationLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100374 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000375 const armnn::ConstTensor& mean,
376 const armnn::ConstTensor& variance,
377 const armnn::ConstTensor& beta,
378 const armnn::ConstTensor& gamma,
379 const char* name) override
380 {
381 VerifyNameAndConnections(layer, name);
382 VerifyDescriptor(descriptor);
383
384 CompareConstTensor(mean, m_Mean);
385 CompareConstTensor(variance, m_Variance);
386 CompareConstTensor(beta, m_Beta);
387 CompareConstTensor(gamma, m_Gamma);
388 }
389
390 private:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000391 armnn::ConstTensor m_Mean;
392 armnn::ConstTensor m_Variance;
393 armnn::ConstTensor m_Beta;
394 armnn::ConstTensor m_Gamma;
395 };
396
397 const std::string layerName("batchNormalization");
398 const armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32);
399 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
400
401 const armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32);
402 const armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32);
403 const armnn::TensorInfo betaInfo({1}, armnn::DataType::Float32);
404 const armnn::TensorInfo gammaInfo({1}, armnn::DataType::Float32);
405
406 armnn::BatchNormalizationDescriptor descriptor;
407 descriptor.m_Eps = 0.0010000000475f;
408 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
409
410 std::vector<float> meanData({5.0});
411 std::vector<float> varianceData({2.0});
412 std::vector<float> betaData({1.0});
413 std::vector<float> gammaData({0.0});
414
415 armnn::ConstTensor mean(meanInfo, meanData);
416 armnn::ConstTensor variance(varianceInfo, varianceData);
417 armnn::ConstTensor beta(betaInfo, betaData);
418 armnn::ConstTensor gamma(gammaInfo, gammaData);
419
420 armnn::INetworkPtr network = armnn::INetwork::Create();
421 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
422 armnn::IConnectableLayer* const batchNormalizationLayer =
423 network->AddBatchNormalizationLayer(descriptor, mean, variance, beta, gamma, layerName.c_str());
424 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
425
426 inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0));
427 batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
428
429 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
430 batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
431
432 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
433 BOOST_CHECK(deserializedNetwork);
434
435 BatchNormalizationLayerVerifier verifier(
436 layerName, {inputInfo}, {outputInfo}, descriptor, mean, variance, beta, gamma);
437 deserializedNetwork->Accept(verifier);
438}
439
440BOOST_AUTO_TEST_CASE(SerializeBatchToSpaceNd)
441{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100442 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(BatchToSpaceNd)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000443
444 const std::string layerName("spaceToBatchNd");
445 const armnn::TensorInfo inputInfo({4, 1, 2, 2}, armnn::DataType::Float32);
446 const armnn::TensorInfo outputInfo({1, 1, 4, 4}, armnn::DataType::Float32);
447
448 armnn::BatchToSpaceNdDescriptor desc;
449 desc.m_DataLayout = armnn::DataLayout::NCHW;
450 desc.m_BlockShape = {2, 2};
451 desc.m_Crops = {{0, 0}, {0, 0}};
452
453 armnn::INetworkPtr network = armnn::INetwork::Create();
454 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
455 armnn::IConnectableLayer* const batchToSpaceNdLayer = network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
456 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
457
458 inputLayer->GetOutputSlot(0).Connect(batchToSpaceNdLayer->GetInputSlot(0));
459 batchToSpaceNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
460
461 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
462 batchToSpaceNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
463
464 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
465 BOOST_CHECK(deserializedNetwork);
466
467 BatchToSpaceNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
468 deserializedNetwork->Accept(verifier);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000469}
470
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100471BOOST_AUTO_TEST_CASE(SerializeComparison)
472{
473 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Comparison)
474
475 const std::string layerName("comparison");
476
477 const armnn::TensorShape shape{2, 1, 2, 4};
478
479 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
480 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
481
482 armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::NotEqual);
483
484 armnn::INetworkPtr network = armnn::INetwork::Create();
485 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
486 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
487 armnn::IConnectableLayer* const comparisonLayer = network->AddComparisonLayer(descriptor, layerName.c_str());
488 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
489
490 inputLayer0->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(0));
491 inputLayer1->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(1));
492 comparisonLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
493
494 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
495 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
496 comparisonLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
497
498 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
499 BOOST_CHECK(deserializedNetwork);
500
501 ComparisonLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo }, descriptor);
502 deserializedNetwork->Accept(verifier);
503}
504
Conor Kennedy76277882019-02-26 08:29:54 +0000505BOOST_AUTO_TEST_CASE(SerializeConstant)
506{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000507 class ConstantLayerVerifier : public LayerVerifierBase
Conor Kennedy76277882019-02-26 08:29:54 +0000508 {
509 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000510 ConstantLayerVerifier(const std::string& layerName,
511 const std::vector<armnn::TensorInfo>& inputInfos,
512 const std::vector<armnn::TensorInfo>& outputInfos,
513 const armnn::ConstTensor& layerInput)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100514 : LayerVerifierBase(layerName, inputInfos, outputInfos)
515 , m_LayerInput(layerInput) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000516
517 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
518 const armnn::ConstTensor& input,
519 const char* name) override
Conor Kennedy76277882019-02-26 08:29:54 +0000520 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000521 VerifyNameAndConnections(layer, name);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000522 CompareConstTensor(input, m_LayerInput);
Conor Kennedy76277882019-02-26 08:29:54 +0000523 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000524
525 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
526
527 private:
528 armnn::ConstTensor m_LayerInput;
Conor Kennedy76277882019-02-26 08:29:54 +0000529 };
530
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000531 const std::string layerName("constant");
532 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
Conor Kennedy76277882019-02-26 08:29:54 +0000533
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000534 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
535 armnn::ConstTensor constTensor(info, constantData);
Conor Kennedy76277882019-02-26 08:29:54 +0000536
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000537 armnn::INetworkPtr network(armnn::INetwork::Create());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000538 armnn::IConnectableLayer* input = network->AddInputLayer(0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000539 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000540 armnn::IConnectableLayer* add = network->AddAdditionLayer();
541 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
Conor Kennedy76277882019-02-26 08:29:54 +0000542
543 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
544 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
545 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
546
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000547 input->GetOutputSlot(0).SetTensorInfo(info);
548 constant->GetOutputSlot(0).SetTensorInfo(info);
549 add->GetOutputSlot(0).SetTensorInfo(info);
Conor Kennedy76277882019-02-26 08:29:54 +0000550
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000551 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Conor Kennedy76277882019-02-26 08:29:54 +0000552 BOOST_CHECK(deserializedNetwork);
553
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000554 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
555 deserializedNetwork->Accept(verifier);
Conor Kennedy76277882019-02-26 08:29:54 +0000556}
557
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000558BOOST_AUTO_TEST_CASE(SerializeConvolution2d)
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000559{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100560 using Descriptor = armnn::Convolution2dDescriptor;
561 class Convolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000562 {
563 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000564 Convolution2dLayerVerifier(const std::string& layerName,
565 const std::vector<armnn::TensorInfo>& inputInfos,
566 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100567 const Descriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100568 const armnn::ConstTensor& weights,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100569 const armnn::Optional<armnn::ConstTensor>& biases)
570 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
571 , m_Weights(weights)
572 , m_Biases(biases) {}
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000573
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000574 void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100575 const Descriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100576 const armnn::ConstTensor& weights,
577 const armnn::Optional<armnn::ConstTensor>& biases,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000578 const char* name) override
579 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000580 VerifyNameAndConnections(layer, name);
581 VerifyDescriptor(descriptor);
582
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100583 // check weights
584 CompareConstTensor(weights, m_Weights);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000585
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100586 // check biases
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100587 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100588 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
589
590 if (biases.has_value() && m_Biases.has_value())
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000591 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100592 CompareConstTensor(biases.value(), m_Biases.value());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000593 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000594 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000595
596 private:
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100597 armnn::ConstTensor m_Weights;
598 armnn::Optional<armnn::ConstTensor> m_Biases;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000599 };
600
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000601 const std::string layerName("convolution2d");
602 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
603 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000604
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000605 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
606 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000607
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000608 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
609 armnn::ConstTensor weights(weightsInfo, weightsData);
610
611 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
612 armnn::ConstTensor biases(biasesInfo, biasesData);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000613
614 armnn::Convolution2dDescriptor descriptor;
615 descriptor.m_PadLeft = 1;
616 descriptor.m_PadRight = 1;
617 descriptor.m_PadTop = 1;
618 descriptor.m_PadBottom = 1;
619 descriptor.m_StrideX = 2;
620 descriptor.m_StrideY = 2;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100621 descriptor.m_DilationX = 2;
622 descriptor.m_DilationY = 2;
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000623 descriptor.m_BiasEnabled = true;
624 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
625
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000626 armnn::INetworkPtr network = armnn::INetwork::Create();
627 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000628 armnn::IConnectableLayer* const convLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100629 network->AddConvolution2dLayer(descriptor,
630 weights,
631 armnn::Optional<armnn::ConstTensor>(biases),
632 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000633 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000634
635 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000636 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000637
638 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000639 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
640
641 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
642 BOOST_CHECK(deserializedNetwork);
643
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000644 Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
645 deserializedNetwork->Accept(verifier);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000646}
647
Aron Virginas-Tarda9d2d32019-09-20 10:42:02 +0100648BOOST_AUTO_TEST_CASE(SerializeDepthToSpace)
649{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100650 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(DepthToSpace)
Aron Virginas-Tarda9d2d32019-09-20 10:42:02 +0100651
652 const std::string layerName("depthToSpace");
653
654 const armnn::TensorInfo inputInfo ({ 1, 8, 4, 12 }, armnn::DataType::Float32);
655 const armnn::TensorInfo outputInfo({ 1, 16, 8, 3 }, armnn::DataType::Float32);
656
657 armnn::DepthToSpaceDescriptor desc;
658 desc.m_BlockSize = 2;
659 desc.m_DataLayout = armnn::DataLayout::NHWC;
660
661 armnn::INetworkPtr network = armnn::INetwork::Create();
662 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
663 armnn::IConnectableLayer* const depthToSpaceLayer = network->AddDepthToSpaceLayer(desc, layerName.c_str());
664 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
665
666 inputLayer->GetOutputSlot(0).Connect(depthToSpaceLayer->GetInputSlot(0));
667 depthToSpaceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
668
669 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
670 depthToSpaceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
671
672 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
673 BOOST_CHECK(deserializedNetwork);
674
675 DepthToSpaceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
676 deserializedNetwork->Accept(verifier);
677}
678
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000679BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d)
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000680{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100681 using Descriptor = armnn::DepthwiseConvolution2dDescriptor;
682 class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000683 {
684 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000685 DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
686 const std::vector<armnn::TensorInfo>& inputInfos,
687 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100688 const Descriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100689 const armnn::ConstTensor& weights,
690 const armnn::Optional<armnn::ConstTensor>& biases) :
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100691 LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor),
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100692 m_Weights(weights),
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100693 m_Biases(biases) {}
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000694
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000695 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100696 const Descriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100697 const armnn::ConstTensor& weights,
698 const armnn::Optional<armnn::ConstTensor>& biases,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000699 const char* name) override
700 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000701 VerifyNameAndConnections(layer, name);
702 VerifyDescriptor(descriptor);
703
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100704 // check weights
705 CompareConstTensor(weights, m_Weights);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000706
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100707 // check biases
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100708 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100709 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
710
711 if (biases.has_value() && m_Biases.has_value())
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000712 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100713 CompareConstTensor(biases.value(), m_Biases.value());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000714 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000715 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000716
717 private:
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100718 armnn::ConstTensor m_Weights;
719 armnn::Optional<armnn::ConstTensor> m_Biases;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000720 };
721
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000722 const std::string layerName("depwiseConvolution2d");
723 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
724 const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000725
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000726 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
727 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000728
729 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
730 armnn::ConstTensor weights(weightsInfo, weightsData);
731
732 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
733 armnn::ConstTensor biases(biasesInfo, biasesData);
734
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000735 armnn::DepthwiseConvolution2dDescriptor descriptor;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100736 descriptor.m_PadLeft = 1;
737 descriptor.m_PadRight = 1;
738 descriptor.m_PadTop = 1;
739 descriptor.m_PadBottom = 1;
740 descriptor.m_StrideX = 2;
741 descriptor.m_StrideY = 2;
742 descriptor.m_DilationX = 2;
743 descriptor.m_DilationY = 2;
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000744 descriptor.m_BiasEnabled = true;
745 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
746
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000747 armnn::INetworkPtr network = armnn::INetwork::Create();
748 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
749 armnn::IConnectableLayer* const depthwiseConvLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100750 network->AddDepthwiseConvolution2dLayer(descriptor,
751 weights,
752 armnn::Optional<armnn::ConstTensor>(biases),
753 layerName.c_str());
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000754 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
755
756 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000757 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000758
759 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000760 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
761
762 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
763 BOOST_CHECK(deserializedNetwork);
764
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000765 DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
766 deserializedNetwork->Accept(verifier);
Jim Flynn18ce3382019-03-08 11:08:30 +0000767}
768
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000769BOOST_AUTO_TEST_CASE(SerializeDequantize)
770{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100771 DECLARE_LAYER_VERIFIER_CLASS(Dequantize)
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000772
773 const std::string layerName("dequantize");
774 const armnn::TensorInfo inputInfo({ 1, 5, 2, 3 }, armnn::DataType::QuantisedAsymm8, 0.5f, 1);
775 const armnn::TensorInfo outputInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
776
777 armnn::INetworkPtr network = armnn::INetwork::Create();
778 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
779 armnn::IConnectableLayer* const dequantizeLayer = network->AddDequantizeLayer(layerName.c_str());
780 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
781
782 inputLayer->GetOutputSlot(0).Connect(dequantizeLayer->GetInputSlot(0));
783 dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
784
785 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
786 dequantizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
787
788 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
789 BOOST_CHECK(deserializedNetwork);
790
791 DequantizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
792 deserializedNetwork->Accept(verifier);
793}
794
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000795BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess)
796{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100797 using Descriptor = armnn::DetectionPostProcessDescriptor;
798 class DetectionPostProcessLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000799 {
800 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000801 DetectionPostProcessLayerVerifier(const std::string& layerName,
802 const std::vector<armnn::TensorInfo>& inputInfos,
803 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100804 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000805 const armnn::ConstTensor& anchors)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100806 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
807 , m_Anchors(anchors) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000808
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000809 void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100810 const Descriptor& descriptor,
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000811 const armnn::ConstTensor& anchors,
812 const char* name) override
813 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000814 VerifyNameAndConnections(layer, name);
815 VerifyDescriptor(descriptor);
816
817 CompareConstTensor(anchors, m_Anchors);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000818 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000819
820 private:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000821 armnn::ConstTensor m_Anchors;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000822 };
823
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000824 const std::string layerName("detectionPostProcess");
825
826 const std::vector<armnn::TensorInfo> inputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000827 armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32),
828 armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000829 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000830
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000831 const std::vector<armnn::TensorInfo> outputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000832 armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32),
833 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
834 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
835 armnn::TensorInfo({ 1 }, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000836 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000837
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000838 armnn::DetectionPostProcessDescriptor descriptor;
839 descriptor.m_UseRegularNms = true;
840 descriptor.m_MaxDetections = 3;
841 descriptor.m_MaxClassesPerDetection = 1;
842 descriptor.m_DetectionsPerClass =1;
843 descriptor.m_NmsScoreThreshold = 0.0;
844 descriptor.m_NmsIouThreshold = 0.5;
845 descriptor.m_NumClasses = 2;
846 descriptor.m_ScaleY = 10.0;
847 descriptor.m_ScaleX = 10.0;
848 descriptor.m_ScaleH = 5.0;
849 descriptor.m_ScaleW = 5.0;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000850
851 const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
852 const std::vector<float> anchorsData({
853 0.5f, 0.5f, 1.0f, 1.0f,
854 0.5f, 0.5f, 1.0f, 1.0f,
855 0.5f, 0.5f, 1.0f, 1.0f,
856 0.5f, 10.5f, 1.0f, 1.0f,
857 0.5f, 10.5f, 1.0f, 1.0f,
858 0.5f, 100.5f, 1.0f, 1.0f
859 });
860 armnn::ConstTensor anchors(anchorsInfo, anchorsData);
861
862 armnn::INetworkPtr network = armnn::INetwork::Create();
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000863 armnn::IConnectableLayer* const detectionLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000864 network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000865
866 for (unsigned int i = 0; i < 2; i++)
867 {
868 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
869 inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
870 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
871 }
872
873 for (unsigned int i = 0; i < 4; i++)
874 {
875 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
876 detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
877 detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
878 }
879
880 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
881 BOOST_CHECK(deserializedNetwork);
882
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000883 DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors);
884 deserializedNetwork->Accept(verifier);
885}
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000886
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000887BOOST_AUTO_TEST_CASE(SerializeDivision)
888{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100889 DECLARE_LAYER_VERIFIER_CLASS(Division)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000890
891 const std::string layerName("division");
892 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
893
894 armnn::INetworkPtr network = armnn::INetwork::Create();
895 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
896 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
897 armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
898 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
899
900 inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
901 inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
902 divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
903
904 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
905 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
906 divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
907
908 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
909 BOOST_CHECK(deserializedNetwork);
910
911 DivisionLayerVerifier verifier(layerName, {info, info}, {info});
912 deserializedNetwork->Accept(verifier);
913}
914
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +0100915class EqualLayerVerifier : public LayerVerifierBase
916{
917public:
918 EqualLayerVerifier(const std::string& layerName,
919 const std::vector<armnn::TensorInfo>& inputInfos,
920 const std::vector<armnn::TensorInfo>& outputInfos)
921 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
922
923 void VisitComparisonLayer(const armnn::IConnectableLayer* layer,
924 const armnn::ComparisonDescriptor& descriptor,
925 const char* name) override
926 {
927 VerifyNameAndConnections(layer, name);
928 BOOST_CHECK(descriptor.m_Operation == armnn::ComparisonOperation::Equal);
929 }
930
931 void VisitEqualLayer(const armnn::IConnectableLayer* layer, const char* name) override
932 {
933 throw armnn::Exception("EqualLayer should have translated to ComparisonLayer");
934 }
935};
936
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100937// NOTE: Until the deprecated AddEqualLayer disappears this test checks that calling
938// AddEqualLayer places a ComparisonLayer into the serialized format and that
939// when this deserialises we have a ComparisonLayer
940BOOST_AUTO_TEST_CASE(SerializeEqual)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000941{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100942 const std::string layerName("equal");
943
944 const armnn::TensorShape shape{2, 1, 2, 4};
945
946 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
947 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
948
949 armnn::INetworkPtr network = armnn::INetwork::Create();
950 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
951 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
952 ARMNN_NO_DEPRECATE_WARN_BEGIN
953 armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str());
954 ARMNN_NO_DEPRECATE_WARN_END
955 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
956
957 inputLayer0->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
958 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
959 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
960
961 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
962 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
963 equalLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
964
965 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
966 BOOST_CHECK(deserializedNetwork);
967
968 EqualLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo });
969 deserializedNetwork->Accept(verifier);
970}
971
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +0100972BOOST_AUTO_TEST_CASE(EnsureEqualBackwardCompatibility)
973{
974 // The hex data below is a flat buffer containing a simple network with two inputs,
975 // an EqualLayer (now deprecated) and an output
976 //
977 // This test verifies that we can still deserialize this old-style model by replacing
978 // the EqualLayer with an equivalent ComparisonLayer
979 const std::vector<uint8_t> equalModel =
980 {
981 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
982 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
983 0xCC, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
984 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
985 0x60, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
986 0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xEA, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
987 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
988 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
989 0x64, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
990 0x00, 0x13, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
991 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
992 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x65, 0x71, 0x75, 0x61, 0x6C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
993 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
994 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00,
995 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
996 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
997 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
998 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
999 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1000 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1001 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1002 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1003 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1004 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1005 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1006 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1007 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
1008 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1009 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1010 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1011 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1012 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1013 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1014 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1015 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1016 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1017 0x04, 0x00, 0x00, 0x00
1018 };
1019
1020 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(equalModel.begin(), equalModel.end()));
1021 BOOST_CHECK(deserializedNetwork);
1022
1023 const armnn::TensorShape shape{ 2, 1, 2, 4 };
1024
1025 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1026 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1027
1028 EqualLayerVerifier verifier("equal", { inputInfo, inputInfo }, { outputInfo });
1029 deserializedNetwork->Accept(verifier);
1030}
1031
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001032BOOST_AUTO_TEST_CASE(SerializeFloor)
1033{
1034 DECLARE_LAYER_VERIFIER_CLASS(Floor)
1035
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001036 const std::string layerName("floor");
1037 const armnn::TensorInfo info({4,4}, armnn::DataType::Float32);
1038
1039 armnn::INetworkPtr network = armnn::INetwork::Create();
1040 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1041 armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
1042 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1043
1044 inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
1045 floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1046
1047 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1048 floorLayer->GetOutputSlot(0).SetTensorInfo(info);
1049
1050 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1051 BOOST_CHECK(deserializedNetwork);
1052
1053 FloorLayerVerifier verifier(layerName, {info}, {info});
1054 deserializedNetwork->Accept(verifier);
1055}
1056
1057BOOST_AUTO_TEST_CASE(SerializeFullyConnected)
1058{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001059 using Descriptor = armnn::FullyConnectedDescriptor;
1060 class FullyConnectedLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001061 {
1062 public:
1063 FullyConnectedLayerVerifier(const std::string& layerName,
1064 const std::vector<armnn::TensorInfo>& inputInfos,
1065 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001066 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001067 const armnn::ConstTensor& weight,
1068 const armnn::Optional<armnn::ConstTensor>& bias)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001069 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
1070 , m_Weight(weight)
1071 , m_Bias(bias) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001072
1073 void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001074 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001075 const armnn::ConstTensor& weight,
1076 const armnn::Optional<armnn::ConstTensor>& bias,
1077 const char* name) override
1078 {
1079 VerifyNameAndConnections(layer, name);
1080 VerifyDescriptor(descriptor);
1081
1082 CompareConstTensor(weight, m_Weight);
1083
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001084 BOOST_TEST(bias.has_value() == descriptor.m_BiasEnabled);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001085 BOOST_TEST(bias.has_value() == m_Bias.has_value());
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001086
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001087 if (bias.has_value() && m_Bias.has_value())
1088 {
1089 CompareConstTensor(bias.value(), m_Bias.value());
1090 }
1091 }
1092
1093 private:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001094 armnn::ConstTensor m_Weight;
1095 armnn::Optional<armnn::ConstTensor> m_Bias;
1096 };
1097
1098 const std::string layerName("fullyConnected");
1099 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
1100 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
1101
1102 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
1103 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
1104 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
1105 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
1106 armnn::ConstTensor weights(weightsInfo, weightsData);
1107 armnn::ConstTensor biases(biasesInfo, biasesData);
1108
1109 armnn::FullyConnectedDescriptor descriptor;
1110 descriptor.m_BiasEnabled = true;
1111 descriptor.m_TransposeWeightMatrix = false;
1112
1113 armnn::INetworkPtr network = armnn::INetwork::Create();
1114 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1115 armnn::IConnectableLayer* const fullyConnectedLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +01001116 network->AddFullyConnectedLayer(descriptor,
1117 weights,
1118 armnn::Optional<armnn::ConstTensor>(biases),
1119 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001120 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1121
1122 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
1123 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1124
1125 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1126 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1127
1128 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1129 BOOST_CHECK(deserializedNetwork);
1130
1131 FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
1132 deserializedNetwork->Accept(verifier);
1133}
1134
1135BOOST_AUTO_TEST_CASE(SerializeGather)
1136{
1137 class GatherLayerVerifier : public LayerVerifierBase
1138 {
1139 public:
1140 GatherLayerVerifier(const std::string& layerName,
1141 const std::vector<armnn::TensorInfo>& inputInfos,
1142 const std::vector<armnn::TensorInfo>& outputInfos)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001143 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001144
1145 void VisitGatherLayer(const armnn::IConnectableLayer* layer, const char *name) override
1146 {
1147 VerifyNameAndConnections(layer, name);
1148 }
1149
1150 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
1151 const armnn::ConstTensor& input,
1152 const char *name) override {}
1153 };
1154
1155 const std::string layerName("gather");
1156 armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QuantisedAsymm8);
1157 armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QuantisedAsymm8);
1158 const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
1159
1160 paramsInfo.SetQuantizationScale(1.0f);
1161 paramsInfo.SetQuantizationOffset(0);
1162 outputInfo.SetQuantizationScale(1.0f);
1163 outputInfo.SetQuantizationOffset(0);
1164
1165 const std::vector<int32_t>& indicesData = {7, 6, 5};
1166
1167 armnn::INetworkPtr network = armnn::INetwork::Create();
1168 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
1169 armnn::IConnectableLayer *const constantLayer =
1170 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
1171 armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(layerName.c_str());
1172 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
1173
1174 inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
1175 constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
1176 gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1177
1178 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
1179 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
1180 gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1181
1182 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1183 BOOST_CHECK(deserializedNetwork);
1184
1185 GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo});
1186 deserializedNetwork->Accept(verifier);
1187}
1188
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +01001189class GreaterLayerVerifier : public LayerVerifierBase
1190{
1191public:
1192 GreaterLayerVerifier(const std::string& layerName,
1193 const std::vector<armnn::TensorInfo>& inputInfos,
1194 const std::vector<armnn::TensorInfo>& outputInfos)
1195 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1196
1197 void VisitComparisonLayer(const armnn::IConnectableLayer* layer,
1198 const armnn::ComparisonDescriptor& descriptor,
1199 const char* name) override
1200 {
1201 VerifyNameAndConnections(layer, name);
1202 BOOST_CHECK(descriptor.m_Operation == armnn::ComparisonOperation::Greater);
1203 }
1204
1205 void VisitGreaterLayer(const armnn::IConnectableLayer* layer, const char* name) override
1206 {
1207 throw armnn::Exception("GreaterLayer should have translated to ComparisonLayer");
1208 }
1209};
1210
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001211// NOTE: Until the deprecated AddGreaterLayer disappears this test checks that calling
1212// AddGreaterLayer places a ComparisonLayer into the serialized format and that
1213// when this deserialises we have a ComparisonLayer
1214BOOST_AUTO_TEST_CASE(SerializeGreater)
Aron Virginas-Tar781ced92019-10-03 11:15:39 +01001215{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001216 const std::string layerName("greater");
1217
1218 const armnn::TensorShape shape{2, 1, 2, 4};
1219
1220 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1221 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1222
1223 armnn::INetworkPtr network = armnn::INetwork::Create();
1224 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1225 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1226 ARMNN_NO_DEPRECATE_WARN_BEGIN
1227 armnn::IConnectableLayer* const equalLayer = network->AddGreaterLayer(layerName.c_str());
1228 ARMNN_NO_DEPRECATE_WARN_END
1229 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1230
1231 inputLayer0->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
1232 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
1233 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1234
1235 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
1236 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
1237 equalLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1238
1239 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1240 BOOST_CHECK(deserializedNetwork);
1241
1242 GreaterLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo });
1243 deserializedNetwork->Accept(verifier);
1244}
1245
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +01001246BOOST_AUTO_TEST_CASE(EnsureGreaterBackwardCompatibility)
1247{
1248 // The hex data below is a flat buffer containing a simple network with two inputs,
1249 // an GreaterLayer (now deprecated) and an output
1250 //
1251 // This test verifies that we can still deserialize this old-style model by replacing
1252 // the GreaterLayer with an equivalent ComparisonLayer
1253 const std::vector<uint8_t> greaterModel =
1254 {
1255 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1256 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1257 0xCC, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1259 0x60, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1260 0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xEA, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1261 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1263 0x64, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1264 0x00, 0x19, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1265 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1266 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00,
1267 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1268 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00,
1269 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1270 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1271 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1272 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1273 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1274 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1275 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1276 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1277 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1279 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1280 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1281 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1282 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1283 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1284 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1285 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1286 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1287 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1288 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1289 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1291 0x02, 0x00, 0x00, 0x00
1292 };
1293
1294 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(greaterModel.begin(), greaterModel.end()));
1295 BOOST_CHECK(deserializedNetwork);
1296
1297 const armnn::TensorShape shape{ 1, 2, 2, 2 };
1298
1299 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1300 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1301
1302 GreaterLayerVerifier verifier("greater", { inputInfo, inputInfo }, { outputInfo });
1303 deserializedNetwork->Accept(verifier);
1304}
1305
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001306BOOST_AUTO_TEST_CASE(SerializeInstanceNormalization)
1307{
1308 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(InstanceNormalization)
1309
Aron Virginas-Tar781ced92019-10-03 11:15:39 +01001310 const std::string layerName("instanceNormalization");
1311 const armnn::TensorInfo info({ 1, 2, 1, 5 }, armnn::DataType::Float32);
1312
1313 armnn::InstanceNormalizationDescriptor descriptor;
1314 descriptor.m_Gamma = 1.1f;
1315 descriptor.m_Beta = 0.1f;
1316 descriptor.m_Eps = 0.0001f;
1317 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
1318
1319 armnn::INetworkPtr network = armnn::INetwork::Create();
1320 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1321 armnn::IConnectableLayer* const instanceNormLayer =
1322 network->AddInstanceNormalizationLayer(descriptor, layerName.c_str());
1323 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1324
1325 inputLayer->GetOutputSlot(0).Connect(instanceNormLayer->GetInputSlot(0));
1326 instanceNormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1327
1328 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1329 instanceNormLayer->GetOutputSlot(0).SetTensorInfo(info);
1330
1331 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1332 BOOST_CHECK(deserializedNetwork);
1333
1334 InstanceNormalizationLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1335 deserializedNetwork->Accept(verifier);
1336}
1337
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001338DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(L2Normalization)
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001339
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001340BOOST_AUTO_TEST_CASE(SerializeL2Normalization)
1341{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001342 const std::string l2NormLayerName("l2Normalization");
1343 const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1344
1345 armnn::L2NormalizationDescriptor desc;
1346 desc.m_DataLayout = armnn::DataLayout::NCHW;
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001347 desc.m_Eps = 0.0001f;
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001348
1349 armnn::INetworkPtr network = armnn::INetwork::Create();
1350 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1351 armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1352 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1353
1354 inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1355 l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1356
1357 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1358 l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1359
1360 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1361 BOOST_CHECK(deserializedNetwork);
1362
1363 L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc);
1364 deserializedNetwork->Accept(verifier);
1365}
1366
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001367BOOST_AUTO_TEST_CASE(EnsureL2NormalizationBackwardCompatibility)
1368{
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001369 // The hex data below is a flat buffer containing a simple network with one input
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001370 // a L2Normalization layer and an output layer with dimensions as per the tensor infos below.
1371 //
1372 // This test verifies that we can still read back these old style
1373 // models without the normalization epsilon value.
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001374 const std::vector<uint8_t> l2NormalizationModel =
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001375 {
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001376 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1377 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1378 0x3C, 0x01, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1379 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xE8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
1380 0x04, 0x00, 0x00, 0x00, 0xD6, 0xFE, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
1381 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
1382 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1384 0x4C, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
1385 0x00, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1386 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1387 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1388 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x20, 0x00,
1389 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x6C, 0x32, 0x4E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x69, 0x7A, 0x61, 0x74,
1390 0x69, 0x6F, 0x6E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00,
1391 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1392 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
1393 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1394 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1395 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1396 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1397 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1398 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1399 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1400 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1401 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1402 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1403 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1404 0x05, 0x00, 0x00, 0x00, 0x00
1405 };
1406
1407 armnn::INetworkPtr deserializedNetwork =
1408 DeserializeNetwork(std::string(l2NormalizationModel.begin(), l2NormalizationModel.end()));
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001409 BOOST_CHECK(deserializedNetwork);
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001410
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001411 const std::string layerName("l2Normalization");
1412 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 2, 1, 5}, armnn::DataType::Float32);
1413
1414 armnn::L2NormalizationDescriptor desc;
1415 desc.m_DataLayout = armnn::DataLayout::NCHW;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001416 // Since this variable does not exist in the l2NormalizationModel dump, the default value will be loaded
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001417 desc.m_Eps = 1e-12f;
1418
1419 L2NormalizationLayerVerifier verifier(layerName, {inputInfo}, {inputInfo}, desc);
1420 deserializedNetwork->Accept(verifier);
1421}
1422
Sadik Armagan26257852019-10-14 13:00:47 +01001423BOOST_AUTO_TEST_CASE(SerializeLogSoftmax)
1424{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001425 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(LogSoftmax)
Sadik Armagan26257852019-10-14 13:00:47 +01001426
1427 const std::string layerName("log_softmax");
1428 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
1429
1430 armnn::LogSoftmaxDescriptor descriptor;
1431 descriptor.m_Beta = 1.0f;
1432 descriptor.m_Axis = -1;
1433
1434 armnn::INetworkPtr network = armnn::INetwork::Create();
1435 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1436 armnn::IConnectableLayer* const logSoftmaxLayer = network->AddLogSoftmaxLayer(descriptor, layerName.c_str());
1437 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1438
1439 inputLayer->GetOutputSlot(0).Connect(logSoftmaxLayer->GetInputSlot(0));
1440 logSoftmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1441
1442 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1443 logSoftmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
1444
1445 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1446 BOOST_CHECK(deserializedNetwork);
1447
1448 LogSoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1449 deserializedNetwork->Accept(verifier);
1450}
1451
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001452BOOST_AUTO_TEST_CASE(SerializeMaximum)
1453{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001454 DECLARE_LAYER_VERIFIER_CLASS(Maximum)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001455
1456 const std::string layerName("maximum");
1457 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1458
1459 armnn::INetworkPtr network = armnn::INetwork::Create();
1460 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1461 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1462 armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1463 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1464
1465 inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1466 inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1467 maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1468
1469 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1470 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1471 maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1472
1473 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1474 BOOST_CHECK(deserializedNetwork);
1475
1476 MaximumLayerVerifier verifier(layerName, {info, info}, {info});
1477 deserializedNetwork->Accept(verifier);
1478}
1479
1480BOOST_AUTO_TEST_CASE(SerializeMean)
1481{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001482 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Mean)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001483
1484 const std::string layerName("mean");
1485 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1486 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1487
1488 armnn::MeanDescriptor descriptor;
1489 descriptor.m_Axis = { 2 };
1490 descriptor.m_KeepDims = true;
1491
1492 armnn::INetworkPtr network = armnn::INetwork::Create();
1493 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1494 armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1495 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1496
1497 inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1498 meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1499
1500 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1501 meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1502
1503 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1504 BOOST_CHECK(deserializedNetwork);
1505
1506 MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1507 deserializedNetwork->Accept(verifier);
1508}
1509
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001510BOOST_AUTO_TEST_CASE(SerializeMerge)
1511{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001512 DECLARE_LAYER_VERIFIER_CLASS(Merge)
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001513
1514 const std::string layerName("merge");
1515 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1516
1517 armnn::INetworkPtr network = armnn::INetwork::Create();
1518 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1519 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1520 armnn::IConnectableLayer* const mergeLayer = network->AddMergeLayer(layerName.c_str());
1521 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1522
1523 inputLayer0->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(0));
1524 inputLayer1->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(1));
1525 mergeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1526
1527 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1528 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1529 mergeLayer->GetOutputSlot(0).SetTensorInfo(info);
1530
1531 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1532 BOOST_CHECK(deserializedNetwork);
1533
1534 MergeLayerVerifier verifier(layerName, {info, info}, {info});
1535 deserializedNetwork->Accept(verifier);
1536}
1537
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001538class MergerLayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::OriginsDescriptor>
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001539{
Jim Flynn5fa83932019-05-09 15:35:43 +01001540public:
1541 MergerLayerVerifier(const std::string& layerName,
1542 const std::vector<armnn::TensorInfo>& inputInfos,
1543 const std::vector<armnn::TensorInfo>& outputInfos,
1544 const armnn::OriginsDescriptor& descriptor)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001545 : LayerVerifierBaseWithDescriptor<armnn::OriginsDescriptor>(layerName, inputInfos, outputInfos, descriptor) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001546
Jim Flynn5fa83932019-05-09 15:35:43 +01001547 void VisitMergerLayer(const armnn::IConnectableLayer* layer,
1548 const armnn::OriginsDescriptor& descriptor,
1549 const char* name) override
1550 {
Jim Flynne242f2d2019-05-22 14:24:13 +01001551 throw armnn::Exception("MergerLayer should have translated to ConcatLayer");
1552 }
1553
1554 void VisitConcatLayer(const armnn::IConnectableLayer* layer,
1555 const armnn::OriginsDescriptor& descriptor,
1556 const char* name) override
1557 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001558 VerifyNameAndConnections(layer, name);
1559 VerifyDescriptor(descriptor);
1560 }
Jim Flynn5fa83932019-05-09 15:35:43 +01001561};
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001562
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001563// NOTE: Until the deprecated AddMergerLayer disappears this test checks that calling
Jim Flynne242f2d2019-05-22 14:24:13 +01001564// AddMergerLayer places a ConcatLayer into the serialized format and that
1565// when this deserialises we have a ConcatLayer
Jim Flynn5fa83932019-05-09 15:35:43 +01001566BOOST_AUTO_TEST_CASE(SerializeMerger)
1567{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001568 const std::string layerName("merger");
1569 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1570 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1571
1572 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1573
1574 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001575 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001576
1577 armnn::INetworkPtr network = armnn::INetwork::Create();
1578 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1579 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
Jim Flynn906f9462019-05-10 13:55:21 +01001580 ARMNN_NO_DEPRECATE_WARN_BEGIN
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001581 armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str());
Jim Flynn906f9462019-05-10 13:55:21 +01001582 ARMNN_NO_DEPRECATE_WARN_END
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001583 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1584
1585 inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
1586 inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
1587 mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1588
1589 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1590 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1591 mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1592
Jim Flynn5fa83932019-05-09 15:35:43 +01001593 std::string mergerLayerNetwork = SerializeNetwork(*network);
1594 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001595 BOOST_CHECK(deserializedNetwork);
1596
1597 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1598 deserializedNetwork->Accept(verifier);
1599}
1600
Jim Flynn5fa83932019-05-09 15:35:43 +01001601BOOST_AUTO_TEST_CASE(EnsureMergerLayerBackwardCompatibility)
1602{
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001603 // The hex data below is a flat buffer containing a simple network with two inputs
Jim Flynne242f2d2019-05-22 14:24:13 +01001604 // a merger layer (now deprecated) and an output layer with dimensions as per the tensor infos below.
1605 //
1606 // This test verifies that we can still read back these old style
Jim Flynn5fa83932019-05-09 15:35:43 +01001607 // models replacing the MergerLayers with ConcatLayers with the same parameters.
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001608 const std::vector<uint8_t> mergerModel =
Jim Flynn5fa83932019-05-09 15:35:43 +01001609 {
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001610 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1611 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1612 0x38, 0x02, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1614 0xF4, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1615 0x00, 0x00, 0x9A, 0xFE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1616 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1618 0xF8, 0xFE, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1619 0x00, 0x1F, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1620 0x68, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
1621 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1622 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0x04, 0x00,
1623 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1624 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1626 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1627 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6D, 0x65, 0x72, 0x67, 0x65, 0x72, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1628 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1629 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
1630 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00,
1631 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1632 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1633 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1634 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1635 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1636 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1637 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1638 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1640 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1641 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1642 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1643 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1644 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1645 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1646 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1647 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1648 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1649 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1650 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1651 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1652 0x02, 0x00, 0x00, 0x00
1653 };
1654
1655 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(mergerModel.begin(), mergerModel.end()));
Jim Flynn5fa83932019-05-09 15:35:43 +01001656 BOOST_CHECK(deserializedNetwork);
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001657
1658 const armnn::TensorInfo inputInfo = armnn::TensorInfo({ 2, 3, 2, 2 }, armnn::DataType::Float32);
1659 const armnn::TensorInfo outputInfo = armnn::TensorInfo({ 4, 3, 2, 2 }, armnn::DataType::Float32);
Jim Flynn5fa83932019-05-09 15:35:43 +01001660
1661 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1662
1663 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001664 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Jim Flynn5fa83932019-05-09 15:35:43 +01001665
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001666 MergerLayerVerifier verifier("merger", { inputInfo, inputInfo }, { outputInfo }, descriptor);
Jim Flynn5fa83932019-05-09 15:35:43 +01001667 deserializedNetwork->Accept(verifier);
1668}
1669
Jim Flynne242f2d2019-05-22 14:24:13 +01001670BOOST_AUTO_TEST_CASE(SerializeConcat)
1671{
1672 const std::string layerName("concat");
1673 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1674 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1675
1676 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1677
1678 armnn::OriginsDescriptor descriptor =
1679 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1680
1681 armnn::INetworkPtr network = armnn::INetwork::Create();
1682 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1683 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1684 armnn::IConnectableLayer* const concatLayer = network->AddConcatLayer(descriptor, layerName.c_str());
1685 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1686
1687 inputLayerOne->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
1688 inputLayerTwo->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
1689 concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1690
1691 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1692 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1693 concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1694
1695 std::string concatLayerNetwork = SerializeNetwork(*network);
1696 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(concatLayerNetwork);
1697 BOOST_CHECK(deserializedNetwork);
1698
1699 // NOTE: using the MergerLayerVerifier to ensure that it is a concat layer and not a
1700 // merger layer that gets placed into the graph.
1701 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1702 deserializedNetwork->Accept(verifier);
1703}
1704
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001705BOOST_AUTO_TEST_CASE(SerializeMinimum)
1706{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001707 DECLARE_LAYER_VERIFIER_CLASS(Minimum)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001708
1709 const std::string layerName("minimum");
1710 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1711
1712 armnn::INetworkPtr network = armnn::INetwork::Create();
1713 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1714 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1715 armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1716 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1717
1718 inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1719 inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1720 minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1721
1722 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1723 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1724 minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
1725
1726 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1727 BOOST_CHECK(deserializedNetwork);
1728
1729 MinimumLayerVerifier verifier(layerName, {info, info}, {info});
1730 deserializedNetwork->Accept(verifier);
1731}
1732
1733BOOST_AUTO_TEST_CASE(SerializeMultiplication)
1734{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001735 DECLARE_LAYER_VERIFIER_CLASS(Multiplication)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001736
1737 const std::string layerName("multiplication");
1738 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1739
1740 armnn::INetworkPtr network = armnn::INetwork::Create();
1741 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1742 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1743 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
1744 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1745
1746 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
1747 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
1748 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1749
1750 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1751 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1752 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
1753
1754 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1755 BOOST_CHECK(deserializedNetwork);
1756
1757 MultiplicationLayerVerifier verifier(layerName, {info, info}, {info});
1758 deserializedNetwork->Accept(verifier);
1759}
1760
Ellen Norris-Thompson51982472019-06-19 11:46:21 +01001761BOOST_AUTO_TEST_CASE(SerializePrelu)
1762{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001763 DECLARE_LAYER_VERIFIER_CLASS(Prelu)
Ellen Norris-Thompson51982472019-06-19 11:46:21 +01001764
1765 const std::string layerName("prelu");
1766
1767 armnn::TensorInfo inputTensorInfo ({ 4, 1, 2 }, armnn::DataType::Float32);
1768 armnn::TensorInfo alphaTensorInfo ({ 5, 4, 3, 1 }, armnn::DataType::Float32);
1769 armnn::TensorInfo outputTensorInfo({ 5, 4, 3, 2 }, armnn::DataType::Float32);
1770
1771 armnn::INetworkPtr network = armnn::INetwork::Create();
1772 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1773 armnn::IConnectableLayer* const alphaLayer = network->AddInputLayer(1);
1774 armnn::IConnectableLayer* const preluLayer = network->AddPreluLayer(layerName.c_str());
1775 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1776
1777 inputLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(0));
1778 alphaLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(1));
1779 preluLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1780
1781 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1782 alphaLayer->GetOutputSlot(0).SetTensorInfo(alphaTensorInfo);
1783 preluLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1784
1785 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1786 BOOST_CHECK(deserializedNetwork);
1787
1788 PreluLayerVerifier verifier(layerName, {inputTensorInfo, alphaTensorInfo}, {outputTensorInfo});
1789 deserializedNetwork->Accept(verifier);
1790}
1791
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001792BOOST_AUTO_TEST_CASE(SerializeNormalization)
1793{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001794 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Normalization)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001795
1796 const std::string layerName("normalization");
1797 const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
1798
1799 armnn::NormalizationDescriptor desc;
1800 desc.m_DataLayout = armnn::DataLayout::NCHW;
1801 desc.m_NormSize = 3;
1802 desc.m_Alpha = 1;
1803 desc.m_Beta = 1;
1804 desc.m_K = 1;
1805
1806 armnn::INetworkPtr network = armnn::INetwork::Create();
1807 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1808 armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
1809 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1810
1811 inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
1812 normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1813
1814 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1815 normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
1816
1817 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1818 BOOST_CHECK(deserializedNetwork);
1819
1820 NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc);
1821 deserializedNetwork->Accept(verifier);
1822}
1823
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001824DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Pad)
Jim Flynn965c7c62019-06-24 14:32:41 +01001825
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001826BOOST_AUTO_TEST_CASE(SerializePad)
1827{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001828 const std::string layerName("pad");
1829 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1830 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1831
1832 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1833
1834 armnn::INetworkPtr network = armnn::INetwork::Create();
1835 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1836 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
1837 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1838
1839 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
1840 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1841
1842 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1843 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1844
1845 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1846 BOOST_CHECK(deserializedNetwork);
1847
1848 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1849 deserializedNetwork->Accept(verifier);
1850}
1851
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001852BOOST_AUTO_TEST_CASE(EnsurePadBackwardCompatibility)
Jim Flynn965c7c62019-06-24 14:32:41 +01001853{
1854 // The PadDescriptor is being extended with a float PadValue (so a value other than 0
1855 // can be used to pad the tensor.
1856 //
1857 // This test contains a binary representation of a simple input->pad->output network
1858 // prior to this change to test that the descriptor has been updated in a backward
1859 // compatible way with respect to Deserialization of older binary dumps
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001860 const std::vector<uint8_t> padModel =
Jim Flynn965c7c62019-06-24 14:32:41 +01001861 {
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001862 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1863 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1864 0x54, 0x01, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1865 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD0, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
1866 0x04, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x04, 0x00,
1867 0x00, 0x00, 0x72, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1868 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
1869 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00,
1870 0x00, 0x00, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x16, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00,
1871 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
1872 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00,
1873 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1874 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
1875 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1876 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00,
1877 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1878 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
1879 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
1880 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00,
1881 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
1882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00,
1883 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00,
1884 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1885 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00,
1886 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
1887 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
1888 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
1889 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1890 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
1891 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00
1892 };
1893
1894 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(padModel.begin(), padModel.end()));
Jim Flynn965c7c62019-06-24 14:32:41 +01001895 BOOST_CHECK(deserializedNetwork);
1896
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001897 const armnn::TensorInfo inputInfo = armnn::TensorInfo({ 1, 2, 3, 4 }, armnn::DataType::Float32);
1898 const armnn::TensorInfo outputInfo = armnn::TensorInfo({ 1, 3, 5, 7 }, armnn::DataType::Float32);
Jim Flynn965c7c62019-06-24 14:32:41 +01001899
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001900 armnn::PadDescriptor descriptor({{ 0, 0 }, { 1, 0 }, { 1, 1 }, { 1, 2 }});
Jim Flynn965c7c62019-06-24 14:32:41 +01001901
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001902 PadLayerVerifier verifier("pad", { inputInfo }, { outputInfo }, descriptor);
Jim Flynn965c7c62019-06-24 14:32:41 +01001903 deserializedNetwork->Accept(verifier);
1904}
1905
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001906BOOST_AUTO_TEST_CASE(SerializePermute)
1907{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001908 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Permute)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001909
1910 const std::string layerName("permute");
1911 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
1912 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1913
1914 armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
1915
1916 armnn::INetworkPtr network = armnn::INetwork::Create();
1917 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1918 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
1919 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1920
1921 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
1922 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1923
1924 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1925 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1926
1927 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1928 BOOST_CHECK(deserializedNetwork);
1929
1930 PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
1931 deserializedNetwork->Accept(verifier);
1932}
1933
1934BOOST_AUTO_TEST_CASE(SerializePooling2d)
1935{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001936 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Pooling2d)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001937
1938 const std::string layerName("pooling2d");
1939 const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
1940 const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
1941
1942 armnn::Pooling2dDescriptor desc;
1943 desc.m_DataLayout = armnn::DataLayout::NHWC;
1944 desc.m_PadTop = 0;
1945 desc.m_PadBottom = 0;
1946 desc.m_PadLeft = 0;
1947 desc.m_PadRight = 0;
1948 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
1949 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1950 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1951 desc.m_PoolHeight = 2;
1952 desc.m_PoolWidth = 2;
1953 desc.m_StrideX = 2;
1954 desc.m_StrideY = 2;
1955
1956 armnn::INetworkPtr network = armnn::INetwork::Create();
1957 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1958 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
1959 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1960
1961 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
1962 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1963
1964 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1965 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1966
1967 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1968 BOOST_CHECK(deserializedNetwork);
1969
1970 Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1971 deserializedNetwork->Accept(verifier);
1972}
1973
Derek Lamberti87acb272019-03-27 16:51:31 +00001974BOOST_AUTO_TEST_CASE(SerializeQuantize)
1975{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001976 DECLARE_LAYER_VERIFIER_CLASS(Quantize)
Derek Lamberti87acb272019-03-27 16:51:31 +00001977
1978 const std::string layerName("quantize");
1979 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1980
1981 armnn::INetworkPtr network = armnn::INetwork::Create();
1982 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1983 armnn::IConnectableLayer* const quantizeLayer = network->AddQuantizeLayer(layerName.c_str());
1984 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1985
1986 inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
1987 quantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1988
1989 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1990 quantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
1991
1992 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1993 BOOST_CHECK(deserializedNetwork);
1994
1995 QuantizeLayerVerifier verifier(layerName, {info}, {info});
1996 deserializedNetwork->Accept(verifier);
1997}
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001998
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001999BOOST_AUTO_TEST_CASE(SerializeReshape)
2000{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002001 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Reshape)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002002
2003 const std::string layerName("reshape");
2004 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
2005 const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
2006
2007 armnn::ReshapeDescriptor descriptor({3, 3});
2008
2009 armnn::INetworkPtr network = armnn::INetwork::Create();
2010 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2011 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
2012 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2013
2014 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
2015 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2016
2017 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2018 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2019
2020 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2021 BOOST_CHECK(deserializedNetwork);
2022
2023 ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2024 deserializedNetwork->Accept(verifier);
2025}
2026
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002027BOOST_AUTO_TEST_CASE(SerializeResize)
2028{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002029 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Resize)
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002030
2031 const std::string layerName("resize");
2032 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2033 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2034
2035 armnn::ResizeDescriptor desc;
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002036 desc.m_TargetWidth = 4;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002037 desc.m_TargetHeight = 2;
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002038 desc.m_Method = armnn::ResizeMethod::NearestNeighbor;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002039
2040 armnn::INetworkPtr network = armnn::INetwork::Create();
2041 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2042 armnn::IConnectableLayer* const resizeLayer = network->AddResizeLayer(desc, layerName.c_str());
2043 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2044
2045 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2046 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2047
2048 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2049 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2050
2051 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2052 BOOST_CHECK(deserializedNetwork);
2053
2054 ResizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2055 deserializedNetwork->Accept(verifier);
2056}
2057
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002058BOOST_AUTO_TEST_CASE(SerializeRsqrt)
2059{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002060 DECLARE_LAYER_VERIFIER_CLASS(Rsqrt)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002061
2062 const std::string layerName("rsqrt");
2063 const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32);
2064
2065 armnn::INetworkPtr network = armnn::INetwork::Create();
2066 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2067 armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer(layerName.c_str());
2068 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2069
2070 inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0));
2071 rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2072
2073 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2074 rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2075
2076 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2077 BOOST_CHECK(deserializedNetwork);
2078
2079 RsqrtLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
2080 deserializedNetwork->Accept(verifier);
2081}
2082
Aron Virginas-Tar2fda80b2019-09-18 13:36:52 +01002083BOOST_AUTO_TEST_CASE(SerializeSlice)
2084{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002085 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Slice)
Aron Virginas-Tar2fda80b2019-09-18 13:36:52 +01002086
2087 const std::string layerName{"slice"};
2088
2089 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2090 const armnn::TensorInfo outputInfo = armnn::TensorInfo({2, 2, 2, 1}, armnn::DataType::Float32);
2091
2092 armnn::SliceDescriptor descriptor({ 0, 0, 1, 0}, {2, 2, 2, 1});
2093
2094 armnn::INetworkPtr network = armnn::INetwork::Create();
2095
2096 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2097 armnn::IConnectableLayer* const sliceLayer = network->AddSliceLayer(descriptor, layerName.c_str());
2098 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2099
2100 inputLayer->GetOutputSlot(0).Connect(sliceLayer->GetInputSlot(0));
2101 sliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2102
2103 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2104 sliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2105
2106 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2107 BOOST_CHECK(deserializedNetwork);
2108
2109 SliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2110 deserializedNetwork->Accept(verifier);
2111}
2112
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002113BOOST_AUTO_TEST_CASE(SerializeSoftmax)
2114{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002115 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Softmax)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002116
2117 const std::string layerName("softmax");
2118 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
2119
2120 armnn::SoftmaxDescriptor descriptor;
2121 descriptor.m_Beta = 1.0f;
2122
2123 armnn::INetworkPtr network = armnn::INetwork::Create();
2124 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2125 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
2126 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2127
2128 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
2129 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2130
2131 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2132 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
2133
2134 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2135 BOOST_CHECK(deserializedNetwork);
2136
2137 SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
2138 deserializedNetwork->Accept(verifier);
2139}
2140
2141BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
2142{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002143 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(SpaceToBatchNd)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002144
2145 const std::string layerName("spaceToBatchNd");
2146 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
2147 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
2148
2149 armnn::SpaceToBatchNdDescriptor desc;
2150 desc.m_DataLayout = armnn::DataLayout::NCHW;
2151 desc.m_BlockShape = {2, 2};
2152 desc.m_PadList = {{0, 0}, {2, 0}};
2153
2154 armnn::INetworkPtr network = armnn::INetwork::Create();
2155 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2156 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2157 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2158
2159 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
2160 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2161
2162 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2163 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2164
2165 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2166 BOOST_CHECK(deserializedNetwork);
2167
2168 SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2169 deserializedNetwork->Accept(verifier);
2170}
2171
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002172BOOST_AUTO_TEST_CASE(SerializeSpaceToDepth)
2173{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002174 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(SpaceToDepth)
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002175
2176 const std::string layerName("spaceToDepth");
2177
2178 const armnn::TensorInfo inputInfo ({ 1, 16, 8, 3 }, armnn::DataType::Float32);
2179 const armnn::TensorInfo outputInfo({ 1, 8, 4, 12 }, armnn::DataType::Float32);
2180
2181 armnn::SpaceToDepthDescriptor desc;
2182 desc.m_BlockSize = 2;
2183 desc.m_DataLayout = armnn::DataLayout::NHWC;
2184
2185 armnn::INetworkPtr network = armnn::INetwork::Create();
2186 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2187 armnn::IConnectableLayer* const spaceToDepthLayer = network->AddSpaceToDepthLayer(desc, layerName.c_str());
2188 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2189
2190 inputLayer->GetOutputSlot(0).Connect(spaceToDepthLayer->GetInputSlot(0));
2191 spaceToDepthLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2192
2193 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2194 spaceToDepthLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2195
2196 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2197 BOOST_CHECK(deserializedNetwork);
2198
2199 SpaceToDepthLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2200 deserializedNetwork->Accept(verifier);
2201}
2202
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002203BOOST_AUTO_TEST_CASE(SerializeSplitter)
2204{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002205 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Splitter)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002206
2207 const unsigned int numViews = 3;
2208 const unsigned int numDimensions = 4;
2209 const unsigned int inputShape[] = {1, 18, 4, 4};
2210 const unsigned int outputShape[] = {1, 6, 4, 4};
2211
2212 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
2213 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
2214 static_cast<unsigned int>(inputShape[1]),
2215 static_cast<unsigned int>(inputShape[2]),
2216 static_cast<unsigned int>(inputShape[3])};
2217 splitterDimSizes[1] /= numViews;
2218 armnn::ViewsDescriptor desc(numViews, numDimensions);
2219
2220 for (unsigned int g = 0; g < numViews; ++g)
2221 {
2222 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
2223
2224 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
2225 {
2226 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
2227 }
2228 }
2229
2230 const std::string layerName("splitter");
2231 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
2232 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
2233
2234 armnn::INetworkPtr network = armnn::INetwork::Create();
2235 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2236 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
2237 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2238 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2239 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
2240
2241 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
2242 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2243 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2244 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
2245
2246 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2247 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2248 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
2249 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2250
2251 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2252 BOOST_CHECK(deserializedNetwork);
2253
2254 SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
2255 deserializedNetwork->Accept(verifier);
2256}
2257
Matthew Jacksonb5433ee2019-07-11 15:54:20 +01002258BOOST_AUTO_TEST_CASE(SerializeStack)
2259{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002260 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Stack)
Matthew Jacksonb5433ee2019-07-11 15:54:20 +01002261
2262 const std::string layerName("stack");
2263
2264 armnn::TensorInfo inputTensorInfo ({4, 3, 5}, armnn::DataType::Float32);
2265 armnn::TensorInfo outputTensorInfo({4, 3, 2, 5}, armnn::DataType::Float32);
2266
2267 armnn::StackDescriptor descriptor(2, 2, {4, 3, 5});
2268
2269 armnn::INetworkPtr network = armnn::INetwork::Create();
2270 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
2271 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
2272 armnn::IConnectableLayer* const stackLayer = network->AddStackLayer(descriptor, layerName.c_str());
2273 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2274
2275 inputLayer1->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(0));
2276 inputLayer2->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(1));
2277 stackLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2278
2279 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2280 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2281 stackLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2282
2283 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2284 BOOST_CHECK(deserializedNetwork);
2285
2286 StackLayerVerifier verifier(layerName, {inputTensorInfo, inputTensorInfo}, {outputTensorInfo}, descriptor);
2287 deserializedNetwork->Accept(verifier);
2288}
2289
Aron Virginas-Tar85121a22019-10-23 10:41:35 +01002290BOOST_AUTO_TEST_CASE(SerializeStandIn)
2291{
2292 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(StandIn)
2293
2294 const std::string layerName("standIn");
2295
2296 armnn::TensorInfo tensorInfo({ 1u }, armnn::DataType::Float32);
2297 armnn::StandInDescriptor descriptor(2u, 2u);
2298
2299 armnn::INetworkPtr network = armnn::INetwork::Create();
2300 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2301 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2302 armnn::IConnectableLayer* const standInLayer = network->AddStandInLayer(descriptor, layerName.c_str());
2303 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2304 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2305
2306 inputLayer0->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(0));
2307 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2308
2309 inputLayer1->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(1));
2310 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2311
2312 standInLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2313 standInLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2314
2315 standInLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2316 standInLayer->GetOutputSlot(1).SetTensorInfo(tensorInfo);
2317
2318 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2319 BOOST_CHECK(deserializedNetwork);
2320
2321 StandInLayerVerifier verifier(layerName, { tensorInfo, tensorInfo }, { tensorInfo, tensorInfo }, descriptor);
2322 deserializedNetwork->Accept(verifier);
2323}
2324
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002325BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
2326{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002327 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(StridedSlice)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002328
2329 const std::string layerName("stridedSlice");
2330 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2331 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2332
2333 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2334 desc.m_EndMask = (1 << 4) - 1;
2335 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2336 desc.m_DataLayout = armnn::DataLayout::NCHW;
2337
2338 armnn::INetworkPtr network = armnn::INetwork::Create();
2339 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2340 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2341 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2342
2343 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2344 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2345
2346 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2347 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2348
2349 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2350 BOOST_CHECK(deserializedNetwork);
2351
2352 StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2353 deserializedNetwork->Accept(verifier);
2354}
2355
2356BOOST_AUTO_TEST_CASE(SerializeSubtraction)
2357{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002358 DECLARE_LAYER_VERIFIER_CLASS(Subtraction)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002359
2360 const std::string layerName("subtraction");
2361 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2362
2363 armnn::INetworkPtr network = armnn::INetwork::Create();
2364 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2365 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2366 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2367 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2368
2369 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2370 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2371 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2372
2373 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2374 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2375 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2376
2377 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2378 BOOST_CHECK(deserializedNetwork);
2379
2380 SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
2381 deserializedNetwork->Accept(verifier);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +00002382}
2383
Sadik Armaganeff363d2019-04-05 15:25:46 +01002384BOOST_AUTO_TEST_CASE(SerializeSwitch)
2385{
2386 class SwitchLayerVerifier : public LayerVerifierBase
2387 {
2388 public:
2389 SwitchLayerVerifier(const std::string& layerName,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002390 const std::vector<armnn::TensorInfo>& inputInfos,
2391 const std::vector<armnn::TensorInfo>& outputInfos)
Sadik Armaganeff363d2019-04-05 15:25:46 +01002392 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2393
2394 void VisitSwitchLayer(const armnn::IConnectableLayer* layer, const char* name) override
2395 {
2396 VerifyNameAndConnections(layer, name);
2397 }
2398
2399 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2400 const armnn::ConstTensor& input,
2401 const char *name) override {}
2402 };
2403
2404 const std::string layerName("switch");
2405 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2406
2407 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2408 armnn::ConstTensor constTensor(info, constantData);
2409
2410 armnn::INetworkPtr network = armnn::INetwork::Create();
2411 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2412 armnn::IConnectableLayer* const constantLayer = network->AddConstantLayer(constTensor, "constant");
2413 armnn::IConnectableLayer* const switchLayer = network->AddSwitchLayer(layerName.c_str());
2414 armnn::IConnectableLayer* const trueOutputLayer = network->AddOutputLayer(0);
2415 armnn::IConnectableLayer* const falseOutputLayer = network->AddOutputLayer(1);
2416
2417 inputLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(0));
2418 constantLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(1));
2419 switchLayer->GetOutputSlot(0).Connect(trueOutputLayer->GetInputSlot(0));
2420 switchLayer->GetOutputSlot(1).Connect(falseOutputLayer->GetInputSlot(0));
2421
2422 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2423 constantLayer->GetOutputSlot(0).SetTensorInfo(info);
2424 switchLayer->GetOutputSlot(0).SetTensorInfo(info);
2425 switchLayer->GetOutputSlot(1).SetTensorInfo(info);
2426
2427 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2428 BOOST_CHECK(deserializedNetwork);
2429
2430 SwitchLayerVerifier verifier(layerName, {info, info}, {info, info});
2431 deserializedNetwork->Accept(verifier);
2432}
2433
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002434BOOST_AUTO_TEST_CASE(SerializeTransposeConvolution2d)
2435{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002436 using Descriptor = armnn::TransposeConvolution2dDescriptor;
2437 class TransposeConvolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002438 {
2439 public:
2440 TransposeConvolution2dLayerVerifier(const std::string& layerName,
2441 const std::vector<armnn::TensorInfo>& inputInfos,
2442 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002443 const Descriptor& descriptor,
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002444 const armnn::ConstTensor& weights,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002445 const armnn::Optional<armnn::ConstTensor>& biases)
2446 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
2447 , m_Weights(weights)
2448 , m_Biases(biases)
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002449 {}
2450
2451 void VisitTransposeConvolution2dLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002452 const Descriptor& descriptor,
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002453 const armnn::ConstTensor& weights,
2454 const armnn::Optional<armnn::ConstTensor>& biases,
2455 const char* name) override
2456 {
2457 VerifyNameAndConnections(layer, name);
2458 VerifyDescriptor(descriptor);
2459
2460 // check weights
2461 CompareConstTensor(weights, m_Weights);
2462
2463 // check biases
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002464 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002465 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
2466
2467 if (biases.has_value() && m_Biases.has_value())
2468 {
2469 CompareConstTensor(biases.value(), m_Biases.value());
2470 }
2471 }
2472
2473 private:
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002474 armnn::ConstTensor m_Weights;
2475 armnn::Optional<armnn::ConstTensor> m_Biases;
2476 };
2477
2478 const std::string layerName("transposeConvolution2d");
2479 const armnn::TensorInfo inputInfo ({ 1, 7, 7, 1 }, armnn::DataType::Float32);
2480 const armnn::TensorInfo outputInfo({ 1, 9, 9, 1 }, armnn::DataType::Float32);
2481
2482 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
2483 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
2484
2485 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
2486 armnn::ConstTensor weights(weightsInfo, weightsData);
2487
2488 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
2489 armnn::ConstTensor biases(biasesInfo, biasesData);
2490
2491 armnn::TransposeConvolution2dDescriptor descriptor;
2492 descriptor.m_PadLeft = 1;
2493 descriptor.m_PadRight = 1;
2494 descriptor.m_PadTop = 1;
2495 descriptor.m_PadBottom = 1;
2496 descriptor.m_StrideX = 1;
2497 descriptor.m_StrideY = 1;
2498 descriptor.m_BiasEnabled = true;
2499 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
2500
2501 armnn::INetworkPtr network = armnn::INetwork::Create();
2502 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2503 armnn::IConnectableLayer* const convLayer =
2504 network->AddTransposeConvolution2dLayer(descriptor,
2505 weights,
2506 armnn::Optional<armnn::ConstTensor>(biases),
2507 layerName.c_str());
2508 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2509
2510 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
2511 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2512
2513 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2514 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2515
2516 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2517 BOOST_CHECK(deserializedNetwork);
2518
2519 TransposeConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
2520 deserializedNetwork->Accept(verifier);
2521}
2522
Sadik Armagandb059fd2019-03-20 12:28:32 +00002523BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
2524{
2525 class ConstantLayerVerifier : public LayerVerifierBase
2526 {
2527 public:
2528 ConstantLayerVerifier(const std::string& layerName,
2529 const std::vector<armnn::TensorInfo>& inputInfos,
2530 const std::vector<armnn::TensorInfo>& outputInfos,
2531 const armnn::ConstTensor& layerInput)
2532 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2533 , m_LayerInput(layerInput) {}
2534
2535 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2536 const armnn::ConstTensor& input,
2537 const char* name) override
2538 {
2539 VerifyNameAndConnections(layer, name);
Sadik Armagandb059fd2019-03-20 12:28:32 +00002540 CompareConstTensor(input, m_LayerInput);
2541 }
2542
2543 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
2544
2545 private:
2546 armnn::ConstTensor m_LayerInput;
2547 };
2548
2549 const std::string layerName("constant");
2550 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
2551
2552 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2553 armnn::ConstTensor constTensor(info, constantData);
2554
2555 armnn::INetworkPtr network(armnn::INetwork::Create());
2556 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2557 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2558 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2559 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2560
2561 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2562 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2563 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2564
2565 input->GetOutputSlot(0).SetTensorInfo(info);
2566 constant->GetOutputSlot(0).SetTensorInfo(info);
2567 add->GetOutputSlot(0).SetTensorInfo(info);
2568
2569 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2570 BOOST_CHECK(deserializedNetwork);
2571
2572 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
2573 deserializedNetwork->Accept(verifier);
2574}
2575
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002576class VerifyLstmLayer : public LayerVerifierBaseWithDescriptor<armnn::LstmDescriptor>
Jim Flynn11af3752019-03-19 17:22:29 +00002577{
2578public:
2579 VerifyLstmLayer(const std::string& layerName,
2580 const std::vector<armnn::TensorInfo>& inputInfos,
2581 const std::vector<armnn::TensorInfo>& outputInfos,
2582 const armnn::LstmDescriptor& descriptor,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002583 const armnn::LstmInputParams& inputParams)
2584 : LayerVerifierBaseWithDescriptor<armnn::LstmDescriptor>(layerName, inputInfos, outputInfos, descriptor)
2585 , m_InputParams(inputParams) {}
2586
Jim Flynn11af3752019-03-19 17:22:29 +00002587 void VisitLstmLayer(const armnn::IConnectableLayer* layer,
2588 const armnn::LstmDescriptor& descriptor,
2589 const armnn::LstmInputParams& params,
2590 const char* name)
2591 {
2592 VerifyNameAndConnections(layer, name);
2593 VerifyDescriptor(descriptor);
2594 VerifyInputParameters(params);
2595 }
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002596
Jim Flynn11af3752019-03-19 17:22:29 +00002597protected:
Jim Flynn11af3752019-03-19 17:22:29 +00002598 void VerifyInputParameters(const armnn::LstmInputParams& params)
2599 {
2600 VerifyConstTensors(
2601 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
2602 VerifyConstTensors(
2603 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
2604 VerifyConstTensors(
2605 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
2606 VerifyConstTensors(
2607 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
2608 VerifyConstTensors(
2609 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
2610 VerifyConstTensors(
2611 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
2612 VerifyConstTensors(
2613 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
2614 VerifyConstTensors(
2615 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
2616 VerifyConstTensors(
2617 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
2618 VerifyConstTensors(
2619 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
2620 VerifyConstTensors(
2621 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
2622 VerifyConstTensors(
2623 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
2624 VerifyConstTensors(
2625 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
2626 VerifyConstTensors(
2627 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
2628 VerifyConstTensors(
2629 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
2630 VerifyConstTensors(
2631 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
2632 VerifyConstTensors(
2633 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
Jan Eilersf8c62972019-07-17 11:07:49 +01002634 VerifyConstTensors(
2635 "m_InputLayerNormWeights", m_InputParams.m_InputLayerNormWeights, params.m_InputLayerNormWeights);
2636 VerifyConstTensors(
2637 "m_ForgetLayerNormWeights", m_InputParams.m_ForgetLayerNormWeights, params.m_ForgetLayerNormWeights);
2638 VerifyConstTensors(
2639 "m_CellLayerNormWeights", m_InputParams.m_CellLayerNormWeights, params.m_CellLayerNormWeights);
2640 VerifyConstTensors(
2641 "m_OutputLayerNormWeights", m_InputParams.m_OutputLayerNormWeights, params.m_OutputLayerNormWeights);
Jim Flynn11af3752019-03-19 17:22:29 +00002642 }
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002643
Jim Flynn11af3752019-03-19 17:22:29 +00002644private:
Jim Flynn11af3752019-03-19 17:22:29 +00002645 armnn::LstmInputParams m_InputParams;
2646};
2647
2648BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
2649{
2650 armnn::LstmDescriptor descriptor;
2651 descriptor.m_ActivationFunc = 4;
2652 descriptor.m_ClippingThresProj = 0.0f;
2653 descriptor.m_ClippingThresCell = 0.0f;
2654 descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
2655 descriptor.m_ProjectionEnabled = false;
2656 descriptor.m_PeepholeEnabled = true;
2657
2658 const uint32_t batchSize = 1;
2659 const uint32_t inputSize = 2;
2660 const uint32_t numUnits = 4;
2661 const uint32_t outputSize = numUnits;
2662
2663 armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
2664 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2665 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
2666
2667 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2668 armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
2669
2670 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2671 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
2672
2673 armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
2674 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2675 armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
2676
2677 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2678 armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
2679
2680 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2681 armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
2682
2683 armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
2684 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2685 armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
2686
2687 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2688 armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
2689
2690 std::vector<float> forgetGateBiasData(numUnits, 1.0f);
2691 armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
2692
2693 std::vector<float> cellBiasData(numUnits, 0.0f);
2694 armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
2695
2696 std::vector<float> outputGateBiasData(numUnits, 0.0f);
2697 armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
2698
2699 armnn::LstmInputParams params;
2700 params.m_InputToForgetWeights = &inputToForgetWeights;
2701 params.m_InputToCellWeights = &inputToCellWeights;
2702 params.m_InputToOutputWeights = &inputToOutputWeights;
2703 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2704 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2705 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2706 params.m_ForgetGateBias = &forgetGateBias;
2707 params.m_CellBias = &cellBias;
2708 params.m_OutputGateBias = &outputGateBias;
2709 params.m_CellToForgetWeights = &cellToForgetWeights;
2710 params.m_CellToOutputWeights = &cellToOutputWeights;
2711
2712 armnn::INetworkPtr network = armnn::INetwork::Create();
2713 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2714 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2715 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2716 const std::string layerName("lstm");
2717 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2718 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2719 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2720 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2721 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2722
2723 // connect up
2724 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2725 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2726 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2727 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
2728
2729 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2730 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2731
2732 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2733 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2734
2735 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2736 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2737
2738 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2739 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2740
2741 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2742 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2743
2744 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2745 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2746
2747 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2748 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2749
2750 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2751 BOOST_CHECK(deserializedNetwork);
2752
2753 VerifyLstmLayer checker(
2754 layerName,
2755 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2756 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2757 descriptor,
2758 params);
2759 deserializedNetwork->Accept(checker);
2760}
2761
2762BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
2763{
2764 armnn::LstmDescriptor descriptor;
2765 descriptor.m_ActivationFunc = 4;
2766 descriptor.m_ClippingThresProj = 0.0f;
2767 descriptor.m_ClippingThresCell = 0.0f;
2768 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
2769 descriptor.m_ProjectionEnabled = true;
2770 descriptor.m_PeepholeEnabled = true;
2771
2772 const uint32_t batchSize = 2;
2773 const uint32_t inputSize = 5;
2774 const uint32_t numUnits = 20;
2775 const uint32_t outputSize = 16;
2776
2777 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
2778 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2779 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
2780
2781 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2782 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
2783
2784 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2785 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
2786
2787 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2788 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
2789
2790 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
2791 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2792 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
2793
2794 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2795 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
2796
2797 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2798 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
2799
2800 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2801 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
2802
2803 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
2804 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2805 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
2806
2807 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2808 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
2809
2810 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2811 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
2812
2813 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2814 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
2815
2816 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2817 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
2818
2819 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2820 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
2821
2822 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2823 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
2824
2825 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
2826 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
2827 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
2828
2829 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
2830 std::vector<float> projectionBiasData(outputSize, 0.f);
2831 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
2832
2833 armnn::LstmInputParams params;
2834 params.m_InputToForgetWeights = &inputToForgetWeights;
2835 params.m_InputToCellWeights = &inputToCellWeights;
2836 params.m_InputToOutputWeights = &inputToOutputWeights;
2837 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2838 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2839 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2840 params.m_ForgetGateBias = &forgetGateBias;
2841 params.m_CellBias = &cellBias;
2842 params.m_OutputGateBias = &outputGateBias;
2843
2844 // additional params because: descriptor.m_CifgEnabled = false
2845 params.m_InputToInputWeights = &inputToInputWeights;
2846 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
2847 params.m_CellToInputWeights = &cellToInputWeights;
2848 params.m_InputGateBias = &inputGateBias;
2849
2850 // additional params because: descriptor.m_ProjectionEnabled = true
2851 params.m_ProjectionWeights = &projectionWeights;
2852 params.m_ProjectionBias = &projectionBias;
2853
2854 // additional params because: descriptor.m_PeepholeEnabled = true
2855 params.m_CellToForgetWeights = &cellToForgetWeights;
2856 params.m_CellToOutputWeights = &cellToOutputWeights;
2857
2858 armnn::INetworkPtr network = armnn::INetwork::Create();
2859 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2860 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2861 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2862 const std::string layerName("lstm");
2863 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2864 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2865 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2866 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2867 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2868
2869 // connect up
2870 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2871 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2872 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2873 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
2874
2875 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2876 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2877
2878 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2879 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2880
2881 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2882 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2883
2884 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2885 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2886
2887 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2888 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2889
2890 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2891 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2892
2893 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2894 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2895
2896 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2897 BOOST_CHECK(deserializedNetwork);
2898
2899 VerifyLstmLayer checker(
2900 layerName,
2901 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2902 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2903 descriptor,
2904 params);
2905 deserializedNetwork->Accept(checker);
2906}
2907
Jan Eilersf8c62972019-07-17 11:07:49 +01002908BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeWithProjectionWithLayerNorm)
2909{
2910 armnn::LstmDescriptor descriptor;
2911 descriptor.m_ActivationFunc = 4;
2912 descriptor.m_ClippingThresProj = 0.0f;
2913 descriptor.m_ClippingThresCell = 0.0f;
2914 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
2915 descriptor.m_ProjectionEnabled = true;
2916 descriptor.m_PeepholeEnabled = true;
2917 descriptor.m_LayerNormEnabled = true;
2918
2919 const uint32_t batchSize = 2;
2920 const uint32_t inputSize = 5;
2921 const uint32_t numUnits = 20;
2922 const uint32_t outputSize = 16;
2923
2924 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
2925 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2926 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
2927
2928 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2929 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
2930
2931 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2932 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
2933
2934 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2935 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
2936
2937 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
2938 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2939 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
2940
2941 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2942 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
2943
2944 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2945 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
2946
2947 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2948 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
2949
2950 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
2951 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2952 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
2953
2954 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2955 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
2956
2957 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2958 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
2959
2960 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2961 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
2962
2963 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2964 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
2965
2966 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2967 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
2968
2969 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2970 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
2971
2972 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
2973 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
2974 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
2975
2976 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
2977 std::vector<float> projectionBiasData(outputSize, 0.f);
2978 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
2979
2980 std::vector<float> inputLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2981 armnn::ConstTensor inputLayerNormWeights(tensorInfo20, forgetGateBiasData);
2982
2983 std::vector<float> forgetLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2984 armnn::ConstTensor forgetLayerNormWeights(tensorInfo20, forgetGateBiasData);
2985
2986 std::vector<float> cellLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2987 armnn::ConstTensor cellLayerNormWeights(tensorInfo20, forgetGateBiasData);
2988
2989 std::vector<float> outLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2990 armnn::ConstTensor outLayerNormWeights(tensorInfo20, forgetGateBiasData);
2991
2992 armnn::LstmInputParams params;
2993 params.m_InputToForgetWeights = &inputToForgetWeights;
2994 params.m_InputToCellWeights = &inputToCellWeights;
2995 params.m_InputToOutputWeights = &inputToOutputWeights;
2996 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2997 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2998 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2999 params.m_ForgetGateBias = &forgetGateBias;
3000 params.m_CellBias = &cellBias;
3001 params.m_OutputGateBias = &outputGateBias;
3002
3003 // additional params because: descriptor.m_CifgEnabled = false
3004 params.m_InputToInputWeights = &inputToInputWeights;
3005 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3006 params.m_CellToInputWeights = &cellToInputWeights;
3007 params.m_InputGateBias = &inputGateBias;
3008
3009 // additional params because: descriptor.m_ProjectionEnabled = true
3010 params.m_ProjectionWeights = &projectionWeights;
3011 params.m_ProjectionBias = &projectionBias;
3012
3013 // additional params because: descriptor.m_PeepholeEnabled = true
3014 params.m_CellToForgetWeights = &cellToForgetWeights;
3015 params.m_CellToOutputWeights = &cellToOutputWeights;
3016
3017 // additional params because: despriptor.m_LayerNormEnabled = true
3018 params.m_InputLayerNormWeights = &inputLayerNormWeights;
3019 params.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
3020 params.m_CellLayerNormWeights = &cellLayerNormWeights;
3021 params.m_OutputLayerNormWeights = &outLayerNormWeights;
3022
3023 armnn::INetworkPtr network = armnn::INetwork::Create();
3024 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3025 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3026 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3027 const std::string layerName("lstm");
3028 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3029 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3030 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3031 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3032 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3033
3034 // connect up
3035 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3036 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3037 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3038 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3039
3040 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3041 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3042
3043 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3044 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3045
3046 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3047 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3048
3049 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3050 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3051
3052 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3053 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3054
3055 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3056 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3057
3058 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3059 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3060
3061 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3062 BOOST_CHECK(deserializedNetwork);
3063
3064 VerifyLstmLayer checker(
3065 layerName,
3066 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3067 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3068 descriptor,
3069 params);
3070 deserializedNetwork->Accept(checker);
3071}
3072
3073BOOST_AUTO_TEST_CASE(EnsureLstmLayersBackwardCompatibility)
3074{
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003075 // The hex data below is a flat buffer containing a lstm layer with no Cifg, with peephole and projection
3076 // enabled. That data was obtained before additional layer normalization parameters where added to the
3077 // lstm serializer. That way it can be tested if a lstm model with the old parameter configuration can
3078 // still be loaded
3079 const std::vector<uint8_t> lstmNoCifgWithPeepholeAndProjectionModel =
Jan Eilersf8c62972019-07-17 11:07:49 +01003080 {
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003081 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
3082 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
3083 0xDC, 0x29, 0x00, 0x00, 0x38, 0x29, 0x00, 0x00, 0xB4, 0x28, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x3C, 0x01,
3084 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
3085 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
3086 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x70, 0xD6, 0xFF, 0xFF,
3087 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x06, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x88, 0xD7,
3088 0xFF, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF6, 0xD6, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,
3089 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
3090 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3091 0xE8, 0xD7, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xC8, 0xD6, 0xFF, 0xFF, 0x00, 0x00,
3092 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x5E, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xE0, 0xD7, 0xFF, 0xFF,
3093 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4E, 0xD7, 0xFF, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
3094 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3095 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xD8,
3096 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
3097 0x04, 0x00, 0x00, 0x00, 0xB6, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x38, 0xD8, 0xFF, 0xFF, 0x08, 0x00,
3098 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA6, 0xD7, 0xFF, 0xFF, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3099 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3100 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xD8, 0xFF, 0xFF,
3101 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00,
3102 0x00, 0x00, 0x0E, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x16, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
3103 0xFA, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00,
3104 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3105 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xD8, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
3106 0x00, 0x00, 0x6C, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
3107 0x12, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xE0, 0x25, 0x00, 0x00, 0xD0, 0x25,
3108 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x48, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00,
3109 0x10, 0x00, 0x14, 0x00, 0x18, 0x00, 0x1C, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2C, 0x00, 0x30, 0x00,
3110 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x40, 0x00, 0x44, 0x00, 0x26, 0x00, 0x00, 0x00, 0xC4, 0x23, 0x00, 0x00,
3111 0xF8, 0x21, 0x00, 0x00, 0x2C, 0x20, 0x00, 0x00, 0xF0, 0x1A, 0x00, 0x00, 0xB4, 0x15, 0x00, 0x00, 0x78, 0x10,
3112 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x68, 0x0F, 0x00, 0x00, 0xE0, 0x0E, 0x00, 0x00, 0x14, 0x0D, 0x00, 0x00,
3113 0xD8, 0x07, 0x00, 0x00, 0x50, 0x07, 0x00, 0x00, 0xC8, 0x06, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x14, 0x01,
3114 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xEE, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3115 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00,
3116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3121 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x72, 0xD8,
3122 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x82, 0xD9, 0xFF, 0xFF,
3123 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xD8,
3128 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3129 0x14, 0x00, 0x00, 0x00, 0xF6, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x54, 0x00, 0x00, 0x00, 0x04, 0x00,
3130 0x00, 0x00, 0x06, 0xDA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xD9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3135 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6A, 0xD9, 0xFF, 0xFF, 0x00, 0x00,
3136 0x00, 0x03, 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7A, 0xDA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
3137 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xDE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3209 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xA2, 0xDE,
3210 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB2, 0xDF, 0xFF, 0xFF,
3211 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xDF,
3216 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3217 0x14, 0x00, 0x00, 0x00, 0x26, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00,
3218 0x00, 0x00, 0x36, 0xE0, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3223 0x00, 0x00, 0x00, 0x00, 0x92, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3224 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xAA, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3225 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xBA, 0xE0, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01,
3226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3297 0x00, 0x00, 0x00, 0x00, 0xC6, 0xE4, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3298 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xE2, 0xE4, 0xFF, 0xFF,
3299 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xE5, 0xFF, 0xFF, 0x04, 0x00,
3300 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3305 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xE6, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3323 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00,
3324 0x00, 0x00, 0xAA, 0xE6, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3325 0xBA, 0xE7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3328 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3330 0x00, 0x00, 0x16, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3331 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x2E, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00,
3332 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3E, 0xE8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
3333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xB2, 0xE7, 0xFF, 0xFF,
3339 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC2, 0xE8, 0xFF, 0xFF, 0x04, 0x00,
3340 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xE8, 0xFF, 0xFF,
3345 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00,
3346 0x00, 0x00, 0x36, 0xE8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3347 0x46, 0xE9, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3381 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3387 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3399 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3407 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3418 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xED, 0xFF, 0xFF,
3419 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00,
3420 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6E, 0xED, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x14, 0x05, 0x00, 0x00,
3421 0x04, 0x00, 0x00, 0x00, 0x7E, 0xEE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00,
3422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3493 0x8A, 0xF2, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3494 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xA6, 0xF2, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3495 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB6, 0xF3, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01,
3496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3500 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3501 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3567 0x00, 0x00, 0x00, 0x00, 0xC2, 0xF7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3568 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xDE, 0xF7, 0xFF, 0xFF,
3569 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xEE, 0xF8, 0xFF, 0xFF, 0x04, 0x00,
3570 0x00, 0x00, 0x64, 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, 0x8A, 0xF9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3593 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00,
3594 0x00, 0x00, 0xA6, 0xF9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3595 0xB6, 0xFA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x64, 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, 0x52, 0xFB,
3618 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
3619 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x6E, 0xFB, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01,
3620 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7E, 0xFC, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x64, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3643 0x00, 0x00, 0x00, 0x00, 0x1A, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3644 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0C, 0x00,
3645 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
3646 0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x2E, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3647 0x22, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6C, 0x73,
3648 0x74, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00,
3649 0xB4, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x30, 0x00,
3650 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3651 0xA6, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3652 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3C, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
3653 0x04, 0x00, 0x00, 0x00, 0xCE, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3654 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x64, 0xFF, 0xFF, 0xFF,
3655 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3657 0xB4, 0xFE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x1A, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
3659 0xF0, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
3660 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
3661 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00,
3663 0x7E, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00,
3664 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x76, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
3665 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
3666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3667 0x68, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xCE, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3669 0x08, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00,
3670 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
3671 0x08, 0x00, 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00,
3672 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00,
3673 0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
3674 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3675 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
3676 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6E, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3677 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00,
3678 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00,
3679 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00,
3680 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
3681 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
3682 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3683 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
3684 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00,
3685 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3686 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00
3687 };
3688
3689 armnn::INetworkPtr deserializedNetwork =
3690 DeserializeNetwork(std::string(lstmNoCifgWithPeepholeAndProjectionModel.begin(),
3691 lstmNoCifgWithPeepholeAndProjectionModel.end()));
3692
Jan Eilersf8c62972019-07-17 11:07:49 +01003693 BOOST_CHECK(deserializedNetwork);
3694
3695 // generating the same model parameters which where used to serialize the model (Layer norm is not specified)
3696 armnn::LstmDescriptor descriptor;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003697 descriptor.m_ActivationFunc = 4;
Jan Eilersf8c62972019-07-17 11:07:49 +01003698 descriptor.m_ClippingThresProj = 0.0f;
3699 descriptor.m_ClippingThresCell = 0.0f;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003700 descriptor.m_CifgEnabled = false;
Jan Eilersf8c62972019-07-17 11:07:49 +01003701 descriptor.m_ProjectionEnabled = true;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003702 descriptor.m_PeepholeEnabled = true;
Jan Eilersf8c62972019-07-17 11:07:49 +01003703
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003704 const uint32_t batchSize = 2u;
3705 const uint32_t inputSize = 5u;
3706 const uint32_t numUnits = 20u;
3707 const uint32_t outputSize = 16u;
Jan Eilersf8c62972019-07-17 11:07:49 +01003708
3709 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3710 std::vector<float> inputToInputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3711 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3712
3713 std::vector<float> inputToForgetWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3714 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3715
3716 std::vector<float> inputToCellWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3717 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3718
3719 std::vector<float> inputToOutputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3720 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3721
3722 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3723 std::vector<float> inputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3724 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3725
3726 std::vector<float> forgetGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3727 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3728
3729 std::vector<float> cellBiasData(tensorInfo20.GetNumElements(), 0.0f);
3730 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3731
3732 std::vector<float> outputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3733 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3734
3735 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3736 std::vector<float> recurrentToInputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3737 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3738
3739 std::vector<float> recurrentToForgetWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3740 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3741
3742 std::vector<float> recurrentToCellWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3743 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3744
3745 std::vector<float> recurrentToOutputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3746 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3747
3748 std::vector<float> cellToInputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
3749 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3750
3751 std::vector<float> cellToForgetWeightsData(tensorInfo20.GetNumElements(), 0.0f);
3752 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3753
3754 std::vector<float> cellToOutputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
3755 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3756
3757 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3758 std::vector<float> projectionWeightsData(tensorInfo16x20.GetNumElements(), 0.0f);
3759 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3760
3761 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3762 std::vector<float> projectionBiasData(outputSize, 0.0f);
3763 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3764
3765 armnn::LstmInputParams params;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003766 params.m_InputToForgetWeights = &inputToForgetWeights;
3767 params.m_InputToCellWeights = &inputToCellWeights;
3768 params.m_InputToOutputWeights = &inputToOutputWeights;
Jan Eilersf8c62972019-07-17 11:07:49 +01003769 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003770 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
Jan Eilersf8c62972019-07-17 11:07:49 +01003771 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003772 params.m_ForgetGateBias = &forgetGateBias;
3773 params.m_CellBias = &cellBias;
3774 params.m_OutputGateBias = &outputGateBias;
Jan Eilersf8c62972019-07-17 11:07:49 +01003775
3776 // additional params because: descriptor.m_CifgEnabled = false
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003777 params.m_InputToInputWeights = &inputToInputWeights;
3778 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3779 params.m_CellToInputWeights = &cellToInputWeights;
3780 params.m_InputGateBias = &inputGateBias;
Jan Eilersf8c62972019-07-17 11:07:49 +01003781
3782 // additional params because: descriptor.m_ProjectionEnabled = true
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003783 params.m_ProjectionWeights = &projectionWeights;
3784 params.m_ProjectionBias = &projectionBias;
Jan Eilersf8c62972019-07-17 11:07:49 +01003785
3786 // additional params because: descriptor.m_PeepholeEnabled = true
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003787 params.m_CellToForgetWeights = &cellToForgetWeights;
3788 params.m_CellToOutputWeights = &cellToOutputWeights;
Jan Eilersf8c62972019-07-17 11:07:49 +01003789
3790 const std::string layerName("lstm");
3791 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3792 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3793 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3794 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3795
Jan Eilersf8c62972019-07-17 11:07:49 +01003796 VerifyLstmLayer checker(
3797 layerName,
3798 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3799 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3800 descriptor,
3801 params);
3802 deserializedNetwork->Accept(checker);
3803}
Jan Eilers5b01a892019-07-23 09:47:43 +01003804class VerifyQuantizedLstmLayer : public LayerVerifierBase
3805{
3806
3807public:
3808 VerifyQuantizedLstmLayer(const std::string& layerName,
3809 const std::vector<armnn::TensorInfo>& inputInfos,
3810 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01003811 const armnn::QuantizedLstmInputParams& inputParams)
3812 : LayerVerifierBase(layerName, inputInfos, outputInfos), m_InputParams(inputParams) {}
Jan Eilers5b01a892019-07-23 09:47:43 +01003813
3814 void VisitQuantizedLstmLayer(const armnn::IConnectableLayer* layer,
3815 const armnn::QuantizedLstmInputParams& params,
3816 const char* name)
3817 {
3818 VerifyNameAndConnections(layer, name);
3819 VerifyInputParameters(params);
3820 }
3821
3822protected:
3823 void VerifyInputParameters(const armnn::QuantizedLstmInputParams& params)
3824 {
3825 VerifyConstTensors("m_InputToInputWeights",
3826 m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
3827 VerifyConstTensors("m_InputToForgetWeights",
3828 m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
3829 VerifyConstTensors("m_InputToCellWeights",
3830 m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
3831 VerifyConstTensors("m_InputToOutputWeights",
3832 m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
3833 VerifyConstTensors("m_RecurrentToInputWeights",
3834 m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
3835 VerifyConstTensors("m_RecurrentToForgetWeights",
3836 m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
3837 VerifyConstTensors("m_RecurrentToCellWeights",
3838 m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
3839 VerifyConstTensors("m_RecurrentToOutputWeights",
3840 m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
3841 VerifyConstTensors("m_InputGateBias",
3842 m_InputParams.m_InputGateBias, params.m_InputGateBias);
3843 VerifyConstTensors("m_ForgetGateBias",
3844 m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
3845 VerifyConstTensors("m_CellBias",
3846 m_InputParams.m_CellBias, params.m_CellBias);
3847 VerifyConstTensors("m_OutputGateBias",
3848 m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
3849 }
3850
3851private:
3852 armnn::QuantizedLstmInputParams m_InputParams;
3853};
3854
3855BOOST_AUTO_TEST_CASE(SerializeDeserializeQuantizedLstm)
3856{
3857 const uint32_t batchSize = 1;
3858 const uint32_t inputSize = 2;
3859 const uint32_t numUnits = 4;
3860 const uint32_t outputSize = numUnits;
3861
3862 std::vector<uint8_t> inputToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3863 std::vector<unsigned int> inputToInputWeightsDimensions = {1, 1, 3, 3};
3864 armnn::ConstTensor inputToInputWeights(armnn::TensorInfo(
3865 4, inputToInputWeightsDimensions.data(),
3866 armnn::DataType::QuantisedAsymm8), inputToInputWeightsData);
3867
3868 std::vector<uint8_t> inputToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3869 std::vector<unsigned int> inputToForgetWeightsDimensions = {1, 1, 3, 3};
3870 armnn::ConstTensor inputToForgetWeights(armnn::TensorInfo(
3871 4, inputToForgetWeightsDimensions.data(),
3872 armnn::DataType::QuantisedAsymm8), inputToForgetWeightsData);
3873
3874 std::vector<uint8_t> inputToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3875 std::vector<unsigned int> inputToCellWeightsDimensions = {1, 1, 3, 3};
3876 armnn::ConstTensor inputToCellWeights(armnn::TensorInfo(
3877 4, inputToCellWeightsDimensions.data(),
3878 armnn::DataType::QuantisedAsymm8), inputToCellWeightsData);
3879
3880 std::vector<uint8_t> inputToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3881 std::vector<unsigned int> inputToOutputWeightsDimensions = {1, 1, 3, 3};
3882 armnn::ConstTensor inputToOutputWeights(armnn::TensorInfo(
3883 4, inputToOutputWeightsDimensions.data(),
3884 armnn::DataType::QuantisedAsymm8), inputToOutputWeightsData);
3885
3886 std::vector<uint8_t> recurrentToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3887 std::vector<unsigned int> recurrentToInputWeightsDimensions = {1, 1, 3, 3};
3888 armnn::ConstTensor recurrentToInputWeights(armnn::TensorInfo(
3889 4, recurrentToInputWeightsDimensions.data(),
3890 armnn::DataType::QuantisedAsymm8), recurrentToInputWeightsData);
3891
3892 std::vector<uint8_t> recurrentToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3893 std::vector<unsigned int> recurrentToForgetWeightsDimensions = {1, 1, 3, 3};
3894 armnn::ConstTensor recurrentToForgetWeights(armnn::TensorInfo(
3895 4, recurrentToForgetWeightsDimensions.data(),
3896 armnn::DataType::QuantisedAsymm8), recurrentToForgetWeightsData);
3897
3898 std::vector<uint8_t> recurrentToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3899 std::vector<unsigned int> recurrentToCellWeightsDimensions = {1, 1, 3, 3};
3900 armnn::ConstTensor recurrentToCellWeights(armnn::TensorInfo(
3901 4, recurrentToCellWeightsDimensions.data(),
3902 armnn::DataType::QuantisedAsymm8), recurrentToCellWeightsData);
3903
3904 std::vector<uint8_t> recurrentToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3905 std::vector<unsigned int> recurrentToOutputWeightsDimensions = {1, 1, 3, 3};
3906 armnn::ConstTensor recurrentToOutputWeights(armnn::TensorInfo(
3907 4, recurrentToOutputWeightsDimensions.data(),
3908 armnn::DataType::QuantisedAsymm8), recurrentToOutputWeightsData);
3909
3910
3911 std::vector<int32_t> inputGateBiasData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3912 std::vector<unsigned int> inputGateBiasDimensions = {1, 1, 3, 3};
3913 armnn::ConstTensor inputGateBias(armnn::TensorInfo(
3914 4, inputGateBiasDimensions.data(),
3915 armnn::DataType::Signed32), inputGateBiasData);
3916
3917 std::vector<int32_t> forgetGateBiasData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3918 std::vector<unsigned int> forgetGateBiasDimensions = {1, 1, 3, 3};
3919 armnn::ConstTensor forgetGateBias(armnn::TensorInfo(
3920 4, forgetGateBiasDimensions.data(),
3921 armnn::DataType::Signed32), forgetGateBiasData);
3922
3923 std::vector<int32_t> cellBiasData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3924 std::vector<unsigned int> cellBiasDimensions = {1, 1, 3, 3};
3925 armnn::ConstTensor cellBias(armnn::TensorInfo(
3926 4, cellBiasDimensions.data(),
3927 armnn::DataType::Signed32), cellBiasData);
3928
3929 std::vector<int32_t> outputGateBiasData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
3930 std::vector<unsigned int> outputGateBiasDimensions = {1, 1, 3, 3};
3931 armnn::ConstTensor outputGateBias(armnn::TensorInfo(
3932 4, outputGateBiasDimensions.data(),
3933 armnn::DataType::Signed32), outputGateBiasData);
3934
3935 armnn::QuantizedLstmInputParams params;
3936 params.m_InputToInputWeights = &inputToInputWeights;
3937 params.m_InputToForgetWeights = &inputToForgetWeights;
3938 params.m_InputToCellWeights = &inputToCellWeights;
3939 params.m_InputToOutputWeights = &inputToOutputWeights;
3940 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3941 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3942 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3943 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3944 params.m_InputGateBias = &inputGateBias;
3945 params.m_ForgetGateBias = &forgetGateBias;
3946 params.m_CellBias = &cellBias;
3947 params.m_OutputGateBias = &outputGateBias;
3948
3949 armnn::INetworkPtr network = armnn::INetwork::Create();
3950 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3951 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3952 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3953 const std::string layerName("QuantizedLstm");
3954 armnn::IConnectableLayer* const quantizedLstmLayer = network->AddQuantizedLstmLayer(params, layerName.c_str());
3955 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(0);
3956 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(1);
3957
3958 // connect up
3959 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::QuantisedAsymm8);
3960 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Signed32);
3961 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::QuantisedAsymm8);
3962
3963 inputLayer->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(0));
3964 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3965
3966 cellStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(1));
3967 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3968
3969 outputStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(2));
3970 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3971
3972 quantizedLstmLayer->GetOutputSlot(0).Connect(cellStateOut->GetInputSlot(0));
3973 quantizedLstmLayer->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3974
3975 quantizedLstmLayer->GetOutputSlot(1).Connect(outputLayer->GetInputSlot(0));
3976 quantizedLstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3977
3978 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3979 BOOST_CHECK(deserializedNetwork);
3980
3981 VerifyQuantizedLstmLayer checker(
3982 layerName,
3983 {inputTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3984 {cellStateTensorInfo, outputStateTensorInfo},
3985 params);
3986
3987 deserializedNetwork->Accept(checker);
3988}
3989
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00003990BOOST_AUTO_TEST_SUITE_END()