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