blob: 42606691247e225460785c867ec73d82c6d5a7b7 [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
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100181 Descriptor m_Descriptor;
182};
183
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000184template<typename T>
185void CompareConstTensorData(const void* data1, const void* data2, unsigned int numElements)
186{
187 T typedData1 = static_cast<T>(data1);
188 T typedData2 = static_cast<T>(data2);
189 BOOST_CHECK(typedData1);
190 BOOST_CHECK(typedData2);
191
192 for (unsigned int i = 0; i < numElements; i++)
193 {
194 BOOST_TEST(typedData1[i] == typedData2[i]);
195 }
196}
197
198void CompareConstTensor(const armnn::ConstTensor& tensor1, const armnn::ConstTensor& tensor2)
199{
200 BOOST_TEST(tensor1.GetShape() == tensor2.GetShape());
201 BOOST_TEST(GetDataTypeName(tensor1.GetDataType()) == GetDataTypeName(tensor2.GetDataType()));
202
203 switch (tensor1.GetDataType())
204 {
205 case armnn::DataType::Float32:
206 CompareConstTensorData<const float*>(
207 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
208 break;
209 case armnn::DataType::QuantisedAsymm8:
210 case armnn::DataType::Boolean:
211 CompareConstTensorData<const uint8_t*>(
212 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
213 break;
214 case armnn::DataType::Signed32:
215 CompareConstTensorData<const int32_t*>(
216 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
217 break;
218 default:
219 // Note that Float16 is not yet implemented
220 BOOST_TEST_MESSAGE("Unexpected datatype");
221 BOOST_TEST(false);
222 }
223}
224
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000225armnn::INetworkPtr DeserializeNetwork(const std::string& serializerString)
226{
227 std::vector<std::uint8_t> const serializerVector{serializerString.begin(), serializerString.end()};
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000228 return IDeserializer::Create()->CreateNetworkFromBinary(serializerVector);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000229}
230
231std::string SerializeNetwork(const armnn::INetwork& network)
232{
233 armnnSerializer::Serializer serializer;
234 serializer.Serialize(network);
235
236 std::stringstream stream;
237 serializer.SaveSerializedToStream(stream);
238
239 std::string serializerString{stream.str()};
240 return serializerString;
241}
242
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000243template<typename DataType>
244static std::vector<DataType> GenerateRandomData(size_t size)
245{
246 constexpr bool isIntegerType = std::is_integral<DataType>::value;
247 using Distribution =
248 typename std::conditional<isIntegerType,
249 std::uniform_int_distribution<DataType>,
250 std::uniform_real_distribution<DataType>>::type;
251
252 static constexpr DataType lowerLimit = std::numeric_limits<DataType>::min();
253 static constexpr DataType upperLimit = std::numeric_limits<DataType>::max();
254
255 static Distribution distribution(lowerLimit, upperLimit);
256 static std::default_random_engine generator;
257
258 std::vector<DataType> randomData(size);
259 std::generate(randomData.begin(), randomData.end(), []() { return distribution(generator); });
260
261 return randomData;
262}
263
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000264} // anonymous namespace
265
266BOOST_AUTO_TEST_SUITE(SerializerTests)
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000267
FinnWilliamsArm4ffcc8f2019-09-05 14:34:20 +0100268BOOST_AUTO_TEST_CASE(SerializeAbs)
269{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100270 DECLARE_LAYER_VERIFIER_CLASS(Abs)
FinnWilliamsArm4ffcc8f2019-09-05 14:34:20 +0100271
272 const std::string layerName("abs");
273 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
274
275 armnn::INetworkPtr network = armnn::INetwork::Create();
276 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
277
278 armnn::IConnectableLayer* const absLayer = network->AddAbsLayer(layerName.c_str());
279 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
280
281 inputLayer->GetOutputSlot(0).Connect(absLayer->GetInputSlot(0));
282 absLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
283
284 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
285 absLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
286
287 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
288 BOOST_CHECK(deserializedNetwork);
289
290 AbsLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
291 deserializedNetwork->Accept(verifier);
292}
293
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000294BOOST_AUTO_TEST_CASE(SerializeAddition)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000295{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100296 DECLARE_LAYER_VERIFIER_CLASS(Addition)
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000297
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000298 const std::string layerName("addition");
299 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
300
Mike Kelly8c1701a2019-02-11 17:01:27 +0000301 armnn::INetworkPtr network = armnn::INetwork::Create();
302 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
303 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000304 armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer(layerName.c_str());
305 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000306
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000307 inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
308 inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000309 additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Mike Kelly8c1701a2019-02-11 17:01:27 +0000310
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000311 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
312 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
313 additionLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
Jim Flynn3091b062019-02-15 14:45:04 +0000314
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000315 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000316 BOOST_CHECK(deserializedNetwork);
317
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000318 AdditionLayerVerifier verifier(layerName, {tensorInfo, tensorInfo}, {tensorInfo});
319 deserializedNetwork->Accept(verifier);
320}
Jim Flynnac25a1b2019-02-28 10:40:49 +0000321
Narumol Prangnawarat0cfcf232019-09-09 17:16:24 +0100322BOOST_AUTO_TEST_CASE(SerializeArgMinMax)
323{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100324 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(ArgMinMax)
Narumol Prangnawarat0cfcf232019-09-09 17:16:24 +0100325
326 const std::string layerName("argminmax");
327 const armnn::TensorInfo inputInfo({1, 2, 3}, armnn::DataType::Float32);
328 const armnn::TensorInfo outputInfo({1, 3}, armnn::DataType::Signed32);
329
330 armnn::ArgMinMaxDescriptor descriptor;
331 descriptor.m_Function = armnn::ArgMinMaxFunction::Max;
332 descriptor.m_Axis = 1;
333
334 armnn::INetworkPtr network = armnn::INetwork::Create();
335 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
336 armnn::IConnectableLayer* const argMinMaxLayer = network->AddArgMinMaxLayer(descriptor, layerName.c_str());
337 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
338
339 inputLayer->GetOutputSlot(0).Connect(argMinMaxLayer->GetInputSlot(0));
340 argMinMaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
341
342 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
343 argMinMaxLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
344
345 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
346 BOOST_CHECK(deserializedNetwork);
347
348 ArgMinMaxLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
349 deserializedNetwork->Accept(verifier);
350}
351
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000352BOOST_AUTO_TEST_CASE(SerializeBatchNormalization)
353{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100354 using Descriptor = armnn::BatchNormalizationDescriptor;
355 class BatchNormalizationLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000356 {
357 public:
358 BatchNormalizationLayerVerifier(const std::string& layerName,
359 const std::vector<armnn::TensorInfo>& inputInfos,
360 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100361 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000362 const armnn::ConstTensor& mean,
363 const armnn::ConstTensor& variance,
364 const armnn::ConstTensor& beta,
365 const armnn::ConstTensor& gamma)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100366 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
367 , m_Mean(mean)
368 , m_Variance(variance)
369 , m_Beta(beta)
370 , m_Gamma(gamma) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000371
372 void VisitBatchNormalizationLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100373 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000374 const armnn::ConstTensor& mean,
375 const armnn::ConstTensor& variance,
376 const armnn::ConstTensor& beta,
377 const armnn::ConstTensor& gamma,
378 const char* name) override
379 {
380 VerifyNameAndConnections(layer, name);
381 VerifyDescriptor(descriptor);
382
383 CompareConstTensor(mean, m_Mean);
384 CompareConstTensor(variance, m_Variance);
385 CompareConstTensor(beta, m_Beta);
386 CompareConstTensor(gamma, m_Gamma);
387 }
388
389 private:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000390 armnn::ConstTensor m_Mean;
391 armnn::ConstTensor m_Variance;
392 armnn::ConstTensor m_Beta;
393 armnn::ConstTensor m_Gamma;
394 };
395
396 const std::string layerName("batchNormalization");
397 const armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32);
398 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
399
400 const armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32);
401 const armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32);
402 const armnn::TensorInfo betaInfo({1}, armnn::DataType::Float32);
403 const armnn::TensorInfo gammaInfo({1}, armnn::DataType::Float32);
404
405 armnn::BatchNormalizationDescriptor descriptor;
406 descriptor.m_Eps = 0.0010000000475f;
407 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
408
409 std::vector<float> meanData({5.0});
410 std::vector<float> varianceData({2.0});
411 std::vector<float> betaData({1.0});
412 std::vector<float> gammaData({0.0});
413
414 armnn::ConstTensor mean(meanInfo, meanData);
415 armnn::ConstTensor variance(varianceInfo, varianceData);
416 armnn::ConstTensor beta(betaInfo, betaData);
417 armnn::ConstTensor gamma(gammaInfo, gammaData);
418
419 armnn::INetworkPtr network = armnn::INetwork::Create();
420 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
421 armnn::IConnectableLayer* const batchNormalizationLayer =
422 network->AddBatchNormalizationLayer(descriptor, mean, variance, beta, gamma, layerName.c_str());
423 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
424
425 inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0));
426 batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
427
428 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
429 batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
430
431 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
432 BOOST_CHECK(deserializedNetwork);
433
434 BatchNormalizationLayerVerifier verifier(
435 layerName, {inputInfo}, {outputInfo}, descriptor, mean, variance, beta, gamma);
436 deserializedNetwork->Accept(verifier);
437}
438
439BOOST_AUTO_TEST_CASE(SerializeBatchToSpaceNd)
440{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100441 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(BatchToSpaceNd)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000442
443 const std::string layerName("spaceToBatchNd");
444 const armnn::TensorInfo inputInfo({4, 1, 2, 2}, armnn::DataType::Float32);
445 const armnn::TensorInfo outputInfo({1, 1, 4, 4}, armnn::DataType::Float32);
446
447 armnn::BatchToSpaceNdDescriptor desc;
448 desc.m_DataLayout = armnn::DataLayout::NCHW;
449 desc.m_BlockShape = {2, 2};
450 desc.m_Crops = {{0, 0}, {0, 0}};
451
452 armnn::INetworkPtr network = armnn::INetwork::Create();
453 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
454 armnn::IConnectableLayer* const batchToSpaceNdLayer = network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
455 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
456
457 inputLayer->GetOutputSlot(0).Connect(batchToSpaceNdLayer->GetInputSlot(0));
458 batchToSpaceNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
459
460 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
461 batchToSpaceNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
462
463 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
464 BOOST_CHECK(deserializedNetwork);
465
466 BatchToSpaceNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
467 deserializedNetwork->Accept(verifier);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000468}
469
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100470BOOST_AUTO_TEST_CASE(SerializeComparison)
471{
472 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Comparison)
473
474 const std::string layerName("comparison");
475
476 const armnn::TensorShape shape{2, 1, 2, 4};
477
478 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
479 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
480
481 armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::NotEqual);
482
483 armnn::INetworkPtr network = armnn::INetwork::Create();
484 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
485 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
486 armnn::IConnectableLayer* const comparisonLayer = network->AddComparisonLayer(descriptor, layerName.c_str());
487 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
488
489 inputLayer0->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(0));
490 inputLayer1->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(1));
491 comparisonLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
492
493 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
494 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
495 comparisonLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
496
497 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
498 BOOST_CHECK(deserializedNetwork);
499
500 ComparisonLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo }, descriptor);
501 deserializedNetwork->Accept(verifier);
502}
503
Conor Kennedy76277882019-02-26 08:29:54 +0000504BOOST_AUTO_TEST_CASE(SerializeConstant)
505{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000506 class ConstantLayerVerifier : public LayerVerifierBase
Conor Kennedy76277882019-02-26 08:29:54 +0000507 {
508 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000509 ConstantLayerVerifier(const std::string& layerName,
510 const std::vector<armnn::TensorInfo>& inputInfos,
511 const std::vector<armnn::TensorInfo>& outputInfos,
512 const armnn::ConstTensor& layerInput)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100513 : LayerVerifierBase(layerName, inputInfos, outputInfos)
514 , m_LayerInput(layerInput) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000515
516 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
517 const armnn::ConstTensor& input,
518 const char* name) override
Conor Kennedy76277882019-02-26 08:29:54 +0000519 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000520 VerifyNameAndConnections(layer, name);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000521 CompareConstTensor(input, m_LayerInput);
Conor Kennedy76277882019-02-26 08:29:54 +0000522 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000523
524 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
525
526 private:
527 armnn::ConstTensor m_LayerInput;
Conor Kennedy76277882019-02-26 08:29:54 +0000528 };
529
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000530 const std::string layerName("constant");
531 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
Conor Kennedy76277882019-02-26 08:29:54 +0000532
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000533 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
534 armnn::ConstTensor constTensor(info, constantData);
Conor Kennedy76277882019-02-26 08:29:54 +0000535
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000536 armnn::INetworkPtr network(armnn::INetwork::Create());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000537 armnn::IConnectableLayer* input = network->AddInputLayer(0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000538 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000539 armnn::IConnectableLayer* add = network->AddAdditionLayer();
540 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
Conor Kennedy76277882019-02-26 08:29:54 +0000541
542 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
543 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
544 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
545
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000546 input->GetOutputSlot(0).SetTensorInfo(info);
547 constant->GetOutputSlot(0).SetTensorInfo(info);
548 add->GetOutputSlot(0).SetTensorInfo(info);
Conor Kennedy76277882019-02-26 08:29:54 +0000549
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000550 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Conor Kennedy76277882019-02-26 08:29:54 +0000551 BOOST_CHECK(deserializedNetwork);
552
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000553 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
554 deserializedNetwork->Accept(verifier);
Conor Kennedy76277882019-02-26 08:29:54 +0000555}
556
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000557BOOST_AUTO_TEST_CASE(SerializeConvolution2d)
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000558{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100559 using Descriptor = armnn::Convolution2dDescriptor;
560 class Convolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000561 {
562 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000563 Convolution2dLayerVerifier(const std::string& layerName,
564 const std::vector<armnn::TensorInfo>& inputInfos,
565 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100566 const Descriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100567 const armnn::ConstTensor& weights,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100568 const armnn::Optional<armnn::ConstTensor>& biases)
569 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
570 , m_Weights(weights)
571 , m_Biases(biases) {}
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000572
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000573 void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100574 const Descriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100575 const armnn::ConstTensor& weights,
576 const armnn::Optional<armnn::ConstTensor>& biases,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000577 const char* name) override
578 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000579 VerifyNameAndConnections(layer, name);
580 VerifyDescriptor(descriptor);
581
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100582 // check weights
583 CompareConstTensor(weights, m_Weights);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000584
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100585 // check biases
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100586 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100587 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
588
589 if (biases.has_value() && m_Biases.has_value())
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000590 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100591 CompareConstTensor(biases.value(), m_Biases.value());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000592 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000593 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000594
595 private:
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100596 armnn::ConstTensor m_Weights;
597 armnn::Optional<armnn::ConstTensor> m_Biases;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000598 };
599
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000600 const std::string layerName("convolution2d");
601 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
602 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000603
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000604 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
605 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000606
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000607 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
608 armnn::ConstTensor weights(weightsInfo, weightsData);
609
610 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
611 armnn::ConstTensor biases(biasesInfo, biasesData);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000612
613 armnn::Convolution2dDescriptor descriptor;
614 descriptor.m_PadLeft = 1;
615 descriptor.m_PadRight = 1;
616 descriptor.m_PadTop = 1;
617 descriptor.m_PadBottom = 1;
618 descriptor.m_StrideX = 2;
619 descriptor.m_StrideY = 2;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100620 descriptor.m_DilationX = 2;
621 descriptor.m_DilationY = 2;
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000622 descriptor.m_BiasEnabled = true;
623 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
624
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000625 armnn::INetworkPtr network = armnn::INetwork::Create();
626 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000627 armnn::IConnectableLayer* const convLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100628 network->AddConvolution2dLayer(descriptor,
629 weights,
630 armnn::Optional<armnn::ConstTensor>(biases),
631 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000632 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000633
634 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000635 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000636
637 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000638 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
639
640 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
641 BOOST_CHECK(deserializedNetwork);
642
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000643 Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
644 deserializedNetwork->Accept(verifier);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000645}
646
Aron Virginas-Tarda9d2d32019-09-20 10:42:02 +0100647BOOST_AUTO_TEST_CASE(SerializeDepthToSpace)
648{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100649 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(DepthToSpace)
Aron Virginas-Tarda9d2d32019-09-20 10:42:02 +0100650
651 const std::string layerName("depthToSpace");
652
653 const armnn::TensorInfo inputInfo ({ 1, 8, 4, 12 }, armnn::DataType::Float32);
654 const armnn::TensorInfo outputInfo({ 1, 16, 8, 3 }, armnn::DataType::Float32);
655
656 armnn::DepthToSpaceDescriptor desc;
657 desc.m_BlockSize = 2;
658 desc.m_DataLayout = armnn::DataLayout::NHWC;
659
660 armnn::INetworkPtr network = armnn::INetwork::Create();
661 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
662 armnn::IConnectableLayer* const depthToSpaceLayer = network->AddDepthToSpaceLayer(desc, layerName.c_str());
663 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
664
665 inputLayer->GetOutputSlot(0).Connect(depthToSpaceLayer->GetInputSlot(0));
666 depthToSpaceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
667
668 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
669 depthToSpaceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
670
671 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
672 BOOST_CHECK(deserializedNetwork);
673
674 DepthToSpaceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
675 deserializedNetwork->Accept(verifier);
676}
677
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000678BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d)
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000679{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100680 using Descriptor = armnn::DepthwiseConvolution2dDescriptor;
681 class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000682 {
683 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000684 DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
685 const std::vector<armnn::TensorInfo>& inputInfos,
686 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100687 const Descriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100688 const armnn::ConstTensor& weights,
689 const armnn::Optional<armnn::ConstTensor>& biases) :
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100690 LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor),
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100691 m_Weights(weights),
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100692 m_Biases(biases) {}
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000693
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000694 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100695 const Descriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100696 const armnn::ConstTensor& weights,
697 const armnn::Optional<armnn::ConstTensor>& biases,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000698 const char* name) override
699 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000700 VerifyNameAndConnections(layer, name);
701 VerifyDescriptor(descriptor);
702
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100703 // check weights
704 CompareConstTensor(weights, m_Weights);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000705
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100706 // check biases
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100707 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100708 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
709
710 if (biases.has_value() && m_Biases.has_value())
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000711 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100712 CompareConstTensor(biases.value(), m_Biases.value());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000713 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000714 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000715
716 private:
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100717 armnn::ConstTensor m_Weights;
718 armnn::Optional<armnn::ConstTensor> m_Biases;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000719 };
720
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000721 const std::string layerName("depwiseConvolution2d");
722 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
723 const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000724
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000725 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
726 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000727
728 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
729 armnn::ConstTensor weights(weightsInfo, weightsData);
730
731 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
732 armnn::ConstTensor biases(biasesInfo, biasesData);
733
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000734 armnn::DepthwiseConvolution2dDescriptor descriptor;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100735 descriptor.m_PadLeft = 1;
736 descriptor.m_PadRight = 1;
737 descriptor.m_PadTop = 1;
738 descriptor.m_PadBottom = 1;
739 descriptor.m_StrideX = 2;
740 descriptor.m_StrideY = 2;
741 descriptor.m_DilationX = 2;
742 descriptor.m_DilationY = 2;
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000743 descriptor.m_BiasEnabled = true;
744 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
745
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000746 armnn::INetworkPtr network = armnn::INetwork::Create();
747 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
748 armnn::IConnectableLayer* const depthwiseConvLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100749 network->AddDepthwiseConvolution2dLayer(descriptor,
750 weights,
751 armnn::Optional<armnn::ConstTensor>(biases),
752 layerName.c_str());
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000753 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
754
755 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000756 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000757
758 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000759 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
760
761 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
762 BOOST_CHECK(deserializedNetwork);
763
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000764 DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
765 deserializedNetwork->Accept(verifier);
Jim Flynn18ce3382019-03-08 11:08:30 +0000766}
767
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000768BOOST_AUTO_TEST_CASE(SerializeDequantize)
769{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100770 DECLARE_LAYER_VERIFIER_CLASS(Dequantize)
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000771
772 const std::string layerName("dequantize");
773 const armnn::TensorInfo inputInfo({ 1, 5, 2, 3 }, armnn::DataType::QuantisedAsymm8, 0.5f, 1);
774 const armnn::TensorInfo outputInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
775
776 armnn::INetworkPtr network = armnn::INetwork::Create();
777 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
778 armnn::IConnectableLayer* const dequantizeLayer = network->AddDequantizeLayer(layerName.c_str());
779 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
780
781 inputLayer->GetOutputSlot(0).Connect(dequantizeLayer->GetInputSlot(0));
782 dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
783
784 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
785 dequantizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
786
787 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
788 BOOST_CHECK(deserializedNetwork);
789
790 DequantizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
791 deserializedNetwork->Accept(verifier);
792}
793
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000794BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess)
795{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100796 using Descriptor = armnn::DetectionPostProcessDescriptor;
797 class DetectionPostProcessLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000798 {
799 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000800 DetectionPostProcessLayerVerifier(const std::string& layerName,
801 const std::vector<armnn::TensorInfo>& inputInfos,
802 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100803 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000804 const armnn::ConstTensor& anchors)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100805 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
806 , m_Anchors(anchors) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000807
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000808 void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100809 const Descriptor& descriptor,
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000810 const armnn::ConstTensor& anchors,
811 const char* name) override
812 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000813 VerifyNameAndConnections(layer, name);
814 VerifyDescriptor(descriptor);
815
816 CompareConstTensor(anchors, m_Anchors);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000817 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000818
819 private:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000820 armnn::ConstTensor m_Anchors;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000821 };
822
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000823 const std::string layerName("detectionPostProcess");
824
825 const std::vector<armnn::TensorInfo> inputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000826 armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32),
827 armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000828 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000829
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000830 const std::vector<armnn::TensorInfo> outputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000831 armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32),
832 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
833 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
834 armnn::TensorInfo({ 1 }, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000835 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000836
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000837 armnn::DetectionPostProcessDescriptor descriptor;
838 descriptor.m_UseRegularNms = true;
839 descriptor.m_MaxDetections = 3;
840 descriptor.m_MaxClassesPerDetection = 1;
841 descriptor.m_DetectionsPerClass =1;
842 descriptor.m_NmsScoreThreshold = 0.0;
843 descriptor.m_NmsIouThreshold = 0.5;
844 descriptor.m_NumClasses = 2;
845 descriptor.m_ScaleY = 10.0;
846 descriptor.m_ScaleX = 10.0;
847 descriptor.m_ScaleH = 5.0;
848 descriptor.m_ScaleW = 5.0;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000849
850 const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
851 const std::vector<float> anchorsData({
852 0.5f, 0.5f, 1.0f, 1.0f,
853 0.5f, 0.5f, 1.0f, 1.0f,
854 0.5f, 0.5f, 1.0f, 1.0f,
855 0.5f, 10.5f, 1.0f, 1.0f,
856 0.5f, 10.5f, 1.0f, 1.0f,
857 0.5f, 100.5f, 1.0f, 1.0f
858 });
859 armnn::ConstTensor anchors(anchorsInfo, anchorsData);
860
861 armnn::INetworkPtr network = armnn::INetwork::Create();
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000862 armnn::IConnectableLayer* const detectionLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000863 network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000864
865 for (unsigned int i = 0; i < 2; i++)
866 {
867 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
868 inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
869 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
870 }
871
872 for (unsigned int i = 0; i < 4; i++)
873 {
874 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
875 detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
876 detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
877 }
878
879 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
880 BOOST_CHECK(deserializedNetwork);
881
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000882 DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors);
883 deserializedNetwork->Accept(verifier);
884}
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000885
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000886BOOST_AUTO_TEST_CASE(SerializeDivision)
887{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100888 DECLARE_LAYER_VERIFIER_CLASS(Division)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000889
890 const std::string layerName("division");
891 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
892
893 armnn::INetworkPtr network = armnn::INetwork::Create();
894 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
895 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
896 armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
897 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
898
899 inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
900 inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
901 divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
902
903 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
904 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
905 divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
906
907 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
908 BOOST_CHECK(deserializedNetwork);
909
910 DivisionLayerVerifier verifier(layerName, {info, info}, {info});
911 deserializedNetwork->Accept(verifier);
912}
913
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +0100914class EqualLayerVerifier : public LayerVerifierBase
915{
916public:
917 EqualLayerVerifier(const std::string& layerName,
918 const std::vector<armnn::TensorInfo>& inputInfos,
919 const std::vector<armnn::TensorInfo>& outputInfos)
920 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
921
922 void VisitComparisonLayer(const armnn::IConnectableLayer* layer,
923 const armnn::ComparisonDescriptor& descriptor,
924 const char* name) override
925 {
926 VerifyNameAndConnections(layer, name);
927 BOOST_CHECK(descriptor.m_Operation == armnn::ComparisonOperation::Equal);
928 }
929
930 void VisitEqualLayer(const armnn::IConnectableLayer* layer, const char* name) override
931 {
932 throw armnn::Exception("EqualLayer should have translated to ComparisonLayer");
933 }
934};
935
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100936// NOTE: Until the deprecated AddEqualLayer disappears this test checks that calling
937// AddEqualLayer places a ComparisonLayer into the serialized format and that
938// when this deserialises we have a ComparisonLayer
939BOOST_AUTO_TEST_CASE(SerializeEqual)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000940{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100941 const std::string layerName("equal");
942
943 const armnn::TensorShape shape{2, 1, 2, 4};
944
945 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
946 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
947
948 armnn::INetworkPtr network = armnn::INetwork::Create();
949 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
950 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
951 ARMNN_NO_DEPRECATE_WARN_BEGIN
952 armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str());
953 ARMNN_NO_DEPRECATE_WARN_END
954 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
955
956 inputLayer0->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
957 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
958 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
959
960 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
961 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
962 equalLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
963
964 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
965 BOOST_CHECK(deserializedNetwork);
966
967 EqualLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo });
968 deserializedNetwork->Accept(verifier);
969}
970
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +0100971BOOST_AUTO_TEST_CASE(EnsureEqualBackwardCompatibility)
972{
973 // The hex data below is a flat buffer containing a simple network with two inputs,
974 // an EqualLayer (now deprecated) and an output
975 //
976 // This test verifies that we can still deserialize this old-style model by replacing
977 // the EqualLayer with an equivalent ComparisonLayer
978 const std::vector<uint8_t> equalModel =
979 {
980 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
981 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
982 0xCC, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
983 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
984 0x60, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
985 0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xEA, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
986 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
987 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
988 0x64, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
989 0x00, 0x13, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
990 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
991 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x65, 0x71, 0x75, 0x61, 0x6C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
992 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
993 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00,
994 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
995 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
996 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
997 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
998 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
999 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1000 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1001 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1002 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1004 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1005 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1006 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
1007 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1008 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1009 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1010 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1011 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1012 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1013 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1014 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1015 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1016 0x04, 0x00, 0x00, 0x00
1017 };
1018
1019 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(equalModel.begin(), equalModel.end()));
1020 BOOST_CHECK(deserializedNetwork);
1021
1022 const armnn::TensorShape shape{ 2, 1, 2, 4 };
1023
1024 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1025 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1026
1027 EqualLayerVerifier verifier("equal", { inputInfo, inputInfo }, { outputInfo });
1028 deserializedNetwork->Accept(verifier);
1029}
1030
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001031BOOST_AUTO_TEST_CASE(SerializeFloor)
1032{
1033 DECLARE_LAYER_VERIFIER_CLASS(Floor)
1034
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001035 const std::string layerName("floor");
1036 const armnn::TensorInfo info({4,4}, armnn::DataType::Float32);
1037
1038 armnn::INetworkPtr network = armnn::INetwork::Create();
1039 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1040 armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
1041 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1042
1043 inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
1044 floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1045
1046 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1047 floorLayer->GetOutputSlot(0).SetTensorInfo(info);
1048
1049 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1050 BOOST_CHECK(deserializedNetwork);
1051
1052 FloorLayerVerifier verifier(layerName, {info}, {info});
1053 deserializedNetwork->Accept(verifier);
1054}
1055
1056BOOST_AUTO_TEST_CASE(SerializeFullyConnected)
1057{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001058 using Descriptor = armnn::FullyConnectedDescriptor;
1059 class FullyConnectedLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001060 {
1061 public:
1062 FullyConnectedLayerVerifier(const std::string& layerName,
1063 const std::vector<armnn::TensorInfo>& inputInfos,
1064 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001065 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001066 const armnn::ConstTensor& weight,
1067 const armnn::Optional<armnn::ConstTensor>& bias)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001068 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
1069 , m_Weight(weight)
1070 , m_Bias(bias) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001071
1072 void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001073 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001074 const armnn::ConstTensor& weight,
1075 const armnn::Optional<armnn::ConstTensor>& bias,
1076 const char* name) override
1077 {
1078 VerifyNameAndConnections(layer, name);
1079 VerifyDescriptor(descriptor);
1080
1081 CompareConstTensor(weight, m_Weight);
1082
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001083 BOOST_TEST(bias.has_value() == descriptor.m_BiasEnabled);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001084 BOOST_TEST(bias.has_value() == m_Bias.has_value());
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001085
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001086 if (bias.has_value() && m_Bias.has_value())
1087 {
1088 CompareConstTensor(bias.value(), m_Bias.value());
1089 }
1090 }
1091
1092 private:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001093 armnn::ConstTensor m_Weight;
1094 armnn::Optional<armnn::ConstTensor> m_Bias;
1095 };
1096
1097 const std::string layerName("fullyConnected");
1098 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
1099 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
1100
1101 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
1102 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
1103 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
1104 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
1105 armnn::ConstTensor weights(weightsInfo, weightsData);
1106 armnn::ConstTensor biases(biasesInfo, biasesData);
1107
1108 armnn::FullyConnectedDescriptor descriptor;
1109 descriptor.m_BiasEnabled = true;
1110 descriptor.m_TransposeWeightMatrix = false;
1111
1112 armnn::INetworkPtr network = armnn::INetwork::Create();
1113 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1114 armnn::IConnectableLayer* const fullyConnectedLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +01001115 network->AddFullyConnectedLayer(descriptor,
1116 weights,
1117 armnn::Optional<armnn::ConstTensor>(biases),
1118 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001119 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1120
1121 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
1122 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1123
1124 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1125 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1126
1127 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1128 BOOST_CHECK(deserializedNetwork);
1129
1130 FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
1131 deserializedNetwork->Accept(verifier);
1132}
1133
1134BOOST_AUTO_TEST_CASE(SerializeGather)
1135{
1136 class GatherLayerVerifier : public LayerVerifierBase
1137 {
1138 public:
1139 GatherLayerVerifier(const std::string& layerName,
1140 const std::vector<armnn::TensorInfo>& inputInfos,
1141 const std::vector<armnn::TensorInfo>& outputInfos)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001142 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001143
1144 void VisitGatherLayer(const armnn::IConnectableLayer* layer, const char *name) override
1145 {
1146 VerifyNameAndConnections(layer, name);
1147 }
1148
1149 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
1150 const armnn::ConstTensor& input,
1151 const char *name) override {}
1152 };
1153
1154 const std::string layerName("gather");
1155 armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QuantisedAsymm8);
1156 armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QuantisedAsymm8);
1157 const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
1158
1159 paramsInfo.SetQuantizationScale(1.0f);
1160 paramsInfo.SetQuantizationOffset(0);
1161 outputInfo.SetQuantizationScale(1.0f);
1162 outputInfo.SetQuantizationOffset(0);
1163
1164 const std::vector<int32_t>& indicesData = {7, 6, 5};
1165
1166 armnn::INetworkPtr network = armnn::INetwork::Create();
1167 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
1168 armnn::IConnectableLayer *const constantLayer =
1169 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
1170 armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(layerName.c_str());
1171 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
1172
1173 inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
1174 constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
1175 gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1176
1177 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
1178 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
1179 gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1180
1181 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1182 BOOST_CHECK(deserializedNetwork);
1183
1184 GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo});
1185 deserializedNetwork->Accept(verifier);
1186}
1187
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +01001188class GreaterLayerVerifier : public LayerVerifierBase
1189{
1190public:
1191 GreaterLayerVerifier(const std::string& layerName,
1192 const std::vector<armnn::TensorInfo>& inputInfos,
1193 const std::vector<armnn::TensorInfo>& outputInfos)
1194 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1195
1196 void VisitComparisonLayer(const armnn::IConnectableLayer* layer,
1197 const armnn::ComparisonDescriptor& descriptor,
1198 const char* name) override
1199 {
1200 VerifyNameAndConnections(layer, name);
1201 BOOST_CHECK(descriptor.m_Operation == armnn::ComparisonOperation::Greater);
1202 }
1203
1204 void VisitGreaterLayer(const armnn::IConnectableLayer* layer, const char* name) override
1205 {
1206 throw armnn::Exception("GreaterLayer should have translated to ComparisonLayer");
1207 }
1208};
1209
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001210// NOTE: Until the deprecated AddGreaterLayer disappears this test checks that calling
1211// AddGreaterLayer places a ComparisonLayer into the serialized format and that
1212// when this deserialises we have a ComparisonLayer
1213BOOST_AUTO_TEST_CASE(SerializeGreater)
Aron Virginas-Tar781ced92019-10-03 11:15:39 +01001214{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001215 const std::string layerName("greater");
1216
1217 const armnn::TensorShape shape{2, 1, 2, 4};
1218
1219 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1220 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1221
1222 armnn::INetworkPtr network = armnn::INetwork::Create();
1223 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1224 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1225 ARMNN_NO_DEPRECATE_WARN_BEGIN
1226 armnn::IConnectableLayer* const equalLayer = network->AddGreaterLayer(layerName.c_str());
1227 ARMNN_NO_DEPRECATE_WARN_END
1228 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1229
1230 inputLayer0->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
1231 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
1232 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1233
1234 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
1235 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
1236 equalLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1237
1238 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1239 BOOST_CHECK(deserializedNetwork);
1240
1241 GreaterLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo });
1242 deserializedNetwork->Accept(verifier);
1243}
1244
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +01001245BOOST_AUTO_TEST_CASE(EnsureGreaterBackwardCompatibility)
1246{
1247 // The hex data below is a flat buffer containing a simple network with two inputs,
1248 // an GreaterLayer (now deprecated) and an output
1249 //
1250 // This test verifies that we can still deserialize this old-style model by replacing
1251 // the GreaterLayer with an equivalent ComparisonLayer
1252 const std::vector<uint8_t> greaterModel =
1253 {
1254 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1255 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1256 0xCC, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1258 0x60, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1259 0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xEA, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1260 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1262 0x64, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1263 0x00, 0x19, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1264 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1265 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00,
1266 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1267 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1269 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1270 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1271 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1272 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1273 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1274 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1275 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1276 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1278 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1279 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1280 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1281 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1282 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1283 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1284 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1285 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1286 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1287 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1288 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1290 0x02, 0x00, 0x00, 0x00
1291 };
1292
1293 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(greaterModel.begin(), greaterModel.end()));
1294 BOOST_CHECK(deserializedNetwork);
1295
1296 const armnn::TensorShape shape{ 1, 2, 2, 2 };
1297
1298 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1299 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1300
1301 GreaterLayerVerifier verifier("greater", { inputInfo, inputInfo }, { outputInfo });
1302 deserializedNetwork->Accept(verifier);
1303}
1304
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001305BOOST_AUTO_TEST_CASE(SerializeInstanceNormalization)
1306{
1307 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(InstanceNormalization)
1308
Aron Virginas-Tar781ced92019-10-03 11:15:39 +01001309 const std::string layerName("instanceNormalization");
1310 const armnn::TensorInfo info({ 1, 2, 1, 5 }, armnn::DataType::Float32);
1311
1312 armnn::InstanceNormalizationDescriptor descriptor;
1313 descriptor.m_Gamma = 1.1f;
1314 descriptor.m_Beta = 0.1f;
1315 descriptor.m_Eps = 0.0001f;
1316 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
1317
1318 armnn::INetworkPtr network = armnn::INetwork::Create();
1319 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1320 armnn::IConnectableLayer* const instanceNormLayer =
1321 network->AddInstanceNormalizationLayer(descriptor, layerName.c_str());
1322 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1323
1324 inputLayer->GetOutputSlot(0).Connect(instanceNormLayer->GetInputSlot(0));
1325 instanceNormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1326
1327 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1328 instanceNormLayer->GetOutputSlot(0).SetTensorInfo(info);
1329
1330 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1331 BOOST_CHECK(deserializedNetwork);
1332
1333 InstanceNormalizationLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1334 deserializedNetwork->Accept(verifier);
1335}
1336
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001337DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(L2Normalization)
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001338
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001339BOOST_AUTO_TEST_CASE(SerializeL2Normalization)
1340{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001341 const std::string l2NormLayerName("l2Normalization");
1342 const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1343
1344 armnn::L2NormalizationDescriptor desc;
1345 desc.m_DataLayout = armnn::DataLayout::NCHW;
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001346 desc.m_Eps = 0.0001f;
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001347
1348 armnn::INetworkPtr network = armnn::INetwork::Create();
1349 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1350 armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1351 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1352
1353 inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1354 l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1355
1356 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1357 l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1358
1359 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1360 BOOST_CHECK(deserializedNetwork);
1361
1362 L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc);
1363 deserializedNetwork->Accept(verifier);
1364}
1365
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001366BOOST_AUTO_TEST_CASE(EnsureL2NormalizationBackwardCompatibility)
1367{
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001368 // The hex data below is a flat buffer containing a simple network with one input
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001369 // a L2Normalization layer and an output layer with dimensions as per the tensor infos below.
1370 //
1371 // This test verifies that we can still read back these old style
1372 // models without the normalization epsilon value.
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001373 const std::vector<uint8_t> l2NormalizationModel =
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001374 {
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001375 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1376 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1377 0x3C, 0x01, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1378 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xE8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
1379 0x04, 0x00, 0x00, 0x00, 0xD6, 0xFE, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
1380 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
1381 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1383 0x4C, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
1384 0x00, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1385 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1386 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1387 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x20, 0x00,
1388 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x6C, 0x32, 0x4E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x69, 0x7A, 0x61, 0x74,
1389 0x69, 0x6F, 0x6E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00,
1390 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1391 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
1392 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1393 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1394 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1395 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1396 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1397 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1398 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1399 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1400 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1401 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1402 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1403 0x05, 0x00, 0x00, 0x00, 0x00
1404 };
1405
1406 armnn::INetworkPtr deserializedNetwork =
1407 DeserializeNetwork(std::string(l2NormalizationModel.begin(), l2NormalizationModel.end()));
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001408 BOOST_CHECK(deserializedNetwork);
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001409
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001410 const std::string layerName("l2Normalization");
1411 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 2, 1, 5}, armnn::DataType::Float32);
1412
1413 armnn::L2NormalizationDescriptor desc;
1414 desc.m_DataLayout = armnn::DataLayout::NCHW;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001415 // Since this variable does not exist in the l2NormalizationModel dump, the default value will be loaded
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001416 desc.m_Eps = 1e-12f;
1417
1418 L2NormalizationLayerVerifier verifier(layerName, {inputInfo}, {inputInfo}, desc);
1419 deserializedNetwork->Accept(verifier);
1420}
1421
Sadik Armagan26257852019-10-14 13:00:47 +01001422BOOST_AUTO_TEST_CASE(SerializeLogSoftmax)
1423{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001424 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(LogSoftmax)
Sadik Armagan26257852019-10-14 13:00:47 +01001425
1426 const std::string layerName("log_softmax");
1427 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
1428
1429 armnn::LogSoftmaxDescriptor descriptor;
1430 descriptor.m_Beta = 1.0f;
1431 descriptor.m_Axis = -1;
1432
1433 armnn::INetworkPtr network = armnn::INetwork::Create();
1434 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1435 armnn::IConnectableLayer* const logSoftmaxLayer = network->AddLogSoftmaxLayer(descriptor, layerName.c_str());
1436 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1437
1438 inputLayer->GetOutputSlot(0).Connect(logSoftmaxLayer->GetInputSlot(0));
1439 logSoftmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1440
1441 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1442 logSoftmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
1443
1444 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1445 BOOST_CHECK(deserializedNetwork);
1446
1447 LogSoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1448 deserializedNetwork->Accept(verifier);
1449}
1450
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001451BOOST_AUTO_TEST_CASE(SerializeMaximum)
1452{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001453 DECLARE_LAYER_VERIFIER_CLASS(Maximum)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001454
1455 const std::string layerName("maximum");
1456 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1457
1458 armnn::INetworkPtr network = armnn::INetwork::Create();
1459 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1460 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1461 armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1462 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1463
1464 inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1465 inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1466 maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1467
1468 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1469 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1470 maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1471
1472 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1473 BOOST_CHECK(deserializedNetwork);
1474
1475 MaximumLayerVerifier verifier(layerName, {info, info}, {info});
1476 deserializedNetwork->Accept(verifier);
1477}
1478
1479BOOST_AUTO_TEST_CASE(SerializeMean)
1480{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001481 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Mean)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001482
1483 const std::string layerName("mean");
1484 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1485 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1486
1487 armnn::MeanDescriptor descriptor;
1488 descriptor.m_Axis = { 2 };
1489 descriptor.m_KeepDims = true;
1490
1491 armnn::INetworkPtr network = armnn::INetwork::Create();
1492 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1493 armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1494 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1495
1496 inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1497 meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1498
1499 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1500 meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1501
1502 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1503 BOOST_CHECK(deserializedNetwork);
1504
1505 MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1506 deserializedNetwork->Accept(verifier);
1507}
1508
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001509BOOST_AUTO_TEST_CASE(SerializeMerge)
1510{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001511 DECLARE_LAYER_VERIFIER_CLASS(Merge)
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001512
1513 const std::string layerName("merge");
1514 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1515
1516 armnn::INetworkPtr network = armnn::INetwork::Create();
1517 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1518 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1519 armnn::IConnectableLayer* const mergeLayer = network->AddMergeLayer(layerName.c_str());
1520 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1521
1522 inputLayer0->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(0));
1523 inputLayer1->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(1));
1524 mergeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1525
1526 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1527 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1528 mergeLayer->GetOutputSlot(0).SetTensorInfo(info);
1529
1530 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1531 BOOST_CHECK(deserializedNetwork);
1532
1533 MergeLayerVerifier verifier(layerName, {info, info}, {info});
1534 deserializedNetwork->Accept(verifier);
1535}
1536
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001537class MergerLayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::OriginsDescriptor>
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001538{
Jim Flynn5fa83932019-05-09 15:35:43 +01001539public:
1540 MergerLayerVerifier(const std::string& layerName,
1541 const std::vector<armnn::TensorInfo>& inputInfos,
1542 const std::vector<armnn::TensorInfo>& outputInfos,
1543 const armnn::OriginsDescriptor& descriptor)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001544 : LayerVerifierBaseWithDescriptor<armnn::OriginsDescriptor>(layerName, inputInfos, outputInfos, descriptor) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001545
Jim Flynn5fa83932019-05-09 15:35:43 +01001546 void VisitMergerLayer(const armnn::IConnectableLayer* layer,
1547 const armnn::OriginsDescriptor& descriptor,
1548 const char* name) override
1549 {
Jim Flynne242f2d2019-05-22 14:24:13 +01001550 throw armnn::Exception("MergerLayer should have translated to ConcatLayer");
1551 }
1552
1553 void VisitConcatLayer(const armnn::IConnectableLayer* layer,
1554 const armnn::OriginsDescriptor& descriptor,
1555 const char* name) override
1556 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001557 VerifyNameAndConnections(layer, name);
1558 VerifyDescriptor(descriptor);
1559 }
Jim Flynn5fa83932019-05-09 15:35:43 +01001560};
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001561
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001562// NOTE: Until the deprecated AddMergerLayer disappears this test checks that calling
Jim Flynne242f2d2019-05-22 14:24:13 +01001563// AddMergerLayer places a ConcatLayer into the serialized format and that
1564// when this deserialises we have a ConcatLayer
Jim Flynn5fa83932019-05-09 15:35:43 +01001565BOOST_AUTO_TEST_CASE(SerializeMerger)
1566{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001567 const std::string layerName("merger");
1568 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1569 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1570
1571 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1572
1573 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001574 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001575
1576 armnn::INetworkPtr network = armnn::INetwork::Create();
1577 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1578 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
Jim Flynn906f9462019-05-10 13:55:21 +01001579 ARMNN_NO_DEPRECATE_WARN_BEGIN
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001580 armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str());
Jim Flynn906f9462019-05-10 13:55:21 +01001581 ARMNN_NO_DEPRECATE_WARN_END
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001582 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1583
1584 inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
1585 inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
1586 mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1587
1588 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1589 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1590 mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1591
Jim Flynn5fa83932019-05-09 15:35:43 +01001592 std::string mergerLayerNetwork = SerializeNetwork(*network);
1593 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001594 BOOST_CHECK(deserializedNetwork);
1595
1596 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1597 deserializedNetwork->Accept(verifier);
1598}
1599
Jim Flynn5fa83932019-05-09 15:35:43 +01001600BOOST_AUTO_TEST_CASE(EnsureMergerLayerBackwardCompatibility)
1601{
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001602 // The hex data below is a flat buffer containing a simple network with two inputs
Jim Flynne242f2d2019-05-22 14:24:13 +01001603 // a merger layer (now deprecated) and an output layer with dimensions as per the tensor infos below.
1604 //
1605 // This test verifies that we can still read back these old style
Jim Flynn5fa83932019-05-09 15:35:43 +01001606 // models replacing the MergerLayers with ConcatLayers with the same parameters.
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001607 const std::vector<uint8_t> mergerModel =
Jim Flynn5fa83932019-05-09 15:35:43 +01001608 {
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001609 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1610 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1611 0x38, 0x02, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1613 0xF4, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1614 0x00, 0x00, 0x9A, 0xFE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1615 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1617 0xF8, 0xFE, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1618 0x00, 0x1F, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1619 0x68, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
1620 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1621 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0x04, 0x00,
1622 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1623 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1625 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1626 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6D, 0x65, 0x72, 0x67, 0x65, 0x72, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1627 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1628 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
1629 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00,
1630 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1631 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1632 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1633 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1634 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1635 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1636 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1637 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1639 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1640 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1641 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1642 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1643 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1644 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1645 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1646 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1647 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1648 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1649 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1650 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1651 0x02, 0x00, 0x00, 0x00
1652 };
1653
1654 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(mergerModel.begin(), mergerModel.end()));
Jim Flynn5fa83932019-05-09 15:35:43 +01001655 BOOST_CHECK(deserializedNetwork);
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001656
1657 const armnn::TensorInfo inputInfo = armnn::TensorInfo({ 2, 3, 2, 2 }, armnn::DataType::Float32);
1658 const armnn::TensorInfo outputInfo = armnn::TensorInfo({ 4, 3, 2, 2 }, armnn::DataType::Float32);
Jim Flynn5fa83932019-05-09 15:35:43 +01001659
1660 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1661
1662 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001663 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Jim Flynn5fa83932019-05-09 15:35:43 +01001664
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001665 MergerLayerVerifier verifier("merger", { inputInfo, inputInfo }, { outputInfo }, descriptor);
Jim Flynn5fa83932019-05-09 15:35:43 +01001666 deserializedNetwork->Accept(verifier);
1667}
1668
Jim Flynne242f2d2019-05-22 14:24:13 +01001669BOOST_AUTO_TEST_CASE(SerializeConcat)
1670{
1671 const std::string layerName("concat");
1672 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1673 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1674
1675 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1676
1677 armnn::OriginsDescriptor descriptor =
1678 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1679
1680 armnn::INetworkPtr network = armnn::INetwork::Create();
1681 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1682 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1683 armnn::IConnectableLayer* const concatLayer = network->AddConcatLayer(descriptor, layerName.c_str());
1684 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1685
1686 inputLayerOne->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
1687 inputLayerTwo->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
1688 concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1689
1690 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1691 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1692 concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1693
1694 std::string concatLayerNetwork = SerializeNetwork(*network);
1695 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(concatLayerNetwork);
1696 BOOST_CHECK(deserializedNetwork);
1697
1698 // NOTE: using the MergerLayerVerifier to ensure that it is a concat layer and not a
1699 // merger layer that gets placed into the graph.
1700 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1701 deserializedNetwork->Accept(verifier);
1702}
1703
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001704BOOST_AUTO_TEST_CASE(SerializeMinimum)
1705{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001706 DECLARE_LAYER_VERIFIER_CLASS(Minimum)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001707
1708 const std::string layerName("minimum");
1709 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1710
1711 armnn::INetworkPtr network = armnn::INetwork::Create();
1712 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1713 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1714 armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1715 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1716
1717 inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1718 inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1719 minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1720
1721 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1722 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1723 minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
1724
1725 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1726 BOOST_CHECK(deserializedNetwork);
1727
1728 MinimumLayerVerifier verifier(layerName, {info, info}, {info});
1729 deserializedNetwork->Accept(verifier);
1730}
1731
1732BOOST_AUTO_TEST_CASE(SerializeMultiplication)
1733{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001734 DECLARE_LAYER_VERIFIER_CLASS(Multiplication)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001735
1736 const std::string layerName("multiplication");
1737 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1738
1739 armnn::INetworkPtr network = armnn::INetwork::Create();
1740 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1741 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1742 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
1743 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1744
1745 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
1746 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
1747 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1748
1749 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1750 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1751 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
1752
1753 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1754 BOOST_CHECK(deserializedNetwork);
1755
1756 MultiplicationLayerVerifier verifier(layerName, {info, info}, {info});
1757 deserializedNetwork->Accept(verifier);
1758}
1759
Ellen Norris-Thompson51982472019-06-19 11:46:21 +01001760BOOST_AUTO_TEST_CASE(SerializePrelu)
1761{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001762 DECLARE_LAYER_VERIFIER_CLASS(Prelu)
Ellen Norris-Thompson51982472019-06-19 11:46:21 +01001763
1764 const std::string layerName("prelu");
1765
1766 armnn::TensorInfo inputTensorInfo ({ 4, 1, 2 }, armnn::DataType::Float32);
1767 armnn::TensorInfo alphaTensorInfo ({ 5, 4, 3, 1 }, armnn::DataType::Float32);
1768 armnn::TensorInfo outputTensorInfo({ 5, 4, 3, 2 }, armnn::DataType::Float32);
1769
1770 armnn::INetworkPtr network = armnn::INetwork::Create();
1771 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1772 armnn::IConnectableLayer* const alphaLayer = network->AddInputLayer(1);
1773 armnn::IConnectableLayer* const preluLayer = network->AddPreluLayer(layerName.c_str());
1774 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1775
1776 inputLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(0));
1777 alphaLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(1));
1778 preluLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1779
1780 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1781 alphaLayer->GetOutputSlot(0).SetTensorInfo(alphaTensorInfo);
1782 preluLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1783
1784 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1785 BOOST_CHECK(deserializedNetwork);
1786
1787 PreluLayerVerifier verifier(layerName, {inputTensorInfo, alphaTensorInfo}, {outputTensorInfo});
1788 deserializedNetwork->Accept(verifier);
1789}
1790
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001791BOOST_AUTO_TEST_CASE(SerializeNormalization)
1792{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001793 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Normalization)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001794
1795 const std::string layerName("normalization");
1796 const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
1797
1798 armnn::NormalizationDescriptor desc;
1799 desc.m_DataLayout = armnn::DataLayout::NCHW;
1800 desc.m_NormSize = 3;
1801 desc.m_Alpha = 1;
1802 desc.m_Beta = 1;
1803 desc.m_K = 1;
1804
1805 armnn::INetworkPtr network = armnn::INetwork::Create();
1806 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1807 armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
1808 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1809
1810 inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
1811 normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1812
1813 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1814 normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
1815
1816 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1817 BOOST_CHECK(deserializedNetwork);
1818
1819 NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc);
1820 deserializedNetwork->Accept(verifier);
1821}
1822
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001823DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Pad)
Jim Flynn965c7c62019-06-24 14:32:41 +01001824
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001825BOOST_AUTO_TEST_CASE(SerializePad)
1826{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001827 const std::string layerName("pad");
1828 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1829 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1830
1831 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1832
1833 armnn::INetworkPtr network = armnn::INetwork::Create();
1834 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1835 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
1836 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1837
1838 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
1839 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1840
1841 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1842 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1843
1844 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1845 BOOST_CHECK(deserializedNetwork);
1846
1847 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1848 deserializedNetwork->Accept(verifier);
1849}
1850
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001851BOOST_AUTO_TEST_CASE(EnsurePadBackwardCompatibility)
Jim Flynn965c7c62019-06-24 14:32:41 +01001852{
1853 // The PadDescriptor is being extended with a float PadValue (so a value other than 0
1854 // can be used to pad the tensor.
1855 //
1856 // This test contains a binary representation of a simple input->pad->output network
1857 // prior to this change to test that the descriptor has been updated in a backward
1858 // compatible way with respect to Deserialization of older binary dumps
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001859 const std::vector<uint8_t> padModel =
Jim Flynn965c7c62019-06-24 14:32:41 +01001860 {
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001861 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1862 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1863 0x54, 0x01, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1864 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD0, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
1865 0x04, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x04, 0x00,
1866 0x00, 0x00, 0x72, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1867 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
1868 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00,
1869 0x00, 0x00, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x16, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00,
1870 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
1871 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00,
1872 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1873 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
1874 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1875 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00,
1876 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1877 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
1878 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
1879 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00,
1880 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
1881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00,
1882 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00,
1883 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1884 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00,
1885 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
1886 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
1887 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
1888 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1889 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
1890 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00
1891 };
1892
1893 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(padModel.begin(), padModel.end()));
Jim Flynn965c7c62019-06-24 14:32:41 +01001894 BOOST_CHECK(deserializedNetwork);
1895
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001896 const armnn::TensorInfo inputInfo = armnn::TensorInfo({ 1, 2, 3, 4 }, armnn::DataType::Float32);
1897 const armnn::TensorInfo outputInfo = armnn::TensorInfo({ 1, 3, 5, 7 }, armnn::DataType::Float32);
Jim Flynn965c7c62019-06-24 14:32:41 +01001898
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001899 armnn::PadDescriptor descriptor({{ 0, 0 }, { 1, 0 }, { 1, 1 }, { 1, 2 }});
Jim Flynn965c7c62019-06-24 14:32:41 +01001900
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001901 PadLayerVerifier verifier("pad", { inputInfo }, { outputInfo }, descriptor);
Jim Flynn965c7c62019-06-24 14:32:41 +01001902 deserializedNetwork->Accept(verifier);
1903}
1904
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001905BOOST_AUTO_TEST_CASE(SerializePermute)
1906{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001907 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Permute)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001908
1909 const std::string layerName("permute");
1910 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
1911 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1912
1913 armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
1914
1915 armnn::INetworkPtr network = armnn::INetwork::Create();
1916 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1917 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
1918 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1919
1920 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
1921 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1922
1923 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1924 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1925
1926 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1927 BOOST_CHECK(deserializedNetwork);
1928
1929 PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
1930 deserializedNetwork->Accept(verifier);
1931}
1932
1933BOOST_AUTO_TEST_CASE(SerializePooling2d)
1934{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001935 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Pooling2d)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001936
1937 const std::string layerName("pooling2d");
1938 const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
1939 const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
1940
1941 armnn::Pooling2dDescriptor desc;
1942 desc.m_DataLayout = armnn::DataLayout::NHWC;
1943 desc.m_PadTop = 0;
1944 desc.m_PadBottom = 0;
1945 desc.m_PadLeft = 0;
1946 desc.m_PadRight = 0;
1947 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
1948 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1949 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1950 desc.m_PoolHeight = 2;
1951 desc.m_PoolWidth = 2;
1952 desc.m_StrideX = 2;
1953 desc.m_StrideY = 2;
1954
1955 armnn::INetworkPtr network = armnn::INetwork::Create();
1956 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1957 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
1958 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1959
1960 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
1961 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1962
1963 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1964 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1965
1966 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1967 BOOST_CHECK(deserializedNetwork);
1968
1969 Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1970 deserializedNetwork->Accept(verifier);
1971}
1972
Derek Lamberti87acb272019-03-27 16:51:31 +00001973BOOST_AUTO_TEST_CASE(SerializeQuantize)
1974{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001975 DECLARE_LAYER_VERIFIER_CLASS(Quantize)
Derek Lamberti87acb272019-03-27 16:51:31 +00001976
1977 const std::string layerName("quantize");
1978 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1979
1980 armnn::INetworkPtr network = armnn::INetwork::Create();
1981 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1982 armnn::IConnectableLayer* const quantizeLayer = network->AddQuantizeLayer(layerName.c_str());
1983 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1984
1985 inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
1986 quantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1987
1988 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1989 quantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
1990
1991 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1992 BOOST_CHECK(deserializedNetwork);
1993
1994 QuantizeLayerVerifier verifier(layerName, {info}, {info});
1995 deserializedNetwork->Accept(verifier);
1996}
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001997
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001998BOOST_AUTO_TEST_CASE(SerializeReshape)
1999{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002000 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Reshape)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002001
2002 const std::string layerName("reshape");
2003 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
2004 const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
2005
2006 armnn::ReshapeDescriptor descriptor({3, 3});
2007
2008 armnn::INetworkPtr network = armnn::INetwork::Create();
2009 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2010 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
2011 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2012
2013 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
2014 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2015
2016 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2017 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2018
2019 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2020 BOOST_CHECK(deserializedNetwork);
2021
2022 ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2023 deserializedNetwork->Accept(verifier);
2024}
2025
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002026BOOST_AUTO_TEST_CASE(SerializeResize)
2027{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002028 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Resize)
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002029
2030 const std::string layerName("resize");
Aron Virginas-Tarfe414cf2019-10-31 14:35:58 +00002031 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002032 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2033
2034 armnn::ResizeDescriptor desc;
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002035 desc.m_TargetWidth = 4;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002036 desc.m_TargetHeight = 2;
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002037 desc.m_Method = armnn::ResizeMethod::NearestNeighbor;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002038
2039 armnn::INetworkPtr network = armnn::INetwork::Create();
2040 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2041 armnn::IConnectableLayer* const resizeLayer = network->AddResizeLayer(desc, layerName.c_str());
2042 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2043
2044 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2045 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2046
2047 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2048 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2049
2050 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2051 BOOST_CHECK(deserializedNetwork);
2052
2053 ResizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2054 deserializedNetwork->Accept(verifier);
2055}
2056
Aron Virginas-Tarfe414cf2019-10-31 14:35:58 +00002057class ResizeBilinearLayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::ResizeBilinearDescriptor>
2058{
2059public:
2060 ResizeBilinearLayerVerifier(const std::string& layerName,
2061 const std::vector<armnn::TensorInfo>& inputInfos,
2062 const std::vector<armnn::TensorInfo>& outputInfos,
2063 const armnn::ResizeBilinearDescriptor& descriptor)
2064 : LayerVerifierBaseWithDescriptor<armnn::ResizeBilinearDescriptor>(
2065 layerName, inputInfos, outputInfos, descriptor) {}
2066
2067 void VisitResizeLayer(const armnn::IConnectableLayer* layer,
2068 const armnn::ResizeDescriptor& descriptor,
2069 const char* name) override
2070 {
2071 VerifyNameAndConnections(layer, name);
2072
2073 BOOST_CHECK(descriptor.m_Method == armnn::ResizeMethod::Bilinear);
2074 BOOST_CHECK(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
2075 BOOST_CHECK(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
2076 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2077 }
2078
2079 void VisitResizeBilinearLayer(const armnn::IConnectableLayer*,
2080 const armnn::ResizeBilinearDescriptor&,
2081 const char*) override
2082 {
2083 throw armnn::Exception("ResizeBilinearLayer should have translated to ResizeLayer");
2084 }
2085};
2086
2087// NOTE: Until the deprecated AddResizeBilinearLayer disappears this test checks that
2088// calling AddResizeBilinearLayer places a ResizeLayer into the serialized format
2089// and that when this deserialises we have a ResizeLayer
2090BOOST_AUTO_TEST_CASE(SerializeResizeBilinear)
2091{
2092 const std::string layerName("resizeBilinear");
2093 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2094 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2095
2096 armnn::ResizeBilinearDescriptor desc;
2097 desc.m_TargetWidth = 4u;
2098 desc.m_TargetHeight = 2u;
2099
2100 armnn::INetworkPtr network = armnn::INetwork::Create();
2101 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2102 ARMNN_NO_DEPRECATE_WARN_BEGIN
2103 armnn::IConnectableLayer* const resizeLayer = network->AddResizeBilinearLayer(desc, layerName.c_str());
2104 ARMNN_NO_DEPRECATE_WARN_END
2105 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2106
2107 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2108 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2109
2110 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2111 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2112
2113 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2114 BOOST_CHECK(deserializedNetwork);
2115
2116 ResizeBilinearLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2117 deserializedNetwork->Accept(verifier);
2118}
2119
2120BOOST_AUTO_TEST_CASE(EnsureResizeBilinearBackwardCompatibility)
2121{
2122 // The hex data below is a flat buffer containing a simple network with an input,
2123 // a ResizeBilinearLayer (now deprecated) and an output
2124 //
2125 // This test verifies that we can still deserialize this old-style model by replacing
2126 // the ResizeBilinearLayer with an equivalent ResizeLayer
2127 const std::vector<uint8_t> resizeBilinearModel =
2128 {
2129 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
2130 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2131 0x50, 0x01, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2132 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD4, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
2133 0x04, 0x00, 0x00, 0x00, 0xC2, 0xFE, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
2134 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8A, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
2135 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
2136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2137 0x38, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
2138 0x00, 0x1A, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
2139 0x34, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x12, 0x00, 0x08, 0x00, 0x0C, 0x00,
2140 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2141 0x00, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00,
2142 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
2143 0x20, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x69, 0x7A, 0x65, 0x42, 0x69, 0x6C, 0x69,
2144 0x6E, 0x65, 0x61, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2145 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
2146 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2147 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
2148 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2149 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
2150 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
2151 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00,
2152 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
2153 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00,
2155 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
2156 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
2157 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00,
2158 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
2159 };
2160
2161 armnn::INetworkPtr deserializedNetwork =
2162 DeserializeNetwork(std::string(resizeBilinearModel.begin(), resizeBilinearModel.end()));
2163 BOOST_CHECK(deserializedNetwork);
2164
2165 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2166 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2167
2168 armnn::ResizeBilinearDescriptor descriptor;
2169 descriptor.m_TargetWidth = 4u;
2170 descriptor.m_TargetHeight = 2u;
2171
2172 ResizeBilinearLayerVerifier verifier("resizeBilinear", { inputInfo }, { outputInfo }, descriptor);
2173 deserializedNetwork->Accept(verifier);
2174}
2175
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002176BOOST_AUTO_TEST_CASE(SerializeRsqrt)
2177{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002178 DECLARE_LAYER_VERIFIER_CLASS(Rsqrt)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002179
2180 const std::string layerName("rsqrt");
2181 const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32);
2182
2183 armnn::INetworkPtr network = armnn::INetwork::Create();
2184 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2185 armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer(layerName.c_str());
2186 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2187
2188 inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0));
2189 rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2190
2191 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2192 rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2193
2194 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2195 BOOST_CHECK(deserializedNetwork);
2196
2197 RsqrtLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
2198 deserializedNetwork->Accept(verifier);
2199}
2200
Aron Virginas-Tar2fda80b2019-09-18 13:36:52 +01002201BOOST_AUTO_TEST_CASE(SerializeSlice)
2202{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002203 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Slice)
Aron Virginas-Tar2fda80b2019-09-18 13:36:52 +01002204
2205 const std::string layerName{"slice"};
2206
2207 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2208 const armnn::TensorInfo outputInfo = armnn::TensorInfo({2, 2, 2, 1}, armnn::DataType::Float32);
2209
2210 armnn::SliceDescriptor descriptor({ 0, 0, 1, 0}, {2, 2, 2, 1});
2211
2212 armnn::INetworkPtr network = armnn::INetwork::Create();
2213
2214 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2215 armnn::IConnectableLayer* const sliceLayer = network->AddSliceLayer(descriptor, layerName.c_str());
2216 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2217
2218 inputLayer->GetOutputSlot(0).Connect(sliceLayer->GetInputSlot(0));
2219 sliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2220
2221 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2222 sliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2223
2224 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2225 BOOST_CHECK(deserializedNetwork);
2226
2227 SliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2228 deserializedNetwork->Accept(verifier);
2229}
2230
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002231BOOST_AUTO_TEST_CASE(SerializeSoftmax)
2232{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002233 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Softmax)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002234
2235 const std::string layerName("softmax");
2236 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
2237
2238 armnn::SoftmaxDescriptor descriptor;
2239 descriptor.m_Beta = 1.0f;
2240
2241 armnn::INetworkPtr network = armnn::INetwork::Create();
2242 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2243 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
2244 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2245
2246 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
2247 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2248
2249 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2250 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
2251
2252 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2253 BOOST_CHECK(deserializedNetwork);
2254
2255 SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
2256 deserializedNetwork->Accept(verifier);
2257}
2258
2259BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
2260{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002261 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(SpaceToBatchNd)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002262
2263 const std::string layerName("spaceToBatchNd");
2264 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
2265 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
2266
2267 armnn::SpaceToBatchNdDescriptor desc;
2268 desc.m_DataLayout = armnn::DataLayout::NCHW;
2269 desc.m_BlockShape = {2, 2};
2270 desc.m_PadList = {{0, 0}, {2, 0}};
2271
2272 armnn::INetworkPtr network = armnn::INetwork::Create();
2273 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2274 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2275 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2276
2277 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
2278 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2279
2280 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2281 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2282
2283 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2284 BOOST_CHECK(deserializedNetwork);
2285
2286 SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2287 deserializedNetwork->Accept(verifier);
2288}
2289
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002290BOOST_AUTO_TEST_CASE(SerializeSpaceToDepth)
2291{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002292 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(SpaceToDepth)
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002293
2294 const std::string layerName("spaceToDepth");
2295
2296 const armnn::TensorInfo inputInfo ({ 1, 16, 8, 3 }, armnn::DataType::Float32);
2297 const armnn::TensorInfo outputInfo({ 1, 8, 4, 12 }, armnn::DataType::Float32);
2298
2299 armnn::SpaceToDepthDescriptor desc;
2300 desc.m_BlockSize = 2;
2301 desc.m_DataLayout = armnn::DataLayout::NHWC;
2302
2303 armnn::INetworkPtr network = armnn::INetwork::Create();
2304 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2305 armnn::IConnectableLayer* const spaceToDepthLayer = network->AddSpaceToDepthLayer(desc, layerName.c_str());
2306 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2307
2308 inputLayer->GetOutputSlot(0).Connect(spaceToDepthLayer->GetInputSlot(0));
2309 spaceToDepthLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2310
2311 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2312 spaceToDepthLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2313
2314 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2315 BOOST_CHECK(deserializedNetwork);
2316
2317 SpaceToDepthLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2318 deserializedNetwork->Accept(verifier);
2319}
2320
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002321BOOST_AUTO_TEST_CASE(SerializeSplitter)
2322{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002323 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Splitter)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002324
2325 const unsigned int numViews = 3;
2326 const unsigned int numDimensions = 4;
2327 const unsigned int inputShape[] = {1, 18, 4, 4};
2328 const unsigned int outputShape[] = {1, 6, 4, 4};
2329
2330 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
2331 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
2332 static_cast<unsigned int>(inputShape[1]),
2333 static_cast<unsigned int>(inputShape[2]),
2334 static_cast<unsigned int>(inputShape[3])};
2335 splitterDimSizes[1] /= numViews;
2336 armnn::ViewsDescriptor desc(numViews, numDimensions);
2337
2338 for (unsigned int g = 0; g < numViews; ++g)
2339 {
2340 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
2341
2342 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
2343 {
2344 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
2345 }
2346 }
2347
2348 const std::string layerName("splitter");
2349 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
2350 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
2351
2352 armnn::INetworkPtr network = armnn::INetwork::Create();
2353 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2354 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
2355 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2356 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2357 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
2358
2359 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
2360 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2361 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2362 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
2363
2364 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2365 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2366 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
2367 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2368
2369 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2370 BOOST_CHECK(deserializedNetwork);
2371
2372 SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
2373 deserializedNetwork->Accept(verifier);
2374}
2375
Matthew Jacksonb5433ee2019-07-11 15:54:20 +01002376BOOST_AUTO_TEST_CASE(SerializeStack)
2377{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002378 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Stack)
Matthew Jacksonb5433ee2019-07-11 15:54:20 +01002379
2380 const std::string layerName("stack");
2381
2382 armnn::TensorInfo inputTensorInfo ({4, 3, 5}, armnn::DataType::Float32);
2383 armnn::TensorInfo outputTensorInfo({4, 3, 2, 5}, armnn::DataType::Float32);
2384
2385 armnn::StackDescriptor descriptor(2, 2, {4, 3, 5});
2386
2387 armnn::INetworkPtr network = armnn::INetwork::Create();
2388 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
2389 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
2390 armnn::IConnectableLayer* const stackLayer = network->AddStackLayer(descriptor, layerName.c_str());
2391 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2392
2393 inputLayer1->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(0));
2394 inputLayer2->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(1));
2395 stackLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2396
2397 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2398 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2399 stackLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2400
2401 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2402 BOOST_CHECK(deserializedNetwork);
2403
2404 StackLayerVerifier verifier(layerName, {inputTensorInfo, inputTensorInfo}, {outputTensorInfo}, descriptor);
2405 deserializedNetwork->Accept(verifier);
2406}
2407
Aron Virginas-Tar85121a22019-10-23 10:41:35 +01002408BOOST_AUTO_TEST_CASE(SerializeStandIn)
2409{
2410 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(StandIn)
2411
2412 const std::string layerName("standIn");
2413
2414 armnn::TensorInfo tensorInfo({ 1u }, armnn::DataType::Float32);
2415 armnn::StandInDescriptor descriptor(2u, 2u);
2416
2417 armnn::INetworkPtr network = armnn::INetwork::Create();
2418 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2419 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2420 armnn::IConnectableLayer* const standInLayer = network->AddStandInLayer(descriptor, layerName.c_str());
2421 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2422 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2423
2424 inputLayer0->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(0));
2425 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2426
2427 inputLayer1->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(1));
2428 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2429
2430 standInLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2431 standInLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2432
2433 standInLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2434 standInLayer->GetOutputSlot(1).SetTensorInfo(tensorInfo);
2435
2436 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2437 BOOST_CHECK(deserializedNetwork);
2438
2439 StandInLayerVerifier verifier(layerName, { tensorInfo, tensorInfo }, { tensorInfo, tensorInfo }, descriptor);
2440 deserializedNetwork->Accept(verifier);
2441}
2442
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002443BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
2444{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002445 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(StridedSlice)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002446
2447 const std::string layerName("stridedSlice");
2448 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2449 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2450
2451 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2452 desc.m_EndMask = (1 << 4) - 1;
2453 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2454 desc.m_DataLayout = armnn::DataLayout::NCHW;
2455
2456 armnn::INetworkPtr network = armnn::INetwork::Create();
2457 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2458 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2459 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2460
2461 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2462 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2463
2464 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2465 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2466
2467 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2468 BOOST_CHECK(deserializedNetwork);
2469
2470 StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2471 deserializedNetwork->Accept(verifier);
2472}
2473
2474BOOST_AUTO_TEST_CASE(SerializeSubtraction)
2475{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002476 DECLARE_LAYER_VERIFIER_CLASS(Subtraction)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002477
2478 const std::string layerName("subtraction");
2479 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2480
2481 armnn::INetworkPtr network = armnn::INetwork::Create();
2482 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2483 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2484 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2485 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2486
2487 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2488 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2489 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2490
2491 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2492 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2493 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2494
2495 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2496 BOOST_CHECK(deserializedNetwork);
2497
2498 SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
2499 deserializedNetwork->Accept(verifier);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +00002500}
2501
Sadik Armaganeff363d2019-04-05 15:25:46 +01002502BOOST_AUTO_TEST_CASE(SerializeSwitch)
2503{
2504 class SwitchLayerVerifier : public LayerVerifierBase
2505 {
2506 public:
2507 SwitchLayerVerifier(const std::string& layerName,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002508 const std::vector<armnn::TensorInfo>& inputInfos,
2509 const std::vector<armnn::TensorInfo>& outputInfos)
Sadik Armaganeff363d2019-04-05 15:25:46 +01002510 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2511
2512 void VisitSwitchLayer(const armnn::IConnectableLayer* layer, const char* name) override
2513 {
2514 VerifyNameAndConnections(layer, name);
2515 }
2516
2517 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2518 const armnn::ConstTensor& input,
2519 const char *name) override {}
2520 };
2521
2522 const std::string layerName("switch");
2523 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2524
2525 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2526 armnn::ConstTensor constTensor(info, constantData);
2527
2528 armnn::INetworkPtr network = armnn::INetwork::Create();
2529 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2530 armnn::IConnectableLayer* const constantLayer = network->AddConstantLayer(constTensor, "constant");
2531 armnn::IConnectableLayer* const switchLayer = network->AddSwitchLayer(layerName.c_str());
2532 armnn::IConnectableLayer* const trueOutputLayer = network->AddOutputLayer(0);
2533 armnn::IConnectableLayer* const falseOutputLayer = network->AddOutputLayer(1);
2534
2535 inputLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(0));
2536 constantLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(1));
2537 switchLayer->GetOutputSlot(0).Connect(trueOutputLayer->GetInputSlot(0));
2538 switchLayer->GetOutputSlot(1).Connect(falseOutputLayer->GetInputSlot(0));
2539
2540 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2541 constantLayer->GetOutputSlot(0).SetTensorInfo(info);
2542 switchLayer->GetOutputSlot(0).SetTensorInfo(info);
2543 switchLayer->GetOutputSlot(1).SetTensorInfo(info);
2544
2545 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2546 BOOST_CHECK(deserializedNetwork);
2547
2548 SwitchLayerVerifier verifier(layerName, {info, info}, {info, info});
2549 deserializedNetwork->Accept(verifier);
2550}
2551
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002552BOOST_AUTO_TEST_CASE(SerializeTransposeConvolution2d)
2553{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002554 using Descriptor = armnn::TransposeConvolution2dDescriptor;
2555 class TransposeConvolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002556 {
2557 public:
2558 TransposeConvolution2dLayerVerifier(const std::string& layerName,
2559 const std::vector<armnn::TensorInfo>& inputInfos,
2560 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002561 const Descriptor& descriptor,
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002562 const armnn::ConstTensor& weights,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002563 const armnn::Optional<armnn::ConstTensor>& biases)
2564 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
2565 , m_Weights(weights)
2566 , m_Biases(biases)
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002567 {}
2568
2569 void VisitTransposeConvolution2dLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002570 const Descriptor& descriptor,
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002571 const armnn::ConstTensor& weights,
2572 const armnn::Optional<armnn::ConstTensor>& biases,
2573 const char* name) override
2574 {
2575 VerifyNameAndConnections(layer, name);
2576 VerifyDescriptor(descriptor);
2577
2578 // check weights
2579 CompareConstTensor(weights, m_Weights);
2580
2581 // check biases
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002582 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002583 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
2584
2585 if (biases.has_value() && m_Biases.has_value())
2586 {
2587 CompareConstTensor(biases.value(), m_Biases.value());
2588 }
2589 }
2590
2591 private:
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002592 armnn::ConstTensor m_Weights;
2593 armnn::Optional<armnn::ConstTensor> m_Biases;
2594 };
2595
2596 const std::string layerName("transposeConvolution2d");
2597 const armnn::TensorInfo inputInfo ({ 1, 7, 7, 1 }, armnn::DataType::Float32);
2598 const armnn::TensorInfo outputInfo({ 1, 9, 9, 1 }, armnn::DataType::Float32);
2599
2600 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
2601 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
2602
2603 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
2604 armnn::ConstTensor weights(weightsInfo, weightsData);
2605
2606 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
2607 armnn::ConstTensor biases(biasesInfo, biasesData);
2608
2609 armnn::TransposeConvolution2dDescriptor descriptor;
2610 descriptor.m_PadLeft = 1;
2611 descriptor.m_PadRight = 1;
2612 descriptor.m_PadTop = 1;
2613 descriptor.m_PadBottom = 1;
2614 descriptor.m_StrideX = 1;
2615 descriptor.m_StrideY = 1;
2616 descriptor.m_BiasEnabled = true;
2617 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
2618
2619 armnn::INetworkPtr network = armnn::INetwork::Create();
2620 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2621 armnn::IConnectableLayer* const convLayer =
2622 network->AddTransposeConvolution2dLayer(descriptor,
2623 weights,
2624 armnn::Optional<armnn::ConstTensor>(biases),
2625 layerName.c_str());
2626 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2627
2628 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
2629 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2630
2631 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2632 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2633
2634 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2635 BOOST_CHECK(deserializedNetwork);
2636
2637 TransposeConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
2638 deserializedNetwork->Accept(verifier);
2639}
2640
Sadik Armagandb059fd2019-03-20 12:28:32 +00002641BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
2642{
2643 class ConstantLayerVerifier : public LayerVerifierBase
2644 {
2645 public:
2646 ConstantLayerVerifier(const std::string& layerName,
2647 const std::vector<armnn::TensorInfo>& inputInfos,
2648 const std::vector<armnn::TensorInfo>& outputInfos,
2649 const armnn::ConstTensor& layerInput)
2650 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2651 , m_LayerInput(layerInput) {}
2652
2653 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2654 const armnn::ConstTensor& input,
2655 const char* name) override
2656 {
2657 VerifyNameAndConnections(layer, name);
Sadik Armagandb059fd2019-03-20 12:28:32 +00002658 CompareConstTensor(input, m_LayerInput);
2659 }
2660
2661 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
2662
2663 private:
2664 armnn::ConstTensor m_LayerInput;
2665 };
2666
2667 const std::string layerName("constant");
2668 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
2669
2670 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2671 armnn::ConstTensor constTensor(info, constantData);
2672
2673 armnn::INetworkPtr network(armnn::INetwork::Create());
2674 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2675 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2676 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2677 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2678
2679 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2680 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2681 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2682
2683 input->GetOutputSlot(0).SetTensorInfo(info);
2684 constant->GetOutputSlot(0).SetTensorInfo(info);
2685 add->GetOutputSlot(0).SetTensorInfo(info);
2686
2687 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2688 BOOST_CHECK(deserializedNetwork);
2689
2690 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
2691 deserializedNetwork->Accept(verifier);
2692}
2693
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002694class VerifyLstmLayer : public LayerVerifierBaseWithDescriptor<armnn::LstmDescriptor>
Jim Flynn11af3752019-03-19 17:22:29 +00002695{
2696public:
2697 VerifyLstmLayer(const std::string& layerName,
2698 const std::vector<armnn::TensorInfo>& inputInfos,
2699 const std::vector<armnn::TensorInfo>& outputInfos,
2700 const armnn::LstmDescriptor& descriptor,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002701 const armnn::LstmInputParams& inputParams)
2702 : LayerVerifierBaseWithDescriptor<armnn::LstmDescriptor>(layerName, inputInfos, outputInfos, descriptor)
2703 , m_InputParams(inputParams) {}
2704
Jim Flynn11af3752019-03-19 17:22:29 +00002705 void VisitLstmLayer(const armnn::IConnectableLayer* layer,
2706 const armnn::LstmDescriptor& descriptor,
2707 const armnn::LstmInputParams& params,
2708 const char* name)
2709 {
2710 VerifyNameAndConnections(layer, name);
2711 VerifyDescriptor(descriptor);
2712 VerifyInputParameters(params);
2713 }
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002714
Jim Flynn11af3752019-03-19 17:22:29 +00002715protected:
Jim Flynn11af3752019-03-19 17:22:29 +00002716 void VerifyInputParameters(const armnn::LstmInputParams& params)
2717 {
2718 VerifyConstTensors(
2719 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
2720 VerifyConstTensors(
2721 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
2722 VerifyConstTensors(
2723 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
2724 VerifyConstTensors(
2725 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
2726 VerifyConstTensors(
2727 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
2728 VerifyConstTensors(
2729 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
2730 VerifyConstTensors(
2731 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
2732 VerifyConstTensors(
2733 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
2734 VerifyConstTensors(
2735 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
2736 VerifyConstTensors(
2737 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
2738 VerifyConstTensors(
2739 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
2740 VerifyConstTensors(
2741 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
2742 VerifyConstTensors(
2743 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
2744 VerifyConstTensors(
2745 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
2746 VerifyConstTensors(
2747 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
2748 VerifyConstTensors(
2749 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
2750 VerifyConstTensors(
2751 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
Jan Eilersf8c62972019-07-17 11:07:49 +01002752 VerifyConstTensors(
2753 "m_InputLayerNormWeights", m_InputParams.m_InputLayerNormWeights, params.m_InputLayerNormWeights);
2754 VerifyConstTensors(
2755 "m_ForgetLayerNormWeights", m_InputParams.m_ForgetLayerNormWeights, params.m_ForgetLayerNormWeights);
2756 VerifyConstTensors(
2757 "m_CellLayerNormWeights", m_InputParams.m_CellLayerNormWeights, params.m_CellLayerNormWeights);
2758 VerifyConstTensors(
2759 "m_OutputLayerNormWeights", m_InputParams.m_OutputLayerNormWeights, params.m_OutputLayerNormWeights);
Jim Flynn11af3752019-03-19 17:22:29 +00002760 }
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002761
Jim Flynn11af3752019-03-19 17:22:29 +00002762private:
Jim Flynn11af3752019-03-19 17:22:29 +00002763 armnn::LstmInputParams m_InputParams;
2764};
2765
2766BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
2767{
2768 armnn::LstmDescriptor descriptor;
2769 descriptor.m_ActivationFunc = 4;
2770 descriptor.m_ClippingThresProj = 0.0f;
2771 descriptor.m_ClippingThresCell = 0.0f;
2772 descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
2773 descriptor.m_ProjectionEnabled = false;
2774 descriptor.m_PeepholeEnabled = true;
2775
2776 const uint32_t batchSize = 1;
2777 const uint32_t inputSize = 2;
2778 const uint32_t numUnits = 4;
2779 const uint32_t outputSize = numUnits;
2780
2781 armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
2782 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2783 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
2784
2785 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2786 armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
2787
2788 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2789 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
2790
2791 armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
2792 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2793 armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
2794
2795 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2796 armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
2797
2798 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2799 armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
2800
2801 armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
2802 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2803 armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
2804
2805 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2806 armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
2807
2808 std::vector<float> forgetGateBiasData(numUnits, 1.0f);
2809 armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
2810
2811 std::vector<float> cellBiasData(numUnits, 0.0f);
2812 armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
2813
2814 std::vector<float> outputGateBiasData(numUnits, 0.0f);
2815 armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
2816
2817 armnn::LstmInputParams params;
2818 params.m_InputToForgetWeights = &inputToForgetWeights;
2819 params.m_InputToCellWeights = &inputToCellWeights;
2820 params.m_InputToOutputWeights = &inputToOutputWeights;
2821 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2822 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2823 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2824 params.m_ForgetGateBias = &forgetGateBias;
2825 params.m_CellBias = &cellBias;
2826 params.m_OutputGateBias = &outputGateBias;
2827 params.m_CellToForgetWeights = &cellToForgetWeights;
2828 params.m_CellToOutputWeights = &cellToOutputWeights;
2829
2830 armnn::INetworkPtr network = armnn::INetwork::Create();
2831 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2832 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2833 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2834 const std::string layerName("lstm");
2835 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2836 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2837 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2838 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2839 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2840
2841 // connect up
2842 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2843 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2844 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2845 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
2846
2847 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2848 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2849
2850 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2851 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2852
2853 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2854 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2855
2856 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2857 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2858
2859 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2860 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2861
2862 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2863 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2864
2865 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2866 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2867
2868 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2869 BOOST_CHECK(deserializedNetwork);
2870
2871 VerifyLstmLayer checker(
2872 layerName,
2873 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2874 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2875 descriptor,
2876 params);
2877 deserializedNetwork->Accept(checker);
2878}
2879
2880BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
2881{
2882 armnn::LstmDescriptor descriptor;
2883 descriptor.m_ActivationFunc = 4;
2884 descriptor.m_ClippingThresProj = 0.0f;
2885 descriptor.m_ClippingThresCell = 0.0f;
2886 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
2887 descriptor.m_ProjectionEnabled = true;
2888 descriptor.m_PeepholeEnabled = true;
2889
2890 const uint32_t batchSize = 2;
2891 const uint32_t inputSize = 5;
2892 const uint32_t numUnits = 20;
2893 const uint32_t outputSize = 16;
2894
2895 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
2896 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2897 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
2898
2899 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2900 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
2901
2902 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2903 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
2904
2905 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2906 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
2907
2908 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
2909 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2910 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
2911
2912 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2913 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
2914
2915 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2916 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
2917
2918 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2919 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
2920
2921 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
2922 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2923 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
2924
2925 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2926 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
2927
2928 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2929 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
2930
2931 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2932 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
2933
2934 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2935 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
2936
2937 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2938 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
2939
2940 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2941 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
2942
2943 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
2944 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
2945 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
2946
2947 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
2948 std::vector<float> projectionBiasData(outputSize, 0.f);
2949 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
2950
2951 armnn::LstmInputParams params;
2952 params.m_InputToForgetWeights = &inputToForgetWeights;
2953 params.m_InputToCellWeights = &inputToCellWeights;
2954 params.m_InputToOutputWeights = &inputToOutputWeights;
2955 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2956 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2957 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2958 params.m_ForgetGateBias = &forgetGateBias;
2959 params.m_CellBias = &cellBias;
2960 params.m_OutputGateBias = &outputGateBias;
2961
2962 // additional params because: descriptor.m_CifgEnabled = false
2963 params.m_InputToInputWeights = &inputToInputWeights;
2964 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
2965 params.m_CellToInputWeights = &cellToInputWeights;
2966 params.m_InputGateBias = &inputGateBias;
2967
2968 // additional params because: descriptor.m_ProjectionEnabled = true
2969 params.m_ProjectionWeights = &projectionWeights;
2970 params.m_ProjectionBias = &projectionBias;
2971
2972 // additional params because: descriptor.m_PeepholeEnabled = true
2973 params.m_CellToForgetWeights = &cellToForgetWeights;
2974 params.m_CellToOutputWeights = &cellToOutputWeights;
2975
2976 armnn::INetworkPtr network = armnn::INetwork::Create();
2977 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2978 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2979 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2980 const std::string layerName("lstm");
2981 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2982 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2983 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2984 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2985 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2986
2987 // connect up
2988 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2989 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2990 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2991 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
2992
2993 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2994 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2995
2996 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2997 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2998
2999 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3000 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3001
3002 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3003 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3004
3005 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3006 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3007
3008 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3009 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3010
3011 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3012 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3013
3014 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3015 BOOST_CHECK(deserializedNetwork);
3016
3017 VerifyLstmLayer checker(
3018 layerName,
3019 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3020 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3021 descriptor,
3022 params);
3023 deserializedNetwork->Accept(checker);
3024}
3025
Jan Eilersf8c62972019-07-17 11:07:49 +01003026BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeWithProjectionWithLayerNorm)
3027{
3028 armnn::LstmDescriptor descriptor;
3029 descriptor.m_ActivationFunc = 4;
3030 descriptor.m_ClippingThresProj = 0.0f;
3031 descriptor.m_ClippingThresCell = 0.0f;
3032 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
3033 descriptor.m_ProjectionEnabled = true;
3034 descriptor.m_PeepholeEnabled = true;
3035 descriptor.m_LayerNormEnabled = true;
3036
3037 const uint32_t batchSize = 2;
3038 const uint32_t inputSize = 5;
3039 const uint32_t numUnits = 20;
3040 const uint32_t outputSize = 16;
3041
3042 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3043 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3044 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3045
3046 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3047 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3048
3049 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3050 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3051
3052 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3053 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3054
3055 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3056 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3057 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3058
3059 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3060 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3061
3062 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3063 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3064
3065 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3066 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3067
3068 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3069 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3070 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3071
3072 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3073 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3074
3075 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3076 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3077
3078 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3079 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3080
3081 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3082 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3083
3084 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3085 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3086
3087 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3088 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3089
3090 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3091 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
3092 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3093
3094 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3095 std::vector<float> projectionBiasData(outputSize, 0.f);
3096 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3097
3098 std::vector<float> inputLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3099 armnn::ConstTensor inputLayerNormWeights(tensorInfo20, forgetGateBiasData);
3100
3101 std::vector<float> forgetLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3102 armnn::ConstTensor forgetLayerNormWeights(tensorInfo20, forgetGateBiasData);
3103
3104 std::vector<float> cellLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3105 armnn::ConstTensor cellLayerNormWeights(tensorInfo20, forgetGateBiasData);
3106
3107 std::vector<float> outLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3108 armnn::ConstTensor outLayerNormWeights(tensorInfo20, forgetGateBiasData);
3109
3110 armnn::LstmInputParams params;
3111 params.m_InputToForgetWeights = &inputToForgetWeights;
3112 params.m_InputToCellWeights = &inputToCellWeights;
3113 params.m_InputToOutputWeights = &inputToOutputWeights;
3114 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3115 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3116 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3117 params.m_ForgetGateBias = &forgetGateBias;
3118 params.m_CellBias = &cellBias;
3119 params.m_OutputGateBias = &outputGateBias;
3120
3121 // additional params because: descriptor.m_CifgEnabled = false
3122 params.m_InputToInputWeights = &inputToInputWeights;
3123 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3124 params.m_CellToInputWeights = &cellToInputWeights;
3125 params.m_InputGateBias = &inputGateBias;
3126
3127 // additional params because: descriptor.m_ProjectionEnabled = true
3128 params.m_ProjectionWeights = &projectionWeights;
3129 params.m_ProjectionBias = &projectionBias;
3130
3131 // additional params because: descriptor.m_PeepholeEnabled = true
3132 params.m_CellToForgetWeights = &cellToForgetWeights;
3133 params.m_CellToOutputWeights = &cellToOutputWeights;
3134
3135 // additional params because: despriptor.m_LayerNormEnabled = true
3136 params.m_InputLayerNormWeights = &inputLayerNormWeights;
3137 params.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
3138 params.m_CellLayerNormWeights = &cellLayerNormWeights;
3139 params.m_OutputLayerNormWeights = &outLayerNormWeights;
3140
3141 armnn::INetworkPtr network = armnn::INetwork::Create();
3142 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3143 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3144 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3145 const std::string layerName("lstm");
3146 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3147 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3148 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3149 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3150 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3151
3152 // connect up
3153 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3154 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3155 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3156 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3157
3158 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3159 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3160
3161 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3162 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3163
3164 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3165 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3166
3167 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3168 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3169
3170 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3171 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3172
3173 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3174 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3175
3176 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3177 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3178
3179 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3180 BOOST_CHECK(deserializedNetwork);
3181
3182 VerifyLstmLayer checker(
3183 layerName,
3184 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3185 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3186 descriptor,
3187 params);
3188 deserializedNetwork->Accept(checker);
3189}
3190
3191BOOST_AUTO_TEST_CASE(EnsureLstmLayersBackwardCompatibility)
3192{
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003193 // The hex data below is a flat buffer containing a lstm layer with no Cifg, with peephole and projection
3194 // enabled. That data was obtained before additional layer normalization parameters where added to the
3195 // lstm serializer. That way it can be tested if a lstm model with the old parameter configuration can
3196 // still be loaded
3197 const std::vector<uint8_t> lstmNoCifgWithPeepholeAndProjectionModel =
Jan Eilersf8c62972019-07-17 11:07:49 +01003198 {
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003199 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
3200 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
3201 0xDC, 0x29, 0x00, 0x00, 0x38, 0x29, 0x00, 0x00, 0xB4, 0x28, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x3C, 0x01,
3202 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
3203 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
3204 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x70, 0xD6, 0xFF, 0xFF,
3205 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x06, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x88, 0xD7,
3206 0xFF, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF6, 0xD6, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,
3207 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
3208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3209 0xE8, 0xD7, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xC8, 0xD6, 0xFF, 0xFF, 0x00, 0x00,
3210 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x5E, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xE0, 0xD7, 0xFF, 0xFF,
3211 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4E, 0xD7, 0xFF, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
3212 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3213 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xD8,
3214 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
3215 0x04, 0x00, 0x00, 0x00, 0xB6, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x38, 0xD8, 0xFF, 0xFF, 0x08, 0x00,
3216 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA6, 0xD7, 0xFF, 0xFF, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3217 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3218 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xD8, 0xFF, 0xFF,
3219 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00,
3220 0x00, 0x00, 0x0E, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x16, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
3221 0xFA, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00,
3222 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3223 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xD8, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
3224 0x00, 0x00, 0x6C, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
3225 0x12, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xE0, 0x25, 0x00, 0x00, 0xD0, 0x25,
3226 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x48, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00,
3227 0x10, 0x00, 0x14, 0x00, 0x18, 0x00, 0x1C, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2C, 0x00, 0x30, 0x00,
3228 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x40, 0x00, 0x44, 0x00, 0x26, 0x00, 0x00, 0x00, 0xC4, 0x23, 0x00, 0x00,
3229 0xF8, 0x21, 0x00, 0x00, 0x2C, 0x20, 0x00, 0x00, 0xF0, 0x1A, 0x00, 0x00, 0xB4, 0x15, 0x00, 0x00, 0x78, 0x10,
3230 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x68, 0x0F, 0x00, 0x00, 0xE0, 0x0E, 0x00, 0x00, 0x14, 0x0D, 0x00, 0x00,
3231 0xD8, 0x07, 0x00, 0x00, 0x50, 0x07, 0x00, 0x00, 0xC8, 0x06, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x14, 0x01,
3232 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xEE, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3233 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 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, 0x5A, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3239 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x72, 0xD8,
3240 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x82, 0xD9, 0xFF, 0xFF,
3241 0x04, 0x00, 0x00, 0x00, 0x14, 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, 0xDE, 0xD8,
3246 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3247 0x14, 0x00, 0x00, 0x00, 0xF6, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x54, 0x00, 0x00, 0x00, 0x04, 0x00,
3248 0x00, 0x00, 0x06, 0xDA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x10, 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, 0x52, 0xD9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3253 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6A, 0xD9, 0xFF, 0xFF, 0x00, 0x00,
3254 0x00, 0x03, 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7A, 0xDA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
3255 0x40, 0x01, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3300 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xDE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3327 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xA2, 0xDE,
3328 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB2, 0xDF, 0xFF, 0xFF,
3329 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xDF,
3334 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3335 0x14, 0x00, 0x00, 0x00, 0x26, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00,
3336 0x00, 0x00, 0x36, 0xE0, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3341 0x00, 0x00, 0x00, 0x00, 0x92, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3342 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xAA, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3343 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xBA, 0xE0, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01,
3344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xC6, 0xE4, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3416 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xE2, 0xE4, 0xFF, 0xFF,
3417 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xE5, 0xFF, 0xFF, 0x04, 0x00,
3418 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x8E, 0xE6, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3441 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00,
3442 0x00, 0x00, 0xAA, 0xE6, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3443 0xBA, 0xE7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 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, 0x16, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3449 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x2E, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00,
3450 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3E, 0xE8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 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, 0x9A, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xB2, 0xE7, 0xFF, 0xFF,
3457 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC2, 0xE8, 0xFF, 0xFF, 0x04, 0x00,
3458 0x00, 0x00, 0x14, 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, 0x1E, 0xE8, 0xFF, 0xFF,
3463 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00,
3464 0x00, 0x00, 0x36, 0xE8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3465 0x46, 0xE9, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x52, 0xED, 0xFF, 0xFF,
3537 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00,
3538 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6E, 0xED, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x14, 0x05, 0x00, 0x00,
3539 0x04, 0x00, 0x00, 0x00, 0x7E, 0xEE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3611 0x8A, 0xF2, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3612 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xA6, 0xF2, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3613 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB6, 0xF3, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01,
3614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3673 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3675 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3680 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3685 0x00, 0x00, 0x00, 0x00, 0xC2, 0xF7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3686 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xDE, 0xF7, 0xFF, 0xFF,
3687 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xEE, 0xF8, 0xFF, 0xFF, 0x04, 0x00,
3688 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xF9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3711 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00,
3712 0x00, 0x00, 0xA6, 0xF9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3713 0xB6, 0xFA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3721 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3733 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xFB,
3736 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
3737 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x6E, 0xFB, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01,
3738 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7E, 0xFC, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
3739 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3750 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3752 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3754 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3755 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3757 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3758 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3759 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3760 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3761 0x00, 0x00, 0x00, 0x00, 0x1A, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3762 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0C, 0x00,
3763 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
3764 0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x2E, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3765 0x22, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6C, 0x73,
3766 0x74, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00,
3767 0xB4, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x30, 0x00,
3768 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3769 0xA6, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3770 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3C, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
3771 0x04, 0x00, 0x00, 0x00, 0xCE, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3772 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x64, 0xFF, 0xFF, 0xFF,
3773 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3774 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3775 0xB4, 0xFE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x1A, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
3777 0xF0, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
3778 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
3779 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3780 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00,
3781 0x7E, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00,
3782 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x76, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
3783 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
3784 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3785 0x68, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xCE, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3786 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3787 0x08, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00,
3788 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
3789 0x08, 0x00, 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00,
3790 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00,
3791 0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
3792 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3793 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
3794 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6E, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3795 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00,
3796 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00,
3797 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00,
3798 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
3799 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
3800 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3801 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
3802 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00,
3803 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3804 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00
3805 };
3806
3807 armnn::INetworkPtr deserializedNetwork =
3808 DeserializeNetwork(std::string(lstmNoCifgWithPeepholeAndProjectionModel.begin(),
3809 lstmNoCifgWithPeepholeAndProjectionModel.end()));
3810
Jan Eilersf8c62972019-07-17 11:07:49 +01003811 BOOST_CHECK(deserializedNetwork);
3812
3813 // generating the same model parameters which where used to serialize the model (Layer norm is not specified)
3814 armnn::LstmDescriptor descriptor;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003815 descriptor.m_ActivationFunc = 4;
Jan Eilersf8c62972019-07-17 11:07:49 +01003816 descriptor.m_ClippingThresProj = 0.0f;
3817 descriptor.m_ClippingThresCell = 0.0f;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003818 descriptor.m_CifgEnabled = false;
Jan Eilersf8c62972019-07-17 11:07:49 +01003819 descriptor.m_ProjectionEnabled = true;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003820 descriptor.m_PeepholeEnabled = true;
Jan Eilersf8c62972019-07-17 11:07:49 +01003821
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003822 const uint32_t batchSize = 2u;
3823 const uint32_t inputSize = 5u;
3824 const uint32_t numUnits = 20u;
3825 const uint32_t outputSize = 16u;
Jan Eilersf8c62972019-07-17 11:07:49 +01003826
3827 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3828 std::vector<float> inputToInputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3829 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3830
3831 std::vector<float> inputToForgetWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3832 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3833
3834 std::vector<float> inputToCellWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3835 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3836
3837 std::vector<float> inputToOutputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3838 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3839
3840 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3841 std::vector<float> inputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3842 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3843
3844 std::vector<float> forgetGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3845 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3846
3847 std::vector<float> cellBiasData(tensorInfo20.GetNumElements(), 0.0f);
3848 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3849
3850 std::vector<float> outputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3851 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3852
3853 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3854 std::vector<float> recurrentToInputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3855 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3856
3857 std::vector<float> recurrentToForgetWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3858 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3859
3860 std::vector<float> recurrentToCellWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3861 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3862
3863 std::vector<float> recurrentToOutputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3864 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3865
3866 std::vector<float> cellToInputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
3867 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3868
3869 std::vector<float> cellToForgetWeightsData(tensorInfo20.GetNumElements(), 0.0f);
3870 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3871
3872 std::vector<float> cellToOutputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
3873 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3874
3875 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3876 std::vector<float> projectionWeightsData(tensorInfo16x20.GetNumElements(), 0.0f);
3877 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3878
3879 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3880 std::vector<float> projectionBiasData(outputSize, 0.0f);
3881 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3882
3883 armnn::LstmInputParams params;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003884 params.m_InputToForgetWeights = &inputToForgetWeights;
3885 params.m_InputToCellWeights = &inputToCellWeights;
3886 params.m_InputToOutputWeights = &inputToOutputWeights;
Jan Eilersf8c62972019-07-17 11:07:49 +01003887 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003888 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
Jan Eilersf8c62972019-07-17 11:07:49 +01003889 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003890 params.m_ForgetGateBias = &forgetGateBias;
3891 params.m_CellBias = &cellBias;
3892 params.m_OutputGateBias = &outputGateBias;
Jan Eilersf8c62972019-07-17 11:07:49 +01003893
3894 // additional params because: descriptor.m_CifgEnabled = false
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003895 params.m_InputToInputWeights = &inputToInputWeights;
3896 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3897 params.m_CellToInputWeights = &cellToInputWeights;
3898 params.m_InputGateBias = &inputGateBias;
Jan Eilersf8c62972019-07-17 11:07:49 +01003899
3900 // additional params because: descriptor.m_ProjectionEnabled = true
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003901 params.m_ProjectionWeights = &projectionWeights;
3902 params.m_ProjectionBias = &projectionBias;
Jan Eilersf8c62972019-07-17 11:07:49 +01003903
3904 // additional params because: descriptor.m_PeepholeEnabled = true
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003905 params.m_CellToForgetWeights = &cellToForgetWeights;
3906 params.m_CellToOutputWeights = &cellToOutputWeights;
Jan Eilersf8c62972019-07-17 11:07:49 +01003907
3908 const std::string layerName("lstm");
3909 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3910 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3911 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3912 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3913
Jan Eilersf8c62972019-07-17 11:07:49 +01003914 VerifyLstmLayer checker(
3915 layerName,
3916 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3917 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3918 descriptor,
3919 params);
3920 deserializedNetwork->Accept(checker);
3921}
Jan Eilers5b01a892019-07-23 09:47:43 +01003922class VerifyQuantizedLstmLayer : public LayerVerifierBase
3923{
3924
3925public:
3926 VerifyQuantizedLstmLayer(const std::string& layerName,
3927 const std::vector<armnn::TensorInfo>& inputInfos,
3928 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01003929 const armnn::QuantizedLstmInputParams& inputParams)
3930 : LayerVerifierBase(layerName, inputInfos, outputInfos), m_InputParams(inputParams) {}
Jan Eilers5b01a892019-07-23 09:47:43 +01003931
3932 void VisitQuantizedLstmLayer(const armnn::IConnectableLayer* layer,
3933 const armnn::QuantizedLstmInputParams& params,
3934 const char* name)
3935 {
3936 VerifyNameAndConnections(layer, name);
3937 VerifyInputParameters(params);
3938 }
3939
3940protected:
3941 void VerifyInputParameters(const armnn::QuantizedLstmInputParams& params)
3942 {
3943 VerifyConstTensors("m_InputToInputWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003944 m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003945 VerifyConstTensors("m_InputToForgetWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003946 m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003947 VerifyConstTensors("m_InputToCellWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003948 m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003949 VerifyConstTensors("m_InputToOutputWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003950 m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003951 VerifyConstTensors("m_RecurrentToInputWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003952 m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003953 VerifyConstTensors("m_RecurrentToForgetWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003954 m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003955 VerifyConstTensors("m_RecurrentToCellWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003956 m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003957 VerifyConstTensors("m_RecurrentToOutputWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003958 m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003959 VerifyConstTensors("m_InputGateBias",
alanhsu567886324fc2019-10-25 23:44:16 +08003960 m_InputParams.m_InputGateBias, params.m_InputGateBias);
Jan Eilers5b01a892019-07-23 09:47:43 +01003961 VerifyConstTensors("m_ForgetGateBias",
alanhsu567886324fc2019-10-25 23:44:16 +08003962 m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
Jan Eilers5b01a892019-07-23 09:47:43 +01003963 VerifyConstTensors("m_CellBias",
alanhsu567886324fc2019-10-25 23:44:16 +08003964 m_InputParams.m_CellBias, params.m_CellBias);
Jan Eilers5b01a892019-07-23 09:47:43 +01003965 VerifyConstTensors("m_OutputGateBias",
alanhsu567886324fc2019-10-25 23:44:16 +08003966 m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
Jan Eilers5b01a892019-07-23 09:47:43 +01003967 }
3968
3969private:
3970 armnn::QuantizedLstmInputParams m_InputParams;
3971};
3972
3973BOOST_AUTO_TEST_CASE(SerializeDeserializeQuantizedLstm)
3974{
3975 const uint32_t batchSize = 1;
3976 const uint32_t inputSize = 2;
3977 const uint32_t numUnits = 4;
3978 const uint32_t outputSize = numUnits;
3979
alanhsu567886324fc2019-10-25 23:44:16 +08003980 // Scale/Offset for input/output, cellState In/Out, weights, bias
3981 float inputOutputScale = 0.0078125f;
3982 int32_t inputOutputOffset = 128;
Jan Eilers5b01a892019-07-23 09:47:43 +01003983
alanhsu567886324fc2019-10-25 23:44:16 +08003984 float cellStateScale = 0.00048828125f;
3985 int32_t cellStateOffset = 0;
Jan Eilers5b01a892019-07-23 09:47:43 +01003986
alanhsu567886324fc2019-10-25 23:44:16 +08003987 float weightsScale = 0.00408021f;
3988 int32_t weightsOffset = 100;
Jan Eilers5b01a892019-07-23 09:47:43 +01003989
alanhsu567886324fc2019-10-25 23:44:16 +08003990 float biasScale = 3.1876640625e-05f;
3991 int32_t biasOffset = 0;
Jan Eilers5b01a892019-07-23 09:47:43 +01003992
alanhsu567886324fc2019-10-25 23:44:16 +08003993 // The shape of weight data is {outputSize, inputSize} = {4, 2}
3994 armnn::TensorShape inputToInputWeightsShape = {4, 2};
3995 std::vector<uint8_t> inputToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
3996 armnn::TensorInfo inputToInputWeightsInfo(inputToInputWeightsShape,
3997 armnn::DataType::QuantisedAsymm8,
3998 weightsScale,
3999 weightsOffset);
4000 armnn::ConstTensor inputToInputWeights(inputToInputWeightsInfo, inputToInputWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004001
alanhsu567886324fc2019-10-25 23:44:16 +08004002 armnn::TensorShape inputToForgetWeightsShape = {4, 2};
4003 std::vector<uint8_t> inputToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4004 armnn::TensorInfo inputToForgetWeightsInfo(inputToForgetWeightsShape,
4005 armnn::DataType::QuantisedAsymm8,
4006 weightsScale,
4007 weightsOffset);
4008 armnn::ConstTensor inputToForgetWeights(inputToForgetWeightsInfo, inputToForgetWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004009
alanhsu567886324fc2019-10-25 23:44:16 +08004010 armnn::TensorShape inputToCellWeightsShape = {4, 2};
4011 std::vector<uint8_t> inputToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4012 armnn::TensorInfo inputToCellWeightsInfo(inputToCellWeightsShape,
4013 armnn::DataType::QuantisedAsymm8,
4014 weightsScale,
4015 weightsOffset);
4016 armnn::ConstTensor inputToCellWeights(inputToCellWeightsInfo, inputToCellWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004017
alanhsu567886324fc2019-10-25 23:44:16 +08004018 armnn::TensorShape inputToOutputWeightsShape = {4, 2};
4019 std::vector<uint8_t> inputToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4020 armnn::TensorInfo inputToOutputWeightsInfo(inputToOutputWeightsShape,
4021 armnn::DataType::QuantisedAsymm8,
4022 weightsScale,
4023 weightsOffset);
4024 armnn::ConstTensor inputToOutputWeights(inputToOutputWeightsInfo, inputToOutputWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004025
alanhsu567886324fc2019-10-25 23:44:16 +08004026 // The shape of recurrent weight data is {outputSize, outputSize} = {4, 4}
4027 armnn::TensorShape recurrentToInputWeightsShape = {4, 4};
4028 std::vector<uint8_t> recurrentToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4029 armnn::TensorInfo recurrentToInputWeightsInfo(recurrentToInputWeightsShape,
4030 armnn::DataType::QuantisedAsymm8,
4031 weightsScale,
4032 weightsOffset);
4033 armnn::ConstTensor recurrentToInputWeights(recurrentToInputWeightsInfo, recurrentToInputWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004034
alanhsu567886324fc2019-10-25 23:44:16 +08004035 armnn::TensorShape recurrentToForgetWeightsShape = {4, 4};
4036 std::vector<uint8_t> recurrentToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4037 armnn::TensorInfo recurrentToForgetWeightsInfo(recurrentToForgetWeightsShape,
4038 armnn::DataType::QuantisedAsymm8,
4039 weightsScale,
4040 weightsOffset);
4041 armnn::ConstTensor recurrentToForgetWeights(recurrentToForgetWeightsInfo, recurrentToForgetWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004042
alanhsu567886324fc2019-10-25 23:44:16 +08004043 armnn::TensorShape recurrentToCellWeightsShape = {4, 4};
4044 std::vector<uint8_t> recurrentToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4045 armnn::TensorInfo recurrentToCellWeightsInfo(recurrentToCellWeightsShape,
4046 armnn::DataType::QuantisedAsymm8,
4047 weightsScale,
4048 weightsOffset);
4049 armnn::ConstTensor recurrentToCellWeights(recurrentToCellWeightsInfo, recurrentToCellWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004050
alanhsu567886324fc2019-10-25 23:44:16 +08004051 armnn::TensorShape recurrentToOutputWeightsShape = {4, 4};
4052 std::vector<uint8_t> recurrentToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4053 armnn::TensorInfo recurrentToOutputWeightsInfo(recurrentToOutputWeightsShape,
4054 armnn::DataType::QuantisedAsymm8,
4055 weightsScale,
4056 weightsOffset);
4057 armnn::ConstTensor recurrentToOutputWeights(recurrentToOutputWeightsInfo, recurrentToOutputWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004058
alanhsu567886324fc2019-10-25 23:44:16 +08004059 // The shape of bias data is {outputSize} = {4}
4060 armnn::TensorShape inputGateBiasShape = {4};
4061 std::vector<int32_t> inputGateBiasData = {1, 2, 3, 4};
4062 armnn::TensorInfo inputGateBiasInfo(inputGateBiasShape,
4063 armnn::DataType::Signed32,
4064 biasScale,
4065 biasOffset);
4066 armnn::ConstTensor inputGateBias(inputGateBiasInfo, inputGateBiasData);
4067
4068 armnn::TensorShape forgetGateBiasShape = {4};
4069 std::vector<int32_t> forgetGateBiasData = {1, 2, 3, 4};
4070 armnn::TensorInfo forgetGateBiasInfo(forgetGateBiasShape,
4071 armnn::DataType::Signed32,
4072 biasScale,
4073 biasOffset);
4074 armnn::ConstTensor forgetGateBias(forgetGateBiasInfo, forgetGateBiasData);
4075
4076 armnn::TensorShape cellBiasShape = {4};
4077 std::vector<int32_t> cellBiasData = {1, 2, 3, 4};
4078 armnn::TensorInfo cellBiasInfo(cellBiasShape,
4079 armnn::DataType::Signed32,
4080 biasScale,
4081 biasOffset);
4082 armnn::ConstTensor cellBias(cellBiasInfo, cellBiasData);
4083
4084 armnn::TensorShape outputGateBiasShape = {4};
4085 std::vector<int32_t> outputGateBiasData = {1, 2, 3, 4};
4086 armnn::TensorInfo outputGateBiasInfo(outputGateBiasShape,
4087 armnn::DataType::Signed32,
4088 biasScale,
4089 biasOffset);
4090 armnn::ConstTensor outputGateBias(outputGateBiasInfo, outputGateBiasData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004091
4092 armnn::QuantizedLstmInputParams params;
4093 params.m_InputToInputWeights = &inputToInputWeights;
4094 params.m_InputToForgetWeights = &inputToForgetWeights;
4095 params.m_InputToCellWeights = &inputToCellWeights;
4096 params.m_InputToOutputWeights = &inputToOutputWeights;
4097 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
4098 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4099 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4100 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4101 params.m_InputGateBias = &inputGateBias;
4102 params.m_ForgetGateBias = &forgetGateBias;
4103 params.m_CellBias = &cellBias;
4104 params.m_OutputGateBias = &outputGateBias;
4105
4106 armnn::INetworkPtr network = armnn::INetwork::Create();
alanhsu567886324fc2019-10-25 23:44:16 +08004107 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
Jan Eilers5b01a892019-07-23 09:47:43 +01004108 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
4109 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
4110 const std::string layerName("QuantizedLstm");
4111 armnn::IConnectableLayer* const quantizedLstmLayer = network->AddQuantizedLstmLayer(params, layerName.c_str());
alanhsu567886324fc2019-10-25 23:44:16 +08004112 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(0);
4113 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(1);
Jan Eilers5b01a892019-07-23 09:47:43 +01004114
alanhsu567886324fc2019-10-25 23:44:16 +08004115 // Connect up
4116 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize },
4117 armnn::DataType::QuantisedAsymm8,
4118 inputOutputScale,
4119 inputOutputOffset);
4120 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits },
4121 armnn::DataType::QuantisedSymm16,
4122 cellStateScale,
4123 cellStateOffset);
4124 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize },
4125 armnn::DataType::QuantisedAsymm8,
4126 inputOutputScale,
4127 inputOutputOffset);
Jan Eilers5b01a892019-07-23 09:47:43 +01004128
4129 inputLayer->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(0));
4130 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
4131
4132 cellStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(1));
4133 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
4134
4135 outputStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(2));
4136 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
4137
4138 quantizedLstmLayer->GetOutputSlot(0).Connect(cellStateOut->GetInputSlot(0));
4139 quantizedLstmLayer->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
4140
4141 quantizedLstmLayer->GetOutputSlot(1).Connect(outputLayer->GetInputSlot(0));
4142 quantizedLstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
4143
4144 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
4145 BOOST_CHECK(deserializedNetwork);
4146
alanhsu567886324fc2019-10-25 23:44:16 +08004147 VerifyQuantizedLstmLayer checker(layerName,
4148 {inputTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
4149 {cellStateTensorInfo, outputStateTensorInfo},
4150 params);
Jan Eilers5b01a892019-07-23 09:47:43 +01004151
4152 deserializedNetwork->Accept(checker);
4153}
4154
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00004155BOOST_AUTO_TEST_SUITE_END()