blob: bbd5402c7cbe247675e14ec2d96ba4312c52c7e4 [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
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000022struct DefaultLayerVerifierPolicy
23{
Les Belle0ca8612019-05-17 16:17:12 +010024 static void Apply(const std::string s = "")
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000025 {
26 BOOST_TEST_MESSAGE("Unexpected layer found in network");
27 BOOST_TEST(false);
28 }
29};
30
31class LayerVerifierBase : public armnn::LayerVisitorBase<DefaultLayerVerifierPolicy>
32{
33public:
34 LayerVerifierBase(const std::string& layerName,
35 const std::vector<armnn::TensorInfo>& inputInfos,
36 const std::vector<armnn::TensorInfo>& outputInfos)
37 : m_LayerName(layerName)
38 , m_InputTensorInfos(inputInfos)
39 , m_OutputTensorInfos(outputInfos) {}
40
41 void VisitInputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId, const char*) override {}
42
43 void VisitOutputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId id, const char*) override {}
44
45protected:
46 void VerifyNameAndConnections(const armnn::IConnectableLayer* layer, const char* name)
47 {
48 BOOST_TEST(name == m_LayerName.c_str());
49
50 BOOST_TEST(layer->GetNumInputSlots() == m_InputTensorInfos.size());
51 BOOST_TEST(layer->GetNumOutputSlots() == m_OutputTensorInfos.size());
52
53 for (unsigned int i = 0; i < m_InputTensorInfos.size(); i++)
54 {
55 const armnn::IOutputSlot* connectedOutput = layer->GetInputSlot(i).GetConnection();
56 BOOST_CHECK(connectedOutput);
57
58 const armnn::TensorInfo& connectedInfo = connectedOutput->GetTensorInfo();
59 BOOST_TEST(connectedInfo.GetShape() == m_InputTensorInfos[i].GetShape());
60 BOOST_TEST(
61 GetDataTypeName(connectedInfo.GetDataType()) == GetDataTypeName(m_InputTensorInfos[i].GetDataType()));
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +000062
63 BOOST_TEST(connectedInfo.GetQuantizationScale() == m_InputTensorInfos[i].GetQuantizationScale());
64 BOOST_TEST(connectedInfo.GetQuantizationOffset() == m_InputTensorInfos[i].GetQuantizationOffset());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000065 }
66
67 for (unsigned int i = 0; i < m_OutputTensorInfos.size(); i++)
68 {
69 const armnn::TensorInfo& outputInfo = layer->GetOutputSlot(i).GetTensorInfo();
70 BOOST_TEST(outputInfo.GetShape() == m_OutputTensorInfos[i].GetShape());
71 BOOST_TEST(
72 GetDataTypeName(outputInfo.GetDataType()) == GetDataTypeName(m_OutputTensorInfos[i].GetDataType()));
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +000073
74 BOOST_TEST(outputInfo.GetQuantizationScale() == m_OutputTensorInfos[i].GetQuantizationScale());
75 BOOST_TEST(outputInfo.GetQuantizationOffset() == m_OutputTensorInfos[i].GetQuantizationOffset());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000076 }
77 }
78
Jan Eilers5b01a892019-07-23 09:47:43 +010079 void VerifyConstTensors(const std::string& tensorName,
80 const armnn::ConstTensor* expectedPtr,
81 const armnn::ConstTensor* actualPtr)
82 {
83 if (expectedPtr == nullptr)
84 {
85 BOOST_CHECK_MESSAGE(actualPtr == nullptr, tensorName + " should not exist");
86 }
87 else
88 {
89 BOOST_CHECK_MESSAGE(actualPtr != nullptr, tensorName + " should have been set");
90 if (actualPtr != nullptr)
91 {
92 const armnn::TensorInfo& expectedInfo = expectedPtr->GetInfo();
93 const armnn::TensorInfo& actualInfo = actualPtr->GetInfo();
94
95 BOOST_CHECK_MESSAGE(expectedInfo.GetShape() == actualInfo.GetShape(),
96 tensorName + " shapes don't match");
97 BOOST_CHECK_MESSAGE(
98 GetDataTypeName(expectedInfo.GetDataType()) == GetDataTypeName(actualInfo.GetDataType()),
99 tensorName + " data types don't match");
100
101 BOOST_CHECK_MESSAGE(expectedPtr->GetNumBytes() == actualPtr->GetNumBytes(),
102 tensorName + " (GetNumBytes) data sizes do not match");
103 if (expectedPtr->GetNumBytes() == actualPtr->GetNumBytes())
104 {
105 //check the data is identical
106 const char* expectedData = static_cast<const char*>(expectedPtr->GetMemoryArea());
107 const char* actualData = static_cast<const char*>(actualPtr->GetMemoryArea());
108 bool same = true;
109 for (unsigned int i = 0; i < expectedPtr->GetNumBytes(); ++i)
110 {
111 same = expectedData[i] == actualData[i];
112 if (!same)
113 {
114 break;
115 }
116 }
117 BOOST_CHECK_MESSAGE(same, tensorName + " data does not match");
118 }
119 }
120 }
121 }
122
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000123private:
124 std::string m_LayerName;
125 std::vector<armnn::TensorInfo> m_InputTensorInfos;
126 std::vector<armnn::TensorInfo> m_OutputTensorInfos;
127};
128
129template<typename T>
130void CompareConstTensorData(const void* data1, const void* data2, unsigned int numElements)
131{
132 T typedData1 = static_cast<T>(data1);
133 T typedData2 = static_cast<T>(data2);
134 BOOST_CHECK(typedData1);
135 BOOST_CHECK(typedData2);
136
137 for (unsigned int i = 0; i < numElements; i++)
138 {
139 BOOST_TEST(typedData1[i] == typedData2[i]);
140 }
141}
142
143void CompareConstTensor(const armnn::ConstTensor& tensor1, const armnn::ConstTensor& tensor2)
144{
145 BOOST_TEST(tensor1.GetShape() == tensor2.GetShape());
146 BOOST_TEST(GetDataTypeName(tensor1.GetDataType()) == GetDataTypeName(tensor2.GetDataType()));
147
148 switch (tensor1.GetDataType())
149 {
150 case armnn::DataType::Float32:
151 CompareConstTensorData<const float*>(
152 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
153 break;
154 case armnn::DataType::QuantisedAsymm8:
155 case armnn::DataType::Boolean:
156 CompareConstTensorData<const uint8_t*>(
157 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
158 break;
159 case armnn::DataType::Signed32:
160 CompareConstTensorData<const int32_t*>(
161 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
162 break;
163 default:
164 // Note that Float16 is not yet implemented
165 BOOST_TEST_MESSAGE("Unexpected datatype");
166 BOOST_TEST(false);
167 }
168}
169
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000170armnn::INetworkPtr DeserializeNetwork(const std::string& serializerString)
171{
172 std::vector<std::uint8_t> const serializerVector{serializerString.begin(), serializerString.end()};
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000173 return IDeserializer::Create()->CreateNetworkFromBinary(serializerVector);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000174}
175
176std::string SerializeNetwork(const armnn::INetwork& network)
177{
178 armnnSerializer::Serializer serializer;
179 serializer.Serialize(network);
180
181 std::stringstream stream;
182 serializer.SaveSerializedToStream(stream);
183
184 std::string serializerString{stream.str()};
185 return serializerString;
186}
187
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000188template<typename DataType>
189static std::vector<DataType> GenerateRandomData(size_t size)
190{
191 constexpr bool isIntegerType = std::is_integral<DataType>::value;
192 using Distribution =
193 typename std::conditional<isIntegerType,
194 std::uniform_int_distribution<DataType>,
195 std::uniform_real_distribution<DataType>>::type;
196
197 static constexpr DataType lowerLimit = std::numeric_limits<DataType>::min();
198 static constexpr DataType upperLimit = std::numeric_limits<DataType>::max();
199
200 static Distribution distribution(lowerLimit, upperLimit);
201 static std::default_random_engine generator;
202
203 std::vector<DataType> randomData(size);
204 std::generate(randomData.begin(), randomData.end(), []() { return distribution(generator); });
205
206 return randomData;
207}
208
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000209} // anonymous namespace
210
211BOOST_AUTO_TEST_SUITE(SerializerTests)
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000212
FinnWilliamsArm4ffcc8f2019-09-05 14:34:20 +0100213BOOST_AUTO_TEST_CASE(SerializeAbs)
214{
215 class AbsLayerVerifier : public LayerVerifierBase
216 {
217 public:
218 AbsLayerVerifier(const std::string& layerName,
219 const std::vector<armnn::TensorInfo>& inputInfos,
220 const std::vector<armnn::TensorInfo>& outputInfos)
221 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
222
223 void VisitAbsLayer(const armnn::IConnectableLayer* layer, const char* name) override
224 {
225 VerifyNameAndConnections(layer, name);
226 }
227 };
228
229 const std::string layerName("abs");
230 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
231
232 armnn::INetworkPtr network = armnn::INetwork::Create();
233 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
234
235 armnn::IConnectableLayer* const absLayer = network->AddAbsLayer(layerName.c_str());
236 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
237
238 inputLayer->GetOutputSlot(0).Connect(absLayer->GetInputSlot(0));
239 absLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
240
241 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
242 absLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
243
244 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
245 BOOST_CHECK(deserializedNetwork);
246
247 AbsLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
248 deserializedNetwork->Accept(verifier);
249}
250
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000251BOOST_AUTO_TEST_CASE(SerializeAddition)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000252{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000253 class AdditionLayerVerifier : public LayerVerifierBase
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000254 {
255 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000256 AdditionLayerVerifier(const std::string& layerName,
257 const std::vector<armnn::TensorInfo>& inputInfos,
258 const std::vector<armnn::TensorInfo>& outputInfos)
259 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
260
261 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name) override
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000262 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000263 VerifyNameAndConnections(layer, name);
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000264 }
265 };
266
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000267 const std::string layerName("addition");
268 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
269
Mike Kelly8c1701a2019-02-11 17:01:27 +0000270 armnn::INetworkPtr network = armnn::INetwork::Create();
271 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
272 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000273 armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer(layerName.c_str());
274 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000275
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000276 inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
277 inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000278 additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Mike Kelly8c1701a2019-02-11 17:01:27 +0000279
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000280 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
281 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
282 additionLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
Jim Flynn3091b062019-02-15 14:45:04 +0000283
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000284 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000285 BOOST_CHECK(deserializedNetwork);
286
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000287 AdditionLayerVerifier verifier(layerName, {tensorInfo, tensorInfo}, {tensorInfo});
288 deserializedNetwork->Accept(verifier);
289}
Jim Flynnac25a1b2019-02-28 10:40:49 +0000290
Narumol Prangnawarat0cfcf232019-09-09 17:16:24 +0100291BOOST_AUTO_TEST_CASE(SerializeArgMinMax)
292{
293 class ArgMinMaxLayerVerifier : public LayerVerifierBase
294 {
295 public:
296 ArgMinMaxLayerVerifier(const std::string& layerName,
297 const std::vector<armnn::TensorInfo>& inputInfos,
298 const std::vector<armnn::TensorInfo>& outputInfos,
299 const armnn::ArgMinMaxDescriptor& descriptor)
300 : LayerVerifierBase(layerName, inputInfos, outputInfos)
301 , m_Descriptor(descriptor) {}
302
303 void VisitArgMinMaxLayer(const armnn::IConnectableLayer* layer,
304 const armnn::ArgMinMaxDescriptor& descriptor,
305 const char* name) override
306 {
307 VerifyNameAndConnections(layer, name);
308 VerifyDescriptor(descriptor);
309 }
310
311 private:
312 void VerifyDescriptor(const armnn::ArgMinMaxDescriptor& descriptor)
313 {
314 BOOST_CHECK(descriptor.m_Function == m_Descriptor.m_Function);
315 BOOST_CHECK(descriptor.m_Axis == m_Descriptor.m_Axis);
316 }
317
318 armnn::ArgMinMaxDescriptor m_Descriptor;
319 };
320
321 const std::string layerName("argminmax");
322 const armnn::TensorInfo inputInfo({1, 2, 3}, armnn::DataType::Float32);
323 const armnn::TensorInfo outputInfo({1, 3}, armnn::DataType::Signed32);
324
325 armnn::ArgMinMaxDescriptor descriptor;
326 descriptor.m_Function = armnn::ArgMinMaxFunction::Max;
327 descriptor.m_Axis = 1;
328
329 armnn::INetworkPtr network = armnn::INetwork::Create();
330 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
331 armnn::IConnectableLayer* const argMinMaxLayer = network->AddArgMinMaxLayer(descriptor, layerName.c_str());
332 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
333
334 inputLayer->GetOutputSlot(0).Connect(argMinMaxLayer->GetInputSlot(0));
335 argMinMaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
336
337 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
338 argMinMaxLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
339
340 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
341 BOOST_CHECK(deserializedNetwork);
342
343 ArgMinMaxLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
344 deserializedNetwork->Accept(verifier);
345}
346
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000347BOOST_AUTO_TEST_CASE(SerializeBatchNormalization)
348{
349 class BatchNormalizationLayerVerifier : public LayerVerifierBase
350 {
351 public:
352 BatchNormalizationLayerVerifier(const std::string& layerName,
353 const std::vector<armnn::TensorInfo>& inputInfos,
354 const std::vector<armnn::TensorInfo>& outputInfos,
355 const armnn::BatchNormalizationDescriptor& descriptor,
356 const armnn::ConstTensor& mean,
357 const armnn::ConstTensor& variance,
358 const armnn::ConstTensor& beta,
359 const armnn::ConstTensor& gamma)
360 : LayerVerifierBase(layerName, inputInfos, outputInfos)
361 , m_Descriptor(descriptor)
362 , m_Mean(mean)
363 , m_Variance(variance)
364 , m_Beta(beta)
365 , m_Gamma(gamma) {}
366
367 void VisitBatchNormalizationLayer(const armnn::IConnectableLayer* layer,
368 const armnn::BatchNormalizationDescriptor& descriptor,
369 const armnn::ConstTensor& mean,
370 const armnn::ConstTensor& variance,
371 const armnn::ConstTensor& beta,
372 const armnn::ConstTensor& gamma,
373 const char* name) override
374 {
375 VerifyNameAndConnections(layer, name);
376 VerifyDescriptor(descriptor);
377
378 CompareConstTensor(mean, m_Mean);
379 CompareConstTensor(variance, m_Variance);
380 CompareConstTensor(beta, m_Beta);
381 CompareConstTensor(gamma, m_Gamma);
382 }
383
384 private:
385 void VerifyDescriptor(const armnn::BatchNormalizationDescriptor& descriptor)
386 {
387 BOOST_TEST(descriptor.m_Eps == m_Descriptor.m_Eps);
388 BOOST_TEST(static_cast<int>(descriptor.m_DataLayout) == static_cast<int>(m_Descriptor.m_DataLayout));
389 }
390
391 armnn::BatchNormalizationDescriptor m_Descriptor;
392 armnn::ConstTensor m_Mean;
393 armnn::ConstTensor m_Variance;
394 armnn::ConstTensor m_Beta;
395 armnn::ConstTensor m_Gamma;
396 };
397
398 const std::string layerName("batchNormalization");
399 const armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32);
400 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
401
402 const armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32);
403 const armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32);
404 const armnn::TensorInfo betaInfo({1}, armnn::DataType::Float32);
405 const armnn::TensorInfo gammaInfo({1}, armnn::DataType::Float32);
406
407 armnn::BatchNormalizationDescriptor descriptor;
408 descriptor.m_Eps = 0.0010000000475f;
409 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
410
411 std::vector<float> meanData({5.0});
412 std::vector<float> varianceData({2.0});
413 std::vector<float> betaData({1.0});
414 std::vector<float> gammaData({0.0});
415
416 armnn::ConstTensor mean(meanInfo, meanData);
417 armnn::ConstTensor variance(varianceInfo, varianceData);
418 armnn::ConstTensor beta(betaInfo, betaData);
419 armnn::ConstTensor gamma(gammaInfo, gammaData);
420
421 armnn::INetworkPtr network = armnn::INetwork::Create();
422 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
423 armnn::IConnectableLayer* const batchNormalizationLayer =
424 network->AddBatchNormalizationLayer(descriptor, mean, variance, beta, gamma, layerName.c_str());
425 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
426
427 inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0));
428 batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
429
430 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
431 batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
432
433 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
434 BOOST_CHECK(deserializedNetwork);
435
436 BatchNormalizationLayerVerifier verifier(
437 layerName, {inputInfo}, {outputInfo}, descriptor, mean, variance, beta, gamma);
438 deserializedNetwork->Accept(verifier);
439}
440
441BOOST_AUTO_TEST_CASE(SerializeBatchToSpaceNd)
442{
443 class BatchToSpaceNdLayerVerifier : public LayerVerifierBase
444 {
445 public:
446 BatchToSpaceNdLayerVerifier(const std::string& layerName,
447 const std::vector<armnn::TensorInfo>& inputInfos,
448 const std::vector<armnn::TensorInfo>& outputInfos,
449 const armnn::BatchToSpaceNdDescriptor& descriptor)
450 : LayerVerifierBase(layerName, inputInfos, outputInfos)
451 , m_Descriptor(descriptor) {}
452
453 void VisitBatchToSpaceNdLayer(const armnn::IConnectableLayer* layer,
454 const armnn::BatchToSpaceNdDescriptor& descriptor,
455 const char* name) override
456 {
457 VerifyNameAndConnections(layer, name);
458 VerifyDescriptor(descriptor);
459 }
460
461 private:
462 void VerifyDescriptor(const armnn::BatchToSpaceNdDescriptor& descriptor)
463 {
464 BOOST_TEST(descriptor.m_Crops == m_Descriptor.m_Crops);
465 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
466 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
467 }
468
469 armnn::BatchToSpaceNdDescriptor m_Descriptor;
470 };
471
472 const std::string layerName("spaceToBatchNd");
473 const armnn::TensorInfo inputInfo({4, 1, 2, 2}, armnn::DataType::Float32);
474 const armnn::TensorInfo outputInfo({1, 1, 4, 4}, armnn::DataType::Float32);
475
476 armnn::BatchToSpaceNdDescriptor desc;
477 desc.m_DataLayout = armnn::DataLayout::NCHW;
478 desc.m_BlockShape = {2, 2};
479 desc.m_Crops = {{0, 0}, {0, 0}};
480
481 armnn::INetworkPtr network = armnn::INetwork::Create();
482 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
483 armnn::IConnectableLayer* const batchToSpaceNdLayer = network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
484 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
485
486 inputLayer->GetOutputSlot(0).Connect(batchToSpaceNdLayer->GetInputSlot(0));
487 batchToSpaceNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
488
489 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
490 batchToSpaceNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
491
492 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
493 BOOST_CHECK(deserializedNetwork);
494
495 BatchToSpaceNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
496 deserializedNetwork->Accept(verifier);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000497}
498
Conor Kennedy76277882019-02-26 08:29:54 +0000499BOOST_AUTO_TEST_CASE(SerializeConstant)
500{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000501 class ConstantLayerVerifier : public LayerVerifierBase
Conor Kennedy76277882019-02-26 08:29:54 +0000502 {
503 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000504 ConstantLayerVerifier(const std::string& layerName,
505 const std::vector<armnn::TensorInfo>& inputInfos,
506 const std::vector<armnn::TensorInfo>& outputInfos,
507 const armnn::ConstTensor& layerInput)
508 : LayerVerifierBase(layerName, inputInfos, outputInfos)
509 , m_LayerInput(layerInput) {}
510
511 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
512 const armnn::ConstTensor& input,
513 const char* name) override
Conor Kennedy76277882019-02-26 08:29:54 +0000514 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000515 VerifyNameAndConnections(layer, name);
516
517 CompareConstTensor(input, m_LayerInput);
Conor Kennedy76277882019-02-26 08:29:54 +0000518 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000519
520 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
521
522 private:
523 armnn::ConstTensor m_LayerInput;
Conor Kennedy76277882019-02-26 08:29:54 +0000524 };
525
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000526 const std::string layerName("constant");
527 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
Conor Kennedy76277882019-02-26 08:29:54 +0000528
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000529 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
530 armnn::ConstTensor constTensor(info, constantData);
Conor Kennedy76277882019-02-26 08:29:54 +0000531
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000532 armnn::INetworkPtr network(armnn::INetwork::Create());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000533 armnn::IConnectableLayer* input = network->AddInputLayer(0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000534 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000535 armnn::IConnectableLayer* add = network->AddAdditionLayer();
536 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
Conor Kennedy76277882019-02-26 08:29:54 +0000537
538 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
539 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
540 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
541
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000542 input->GetOutputSlot(0).SetTensorInfo(info);
543 constant->GetOutputSlot(0).SetTensorInfo(info);
544 add->GetOutputSlot(0).SetTensorInfo(info);
Conor Kennedy76277882019-02-26 08:29:54 +0000545
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000546 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Conor Kennedy76277882019-02-26 08:29:54 +0000547 BOOST_CHECK(deserializedNetwork);
548
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000549 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
550 deserializedNetwork->Accept(verifier);
Conor Kennedy76277882019-02-26 08:29:54 +0000551}
552
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000553BOOST_AUTO_TEST_CASE(SerializeConvolution2d)
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000554{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000555 class Convolution2dLayerVerifier : public LayerVerifierBase
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000556 {
557 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000558 Convolution2dLayerVerifier(const std::string& layerName,
559 const std::vector<armnn::TensorInfo>& inputInfos,
560 const std::vector<armnn::TensorInfo>& outputInfos,
561 const armnn::Convolution2dDescriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100562 const armnn::ConstTensor& weights,
563 const armnn::Optional<armnn::ConstTensor>& biases) :
564 LayerVerifierBase(layerName, inputInfos, outputInfos),
565 m_Descriptor(descriptor),
566 m_Weights(weights),
567 m_Biases(biases)
568 {}
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000569
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000570 void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
571 const armnn::Convolution2dDescriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100572 const armnn::ConstTensor& weights,
573 const armnn::Optional<armnn::ConstTensor>& biases,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000574 const char* name) override
575 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000576 VerifyNameAndConnections(layer, name);
577 VerifyDescriptor(descriptor);
578
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100579 // check weights
580 CompareConstTensor(weights, m_Weights);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000581
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100582 // check biases
583 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
584 BOOST_CHECK(m_Biases.has_value() == m_Descriptor.m_BiasEnabled);
585
586 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
587
588 if (biases.has_value() && m_Biases.has_value())
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000589 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100590 CompareConstTensor(biases.value(), m_Biases.value());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000591 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000592 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000593
594 private:
595 void VerifyDescriptor(const armnn::Convolution2dDescriptor& descriptor)
596 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100597 BOOST_CHECK(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
598 BOOST_CHECK(descriptor.m_PadRight == m_Descriptor.m_PadRight);
599 BOOST_CHECK(descriptor.m_PadTop == m_Descriptor.m_PadTop);
600 BOOST_CHECK(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
601 BOOST_CHECK(descriptor.m_StrideX == m_Descriptor.m_StrideX);
602 BOOST_CHECK(descriptor.m_StrideY == m_Descriptor.m_StrideY);
603 BOOST_CHECK(descriptor.m_DilationX == m_Descriptor.m_DilationX);
604 BOOST_CHECK(descriptor.m_DilationY == m_Descriptor.m_DilationY);
605 BOOST_CHECK(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
606 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000607 }
608
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100609 armnn::Convolution2dDescriptor m_Descriptor;
610 armnn::ConstTensor m_Weights;
611 armnn::Optional<armnn::ConstTensor> m_Biases;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000612 };
613
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000614 const std::string layerName("convolution2d");
615 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
616 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000617
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000618 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
619 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000620
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000621 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
622 armnn::ConstTensor weights(weightsInfo, weightsData);
623
624 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
625 armnn::ConstTensor biases(biasesInfo, biasesData);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000626
627 armnn::Convolution2dDescriptor descriptor;
628 descriptor.m_PadLeft = 1;
629 descriptor.m_PadRight = 1;
630 descriptor.m_PadTop = 1;
631 descriptor.m_PadBottom = 1;
632 descriptor.m_StrideX = 2;
633 descriptor.m_StrideY = 2;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100634 descriptor.m_DilationX = 2;
635 descriptor.m_DilationY = 2;
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000636 descriptor.m_BiasEnabled = true;
637 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
638
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000639 armnn::INetworkPtr network = armnn::INetwork::Create();
640 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000641 armnn::IConnectableLayer* const convLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100642 network->AddConvolution2dLayer(descriptor,
643 weights,
644 armnn::Optional<armnn::ConstTensor>(biases),
645 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000646 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000647
648 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000649 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000650
651 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000652 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
653
654 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
655 BOOST_CHECK(deserializedNetwork);
656
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000657 Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
658 deserializedNetwork->Accept(verifier);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000659}
660
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000661BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d)
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000662{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000663 class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBase
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000664 {
665 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000666 DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
667 const std::vector<armnn::TensorInfo>& inputInfos,
668 const std::vector<armnn::TensorInfo>& outputInfos,
669 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100670 const armnn::ConstTensor& weights,
671 const armnn::Optional<armnn::ConstTensor>& biases) :
672 LayerVerifierBase(layerName, inputInfos, outputInfos),
673 m_Descriptor(descriptor),
674 m_Weights(weights),
675 m_Biases(biases)
676 {}
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000677
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000678 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
679 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100680 const armnn::ConstTensor& weights,
681 const armnn::Optional<armnn::ConstTensor>& biases,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000682 const char* name) override
683 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000684 VerifyNameAndConnections(layer, name);
685 VerifyDescriptor(descriptor);
686
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100687 // check weights
688 CompareConstTensor(weights, m_Weights);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000689
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100690 // check biases
691 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
692 BOOST_CHECK(m_Biases.has_value() == m_Descriptor.m_BiasEnabled);
693
694 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
695
696 if (biases.has_value() && m_Biases.has_value())
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000697 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100698 CompareConstTensor(biases.value(), m_Biases.value());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000699 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000700 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000701
702 private:
703 void VerifyDescriptor(const armnn::DepthwiseConvolution2dDescriptor& descriptor)
704 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100705 BOOST_CHECK(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
706 BOOST_CHECK(descriptor.m_PadRight == m_Descriptor.m_PadRight);
707 BOOST_CHECK(descriptor.m_PadTop == m_Descriptor.m_PadTop);
708 BOOST_CHECK(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
709 BOOST_CHECK(descriptor.m_StrideX == m_Descriptor.m_StrideX);
710 BOOST_CHECK(descriptor.m_StrideY == m_Descriptor.m_StrideY);
711 BOOST_CHECK(descriptor.m_DilationX == m_Descriptor.m_DilationX);
712 BOOST_CHECK(descriptor.m_DilationY == m_Descriptor.m_DilationY);
713 BOOST_CHECK(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
714 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000715 }
716
717 armnn::DepthwiseConvolution2dDescriptor m_Descriptor;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100718 armnn::ConstTensor m_Weights;
719 armnn::Optional<armnn::ConstTensor> m_Biases;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000720 };
721
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000722 const std::string layerName("depwiseConvolution2d");
723 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
724 const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000725
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000726 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
727 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000728
729 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
730 armnn::ConstTensor weights(weightsInfo, weightsData);
731
732 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
733 armnn::ConstTensor biases(biasesInfo, biasesData);
734
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000735 armnn::DepthwiseConvolution2dDescriptor descriptor;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100736 descriptor.m_PadLeft = 1;
737 descriptor.m_PadRight = 1;
738 descriptor.m_PadTop = 1;
739 descriptor.m_PadBottom = 1;
740 descriptor.m_StrideX = 2;
741 descriptor.m_StrideY = 2;
742 descriptor.m_DilationX = 2;
743 descriptor.m_DilationY = 2;
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000744 descriptor.m_BiasEnabled = true;
745 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
746
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000747 armnn::INetworkPtr network = armnn::INetwork::Create();
748 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
749 armnn::IConnectableLayer* const depthwiseConvLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100750 network->AddDepthwiseConvolution2dLayer(descriptor,
751 weights,
752 armnn::Optional<armnn::ConstTensor>(biases),
753 layerName.c_str());
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000754 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
755
756 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000757 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000758
759 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000760 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
761
762 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
763 BOOST_CHECK(deserializedNetwork);
764
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000765 DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
766 deserializedNetwork->Accept(verifier);
Jim Flynn18ce3382019-03-08 11:08:30 +0000767}
768
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000769BOOST_AUTO_TEST_CASE(SerializeDequantize)
770{
771 class DequantizeLayerVerifier : public LayerVerifierBase
772 {
773 public:
774 DequantizeLayerVerifier(const std::string& layerName,
775 const std::vector<armnn::TensorInfo>& inputInfos,
776 const std::vector<armnn::TensorInfo>& outputInfos)
777 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
778
779 void VisitDequantizeLayer(const armnn::IConnectableLayer* layer, const char* name) override
780 {
781 VerifyNameAndConnections(layer, name);
782 }
783 };
784
785 const std::string layerName("dequantize");
786 const armnn::TensorInfo inputInfo({ 1, 5, 2, 3 }, armnn::DataType::QuantisedAsymm8, 0.5f, 1);
787 const armnn::TensorInfo outputInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
788
789 armnn::INetworkPtr network = armnn::INetwork::Create();
790 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
791 armnn::IConnectableLayer* const dequantizeLayer = network->AddDequantizeLayer(layerName.c_str());
792 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
793
794 inputLayer->GetOutputSlot(0).Connect(dequantizeLayer->GetInputSlot(0));
795 dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
796
797 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
798 dequantizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
799
800 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
801 BOOST_CHECK(deserializedNetwork);
802
803 DequantizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
804 deserializedNetwork->Accept(verifier);
805}
806
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000807BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess)
808{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000809 class DetectionPostProcessLayerVerifier : public LayerVerifierBase
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000810 {
811 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000812 DetectionPostProcessLayerVerifier(const std::string& layerName,
813 const std::vector<armnn::TensorInfo>& inputInfos,
814 const std::vector<armnn::TensorInfo>& outputInfos,
815 const armnn::DetectionPostProcessDescriptor& descriptor,
816 const armnn::ConstTensor& anchors)
817 : LayerVerifierBase(layerName, inputInfos, outputInfos)
818 , m_Descriptor(descriptor)
819 , m_Anchors(anchors) {}
820
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000821 void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
822 const armnn::DetectionPostProcessDescriptor& descriptor,
823 const armnn::ConstTensor& anchors,
824 const char* name) override
825 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000826 VerifyNameAndConnections(layer, name);
827 VerifyDescriptor(descriptor);
828
829 CompareConstTensor(anchors, m_Anchors);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000830 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000831
832 private:
833 void VerifyDescriptor(const armnn::DetectionPostProcessDescriptor& descriptor)
834 {
835 BOOST_TEST(descriptor.m_UseRegularNms == m_Descriptor.m_UseRegularNms);
836 BOOST_TEST(descriptor.m_MaxDetections == m_Descriptor.m_MaxDetections);
837 BOOST_TEST(descriptor.m_MaxClassesPerDetection == m_Descriptor.m_MaxClassesPerDetection);
838 BOOST_TEST(descriptor.m_DetectionsPerClass == m_Descriptor.m_DetectionsPerClass);
839 BOOST_TEST(descriptor.m_NmsScoreThreshold == m_Descriptor.m_NmsScoreThreshold);
840 BOOST_TEST(descriptor.m_NmsIouThreshold == m_Descriptor.m_NmsIouThreshold);
841 BOOST_TEST(descriptor.m_NumClasses == m_Descriptor.m_NumClasses);
842 BOOST_TEST(descriptor.m_ScaleY == m_Descriptor.m_ScaleY);
843 BOOST_TEST(descriptor.m_ScaleX == m_Descriptor.m_ScaleX);
844 BOOST_TEST(descriptor.m_ScaleH == m_Descriptor.m_ScaleH);
845 BOOST_TEST(descriptor.m_ScaleW == m_Descriptor.m_ScaleW);
846 }
847
848 armnn::DetectionPostProcessDescriptor m_Descriptor;
849 armnn::ConstTensor m_Anchors;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000850 };
851
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000852 const std::string layerName("detectionPostProcess");
853
854 const std::vector<armnn::TensorInfo> inputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000855 armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32),
856 armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000857 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000858
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000859 const std::vector<armnn::TensorInfo> outputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000860 armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32),
861 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
862 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
863 armnn::TensorInfo({ 1 }, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000864 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000865
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000866 armnn::DetectionPostProcessDescriptor descriptor;
867 descriptor.m_UseRegularNms = true;
868 descriptor.m_MaxDetections = 3;
869 descriptor.m_MaxClassesPerDetection = 1;
870 descriptor.m_DetectionsPerClass =1;
871 descriptor.m_NmsScoreThreshold = 0.0;
872 descriptor.m_NmsIouThreshold = 0.5;
873 descriptor.m_NumClasses = 2;
874 descriptor.m_ScaleY = 10.0;
875 descriptor.m_ScaleX = 10.0;
876 descriptor.m_ScaleH = 5.0;
877 descriptor.m_ScaleW = 5.0;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000878
879 const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
880 const std::vector<float> anchorsData({
881 0.5f, 0.5f, 1.0f, 1.0f,
882 0.5f, 0.5f, 1.0f, 1.0f,
883 0.5f, 0.5f, 1.0f, 1.0f,
884 0.5f, 10.5f, 1.0f, 1.0f,
885 0.5f, 10.5f, 1.0f, 1.0f,
886 0.5f, 100.5f, 1.0f, 1.0f
887 });
888 armnn::ConstTensor anchors(anchorsInfo, anchorsData);
889
890 armnn::INetworkPtr network = armnn::INetwork::Create();
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000891 armnn::IConnectableLayer* const detectionLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000892 network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000893
894 for (unsigned int i = 0; i < 2; i++)
895 {
896 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
897 inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
898 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
899 }
900
901 for (unsigned int i = 0; i < 4; i++)
902 {
903 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
904 detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
905 detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
906 }
907
908 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
909 BOOST_CHECK(deserializedNetwork);
910
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000911 DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors);
912 deserializedNetwork->Accept(verifier);
913}
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000914
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000915BOOST_AUTO_TEST_CASE(SerializeDivision)
916{
917 class DivisionLayerVerifier : public LayerVerifierBase
918 {
919 public:
920 DivisionLayerVerifier(const std::string& layerName,
921 const std::vector<armnn::TensorInfo>& inputInfos,
922 const std::vector<armnn::TensorInfo>& outputInfos)
923 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
924
925 void VisitDivisionLayer(const armnn::IConnectableLayer* layer, const char* name) override
926 {
927 VerifyNameAndConnections(layer, name);
928 }
929 };
930
931 const std::string layerName("division");
932 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
933
934 armnn::INetworkPtr network = armnn::INetwork::Create();
935 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
936 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
937 armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
938 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
939
940 inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
941 inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
942 divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
943
944 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
945 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
946 divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
947
948 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
949 BOOST_CHECK(deserializedNetwork);
950
951 DivisionLayerVerifier verifier(layerName, {info, info}, {info});
952 deserializedNetwork->Accept(verifier);
953}
954
955BOOST_AUTO_TEST_CASE(SerializeEqual)
956{
957 class EqualLayerVerifier : public LayerVerifierBase
958 {
959 public:
960 EqualLayerVerifier(const std::string& layerName,
961 const std::vector<armnn::TensorInfo>& inputInfos,
962 const std::vector<armnn::TensorInfo>& outputInfos)
963 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
964
965 void VisitEqualLayer(const armnn::IConnectableLayer* layer, const char* name) override
966 {
967 VerifyNameAndConnections(layer, name);
968 }
969 };
970
971 const std::string layerName("equal");
972 const armnn::TensorInfo inputTensorInfo1 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
973 const armnn::TensorInfo inputTensorInfo2 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
974 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Boolean);
975
976 armnn::INetworkPtr network = armnn::INetwork::Create();
977 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
978 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
979 armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str());
980 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
981
982 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
983 inputLayer2->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
984 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
985
986 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
987 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
988 equalLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
989
990 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
991 BOOST_CHECK(deserializedNetwork);
992
993 EqualLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
994 deserializedNetwork->Accept(verifier);
995}
996
997BOOST_AUTO_TEST_CASE(SerializeFloor)
998{
999 class FloorLayerVerifier : public LayerVerifierBase
1000 {
1001 public:
1002 FloorLayerVerifier(const std::string& layerName,
1003 const std::vector<armnn::TensorInfo>& inputInfos,
1004 const std::vector<armnn::TensorInfo>& outputInfos)
1005 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1006
1007 void VisitFloorLayer(const armnn::IConnectableLayer* layer, const char* name) override
1008 {
1009 VerifyNameAndConnections(layer, name);
1010 }
1011 };
1012
1013 const std::string layerName("floor");
1014 const armnn::TensorInfo info({4,4}, armnn::DataType::Float32);
1015
1016 armnn::INetworkPtr network = armnn::INetwork::Create();
1017 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1018 armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
1019 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1020
1021 inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
1022 floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1023
1024 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1025 floorLayer->GetOutputSlot(0).SetTensorInfo(info);
1026
1027 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1028 BOOST_CHECK(deserializedNetwork);
1029
1030 FloorLayerVerifier verifier(layerName, {info}, {info});
1031 deserializedNetwork->Accept(verifier);
1032}
1033
1034BOOST_AUTO_TEST_CASE(SerializeFullyConnected)
1035{
1036 class FullyConnectedLayerVerifier : public LayerVerifierBase
1037 {
1038 public:
1039 FullyConnectedLayerVerifier(const std::string& layerName,
1040 const std::vector<armnn::TensorInfo>& inputInfos,
1041 const std::vector<armnn::TensorInfo>& outputInfos,
1042 const armnn::FullyConnectedDescriptor& descriptor,
1043 const armnn::ConstTensor& weight,
1044 const armnn::Optional<armnn::ConstTensor>& bias)
1045 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1046 , m_Descriptor(descriptor)
1047 , m_Weight(weight)
1048 , m_Bias(bias) {}
1049
1050 void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
1051 const armnn::FullyConnectedDescriptor& descriptor,
1052 const armnn::ConstTensor& weight,
1053 const armnn::Optional<armnn::ConstTensor>& bias,
1054 const char* name) override
1055 {
1056 VerifyNameAndConnections(layer, name);
1057 VerifyDescriptor(descriptor);
1058
1059 CompareConstTensor(weight, m_Weight);
1060
1061 BOOST_TEST(bias.has_value() == m_Bias.has_value());
1062 if (bias.has_value() && m_Bias.has_value())
1063 {
1064 CompareConstTensor(bias.value(), m_Bias.value());
1065 }
1066 }
1067
1068 private:
1069 void VerifyDescriptor(const armnn::FullyConnectedDescriptor& descriptor)
1070 {
1071 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
1072 BOOST_TEST(descriptor.m_TransposeWeightMatrix == m_Descriptor.m_TransposeWeightMatrix);
1073 }
1074
1075 armnn::FullyConnectedDescriptor m_Descriptor;
1076 armnn::ConstTensor m_Weight;
1077 armnn::Optional<armnn::ConstTensor> m_Bias;
1078 };
1079
1080 const std::string layerName("fullyConnected");
1081 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
1082 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
1083
1084 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
1085 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
1086 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
1087 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
1088 armnn::ConstTensor weights(weightsInfo, weightsData);
1089 armnn::ConstTensor biases(biasesInfo, biasesData);
1090
1091 armnn::FullyConnectedDescriptor descriptor;
1092 descriptor.m_BiasEnabled = true;
1093 descriptor.m_TransposeWeightMatrix = false;
1094
1095 armnn::INetworkPtr network = armnn::INetwork::Create();
1096 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1097 armnn::IConnectableLayer* const fullyConnectedLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +01001098 network->AddFullyConnectedLayer(descriptor,
1099 weights,
1100 armnn::Optional<armnn::ConstTensor>(biases),
1101 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001102 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1103
1104 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
1105 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1106
1107 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1108 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1109
1110 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1111 BOOST_CHECK(deserializedNetwork);
1112
1113 FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
1114 deserializedNetwork->Accept(verifier);
1115}
1116
1117BOOST_AUTO_TEST_CASE(SerializeGather)
1118{
1119 class GatherLayerVerifier : public LayerVerifierBase
1120 {
1121 public:
1122 GatherLayerVerifier(const std::string& layerName,
1123 const std::vector<armnn::TensorInfo>& inputInfos,
1124 const std::vector<armnn::TensorInfo>& outputInfos)
1125 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1126
1127 void VisitGatherLayer(const armnn::IConnectableLayer* layer, const char *name) override
1128 {
1129 VerifyNameAndConnections(layer, name);
1130 }
1131
1132 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
1133 const armnn::ConstTensor& input,
1134 const char *name) override {}
1135 };
1136
1137 const std::string layerName("gather");
1138 armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QuantisedAsymm8);
1139 armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QuantisedAsymm8);
1140 const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
1141
1142 paramsInfo.SetQuantizationScale(1.0f);
1143 paramsInfo.SetQuantizationOffset(0);
1144 outputInfo.SetQuantizationScale(1.0f);
1145 outputInfo.SetQuantizationOffset(0);
1146
1147 const std::vector<int32_t>& indicesData = {7, 6, 5};
1148
1149 armnn::INetworkPtr network = armnn::INetwork::Create();
1150 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
1151 armnn::IConnectableLayer *const constantLayer =
1152 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
1153 armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(layerName.c_str());
1154 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
1155
1156 inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
1157 constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
1158 gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1159
1160 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
1161 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
1162 gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1163
1164 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1165 BOOST_CHECK(deserializedNetwork);
1166
1167 GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo});
1168 deserializedNetwork->Accept(verifier);
1169}
1170
1171BOOST_AUTO_TEST_CASE(SerializeGreater)
1172{
1173 class GreaterLayerVerifier : public LayerVerifierBase
1174 {
1175 public:
1176 GreaterLayerVerifier(const std::string& layerName,
1177 const std::vector<armnn::TensorInfo>& inputInfos,
1178 const std::vector<armnn::TensorInfo>& outputInfos)
1179 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1180
1181 void VisitGreaterLayer(const armnn::IConnectableLayer* layer, const char* name) override
1182 {
1183 VerifyNameAndConnections(layer, name);
1184 }
1185 };
1186
1187 const std::string layerName("greater");
1188 const armnn::TensorInfo inputTensorInfo1({ 1, 2, 2, 2 }, armnn::DataType::Float32);
1189 const armnn::TensorInfo inputTensorInfo2({ 1, 2, 2, 2 }, armnn::DataType::Float32);
1190 const armnn::TensorInfo outputTensorInfo({ 1, 2, 2, 2 }, armnn::DataType::Boolean);
1191
1192 armnn::INetworkPtr network = armnn::INetwork::Create();
1193 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
1194 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
1195 armnn::IConnectableLayer* const greaterLayer = network->AddGreaterLayer(layerName.c_str());
1196 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1197
1198 inputLayer1->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(0));
1199 inputLayer2->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(1));
1200 greaterLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1201
1202 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
1203 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
1204 greaterLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1205
1206 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1207 BOOST_CHECK(deserializedNetwork);
1208
1209 GreaterLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
1210 deserializedNetwork->Accept(verifier);
1211}
1212
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001213class L2NormalizationLayerVerifier : public LayerVerifierBase
1214{
1215public:
1216 L2NormalizationLayerVerifier(const std::string& layerName,
1217 const std::vector<armnn::TensorInfo>& inputInfos,
1218 const std::vector<armnn::TensorInfo>& outputInfos,
1219 const armnn::L2NormalizationDescriptor& descriptor)
1220 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1221 , m_Descriptor(descriptor) {}
1222
1223 void VisitL2NormalizationLayer(const armnn::IConnectableLayer* layer,
1224 const armnn::L2NormalizationDescriptor& descriptor,
1225 const char* name) override
1226 {
1227 VerifyNameAndConnections(layer, name);
1228 VerifyDescriptor(descriptor);
1229 }
1230private:
1231 void VerifyDescriptor(const armnn::L2NormalizationDescriptor& descriptor)
1232 {
1233 BOOST_TEST(descriptor.m_Eps == m_Descriptor.m_Eps);
1234 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1235 }
1236
1237 armnn::L2NormalizationDescriptor m_Descriptor;
1238};
1239
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001240BOOST_AUTO_TEST_CASE(SerializeL2Normalization)
1241{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001242 const std::string l2NormLayerName("l2Normalization");
1243 const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1244
1245 armnn::L2NormalizationDescriptor desc;
1246 desc.m_DataLayout = armnn::DataLayout::NCHW;
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001247 desc.m_Eps = 0.0001f;
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001248
1249 armnn::INetworkPtr network = armnn::INetwork::Create();
1250 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1251 armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1252 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1253
1254 inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1255 l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1256
1257 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1258 l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1259
1260 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1261 BOOST_CHECK(deserializedNetwork);
1262
1263 L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc);
1264 deserializedNetwork->Accept(verifier);
1265}
1266
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001267BOOST_AUTO_TEST_CASE(EnsureL2NormalizationBackwardCompatibility)
1268{
1269 // The hex array below is a flat buffer containing a simple network with one input
1270 // a L2Normalization layer and an output layer with dimensions as per the tensor infos below.
1271 //
1272 // This test verifies that we can still read back these old style
1273 // models without the normalization epsilon value.
1274 unsigned int size = 508;
1275 const unsigned char l2NormalizationModel[] = {
1276 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1277 0x0C,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x3C,0x01,0x00,0x00,
1278 0x74,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1279 0x02,0x00,0x00,0x00,0xE8,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x0B,0x04,0x00,0x00,0x00,0xD6,0xFE,0xFF,0xFF,
1280 0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1281 0x9E,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1282 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
1283 0x00,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0xFF,0xFF,0xFF,
1284 0x00,0x00,0x00,0x20,0x0C,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1285 0x20,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x06,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,
1286 0x18,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,0x0E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1287 0x10,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,
1288 0x6C,0x32,0x4E,0x6F,0x72,0x6D,0x61,0x6C,0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x00,0x01,0x00,0x00,0x00,
1289 0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x04,0x00,
1290 0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x52,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
1291 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1292 0x05,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1293 0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x09,
1294 0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0A,0x00,0x04,0x00,
1295 0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x08,0x00,
1296 0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1297 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1298 0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1299 0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
1300 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1301 0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0 };
1302
1303 std::stringstream ss;
1304 for (unsigned int i = 0; i < size; ++i)
1305 {
1306 ss << l2NormalizationModel[i];
1307 }
1308 std::string l2NormalizationLayerNetwork = ss.str();
1309 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(l2NormalizationLayerNetwork);
1310 BOOST_CHECK(deserializedNetwork);
1311 const std::string layerName("l2Normalization");
1312 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 2, 1, 5}, armnn::DataType::Float32);
1313
1314 armnn::L2NormalizationDescriptor desc;
1315 desc.m_DataLayout = armnn::DataLayout::NCHW;
1316 // Since this variable does not exist in the l2NormalizationModel[] dump, the default value will be loaded.
1317 desc.m_Eps = 1e-12f;
1318
1319 L2NormalizationLayerVerifier verifier(layerName, {inputInfo}, {inputInfo}, desc);
1320 deserializedNetwork->Accept(verifier);
1321}
1322
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001323BOOST_AUTO_TEST_CASE(SerializeMaximum)
1324{
1325 class MaximumLayerVerifier : public LayerVerifierBase
1326 {
1327 public:
1328 MaximumLayerVerifier(const std::string& layerName,
1329 const std::vector<armnn::TensorInfo>& inputInfos,
1330 const std::vector<armnn::TensorInfo>& outputInfos)
1331 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1332
1333 void VisitMaximumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1334 {
1335 VerifyNameAndConnections(layer, name);
1336 }
1337 };
1338
1339 const std::string layerName("maximum");
1340 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1341
1342 armnn::INetworkPtr network = armnn::INetwork::Create();
1343 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1344 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1345 armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1346 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1347
1348 inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1349 inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1350 maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1351
1352 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1353 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1354 maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1355
1356 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1357 BOOST_CHECK(deserializedNetwork);
1358
1359 MaximumLayerVerifier verifier(layerName, {info, info}, {info});
1360 deserializedNetwork->Accept(verifier);
1361}
1362
1363BOOST_AUTO_TEST_CASE(SerializeMean)
1364{
1365 class MeanLayerVerifier : public LayerVerifierBase
1366 {
1367 public:
1368 MeanLayerVerifier(const std::string& layerName,
1369 const std::vector<armnn::TensorInfo>& inputInfos,
1370 const std::vector<armnn::TensorInfo>& outputInfos,
1371 const armnn::MeanDescriptor& descriptor)
1372 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1373 , m_Descriptor(descriptor) {}
1374
1375 void VisitMeanLayer(const armnn::IConnectableLayer* layer,
1376 const armnn::MeanDescriptor& descriptor,
1377 const char* name) override
1378 {
1379 VerifyNameAndConnections(layer, name);
1380 VerifyDescriptor(descriptor);
1381 }
1382
1383 private:
1384 void VerifyDescriptor(const armnn::MeanDescriptor& descriptor)
1385 {
1386 BOOST_TEST(descriptor.m_Axis == m_Descriptor.m_Axis);
1387 BOOST_TEST(descriptor.m_KeepDims == m_Descriptor.m_KeepDims);
1388 }
1389
1390 armnn::MeanDescriptor m_Descriptor;
1391 };
1392
1393 const std::string layerName("mean");
1394 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1395 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1396
1397 armnn::MeanDescriptor descriptor;
1398 descriptor.m_Axis = { 2 };
1399 descriptor.m_KeepDims = true;
1400
1401 armnn::INetworkPtr network = armnn::INetwork::Create();
1402 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1403 armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1404 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1405
1406 inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1407 meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1408
1409 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1410 meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1411
1412 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1413 BOOST_CHECK(deserializedNetwork);
1414
1415 MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1416 deserializedNetwork->Accept(verifier);
1417}
1418
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001419BOOST_AUTO_TEST_CASE(SerializeMerge)
1420{
1421 class MergeLayerVerifier : public LayerVerifierBase
1422 {
1423 public:
1424 MergeLayerVerifier(const std::string& layerName,
1425 const std::vector<armnn::TensorInfo>& inputInfos,
1426 const std::vector<armnn::TensorInfo>& outputInfos)
1427 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1428
1429 void VisitMergeLayer(const armnn::IConnectableLayer* layer, const char* name) override
1430 {
1431 VerifyNameAndConnections(layer, name);
1432 }
1433 };
1434
1435 const std::string layerName("merge");
1436 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1437
1438 armnn::INetworkPtr network = armnn::INetwork::Create();
1439 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1440 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1441 armnn::IConnectableLayer* const mergeLayer = network->AddMergeLayer(layerName.c_str());
1442 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1443
1444 inputLayer0->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(0));
1445 inputLayer1->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(1));
1446 mergeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1447
1448 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1449 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1450 mergeLayer->GetOutputSlot(0).SetTensorInfo(info);
1451
1452 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1453 BOOST_CHECK(deserializedNetwork);
1454
1455 MergeLayerVerifier verifier(layerName, {info, info}, {info});
1456 deserializedNetwork->Accept(verifier);
1457}
1458
Jim Flynn5fa83932019-05-09 15:35:43 +01001459class MergerLayerVerifier : public LayerVerifierBase
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001460{
Jim Flynn5fa83932019-05-09 15:35:43 +01001461public:
1462 MergerLayerVerifier(const std::string& layerName,
1463 const std::vector<armnn::TensorInfo>& inputInfos,
1464 const std::vector<armnn::TensorInfo>& outputInfos,
1465 const armnn::OriginsDescriptor& descriptor)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001466 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1467 , m_Descriptor(descriptor) {}
1468
Jim Flynn5fa83932019-05-09 15:35:43 +01001469 void VisitMergerLayer(const armnn::IConnectableLayer* layer,
1470 const armnn::OriginsDescriptor& descriptor,
1471 const char* name) override
1472 {
Jim Flynne242f2d2019-05-22 14:24:13 +01001473 throw armnn::Exception("MergerLayer should have translated to ConcatLayer");
1474 }
1475
1476 void VisitConcatLayer(const armnn::IConnectableLayer* layer,
1477 const armnn::OriginsDescriptor& descriptor,
1478 const char* name) override
1479 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001480 VerifyNameAndConnections(layer, name);
1481 VerifyDescriptor(descriptor);
1482 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001483
Jim Flynn5fa83932019-05-09 15:35:43 +01001484private:
1485 void VerifyDescriptor(const armnn::OriginsDescriptor& descriptor)
1486 {
1487 BOOST_TEST(descriptor.GetConcatAxis() == m_Descriptor.GetConcatAxis());
1488 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
1489 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001490
Jim Flynn5fa83932019-05-09 15:35:43 +01001491 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
1492 {
1493 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001494 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001495 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001496 }
1497 }
Jim Flynn5fa83932019-05-09 15:35:43 +01001498 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001499
Jim Flynn5fa83932019-05-09 15:35:43 +01001500 armnn::OriginsDescriptor m_Descriptor;
1501};
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001502
Jim Flynne242f2d2019-05-22 14:24:13 +01001503// NOTE: until the deprecated AddMergerLayer disappears this test checks that calling
1504// AddMergerLayer places a ConcatLayer into the serialized format and that
1505// when this deserialises we have a ConcatLayer
Jim Flynn5fa83932019-05-09 15:35:43 +01001506BOOST_AUTO_TEST_CASE(SerializeMerger)
1507{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001508 const std::string layerName("merger");
1509 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1510 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1511
1512 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1513
1514 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001515 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001516
1517 armnn::INetworkPtr network = armnn::INetwork::Create();
1518 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1519 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
Jim Flynn906f9462019-05-10 13:55:21 +01001520 ARMNN_NO_DEPRECATE_WARN_BEGIN
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001521 armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str());
Jim Flynn906f9462019-05-10 13:55:21 +01001522 ARMNN_NO_DEPRECATE_WARN_END
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001523 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1524
1525 inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
1526 inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
1527 mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1528
1529 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1530 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1531 mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1532
Jim Flynn5fa83932019-05-09 15:35:43 +01001533 std::string mergerLayerNetwork = SerializeNetwork(*network);
1534 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001535 BOOST_CHECK(deserializedNetwork);
1536
1537 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1538 deserializedNetwork->Accept(verifier);
1539}
1540
Jim Flynn5fa83932019-05-09 15:35:43 +01001541BOOST_AUTO_TEST_CASE(EnsureMergerLayerBackwardCompatibility)
1542{
1543 // The hex array below is a flat buffer containing a simple network with two inputs
Jim Flynne242f2d2019-05-22 14:24:13 +01001544 // a merger layer (now deprecated) and an output layer with dimensions as per the tensor infos below.
1545 //
1546 // This test verifies that we can still read back these old style
Jim Flynn5fa83932019-05-09 15:35:43 +01001547 // models replacing the MergerLayers with ConcatLayers with the same parameters.
Jim Flynn5fa83932019-05-09 15:35:43 +01001548 unsigned int size = 760;
1549 const unsigned char mergerModel[] = {
1550 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1551 0x0C,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x38,0x02,0x00,0x00,
1552 0x8C,0x01,0x00,0x00,0x70,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1553 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xF4,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x0B,
1554 0x04,0x00,0x00,0x00,0x92,0xFE,0xFF,0xFF,0x04,0x00,0x00,0x00,0x9A,0xFE,0xFF,0xFF,0x04,0x00,0x00,0x00,
1555 0x7E,0xFE,0xFF,0xFF,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1556 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
1557 0x00,0x00,0x00,0x00,0xF8,0xFE,0xFF,0xFF,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0xFE,0xFF,0xFF,
1558 0x00,0x00,0x00,0x1F,0x0C,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1559 0x68,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x0C,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,
1560 0x0C,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1561 0x24,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x22,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1562 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,
1563 0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1564 0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,
1565 0x14,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x6D,0x65,0x72,0x67,0x65,0x72,0x00,0x00,
1566 0x02,0x00,0x00,0x00,0x5C,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1567 0x34,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x92,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
1568 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1569 0x02,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1570 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,
1571 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1572 0x00,0x00,0x00,0x09,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,
1573 0x0C,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,
1574 0x01,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x18,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,
1575 0x0E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1576 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1577 0x0C,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1578 0x66,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1579 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,
1580 0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,
1581 0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0A,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1582 0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,
1583 0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1584 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,
1585 0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,
1586 0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1587 0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00};
1588 std::stringstream ss;
1589 for (unsigned int i = 0; i < size; ++i)
1590 {
1591 ss << mergerModel[i];
1592 }
1593 std::string mergerLayerNetwork = ss.str();
1594 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
1595 BOOST_CHECK(deserializedNetwork);
1596 const std::string layerName("merger");
1597 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1598 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1599
1600 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1601
1602 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001603 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Jim Flynn5fa83932019-05-09 15:35:43 +01001604
1605 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1606 deserializedNetwork->Accept(verifier);
1607}
1608
Jim Flynne242f2d2019-05-22 14:24:13 +01001609BOOST_AUTO_TEST_CASE(SerializeConcat)
1610{
1611 const std::string layerName("concat");
1612 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1613 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1614
1615 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1616
1617 armnn::OriginsDescriptor descriptor =
1618 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1619
1620 armnn::INetworkPtr network = armnn::INetwork::Create();
1621 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1622 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1623 armnn::IConnectableLayer* const concatLayer = network->AddConcatLayer(descriptor, layerName.c_str());
1624 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1625
1626 inputLayerOne->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
1627 inputLayerTwo->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
1628 concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1629
1630 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1631 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1632 concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1633
1634 std::string concatLayerNetwork = SerializeNetwork(*network);
1635 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(concatLayerNetwork);
1636 BOOST_CHECK(deserializedNetwork);
1637
1638 // NOTE: using the MergerLayerVerifier to ensure that it is a concat layer and not a
1639 // merger layer that gets placed into the graph.
1640 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1641 deserializedNetwork->Accept(verifier);
1642}
1643
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001644BOOST_AUTO_TEST_CASE(SerializeMinimum)
1645{
1646 class MinimumLayerVerifier : public LayerVerifierBase
1647 {
1648 public:
1649 MinimumLayerVerifier(const std::string& layerName,
1650 const std::vector<armnn::TensorInfo>& inputInfos,
1651 const std::vector<armnn::TensorInfo>& outputInfos)
1652 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1653
1654 void VisitMinimumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1655 {
1656 VerifyNameAndConnections(layer, name);
1657 }
1658 };
1659
1660 const std::string layerName("minimum");
1661 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1662
1663 armnn::INetworkPtr network = armnn::INetwork::Create();
1664 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1665 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1666 armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1667 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1668
1669 inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1670 inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1671 minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1672
1673 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1674 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1675 minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
1676
1677 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1678 BOOST_CHECK(deserializedNetwork);
1679
1680 MinimumLayerVerifier verifier(layerName, {info, info}, {info});
1681 deserializedNetwork->Accept(verifier);
1682}
1683
1684BOOST_AUTO_TEST_CASE(SerializeMultiplication)
1685{
1686 class MultiplicationLayerVerifier : public LayerVerifierBase
1687 {
1688 public:
1689 MultiplicationLayerVerifier(const std::string& layerName,
1690 const std::vector<armnn::TensorInfo>& inputInfos,
1691 const std::vector<armnn::TensorInfo>& outputInfos)
1692 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1693
1694 void VisitMultiplicationLayer(const armnn::IConnectableLayer* layer, const char* name) override
1695 {
1696 VerifyNameAndConnections(layer, name);
1697 }
1698 };
1699
1700 const std::string layerName("multiplication");
1701 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1702
1703 armnn::INetworkPtr network = armnn::INetwork::Create();
1704 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1705 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1706 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
1707 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1708
1709 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
1710 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
1711 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1712
1713 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1714 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1715 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
1716
1717 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1718 BOOST_CHECK(deserializedNetwork);
1719
1720 MultiplicationLayerVerifier verifier(layerName, {info, info}, {info});
1721 deserializedNetwork->Accept(verifier);
1722}
1723
Ellen Norris-Thompson51982472019-06-19 11:46:21 +01001724BOOST_AUTO_TEST_CASE(SerializePrelu)
1725{
1726 class PreluLayerVerifier : public LayerVerifierBase
1727 {
1728 public:
1729 PreluLayerVerifier(const std::string& layerName,
1730 const std::vector<armnn::TensorInfo>& inputInfos,
1731 const std::vector<armnn::TensorInfo>& outputInfos)
1732 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1733
1734 void VisitPreluLayer(const armnn::IConnectableLayer* layer, const char* name) override
1735 {
1736 VerifyNameAndConnections(layer, name);
1737 }
1738 };
1739
1740 const std::string layerName("prelu");
1741
1742 armnn::TensorInfo inputTensorInfo ({ 4, 1, 2 }, armnn::DataType::Float32);
1743 armnn::TensorInfo alphaTensorInfo ({ 5, 4, 3, 1 }, armnn::DataType::Float32);
1744 armnn::TensorInfo outputTensorInfo({ 5, 4, 3, 2 }, armnn::DataType::Float32);
1745
1746 armnn::INetworkPtr network = armnn::INetwork::Create();
1747 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1748 armnn::IConnectableLayer* const alphaLayer = network->AddInputLayer(1);
1749 armnn::IConnectableLayer* const preluLayer = network->AddPreluLayer(layerName.c_str());
1750 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1751
1752 inputLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(0));
1753 alphaLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(1));
1754 preluLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1755
1756 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1757 alphaLayer->GetOutputSlot(0).SetTensorInfo(alphaTensorInfo);
1758 preluLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1759
1760 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1761 BOOST_CHECK(deserializedNetwork);
1762
1763 PreluLayerVerifier verifier(layerName, {inputTensorInfo, alphaTensorInfo}, {outputTensorInfo});
1764 deserializedNetwork->Accept(verifier);
1765}
1766
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001767BOOST_AUTO_TEST_CASE(SerializeNormalization)
1768{
1769 class NormalizationLayerVerifier : public LayerVerifierBase
1770 {
1771 public:
1772 NormalizationLayerVerifier(const std::string& layerName,
1773 const std::vector<armnn::TensorInfo>& inputInfos,
1774 const std::vector<armnn::TensorInfo>& outputInfos,
1775 const armnn::NormalizationDescriptor& descriptor)
1776 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1777 , m_Descriptor(descriptor) {}
1778
1779 void VisitNormalizationLayer(const armnn::IConnectableLayer* layer,
1780 const armnn::NormalizationDescriptor& descriptor,
1781 const char* name) override
1782 {
1783 VerifyNameAndConnections(layer, name);
1784 VerifyDescriptor(descriptor);
1785 }
1786
1787 private:
1788 void VerifyDescriptor(const armnn::NormalizationDescriptor& descriptor)
1789 {
1790 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1791 BOOST_TEST(descriptor.m_NormSize == m_Descriptor.m_NormSize);
1792 BOOST_TEST(descriptor.m_Alpha == m_Descriptor.m_Alpha);
1793 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
1794 BOOST_TEST(descriptor.m_K == m_Descriptor.m_K);
1795 BOOST_TEST(
1796 static_cast<int>(descriptor.m_NormChannelType) == static_cast<int>(m_Descriptor.m_NormChannelType));
1797 BOOST_TEST(
1798 static_cast<int>(descriptor.m_NormMethodType) == static_cast<int>(m_Descriptor.m_NormMethodType));
1799 }
1800
1801 armnn::NormalizationDescriptor m_Descriptor;
1802 };
1803
1804 const std::string layerName("normalization");
1805 const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
1806
1807 armnn::NormalizationDescriptor desc;
1808 desc.m_DataLayout = armnn::DataLayout::NCHW;
1809 desc.m_NormSize = 3;
1810 desc.m_Alpha = 1;
1811 desc.m_Beta = 1;
1812 desc.m_K = 1;
1813
1814 armnn::INetworkPtr network = armnn::INetwork::Create();
1815 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1816 armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
1817 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1818
1819 inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
1820 normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1821
1822 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1823 normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
1824
1825 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1826 BOOST_CHECK(deserializedNetwork);
1827
1828 NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc);
1829 deserializedNetwork->Accept(verifier);
1830}
1831
Jim Flynn965c7c62019-06-24 14:32:41 +01001832class PadLayerVerifier : public LayerVerifierBase
1833{
1834public:
1835 PadLayerVerifier(const std::string& layerName,
1836 const std::vector<armnn::TensorInfo>& inputInfos,
1837 const std::vector<armnn::TensorInfo>& outputInfos,
1838 const armnn::PadDescriptor& descriptor)
1839 : LayerVerifierBase(layerName, inputInfos, outputInfos), m_Descriptor(descriptor) {}
1840
1841 void VisitPadLayer(const armnn::IConnectableLayer* layer,
1842 const armnn::PadDescriptor& descriptor,
1843 const char* name) override
1844 {
1845 VerifyNameAndConnections(layer, name);
1846 VerifyDescriptor(descriptor);
1847 }
1848
1849private:
1850 void VerifyDescriptor(const armnn::PadDescriptor& descriptor)
1851 {
1852 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
Aron Virginas-Tarf3569052019-07-05 16:01:08 +01001853 BOOST_TEST(descriptor.m_PadValue == m_Descriptor.m_PadValue);
Jim Flynn965c7c62019-06-24 14:32:41 +01001854 }
1855
1856 armnn::PadDescriptor m_Descriptor;
1857};
1858
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001859BOOST_AUTO_TEST_CASE(SerializePad)
1860{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001861
1862 const std::string layerName("pad");
1863 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1864 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1865
1866 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1867
1868 armnn::INetworkPtr network = armnn::INetwork::Create();
1869 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1870 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
1871 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1872
1873 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
1874 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1875
1876 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1877 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1878
1879 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1880 BOOST_CHECK(deserializedNetwork);
1881
1882 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1883 deserializedNetwork->Accept(verifier);
1884}
1885
Jim Flynn965c7c62019-06-24 14:32:41 +01001886BOOST_AUTO_TEST_CASE(CheckSerializePadBackwardCompatibility)
1887{
1888 // The PadDescriptor is being extended with a float PadValue (so a value other than 0
1889 // can be used to pad the tensor.
1890 //
1891 // This test contains a binary representation of a simple input->pad->output network
1892 // prior to this change to test that the descriptor has been updated in a backward
1893 // compatible way with respect to Deserialization of older binary dumps
1894 unsigned int size = 532;
1895 const unsigned char padModel[] = {
1896 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1897 0x0C,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x54,0x01,0x00,0x00,
1898 0x6C,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1899 0x02,0x00,0x00,0x00,0xD0,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x0B,0x04,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,
1900 0x04,0x00,0x00,0x00,0x9E,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x72,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,
1901 0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1902 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2C,0xFF,0xFF,0xFF,
1903 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x16,0x0C,0x00,0x00,0x00,
1904 0x08,0x00,0x0E,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x4C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,
1905 0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
1906 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1907 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x18,0x00,0x04,0x00,
1908 0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,0x0E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1909 0x14,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x70,0x61,0x64,0x00,
1910 0x01,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x08,0x00,
1911 0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x52,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,
1912 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
1913 0x05,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,
1914 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1915 0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,
1916 0x0A,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,
1917 0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1918 0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1919 0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,
1920 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1921 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1922 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0 };
1923
1924 std::stringstream ss;
1925 for (unsigned int i = 0; i < size; ++i)
1926 {
1927 ss << padModel[i];
1928 }
1929 std::string padNetwork = ss.str();
1930 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(padNetwork);
1931 BOOST_CHECK(deserializedNetwork);
1932
1933 const std::string layerName("pad");
1934 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1935 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1936
1937 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1938
1939 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1940 deserializedNetwork->Accept(verifier);
1941}
1942
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001943BOOST_AUTO_TEST_CASE(SerializePermute)
1944{
1945 class PermuteLayerVerifier : public LayerVerifierBase
1946 {
1947 public:
1948 PermuteLayerVerifier(const std::string& layerName,
1949 const std::vector<armnn::TensorInfo>& inputInfos,
1950 const std::vector<armnn::TensorInfo>& outputInfos,
1951 const armnn::PermuteDescriptor& descriptor)
1952 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1953 , m_Descriptor(descriptor) {}
1954
1955 void VisitPermuteLayer(const armnn::IConnectableLayer* layer,
1956 const armnn::PermuteDescriptor& descriptor,
1957 const char* name) override
1958 {
1959 VerifyNameAndConnections(layer, name);
1960 VerifyDescriptor(descriptor);
1961 }
1962
1963 private:
1964 void VerifyDescriptor(const armnn::PermuteDescriptor& descriptor)
1965 {
1966 BOOST_TEST(descriptor.m_DimMappings.IsEqual(m_Descriptor.m_DimMappings));
1967 }
1968
1969 armnn::PermuteDescriptor m_Descriptor;
1970 };
1971
1972 const std::string layerName("permute");
1973 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
1974 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1975
1976 armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
1977
1978 armnn::INetworkPtr network = armnn::INetwork::Create();
1979 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1980 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
1981 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1982
1983 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
1984 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1985
1986 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1987 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1988
1989 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1990 BOOST_CHECK(deserializedNetwork);
1991
1992 PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
1993 deserializedNetwork->Accept(verifier);
1994}
1995
1996BOOST_AUTO_TEST_CASE(SerializePooling2d)
1997{
1998 class Pooling2dLayerVerifier : public LayerVerifierBase
1999 {
2000 public:
2001 Pooling2dLayerVerifier(const std::string& layerName,
2002 const std::vector<armnn::TensorInfo>& inputInfos,
2003 const std::vector<armnn::TensorInfo>& outputInfos,
2004 const armnn::Pooling2dDescriptor& descriptor)
2005 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2006 , m_Descriptor(descriptor) {}
2007
2008 void VisitPooling2dLayer(const armnn::IConnectableLayer* layer,
2009 const armnn::Pooling2dDescriptor& descriptor,
2010 const char* name) override
2011 {
2012 VerifyNameAndConnections(layer, name);
2013 VerifyDescriptor(descriptor);
2014 }
2015
2016 private:
2017 void VerifyDescriptor(const armnn::Pooling2dDescriptor& descriptor)
2018 {
2019 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2020 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
2021 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
2022 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
2023 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
2024 BOOST_TEST(descriptor.m_PoolWidth == m_Descriptor.m_PoolWidth);
2025 BOOST_TEST(descriptor.m_PoolHeight == m_Descriptor.m_PoolHeight);
2026 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
2027 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
2028
2029 BOOST_TEST(
2030 static_cast<int>(descriptor.m_PaddingMethod) == static_cast<int>(m_Descriptor.m_PaddingMethod));
2031 BOOST_TEST(
2032 static_cast<int>(descriptor.m_PoolType) == static_cast<int>(m_Descriptor.m_PoolType));
2033 BOOST_TEST(
2034 static_cast<int>(descriptor.m_OutputShapeRounding) ==
2035 static_cast<int>(m_Descriptor.m_OutputShapeRounding));
2036 }
2037
2038 armnn::Pooling2dDescriptor m_Descriptor;
2039 };
2040
2041 const std::string layerName("pooling2d");
2042 const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
2043 const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
2044
2045 armnn::Pooling2dDescriptor desc;
2046 desc.m_DataLayout = armnn::DataLayout::NHWC;
2047 desc.m_PadTop = 0;
2048 desc.m_PadBottom = 0;
2049 desc.m_PadLeft = 0;
2050 desc.m_PadRight = 0;
2051 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
2052 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
2053 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
2054 desc.m_PoolHeight = 2;
2055 desc.m_PoolWidth = 2;
2056 desc.m_StrideX = 2;
2057 desc.m_StrideY = 2;
2058
2059 armnn::INetworkPtr network = armnn::INetwork::Create();
2060 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2061 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
2062 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2063
2064 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
2065 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2066
2067 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2068 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2069
2070 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2071 BOOST_CHECK(deserializedNetwork);
2072
2073 Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2074 deserializedNetwork->Accept(verifier);
2075}
2076
Derek Lamberti87acb272019-03-27 16:51:31 +00002077BOOST_AUTO_TEST_CASE(SerializeQuantize)
2078{
2079 class QuantizeLayerVerifier : public LayerVerifierBase
2080 {
2081 public:
2082 QuantizeLayerVerifier(const std::string& layerName,
2083 const std::vector<armnn::TensorInfo>& inputInfos,
2084 const std::vector<armnn::TensorInfo>& outputInfos)
2085 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2086
2087 void VisitQuantizeLayer(const armnn::IConnectableLayer* layer, const char* name) override
2088 {
2089 VerifyNameAndConnections(layer, name);
2090 }
2091 };
2092
2093 const std::string layerName("quantize");
2094 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
2095
2096 armnn::INetworkPtr network = armnn::INetwork::Create();
2097 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2098 armnn::IConnectableLayer* const quantizeLayer = network->AddQuantizeLayer(layerName.c_str());
2099 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2100
2101 inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
2102 quantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2103
2104 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2105 quantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
2106
2107 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2108 BOOST_CHECK(deserializedNetwork);
2109
2110 QuantizeLayerVerifier verifier(layerName, {info}, {info});
2111 deserializedNetwork->Accept(verifier);
2112}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002113BOOST_AUTO_TEST_CASE(SerializeReshape)
2114{
2115 class ReshapeLayerVerifier : public LayerVerifierBase
2116 {
2117 public:
2118 ReshapeLayerVerifier(const std::string& layerName,
2119 const std::vector<armnn::TensorInfo>& inputInfos,
2120 const std::vector<armnn::TensorInfo>& outputInfos,
2121 const armnn::ReshapeDescriptor& descriptor)
2122 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2123 , m_Descriptor(descriptor) {}
2124
2125 void VisitReshapeLayer(const armnn::IConnectableLayer* layer,
2126 const armnn::ReshapeDescriptor& descriptor,
2127 const char* name) override
2128 {
2129 VerifyNameAndConnections(layer, name);
2130 VerifyDescriptor(descriptor);
2131 }
2132
2133 private:
2134 void VerifyDescriptor(const armnn::ReshapeDescriptor& descriptor)
2135 {
2136 BOOST_TEST(descriptor.m_TargetShape == m_Descriptor.m_TargetShape);
2137 }
2138
2139 armnn::ReshapeDescriptor m_Descriptor;
2140 };
2141
2142 const std::string layerName("reshape");
2143 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
2144 const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
2145
2146 armnn::ReshapeDescriptor descriptor({3, 3});
2147
2148 armnn::INetworkPtr network = armnn::INetwork::Create();
2149 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2150 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
2151 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2152
2153 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
2154 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2155
2156 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2157 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2158
2159 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2160 BOOST_CHECK(deserializedNetwork);
2161
2162 ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2163 deserializedNetwork->Accept(verifier);
2164}
2165
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002166BOOST_AUTO_TEST_CASE(SerializeResize)
2167{
2168 class ResizeLayerVerifier : public LayerVerifierBase
2169 {
2170 public:
2171 ResizeLayerVerifier(const std::string& layerName,
2172 const std::vector<armnn::TensorInfo>& inputInfos,
2173 const std::vector<armnn::TensorInfo>& outputInfos,
2174 const armnn::ResizeDescriptor& descriptor)
2175 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2176 , m_Descriptor(descriptor) {}
2177
2178 void VisitResizeLayer(const armnn::IConnectableLayer* layer,
2179 const armnn::ResizeDescriptor& descriptor,
2180 const char* name) override
2181 {
2182 VerifyNameAndConnections(layer, name);
2183 VerifyDescriptor(descriptor);
2184 }
2185
2186 private:
2187 void VerifyDescriptor(const armnn::ResizeDescriptor& descriptor)
2188 {
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002189 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2190 BOOST_CHECK(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002191 BOOST_CHECK(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002192 BOOST_CHECK(descriptor.m_Method == m_Descriptor.m_Method);
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002193 }
2194
2195 armnn::ResizeDescriptor m_Descriptor;
2196 };
2197
2198 const std::string layerName("resize");
2199 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2200 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2201
2202 armnn::ResizeDescriptor desc;
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002203 desc.m_TargetWidth = 4;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002204 desc.m_TargetHeight = 2;
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002205 desc.m_Method = armnn::ResizeMethod::NearestNeighbor;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002206
2207 armnn::INetworkPtr network = armnn::INetwork::Create();
2208 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2209 armnn::IConnectableLayer* const resizeLayer = network->AddResizeLayer(desc, layerName.c_str());
2210 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2211
2212 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2213 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2214
2215 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2216 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2217
2218 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2219 BOOST_CHECK(deserializedNetwork);
2220
2221 ResizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2222 deserializedNetwork->Accept(verifier);
2223}
2224
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002225BOOST_AUTO_TEST_CASE(SerializeRsqrt)
2226{
2227 class RsqrtLayerVerifier : public LayerVerifierBase
2228 {
2229 public:
2230 RsqrtLayerVerifier(const std::string& layerName,
2231 const std::vector<armnn::TensorInfo>& inputInfos,
2232 const std::vector<armnn::TensorInfo>& outputInfos)
2233 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2234
2235 void VisitRsqrtLayer(const armnn::IConnectableLayer* layer, const char* name) override
2236 {
2237 VerifyNameAndConnections(layer, name);
2238 }
2239 };
2240
2241 const std::string layerName("rsqrt");
2242 const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32);
2243
2244 armnn::INetworkPtr network = armnn::INetwork::Create();
2245 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2246 armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer(layerName.c_str());
2247 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2248
2249 inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0));
2250 rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2251
2252 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2253 rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2254
2255 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2256 BOOST_CHECK(deserializedNetwork);
2257
2258 RsqrtLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
2259 deserializedNetwork->Accept(verifier);
2260}
2261
2262BOOST_AUTO_TEST_CASE(SerializeSoftmax)
2263{
2264 class SoftmaxLayerVerifier : public LayerVerifierBase
2265 {
2266 public:
2267 SoftmaxLayerVerifier(const std::string& layerName,
2268 const std::vector<armnn::TensorInfo>& inputInfos,
2269 const std::vector<armnn::TensorInfo>& outputInfos,
2270 const armnn::SoftmaxDescriptor& descriptor)
2271 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2272 , m_Descriptor(descriptor) {}
2273
2274 void VisitSoftmaxLayer(const armnn::IConnectableLayer* layer,
2275 const armnn::SoftmaxDescriptor& descriptor,
2276 const char* name) override
2277 {
2278 VerifyNameAndConnections(layer, name);
2279 VerifyDescriptor(descriptor);
2280 }
2281
2282 private:
2283 void VerifyDescriptor(const armnn::SoftmaxDescriptor& descriptor)
2284 {
2285 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
2286 }
2287
2288 armnn::SoftmaxDescriptor m_Descriptor;
2289 };
2290
2291 const std::string layerName("softmax");
2292 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
2293
2294 armnn::SoftmaxDescriptor descriptor;
2295 descriptor.m_Beta = 1.0f;
2296
2297 armnn::INetworkPtr network = armnn::INetwork::Create();
2298 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2299 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
2300 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2301
2302 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
2303 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2304
2305 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2306 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
2307
2308 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2309 BOOST_CHECK(deserializedNetwork);
2310
2311 SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
2312 deserializedNetwork->Accept(verifier);
2313}
2314
2315BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
2316{
2317 class SpaceToBatchNdLayerVerifier : public LayerVerifierBase
2318 {
2319 public:
2320 SpaceToBatchNdLayerVerifier(const std::string& layerName,
2321 const std::vector<armnn::TensorInfo>& inputInfos,
2322 const std::vector<armnn::TensorInfo>& outputInfos,
2323 const armnn::SpaceToBatchNdDescriptor& descriptor)
2324 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2325 , m_Descriptor(descriptor) {}
2326
2327 void VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer* layer,
2328 const armnn::SpaceToBatchNdDescriptor& descriptor,
2329 const char* name) override
2330 {
2331 VerifyNameAndConnections(layer, name);
2332 VerifyDescriptor(descriptor);
2333 }
2334
2335 private:
2336 void VerifyDescriptor(const armnn::SpaceToBatchNdDescriptor& descriptor)
2337 {
2338 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
2339 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
2340 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2341 }
2342
2343 armnn::SpaceToBatchNdDescriptor m_Descriptor;
2344 };
2345
2346 const std::string layerName("spaceToBatchNd");
2347 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
2348 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
2349
2350 armnn::SpaceToBatchNdDescriptor desc;
2351 desc.m_DataLayout = armnn::DataLayout::NCHW;
2352 desc.m_BlockShape = {2, 2};
2353 desc.m_PadList = {{0, 0}, {2, 0}};
2354
2355 armnn::INetworkPtr network = armnn::INetwork::Create();
2356 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2357 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2358 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2359
2360 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
2361 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2362
2363 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2364 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2365
2366 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2367 BOOST_CHECK(deserializedNetwork);
2368
2369 SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2370 deserializedNetwork->Accept(verifier);
2371}
2372
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002373BOOST_AUTO_TEST_CASE(SerializeSpaceToDepth)
2374{
2375 class SpaceToDepthLayerVerifier : public LayerVerifierBase
2376 {
2377 public:
2378 SpaceToDepthLayerVerifier(const std::string& layerName,
2379 const std::vector<armnn::TensorInfo>& inputInfos,
2380 const std::vector<armnn::TensorInfo>& outputInfos,
2381 const armnn::SpaceToDepthDescriptor& descriptor)
2382 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2383 , m_Descriptor(descriptor) {}
2384
2385 void VisitSpaceToDepthLayer(const armnn::IConnectableLayer* layer,
2386 const armnn::SpaceToDepthDescriptor& descriptor,
2387 const char* name) override
2388 {
2389 VerifyNameAndConnections(layer, name);
2390 VerifyDescriptor(descriptor);
2391 }
2392
2393 private:
2394 void VerifyDescriptor(const armnn::SpaceToDepthDescriptor& descriptor)
2395 {
2396 BOOST_TEST(descriptor.m_BlockSize == m_Descriptor.m_BlockSize);
2397 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2398 }
2399
2400 armnn::SpaceToDepthDescriptor m_Descriptor;
2401 };
2402
2403 const std::string layerName("spaceToDepth");
2404
2405 const armnn::TensorInfo inputInfo ({ 1, 16, 8, 3 }, armnn::DataType::Float32);
2406 const armnn::TensorInfo outputInfo({ 1, 8, 4, 12 }, armnn::DataType::Float32);
2407
2408 armnn::SpaceToDepthDescriptor desc;
2409 desc.m_BlockSize = 2;
2410 desc.m_DataLayout = armnn::DataLayout::NHWC;
2411
2412 armnn::INetworkPtr network = armnn::INetwork::Create();
2413 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2414 armnn::IConnectableLayer* const spaceToDepthLayer = network->AddSpaceToDepthLayer(desc, layerName.c_str());
2415 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2416
2417 inputLayer->GetOutputSlot(0).Connect(spaceToDepthLayer->GetInputSlot(0));
2418 spaceToDepthLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2419
2420 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2421 spaceToDepthLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2422
2423 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2424 BOOST_CHECK(deserializedNetwork);
2425
2426 SpaceToDepthLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2427 deserializedNetwork->Accept(verifier);
2428}
2429
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002430BOOST_AUTO_TEST_CASE(SerializeSplitter)
2431{
2432 class SplitterLayerVerifier : public LayerVerifierBase
2433 {
2434 public:
2435 SplitterLayerVerifier(const std::string& layerName,
2436 const std::vector<armnn::TensorInfo>& inputInfos,
2437 const std::vector<armnn::TensorInfo>& outputInfos,
2438 const armnn::ViewsDescriptor& descriptor)
2439 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2440 , m_Descriptor(descriptor) {}
2441
2442 void VisitSplitterLayer(const armnn::IConnectableLayer* layer,
2443 const armnn::ViewsDescriptor& descriptor,
2444 const char* name) override
2445 {
2446 VerifyNameAndConnections(layer, name);
2447 VerifyDescriptor(descriptor);
2448 }
2449
2450 private:
2451 void VerifyDescriptor(const armnn::ViewsDescriptor& descriptor)
2452 {
2453 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
2454 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
2455
2456 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
2457 {
2458 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
2459 {
2460 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
2461 BOOST_TEST(descriptor.GetViewSizes(i)[j] == m_Descriptor.GetViewSizes(i)[j]);
2462 }
2463 }
2464 }
2465
2466 armnn::ViewsDescriptor m_Descriptor;
2467 };
2468
2469 const unsigned int numViews = 3;
2470 const unsigned int numDimensions = 4;
2471 const unsigned int inputShape[] = {1, 18, 4, 4};
2472 const unsigned int outputShape[] = {1, 6, 4, 4};
2473
2474 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
2475 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
2476 static_cast<unsigned int>(inputShape[1]),
2477 static_cast<unsigned int>(inputShape[2]),
2478 static_cast<unsigned int>(inputShape[3])};
2479 splitterDimSizes[1] /= numViews;
2480 armnn::ViewsDescriptor desc(numViews, numDimensions);
2481
2482 for (unsigned int g = 0; g < numViews; ++g)
2483 {
2484 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
2485
2486 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
2487 {
2488 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
2489 }
2490 }
2491
2492 const std::string layerName("splitter");
2493 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
2494 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
2495
2496 armnn::INetworkPtr network = armnn::INetwork::Create();
2497 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2498 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
2499 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2500 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2501 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
2502
2503 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
2504 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2505 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2506 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
2507
2508 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2509 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2510 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
2511 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2512
2513 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2514 BOOST_CHECK(deserializedNetwork);
2515
2516 SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
2517 deserializedNetwork->Accept(verifier);
2518}
2519
Matthew Jacksonb5433ee2019-07-11 15:54:20 +01002520BOOST_AUTO_TEST_CASE(SerializeStack)
2521{
2522 class StackLayerVerifier : public LayerVerifierBase
2523 {
2524 public:
2525 StackLayerVerifier(const std::string& layerName,
2526 const std::vector<armnn::TensorInfo>& inputInfos,
2527 const std::vector<armnn::TensorInfo>& outputInfos,
2528 const armnn::StackDescriptor& descriptor)
2529 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2530 , m_Descriptor(descriptor) {}
2531
2532 void VisitStackLayer(const armnn::IConnectableLayer* layer,
2533 const armnn::StackDescriptor& descriptor,
2534 const char* name) override
2535 {
2536 VerifyNameAndConnections(layer, name);
2537 VerifyDescriptor(descriptor);
2538 }
2539
2540 private:
2541 void VerifyDescriptor(const armnn::StackDescriptor& descriptor)
2542 {
2543 BOOST_TEST(descriptor.m_Axis == m_Descriptor.m_Axis);
2544 BOOST_TEST(descriptor.m_InputShape == m_Descriptor.m_InputShape);
2545 BOOST_TEST(descriptor.m_NumInputs == m_Descriptor.m_NumInputs);
2546 }
2547
2548 armnn::StackDescriptor m_Descriptor;
2549 };
2550
2551 const std::string layerName("stack");
2552
2553 armnn::TensorInfo inputTensorInfo ({4, 3, 5}, armnn::DataType::Float32);
2554 armnn::TensorInfo outputTensorInfo({4, 3, 2, 5}, armnn::DataType::Float32);
2555
2556 armnn::StackDescriptor descriptor(2, 2, {4, 3, 5});
2557
2558 armnn::INetworkPtr network = armnn::INetwork::Create();
2559 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
2560 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
2561 armnn::IConnectableLayer* const stackLayer = network->AddStackLayer(descriptor, layerName.c_str());
2562 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2563
2564 inputLayer1->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(0));
2565 inputLayer2->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(1));
2566 stackLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2567
2568 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2569 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2570 stackLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2571
2572 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2573 BOOST_CHECK(deserializedNetwork);
2574
2575 StackLayerVerifier verifier(layerName, {inputTensorInfo, inputTensorInfo}, {outputTensorInfo}, descriptor);
2576 deserializedNetwork->Accept(verifier);
2577}
2578
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002579BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
2580{
2581 class StridedSliceLayerVerifier : public LayerVerifierBase
2582 {
2583 public:
2584 StridedSliceLayerVerifier(const std::string& layerName,
2585 const std::vector<armnn::TensorInfo>& inputInfos,
2586 const std::vector<armnn::TensorInfo>& outputInfos,
2587 const armnn::StridedSliceDescriptor& descriptor)
2588 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2589 , m_Descriptor(descriptor) {}
2590
2591 void VisitStridedSliceLayer(const armnn::IConnectableLayer* layer,
2592 const armnn::StridedSliceDescriptor& descriptor,
2593 const char* name) override
2594 {
2595 VerifyNameAndConnections(layer, name);
2596 VerifyDescriptor(descriptor);
2597 }
2598
2599 private:
2600 void VerifyDescriptor(const armnn::StridedSliceDescriptor& descriptor)
2601 {
2602 BOOST_TEST(descriptor.m_Begin == m_Descriptor.m_Begin);
2603 BOOST_TEST(descriptor.m_End == m_Descriptor.m_End);
2604 BOOST_TEST(descriptor.m_Stride == m_Descriptor.m_Stride);
2605 BOOST_TEST(descriptor.m_BeginMask == m_Descriptor.m_BeginMask);
2606 BOOST_TEST(descriptor.m_EndMask == m_Descriptor.m_EndMask);
2607 BOOST_TEST(descriptor.m_ShrinkAxisMask == m_Descriptor.m_ShrinkAxisMask);
2608 BOOST_TEST(descriptor.m_EllipsisMask == m_Descriptor.m_EllipsisMask);
2609 BOOST_TEST(descriptor.m_NewAxisMask == m_Descriptor.m_NewAxisMask);
2610 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2611 }
2612 armnn::StridedSliceDescriptor m_Descriptor;
2613 };
2614
2615 const std::string layerName("stridedSlice");
2616 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2617 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2618
2619 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2620 desc.m_EndMask = (1 << 4) - 1;
2621 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2622 desc.m_DataLayout = armnn::DataLayout::NCHW;
2623
2624 armnn::INetworkPtr network = armnn::INetwork::Create();
2625 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2626 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2627 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2628
2629 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2630 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2631
2632 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2633 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2634
2635 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2636 BOOST_CHECK(deserializedNetwork);
2637
2638 StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2639 deserializedNetwork->Accept(verifier);
2640}
2641
2642BOOST_AUTO_TEST_CASE(SerializeSubtraction)
2643{
2644 class SubtractionLayerVerifier : public LayerVerifierBase
2645 {
2646 public:
2647 SubtractionLayerVerifier(const std::string& layerName,
2648 const std::vector<armnn::TensorInfo>& inputInfos,
2649 const std::vector<armnn::TensorInfo>& outputInfos)
2650 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2651
2652 void VisitSubtractionLayer(const armnn::IConnectableLayer* layer, const char* name) override
2653 {
2654 VerifyNameAndConnections(layer, name);
2655 }
2656 };
2657
2658 const std::string layerName("subtraction");
2659 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2660
2661 armnn::INetworkPtr network = armnn::INetwork::Create();
2662 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2663 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2664 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2665 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2666
2667 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2668 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2669 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2670
2671 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2672 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2673 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2674
2675 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2676 BOOST_CHECK(deserializedNetwork);
2677
2678 SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
2679 deserializedNetwork->Accept(verifier);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +00002680}
2681
Sadik Armaganeff363d2019-04-05 15:25:46 +01002682BOOST_AUTO_TEST_CASE(SerializeSwitch)
2683{
2684 class SwitchLayerVerifier : public LayerVerifierBase
2685 {
2686 public:
2687 SwitchLayerVerifier(const std::string& layerName,
2688 const std::vector<armnn::TensorInfo>& inputInfos,
2689 const std::vector<armnn::TensorInfo>& outputInfos)
2690 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2691
2692 void VisitSwitchLayer(const armnn::IConnectableLayer* layer, const char* name) override
2693 {
2694 VerifyNameAndConnections(layer, name);
2695 }
2696
2697 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2698 const armnn::ConstTensor& input,
2699 const char *name) override {}
2700 };
2701
2702 const std::string layerName("switch");
2703 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2704
2705 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2706 armnn::ConstTensor constTensor(info, constantData);
2707
2708 armnn::INetworkPtr network = armnn::INetwork::Create();
2709 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2710 armnn::IConnectableLayer* const constantLayer = network->AddConstantLayer(constTensor, "constant");
2711 armnn::IConnectableLayer* const switchLayer = network->AddSwitchLayer(layerName.c_str());
2712 armnn::IConnectableLayer* const trueOutputLayer = network->AddOutputLayer(0);
2713 armnn::IConnectableLayer* const falseOutputLayer = network->AddOutputLayer(1);
2714
2715 inputLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(0));
2716 constantLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(1));
2717 switchLayer->GetOutputSlot(0).Connect(trueOutputLayer->GetInputSlot(0));
2718 switchLayer->GetOutputSlot(1).Connect(falseOutputLayer->GetInputSlot(0));
2719
2720 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2721 constantLayer->GetOutputSlot(0).SetTensorInfo(info);
2722 switchLayer->GetOutputSlot(0).SetTensorInfo(info);
2723 switchLayer->GetOutputSlot(1).SetTensorInfo(info);
2724
2725 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2726 BOOST_CHECK(deserializedNetwork);
2727
2728 SwitchLayerVerifier verifier(layerName, {info, info}, {info, info});
2729 deserializedNetwork->Accept(verifier);
2730}
2731
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002732BOOST_AUTO_TEST_CASE(SerializeTransposeConvolution2d)
2733{
2734 class TransposeConvolution2dLayerVerifier : public LayerVerifierBase
2735 {
2736 public:
2737 TransposeConvolution2dLayerVerifier(const std::string& layerName,
2738 const std::vector<armnn::TensorInfo>& inputInfos,
2739 const std::vector<armnn::TensorInfo>& outputInfos,
2740 const armnn::TransposeConvolution2dDescriptor& descriptor,
2741 const armnn::ConstTensor& weights,
2742 const armnn::Optional<armnn::ConstTensor>& biases) :
2743 LayerVerifierBase(layerName, inputInfos, outputInfos),
2744 m_Descriptor(descriptor),
2745 m_Weights(weights),
2746 m_Biases(biases)
2747 {}
2748
2749 void VisitTransposeConvolution2dLayer(const armnn::IConnectableLayer* layer,
2750 const armnn::TransposeConvolution2dDescriptor& descriptor,
2751 const armnn::ConstTensor& weights,
2752 const armnn::Optional<armnn::ConstTensor>& biases,
2753 const char* name) override
2754 {
2755 VerifyNameAndConnections(layer, name);
2756 VerifyDescriptor(descriptor);
2757
2758 // check weights
2759 CompareConstTensor(weights, m_Weights);
2760
2761 // check biases
2762 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
2763 BOOST_CHECK(m_Biases.has_value() == m_Descriptor.m_BiasEnabled);
2764
2765 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
2766
2767 if (biases.has_value() && m_Biases.has_value())
2768 {
2769 CompareConstTensor(biases.value(), m_Biases.value());
2770 }
2771 }
2772
2773 private:
2774 void VerifyDescriptor(const armnn::TransposeConvolution2dDescriptor& descriptor)
2775 {
2776 BOOST_CHECK(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
2777 BOOST_CHECK(descriptor.m_PadRight == m_Descriptor.m_PadRight);
2778 BOOST_CHECK(descriptor.m_PadTop == m_Descriptor.m_PadTop);
2779 BOOST_CHECK(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
2780 BOOST_CHECK(descriptor.m_StrideX == m_Descriptor.m_StrideX);
2781 BOOST_CHECK(descriptor.m_StrideY == m_Descriptor.m_StrideY);
2782 BOOST_CHECK(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
2783 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2784 }
2785
2786 armnn::TransposeConvolution2dDescriptor m_Descriptor;
2787 armnn::ConstTensor m_Weights;
2788 armnn::Optional<armnn::ConstTensor> m_Biases;
2789 };
2790
2791 const std::string layerName("transposeConvolution2d");
2792 const armnn::TensorInfo inputInfo ({ 1, 7, 7, 1 }, armnn::DataType::Float32);
2793 const armnn::TensorInfo outputInfo({ 1, 9, 9, 1 }, armnn::DataType::Float32);
2794
2795 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
2796 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
2797
2798 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
2799 armnn::ConstTensor weights(weightsInfo, weightsData);
2800
2801 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
2802 armnn::ConstTensor biases(biasesInfo, biasesData);
2803
2804 armnn::TransposeConvolution2dDescriptor descriptor;
2805 descriptor.m_PadLeft = 1;
2806 descriptor.m_PadRight = 1;
2807 descriptor.m_PadTop = 1;
2808 descriptor.m_PadBottom = 1;
2809 descriptor.m_StrideX = 1;
2810 descriptor.m_StrideY = 1;
2811 descriptor.m_BiasEnabled = true;
2812 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
2813
2814 armnn::INetworkPtr network = armnn::INetwork::Create();
2815 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2816 armnn::IConnectableLayer* const convLayer =
2817 network->AddTransposeConvolution2dLayer(descriptor,
2818 weights,
2819 armnn::Optional<armnn::ConstTensor>(biases),
2820 layerName.c_str());
2821 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2822
2823 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
2824 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2825
2826 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2827 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2828
2829 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2830 BOOST_CHECK(deserializedNetwork);
2831
2832 TransposeConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
2833 deserializedNetwork->Accept(verifier);
2834}
2835
Sadik Armagandb059fd2019-03-20 12:28:32 +00002836BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
2837{
2838 class ConstantLayerVerifier : public LayerVerifierBase
2839 {
2840 public:
2841 ConstantLayerVerifier(const std::string& layerName,
2842 const std::vector<armnn::TensorInfo>& inputInfos,
2843 const std::vector<armnn::TensorInfo>& outputInfos,
2844 const armnn::ConstTensor& layerInput)
2845 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2846 , m_LayerInput(layerInput) {}
2847
2848 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2849 const armnn::ConstTensor& input,
2850 const char* name) override
2851 {
2852 VerifyNameAndConnections(layer, name);
2853
2854 CompareConstTensor(input, m_LayerInput);
2855 }
2856
2857 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
2858
2859 private:
2860 armnn::ConstTensor m_LayerInput;
2861 };
2862
2863 const std::string layerName("constant");
2864 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
2865
2866 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2867 armnn::ConstTensor constTensor(info, constantData);
2868
2869 armnn::INetworkPtr network(armnn::INetwork::Create());
2870 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2871 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2872 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2873 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2874
2875 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2876 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2877 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2878
2879 input->GetOutputSlot(0).SetTensorInfo(info);
2880 constant->GetOutputSlot(0).SetTensorInfo(info);
2881 add->GetOutputSlot(0).SetTensorInfo(info);
2882
2883 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2884 BOOST_CHECK(deserializedNetwork);
2885
2886 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
2887 deserializedNetwork->Accept(verifier);
2888}
2889
Jim Flynn11af3752019-03-19 17:22:29 +00002890class VerifyLstmLayer : public LayerVerifierBase
2891{
2892public:
2893 VerifyLstmLayer(const std::string& layerName,
2894 const std::vector<armnn::TensorInfo>& inputInfos,
2895 const std::vector<armnn::TensorInfo>& outputInfos,
2896 const armnn::LstmDescriptor& descriptor,
2897 const armnn::LstmInputParams& inputParams) :
2898 LayerVerifierBase(layerName, inputInfos, outputInfos), m_Descriptor(descriptor), m_InputParams(inputParams)
2899 {
2900 }
2901 void VisitLstmLayer(const armnn::IConnectableLayer* layer,
2902 const armnn::LstmDescriptor& descriptor,
2903 const armnn::LstmInputParams& params,
2904 const char* name)
2905 {
2906 VerifyNameAndConnections(layer, name);
2907 VerifyDescriptor(descriptor);
2908 VerifyInputParameters(params);
2909 }
2910protected:
2911 void VerifyDescriptor(const armnn::LstmDescriptor& descriptor)
2912 {
2913 BOOST_TEST(m_Descriptor.m_ActivationFunc == descriptor.m_ActivationFunc);
2914 BOOST_TEST(m_Descriptor.m_ClippingThresCell == descriptor.m_ClippingThresCell);
2915 BOOST_TEST(m_Descriptor.m_ClippingThresProj == descriptor.m_ClippingThresProj);
2916 BOOST_TEST(m_Descriptor.m_CifgEnabled == descriptor.m_CifgEnabled);
2917 BOOST_TEST(m_Descriptor.m_PeepholeEnabled = descriptor.m_PeepholeEnabled);
2918 BOOST_TEST(m_Descriptor.m_ProjectionEnabled == descriptor.m_ProjectionEnabled);
Jan Eilersf8c62972019-07-17 11:07:49 +01002919 BOOST_TEST(m_Descriptor.m_LayerNormEnabled == descriptor.m_LayerNormEnabled);
Jim Flynn11af3752019-03-19 17:22:29 +00002920 }
2921 void VerifyInputParameters(const armnn::LstmInputParams& params)
2922 {
2923 VerifyConstTensors(
2924 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
2925 VerifyConstTensors(
2926 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
2927 VerifyConstTensors(
2928 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
2929 VerifyConstTensors(
2930 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
2931 VerifyConstTensors(
2932 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
2933 VerifyConstTensors(
2934 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
2935 VerifyConstTensors(
2936 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
2937 VerifyConstTensors(
2938 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
2939 VerifyConstTensors(
2940 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
2941 VerifyConstTensors(
2942 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
2943 VerifyConstTensors(
2944 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
2945 VerifyConstTensors(
2946 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
2947 VerifyConstTensors(
2948 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
2949 VerifyConstTensors(
2950 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
2951 VerifyConstTensors(
2952 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
2953 VerifyConstTensors(
2954 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
2955 VerifyConstTensors(
2956 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
Jan Eilersf8c62972019-07-17 11:07:49 +01002957 VerifyConstTensors(
2958 "m_InputLayerNormWeights", m_InputParams.m_InputLayerNormWeights, params.m_InputLayerNormWeights);
2959 VerifyConstTensors(
2960 "m_ForgetLayerNormWeights", m_InputParams.m_ForgetLayerNormWeights, params.m_ForgetLayerNormWeights);
2961 VerifyConstTensors(
2962 "m_CellLayerNormWeights", m_InputParams.m_CellLayerNormWeights, params.m_CellLayerNormWeights);
2963 VerifyConstTensors(
2964 "m_OutputLayerNormWeights", m_InputParams.m_OutputLayerNormWeights, params.m_OutputLayerNormWeights);
Jim Flynn11af3752019-03-19 17:22:29 +00002965 }
Jim Flynn11af3752019-03-19 17:22:29 +00002966private:
2967 armnn::LstmDescriptor m_Descriptor;
2968 armnn::LstmInputParams m_InputParams;
2969};
2970
2971BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
2972{
2973 armnn::LstmDescriptor descriptor;
2974 descriptor.m_ActivationFunc = 4;
2975 descriptor.m_ClippingThresProj = 0.0f;
2976 descriptor.m_ClippingThresCell = 0.0f;
2977 descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
2978 descriptor.m_ProjectionEnabled = false;
2979 descriptor.m_PeepholeEnabled = true;
2980
2981 const uint32_t batchSize = 1;
2982 const uint32_t inputSize = 2;
2983 const uint32_t numUnits = 4;
2984 const uint32_t outputSize = numUnits;
2985
2986 armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
2987 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2988 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
2989
2990 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2991 armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
2992
2993 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2994 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
2995
2996 armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
2997 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2998 armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
2999
3000 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
3001 armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
3002
3003 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
3004 armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
3005
3006 armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
3007 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
3008 armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
3009
3010 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
3011 armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
3012
3013 std::vector<float> forgetGateBiasData(numUnits, 1.0f);
3014 armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
3015
3016 std::vector<float> cellBiasData(numUnits, 0.0f);
3017 armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
3018
3019 std::vector<float> outputGateBiasData(numUnits, 0.0f);
3020 armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
3021
3022 armnn::LstmInputParams params;
3023 params.m_InputToForgetWeights = &inputToForgetWeights;
3024 params.m_InputToCellWeights = &inputToCellWeights;
3025 params.m_InputToOutputWeights = &inputToOutputWeights;
3026 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3027 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3028 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3029 params.m_ForgetGateBias = &forgetGateBias;
3030 params.m_CellBias = &cellBias;
3031 params.m_OutputGateBias = &outputGateBias;
3032 params.m_CellToForgetWeights = &cellToForgetWeights;
3033 params.m_CellToOutputWeights = &cellToOutputWeights;
3034
3035 armnn::INetworkPtr network = armnn::INetwork::Create();
3036 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3037 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3038 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3039 const std::string layerName("lstm");
3040 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3041 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3042 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3043 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3044 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3045
3046 // connect up
3047 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3048 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3049 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3050 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
3051
3052 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3053 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3054
3055 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3056 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3057
3058 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3059 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3060
3061 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3062 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3063
3064 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3065 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3066
3067 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3068 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3069
3070 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3071 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3072
3073 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3074 BOOST_CHECK(deserializedNetwork);
3075
3076 VerifyLstmLayer checker(
3077 layerName,
3078 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3079 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3080 descriptor,
3081 params);
3082 deserializedNetwork->Accept(checker);
3083}
3084
3085BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
3086{
3087 armnn::LstmDescriptor descriptor;
3088 descriptor.m_ActivationFunc = 4;
3089 descriptor.m_ClippingThresProj = 0.0f;
3090 descriptor.m_ClippingThresCell = 0.0f;
3091 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
3092 descriptor.m_ProjectionEnabled = true;
3093 descriptor.m_PeepholeEnabled = true;
3094
3095 const uint32_t batchSize = 2;
3096 const uint32_t inputSize = 5;
3097 const uint32_t numUnits = 20;
3098 const uint32_t outputSize = 16;
3099
3100 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3101 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3102 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3103
3104 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3105 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3106
3107 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3108 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3109
3110 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3111 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3112
3113 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3114 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3115 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3116
3117 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3118 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3119
3120 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3121 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3122
3123 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3124 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3125
3126 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3127 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3128 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3129
3130 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3131 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3132
3133 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3134 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3135
3136 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3137 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3138
3139 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3140 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3141
3142 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3143 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3144
3145 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3146 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3147
3148 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3149 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
3150 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3151
3152 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3153 std::vector<float> projectionBiasData(outputSize, 0.f);
3154 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3155
3156 armnn::LstmInputParams params;
3157 params.m_InputToForgetWeights = &inputToForgetWeights;
3158 params.m_InputToCellWeights = &inputToCellWeights;
3159 params.m_InputToOutputWeights = &inputToOutputWeights;
3160 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3161 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3162 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3163 params.m_ForgetGateBias = &forgetGateBias;
3164 params.m_CellBias = &cellBias;
3165 params.m_OutputGateBias = &outputGateBias;
3166
3167 // additional params because: descriptor.m_CifgEnabled = false
3168 params.m_InputToInputWeights = &inputToInputWeights;
3169 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3170 params.m_CellToInputWeights = &cellToInputWeights;
3171 params.m_InputGateBias = &inputGateBias;
3172
3173 // additional params because: descriptor.m_ProjectionEnabled = true
3174 params.m_ProjectionWeights = &projectionWeights;
3175 params.m_ProjectionBias = &projectionBias;
3176
3177 // additional params because: descriptor.m_PeepholeEnabled = true
3178 params.m_CellToForgetWeights = &cellToForgetWeights;
3179 params.m_CellToOutputWeights = &cellToOutputWeights;
3180
3181 armnn::INetworkPtr network = armnn::INetwork::Create();
3182 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3183 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3184 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3185 const std::string layerName("lstm");
3186 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3187 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3188 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3189 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3190 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3191
3192 // connect up
3193 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3194 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3195 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3196 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3197
3198 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3199 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3200
3201 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3202 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3203
3204 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3205 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3206
3207 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3208 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3209
3210 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3211 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3212
3213 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3214 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3215
3216 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3217 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3218
3219 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3220 BOOST_CHECK(deserializedNetwork);
3221
3222 VerifyLstmLayer checker(
3223 layerName,
3224 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3225 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3226 descriptor,
3227 params);
3228 deserializedNetwork->Accept(checker);
3229}
3230
Jan Eilersf8c62972019-07-17 11:07:49 +01003231BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeWithProjectionWithLayerNorm)
3232{
3233 armnn::LstmDescriptor descriptor;
3234 descriptor.m_ActivationFunc = 4;
3235 descriptor.m_ClippingThresProj = 0.0f;
3236 descriptor.m_ClippingThresCell = 0.0f;
3237 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
3238 descriptor.m_ProjectionEnabled = true;
3239 descriptor.m_PeepholeEnabled = true;
3240 descriptor.m_LayerNormEnabled = true;
3241
3242 const uint32_t batchSize = 2;
3243 const uint32_t inputSize = 5;
3244 const uint32_t numUnits = 20;
3245 const uint32_t outputSize = 16;
3246
3247 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3248 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3249 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3250
3251 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3252 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3253
3254 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3255 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3256
3257 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3258 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3259
3260 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3261 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3262 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3263
3264 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3265 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3266
3267 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3268 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3269
3270 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3271 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3272
3273 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3274 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3275 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3276
3277 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3278 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3279
3280 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3281 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3282
3283 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3284 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3285
3286 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3287 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3288
3289 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3290 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3291
3292 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3293 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3294
3295 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3296 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
3297 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3298
3299 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3300 std::vector<float> projectionBiasData(outputSize, 0.f);
3301 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3302
3303 std::vector<float> inputLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3304 armnn::ConstTensor inputLayerNormWeights(tensorInfo20, forgetGateBiasData);
3305
3306 std::vector<float> forgetLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3307 armnn::ConstTensor forgetLayerNormWeights(tensorInfo20, forgetGateBiasData);
3308
3309 std::vector<float> cellLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3310 armnn::ConstTensor cellLayerNormWeights(tensorInfo20, forgetGateBiasData);
3311
3312 std::vector<float> outLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3313 armnn::ConstTensor outLayerNormWeights(tensorInfo20, forgetGateBiasData);
3314
3315 armnn::LstmInputParams params;
3316 params.m_InputToForgetWeights = &inputToForgetWeights;
3317 params.m_InputToCellWeights = &inputToCellWeights;
3318 params.m_InputToOutputWeights = &inputToOutputWeights;
3319 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3320 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3321 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3322 params.m_ForgetGateBias = &forgetGateBias;
3323 params.m_CellBias = &cellBias;
3324 params.m_OutputGateBias = &outputGateBias;
3325
3326 // additional params because: descriptor.m_CifgEnabled = false
3327 params.m_InputToInputWeights = &inputToInputWeights;
3328 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3329 params.m_CellToInputWeights = &cellToInputWeights;
3330 params.m_InputGateBias = &inputGateBias;
3331
3332 // additional params because: descriptor.m_ProjectionEnabled = true
3333 params.m_ProjectionWeights = &projectionWeights;
3334 params.m_ProjectionBias = &projectionBias;
3335
3336 // additional params because: descriptor.m_PeepholeEnabled = true
3337 params.m_CellToForgetWeights = &cellToForgetWeights;
3338 params.m_CellToOutputWeights = &cellToOutputWeights;
3339
3340 // additional params because: despriptor.m_LayerNormEnabled = true
3341 params.m_InputLayerNormWeights = &inputLayerNormWeights;
3342 params.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
3343 params.m_CellLayerNormWeights = &cellLayerNormWeights;
3344 params.m_OutputLayerNormWeights = &outLayerNormWeights;
3345
3346 armnn::INetworkPtr network = armnn::INetwork::Create();
3347 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3348 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3349 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3350 const std::string layerName("lstm");
3351 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3352 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3353 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3354 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3355 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3356
3357 // connect up
3358 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3359 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3360 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3361 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3362
3363 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3364 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3365
3366 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3367 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3368
3369 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3370 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3371
3372 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3373 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3374
3375 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3376 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3377
3378 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3379 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3380
3381 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3382 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3383
3384 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3385 BOOST_CHECK(deserializedNetwork);
3386
3387 VerifyLstmLayer checker(
3388 layerName,
3389 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3390 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3391 descriptor,
3392 params);
3393 deserializedNetwork->Accept(checker);
3394}
3395
3396BOOST_AUTO_TEST_CASE(EnsureLstmLayersBackwardCompatibility)
3397{
3398 // The hex array below is a flat buffer containing a lstm layer with no Cifg, with peephole and projection
3399 // enabled. That array is created before additional layer normalization parameters where added to the
3400 // lstm serializer. That way it can be tested if a lstm model with the old parameter configuration can still be
3401 // loaded
3402 unsigned int size = 10900;
3403 const unsigned char LstmNoCifgWithPeepholeAndProjection_Model[] = {
3404 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
3405 0x0C,0x00,0x00,0x00,0x2C,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0xDC,0x29,0x00,0x00,
3406 0x38,0x29,0x00,0x00,0xB4,0x28,0x00,0x00,0x94,0x01,0x00,0x00,0x3C,0x01,0x00,0x00,0xE0,0x00,0x00,0x00,
3407 0x84,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3408 0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
3409 0x07,0x00,0x00,0x00,0x70,0xD6,0xFF,0xFF,0x00,0x00,0x00,0x0B,0x04,0x00,0x00,0x00,0x06,0xD7,0xFF,0xFF,
3410 0x04,0x00,0x00,0x00,0x88,0xD7,0xFF,0xFF,0x08,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xF6,0xD6,0xFF,0xFF,
3411 0x07,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
3412 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3413 0xE8,0xD7,0xFF,0xFF,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xC8,0xD6,0xFF,0xFF,0x00,0x00,0x00,0x0B,
3414 0x04,0x00,0x00,0x00,0x5E,0xD7,0xFF,0xFF,0x04,0x00,0x00,0x00,0xE0,0xD7,0xFF,0xFF,0x08,0x00,0x00,0x00,
3415 0x02,0x00,0x00,0x00,0x4E,0xD7,0xFF,0xFF,0x06,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
3416 0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3417 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xD8,0xFF,0xFF,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3418 0x20,0xD7,0xFF,0xFF,0x00,0x00,0x00,0x0B,0x04,0x00,0x00,0x00,0xB6,0xD7,0xFF,0xFF,0x04,0x00,0x00,0x00,
3419 0x38,0xD8,0xFF,0xFF,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xA6,0xD7,0xFF,0xFF,0x05,0x00,0x00,0x00,
3420 0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3421 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0xD8,0xFF,0xFF,
3422 0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x78,0xD7,0xFF,0xFF,0x00,0x00,0x00,0x0B,0x04,0x00,0x00,0x00,
3423 0x0E,0xD8,0xFF,0xFF,0x04,0x00,0x00,0x00,0x16,0xD8,0xFF,0xFF,0x04,0x00,0x00,0x00,0xFA,0xD7,0xFF,0xFF,
3424 0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
3425 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3426 0xEC,0xD8,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xD8,0xFF,0xFF,0x00,0x00,0x00,0x23,
3427 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x12,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
3428 0xE0,0x25,0x00,0x00,0xD0,0x25,0x00,0x00,0x2C,0x00,0x00,0x00,0x00,0x00,0x26,0x00,0x48,0x00,0x04,0x00,
3429 0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,0x18,0x00,0x1C,0x00,0x20,0x00,0x24,0x00,0x28,0x00,0x2C,0x00,
3430 0x30,0x00,0x34,0x00,0x38,0x00,0x3C,0x00,0x40,0x00,0x44,0x00,0x26,0x00,0x00,0x00,0xC4,0x23,0x00,0x00,
3431 0xF8,0x21,0x00,0x00,0x2C,0x20,0x00,0x00,0xF0,0x1A,0x00,0x00,0xB4,0x15,0x00,0x00,0x78,0x10,0x00,0x00,
3432 0xF0,0x0F,0x00,0x00,0x68,0x0F,0x00,0x00,0xE0,0x0E,0x00,0x00,0x14,0x0D,0x00,0x00,0xD8,0x07,0x00,0x00,
3433 0x50,0x07,0x00,0x00,0xC8,0x06,0x00,0x00,0x8C,0x01,0x00,0x00,0x14,0x01,0x00,0x00,0x8C,0x00,0x00,0x00,
3434 0x04,0x00,0x00,0x00,0xEE,0xD7,0xFF,0xFF,0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
3435 0xFE,0xD8,0xFF,0xFF,0x04,0x00,0x00,0x00,0x14,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,0x00,0x00,
3437 0x00,0x00,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,0x00,0x00,
3439 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5A,0xD8,0xFF,0xFF,0x00,0x00,0x00,0x01,
3440 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x72,0xD8,0xFF,0xFF,
3441 0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x82,0xD9,0xFF,0xFF,0x04,0x00,0x00,0x00,
3442 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3443 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3444 0x00,0x00,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,0x00,0x00,
3446 0x00,0x00,0x00,0x00,0xDE,0xD8,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3447 0x01,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0xF6,0xD8,0xFF,0xFF,0x00,0x00,0x00,0x03,0x54,0x00,0x00,0x00,
3448 0x04,0x00,0x00,0x00,0x06,0xDA,0xFF,0xFF,0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3449 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3450 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3451 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3452 0x52,0xD9,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3453 0x10,0x00,0x00,0x00,0x6A,0xD9,0xFF,0xFF,0x00,0x00,0x00,0x03,0x14,0x05,0x00,0x00,0x04,0x00,0x00,0x00,
3454 0x7A,0xDA,0xFF,0xFF,0x04,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3455 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3456 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3457 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3458 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3459 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3460 0x00,0x00,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,0x00,0x00,
3462 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3463 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3464 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3465 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3466 0x00,0x00,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,0x00,0x00,
3468 0x00,0x00,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,0x00,0x00,
3470 0x00,0x00,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,0x00,0x00,
3472 0x00,0x00,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,0x00,0x00,
3474 0x00,0x00,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,0x00,0x00,
3476 0x00,0x00,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,0x00,0x00,
3478 0x00,0x00,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,0x00,0x00,
3480 0x00,0x00,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,0x00,0x00,
3482 0x00,0x00,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,0x00,0x00,
3484 0x00,0x00,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,0x00,0x00,
3486 0x00,0x00,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,0x00,0x00,
3488 0x00,0x00,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,0x00,0x00,
3490 0x00,0x00,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,0x00,0x00,
3492 0x00,0x00,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,0x00,0x00,
3494 0x00,0x00,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,0x00,0x00,
3496 0x00,0x00,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,0x00,0x00,
3498 0x00,0x00,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,0x00,0x00,
3500 0x00,0x00,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,0x00,0x00,
3502 0x00,0x00,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,0x00,0x00,
3504 0x00,0x00,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,0x00,0x00,
3506 0x00,0x00,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,0x00,0x00,
3508 0x00,0x00,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,0x00,0x00,
3510 0x00,0x00,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,0x00,0x00,
3512 0x00,0x00,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,0x00,0x00,
3514 0x00,0x00,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,0x00,0x00,
3516 0x00,0x00,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,0x00,0x00,
3518 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x86,0xDE,0xFF,0xFF,0x00,0x00,0x00,0x01,
3519 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
3520 0xA2,0xDE,0xFF,0xFF,0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xB2,0xDF,0xFF,0xFF,
3521 0x04,0x00,0x00,0x00,0x14,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,0x00,0x00,
3523 0x00,0x00,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,0x00,0x00,
3525 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0xDF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
3526 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x26,0xDF,0xFF,0xFF,0x00,0x00,0x00,0x03,
3527 0x64,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x36,0xE0,0xFF,0xFF,0x04,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
3528 0x00,0x00,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,0x00,0x00,
3530 0x00,0x00,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,0x00,0x00,
3532 0x92,0xDF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3533 0x14,0x00,0x00,0x00,0xAA,0xDF,0xFF,0xFF,0x00,0x00,0x00,0x03,0x14,0x05,0x00,0x00,0x04,0x00,0x00,0x00,
3534 0xBA,0xE0,0xFF,0xFF,0x04,0x00,0x00,0x00,0x40,0x01,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,0x00,0x00,
3536 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3537 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3538 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3539 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3540 0x00,0x00,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,0x00,0x00,
3542 0x00,0x00,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,0x00,0x00,
3544 0x00,0x00,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,0x00,0x00,
3546 0x00,0x00,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,0x00,0x00,
3548 0x00,0x00,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,0x00,0x00,
3550 0x00,0x00,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,0x00,0x00,
3552 0x00,0x00,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,0x00,0x00,
3554 0x00,0x00,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,0x00,0x00,
3556 0x00,0x00,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,0x00,0x00,
3558 0x00,0x00,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,0x00,0x00,
3560 0x00,0x00,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,0x00,0x00,
3562 0x00,0x00,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,0x00,0x00,
3564 0x00,0x00,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,0x00,0x00,
3566 0x00,0x00,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,0x00,0x00,
3568 0x00,0x00,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,0x00,0x00,
3570 0x00,0x00,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,0x00,0x00,
3572 0x00,0x00,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,0x00,0x00,
3574 0x00,0x00,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,0x00,0x00,
3576 0x00,0x00,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,0x00,0x00,
3578 0x00,0x00,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,0x00,0x00,
3580 0x00,0x00,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,0x00,0x00,
3582 0x00,0x00,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,0x00,0x00,
3584 0x00,0x00,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,0x00,0x00,
3586 0x00,0x00,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,0x00,0x00,
3588 0x00,0x00,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,0x00,0x00,
3590 0x00,0x00,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,0x00,0x00,
3592 0x00,0x00,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,0x00,0x00,
3594 0x00,0x00,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,0x00,0x00,
3596 0x00,0x00,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,0x00,0x00,
3598 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xE4,0xFF,0xFF,0x00,0x00,0x00,0x01,
3599 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
3600 0xE2,0xE4,0xFF,0xFF,0x00,0x00,0x00,0x03,0xA4,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xF2,0xE5,0xFF,0xFF,
3601 0x04,0x00,0x00,0x00,0x64,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,0x00,0x00,
3603 0x00,0x00,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,0x00,0x00,
3605 0x00,0x00,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,0x00,0x00,
3607 0x00,0x00,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,0x00,0x00,
3609 0x00,0x00,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,0x00,0x00,
3611 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3612 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3613 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3614 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3615 0x00,0x00,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,0x00,0x00,
3617 0x00,0x00,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,0x00,0x00,
3619 0x00,0x00,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,0x00,0x00,
3621 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0xE6,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
3622 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0xAA,0xE6,0xFF,0xFF,
3623 0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xBA,0xE7,0xFF,0xFF,0x04,0x00,0x00,0x00,
3624 0x14,0x00,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,0x00,0x00,
3626 0x00,0x00,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,0x00,0x00,
3628 0x00,0x00,0x00,0x00,0x16,0xE7,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3629 0x01,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x2E,0xE7,0xFF,0xFF,0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,
3630 0x04,0x00,0x00,0x00,0x3E,0xE8,0xFF,0xFF,0x04,0x00,0x00,0x00,0x14,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,0x00,0x00,
3632 0x00,0x00,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,0x00,0x00,
3634 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xE7,0xFF,0xFF,
3635 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
3636 0xB2,0xE7,0xFF,0xFF,0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xC2,0xE8,0xFF,0xFF,
3637 0x04,0x00,0x00,0x00,0x14,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,0x00,0x00,
3639 0x00,0x00,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,0x00,0x00,
3641 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0xE8,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
3642 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x36,0xE8,0xFF,0xFF,0x00,0x00,0x00,0x03,
3643 0x14,0x05,0x00,0x00,0x04,0x00,0x00,0x00,0x46,0xE9,0xFF,0xFF,0x04,0x00,0x00,0x00,0x40,0x01,0x00,0x00,
3644 0x00,0x00,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,0x00,0x00,
3646 0x00,0x00,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,0x00,0x00,
3648 0x00,0x00,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,0x00,0x00,
3650 0x00,0x00,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,0x00,0x00,
3652 0x00,0x00,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,0x00,0x00,
3654 0x00,0x00,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,0x00,0x00,
3656 0x00,0x00,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,0x00,0x00,
3658 0x00,0x00,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,0x00,0x00,
3660 0x00,0x00,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,0x00,0x00,
3662 0x00,0x00,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,0x00,0x00,
3664 0x00,0x00,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,0x00,0x00,
3666 0x00,0x00,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,0x00,0x00,
3668 0x00,0x00,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,0x00,0x00,
3670 0x00,0x00,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,0x00,0x00,
3672 0x00,0x00,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,0x00,0x00,
3674 0x00,0x00,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,0x00,0x00,
3676 0x00,0x00,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,0x00,0x00,
3678 0x00,0x00,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,0x00,0x00,
3680 0x00,0x00,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,0x00,0x00,
3682 0x00,0x00,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,0x00,0x00,
3684 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3685 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3686 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3687 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3688 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3689 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3690 0x00,0x00,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,0x00,0x00,
3692 0x00,0x00,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,0x00,0x00,
3694 0x00,0x00,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,0x00,0x00,
3696 0x00,0x00,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,0x00,0x00,
3698 0x00,0x00,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,0x00,0x00,
3700 0x00,0x00,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,0x00,0x00,
3702 0x00,0x00,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,0x00,0x00,
3704 0x00,0x00,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,0x00,0x00,
3706 0x00,0x00,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,0x00,0x00,
3708 0x52,0xED,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3709 0x14,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x6E,0xED,0xFF,0xFF,0x00,0x00,0x00,0x03,0x14,0x05,0x00,0x00,
3710 0x04,0x00,0x00,0x00,0x7E,0xEE,0xFF,0xFF,0x04,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
3711 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3712 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3713 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3714 0x00,0x00,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,0x00,0x00,
3716 0x00,0x00,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,0x00,0x00,
3718 0x00,0x00,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,0x00,0x00,
3720 0x00,0x00,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,0x00,0x00,
3722 0x00,0x00,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,0x00,0x00,
3724 0x00,0x00,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,0x00,0x00,
3726 0x00,0x00,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,0x00,0x00,
3728 0x00,0x00,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,0x00,0x00,
3730 0x00,0x00,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,0x00,0x00,
3732 0x00,0x00,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,0x00,0x00,
3734 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3735 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3736 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3737 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3738 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3739 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3740 0x00,0x00,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,0x00,0x00,
3742 0x00,0x00,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,0x00,0x00,
3744 0x00,0x00,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,0x00,0x00,
3746 0x00,0x00,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,0x00,0x00,
3748 0x00,0x00,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,0x00,0x00,
3750 0x00,0x00,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,0x00,0x00,
3752 0x00,0x00,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,0x00,0x00,
3754 0x00,0x00,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,0x00,0x00,
3756 0x00,0x00,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,0x00,0x00,
3758 0x00,0x00,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,0x00,0x00,
3760 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3761 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3762 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3763 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3764 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3765 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3766 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3767 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3768 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3769 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3770 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3771 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3772 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3773 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3774 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0xF2,0xFF,0xFF,
3775 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
3776 0x10,0x00,0x00,0x00,0xA6,0xF2,0xFF,0xFF,0x00,0x00,0x00,0x03,0x14,0x05,0x00,0x00,0x04,0x00,0x00,0x00,
3777 0xB6,0xF3,0xFF,0xFF,0x04,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3778 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3779 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3780 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3781 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3782 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3783 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3784 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3785 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3786 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3787 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3788 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3789 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3790 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3791 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3792 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3793 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3794 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3795 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3796 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3797 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3798 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3799 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3800 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3801 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3802 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3803 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3804 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3805 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3806 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3807 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3808 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3809 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3810 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3811 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3812 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3813 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3814 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3815 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3816 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3817 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3818 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3819 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3820 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3821 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3822 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3823 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3824 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3825 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3826 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3827 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3828 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3829 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3830 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3831 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3832 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3833 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3834 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3835 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3836 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3837 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3838 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3839 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3840 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3841 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC2,0xF7,0xFF,0xFF,0x00,0x00,0x00,0x01,
3842 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
3843 0xDE,0xF7,0xFF,0xFF,0x00,0x00,0x00,0x03,0xA4,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xEE,0xF8,0xFF,0xFF,
3844 0x04,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3845 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3846 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3847 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3848 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3849 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3850 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3851 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3852 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3853 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3854 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3855 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3856 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3857 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3858 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3859 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3860 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3861 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3862 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3863 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3864 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0xF9,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
3865 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0xA6,0xF9,0xFF,0xFF,
3866 0x00,0x00,0x00,0x03,0xA4,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xB6,0xFA,0xFF,0xFF,0x04,0x00,0x00,0x00,
3867 0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3868 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3869 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3870 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3871 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3872 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3873 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3874 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3875 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3876 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3877 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3878 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3879 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3880 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3881 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3882 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3883 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3884 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3885 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3886 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3887 0x00,0x00,0x00,0x00,0x52,0xFB,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3888 0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x6E,0xFB,0xFF,0xFF,0x00,0x00,0x00,0x03,
3889 0xA4,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0x7E,0xFC,0xFF,0xFF,0x04,0x00,0x00,0x00,0x64,0x00,0x00,0x00,
3890 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3891 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3892 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3893 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3894 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3895 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3896 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3897 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3898 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3899 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3900 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3901 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3902 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3903 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3904 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3905 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3906 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3907 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3908 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3909 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3910 0x1A,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3911 0x14,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x10,0x00,0x0C,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x05,0x00,
3912 0x06,0x00,0x07,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x04,0x00,0x00,0x00,0x2E,0xFE,0xFF,0xFF,
3913 0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
3914 0x04,0x00,0x00,0x00,0x6C,0x73,0x74,0x6D,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xEC,0x00,0x00,0x00,
3915 0xD0,0x00,0x00,0x00,0xB4,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x88,0x00,0x00,0x00,0x5C,0x00,0x00,0x00,
3916 0x30,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x14,0xFF,0xFF,0xFF,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
3917 0xA6,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3918 0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x3C,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
3919 0xCE,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3920 0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x64,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
3921 0xF6,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3922 0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0xB4,0xFE,0xFF,0xFF,0x04,0x00,0x00,0x00,0x1A,0xFE,0xFF,0xFF,
3923 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3924 0x50,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3925 0x08,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3926 0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3927 0x00,0x00,0x00,0x00,0xE8,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00,0x7E,0xFF,0xFF,0xFF,
3928 0x0C,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
3929 0x02,0x00,0x00,0x00,0x76,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3930 0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3931 0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x68,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0xCE,0xFE,0xFF,0xFF,
3932 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3933 0x10,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x09,
3934 0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,
3935 0x08,0x00,0x0E,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3936 0x00,0x00,0x0E,0x00,0x18,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,0x0E,0x00,0x00,0x00,
3937 0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
3938 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,
3939 0x08,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x6E,0xFF,0xFF,0xFF,
3940 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3941 0x14,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x09,
3942 0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0A,0x00,0x04,0x00,
3943 0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x08,0x00,
3944 0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
3945 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3946 0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
3947 0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
3948 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0 };
3949
3950 std::stringstream ss;
3951 for (unsigned int i = 0; i < size; ++i)
3952 {
3953 ss << LstmNoCifgWithPeepholeAndProjection_Model[i];
3954 }
3955 std::string lstmLayerNetwork = ss.str();
3956 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(lstmLayerNetwork);
3957 BOOST_CHECK(deserializedNetwork);
3958
3959 // generating the same model parameters which where used to serialize the model (Layer norm is not specified)
3960 armnn::LstmDescriptor descriptor;
3961 descriptor.m_ActivationFunc = 4;
3962 descriptor.m_ClippingThresProj = 0.0f;
3963 descriptor.m_ClippingThresCell = 0.0f;
3964 descriptor.m_CifgEnabled = false;
3965 descriptor.m_ProjectionEnabled = true;
3966 descriptor.m_PeepholeEnabled = true;
3967
3968 const uint32_t batchSize = 2;
3969 const uint32_t inputSize = 5;
3970 const uint32_t numUnits = 20;
3971 const uint32_t outputSize = 16;
3972
3973 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3974 std::vector<float> inputToInputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3975 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3976
3977 std::vector<float> inputToForgetWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3978 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3979
3980 std::vector<float> inputToCellWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3981 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3982
3983 std::vector<float> inputToOutputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3984 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3985
3986 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3987 std::vector<float> inputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3988 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3989
3990 std::vector<float> forgetGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3991 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3992
3993 std::vector<float> cellBiasData(tensorInfo20.GetNumElements(), 0.0f);
3994 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3995
3996 std::vector<float> outputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3997 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3998
3999 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
4000 std::vector<float> recurrentToInputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
4001 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
4002
4003 std::vector<float> recurrentToForgetWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
4004 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
4005
4006 std::vector<float> recurrentToCellWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
4007 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
4008
4009 std::vector<float> recurrentToOutputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
4010 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
4011
4012 std::vector<float> cellToInputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
4013 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
4014
4015 std::vector<float> cellToForgetWeightsData(tensorInfo20.GetNumElements(), 0.0f);
4016 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
4017
4018 std::vector<float> cellToOutputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
4019 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
4020
4021 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
4022 std::vector<float> projectionWeightsData(tensorInfo16x20.GetNumElements(), 0.0f);
4023 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
4024
4025 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
4026 std::vector<float> projectionBiasData(outputSize, 0.0f);
4027 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
4028
4029 armnn::LstmInputParams params;
4030 params.m_InputToForgetWeights = &inputToForgetWeights;
4031 params.m_InputToCellWeights = &inputToCellWeights;
4032 params.m_InputToOutputWeights = &inputToOutputWeights;
4033 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4034 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4035 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4036 params.m_ForgetGateBias = &forgetGateBias;
4037 params.m_CellBias = &cellBias;
4038 params.m_OutputGateBias = &outputGateBias;
4039
4040 // additional params because: descriptor.m_CifgEnabled = false
4041 params.m_InputToInputWeights = &inputToInputWeights;
4042 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
4043 params.m_CellToInputWeights = &cellToInputWeights;
4044 params.m_InputGateBias = &inputGateBias;
4045
4046 // additional params because: descriptor.m_ProjectionEnabled = true
4047 params.m_ProjectionWeights = &projectionWeights;
4048 params.m_ProjectionBias = &projectionBias;
4049
4050 // additional params because: descriptor.m_PeepholeEnabled = true
4051 params.m_CellToForgetWeights = &cellToForgetWeights;
4052 params.m_CellToOutputWeights = &cellToOutputWeights;
4053
4054 const std::string layerName("lstm");
4055 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
4056 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
4057 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
4058 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
4059
4060 // lets verify that the deserialized model without the new layer normalization parameters still works
4061 VerifyLstmLayer checker(
4062 layerName,
4063 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
4064 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
4065 descriptor,
4066 params);
4067 deserializedNetwork->Accept(checker);
4068}
4069
Jan Eilers5b01a892019-07-23 09:47:43 +01004070class VerifyQuantizedLstmLayer : public LayerVerifierBase
4071{
4072
4073public:
4074 VerifyQuantizedLstmLayer(const std::string& layerName,
4075 const std::vector<armnn::TensorInfo>& inputInfos,
4076 const std::vector<armnn::TensorInfo>& outputInfos,
4077 const armnn::QuantizedLstmInputParams& inputParams) :
4078 LayerVerifierBase(layerName, inputInfos, outputInfos), m_InputParams(inputParams)
4079 {
4080 }
4081
4082 void VisitQuantizedLstmLayer(const armnn::IConnectableLayer* layer,
4083 const armnn::QuantizedLstmInputParams& params,
4084 const char* name)
4085 {
4086 VerifyNameAndConnections(layer, name);
4087 VerifyInputParameters(params);
4088 }
4089
4090protected:
4091 void VerifyInputParameters(const armnn::QuantizedLstmInputParams& params)
4092 {
4093 VerifyConstTensors("m_InputToInputWeights",
4094 m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
4095 VerifyConstTensors("m_InputToForgetWeights",
4096 m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
4097 VerifyConstTensors("m_InputToCellWeights",
4098 m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
4099 VerifyConstTensors("m_InputToOutputWeights",
4100 m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
4101 VerifyConstTensors("m_RecurrentToInputWeights",
4102 m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
4103 VerifyConstTensors("m_RecurrentToForgetWeights",
4104 m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
4105 VerifyConstTensors("m_RecurrentToCellWeights",
4106 m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
4107 VerifyConstTensors("m_RecurrentToOutputWeights",
4108 m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
4109 VerifyConstTensors("m_InputGateBias",
4110 m_InputParams.m_InputGateBias, params.m_InputGateBias);
4111 VerifyConstTensors("m_ForgetGateBias",
4112 m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
4113 VerifyConstTensors("m_CellBias",
4114 m_InputParams.m_CellBias, params.m_CellBias);
4115 VerifyConstTensors("m_OutputGateBias",
4116 m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
4117 }
4118
4119private:
4120 armnn::QuantizedLstmInputParams m_InputParams;
4121};
4122
4123BOOST_AUTO_TEST_CASE(SerializeDeserializeQuantizedLstm)
4124{
4125 const uint32_t batchSize = 1;
4126 const uint32_t inputSize = 2;
4127 const uint32_t numUnits = 4;
4128 const uint32_t outputSize = numUnits;
4129
4130 std::vector<uint8_t> inputToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4131 std::vector<unsigned int> inputToInputWeightsDimensions = {1, 1, 3, 3};
4132 armnn::ConstTensor inputToInputWeights(armnn::TensorInfo(
4133 4, inputToInputWeightsDimensions.data(),
4134 armnn::DataType::QuantisedAsymm8), inputToInputWeightsData);
4135
4136 std::vector<uint8_t> inputToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4137 std::vector<unsigned int> inputToForgetWeightsDimensions = {1, 1, 3, 3};
4138 armnn::ConstTensor inputToForgetWeights(armnn::TensorInfo(
4139 4, inputToForgetWeightsDimensions.data(),
4140 armnn::DataType::QuantisedAsymm8), inputToForgetWeightsData);
4141
4142 std::vector<uint8_t> inputToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4143 std::vector<unsigned int> inputToCellWeightsDimensions = {1, 1, 3, 3};
4144 armnn::ConstTensor inputToCellWeights(armnn::TensorInfo(
4145 4, inputToCellWeightsDimensions.data(),
4146 armnn::DataType::QuantisedAsymm8), inputToCellWeightsData);
4147
4148 std::vector<uint8_t> inputToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4149 std::vector<unsigned int> inputToOutputWeightsDimensions = {1, 1, 3, 3};
4150 armnn::ConstTensor inputToOutputWeights(armnn::TensorInfo(
4151 4, inputToOutputWeightsDimensions.data(),
4152 armnn::DataType::QuantisedAsymm8), inputToOutputWeightsData);
4153
4154 std::vector<uint8_t> recurrentToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4155 std::vector<unsigned int> recurrentToInputWeightsDimensions = {1, 1, 3, 3};
4156 armnn::ConstTensor recurrentToInputWeights(armnn::TensorInfo(
4157 4, recurrentToInputWeightsDimensions.data(),
4158 armnn::DataType::QuantisedAsymm8), recurrentToInputWeightsData);
4159
4160 std::vector<uint8_t> recurrentToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4161 std::vector<unsigned int> recurrentToForgetWeightsDimensions = {1, 1, 3, 3};
4162 armnn::ConstTensor recurrentToForgetWeights(armnn::TensorInfo(
4163 4, recurrentToForgetWeightsDimensions.data(),
4164 armnn::DataType::QuantisedAsymm8), recurrentToForgetWeightsData);
4165
4166 std::vector<uint8_t> recurrentToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4167 std::vector<unsigned int> recurrentToCellWeightsDimensions = {1, 1, 3, 3};
4168 armnn::ConstTensor recurrentToCellWeights(armnn::TensorInfo(
4169 4, recurrentToCellWeightsDimensions.data(),
4170 armnn::DataType::QuantisedAsymm8), recurrentToCellWeightsData);
4171
4172 std::vector<uint8_t> recurrentToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4173 std::vector<unsigned int> recurrentToOutputWeightsDimensions = {1, 1, 3, 3};
4174 armnn::ConstTensor recurrentToOutputWeights(armnn::TensorInfo(
4175 4, recurrentToOutputWeightsDimensions.data(),
4176 armnn::DataType::QuantisedAsymm8), recurrentToOutputWeightsData);
4177
4178
4179 std::vector<int32_t> inputGateBiasData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4180 std::vector<unsigned int> inputGateBiasDimensions = {1, 1, 3, 3};
4181 armnn::ConstTensor inputGateBias(armnn::TensorInfo(
4182 4, inputGateBiasDimensions.data(),
4183 armnn::DataType::Signed32), inputGateBiasData);
4184
4185 std::vector<int32_t> forgetGateBiasData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4186 std::vector<unsigned int> forgetGateBiasDimensions = {1, 1, 3, 3};
4187 armnn::ConstTensor forgetGateBias(armnn::TensorInfo(
4188 4, forgetGateBiasDimensions.data(),
4189 armnn::DataType::Signed32), forgetGateBiasData);
4190
4191 std::vector<int32_t> cellBiasData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4192 std::vector<unsigned int> cellBiasDimensions = {1, 1, 3, 3};
4193 armnn::ConstTensor cellBias(armnn::TensorInfo(
4194 4, cellBiasDimensions.data(),
4195 armnn::DataType::Signed32), cellBiasData);
4196
4197 std::vector<int32_t> outputGateBiasData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4198 std::vector<unsigned int> outputGateBiasDimensions = {1, 1, 3, 3};
4199 armnn::ConstTensor outputGateBias(armnn::TensorInfo(
4200 4, outputGateBiasDimensions.data(),
4201 armnn::DataType::Signed32), outputGateBiasData);
4202
4203 armnn::QuantizedLstmInputParams params;
4204 params.m_InputToInputWeights = &inputToInputWeights;
4205 params.m_InputToForgetWeights = &inputToForgetWeights;
4206 params.m_InputToCellWeights = &inputToCellWeights;
4207 params.m_InputToOutputWeights = &inputToOutputWeights;
4208 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
4209 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4210 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4211 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4212 params.m_InputGateBias = &inputGateBias;
4213 params.m_ForgetGateBias = &forgetGateBias;
4214 params.m_CellBias = &cellBias;
4215 params.m_OutputGateBias = &outputGateBias;
4216
4217 armnn::INetworkPtr network = armnn::INetwork::Create();
4218 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
4219 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
4220 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
4221 const std::string layerName("QuantizedLstm");
4222 armnn::IConnectableLayer* const quantizedLstmLayer = network->AddQuantizedLstmLayer(params, layerName.c_str());
4223 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(0);
4224 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(1);
4225
4226 // connect up
4227 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::QuantisedAsymm8);
4228 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Signed32);
4229 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::QuantisedAsymm8);
4230
4231 inputLayer->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(0));
4232 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
4233
4234 cellStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(1));
4235 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
4236
4237 outputStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(2));
4238 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
4239
4240 quantizedLstmLayer->GetOutputSlot(0).Connect(cellStateOut->GetInputSlot(0));
4241 quantizedLstmLayer->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
4242
4243 quantizedLstmLayer->GetOutputSlot(1).Connect(outputLayer->GetInputSlot(0));
4244 quantizedLstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
4245
4246 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
4247 BOOST_CHECK(deserializedNetwork);
4248
4249 VerifyQuantizedLstmLayer checker(
4250 layerName,
4251 {inputTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
4252 {cellStateTensorInfo, outputStateTensorInfo},
4253 params);
4254
4255 deserializedNetwork->Accept(checker);
4256}
4257
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00004258BOOST_AUTO_TEST_SUITE_END()