blob: 79d83f054fde2cb6d899a03218aa9ac6be2a5be9 [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
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000213BOOST_AUTO_TEST_CASE(SerializeAddition)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000214{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000215 class AdditionLayerVerifier : public LayerVerifierBase
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000216 {
217 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000218 AdditionLayerVerifier(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 VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name) override
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000224 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000225 VerifyNameAndConnections(layer, name);
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000226 }
227 };
228
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000229 const std::string layerName("addition");
230 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
231
Mike Kelly8c1701a2019-02-11 17:01:27 +0000232 armnn::INetworkPtr network = armnn::INetwork::Create();
233 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
234 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000235 armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer(layerName.c_str());
236 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000237
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000238 inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
239 inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000240 additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Mike Kelly8c1701a2019-02-11 17:01:27 +0000241
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000242 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
243 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
244 additionLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
Jim Flynn3091b062019-02-15 14:45:04 +0000245
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000246 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000247 BOOST_CHECK(deserializedNetwork);
248
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000249 AdditionLayerVerifier verifier(layerName, {tensorInfo, tensorInfo}, {tensorInfo});
250 deserializedNetwork->Accept(verifier);
251}
Jim Flynnac25a1b2019-02-28 10:40:49 +0000252
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000253BOOST_AUTO_TEST_CASE(SerializeBatchNormalization)
254{
255 class BatchNormalizationLayerVerifier : public LayerVerifierBase
256 {
257 public:
258 BatchNormalizationLayerVerifier(const std::string& layerName,
259 const std::vector<armnn::TensorInfo>& inputInfos,
260 const std::vector<armnn::TensorInfo>& outputInfos,
261 const armnn::BatchNormalizationDescriptor& descriptor,
262 const armnn::ConstTensor& mean,
263 const armnn::ConstTensor& variance,
264 const armnn::ConstTensor& beta,
265 const armnn::ConstTensor& gamma)
266 : LayerVerifierBase(layerName, inputInfos, outputInfos)
267 , m_Descriptor(descriptor)
268 , m_Mean(mean)
269 , m_Variance(variance)
270 , m_Beta(beta)
271 , m_Gamma(gamma) {}
272
273 void VisitBatchNormalizationLayer(const armnn::IConnectableLayer* layer,
274 const armnn::BatchNormalizationDescriptor& descriptor,
275 const armnn::ConstTensor& mean,
276 const armnn::ConstTensor& variance,
277 const armnn::ConstTensor& beta,
278 const armnn::ConstTensor& gamma,
279 const char* name) override
280 {
281 VerifyNameAndConnections(layer, name);
282 VerifyDescriptor(descriptor);
283
284 CompareConstTensor(mean, m_Mean);
285 CompareConstTensor(variance, m_Variance);
286 CompareConstTensor(beta, m_Beta);
287 CompareConstTensor(gamma, m_Gamma);
288 }
289
290 private:
291 void VerifyDescriptor(const armnn::BatchNormalizationDescriptor& descriptor)
292 {
293 BOOST_TEST(descriptor.m_Eps == m_Descriptor.m_Eps);
294 BOOST_TEST(static_cast<int>(descriptor.m_DataLayout) == static_cast<int>(m_Descriptor.m_DataLayout));
295 }
296
297 armnn::BatchNormalizationDescriptor m_Descriptor;
298 armnn::ConstTensor m_Mean;
299 armnn::ConstTensor m_Variance;
300 armnn::ConstTensor m_Beta;
301 armnn::ConstTensor m_Gamma;
302 };
303
304 const std::string layerName("batchNormalization");
305 const armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32);
306 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
307
308 const armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32);
309 const armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32);
310 const armnn::TensorInfo betaInfo({1}, armnn::DataType::Float32);
311 const armnn::TensorInfo gammaInfo({1}, armnn::DataType::Float32);
312
313 armnn::BatchNormalizationDescriptor descriptor;
314 descriptor.m_Eps = 0.0010000000475f;
315 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
316
317 std::vector<float> meanData({5.0});
318 std::vector<float> varianceData({2.0});
319 std::vector<float> betaData({1.0});
320 std::vector<float> gammaData({0.0});
321
322 armnn::ConstTensor mean(meanInfo, meanData);
323 armnn::ConstTensor variance(varianceInfo, varianceData);
324 armnn::ConstTensor beta(betaInfo, betaData);
325 armnn::ConstTensor gamma(gammaInfo, gammaData);
326
327 armnn::INetworkPtr network = armnn::INetwork::Create();
328 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
329 armnn::IConnectableLayer* const batchNormalizationLayer =
330 network->AddBatchNormalizationLayer(descriptor, mean, variance, beta, gamma, layerName.c_str());
331 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
332
333 inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0));
334 batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
335
336 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
337 batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
338
339 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
340 BOOST_CHECK(deserializedNetwork);
341
342 BatchNormalizationLayerVerifier verifier(
343 layerName, {inputInfo}, {outputInfo}, descriptor, mean, variance, beta, gamma);
344 deserializedNetwork->Accept(verifier);
345}
346
347BOOST_AUTO_TEST_CASE(SerializeBatchToSpaceNd)
348{
349 class BatchToSpaceNdLayerVerifier : public LayerVerifierBase
350 {
351 public:
352 BatchToSpaceNdLayerVerifier(const std::string& layerName,
353 const std::vector<armnn::TensorInfo>& inputInfos,
354 const std::vector<armnn::TensorInfo>& outputInfos,
355 const armnn::BatchToSpaceNdDescriptor& descriptor)
356 : LayerVerifierBase(layerName, inputInfos, outputInfos)
357 , m_Descriptor(descriptor) {}
358
359 void VisitBatchToSpaceNdLayer(const armnn::IConnectableLayer* layer,
360 const armnn::BatchToSpaceNdDescriptor& descriptor,
361 const char* name) override
362 {
363 VerifyNameAndConnections(layer, name);
364 VerifyDescriptor(descriptor);
365 }
366
367 private:
368 void VerifyDescriptor(const armnn::BatchToSpaceNdDescriptor& descriptor)
369 {
370 BOOST_TEST(descriptor.m_Crops == m_Descriptor.m_Crops);
371 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
372 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
373 }
374
375 armnn::BatchToSpaceNdDescriptor m_Descriptor;
376 };
377
378 const std::string layerName("spaceToBatchNd");
379 const armnn::TensorInfo inputInfo({4, 1, 2, 2}, armnn::DataType::Float32);
380 const armnn::TensorInfo outputInfo({1, 1, 4, 4}, armnn::DataType::Float32);
381
382 armnn::BatchToSpaceNdDescriptor desc;
383 desc.m_DataLayout = armnn::DataLayout::NCHW;
384 desc.m_BlockShape = {2, 2};
385 desc.m_Crops = {{0, 0}, {0, 0}};
386
387 armnn::INetworkPtr network = armnn::INetwork::Create();
388 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
389 armnn::IConnectableLayer* const batchToSpaceNdLayer = network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
390 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
391
392 inputLayer->GetOutputSlot(0).Connect(batchToSpaceNdLayer->GetInputSlot(0));
393 batchToSpaceNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
394
395 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
396 batchToSpaceNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
397
398 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
399 BOOST_CHECK(deserializedNetwork);
400
401 BatchToSpaceNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
402 deserializedNetwork->Accept(verifier);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000403}
404
Conor Kennedy76277882019-02-26 08:29:54 +0000405BOOST_AUTO_TEST_CASE(SerializeConstant)
406{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000407 class ConstantLayerVerifier : public LayerVerifierBase
Conor Kennedy76277882019-02-26 08:29:54 +0000408 {
409 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000410 ConstantLayerVerifier(const std::string& layerName,
411 const std::vector<armnn::TensorInfo>& inputInfos,
412 const std::vector<armnn::TensorInfo>& outputInfos,
413 const armnn::ConstTensor& layerInput)
414 : LayerVerifierBase(layerName, inputInfos, outputInfos)
415 , m_LayerInput(layerInput) {}
416
417 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
418 const armnn::ConstTensor& input,
419 const char* name) override
Conor Kennedy76277882019-02-26 08:29:54 +0000420 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000421 VerifyNameAndConnections(layer, name);
422
423 CompareConstTensor(input, m_LayerInput);
Conor Kennedy76277882019-02-26 08:29:54 +0000424 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000425
426 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
427
428 private:
429 armnn::ConstTensor m_LayerInput;
Conor Kennedy76277882019-02-26 08:29:54 +0000430 };
431
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000432 const std::string layerName("constant");
433 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
Conor Kennedy76277882019-02-26 08:29:54 +0000434
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000435 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
436 armnn::ConstTensor constTensor(info, constantData);
Conor Kennedy76277882019-02-26 08:29:54 +0000437
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000438 armnn::INetworkPtr network(armnn::INetwork::Create());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000439 armnn::IConnectableLayer* input = network->AddInputLayer(0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000440 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000441 armnn::IConnectableLayer* add = network->AddAdditionLayer();
442 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
Conor Kennedy76277882019-02-26 08:29:54 +0000443
444 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
445 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
446 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
447
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000448 input->GetOutputSlot(0).SetTensorInfo(info);
449 constant->GetOutputSlot(0).SetTensorInfo(info);
450 add->GetOutputSlot(0).SetTensorInfo(info);
Conor Kennedy76277882019-02-26 08:29:54 +0000451
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000452 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Conor Kennedy76277882019-02-26 08:29:54 +0000453 BOOST_CHECK(deserializedNetwork);
454
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000455 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
456 deserializedNetwork->Accept(verifier);
Conor Kennedy76277882019-02-26 08:29:54 +0000457}
458
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000459BOOST_AUTO_TEST_CASE(SerializeConvolution2d)
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000460{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000461 class Convolution2dLayerVerifier : public LayerVerifierBase
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000462 {
463 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000464 Convolution2dLayerVerifier(const std::string& layerName,
465 const std::vector<armnn::TensorInfo>& inputInfos,
466 const std::vector<armnn::TensorInfo>& outputInfos,
467 const armnn::Convolution2dDescriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100468 const armnn::ConstTensor& weights,
469 const armnn::Optional<armnn::ConstTensor>& biases) :
470 LayerVerifierBase(layerName, inputInfos, outputInfos),
471 m_Descriptor(descriptor),
472 m_Weights(weights),
473 m_Biases(biases)
474 {}
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000475
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000476 void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
477 const armnn::Convolution2dDescriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100478 const armnn::ConstTensor& weights,
479 const armnn::Optional<armnn::ConstTensor>& biases,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000480 const char* name) override
481 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000482 VerifyNameAndConnections(layer, name);
483 VerifyDescriptor(descriptor);
484
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100485 // check weights
486 CompareConstTensor(weights, m_Weights);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000487
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100488 // check biases
489 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
490 BOOST_CHECK(m_Biases.has_value() == m_Descriptor.m_BiasEnabled);
491
492 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
493
494 if (biases.has_value() && m_Biases.has_value())
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000495 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100496 CompareConstTensor(biases.value(), m_Biases.value());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000497 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000498 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000499
500 private:
501 void VerifyDescriptor(const armnn::Convolution2dDescriptor& descriptor)
502 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100503 BOOST_CHECK(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
504 BOOST_CHECK(descriptor.m_PadRight == m_Descriptor.m_PadRight);
505 BOOST_CHECK(descriptor.m_PadTop == m_Descriptor.m_PadTop);
506 BOOST_CHECK(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
507 BOOST_CHECK(descriptor.m_StrideX == m_Descriptor.m_StrideX);
508 BOOST_CHECK(descriptor.m_StrideY == m_Descriptor.m_StrideY);
509 BOOST_CHECK(descriptor.m_DilationX == m_Descriptor.m_DilationX);
510 BOOST_CHECK(descriptor.m_DilationY == m_Descriptor.m_DilationY);
511 BOOST_CHECK(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
512 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000513 }
514
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100515 armnn::Convolution2dDescriptor m_Descriptor;
516 armnn::ConstTensor m_Weights;
517 armnn::Optional<armnn::ConstTensor> m_Biases;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000518 };
519
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000520 const std::string layerName("convolution2d");
521 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
522 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000523
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000524 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
525 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000526
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000527 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
528 armnn::ConstTensor weights(weightsInfo, weightsData);
529
530 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
531 armnn::ConstTensor biases(biasesInfo, biasesData);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000532
533 armnn::Convolution2dDescriptor descriptor;
534 descriptor.m_PadLeft = 1;
535 descriptor.m_PadRight = 1;
536 descriptor.m_PadTop = 1;
537 descriptor.m_PadBottom = 1;
538 descriptor.m_StrideX = 2;
539 descriptor.m_StrideY = 2;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100540 descriptor.m_DilationX = 2;
541 descriptor.m_DilationY = 2;
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000542 descriptor.m_BiasEnabled = true;
543 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
544
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000545 armnn::INetworkPtr network = armnn::INetwork::Create();
546 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000547 armnn::IConnectableLayer* const convLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100548 network->AddConvolution2dLayer(descriptor,
549 weights,
550 armnn::Optional<armnn::ConstTensor>(biases),
551 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000552 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000553
554 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000555 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000556
557 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000558 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
559
560 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
561 BOOST_CHECK(deserializedNetwork);
562
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000563 Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
564 deserializedNetwork->Accept(verifier);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000565}
566
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000567BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d)
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000568{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000569 class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBase
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000570 {
571 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000572 DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
573 const std::vector<armnn::TensorInfo>& inputInfos,
574 const std::vector<armnn::TensorInfo>& outputInfos,
575 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100576 const armnn::ConstTensor& weights,
577 const armnn::Optional<armnn::ConstTensor>& biases) :
578 LayerVerifierBase(layerName, inputInfos, outputInfos),
579 m_Descriptor(descriptor),
580 m_Weights(weights),
581 m_Biases(biases)
582 {}
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000583
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000584 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
585 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100586 const armnn::ConstTensor& weights,
587 const armnn::Optional<armnn::ConstTensor>& biases,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000588 const char* name) override
589 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000590 VerifyNameAndConnections(layer, name);
591 VerifyDescriptor(descriptor);
592
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100593 // check weights
594 CompareConstTensor(weights, m_Weights);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000595
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100596 // check biases
597 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
598 BOOST_CHECK(m_Biases.has_value() == m_Descriptor.m_BiasEnabled);
599
600 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
601
602 if (biases.has_value() && m_Biases.has_value())
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000603 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100604 CompareConstTensor(biases.value(), m_Biases.value());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000605 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000606 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000607
608 private:
609 void VerifyDescriptor(const armnn::DepthwiseConvolution2dDescriptor& descriptor)
610 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100611 BOOST_CHECK(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
612 BOOST_CHECK(descriptor.m_PadRight == m_Descriptor.m_PadRight);
613 BOOST_CHECK(descriptor.m_PadTop == m_Descriptor.m_PadTop);
614 BOOST_CHECK(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
615 BOOST_CHECK(descriptor.m_StrideX == m_Descriptor.m_StrideX);
616 BOOST_CHECK(descriptor.m_StrideY == m_Descriptor.m_StrideY);
617 BOOST_CHECK(descriptor.m_DilationX == m_Descriptor.m_DilationX);
618 BOOST_CHECK(descriptor.m_DilationY == m_Descriptor.m_DilationY);
619 BOOST_CHECK(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
620 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000621 }
622
623 armnn::DepthwiseConvolution2dDescriptor m_Descriptor;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100624 armnn::ConstTensor m_Weights;
625 armnn::Optional<armnn::ConstTensor> m_Biases;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000626 };
627
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000628 const std::string layerName("depwiseConvolution2d");
629 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
630 const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000631
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000632 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
633 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000634
635 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
636 armnn::ConstTensor weights(weightsInfo, weightsData);
637
638 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
639 armnn::ConstTensor biases(biasesInfo, biasesData);
640
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000641 armnn::DepthwiseConvolution2dDescriptor descriptor;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100642 descriptor.m_PadLeft = 1;
643 descriptor.m_PadRight = 1;
644 descriptor.m_PadTop = 1;
645 descriptor.m_PadBottom = 1;
646 descriptor.m_StrideX = 2;
647 descriptor.m_StrideY = 2;
648 descriptor.m_DilationX = 2;
649 descriptor.m_DilationY = 2;
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000650 descriptor.m_BiasEnabled = true;
651 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
652
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000653 armnn::INetworkPtr network = armnn::INetwork::Create();
654 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
655 armnn::IConnectableLayer* const depthwiseConvLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100656 network->AddDepthwiseConvolution2dLayer(descriptor,
657 weights,
658 armnn::Optional<armnn::ConstTensor>(biases),
659 layerName.c_str());
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000660 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
661
662 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000663 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000664
665 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000666 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
667
668 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
669 BOOST_CHECK(deserializedNetwork);
670
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000671 DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
672 deserializedNetwork->Accept(verifier);
Jim Flynn18ce3382019-03-08 11:08:30 +0000673}
674
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000675BOOST_AUTO_TEST_CASE(SerializeDequantize)
676{
677 class DequantizeLayerVerifier : public LayerVerifierBase
678 {
679 public:
680 DequantizeLayerVerifier(const std::string& layerName,
681 const std::vector<armnn::TensorInfo>& inputInfos,
682 const std::vector<armnn::TensorInfo>& outputInfos)
683 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
684
685 void VisitDequantizeLayer(const armnn::IConnectableLayer* layer, const char* name) override
686 {
687 VerifyNameAndConnections(layer, name);
688 }
689 };
690
691 const std::string layerName("dequantize");
692 const armnn::TensorInfo inputInfo({ 1, 5, 2, 3 }, armnn::DataType::QuantisedAsymm8, 0.5f, 1);
693 const armnn::TensorInfo outputInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
694
695 armnn::INetworkPtr network = armnn::INetwork::Create();
696 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
697 armnn::IConnectableLayer* const dequantizeLayer = network->AddDequantizeLayer(layerName.c_str());
698 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
699
700 inputLayer->GetOutputSlot(0).Connect(dequantizeLayer->GetInputSlot(0));
701 dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
702
703 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
704 dequantizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
705
706 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
707 BOOST_CHECK(deserializedNetwork);
708
709 DequantizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
710 deserializedNetwork->Accept(verifier);
711}
712
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000713BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess)
714{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000715 class DetectionPostProcessLayerVerifier : public LayerVerifierBase
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000716 {
717 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000718 DetectionPostProcessLayerVerifier(const std::string& layerName,
719 const std::vector<armnn::TensorInfo>& inputInfos,
720 const std::vector<armnn::TensorInfo>& outputInfos,
721 const armnn::DetectionPostProcessDescriptor& descriptor,
722 const armnn::ConstTensor& anchors)
723 : LayerVerifierBase(layerName, inputInfos, outputInfos)
724 , m_Descriptor(descriptor)
725 , m_Anchors(anchors) {}
726
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000727 void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
728 const armnn::DetectionPostProcessDescriptor& descriptor,
729 const armnn::ConstTensor& anchors,
730 const char* name) override
731 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000732 VerifyNameAndConnections(layer, name);
733 VerifyDescriptor(descriptor);
734
735 CompareConstTensor(anchors, m_Anchors);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000736 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000737
738 private:
739 void VerifyDescriptor(const armnn::DetectionPostProcessDescriptor& descriptor)
740 {
741 BOOST_TEST(descriptor.m_UseRegularNms == m_Descriptor.m_UseRegularNms);
742 BOOST_TEST(descriptor.m_MaxDetections == m_Descriptor.m_MaxDetections);
743 BOOST_TEST(descriptor.m_MaxClassesPerDetection == m_Descriptor.m_MaxClassesPerDetection);
744 BOOST_TEST(descriptor.m_DetectionsPerClass == m_Descriptor.m_DetectionsPerClass);
745 BOOST_TEST(descriptor.m_NmsScoreThreshold == m_Descriptor.m_NmsScoreThreshold);
746 BOOST_TEST(descriptor.m_NmsIouThreshold == m_Descriptor.m_NmsIouThreshold);
747 BOOST_TEST(descriptor.m_NumClasses == m_Descriptor.m_NumClasses);
748 BOOST_TEST(descriptor.m_ScaleY == m_Descriptor.m_ScaleY);
749 BOOST_TEST(descriptor.m_ScaleX == m_Descriptor.m_ScaleX);
750 BOOST_TEST(descriptor.m_ScaleH == m_Descriptor.m_ScaleH);
751 BOOST_TEST(descriptor.m_ScaleW == m_Descriptor.m_ScaleW);
752 }
753
754 armnn::DetectionPostProcessDescriptor m_Descriptor;
755 armnn::ConstTensor m_Anchors;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000756 };
757
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000758 const std::string layerName("detectionPostProcess");
759
760 const std::vector<armnn::TensorInfo> inputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000761 armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32),
762 armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000763 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000764
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000765 const std::vector<armnn::TensorInfo> outputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000766 armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32),
767 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
768 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
769 armnn::TensorInfo({ 1 }, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000770 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000771
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000772 armnn::DetectionPostProcessDescriptor descriptor;
773 descriptor.m_UseRegularNms = true;
774 descriptor.m_MaxDetections = 3;
775 descriptor.m_MaxClassesPerDetection = 1;
776 descriptor.m_DetectionsPerClass =1;
777 descriptor.m_NmsScoreThreshold = 0.0;
778 descriptor.m_NmsIouThreshold = 0.5;
779 descriptor.m_NumClasses = 2;
780 descriptor.m_ScaleY = 10.0;
781 descriptor.m_ScaleX = 10.0;
782 descriptor.m_ScaleH = 5.0;
783 descriptor.m_ScaleW = 5.0;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000784
785 const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
786 const std::vector<float> anchorsData({
787 0.5f, 0.5f, 1.0f, 1.0f,
788 0.5f, 0.5f, 1.0f, 1.0f,
789 0.5f, 0.5f, 1.0f, 1.0f,
790 0.5f, 10.5f, 1.0f, 1.0f,
791 0.5f, 10.5f, 1.0f, 1.0f,
792 0.5f, 100.5f, 1.0f, 1.0f
793 });
794 armnn::ConstTensor anchors(anchorsInfo, anchorsData);
795
796 armnn::INetworkPtr network = armnn::INetwork::Create();
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000797 armnn::IConnectableLayer* const detectionLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000798 network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000799
800 for (unsigned int i = 0; i < 2; i++)
801 {
802 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
803 inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
804 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
805 }
806
807 for (unsigned int i = 0; i < 4; i++)
808 {
809 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
810 detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
811 detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
812 }
813
814 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
815 BOOST_CHECK(deserializedNetwork);
816
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000817 DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors);
818 deserializedNetwork->Accept(verifier);
819}
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000820
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000821BOOST_AUTO_TEST_CASE(SerializeDivision)
822{
823 class DivisionLayerVerifier : public LayerVerifierBase
824 {
825 public:
826 DivisionLayerVerifier(const std::string& layerName,
827 const std::vector<armnn::TensorInfo>& inputInfos,
828 const std::vector<armnn::TensorInfo>& outputInfos)
829 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
830
831 void VisitDivisionLayer(const armnn::IConnectableLayer* layer, const char* name) override
832 {
833 VerifyNameAndConnections(layer, name);
834 }
835 };
836
837 const std::string layerName("division");
838 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
839
840 armnn::INetworkPtr network = armnn::INetwork::Create();
841 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
842 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
843 armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
844 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
845
846 inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
847 inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
848 divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
849
850 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
851 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
852 divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
853
854 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
855 BOOST_CHECK(deserializedNetwork);
856
857 DivisionLayerVerifier verifier(layerName, {info, info}, {info});
858 deserializedNetwork->Accept(verifier);
859}
860
861BOOST_AUTO_TEST_CASE(SerializeEqual)
862{
863 class EqualLayerVerifier : public LayerVerifierBase
864 {
865 public:
866 EqualLayerVerifier(const std::string& layerName,
867 const std::vector<armnn::TensorInfo>& inputInfos,
868 const std::vector<armnn::TensorInfo>& outputInfos)
869 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
870
871 void VisitEqualLayer(const armnn::IConnectableLayer* layer, const char* name) override
872 {
873 VerifyNameAndConnections(layer, name);
874 }
875 };
876
877 const std::string layerName("equal");
878 const armnn::TensorInfo inputTensorInfo1 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
879 const armnn::TensorInfo inputTensorInfo2 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
880 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Boolean);
881
882 armnn::INetworkPtr network = armnn::INetwork::Create();
883 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
884 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
885 armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str());
886 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
887
888 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
889 inputLayer2->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
890 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
891
892 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
893 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
894 equalLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
895
896 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
897 BOOST_CHECK(deserializedNetwork);
898
899 EqualLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
900 deserializedNetwork->Accept(verifier);
901}
902
903BOOST_AUTO_TEST_CASE(SerializeFloor)
904{
905 class FloorLayerVerifier : public LayerVerifierBase
906 {
907 public:
908 FloorLayerVerifier(const std::string& layerName,
909 const std::vector<armnn::TensorInfo>& inputInfos,
910 const std::vector<armnn::TensorInfo>& outputInfos)
911 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
912
913 void VisitFloorLayer(const armnn::IConnectableLayer* layer, const char* name) override
914 {
915 VerifyNameAndConnections(layer, name);
916 }
917 };
918
919 const std::string layerName("floor");
920 const armnn::TensorInfo info({4,4}, armnn::DataType::Float32);
921
922 armnn::INetworkPtr network = armnn::INetwork::Create();
923 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
924 armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
925 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
926
927 inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
928 floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
929
930 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
931 floorLayer->GetOutputSlot(0).SetTensorInfo(info);
932
933 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
934 BOOST_CHECK(deserializedNetwork);
935
936 FloorLayerVerifier verifier(layerName, {info}, {info});
937 deserializedNetwork->Accept(verifier);
938}
939
940BOOST_AUTO_TEST_CASE(SerializeFullyConnected)
941{
942 class FullyConnectedLayerVerifier : public LayerVerifierBase
943 {
944 public:
945 FullyConnectedLayerVerifier(const std::string& layerName,
946 const std::vector<armnn::TensorInfo>& inputInfos,
947 const std::vector<armnn::TensorInfo>& outputInfos,
948 const armnn::FullyConnectedDescriptor& descriptor,
949 const armnn::ConstTensor& weight,
950 const armnn::Optional<armnn::ConstTensor>& bias)
951 : LayerVerifierBase(layerName, inputInfos, outputInfos)
952 , m_Descriptor(descriptor)
953 , m_Weight(weight)
954 , m_Bias(bias) {}
955
956 void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
957 const armnn::FullyConnectedDescriptor& descriptor,
958 const armnn::ConstTensor& weight,
959 const armnn::Optional<armnn::ConstTensor>& bias,
960 const char* name) override
961 {
962 VerifyNameAndConnections(layer, name);
963 VerifyDescriptor(descriptor);
964
965 CompareConstTensor(weight, m_Weight);
966
967 BOOST_TEST(bias.has_value() == m_Bias.has_value());
968 if (bias.has_value() && m_Bias.has_value())
969 {
970 CompareConstTensor(bias.value(), m_Bias.value());
971 }
972 }
973
974 private:
975 void VerifyDescriptor(const armnn::FullyConnectedDescriptor& descriptor)
976 {
977 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
978 BOOST_TEST(descriptor.m_TransposeWeightMatrix == m_Descriptor.m_TransposeWeightMatrix);
979 }
980
981 armnn::FullyConnectedDescriptor m_Descriptor;
982 armnn::ConstTensor m_Weight;
983 armnn::Optional<armnn::ConstTensor> m_Bias;
984 };
985
986 const std::string layerName("fullyConnected");
987 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
988 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
989
990 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
991 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
992 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
993 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
994 armnn::ConstTensor weights(weightsInfo, weightsData);
995 armnn::ConstTensor biases(biasesInfo, biasesData);
996
997 armnn::FullyConnectedDescriptor descriptor;
998 descriptor.m_BiasEnabled = true;
999 descriptor.m_TransposeWeightMatrix = false;
1000
1001 armnn::INetworkPtr network = armnn::INetwork::Create();
1002 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1003 armnn::IConnectableLayer* const fullyConnectedLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +01001004 network->AddFullyConnectedLayer(descriptor,
1005 weights,
1006 armnn::Optional<armnn::ConstTensor>(biases),
1007 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001008 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1009
1010 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
1011 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1012
1013 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1014 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1015
1016 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1017 BOOST_CHECK(deserializedNetwork);
1018
1019 FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
1020 deserializedNetwork->Accept(verifier);
1021}
1022
1023BOOST_AUTO_TEST_CASE(SerializeGather)
1024{
1025 class GatherLayerVerifier : public LayerVerifierBase
1026 {
1027 public:
1028 GatherLayerVerifier(const std::string& layerName,
1029 const std::vector<armnn::TensorInfo>& inputInfos,
1030 const std::vector<armnn::TensorInfo>& outputInfos)
1031 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1032
1033 void VisitGatherLayer(const armnn::IConnectableLayer* layer, const char *name) override
1034 {
1035 VerifyNameAndConnections(layer, name);
1036 }
1037
1038 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
1039 const armnn::ConstTensor& input,
1040 const char *name) override {}
1041 };
1042
1043 const std::string layerName("gather");
1044 armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QuantisedAsymm8);
1045 armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QuantisedAsymm8);
1046 const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
1047
1048 paramsInfo.SetQuantizationScale(1.0f);
1049 paramsInfo.SetQuantizationOffset(0);
1050 outputInfo.SetQuantizationScale(1.0f);
1051 outputInfo.SetQuantizationOffset(0);
1052
1053 const std::vector<int32_t>& indicesData = {7, 6, 5};
1054
1055 armnn::INetworkPtr network = armnn::INetwork::Create();
1056 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
1057 armnn::IConnectableLayer *const constantLayer =
1058 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
1059 armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(layerName.c_str());
1060 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
1061
1062 inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
1063 constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
1064 gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1065
1066 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
1067 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
1068 gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1069
1070 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1071 BOOST_CHECK(deserializedNetwork);
1072
1073 GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo});
1074 deserializedNetwork->Accept(verifier);
1075}
1076
1077BOOST_AUTO_TEST_CASE(SerializeGreater)
1078{
1079 class GreaterLayerVerifier : public LayerVerifierBase
1080 {
1081 public:
1082 GreaterLayerVerifier(const std::string& layerName,
1083 const std::vector<armnn::TensorInfo>& inputInfos,
1084 const std::vector<armnn::TensorInfo>& outputInfos)
1085 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1086
1087 void VisitGreaterLayer(const armnn::IConnectableLayer* layer, const char* name) override
1088 {
1089 VerifyNameAndConnections(layer, name);
1090 }
1091 };
1092
1093 const std::string layerName("greater");
1094 const armnn::TensorInfo inputTensorInfo1({ 1, 2, 2, 2 }, armnn::DataType::Float32);
1095 const armnn::TensorInfo inputTensorInfo2({ 1, 2, 2, 2 }, armnn::DataType::Float32);
1096 const armnn::TensorInfo outputTensorInfo({ 1, 2, 2, 2 }, armnn::DataType::Boolean);
1097
1098 armnn::INetworkPtr network = armnn::INetwork::Create();
1099 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
1100 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
1101 armnn::IConnectableLayer* const greaterLayer = network->AddGreaterLayer(layerName.c_str());
1102 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1103
1104 inputLayer1->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(0));
1105 inputLayer2->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(1));
1106 greaterLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1107
1108 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
1109 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
1110 greaterLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1111
1112 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1113 BOOST_CHECK(deserializedNetwork);
1114
1115 GreaterLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
1116 deserializedNetwork->Accept(verifier);
1117}
1118
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001119class L2NormalizationLayerVerifier : public LayerVerifierBase
1120{
1121public:
1122 L2NormalizationLayerVerifier(const std::string& layerName,
1123 const std::vector<armnn::TensorInfo>& inputInfos,
1124 const std::vector<armnn::TensorInfo>& outputInfos,
1125 const armnn::L2NormalizationDescriptor& descriptor)
1126 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1127 , m_Descriptor(descriptor) {}
1128
1129 void VisitL2NormalizationLayer(const armnn::IConnectableLayer* layer,
1130 const armnn::L2NormalizationDescriptor& descriptor,
1131 const char* name) override
1132 {
1133 VerifyNameAndConnections(layer, name);
1134 VerifyDescriptor(descriptor);
1135 }
1136private:
1137 void VerifyDescriptor(const armnn::L2NormalizationDescriptor& descriptor)
1138 {
1139 BOOST_TEST(descriptor.m_Eps == m_Descriptor.m_Eps);
1140 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1141 }
1142
1143 armnn::L2NormalizationDescriptor m_Descriptor;
1144};
1145
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001146BOOST_AUTO_TEST_CASE(SerializeL2Normalization)
1147{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001148 const std::string l2NormLayerName("l2Normalization");
1149 const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1150
1151 armnn::L2NormalizationDescriptor desc;
1152 desc.m_DataLayout = armnn::DataLayout::NCHW;
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001153 desc.m_Eps = 0.0001f;
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001154
1155 armnn::INetworkPtr network = armnn::INetwork::Create();
1156 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1157 armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1158 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1159
1160 inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1161 l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1162
1163 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1164 l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1165
1166 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1167 BOOST_CHECK(deserializedNetwork);
1168
1169 L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc);
1170 deserializedNetwork->Accept(verifier);
1171}
1172
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001173BOOST_AUTO_TEST_CASE(EnsureL2NormalizationBackwardCompatibility)
1174{
1175 // The hex array below is a flat buffer containing a simple network with one input
1176 // a L2Normalization layer and an output layer with dimensions as per the tensor infos below.
1177 //
1178 // This test verifies that we can still read back these old style
1179 // models without the normalization epsilon value.
1180 unsigned int size = 508;
1181 const unsigned char l2NormalizationModel[] = {
1182 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1183 0x0C,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x3C,0x01,0x00,0x00,
1184 0x74,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1185 0x02,0x00,0x00,0x00,0xE8,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x0B,0x04,0x00,0x00,0x00,0xD6,0xFE,0xFF,0xFF,
1186 0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1187 0x9E,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1188 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
1189 0x00,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0xFF,0xFF,0xFF,
1190 0x00,0x00,0x00,0x20,0x0C,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1191 0x20,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x06,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,
1192 0x18,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,0x0E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1193 0x10,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,
1194 0x6C,0x32,0x4E,0x6F,0x72,0x6D,0x61,0x6C,0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x00,0x01,0x00,0x00,0x00,
1195 0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x04,0x00,
1196 0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x52,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
1197 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1198 0x05,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1199 0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x09,
1200 0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0A,0x00,0x04,0x00,
1201 0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x08,0x00,
1202 0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1203 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1204 0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1205 0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
1206 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1207 0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0 };
1208
1209 std::stringstream ss;
1210 for (unsigned int i = 0; i < size; ++i)
1211 {
1212 ss << l2NormalizationModel[i];
1213 }
1214 std::string l2NormalizationLayerNetwork = ss.str();
1215 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(l2NormalizationLayerNetwork);
1216 BOOST_CHECK(deserializedNetwork);
1217 const std::string layerName("l2Normalization");
1218 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 2, 1, 5}, armnn::DataType::Float32);
1219
1220 armnn::L2NormalizationDescriptor desc;
1221 desc.m_DataLayout = armnn::DataLayout::NCHW;
1222 // Since this variable does not exist in the l2NormalizationModel[] dump, the default value will be loaded.
1223 desc.m_Eps = 1e-12f;
1224
1225 L2NormalizationLayerVerifier verifier(layerName, {inputInfo}, {inputInfo}, desc);
1226 deserializedNetwork->Accept(verifier);
1227}
1228
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001229BOOST_AUTO_TEST_CASE(SerializeMaximum)
1230{
1231 class MaximumLayerVerifier : public LayerVerifierBase
1232 {
1233 public:
1234 MaximumLayerVerifier(const std::string& layerName,
1235 const std::vector<armnn::TensorInfo>& inputInfos,
1236 const std::vector<armnn::TensorInfo>& outputInfos)
1237 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1238
1239 void VisitMaximumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1240 {
1241 VerifyNameAndConnections(layer, name);
1242 }
1243 };
1244
1245 const std::string layerName("maximum");
1246 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1247
1248 armnn::INetworkPtr network = armnn::INetwork::Create();
1249 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1250 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1251 armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1252 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1253
1254 inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1255 inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1256 maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1257
1258 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1259 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1260 maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1261
1262 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1263 BOOST_CHECK(deserializedNetwork);
1264
1265 MaximumLayerVerifier verifier(layerName, {info, info}, {info});
1266 deserializedNetwork->Accept(verifier);
1267}
1268
1269BOOST_AUTO_TEST_CASE(SerializeMean)
1270{
1271 class MeanLayerVerifier : public LayerVerifierBase
1272 {
1273 public:
1274 MeanLayerVerifier(const std::string& layerName,
1275 const std::vector<armnn::TensorInfo>& inputInfos,
1276 const std::vector<armnn::TensorInfo>& outputInfos,
1277 const armnn::MeanDescriptor& descriptor)
1278 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1279 , m_Descriptor(descriptor) {}
1280
1281 void VisitMeanLayer(const armnn::IConnectableLayer* layer,
1282 const armnn::MeanDescriptor& descriptor,
1283 const char* name) override
1284 {
1285 VerifyNameAndConnections(layer, name);
1286 VerifyDescriptor(descriptor);
1287 }
1288
1289 private:
1290 void VerifyDescriptor(const armnn::MeanDescriptor& descriptor)
1291 {
1292 BOOST_TEST(descriptor.m_Axis == m_Descriptor.m_Axis);
1293 BOOST_TEST(descriptor.m_KeepDims == m_Descriptor.m_KeepDims);
1294 }
1295
1296 armnn::MeanDescriptor m_Descriptor;
1297 };
1298
1299 const std::string layerName("mean");
1300 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1301 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1302
1303 armnn::MeanDescriptor descriptor;
1304 descriptor.m_Axis = { 2 };
1305 descriptor.m_KeepDims = true;
1306
1307 armnn::INetworkPtr network = armnn::INetwork::Create();
1308 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1309 armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1310 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1311
1312 inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1313 meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1314
1315 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1316 meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1317
1318 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1319 BOOST_CHECK(deserializedNetwork);
1320
1321 MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1322 deserializedNetwork->Accept(verifier);
1323}
1324
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001325BOOST_AUTO_TEST_CASE(SerializeMerge)
1326{
1327 class MergeLayerVerifier : public LayerVerifierBase
1328 {
1329 public:
1330 MergeLayerVerifier(const std::string& layerName,
1331 const std::vector<armnn::TensorInfo>& inputInfos,
1332 const std::vector<armnn::TensorInfo>& outputInfos)
1333 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1334
1335 void VisitMergeLayer(const armnn::IConnectableLayer* layer, const char* name) override
1336 {
1337 VerifyNameAndConnections(layer, name);
1338 }
1339 };
1340
1341 const std::string layerName("merge");
1342 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1343
1344 armnn::INetworkPtr network = armnn::INetwork::Create();
1345 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1346 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1347 armnn::IConnectableLayer* const mergeLayer = network->AddMergeLayer(layerName.c_str());
1348 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1349
1350 inputLayer0->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(0));
1351 inputLayer1->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(1));
1352 mergeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1353
1354 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1355 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1356 mergeLayer->GetOutputSlot(0).SetTensorInfo(info);
1357
1358 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1359 BOOST_CHECK(deserializedNetwork);
1360
1361 MergeLayerVerifier verifier(layerName, {info, info}, {info});
1362 deserializedNetwork->Accept(verifier);
1363}
1364
Jim Flynn5fa83932019-05-09 15:35:43 +01001365class MergerLayerVerifier : public LayerVerifierBase
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001366{
Jim Flynn5fa83932019-05-09 15:35:43 +01001367public:
1368 MergerLayerVerifier(const std::string& layerName,
1369 const std::vector<armnn::TensorInfo>& inputInfos,
1370 const std::vector<armnn::TensorInfo>& outputInfos,
1371 const armnn::OriginsDescriptor& descriptor)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001372 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1373 , m_Descriptor(descriptor) {}
1374
Jim Flynn5fa83932019-05-09 15:35:43 +01001375 void VisitMergerLayer(const armnn::IConnectableLayer* layer,
1376 const armnn::OriginsDescriptor& descriptor,
1377 const char* name) override
1378 {
Jim Flynne242f2d2019-05-22 14:24:13 +01001379 throw armnn::Exception("MergerLayer should have translated to ConcatLayer");
1380 }
1381
1382 void VisitConcatLayer(const armnn::IConnectableLayer* layer,
1383 const armnn::OriginsDescriptor& descriptor,
1384 const char* name) override
1385 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001386 VerifyNameAndConnections(layer, name);
1387 VerifyDescriptor(descriptor);
1388 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001389
Jim Flynn5fa83932019-05-09 15:35:43 +01001390private:
1391 void VerifyDescriptor(const armnn::OriginsDescriptor& descriptor)
1392 {
1393 BOOST_TEST(descriptor.GetConcatAxis() == m_Descriptor.GetConcatAxis());
1394 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
1395 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001396
Jim Flynn5fa83932019-05-09 15:35:43 +01001397 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
1398 {
1399 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001400 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001401 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001402 }
1403 }
Jim Flynn5fa83932019-05-09 15:35:43 +01001404 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001405
Jim Flynn5fa83932019-05-09 15:35:43 +01001406 armnn::OriginsDescriptor m_Descriptor;
1407};
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001408
Jim Flynne242f2d2019-05-22 14:24:13 +01001409// NOTE: until the deprecated AddMergerLayer disappears this test checks that calling
1410// AddMergerLayer places a ConcatLayer into the serialized format and that
1411// when this deserialises we have a ConcatLayer
Jim Flynn5fa83932019-05-09 15:35:43 +01001412BOOST_AUTO_TEST_CASE(SerializeMerger)
1413{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001414 const std::string layerName("merger");
1415 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1416 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1417
1418 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1419
1420 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001421 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001422
1423 armnn::INetworkPtr network = armnn::INetwork::Create();
1424 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1425 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
Jim Flynn906f9462019-05-10 13:55:21 +01001426 ARMNN_NO_DEPRECATE_WARN_BEGIN
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001427 armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str());
Jim Flynn906f9462019-05-10 13:55:21 +01001428 ARMNN_NO_DEPRECATE_WARN_END
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001429 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1430
1431 inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
1432 inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
1433 mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1434
1435 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1436 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1437 mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1438
Jim Flynn5fa83932019-05-09 15:35:43 +01001439 std::string mergerLayerNetwork = SerializeNetwork(*network);
1440 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001441 BOOST_CHECK(deserializedNetwork);
1442
1443 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1444 deserializedNetwork->Accept(verifier);
1445}
1446
Jim Flynn5fa83932019-05-09 15:35:43 +01001447BOOST_AUTO_TEST_CASE(EnsureMergerLayerBackwardCompatibility)
1448{
1449 // The hex array below is a flat buffer containing a simple network with two inputs
Jim Flynne242f2d2019-05-22 14:24:13 +01001450 // a merger layer (now deprecated) and an output layer with dimensions as per the tensor infos below.
1451 //
1452 // This test verifies that we can still read back these old style
Jim Flynn5fa83932019-05-09 15:35:43 +01001453 // models replacing the MergerLayers with ConcatLayers with the same parameters.
Jim Flynn5fa83932019-05-09 15:35:43 +01001454 unsigned int size = 760;
1455 const unsigned char mergerModel[] = {
1456 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1457 0x0C,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x38,0x02,0x00,0x00,
1458 0x8C,0x01,0x00,0x00,0x70,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1459 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xF4,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x0B,
1460 0x04,0x00,0x00,0x00,0x92,0xFE,0xFF,0xFF,0x04,0x00,0x00,0x00,0x9A,0xFE,0xFF,0xFF,0x04,0x00,0x00,0x00,
1461 0x7E,0xFE,0xFF,0xFF,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1462 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
1463 0x00,0x00,0x00,0x00,0xF8,0xFE,0xFF,0xFF,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0xFE,0xFF,0xFF,
1464 0x00,0x00,0x00,0x1F,0x0C,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1465 0x68,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x0C,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,
1466 0x0C,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1467 0x24,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x22,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1468 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,
1469 0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1470 0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,
1471 0x14,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x6D,0x65,0x72,0x67,0x65,0x72,0x00,0x00,
1472 0x02,0x00,0x00,0x00,0x5C,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1473 0x34,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x92,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
1474 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1475 0x02,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1476 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,
1477 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1478 0x00,0x00,0x00,0x09,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,
1479 0x0C,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,
1480 0x01,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x18,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,
1481 0x0E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1482 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1483 0x0C,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1484 0x66,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1485 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,
1486 0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,
1487 0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0A,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1488 0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,
1489 0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1490 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,
1491 0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,
1492 0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1493 0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00};
1494 std::stringstream ss;
1495 for (unsigned int i = 0; i < size; ++i)
1496 {
1497 ss << mergerModel[i];
1498 }
1499 std::string mergerLayerNetwork = ss.str();
1500 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
1501 BOOST_CHECK(deserializedNetwork);
1502 const std::string layerName("merger");
1503 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1504 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1505
1506 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1507
1508 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001509 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Jim Flynn5fa83932019-05-09 15:35:43 +01001510
1511 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1512 deserializedNetwork->Accept(verifier);
1513}
1514
Jim Flynne242f2d2019-05-22 14:24:13 +01001515BOOST_AUTO_TEST_CASE(SerializeConcat)
1516{
1517 const std::string layerName("concat");
1518 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1519 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1520
1521 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1522
1523 armnn::OriginsDescriptor descriptor =
1524 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1525
1526 armnn::INetworkPtr network = armnn::INetwork::Create();
1527 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1528 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1529 armnn::IConnectableLayer* const concatLayer = network->AddConcatLayer(descriptor, layerName.c_str());
1530 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1531
1532 inputLayerOne->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
1533 inputLayerTwo->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
1534 concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1535
1536 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1537 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1538 concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1539
1540 std::string concatLayerNetwork = SerializeNetwork(*network);
1541 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(concatLayerNetwork);
1542 BOOST_CHECK(deserializedNetwork);
1543
1544 // NOTE: using the MergerLayerVerifier to ensure that it is a concat layer and not a
1545 // merger layer that gets placed into the graph.
1546 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1547 deserializedNetwork->Accept(verifier);
1548}
1549
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001550BOOST_AUTO_TEST_CASE(SerializeMinimum)
1551{
1552 class MinimumLayerVerifier : public LayerVerifierBase
1553 {
1554 public:
1555 MinimumLayerVerifier(const std::string& layerName,
1556 const std::vector<armnn::TensorInfo>& inputInfos,
1557 const std::vector<armnn::TensorInfo>& outputInfos)
1558 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1559
1560 void VisitMinimumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1561 {
1562 VerifyNameAndConnections(layer, name);
1563 }
1564 };
1565
1566 const std::string layerName("minimum");
1567 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1568
1569 armnn::INetworkPtr network = armnn::INetwork::Create();
1570 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1571 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1572 armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1573 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1574
1575 inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1576 inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1577 minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1578
1579 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1580 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1581 minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
1582
1583 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1584 BOOST_CHECK(deserializedNetwork);
1585
1586 MinimumLayerVerifier verifier(layerName, {info, info}, {info});
1587 deserializedNetwork->Accept(verifier);
1588}
1589
1590BOOST_AUTO_TEST_CASE(SerializeMultiplication)
1591{
1592 class MultiplicationLayerVerifier : public LayerVerifierBase
1593 {
1594 public:
1595 MultiplicationLayerVerifier(const std::string& layerName,
1596 const std::vector<armnn::TensorInfo>& inputInfos,
1597 const std::vector<armnn::TensorInfo>& outputInfos)
1598 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1599
1600 void VisitMultiplicationLayer(const armnn::IConnectableLayer* layer, const char* name) override
1601 {
1602 VerifyNameAndConnections(layer, name);
1603 }
1604 };
1605
1606 const std::string layerName("multiplication");
1607 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1608
1609 armnn::INetworkPtr network = armnn::INetwork::Create();
1610 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1611 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1612 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
1613 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1614
1615 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
1616 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
1617 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1618
1619 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1620 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1621 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
1622
1623 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1624 BOOST_CHECK(deserializedNetwork);
1625
1626 MultiplicationLayerVerifier verifier(layerName, {info, info}, {info});
1627 deserializedNetwork->Accept(verifier);
1628}
1629
Ellen Norris-Thompson51982472019-06-19 11:46:21 +01001630BOOST_AUTO_TEST_CASE(SerializePrelu)
1631{
1632 class PreluLayerVerifier : public LayerVerifierBase
1633 {
1634 public:
1635 PreluLayerVerifier(const std::string& layerName,
1636 const std::vector<armnn::TensorInfo>& inputInfos,
1637 const std::vector<armnn::TensorInfo>& outputInfos)
1638 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1639
1640 void VisitPreluLayer(const armnn::IConnectableLayer* layer, const char* name) override
1641 {
1642 VerifyNameAndConnections(layer, name);
1643 }
1644 };
1645
1646 const std::string layerName("prelu");
1647
1648 armnn::TensorInfo inputTensorInfo ({ 4, 1, 2 }, armnn::DataType::Float32);
1649 armnn::TensorInfo alphaTensorInfo ({ 5, 4, 3, 1 }, armnn::DataType::Float32);
1650 armnn::TensorInfo outputTensorInfo({ 5, 4, 3, 2 }, armnn::DataType::Float32);
1651
1652 armnn::INetworkPtr network = armnn::INetwork::Create();
1653 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1654 armnn::IConnectableLayer* const alphaLayer = network->AddInputLayer(1);
1655 armnn::IConnectableLayer* const preluLayer = network->AddPreluLayer(layerName.c_str());
1656 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1657
1658 inputLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(0));
1659 alphaLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(1));
1660 preluLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1661
1662 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1663 alphaLayer->GetOutputSlot(0).SetTensorInfo(alphaTensorInfo);
1664 preluLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1665
1666 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1667 BOOST_CHECK(deserializedNetwork);
1668
1669 PreluLayerVerifier verifier(layerName, {inputTensorInfo, alphaTensorInfo}, {outputTensorInfo});
1670 deserializedNetwork->Accept(verifier);
1671}
1672
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001673BOOST_AUTO_TEST_CASE(SerializeNormalization)
1674{
1675 class NormalizationLayerVerifier : public LayerVerifierBase
1676 {
1677 public:
1678 NormalizationLayerVerifier(const std::string& layerName,
1679 const std::vector<armnn::TensorInfo>& inputInfos,
1680 const std::vector<armnn::TensorInfo>& outputInfos,
1681 const armnn::NormalizationDescriptor& descriptor)
1682 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1683 , m_Descriptor(descriptor) {}
1684
1685 void VisitNormalizationLayer(const armnn::IConnectableLayer* layer,
1686 const armnn::NormalizationDescriptor& descriptor,
1687 const char* name) override
1688 {
1689 VerifyNameAndConnections(layer, name);
1690 VerifyDescriptor(descriptor);
1691 }
1692
1693 private:
1694 void VerifyDescriptor(const armnn::NormalizationDescriptor& descriptor)
1695 {
1696 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1697 BOOST_TEST(descriptor.m_NormSize == m_Descriptor.m_NormSize);
1698 BOOST_TEST(descriptor.m_Alpha == m_Descriptor.m_Alpha);
1699 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
1700 BOOST_TEST(descriptor.m_K == m_Descriptor.m_K);
1701 BOOST_TEST(
1702 static_cast<int>(descriptor.m_NormChannelType) == static_cast<int>(m_Descriptor.m_NormChannelType));
1703 BOOST_TEST(
1704 static_cast<int>(descriptor.m_NormMethodType) == static_cast<int>(m_Descriptor.m_NormMethodType));
1705 }
1706
1707 armnn::NormalizationDescriptor m_Descriptor;
1708 };
1709
1710 const std::string layerName("normalization");
1711 const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
1712
1713 armnn::NormalizationDescriptor desc;
1714 desc.m_DataLayout = armnn::DataLayout::NCHW;
1715 desc.m_NormSize = 3;
1716 desc.m_Alpha = 1;
1717 desc.m_Beta = 1;
1718 desc.m_K = 1;
1719
1720 armnn::INetworkPtr network = armnn::INetwork::Create();
1721 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1722 armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
1723 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1724
1725 inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
1726 normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1727
1728 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1729 normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
1730
1731 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1732 BOOST_CHECK(deserializedNetwork);
1733
1734 NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc);
1735 deserializedNetwork->Accept(verifier);
1736}
1737
Jim Flynn965c7c62019-06-24 14:32:41 +01001738class PadLayerVerifier : public LayerVerifierBase
1739{
1740public:
1741 PadLayerVerifier(const std::string& layerName,
1742 const std::vector<armnn::TensorInfo>& inputInfos,
1743 const std::vector<armnn::TensorInfo>& outputInfos,
1744 const armnn::PadDescriptor& descriptor)
1745 : LayerVerifierBase(layerName, inputInfos, outputInfos), m_Descriptor(descriptor) {}
1746
1747 void VisitPadLayer(const armnn::IConnectableLayer* layer,
1748 const armnn::PadDescriptor& descriptor,
1749 const char* name) override
1750 {
1751 VerifyNameAndConnections(layer, name);
1752 VerifyDescriptor(descriptor);
1753 }
1754
1755private:
1756 void VerifyDescriptor(const armnn::PadDescriptor& descriptor)
1757 {
1758 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
Aron Virginas-Tarf3569052019-07-05 16:01:08 +01001759 BOOST_TEST(descriptor.m_PadValue == m_Descriptor.m_PadValue);
Jim Flynn965c7c62019-06-24 14:32:41 +01001760 }
1761
1762 armnn::PadDescriptor m_Descriptor;
1763};
1764
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001765BOOST_AUTO_TEST_CASE(SerializePad)
1766{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001767
1768 const std::string layerName("pad");
1769 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1770 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1771
1772 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1773
1774 armnn::INetworkPtr network = armnn::INetwork::Create();
1775 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1776 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
1777 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1778
1779 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
1780 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1781
1782 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1783 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1784
1785 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1786 BOOST_CHECK(deserializedNetwork);
1787
1788 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1789 deserializedNetwork->Accept(verifier);
1790}
1791
Jim Flynn965c7c62019-06-24 14:32:41 +01001792BOOST_AUTO_TEST_CASE(CheckSerializePadBackwardCompatibility)
1793{
1794 // The PadDescriptor is being extended with a float PadValue (so a value other than 0
1795 // can be used to pad the tensor.
1796 //
1797 // This test contains a binary representation of a simple input->pad->output network
1798 // prior to this change to test that the descriptor has been updated in a backward
1799 // compatible way with respect to Deserialization of older binary dumps
1800 unsigned int size = 532;
1801 const unsigned char padModel[] = {
1802 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1803 0x0C,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x54,0x01,0x00,0x00,
1804 0x6C,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1805 0x02,0x00,0x00,0x00,0xD0,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x0B,0x04,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,
1806 0x04,0x00,0x00,0x00,0x9E,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x72,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,
1807 0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1808 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2C,0xFF,0xFF,0xFF,
1809 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x16,0x0C,0x00,0x00,0x00,
1810 0x08,0x00,0x0E,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x4C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,
1811 0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
1812 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1813 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x18,0x00,0x04,0x00,
1814 0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,0x0E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1815 0x14,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x70,0x61,0x64,0x00,
1816 0x01,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x08,0x00,
1817 0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x52,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,
1818 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
1819 0x05,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,
1820 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1821 0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,
1822 0x0A,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,
1823 0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1824 0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1825 0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,
1826 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1827 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1828 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0 };
1829
1830 std::stringstream ss;
1831 for (unsigned int i = 0; i < size; ++i)
1832 {
1833 ss << padModel[i];
1834 }
1835 std::string padNetwork = ss.str();
1836 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(padNetwork);
1837 BOOST_CHECK(deserializedNetwork);
1838
1839 const std::string layerName("pad");
1840 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1841 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1842
1843 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1844
1845 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1846 deserializedNetwork->Accept(verifier);
1847}
1848
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001849BOOST_AUTO_TEST_CASE(SerializePermute)
1850{
1851 class PermuteLayerVerifier : public LayerVerifierBase
1852 {
1853 public:
1854 PermuteLayerVerifier(const std::string& layerName,
1855 const std::vector<armnn::TensorInfo>& inputInfos,
1856 const std::vector<armnn::TensorInfo>& outputInfos,
1857 const armnn::PermuteDescriptor& descriptor)
1858 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1859 , m_Descriptor(descriptor) {}
1860
1861 void VisitPermuteLayer(const armnn::IConnectableLayer* layer,
1862 const armnn::PermuteDescriptor& descriptor,
1863 const char* name) override
1864 {
1865 VerifyNameAndConnections(layer, name);
1866 VerifyDescriptor(descriptor);
1867 }
1868
1869 private:
1870 void VerifyDescriptor(const armnn::PermuteDescriptor& descriptor)
1871 {
1872 BOOST_TEST(descriptor.m_DimMappings.IsEqual(m_Descriptor.m_DimMappings));
1873 }
1874
1875 armnn::PermuteDescriptor m_Descriptor;
1876 };
1877
1878 const std::string layerName("permute");
1879 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
1880 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1881
1882 armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
1883
1884 armnn::INetworkPtr network = armnn::INetwork::Create();
1885 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1886 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
1887 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1888
1889 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
1890 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1891
1892 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1893 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1894
1895 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1896 BOOST_CHECK(deserializedNetwork);
1897
1898 PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
1899 deserializedNetwork->Accept(verifier);
1900}
1901
1902BOOST_AUTO_TEST_CASE(SerializePooling2d)
1903{
1904 class Pooling2dLayerVerifier : public LayerVerifierBase
1905 {
1906 public:
1907 Pooling2dLayerVerifier(const std::string& layerName,
1908 const std::vector<armnn::TensorInfo>& inputInfos,
1909 const std::vector<armnn::TensorInfo>& outputInfos,
1910 const armnn::Pooling2dDescriptor& descriptor)
1911 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1912 , m_Descriptor(descriptor) {}
1913
1914 void VisitPooling2dLayer(const armnn::IConnectableLayer* layer,
1915 const armnn::Pooling2dDescriptor& descriptor,
1916 const char* name) override
1917 {
1918 VerifyNameAndConnections(layer, name);
1919 VerifyDescriptor(descriptor);
1920 }
1921
1922 private:
1923 void VerifyDescriptor(const armnn::Pooling2dDescriptor& descriptor)
1924 {
1925 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1926 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
1927 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
1928 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
1929 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
1930 BOOST_TEST(descriptor.m_PoolWidth == m_Descriptor.m_PoolWidth);
1931 BOOST_TEST(descriptor.m_PoolHeight == m_Descriptor.m_PoolHeight);
1932 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
1933 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
1934
1935 BOOST_TEST(
1936 static_cast<int>(descriptor.m_PaddingMethod) == static_cast<int>(m_Descriptor.m_PaddingMethod));
1937 BOOST_TEST(
1938 static_cast<int>(descriptor.m_PoolType) == static_cast<int>(m_Descriptor.m_PoolType));
1939 BOOST_TEST(
1940 static_cast<int>(descriptor.m_OutputShapeRounding) ==
1941 static_cast<int>(m_Descriptor.m_OutputShapeRounding));
1942 }
1943
1944 armnn::Pooling2dDescriptor m_Descriptor;
1945 };
1946
1947 const std::string layerName("pooling2d");
1948 const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
1949 const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
1950
1951 armnn::Pooling2dDescriptor desc;
1952 desc.m_DataLayout = armnn::DataLayout::NHWC;
1953 desc.m_PadTop = 0;
1954 desc.m_PadBottom = 0;
1955 desc.m_PadLeft = 0;
1956 desc.m_PadRight = 0;
1957 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
1958 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1959 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1960 desc.m_PoolHeight = 2;
1961 desc.m_PoolWidth = 2;
1962 desc.m_StrideX = 2;
1963 desc.m_StrideY = 2;
1964
1965 armnn::INetworkPtr network = armnn::INetwork::Create();
1966 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1967 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
1968 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1969
1970 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
1971 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1972
1973 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1974 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1975
1976 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1977 BOOST_CHECK(deserializedNetwork);
1978
1979 Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1980 deserializedNetwork->Accept(verifier);
1981}
1982
Derek Lamberti87acb272019-03-27 16:51:31 +00001983BOOST_AUTO_TEST_CASE(SerializeQuantize)
1984{
1985 class QuantizeLayerVerifier : public LayerVerifierBase
1986 {
1987 public:
1988 QuantizeLayerVerifier(const std::string& layerName,
1989 const std::vector<armnn::TensorInfo>& inputInfos,
1990 const std::vector<armnn::TensorInfo>& outputInfos)
1991 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1992
1993 void VisitQuantizeLayer(const armnn::IConnectableLayer* layer, const char* name) override
1994 {
1995 VerifyNameAndConnections(layer, name);
1996 }
1997 };
1998
1999 const std::string layerName("quantize");
2000 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
2001
2002 armnn::INetworkPtr network = armnn::INetwork::Create();
2003 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2004 armnn::IConnectableLayer* const quantizeLayer = network->AddQuantizeLayer(layerName.c_str());
2005 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2006
2007 inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
2008 quantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2009
2010 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2011 quantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
2012
2013 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2014 BOOST_CHECK(deserializedNetwork);
2015
2016 QuantizeLayerVerifier verifier(layerName, {info}, {info});
2017 deserializedNetwork->Accept(verifier);
2018}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002019BOOST_AUTO_TEST_CASE(SerializeReshape)
2020{
2021 class ReshapeLayerVerifier : public LayerVerifierBase
2022 {
2023 public:
2024 ReshapeLayerVerifier(const std::string& layerName,
2025 const std::vector<armnn::TensorInfo>& inputInfos,
2026 const std::vector<armnn::TensorInfo>& outputInfos,
2027 const armnn::ReshapeDescriptor& descriptor)
2028 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2029 , m_Descriptor(descriptor) {}
2030
2031 void VisitReshapeLayer(const armnn::IConnectableLayer* layer,
2032 const armnn::ReshapeDescriptor& descriptor,
2033 const char* name) override
2034 {
2035 VerifyNameAndConnections(layer, name);
2036 VerifyDescriptor(descriptor);
2037 }
2038
2039 private:
2040 void VerifyDescriptor(const armnn::ReshapeDescriptor& descriptor)
2041 {
2042 BOOST_TEST(descriptor.m_TargetShape == m_Descriptor.m_TargetShape);
2043 }
2044
2045 armnn::ReshapeDescriptor m_Descriptor;
2046 };
2047
2048 const std::string layerName("reshape");
2049 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
2050 const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
2051
2052 armnn::ReshapeDescriptor descriptor({3, 3});
2053
2054 armnn::INetworkPtr network = armnn::INetwork::Create();
2055 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2056 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
2057 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2058
2059 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
2060 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2061
2062 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2063 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2064
2065 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2066 BOOST_CHECK(deserializedNetwork);
2067
2068 ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2069 deserializedNetwork->Accept(verifier);
2070}
2071
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002072BOOST_AUTO_TEST_CASE(SerializeResize)
2073{
2074 class ResizeLayerVerifier : public LayerVerifierBase
2075 {
2076 public:
2077 ResizeLayerVerifier(const std::string& layerName,
2078 const std::vector<armnn::TensorInfo>& inputInfos,
2079 const std::vector<armnn::TensorInfo>& outputInfos,
2080 const armnn::ResizeDescriptor& descriptor)
2081 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2082 , m_Descriptor(descriptor) {}
2083
2084 void VisitResizeLayer(const armnn::IConnectableLayer* layer,
2085 const armnn::ResizeDescriptor& descriptor,
2086 const char* name) override
2087 {
2088 VerifyNameAndConnections(layer, name);
2089 VerifyDescriptor(descriptor);
2090 }
2091
2092 private:
2093 void VerifyDescriptor(const armnn::ResizeDescriptor& descriptor)
2094 {
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002095 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2096 BOOST_CHECK(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002097 BOOST_CHECK(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002098 BOOST_CHECK(descriptor.m_Method == m_Descriptor.m_Method);
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002099 }
2100
2101 armnn::ResizeDescriptor m_Descriptor;
2102 };
2103
2104 const std::string layerName("resize");
2105 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2106 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2107
2108 armnn::ResizeDescriptor desc;
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002109 desc.m_TargetWidth = 4;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002110 desc.m_TargetHeight = 2;
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002111 desc.m_Method = armnn::ResizeMethod::NearestNeighbor;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002112
2113 armnn::INetworkPtr network = armnn::INetwork::Create();
2114 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2115 armnn::IConnectableLayer* const resizeLayer = network->AddResizeLayer(desc, layerName.c_str());
2116 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2117
2118 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2119 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2120
2121 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2122 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2123
2124 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2125 BOOST_CHECK(deserializedNetwork);
2126
2127 ResizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2128 deserializedNetwork->Accept(verifier);
2129}
2130
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002131BOOST_AUTO_TEST_CASE(SerializeRsqrt)
2132{
2133 class RsqrtLayerVerifier : public LayerVerifierBase
2134 {
2135 public:
2136 RsqrtLayerVerifier(const std::string& layerName,
2137 const std::vector<armnn::TensorInfo>& inputInfos,
2138 const std::vector<armnn::TensorInfo>& outputInfos)
2139 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2140
2141 void VisitRsqrtLayer(const armnn::IConnectableLayer* layer, const char* name) override
2142 {
2143 VerifyNameAndConnections(layer, name);
2144 }
2145 };
2146
2147 const std::string layerName("rsqrt");
2148 const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32);
2149
2150 armnn::INetworkPtr network = armnn::INetwork::Create();
2151 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2152 armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer(layerName.c_str());
2153 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2154
2155 inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0));
2156 rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2157
2158 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2159 rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2160
2161 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2162 BOOST_CHECK(deserializedNetwork);
2163
2164 RsqrtLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
2165 deserializedNetwork->Accept(verifier);
2166}
2167
2168BOOST_AUTO_TEST_CASE(SerializeSoftmax)
2169{
2170 class SoftmaxLayerVerifier : public LayerVerifierBase
2171 {
2172 public:
2173 SoftmaxLayerVerifier(const std::string& layerName,
2174 const std::vector<armnn::TensorInfo>& inputInfos,
2175 const std::vector<armnn::TensorInfo>& outputInfos,
2176 const armnn::SoftmaxDescriptor& descriptor)
2177 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2178 , m_Descriptor(descriptor) {}
2179
2180 void VisitSoftmaxLayer(const armnn::IConnectableLayer* layer,
2181 const armnn::SoftmaxDescriptor& descriptor,
2182 const char* name) override
2183 {
2184 VerifyNameAndConnections(layer, name);
2185 VerifyDescriptor(descriptor);
2186 }
2187
2188 private:
2189 void VerifyDescriptor(const armnn::SoftmaxDescriptor& descriptor)
2190 {
2191 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
2192 }
2193
2194 armnn::SoftmaxDescriptor m_Descriptor;
2195 };
2196
2197 const std::string layerName("softmax");
2198 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
2199
2200 armnn::SoftmaxDescriptor descriptor;
2201 descriptor.m_Beta = 1.0f;
2202
2203 armnn::INetworkPtr network = armnn::INetwork::Create();
2204 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2205 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
2206 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2207
2208 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
2209 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2210
2211 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2212 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
2213
2214 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2215 BOOST_CHECK(deserializedNetwork);
2216
2217 SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
2218 deserializedNetwork->Accept(verifier);
2219}
2220
2221BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
2222{
2223 class SpaceToBatchNdLayerVerifier : public LayerVerifierBase
2224 {
2225 public:
2226 SpaceToBatchNdLayerVerifier(const std::string& layerName,
2227 const std::vector<armnn::TensorInfo>& inputInfos,
2228 const std::vector<armnn::TensorInfo>& outputInfos,
2229 const armnn::SpaceToBatchNdDescriptor& descriptor)
2230 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2231 , m_Descriptor(descriptor) {}
2232
2233 void VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer* layer,
2234 const armnn::SpaceToBatchNdDescriptor& descriptor,
2235 const char* name) override
2236 {
2237 VerifyNameAndConnections(layer, name);
2238 VerifyDescriptor(descriptor);
2239 }
2240
2241 private:
2242 void VerifyDescriptor(const armnn::SpaceToBatchNdDescriptor& descriptor)
2243 {
2244 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
2245 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
2246 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2247 }
2248
2249 armnn::SpaceToBatchNdDescriptor m_Descriptor;
2250 };
2251
2252 const std::string layerName("spaceToBatchNd");
2253 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
2254 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
2255
2256 armnn::SpaceToBatchNdDescriptor desc;
2257 desc.m_DataLayout = armnn::DataLayout::NCHW;
2258 desc.m_BlockShape = {2, 2};
2259 desc.m_PadList = {{0, 0}, {2, 0}};
2260
2261 armnn::INetworkPtr network = armnn::INetwork::Create();
2262 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2263 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2264 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2265
2266 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
2267 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2268
2269 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2270 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2271
2272 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2273 BOOST_CHECK(deserializedNetwork);
2274
2275 SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2276 deserializedNetwork->Accept(verifier);
2277}
2278
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002279BOOST_AUTO_TEST_CASE(SerializeSpaceToDepth)
2280{
2281 class SpaceToDepthLayerVerifier : public LayerVerifierBase
2282 {
2283 public:
2284 SpaceToDepthLayerVerifier(const std::string& layerName,
2285 const std::vector<armnn::TensorInfo>& inputInfos,
2286 const std::vector<armnn::TensorInfo>& outputInfos,
2287 const armnn::SpaceToDepthDescriptor& descriptor)
2288 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2289 , m_Descriptor(descriptor) {}
2290
2291 void VisitSpaceToDepthLayer(const armnn::IConnectableLayer* layer,
2292 const armnn::SpaceToDepthDescriptor& descriptor,
2293 const char* name) override
2294 {
2295 VerifyNameAndConnections(layer, name);
2296 VerifyDescriptor(descriptor);
2297 }
2298
2299 private:
2300 void VerifyDescriptor(const armnn::SpaceToDepthDescriptor& descriptor)
2301 {
2302 BOOST_TEST(descriptor.m_BlockSize == m_Descriptor.m_BlockSize);
2303 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2304 }
2305
2306 armnn::SpaceToDepthDescriptor m_Descriptor;
2307 };
2308
2309 const std::string layerName("spaceToDepth");
2310
2311 const armnn::TensorInfo inputInfo ({ 1, 16, 8, 3 }, armnn::DataType::Float32);
2312 const armnn::TensorInfo outputInfo({ 1, 8, 4, 12 }, armnn::DataType::Float32);
2313
2314 armnn::SpaceToDepthDescriptor desc;
2315 desc.m_BlockSize = 2;
2316 desc.m_DataLayout = armnn::DataLayout::NHWC;
2317
2318 armnn::INetworkPtr network = armnn::INetwork::Create();
2319 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2320 armnn::IConnectableLayer* const spaceToDepthLayer = network->AddSpaceToDepthLayer(desc, layerName.c_str());
2321 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2322
2323 inputLayer->GetOutputSlot(0).Connect(spaceToDepthLayer->GetInputSlot(0));
2324 spaceToDepthLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2325
2326 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2327 spaceToDepthLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2328
2329 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2330 BOOST_CHECK(deserializedNetwork);
2331
2332 SpaceToDepthLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2333 deserializedNetwork->Accept(verifier);
2334}
2335
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002336BOOST_AUTO_TEST_CASE(SerializeSplitter)
2337{
2338 class SplitterLayerVerifier : public LayerVerifierBase
2339 {
2340 public:
2341 SplitterLayerVerifier(const std::string& layerName,
2342 const std::vector<armnn::TensorInfo>& inputInfos,
2343 const std::vector<armnn::TensorInfo>& outputInfos,
2344 const armnn::ViewsDescriptor& descriptor)
2345 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2346 , m_Descriptor(descriptor) {}
2347
2348 void VisitSplitterLayer(const armnn::IConnectableLayer* layer,
2349 const armnn::ViewsDescriptor& descriptor,
2350 const char* name) override
2351 {
2352 VerifyNameAndConnections(layer, name);
2353 VerifyDescriptor(descriptor);
2354 }
2355
2356 private:
2357 void VerifyDescriptor(const armnn::ViewsDescriptor& descriptor)
2358 {
2359 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
2360 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
2361
2362 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
2363 {
2364 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
2365 {
2366 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
2367 BOOST_TEST(descriptor.GetViewSizes(i)[j] == m_Descriptor.GetViewSizes(i)[j]);
2368 }
2369 }
2370 }
2371
2372 armnn::ViewsDescriptor m_Descriptor;
2373 };
2374
2375 const unsigned int numViews = 3;
2376 const unsigned int numDimensions = 4;
2377 const unsigned int inputShape[] = {1, 18, 4, 4};
2378 const unsigned int outputShape[] = {1, 6, 4, 4};
2379
2380 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
2381 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
2382 static_cast<unsigned int>(inputShape[1]),
2383 static_cast<unsigned int>(inputShape[2]),
2384 static_cast<unsigned int>(inputShape[3])};
2385 splitterDimSizes[1] /= numViews;
2386 armnn::ViewsDescriptor desc(numViews, numDimensions);
2387
2388 for (unsigned int g = 0; g < numViews; ++g)
2389 {
2390 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
2391
2392 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
2393 {
2394 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
2395 }
2396 }
2397
2398 const std::string layerName("splitter");
2399 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
2400 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
2401
2402 armnn::INetworkPtr network = armnn::INetwork::Create();
2403 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2404 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
2405 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2406 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2407 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
2408
2409 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
2410 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2411 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2412 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
2413
2414 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2415 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2416 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
2417 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2418
2419 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2420 BOOST_CHECK(deserializedNetwork);
2421
2422 SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
2423 deserializedNetwork->Accept(verifier);
2424}
2425
Matthew Jacksonb5433ee2019-07-11 15:54:20 +01002426BOOST_AUTO_TEST_CASE(SerializeStack)
2427{
2428 class StackLayerVerifier : public LayerVerifierBase
2429 {
2430 public:
2431 StackLayerVerifier(const std::string& layerName,
2432 const std::vector<armnn::TensorInfo>& inputInfos,
2433 const std::vector<armnn::TensorInfo>& outputInfos,
2434 const armnn::StackDescriptor& descriptor)
2435 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2436 , m_Descriptor(descriptor) {}
2437
2438 void VisitStackLayer(const armnn::IConnectableLayer* layer,
2439 const armnn::StackDescriptor& descriptor,
2440 const char* name) override
2441 {
2442 VerifyNameAndConnections(layer, name);
2443 VerifyDescriptor(descriptor);
2444 }
2445
2446 private:
2447 void VerifyDescriptor(const armnn::StackDescriptor& descriptor)
2448 {
2449 BOOST_TEST(descriptor.m_Axis == m_Descriptor.m_Axis);
2450 BOOST_TEST(descriptor.m_InputShape == m_Descriptor.m_InputShape);
2451 BOOST_TEST(descriptor.m_NumInputs == m_Descriptor.m_NumInputs);
2452 }
2453
2454 armnn::StackDescriptor m_Descriptor;
2455 };
2456
2457 const std::string layerName("stack");
2458
2459 armnn::TensorInfo inputTensorInfo ({4, 3, 5}, armnn::DataType::Float32);
2460 armnn::TensorInfo outputTensorInfo({4, 3, 2, 5}, armnn::DataType::Float32);
2461
2462 armnn::StackDescriptor descriptor(2, 2, {4, 3, 5});
2463
2464 armnn::INetworkPtr network = armnn::INetwork::Create();
2465 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
2466 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
2467 armnn::IConnectableLayer* const stackLayer = network->AddStackLayer(descriptor, layerName.c_str());
2468 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2469
2470 inputLayer1->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(0));
2471 inputLayer2->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(1));
2472 stackLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2473
2474 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2475 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2476 stackLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2477
2478 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2479 BOOST_CHECK(deserializedNetwork);
2480
2481 StackLayerVerifier verifier(layerName, {inputTensorInfo, inputTensorInfo}, {outputTensorInfo}, descriptor);
2482 deserializedNetwork->Accept(verifier);
2483}
2484
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002485BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
2486{
2487 class StridedSliceLayerVerifier : public LayerVerifierBase
2488 {
2489 public:
2490 StridedSliceLayerVerifier(const std::string& layerName,
2491 const std::vector<armnn::TensorInfo>& inputInfos,
2492 const std::vector<armnn::TensorInfo>& outputInfos,
2493 const armnn::StridedSliceDescriptor& descriptor)
2494 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2495 , m_Descriptor(descriptor) {}
2496
2497 void VisitStridedSliceLayer(const armnn::IConnectableLayer* layer,
2498 const armnn::StridedSliceDescriptor& descriptor,
2499 const char* name) override
2500 {
2501 VerifyNameAndConnections(layer, name);
2502 VerifyDescriptor(descriptor);
2503 }
2504
2505 private:
2506 void VerifyDescriptor(const armnn::StridedSliceDescriptor& descriptor)
2507 {
2508 BOOST_TEST(descriptor.m_Begin == m_Descriptor.m_Begin);
2509 BOOST_TEST(descriptor.m_End == m_Descriptor.m_End);
2510 BOOST_TEST(descriptor.m_Stride == m_Descriptor.m_Stride);
2511 BOOST_TEST(descriptor.m_BeginMask == m_Descriptor.m_BeginMask);
2512 BOOST_TEST(descriptor.m_EndMask == m_Descriptor.m_EndMask);
2513 BOOST_TEST(descriptor.m_ShrinkAxisMask == m_Descriptor.m_ShrinkAxisMask);
2514 BOOST_TEST(descriptor.m_EllipsisMask == m_Descriptor.m_EllipsisMask);
2515 BOOST_TEST(descriptor.m_NewAxisMask == m_Descriptor.m_NewAxisMask);
2516 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2517 }
2518 armnn::StridedSliceDescriptor m_Descriptor;
2519 };
2520
2521 const std::string layerName("stridedSlice");
2522 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2523 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2524
2525 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2526 desc.m_EndMask = (1 << 4) - 1;
2527 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2528 desc.m_DataLayout = armnn::DataLayout::NCHW;
2529
2530 armnn::INetworkPtr network = armnn::INetwork::Create();
2531 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2532 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2533 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2534
2535 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2536 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2537
2538 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2539 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2540
2541 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2542 BOOST_CHECK(deserializedNetwork);
2543
2544 StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2545 deserializedNetwork->Accept(verifier);
2546}
2547
2548BOOST_AUTO_TEST_CASE(SerializeSubtraction)
2549{
2550 class SubtractionLayerVerifier : public LayerVerifierBase
2551 {
2552 public:
2553 SubtractionLayerVerifier(const std::string& layerName,
2554 const std::vector<armnn::TensorInfo>& inputInfos,
2555 const std::vector<armnn::TensorInfo>& outputInfos)
2556 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2557
2558 void VisitSubtractionLayer(const armnn::IConnectableLayer* layer, const char* name) override
2559 {
2560 VerifyNameAndConnections(layer, name);
2561 }
2562 };
2563
2564 const std::string layerName("subtraction");
2565 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2566
2567 armnn::INetworkPtr network = armnn::INetwork::Create();
2568 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2569 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2570 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2571 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2572
2573 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2574 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2575 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2576
2577 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2578 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2579 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2580
2581 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2582 BOOST_CHECK(deserializedNetwork);
2583
2584 SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
2585 deserializedNetwork->Accept(verifier);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +00002586}
2587
Sadik Armaganeff363d2019-04-05 15:25:46 +01002588BOOST_AUTO_TEST_CASE(SerializeSwitch)
2589{
2590 class SwitchLayerVerifier : public LayerVerifierBase
2591 {
2592 public:
2593 SwitchLayerVerifier(const std::string& layerName,
2594 const std::vector<armnn::TensorInfo>& inputInfos,
2595 const std::vector<armnn::TensorInfo>& outputInfos)
2596 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2597
2598 void VisitSwitchLayer(const armnn::IConnectableLayer* layer, const char* name) override
2599 {
2600 VerifyNameAndConnections(layer, name);
2601 }
2602
2603 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2604 const armnn::ConstTensor& input,
2605 const char *name) override {}
2606 };
2607
2608 const std::string layerName("switch");
2609 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2610
2611 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2612 armnn::ConstTensor constTensor(info, constantData);
2613
2614 armnn::INetworkPtr network = armnn::INetwork::Create();
2615 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2616 armnn::IConnectableLayer* const constantLayer = network->AddConstantLayer(constTensor, "constant");
2617 armnn::IConnectableLayer* const switchLayer = network->AddSwitchLayer(layerName.c_str());
2618 armnn::IConnectableLayer* const trueOutputLayer = network->AddOutputLayer(0);
2619 armnn::IConnectableLayer* const falseOutputLayer = network->AddOutputLayer(1);
2620
2621 inputLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(0));
2622 constantLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(1));
2623 switchLayer->GetOutputSlot(0).Connect(trueOutputLayer->GetInputSlot(0));
2624 switchLayer->GetOutputSlot(1).Connect(falseOutputLayer->GetInputSlot(0));
2625
2626 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2627 constantLayer->GetOutputSlot(0).SetTensorInfo(info);
2628 switchLayer->GetOutputSlot(0).SetTensorInfo(info);
2629 switchLayer->GetOutputSlot(1).SetTensorInfo(info);
2630
2631 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2632 BOOST_CHECK(deserializedNetwork);
2633
2634 SwitchLayerVerifier verifier(layerName, {info, info}, {info, info});
2635 deserializedNetwork->Accept(verifier);
2636}
2637
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002638BOOST_AUTO_TEST_CASE(SerializeTransposeConvolution2d)
2639{
2640 class TransposeConvolution2dLayerVerifier : public LayerVerifierBase
2641 {
2642 public:
2643 TransposeConvolution2dLayerVerifier(const std::string& layerName,
2644 const std::vector<armnn::TensorInfo>& inputInfos,
2645 const std::vector<armnn::TensorInfo>& outputInfos,
2646 const armnn::TransposeConvolution2dDescriptor& descriptor,
2647 const armnn::ConstTensor& weights,
2648 const armnn::Optional<armnn::ConstTensor>& biases) :
2649 LayerVerifierBase(layerName, inputInfos, outputInfos),
2650 m_Descriptor(descriptor),
2651 m_Weights(weights),
2652 m_Biases(biases)
2653 {}
2654
2655 void VisitTransposeConvolution2dLayer(const armnn::IConnectableLayer* layer,
2656 const armnn::TransposeConvolution2dDescriptor& descriptor,
2657 const armnn::ConstTensor& weights,
2658 const armnn::Optional<armnn::ConstTensor>& biases,
2659 const char* name) override
2660 {
2661 VerifyNameAndConnections(layer, name);
2662 VerifyDescriptor(descriptor);
2663
2664 // check weights
2665 CompareConstTensor(weights, m_Weights);
2666
2667 // check biases
2668 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
2669 BOOST_CHECK(m_Biases.has_value() == m_Descriptor.m_BiasEnabled);
2670
2671 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
2672
2673 if (biases.has_value() && m_Biases.has_value())
2674 {
2675 CompareConstTensor(biases.value(), m_Biases.value());
2676 }
2677 }
2678
2679 private:
2680 void VerifyDescriptor(const armnn::TransposeConvolution2dDescriptor& descriptor)
2681 {
2682 BOOST_CHECK(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
2683 BOOST_CHECK(descriptor.m_PadRight == m_Descriptor.m_PadRight);
2684 BOOST_CHECK(descriptor.m_PadTop == m_Descriptor.m_PadTop);
2685 BOOST_CHECK(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
2686 BOOST_CHECK(descriptor.m_StrideX == m_Descriptor.m_StrideX);
2687 BOOST_CHECK(descriptor.m_StrideY == m_Descriptor.m_StrideY);
2688 BOOST_CHECK(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
2689 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2690 }
2691
2692 armnn::TransposeConvolution2dDescriptor m_Descriptor;
2693 armnn::ConstTensor m_Weights;
2694 armnn::Optional<armnn::ConstTensor> m_Biases;
2695 };
2696
2697 const std::string layerName("transposeConvolution2d");
2698 const armnn::TensorInfo inputInfo ({ 1, 7, 7, 1 }, armnn::DataType::Float32);
2699 const armnn::TensorInfo outputInfo({ 1, 9, 9, 1 }, armnn::DataType::Float32);
2700
2701 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
2702 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
2703
2704 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
2705 armnn::ConstTensor weights(weightsInfo, weightsData);
2706
2707 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
2708 armnn::ConstTensor biases(biasesInfo, biasesData);
2709
2710 armnn::TransposeConvolution2dDescriptor descriptor;
2711 descriptor.m_PadLeft = 1;
2712 descriptor.m_PadRight = 1;
2713 descriptor.m_PadTop = 1;
2714 descriptor.m_PadBottom = 1;
2715 descriptor.m_StrideX = 1;
2716 descriptor.m_StrideY = 1;
2717 descriptor.m_BiasEnabled = true;
2718 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
2719
2720 armnn::INetworkPtr network = armnn::INetwork::Create();
2721 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2722 armnn::IConnectableLayer* const convLayer =
2723 network->AddTransposeConvolution2dLayer(descriptor,
2724 weights,
2725 armnn::Optional<armnn::ConstTensor>(biases),
2726 layerName.c_str());
2727 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2728
2729 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
2730 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2731
2732 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2733 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2734
2735 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2736 BOOST_CHECK(deserializedNetwork);
2737
2738 TransposeConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
2739 deserializedNetwork->Accept(verifier);
2740}
2741
Sadik Armagandb059fd2019-03-20 12:28:32 +00002742BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
2743{
2744 class ConstantLayerVerifier : public LayerVerifierBase
2745 {
2746 public:
2747 ConstantLayerVerifier(const std::string& layerName,
2748 const std::vector<armnn::TensorInfo>& inputInfos,
2749 const std::vector<armnn::TensorInfo>& outputInfos,
2750 const armnn::ConstTensor& layerInput)
2751 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2752 , m_LayerInput(layerInput) {}
2753
2754 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2755 const armnn::ConstTensor& input,
2756 const char* name) override
2757 {
2758 VerifyNameAndConnections(layer, name);
2759
2760 CompareConstTensor(input, m_LayerInput);
2761 }
2762
2763 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
2764
2765 private:
2766 armnn::ConstTensor m_LayerInput;
2767 };
2768
2769 const std::string layerName("constant");
2770 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
2771
2772 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2773 armnn::ConstTensor constTensor(info, constantData);
2774
2775 armnn::INetworkPtr network(armnn::INetwork::Create());
2776 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2777 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2778 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2779 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2780
2781 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2782 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2783 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2784
2785 input->GetOutputSlot(0).SetTensorInfo(info);
2786 constant->GetOutputSlot(0).SetTensorInfo(info);
2787 add->GetOutputSlot(0).SetTensorInfo(info);
2788
2789 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2790 BOOST_CHECK(deserializedNetwork);
2791
2792 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
2793 deserializedNetwork->Accept(verifier);
2794}
2795
Jim Flynn11af3752019-03-19 17:22:29 +00002796class VerifyLstmLayer : public LayerVerifierBase
2797{
2798public:
2799 VerifyLstmLayer(const std::string& layerName,
2800 const std::vector<armnn::TensorInfo>& inputInfos,
2801 const std::vector<armnn::TensorInfo>& outputInfos,
2802 const armnn::LstmDescriptor& descriptor,
2803 const armnn::LstmInputParams& inputParams) :
2804 LayerVerifierBase(layerName, inputInfos, outputInfos), m_Descriptor(descriptor), m_InputParams(inputParams)
2805 {
2806 }
2807 void VisitLstmLayer(const armnn::IConnectableLayer* layer,
2808 const armnn::LstmDescriptor& descriptor,
2809 const armnn::LstmInputParams& params,
2810 const char* name)
2811 {
2812 VerifyNameAndConnections(layer, name);
2813 VerifyDescriptor(descriptor);
2814 VerifyInputParameters(params);
2815 }
2816protected:
2817 void VerifyDescriptor(const armnn::LstmDescriptor& descriptor)
2818 {
2819 BOOST_TEST(m_Descriptor.m_ActivationFunc == descriptor.m_ActivationFunc);
2820 BOOST_TEST(m_Descriptor.m_ClippingThresCell == descriptor.m_ClippingThresCell);
2821 BOOST_TEST(m_Descriptor.m_ClippingThresProj == descriptor.m_ClippingThresProj);
2822 BOOST_TEST(m_Descriptor.m_CifgEnabled == descriptor.m_CifgEnabled);
2823 BOOST_TEST(m_Descriptor.m_PeepholeEnabled = descriptor.m_PeepholeEnabled);
2824 BOOST_TEST(m_Descriptor.m_ProjectionEnabled == descriptor.m_ProjectionEnabled);
Jan Eilersf8c62972019-07-17 11:07:49 +01002825 BOOST_TEST(m_Descriptor.m_LayerNormEnabled == descriptor.m_LayerNormEnabled);
Jim Flynn11af3752019-03-19 17:22:29 +00002826 }
2827 void VerifyInputParameters(const armnn::LstmInputParams& params)
2828 {
2829 VerifyConstTensors(
2830 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
2831 VerifyConstTensors(
2832 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
2833 VerifyConstTensors(
2834 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
2835 VerifyConstTensors(
2836 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
2837 VerifyConstTensors(
2838 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
2839 VerifyConstTensors(
2840 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
2841 VerifyConstTensors(
2842 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
2843 VerifyConstTensors(
2844 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
2845 VerifyConstTensors(
2846 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
2847 VerifyConstTensors(
2848 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
2849 VerifyConstTensors(
2850 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
2851 VerifyConstTensors(
2852 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
2853 VerifyConstTensors(
2854 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
2855 VerifyConstTensors(
2856 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
2857 VerifyConstTensors(
2858 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
2859 VerifyConstTensors(
2860 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
2861 VerifyConstTensors(
2862 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
Jan Eilersf8c62972019-07-17 11:07:49 +01002863 VerifyConstTensors(
2864 "m_InputLayerNormWeights", m_InputParams.m_InputLayerNormWeights, params.m_InputLayerNormWeights);
2865 VerifyConstTensors(
2866 "m_ForgetLayerNormWeights", m_InputParams.m_ForgetLayerNormWeights, params.m_ForgetLayerNormWeights);
2867 VerifyConstTensors(
2868 "m_CellLayerNormWeights", m_InputParams.m_CellLayerNormWeights, params.m_CellLayerNormWeights);
2869 VerifyConstTensors(
2870 "m_OutputLayerNormWeights", m_InputParams.m_OutputLayerNormWeights, params.m_OutputLayerNormWeights);
Jim Flynn11af3752019-03-19 17:22:29 +00002871 }
Jim Flynn11af3752019-03-19 17:22:29 +00002872private:
2873 armnn::LstmDescriptor m_Descriptor;
2874 armnn::LstmInputParams m_InputParams;
2875};
2876
2877BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
2878{
2879 armnn::LstmDescriptor descriptor;
2880 descriptor.m_ActivationFunc = 4;
2881 descriptor.m_ClippingThresProj = 0.0f;
2882 descriptor.m_ClippingThresCell = 0.0f;
2883 descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
2884 descriptor.m_ProjectionEnabled = false;
2885 descriptor.m_PeepholeEnabled = true;
2886
2887 const uint32_t batchSize = 1;
2888 const uint32_t inputSize = 2;
2889 const uint32_t numUnits = 4;
2890 const uint32_t outputSize = numUnits;
2891
2892 armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
2893 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2894 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
2895
2896 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2897 armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
2898
2899 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2900 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
2901
2902 armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
2903 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2904 armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
2905
2906 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2907 armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
2908
2909 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2910 armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
2911
2912 armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
2913 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2914 armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
2915
2916 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2917 armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
2918
2919 std::vector<float> forgetGateBiasData(numUnits, 1.0f);
2920 armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
2921
2922 std::vector<float> cellBiasData(numUnits, 0.0f);
2923 armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
2924
2925 std::vector<float> outputGateBiasData(numUnits, 0.0f);
2926 armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
2927
2928 armnn::LstmInputParams params;
2929 params.m_InputToForgetWeights = &inputToForgetWeights;
2930 params.m_InputToCellWeights = &inputToCellWeights;
2931 params.m_InputToOutputWeights = &inputToOutputWeights;
2932 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2933 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2934 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2935 params.m_ForgetGateBias = &forgetGateBias;
2936 params.m_CellBias = &cellBias;
2937 params.m_OutputGateBias = &outputGateBias;
2938 params.m_CellToForgetWeights = &cellToForgetWeights;
2939 params.m_CellToOutputWeights = &cellToOutputWeights;
2940
2941 armnn::INetworkPtr network = armnn::INetwork::Create();
2942 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2943 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2944 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2945 const std::string layerName("lstm");
2946 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2947 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2948 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2949 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2950 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2951
2952 // connect up
2953 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2954 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2955 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2956 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
2957
2958 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2959 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2960
2961 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2962 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2963
2964 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2965 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2966
2967 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2968 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2969
2970 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2971 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2972
2973 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2974 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2975
2976 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2977 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2978
2979 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2980 BOOST_CHECK(deserializedNetwork);
2981
2982 VerifyLstmLayer checker(
2983 layerName,
2984 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2985 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2986 descriptor,
2987 params);
2988 deserializedNetwork->Accept(checker);
2989}
2990
2991BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
2992{
2993 armnn::LstmDescriptor descriptor;
2994 descriptor.m_ActivationFunc = 4;
2995 descriptor.m_ClippingThresProj = 0.0f;
2996 descriptor.m_ClippingThresCell = 0.0f;
2997 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
2998 descriptor.m_ProjectionEnabled = true;
2999 descriptor.m_PeepholeEnabled = true;
3000
3001 const uint32_t batchSize = 2;
3002 const uint32_t inputSize = 5;
3003 const uint32_t numUnits = 20;
3004 const uint32_t outputSize = 16;
3005
3006 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3007 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3008 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3009
3010 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3011 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3012
3013 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3014 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3015
3016 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3017 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3018
3019 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3020 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3021 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3022
3023 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3024 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3025
3026 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3027 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3028
3029 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3030 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3031
3032 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3033 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3034 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3035
3036 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3037 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3038
3039 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3040 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3041
3042 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3043 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3044
3045 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3046 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3047
3048 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3049 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3050
3051 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3052 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3053
3054 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3055 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
3056 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3057
3058 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3059 std::vector<float> projectionBiasData(outputSize, 0.f);
3060 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3061
3062 armnn::LstmInputParams params;
3063 params.m_InputToForgetWeights = &inputToForgetWeights;
3064 params.m_InputToCellWeights = &inputToCellWeights;
3065 params.m_InputToOutputWeights = &inputToOutputWeights;
3066 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3067 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3068 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3069 params.m_ForgetGateBias = &forgetGateBias;
3070 params.m_CellBias = &cellBias;
3071 params.m_OutputGateBias = &outputGateBias;
3072
3073 // additional params because: descriptor.m_CifgEnabled = false
3074 params.m_InputToInputWeights = &inputToInputWeights;
3075 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3076 params.m_CellToInputWeights = &cellToInputWeights;
3077 params.m_InputGateBias = &inputGateBias;
3078
3079 // additional params because: descriptor.m_ProjectionEnabled = true
3080 params.m_ProjectionWeights = &projectionWeights;
3081 params.m_ProjectionBias = &projectionBias;
3082
3083 // additional params because: descriptor.m_PeepholeEnabled = true
3084 params.m_CellToForgetWeights = &cellToForgetWeights;
3085 params.m_CellToOutputWeights = &cellToOutputWeights;
3086
3087 armnn::INetworkPtr network = armnn::INetwork::Create();
3088 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3089 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3090 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3091 const std::string layerName("lstm");
3092 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3093 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3094 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3095 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3096 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3097
3098 // connect up
3099 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3100 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3101 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3102 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3103
3104 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3105 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3106
3107 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3108 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3109
3110 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3111 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3112
3113 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3114 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3115
3116 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3117 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3118
3119 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3120 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3121
3122 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3123 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3124
3125 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3126 BOOST_CHECK(deserializedNetwork);
3127
3128 VerifyLstmLayer checker(
3129 layerName,
3130 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3131 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3132 descriptor,
3133 params);
3134 deserializedNetwork->Accept(checker);
3135}
3136
Jan Eilersf8c62972019-07-17 11:07:49 +01003137BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeWithProjectionWithLayerNorm)
3138{
3139 armnn::LstmDescriptor descriptor;
3140 descriptor.m_ActivationFunc = 4;
3141 descriptor.m_ClippingThresProj = 0.0f;
3142 descriptor.m_ClippingThresCell = 0.0f;
3143 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
3144 descriptor.m_ProjectionEnabled = true;
3145 descriptor.m_PeepholeEnabled = true;
3146 descriptor.m_LayerNormEnabled = true;
3147
3148 const uint32_t batchSize = 2;
3149 const uint32_t inputSize = 5;
3150 const uint32_t numUnits = 20;
3151 const uint32_t outputSize = 16;
3152
3153 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3154 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3155 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3156
3157 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3158 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3159
3160 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3161 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3162
3163 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3164 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3165
3166 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3167 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3168 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3169
3170 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3171 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3172
3173 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3174 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3175
3176 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3177 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3178
3179 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3180 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3181 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3182
3183 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3184 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3185
3186 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3187 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3188
3189 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3190 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3191
3192 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3193 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3194
3195 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3196 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3197
3198 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3199 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3200
3201 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3202 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
3203 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3204
3205 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3206 std::vector<float> projectionBiasData(outputSize, 0.f);
3207 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3208
3209 std::vector<float> inputLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3210 armnn::ConstTensor inputLayerNormWeights(tensorInfo20, forgetGateBiasData);
3211
3212 std::vector<float> forgetLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3213 armnn::ConstTensor forgetLayerNormWeights(tensorInfo20, forgetGateBiasData);
3214
3215 std::vector<float> cellLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3216 armnn::ConstTensor cellLayerNormWeights(tensorInfo20, forgetGateBiasData);
3217
3218 std::vector<float> outLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3219 armnn::ConstTensor outLayerNormWeights(tensorInfo20, forgetGateBiasData);
3220
3221 armnn::LstmInputParams params;
3222 params.m_InputToForgetWeights = &inputToForgetWeights;
3223 params.m_InputToCellWeights = &inputToCellWeights;
3224 params.m_InputToOutputWeights = &inputToOutputWeights;
3225 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3226 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3227 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3228 params.m_ForgetGateBias = &forgetGateBias;
3229 params.m_CellBias = &cellBias;
3230 params.m_OutputGateBias = &outputGateBias;
3231
3232 // additional params because: descriptor.m_CifgEnabled = false
3233 params.m_InputToInputWeights = &inputToInputWeights;
3234 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3235 params.m_CellToInputWeights = &cellToInputWeights;
3236 params.m_InputGateBias = &inputGateBias;
3237
3238 // additional params because: descriptor.m_ProjectionEnabled = true
3239 params.m_ProjectionWeights = &projectionWeights;
3240 params.m_ProjectionBias = &projectionBias;
3241
3242 // additional params because: descriptor.m_PeepholeEnabled = true
3243 params.m_CellToForgetWeights = &cellToForgetWeights;
3244 params.m_CellToOutputWeights = &cellToOutputWeights;
3245
3246 // additional params because: despriptor.m_LayerNormEnabled = true
3247 params.m_InputLayerNormWeights = &inputLayerNormWeights;
3248 params.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
3249 params.m_CellLayerNormWeights = &cellLayerNormWeights;
3250 params.m_OutputLayerNormWeights = &outLayerNormWeights;
3251
3252 armnn::INetworkPtr network = armnn::INetwork::Create();
3253 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3254 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3255 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3256 const std::string layerName("lstm");
3257 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3258 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3259 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3260 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3261 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3262
3263 // connect up
3264 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3265 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3266 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3267 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3268
3269 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3270 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3271
3272 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3273 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3274
3275 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3276 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3277
3278 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3279 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3280
3281 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3282 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3283
3284 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3285 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3286
3287 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3288 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3289
3290 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3291 BOOST_CHECK(deserializedNetwork);
3292
3293 VerifyLstmLayer checker(
3294 layerName,
3295 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3296 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3297 descriptor,
3298 params);
3299 deserializedNetwork->Accept(checker);
3300}
3301
3302BOOST_AUTO_TEST_CASE(EnsureLstmLayersBackwardCompatibility)
3303{
3304 // The hex array below is a flat buffer containing a lstm layer with no Cifg, with peephole and projection
3305 // enabled. That array is created before additional layer normalization parameters where added to the
3306 // lstm serializer. That way it can be tested if a lstm model with the old parameter configuration can still be
3307 // loaded
3308 unsigned int size = 10900;
3309 const unsigned char LstmNoCifgWithPeepholeAndProjection_Model[] = {
3310 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
3311 0x0C,0x00,0x00,0x00,0x2C,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0xDC,0x29,0x00,0x00,
3312 0x38,0x29,0x00,0x00,0xB4,0x28,0x00,0x00,0x94,0x01,0x00,0x00,0x3C,0x01,0x00,0x00,0xE0,0x00,0x00,0x00,
3313 0x84,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3314 0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
3315 0x07,0x00,0x00,0x00,0x70,0xD6,0xFF,0xFF,0x00,0x00,0x00,0x0B,0x04,0x00,0x00,0x00,0x06,0xD7,0xFF,0xFF,
3316 0x04,0x00,0x00,0x00,0x88,0xD7,0xFF,0xFF,0x08,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xF6,0xD6,0xFF,0xFF,
3317 0x07,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
3318 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3319 0xE8,0xD7,0xFF,0xFF,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xC8,0xD6,0xFF,0xFF,0x00,0x00,0x00,0x0B,
3320 0x04,0x00,0x00,0x00,0x5E,0xD7,0xFF,0xFF,0x04,0x00,0x00,0x00,0xE0,0xD7,0xFF,0xFF,0x08,0x00,0x00,0x00,
3321 0x02,0x00,0x00,0x00,0x4E,0xD7,0xFF,0xFF,0x06,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
3322 0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3323 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xD8,0xFF,0xFF,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3324 0x20,0xD7,0xFF,0xFF,0x00,0x00,0x00,0x0B,0x04,0x00,0x00,0x00,0xB6,0xD7,0xFF,0xFF,0x04,0x00,0x00,0x00,
3325 0x38,0xD8,0xFF,0xFF,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xA6,0xD7,0xFF,0xFF,0x05,0x00,0x00,0x00,
3326 0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3327 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0xD8,0xFF,0xFF,
3328 0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x78,0xD7,0xFF,0xFF,0x00,0x00,0x00,0x0B,0x04,0x00,0x00,0x00,
3329 0x0E,0xD8,0xFF,0xFF,0x04,0x00,0x00,0x00,0x16,0xD8,0xFF,0xFF,0x04,0x00,0x00,0x00,0xFA,0xD7,0xFF,0xFF,
3330 0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
3331 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3332 0xEC,0xD8,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xD8,0xFF,0xFF,0x00,0x00,0x00,0x23,
3333 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x12,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
3334 0xE0,0x25,0x00,0x00,0xD0,0x25,0x00,0x00,0x2C,0x00,0x00,0x00,0x00,0x00,0x26,0x00,0x48,0x00,0x04,0x00,
3335 0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,0x18,0x00,0x1C,0x00,0x20,0x00,0x24,0x00,0x28,0x00,0x2C,0x00,
3336 0x30,0x00,0x34,0x00,0x38,0x00,0x3C,0x00,0x40,0x00,0x44,0x00,0x26,0x00,0x00,0x00,0xC4,0x23,0x00,0x00,
3337 0xF8,0x21,0x00,0x00,0x2C,0x20,0x00,0x00,0xF0,0x1A,0x00,0x00,0xB4,0x15,0x00,0x00,0x78,0x10,0x00,0x00,
3338 0xF0,0x0F,0x00,0x00,0x68,0x0F,0x00,0x00,0xE0,0x0E,0x00,0x00,0x14,0x0D,0x00,0x00,0xD8,0x07,0x00,0x00,
3339 0x50,0x07,0x00,0x00,0xC8,0x06,0x00,0x00,0x8C,0x01,0x00,0x00,0x14,0x01,0x00,0x00,0x8C,0x00,0x00,0x00,
3340 0x04,0x00,0x00,0x00,0xEE,0xD7,0xFF,0xFF,0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
3341 0xFE,0xD8,0xFF,0xFF,0x04,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3342 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3343 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3344 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3345 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5A,0xD8,0xFF,0xFF,0x00,0x00,0x00,0x01,
3346 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x72,0xD8,0xFF,0xFF,
3347 0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x82,0xD9,0xFF,0xFF,0x04,0x00,0x00,0x00,
3348 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3349 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3350 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3351 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3352 0x00,0x00,0x00,0x00,0xDE,0xD8,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3353 0x01,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0xF6,0xD8,0xFF,0xFF,0x00,0x00,0x00,0x03,0x54,0x00,0x00,0x00,
3354 0x04,0x00,0x00,0x00,0x06,0xDA,0xFF,0xFF,0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3355 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3356 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3357 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3358 0x52,0xD9,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3359 0x10,0x00,0x00,0x00,0x6A,0xD9,0xFF,0xFF,0x00,0x00,0x00,0x03,0x14,0x05,0x00,0x00,0x04,0x00,0x00,0x00,
3360 0x7A,0xDA,0xFF,0xFF,0x04,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3361 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3362 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3363 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3364 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3365 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3366 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3367 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3368 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3369 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3370 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3371 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3372 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3373 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3374 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3375 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3376 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3377 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3378 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3379 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3380 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3381 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3382 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3383 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3384 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3385 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3386 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3387 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3388 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3389 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3390 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3391 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3392 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3393 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3394 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3395 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3396 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3397 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3398 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3399 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3400 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3401 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3402 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3403 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3404 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3405 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3406 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3407 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3408 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3409 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3410 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3411 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3412 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3413 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3414 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3415 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3416 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3417 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3418 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3419 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3420 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3421 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3422 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3423 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3424 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x86,0xDE,0xFF,0xFF,0x00,0x00,0x00,0x01,
3425 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
3426 0xA2,0xDE,0xFF,0xFF,0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xB2,0xDF,0xFF,0xFF,
3427 0x04,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3428 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3429 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3430 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3431 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0xDF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
3432 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x26,0xDF,0xFF,0xFF,0x00,0x00,0x00,0x03,
3433 0x64,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x36,0xE0,0xFF,0xFF,0x04,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
3434 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3435 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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 0x92,0xDF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3439 0x14,0x00,0x00,0x00,0xAA,0xDF,0xFF,0xFF,0x00,0x00,0x00,0x03,0x14,0x05,0x00,0x00,0x04,0x00,0x00,0x00,
3440 0xBA,0xE0,0xFF,0xFF,0x04,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3441 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3442 0x00,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3447 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3448 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3449 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3453 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3454 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3455 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xC6,0xE4,0xFF,0xFF,0x00,0x00,0x00,0x01,
3505 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
3506 0xE2,0xE4,0xFF,0xFF,0x00,0x00,0x00,0x03,0xA4,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xF2,0xE5,0xFF,0xFF,
3507 0x04,0x00,0x00,0x00,0x64,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3519 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3520 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3521 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3526 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3527 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0xE6,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
3528 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0xAA,0xE6,0xFF,0xFF,
3529 0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xBA,0xE7,0xFF,0xFF,0x04,0x00,0x00,0x00,
3530 0x14,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 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3533 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3534 0x00,0x00,0x00,0x00,0x16,0xE7,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3535 0x01,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x2E,0xE7,0xFF,0xFF,0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,
3536 0x04,0x00,0x00,0x00,0x3E,0xE8,0xFF,0xFF,0x04,0x00,0x00,0x00,0x14,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,0x9A,0xE7,0xFF,0xFF,
3541 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
3542 0xB2,0xE7,0xFF,0xFF,0x00,0x00,0x00,0x03,0x64,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xC2,0xE8,0xFF,0xFF,
3543 0x04,0x00,0x00,0x00,0x14,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,0x1E,0xE8,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
3548 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x36,0xE8,0xFF,0xFF,0x00,0x00,0x00,0x03,
3549 0x14,0x05,0x00,0x00,0x04,0x00,0x00,0x00,0x46,0xE9,0xFF,0xFF,0x04,0x00,0x00,0x00,0x40,0x01,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3599 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3600 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3601 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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 0x52,0xED,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3615 0x14,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x6E,0xED,0xFF,0xFF,0x00,0x00,0x00,0x03,0x14,0x05,0x00,0x00,
3616 0x04,0x00,0x00,0x00,0x7E,0xEE,0xFF,0xFF,0x04,0x00,0x00,0x00,0x40,0x01,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3622 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3623 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3624 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3629 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3630 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3631 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x00,0x00,0x00,0x00,
3635 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3636 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3637 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3638 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3642 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3643 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3644 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x8A,0xF2,0xFF,0xFF,
3681 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
3682 0x10,0x00,0x00,0x00,0xA6,0xF2,0xFF,0xFF,0x00,0x00,0x00,0x03,0x14,0x05,0x00,0x00,0x04,0x00,0x00,0x00,
3683 0xB6,0xF3,0xFF,0xFF,0x04,0x00,0x00,0x00,0x40,0x01,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 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3709 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3710 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3711 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xC2,0xF7,0xFF,0xFF,0x00,0x00,0x00,0x01,
3748 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
3749 0xDE,0xF7,0xFF,0xFF,0x00,0x00,0x00,0x03,0xA4,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xEE,0xF8,0xFF,0xFF,
3750 0x04,0x00,0x00,0x00,0x64,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,0x8A,0xF9,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
3771 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0xA6,0xF9,0xFF,0xFF,
3772 0x00,0x00,0x00,0x03,0xA4,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xB6,0xFA,0xFF,0xFF,0x04,0x00,0x00,0x00,
3773 0x64,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,0x00,0x00,0x00,0x00,
3775 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3776 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3777 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3778 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x52,0xFB,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3794 0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x6E,0xFB,0xFF,0xFF,0x00,0x00,0x00,0x03,
3795 0xA4,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0x7E,0xFC,0xFF,0xFF,0x04,0x00,0x00,0x00,0x64,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 0x1A,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3817 0x14,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x10,0x00,0x0C,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x05,0x00,
3818 0x06,0x00,0x07,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x04,0x00,0x00,0x00,0x2E,0xFE,0xFF,0xFF,
3819 0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
3820 0x04,0x00,0x00,0x00,0x6C,0x73,0x74,0x6D,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xEC,0x00,0x00,0x00,
3821 0xD0,0x00,0x00,0x00,0xB4,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x88,0x00,0x00,0x00,0x5C,0x00,0x00,0x00,
3822 0x30,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x14,0xFF,0xFF,0xFF,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
3823 0xA6,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3824 0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x3C,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
3825 0xCE,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3826 0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x64,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
3827 0xF6,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3828 0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0xB4,0xFE,0xFF,0xFF,0x04,0x00,0x00,0x00,0x1A,0xFE,0xFF,0xFF,
3829 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3830 0x50,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3831 0x08,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3832 0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3833 0x00,0x00,0x00,0x00,0xE8,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00,0x7E,0xFF,0xFF,0xFF,
3834 0x0C,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
3835 0x02,0x00,0x00,0x00,0x76,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3836 0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3837 0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x68,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0xCE,0xFE,0xFF,0xFF,
3838 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3839 0x10,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x09,
3840 0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,
3841 0x08,0x00,0x0E,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3842 0x00,0x00,0x0E,0x00,0x18,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,0x0E,0x00,0x00,0x00,
3843 0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
3844 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,
3845 0x08,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x6E,0xFF,0xFF,0xFF,
3846 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
3847 0x14,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x09,
3848 0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0A,0x00,0x04,0x00,
3849 0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x08,0x00,
3850 0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
3851 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
3852 0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
3853 0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
3854 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0 };
3855
3856 std::stringstream ss;
3857 for (unsigned int i = 0; i < size; ++i)
3858 {
3859 ss << LstmNoCifgWithPeepholeAndProjection_Model[i];
3860 }
3861 std::string lstmLayerNetwork = ss.str();
3862 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(lstmLayerNetwork);
3863 BOOST_CHECK(deserializedNetwork);
3864
3865 // generating the same model parameters which where used to serialize the model (Layer norm is not specified)
3866 armnn::LstmDescriptor descriptor;
3867 descriptor.m_ActivationFunc = 4;
3868 descriptor.m_ClippingThresProj = 0.0f;
3869 descriptor.m_ClippingThresCell = 0.0f;
3870 descriptor.m_CifgEnabled = false;
3871 descriptor.m_ProjectionEnabled = true;
3872 descriptor.m_PeepholeEnabled = true;
3873
3874 const uint32_t batchSize = 2;
3875 const uint32_t inputSize = 5;
3876 const uint32_t numUnits = 20;
3877 const uint32_t outputSize = 16;
3878
3879 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3880 std::vector<float> inputToInputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3881 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3882
3883 std::vector<float> inputToForgetWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3884 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3885
3886 std::vector<float> inputToCellWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3887 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3888
3889 std::vector<float> inputToOutputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3890 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3891
3892 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3893 std::vector<float> inputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3894 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3895
3896 std::vector<float> forgetGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3897 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3898
3899 std::vector<float> cellBiasData(tensorInfo20.GetNumElements(), 0.0f);
3900 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3901
3902 std::vector<float> outputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3903 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3904
3905 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3906 std::vector<float> recurrentToInputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3907 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3908
3909 std::vector<float> recurrentToForgetWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3910 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3911
3912 std::vector<float> recurrentToCellWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3913 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3914
3915 std::vector<float> recurrentToOutputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3916 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3917
3918 std::vector<float> cellToInputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
3919 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3920
3921 std::vector<float> cellToForgetWeightsData(tensorInfo20.GetNumElements(), 0.0f);
3922 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3923
3924 std::vector<float> cellToOutputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
3925 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3926
3927 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3928 std::vector<float> projectionWeightsData(tensorInfo16x20.GetNumElements(), 0.0f);
3929 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3930
3931 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3932 std::vector<float> projectionBiasData(outputSize, 0.0f);
3933 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3934
3935 armnn::LstmInputParams params;
3936 params.m_InputToForgetWeights = &inputToForgetWeights;
3937 params.m_InputToCellWeights = &inputToCellWeights;
3938 params.m_InputToOutputWeights = &inputToOutputWeights;
3939 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3940 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3941 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3942 params.m_ForgetGateBias = &forgetGateBias;
3943 params.m_CellBias = &cellBias;
3944 params.m_OutputGateBias = &outputGateBias;
3945
3946 // additional params because: descriptor.m_CifgEnabled = false
3947 params.m_InputToInputWeights = &inputToInputWeights;
3948 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3949 params.m_CellToInputWeights = &cellToInputWeights;
3950 params.m_InputGateBias = &inputGateBias;
3951
3952 // additional params because: descriptor.m_ProjectionEnabled = true
3953 params.m_ProjectionWeights = &projectionWeights;
3954 params.m_ProjectionBias = &projectionBias;
3955
3956 // additional params because: descriptor.m_PeepholeEnabled = true
3957 params.m_CellToForgetWeights = &cellToForgetWeights;
3958 params.m_CellToOutputWeights = &cellToOutputWeights;
3959
3960 const std::string layerName("lstm");
3961 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3962 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3963 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3964 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3965
3966 // lets verify that the deserialized model without the new layer normalization parameters still works
3967 VerifyLstmLayer checker(
3968 layerName,
3969 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3970 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3971 descriptor,
3972 params);
3973 deserializedNetwork->Accept(checker);
3974}
3975
Jan Eilers5b01a892019-07-23 09:47:43 +01003976class VerifyQuantizedLstmLayer : public LayerVerifierBase
3977{
3978
3979public:
3980 VerifyQuantizedLstmLayer(const std::string& layerName,
3981 const std::vector<armnn::TensorInfo>& inputInfos,
3982 const std::vector<armnn::TensorInfo>& outputInfos,
3983 const armnn::QuantizedLstmInputParams& inputParams) :
3984 LayerVerifierBase(layerName, inputInfos, outputInfos), m_InputParams(inputParams)
3985 {
3986 }
3987
3988 void VisitQuantizedLstmLayer(const armnn::IConnectableLayer* layer,
3989 const armnn::QuantizedLstmInputParams& params,
3990 const char* name)
3991 {
3992 VerifyNameAndConnections(layer, name);
3993 VerifyInputParameters(params);
3994 }
3995
3996protected:
3997 void VerifyInputParameters(const armnn::QuantizedLstmInputParams& params)
3998 {
3999 VerifyConstTensors("m_InputToInputWeights",
4000 m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
4001 VerifyConstTensors("m_InputToForgetWeights",
4002 m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
4003 VerifyConstTensors("m_InputToCellWeights",
4004 m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
4005 VerifyConstTensors("m_InputToOutputWeights",
4006 m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
4007 VerifyConstTensors("m_RecurrentToInputWeights",
4008 m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
4009 VerifyConstTensors("m_RecurrentToForgetWeights",
4010 m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
4011 VerifyConstTensors("m_RecurrentToCellWeights",
4012 m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
4013 VerifyConstTensors("m_RecurrentToOutputWeights",
4014 m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
4015 VerifyConstTensors("m_InputGateBias",
4016 m_InputParams.m_InputGateBias, params.m_InputGateBias);
4017 VerifyConstTensors("m_ForgetGateBias",
4018 m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
4019 VerifyConstTensors("m_CellBias",
4020 m_InputParams.m_CellBias, params.m_CellBias);
4021 VerifyConstTensors("m_OutputGateBias",
4022 m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
4023 }
4024
4025private:
4026 armnn::QuantizedLstmInputParams m_InputParams;
4027};
4028
4029BOOST_AUTO_TEST_CASE(SerializeDeserializeQuantizedLstm)
4030{
4031 const uint32_t batchSize = 1;
4032 const uint32_t inputSize = 2;
4033 const uint32_t numUnits = 4;
4034 const uint32_t outputSize = numUnits;
4035
4036 std::vector<uint8_t> inputToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4037 std::vector<unsigned int> inputToInputWeightsDimensions = {1, 1, 3, 3};
4038 armnn::ConstTensor inputToInputWeights(armnn::TensorInfo(
4039 4, inputToInputWeightsDimensions.data(),
4040 armnn::DataType::QuantisedAsymm8), inputToInputWeightsData);
4041
4042 std::vector<uint8_t> inputToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4043 std::vector<unsigned int> inputToForgetWeightsDimensions = {1, 1, 3, 3};
4044 armnn::ConstTensor inputToForgetWeights(armnn::TensorInfo(
4045 4, inputToForgetWeightsDimensions.data(),
4046 armnn::DataType::QuantisedAsymm8), inputToForgetWeightsData);
4047
4048 std::vector<uint8_t> inputToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4049 std::vector<unsigned int> inputToCellWeightsDimensions = {1, 1, 3, 3};
4050 armnn::ConstTensor inputToCellWeights(armnn::TensorInfo(
4051 4, inputToCellWeightsDimensions.data(),
4052 armnn::DataType::QuantisedAsymm8), inputToCellWeightsData);
4053
4054 std::vector<uint8_t> inputToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4055 std::vector<unsigned int> inputToOutputWeightsDimensions = {1, 1, 3, 3};
4056 armnn::ConstTensor inputToOutputWeights(armnn::TensorInfo(
4057 4, inputToOutputWeightsDimensions.data(),
4058 armnn::DataType::QuantisedAsymm8), inputToOutputWeightsData);
4059
4060 std::vector<uint8_t> recurrentToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4061 std::vector<unsigned int> recurrentToInputWeightsDimensions = {1, 1, 3, 3};
4062 armnn::ConstTensor recurrentToInputWeights(armnn::TensorInfo(
4063 4, recurrentToInputWeightsDimensions.data(),
4064 armnn::DataType::QuantisedAsymm8), recurrentToInputWeightsData);
4065
4066 std::vector<uint8_t> recurrentToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4067 std::vector<unsigned int> recurrentToForgetWeightsDimensions = {1, 1, 3, 3};
4068 armnn::ConstTensor recurrentToForgetWeights(armnn::TensorInfo(
4069 4, recurrentToForgetWeightsDimensions.data(),
4070 armnn::DataType::QuantisedAsymm8), recurrentToForgetWeightsData);
4071
4072 std::vector<uint8_t> recurrentToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4073 std::vector<unsigned int> recurrentToCellWeightsDimensions = {1, 1, 3, 3};
4074 armnn::ConstTensor recurrentToCellWeights(armnn::TensorInfo(
4075 4, recurrentToCellWeightsDimensions.data(),
4076 armnn::DataType::QuantisedAsymm8), recurrentToCellWeightsData);
4077
4078 std::vector<uint8_t> recurrentToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4079 std::vector<unsigned int> recurrentToOutputWeightsDimensions = {1, 1, 3, 3};
4080 armnn::ConstTensor recurrentToOutputWeights(armnn::TensorInfo(
4081 4, recurrentToOutputWeightsDimensions.data(),
4082 armnn::DataType::QuantisedAsymm8), recurrentToOutputWeightsData);
4083
4084
4085 std::vector<int32_t> inputGateBiasData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4086 std::vector<unsigned int> inputGateBiasDimensions = {1, 1, 3, 3};
4087 armnn::ConstTensor inputGateBias(armnn::TensorInfo(
4088 4, inputGateBiasDimensions.data(),
4089 armnn::DataType::Signed32), inputGateBiasData);
4090
4091 std::vector<int32_t> forgetGateBiasData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4092 std::vector<unsigned int> forgetGateBiasDimensions = {1, 1, 3, 3};
4093 armnn::ConstTensor forgetGateBias(armnn::TensorInfo(
4094 4, forgetGateBiasDimensions.data(),
4095 armnn::DataType::Signed32), forgetGateBiasData);
4096
4097 std::vector<int32_t> cellBiasData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4098 std::vector<unsigned int> cellBiasDimensions = {1, 1, 3, 3};
4099 armnn::ConstTensor cellBias(armnn::TensorInfo(
4100 4, cellBiasDimensions.data(),
4101 armnn::DataType::Signed32), cellBiasData);
4102
4103 std::vector<int32_t> outputGateBiasData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
4104 std::vector<unsigned int> outputGateBiasDimensions = {1, 1, 3, 3};
4105 armnn::ConstTensor outputGateBias(armnn::TensorInfo(
4106 4, outputGateBiasDimensions.data(),
4107 armnn::DataType::Signed32), outputGateBiasData);
4108
4109 armnn::QuantizedLstmInputParams params;
4110 params.m_InputToInputWeights = &inputToInputWeights;
4111 params.m_InputToForgetWeights = &inputToForgetWeights;
4112 params.m_InputToCellWeights = &inputToCellWeights;
4113 params.m_InputToOutputWeights = &inputToOutputWeights;
4114 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
4115 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4116 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4117 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4118 params.m_InputGateBias = &inputGateBias;
4119 params.m_ForgetGateBias = &forgetGateBias;
4120 params.m_CellBias = &cellBias;
4121 params.m_OutputGateBias = &outputGateBias;
4122
4123 armnn::INetworkPtr network = armnn::INetwork::Create();
4124 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
4125 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
4126 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
4127 const std::string layerName("QuantizedLstm");
4128 armnn::IConnectableLayer* const quantizedLstmLayer = network->AddQuantizedLstmLayer(params, layerName.c_str());
4129 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(0);
4130 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(1);
4131
4132 // connect up
4133 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::QuantisedAsymm8);
4134 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Signed32);
4135 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::QuantisedAsymm8);
4136
4137 inputLayer->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(0));
4138 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
4139
4140 cellStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(1));
4141 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
4142
4143 outputStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(2));
4144 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
4145
4146 quantizedLstmLayer->GetOutputSlot(0).Connect(cellStateOut->GetInputSlot(0));
4147 quantizedLstmLayer->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
4148
4149 quantizedLstmLayer->GetOutputSlot(1).Connect(outputLayer->GetInputSlot(0));
4150 quantizedLstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
4151
4152 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
4153 BOOST_CHECK(deserializedNetwork);
4154
4155 VerifyQuantizedLstmLayer checker(
4156 layerName,
4157 {inputTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
4158 {cellStateTensorInfo, outputStateTensorInfo},
4159 params);
4160
4161 deserializedNetwork->Accept(checker);
4162}
4163
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00004164BOOST_AUTO_TEST_SUITE_END()