blob: 2b131097257b6f795aa9ab092cfb09e98b4eb48a [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
Matthew Benthamff130e22020-01-17 11:47:42 +00008#include <armnn/Descriptors.hpp>
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00009#include <armnn/INetwork.hpp>
Matthew Benthamff130e22020-01-17 11:47:42 +000010#include <armnn/TypesUtils.hpp>
11#include <armnn/LstmParams.hpp>
12#include <armnn/QuantizedLstmParams.hpp>
Derek Lamberti0028d1b2019-02-20 13:57:42 +000013#include <armnnDeserializer/IDeserializer.hpp>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000014
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +000015#include <random>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000016#include <vector>
17
Mike Kelly8c1701a2019-02-11 17:01:27 +000018#include <boost/test/unit_test.hpp>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000019
Derek Lamberti0028d1b2019-02-20 13:57:42 +000020using armnnDeserializer::IDeserializer;
Mike Kelly8c1701a2019-02-11 17:01:27 +000021
Saoirse Stewart3166c3e2019-02-18 15:24:53 +000022namespace
23{
24
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +010025#define DECLARE_LAYER_VERIFIER_CLASS(name) \
26class name##LayerVerifier : public LayerVerifierBase \
27{ \
28public: \
29 name##LayerVerifier(const std::string& layerName, \
30 const std::vector<armnn::TensorInfo>& inputInfos, \
31 const std::vector<armnn::TensorInfo>& outputInfos) \
32 : LayerVerifierBase(layerName, inputInfos, outputInfos) {} \
33\
34 void Visit##name##Layer(const armnn::IConnectableLayer* layer, const char* name) override \
35 { \
36 VerifyNameAndConnections(layer, name); \
37 } \
38};
39
40#define DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(name) \
41class name##LayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::name##Descriptor> \
42{ \
43public: \
44 name##LayerVerifier(const std::string& layerName, \
45 const std::vector<armnn::TensorInfo>& inputInfos, \
46 const std::vector<armnn::TensorInfo>& outputInfos, \
47 const armnn::name##Descriptor& descriptor) \
48 : LayerVerifierBaseWithDescriptor<armnn::name##Descriptor>( \
49 layerName, inputInfos, outputInfos, descriptor) {} \
50\
51 void Visit##name##Layer(const armnn::IConnectableLayer* layer, \
52 const armnn::name##Descriptor& descriptor, \
53 const char* name) override \
54 { \
55 VerifyNameAndConnections(layer, name); \
56 VerifyDescriptor(descriptor); \
57 } \
58};
59
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000060struct DefaultLayerVerifierPolicy
61{
Derek Lamberti859f9ce2019-12-10 22:05:21 +000062 static void Apply(const std::string)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000063 {
64 BOOST_TEST_MESSAGE("Unexpected layer found in network");
65 BOOST_TEST(false);
66 }
67};
68
69class LayerVerifierBase : public armnn::LayerVisitorBase<DefaultLayerVerifierPolicy>
70{
71public:
72 LayerVerifierBase(const std::string& layerName,
73 const std::vector<armnn::TensorInfo>& inputInfos,
74 const std::vector<armnn::TensorInfo>& outputInfos)
75 : m_LayerName(layerName)
76 , m_InputTensorInfos(inputInfos)
77 , m_OutputTensorInfos(outputInfos) {}
78
79 void VisitInputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId, const char*) override {}
80
Derek Lamberti859f9ce2019-12-10 22:05:21 +000081 void VisitOutputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId, const char*) override {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000082
83protected:
84 void VerifyNameAndConnections(const armnn::IConnectableLayer* layer, const char* name)
85 {
86 BOOST_TEST(name == m_LayerName.c_str());
87
88 BOOST_TEST(layer->GetNumInputSlots() == m_InputTensorInfos.size());
89 BOOST_TEST(layer->GetNumOutputSlots() == m_OutputTensorInfos.size());
90
91 for (unsigned int i = 0; i < m_InputTensorInfos.size(); i++)
92 {
93 const armnn::IOutputSlot* connectedOutput = layer->GetInputSlot(i).GetConnection();
94 BOOST_CHECK(connectedOutput);
95
96 const armnn::TensorInfo& connectedInfo = connectedOutput->GetTensorInfo();
97 BOOST_TEST(connectedInfo.GetShape() == m_InputTensorInfos[i].GetShape());
98 BOOST_TEST(
99 GetDataTypeName(connectedInfo.GetDataType()) == GetDataTypeName(m_InputTensorInfos[i].GetDataType()));
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000100
101 BOOST_TEST(connectedInfo.GetQuantizationScale() == m_InputTensorInfos[i].GetQuantizationScale());
102 BOOST_TEST(connectedInfo.GetQuantizationOffset() == m_InputTensorInfos[i].GetQuantizationOffset());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000103 }
104
105 for (unsigned int i = 0; i < m_OutputTensorInfos.size(); i++)
106 {
107 const armnn::TensorInfo& outputInfo = layer->GetOutputSlot(i).GetTensorInfo();
108 BOOST_TEST(outputInfo.GetShape() == m_OutputTensorInfos[i].GetShape());
109 BOOST_TEST(
110 GetDataTypeName(outputInfo.GetDataType()) == GetDataTypeName(m_OutputTensorInfos[i].GetDataType()));
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000111
112 BOOST_TEST(outputInfo.GetQuantizationScale() == m_OutputTensorInfos[i].GetQuantizationScale());
113 BOOST_TEST(outputInfo.GetQuantizationOffset() == m_OutputTensorInfos[i].GetQuantizationOffset());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000114 }
115 }
116
Jan Eilers5b01a892019-07-23 09:47:43 +0100117 void VerifyConstTensors(const std::string& tensorName,
118 const armnn::ConstTensor* expectedPtr,
119 const armnn::ConstTensor* actualPtr)
120 {
121 if (expectedPtr == nullptr)
122 {
123 BOOST_CHECK_MESSAGE(actualPtr == nullptr, tensorName + " should not exist");
124 }
125 else
126 {
127 BOOST_CHECK_MESSAGE(actualPtr != nullptr, tensorName + " should have been set");
128 if (actualPtr != nullptr)
129 {
130 const armnn::TensorInfo& expectedInfo = expectedPtr->GetInfo();
131 const armnn::TensorInfo& actualInfo = actualPtr->GetInfo();
132
133 BOOST_CHECK_MESSAGE(expectedInfo.GetShape() == actualInfo.GetShape(),
134 tensorName + " shapes don't match");
135 BOOST_CHECK_MESSAGE(
136 GetDataTypeName(expectedInfo.GetDataType()) == GetDataTypeName(actualInfo.GetDataType()),
137 tensorName + " data types don't match");
138
139 BOOST_CHECK_MESSAGE(expectedPtr->GetNumBytes() == actualPtr->GetNumBytes(),
140 tensorName + " (GetNumBytes) data sizes do not match");
141 if (expectedPtr->GetNumBytes() == actualPtr->GetNumBytes())
142 {
143 //check the data is identical
144 const char* expectedData = static_cast<const char*>(expectedPtr->GetMemoryArea());
145 const char* actualData = static_cast<const char*>(actualPtr->GetMemoryArea());
146 bool same = true;
147 for (unsigned int i = 0; i < expectedPtr->GetNumBytes(); ++i)
148 {
149 same = expectedData[i] == actualData[i];
150 if (!same)
151 {
152 break;
153 }
154 }
155 BOOST_CHECK_MESSAGE(same, tensorName + " data does not match");
156 }
157 }
158 }
159 }
160
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000161private:
162 std::string m_LayerName;
163 std::vector<armnn::TensorInfo> m_InputTensorInfos;
164 std::vector<armnn::TensorInfo> m_OutputTensorInfos;
165};
166
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100167template<typename Descriptor>
168class LayerVerifierBaseWithDescriptor : public LayerVerifierBase
169{
170public:
171 LayerVerifierBaseWithDescriptor(const std::string& layerName,
172 const std::vector<armnn::TensorInfo>& inputInfos,
173 const std::vector<armnn::TensorInfo>& outputInfos,
174 const Descriptor& descriptor)
175 : LayerVerifierBase(layerName, inputInfos, outputInfos)
176 , m_Descriptor(descriptor) {}
177
178protected:
179 void VerifyDescriptor(const Descriptor& descriptor)
180 {
181 BOOST_CHECK(descriptor == m_Descriptor);
182 }
183
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100184 Descriptor m_Descriptor;
185};
186
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000187template<typename T>
188void CompareConstTensorData(const void* data1, const void* data2, unsigned int numElements)
189{
190 T typedData1 = static_cast<T>(data1);
191 T typedData2 = static_cast<T>(data2);
192 BOOST_CHECK(typedData1);
193 BOOST_CHECK(typedData2);
194
195 for (unsigned int i = 0; i < numElements; i++)
196 {
197 BOOST_TEST(typedData1[i] == typedData2[i]);
198 }
199}
200
201void CompareConstTensor(const armnn::ConstTensor& tensor1, const armnn::ConstTensor& tensor2)
202{
203 BOOST_TEST(tensor1.GetShape() == tensor2.GetShape());
204 BOOST_TEST(GetDataTypeName(tensor1.GetDataType()) == GetDataTypeName(tensor2.GetDataType()));
205
206 switch (tensor1.GetDataType())
207 {
208 case armnn::DataType::Float32:
209 CompareConstTensorData<const float*>(
210 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
211 break;
Derek Lambertif90c56d2020-01-10 17:14:08 +0000212 case armnn::DataType::QAsymmU8:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000213 case armnn::DataType::Boolean:
214 CompareConstTensorData<const uint8_t*>(
215 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
216 break;
217 case armnn::DataType::Signed32:
218 CompareConstTensorData<const int32_t*>(
219 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
220 break;
221 default:
222 // Note that Float16 is not yet implemented
223 BOOST_TEST_MESSAGE("Unexpected datatype");
224 BOOST_TEST(false);
225 }
226}
227
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000228armnn::INetworkPtr DeserializeNetwork(const std::string& serializerString)
229{
230 std::vector<std::uint8_t> const serializerVector{serializerString.begin(), serializerString.end()};
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000231 return IDeserializer::Create()->CreateNetworkFromBinary(serializerVector);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000232}
233
234std::string SerializeNetwork(const armnn::INetwork& network)
235{
236 armnnSerializer::Serializer serializer;
237 serializer.Serialize(network);
238
239 std::stringstream stream;
240 serializer.SaveSerializedToStream(stream);
241
242 std::string serializerString{stream.str()};
243 return serializerString;
244}
245
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000246template<typename DataType>
247static std::vector<DataType> GenerateRandomData(size_t size)
248{
249 constexpr bool isIntegerType = std::is_integral<DataType>::value;
250 using Distribution =
251 typename std::conditional<isIntegerType,
252 std::uniform_int_distribution<DataType>,
253 std::uniform_real_distribution<DataType>>::type;
254
255 static constexpr DataType lowerLimit = std::numeric_limits<DataType>::min();
256 static constexpr DataType upperLimit = std::numeric_limits<DataType>::max();
257
258 static Distribution distribution(lowerLimit, upperLimit);
259 static std::default_random_engine generator;
260
261 std::vector<DataType> randomData(size);
262 std::generate(randomData.begin(), randomData.end(), []() { return distribution(generator); });
263
264 return randomData;
265}
266
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000267} // anonymous namespace
268
269BOOST_AUTO_TEST_SUITE(SerializerTests)
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000270
FinnWilliamsArm4ffcc8f2019-09-05 14:34:20 +0100271BOOST_AUTO_TEST_CASE(SerializeAbs)
272{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100273 DECLARE_LAYER_VERIFIER_CLASS(Abs)
FinnWilliamsArm4ffcc8f2019-09-05 14:34:20 +0100274
275 const std::string layerName("abs");
276 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
277
278 armnn::INetworkPtr network = armnn::INetwork::Create();
279 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
280
281 armnn::IConnectableLayer* const absLayer = network->AddAbsLayer(layerName.c_str());
282 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
283
284 inputLayer->GetOutputSlot(0).Connect(absLayer->GetInputSlot(0));
285 absLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
286
287 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
288 absLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
289
290 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
291 BOOST_CHECK(deserializedNetwork);
292
293 AbsLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
294 deserializedNetwork->Accept(verifier);
295}
296
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000297BOOST_AUTO_TEST_CASE(SerializeAddition)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000298{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100299 DECLARE_LAYER_VERIFIER_CLASS(Addition)
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000300
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000301 const std::string layerName("addition");
302 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
303
Mike Kelly8c1701a2019-02-11 17:01:27 +0000304 armnn::INetworkPtr network = armnn::INetwork::Create();
305 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
306 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000307 armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer(layerName.c_str());
308 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000309
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000310 inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
311 inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000312 additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Mike Kelly8c1701a2019-02-11 17:01:27 +0000313
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000314 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
315 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
316 additionLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
Jim Flynn3091b062019-02-15 14:45:04 +0000317
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000318 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000319 BOOST_CHECK(deserializedNetwork);
320
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000321 AdditionLayerVerifier verifier(layerName, {tensorInfo, tensorInfo}, {tensorInfo});
322 deserializedNetwork->Accept(verifier);
323}
Jim Flynnac25a1b2019-02-28 10:40:49 +0000324
Narumol Prangnawarat0cfcf232019-09-09 17:16:24 +0100325BOOST_AUTO_TEST_CASE(SerializeArgMinMax)
326{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100327 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(ArgMinMax)
Narumol Prangnawarat0cfcf232019-09-09 17:16:24 +0100328
329 const std::string layerName("argminmax");
330 const armnn::TensorInfo inputInfo({1, 2, 3}, armnn::DataType::Float32);
331 const armnn::TensorInfo outputInfo({1, 3}, armnn::DataType::Signed32);
332
333 armnn::ArgMinMaxDescriptor descriptor;
334 descriptor.m_Function = armnn::ArgMinMaxFunction::Max;
335 descriptor.m_Axis = 1;
336
337 armnn::INetworkPtr network = armnn::INetwork::Create();
338 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
339 armnn::IConnectableLayer* const argMinMaxLayer = network->AddArgMinMaxLayer(descriptor, layerName.c_str());
340 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
341
342 inputLayer->GetOutputSlot(0).Connect(argMinMaxLayer->GetInputSlot(0));
343 argMinMaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
344
345 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
346 argMinMaxLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
347
348 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
349 BOOST_CHECK(deserializedNetwork);
350
351 ArgMinMaxLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
352 deserializedNetwork->Accept(verifier);
353}
354
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000355BOOST_AUTO_TEST_CASE(SerializeBatchNormalization)
356{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100357 using Descriptor = armnn::BatchNormalizationDescriptor;
358 class BatchNormalizationLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000359 {
360 public:
361 BatchNormalizationLayerVerifier(const std::string& layerName,
362 const std::vector<armnn::TensorInfo>& inputInfos,
363 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100364 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000365 const armnn::ConstTensor& mean,
366 const armnn::ConstTensor& variance,
367 const armnn::ConstTensor& beta,
368 const armnn::ConstTensor& gamma)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100369 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
370 , m_Mean(mean)
371 , m_Variance(variance)
372 , m_Beta(beta)
373 , m_Gamma(gamma) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000374
375 void VisitBatchNormalizationLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100376 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000377 const armnn::ConstTensor& mean,
378 const armnn::ConstTensor& variance,
379 const armnn::ConstTensor& beta,
380 const armnn::ConstTensor& gamma,
381 const char* name) override
382 {
383 VerifyNameAndConnections(layer, name);
384 VerifyDescriptor(descriptor);
385
386 CompareConstTensor(mean, m_Mean);
387 CompareConstTensor(variance, m_Variance);
388 CompareConstTensor(beta, m_Beta);
389 CompareConstTensor(gamma, m_Gamma);
390 }
391
392 private:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000393 armnn::ConstTensor m_Mean;
394 armnn::ConstTensor m_Variance;
395 armnn::ConstTensor m_Beta;
396 armnn::ConstTensor m_Gamma;
397 };
398
399 const std::string layerName("batchNormalization");
400 const armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32);
401 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
402
403 const armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32);
404 const armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32);
405 const armnn::TensorInfo betaInfo({1}, armnn::DataType::Float32);
406 const armnn::TensorInfo gammaInfo({1}, armnn::DataType::Float32);
407
408 armnn::BatchNormalizationDescriptor descriptor;
409 descriptor.m_Eps = 0.0010000000475f;
410 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
411
412 std::vector<float> meanData({5.0});
413 std::vector<float> varianceData({2.0});
414 std::vector<float> betaData({1.0});
415 std::vector<float> gammaData({0.0});
416
417 armnn::ConstTensor mean(meanInfo, meanData);
418 armnn::ConstTensor variance(varianceInfo, varianceData);
419 armnn::ConstTensor beta(betaInfo, betaData);
420 armnn::ConstTensor gamma(gammaInfo, gammaData);
421
422 armnn::INetworkPtr network = armnn::INetwork::Create();
423 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
424 armnn::IConnectableLayer* const batchNormalizationLayer =
425 network->AddBatchNormalizationLayer(descriptor, mean, variance, beta, gamma, layerName.c_str());
426 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
427
428 inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0));
429 batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
430
431 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
432 batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
433
434 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
435 BOOST_CHECK(deserializedNetwork);
436
437 BatchNormalizationLayerVerifier verifier(
438 layerName, {inputInfo}, {outputInfo}, descriptor, mean, variance, beta, gamma);
439 deserializedNetwork->Accept(verifier);
440}
441
442BOOST_AUTO_TEST_CASE(SerializeBatchToSpaceNd)
443{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100444 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(BatchToSpaceNd)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000445
446 const std::string layerName("spaceToBatchNd");
447 const armnn::TensorInfo inputInfo({4, 1, 2, 2}, armnn::DataType::Float32);
448 const armnn::TensorInfo outputInfo({1, 1, 4, 4}, armnn::DataType::Float32);
449
450 armnn::BatchToSpaceNdDescriptor desc;
451 desc.m_DataLayout = armnn::DataLayout::NCHW;
452 desc.m_BlockShape = {2, 2};
453 desc.m_Crops = {{0, 0}, {0, 0}};
454
455 armnn::INetworkPtr network = armnn::INetwork::Create();
456 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
457 armnn::IConnectableLayer* const batchToSpaceNdLayer = network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
458 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
459
460 inputLayer->GetOutputSlot(0).Connect(batchToSpaceNdLayer->GetInputSlot(0));
461 batchToSpaceNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
462
463 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
464 batchToSpaceNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
465
466 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
467 BOOST_CHECK(deserializedNetwork);
468
469 BatchToSpaceNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
470 deserializedNetwork->Accept(verifier);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000471}
472
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100473BOOST_AUTO_TEST_CASE(SerializeComparison)
474{
475 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Comparison)
476
477 const std::string layerName("comparison");
478
479 const armnn::TensorShape shape{2, 1, 2, 4};
480
481 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
482 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
483
484 armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::NotEqual);
485
486 armnn::INetworkPtr network = armnn::INetwork::Create();
487 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
488 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
489 armnn::IConnectableLayer* const comparisonLayer = network->AddComparisonLayer(descriptor, layerName.c_str());
490 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
491
492 inputLayer0->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(0));
493 inputLayer1->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(1));
494 comparisonLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
495
496 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
497 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
498 comparisonLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
499
500 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
501 BOOST_CHECK(deserializedNetwork);
502
503 ComparisonLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo }, descriptor);
504 deserializedNetwork->Accept(verifier);
505}
506
Conor Kennedy76277882019-02-26 08:29:54 +0000507BOOST_AUTO_TEST_CASE(SerializeConstant)
508{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000509 class ConstantLayerVerifier : public LayerVerifierBase
Conor Kennedy76277882019-02-26 08:29:54 +0000510 {
511 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000512 ConstantLayerVerifier(const std::string& layerName,
513 const std::vector<armnn::TensorInfo>& inputInfos,
514 const std::vector<armnn::TensorInfo>& outputInfos,
515 const armnn::ConstTensor& layerInput)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100516 : LayerVerifierBase(layerName, inputInfos, outputInfos)
517 , m_LayerInput(layerInput) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000518
519 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
520 const armnn::ConstTensor& input,
521 const char* name) override
Conor Kennedy76277882019-02-26 08:29:54 +0000522 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000523 VerifyNameAndConnections(layer, name);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000524 CompareConstTensor(input, m_LayerInput);
Conor Kennedy76277882019-02-26 08:29:54 +0000525 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000526
Derek Lamberti859f9ce2019-12-10 22:05:21 +0000527 void VisitAdditionLayer(const armnn::IConnectableLayer*, const char*) override {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000528
529 private:
530 armnn::ConstTensor m_LayerInput;
Conor Kennedy76277882019-02-26 08:29:54 +0000531 };
532
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000533 const std::string layerName("constant");
534 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
Conor Kennedy76277882019-02-26 08:29:54 +0000535
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000536 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
537 armnn::ConstTensor constTensor(info, constantData);
Conor Kennedy76277882019-02-26 08:29:54 +0000538
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000539 armnn::INetworkPtr network(armnn::INetwork::Create());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000540 armnn::IConnectableLayer* input = network->AddInputLayer(0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000541 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000542 armnn::IConnectableLayer* add = network->AddAdditionLayer();
543 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
Conor Kennedy76277882019-02-26 08:29:54 +0000544
545 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
546 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
547 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
548
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000549 input->GetOutputSlot(0).SetTensorInfo(info);
550 constant->GetOutputSlot(0).SetTensorInfo(info);
551 add->GetOutputSlot(0).SetTensorInfo(info);
Conor Kennedy76277882019-02-26 08:29:54 +0000552
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000553 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Conor Kennedy76277882019-02-26 08:29:54 +0000554 BOOST_CHECK(deserializedNetwork);
555
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000556 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
557 deserializedNetwork->Accept(verifier);
Conor Kennedy76277882019-02-26 08:29:54 +0000558}
559
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000560BOOST_AUTO_TEST_CASE(SerializeConvolution2d)
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000561{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100562 using Descriptor = armnn::Convolution2dDescriptor;
563 class Convolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000564 {
565 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000566 Convolution2dLayerVerifier(const std::string& layerName,
567 const std::vector<armnn::TensorInfo>& inputInfos,
568 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100569 const Descriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100570 const armnn::ConstTensor& weights,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100571 const armnn::Optional<armnn::ConstTensor>& biases)
572 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
573 , m_Weights(weights)
574 , m_Biases(biases) {}
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000575
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000576 void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100577 const Descriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100578 const armnn::ConstTensor& weights,
579 const armnn::Optional<armnn::ConstTensor>& biases,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000580 const char* name) override
581 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000582 VerifyNameAndConnections(layer, name);
583 VerifyDescriptor(descriptor);
584
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100585 // check weights
586 CompareConstTensor(weights, m_Weights);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000587
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100588 // check biases
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100589 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100590 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
591
592 if (biases.has_value() && m_Biases.has_value())
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000593 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100594 CompareConstTensor(biases.value(), m_Biases.value());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000595 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000596 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000597
598 private:
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100599 armnn::ConstTensor m_Weights;
600 armnn::Optional<armnn::ConstTensor> m_Biases;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000601 };
602
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000603 const std::string layerName("convolution2d");
604 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
605 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000606
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000607 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
608 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000609
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000610 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
611 armnn::ConstTensor weights(weightsInfo, weightsData);
612
613 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
614 armnn::ConstTensor biases(biasesInfo, biasesData);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000615
616 armnn::Convolution2dDescriptor descriptor;
617 descriptor.m_PadLeft = 1;
618 descriptor.m_PadRight = 1;
619 descriptor.m_PadTop = 1;
620 descriptor.m_PadBottom = 1;
621 descriptor.m_StrideX = 2;
622 descriptor.m_StrideY = 2;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100623 descriptor.m_DilationX = 2;
624 descriptor.m_DilationY = 2;
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000625 descriptor.m_BiasEnabled = true;
626 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
627
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000628 armnn::INetworkPtr network = armnn::INetwork::Create();
629 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000630 armnn::IConnectableLayer* const convLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100631 network->AddConvolution2dLayer(descriptor,
632 weights,
633 armnn::Optional<armnn::ConstTensor>(biases),
634 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000635 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000636
637 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000638 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000639
640 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000641 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
642
643 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
644 BOOST_CHECK(deserializedNetwork);
645
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000646 Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
647 deserializedNetwork->Accept(verifier);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000648}
649
Aron Virginas-Tarda9d2d32019-09-20 10:42:02 +0100650BOOST_AUTO_TEST_CASE(SerializeDepthToSpace)
651{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100652 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(DepthToSpace)
Aron Virginas-Tarda9d2d32019-09-20 10:42:02 +0100653
654 const std::string layerName("depthToSpace");
655
656 const armnn::TensorInfo inputInfo ({ 1, 8, 4, 12 }, armnn::DataType::Float32);
657 const armnn::TensorInfo outputInfo({ 1, 16, 8, 3 }, armnn::DataType::Float32);
658
659 armnn::DepthToSpaceDescriptor desc;
660 desc.m_BlockSize = 2;
661 desc.m_DataLayout = armnn::DataLayout::NHWC;
662
663 armnn::INetworkPtr network = armnn::INetwork::Create();
664 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
665 armnn::IConnectableLayer* const depthToSpaceLayer = network->AddDepthToSpaceLayer(desc, layerName.c_str());
666 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
667
668 inputLayer->GetOutputSlot(0).Connect(depthToSpaceLayer->GetInputSlot(0));
669 depthToSpaceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
670
671 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
672 depthToSpaceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
673
674 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
675 BOOST_CHECK(deserializedNetwork);
676
677 DepthToSpaceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
678 deserializedNetwork->Accept(verifier);
679}
680
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000681BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d)
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000682{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100683 using Descriptor = armnn::DepthwiseConvolution2dDescriptor;
684 class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000685 {
686 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000687 DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
688 const std::vector<armnn::TensorInfo>& inputInfos,
689 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100690 const Descriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100691 const armnn::ConstTensor& weights,
692 const armnn::Optional<armnn::ConstTensor>& biases) :
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100693 LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor),
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100694 m_Weights(weights),
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100695 m_Biases(biases) {}
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000696
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000697 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100698 const Descriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100699 const armnn::ConstTensor& weights,
700 const armnn::Optional<armnn::ConstTensor>& biases,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000701 const char* name) override
702 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000703 VerifyNameAndConnections(layer, name);
704 VerifyDescriptor(descriptor);
705
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100706 // check weights
707 CompareConstTensor(weights, m_Weights);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000708
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100709 // check biases
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100710 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100711 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
712
713 if (biases.has_value() && m_Biases.has_value())
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000714 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100715 CompareConstTensor(biases.value(), m_Biases.value());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000716 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000717 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000718
719 private:
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100720 armnn::ConstTensor m_Weights;
721 armnn::Optional<armnn::ConstTensor> m_Biases;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000722 };
723
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000724 const std::string layerName("depwiseConvolution2d");
725 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
726 const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000727
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000728 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
729 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000730
731 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
732 armnn::ConstTensor weights(weightsInfo, weightsData);
733
734 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
735 armnn::ConstTensor biases(biasesInfo, biasesData);
736
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000737 armnn::DepthwiseConvolution2dDescriptor descriptor;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100738 descriptor.m_PadLeft = 1;
739 descriptor.m_PadRight = 1;
740 descriptor.m_PadTop = 1;
741 descriptor.m_PadBottom = 1;
742 descriptor.m_StrideX = 2;
743 descriptor.m_StrideY = 2;
744 descriptor.m_DilationX = 2;
745 descriptor.m_DilationY = 2;
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000746 descriptor.m_BiasEnabled = true;
747 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
748
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000749 armnn::INetworkPtr network = armnn::INetwork::Create();
750 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
751 armnn::IConnectableLayer* const depthwiseConvLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100752 network->AddDepthwiseConvolution2dLayer(descriptor,
753 weights,
754 armnn::Optional<armnn::ConstTensor>(biases),
755 layerName.c_str());
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000756 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
757
758 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000759 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000760
761 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000762 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
763
764 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
765 BOOST_CHECK(deserializedNetwork);
766
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000767 DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
768 deserializedNetwork->Accept(verifier);
Jim Flynn18ce3382019-03-08 11:08:30 +0000769}
770
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000771BOOST_AUTO_TEST_CASE(SerializeDequantize)
772{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100773 DECLARE_LAYER_VERIFIER_CLASS(Dequantize)
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000774
775 const std::string layerName("dequantize");
Derek Lambertif90c56d2020-01-10 17:14:08 +0000776 const armnn::TensorInfo inputInfo({ 1, 5, 2, 3 }, armnn::DataType::QAsymmU8, 0.5f, 1);
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000777 const armnn::TensorInfo outputInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
778
779 armnn::INetworkPtr network = armnn::INetwork::Create();
780 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
781 armnn::IConnectableLayer* const dequantizeLayer = network->AddDequantizeLayer(layerName.c_str());
782 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
783
784 inputLayer->GetOutputSlot(0).Connect(dequantizeLayer->GetInputSlot(0));
785 dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
786
787 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
788 dequantizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
789
790 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
791 BOOST_CHECK(deserializedNetwork);
792
793 DequantizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
794 deserializedNetwork->Accept(verifier);
795}
796
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000797BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess)
798{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100799 using Descriptor = armnn::DetectionPostProcessDescriptor;
800 class DetectionPostProcessLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000801 {
802 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000803 DetectionPostProcessLayerVerifier(const std::string& layerName,
804 const std::vector<armnn::TensorInfo>& inputInfos,
805 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100806 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000807 const armnn::ConstTensor& anchors)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100808 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
809 , m_Anchors(anchors) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000810
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000811 void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100812 const Descriptor& descriptor,
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000813 const armnn::ConstTensor& anchors,
814 const char* name) override
815 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000816 VerifyNameAndConnections(layer, name);
817 VerifyDescriptor(descriptor);
818
819 CompareConstTensor(anchors, m_Anchors);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000820 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000821
822 private:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000823 armnn::ConstTensor m_Anchors;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000824 };
825
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000826 const std::string layerName("detectionPostProcess");
827
828 const std::vector<armnn::TensorInfo> inputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000829 armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32),
830 armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000831 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000832
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000833 const std::vector<armnn::TensorInfo> outputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000834 armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32),
835 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
836 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
837 armnn::TensorInfo({ 1 }, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000838 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000839
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000840 armnn::DetectionPostProcessDescriptor descriptor;
841 descriptor.m_UseRegularNms = true;
842 descriptor.m_MaxDetections = 3;
843 descriptor.m_MaxClassesPerDetection = 1;
844 descriptor.m_DetectionsPerClass =1;
845 descriptor.m_NmsScoreThreshold = 0.0;
846 descriptor.m_NmsIouThreshold = 0.5;
847 descriptor.m_NumClasses = 2;
848 descriptor.m_ScaleY = 10.0;
849 descriptor.m_ScaleX = 10.0;
850 descriptor.m_ScaleH = 5.0;
851 descriptor.m_ScaleW = 5.0;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000852
853 const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
854 const std::vector<float> anchorsData({
855 0.5f, 0.5f, 1.0f, 1.0f,
856 0.5f, 0.5f, 1.0f, 1.0f,
857 0.5f, 0.5f, 1.0f, 1.0f,
858 0.5f, 10.5f, 1.0f, 1.0f,
859 0.5f, 10.5f, 1.0f, 1.0f,
860 0.5f, 100.5f, 1.0f, 1.0f
861 });
862 armnn::ConstTensor anchors(anchorsInfo, anchorsData);
863
864 armnn::INetworkPtr network = armnn::INetwork::Create();
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000865 armnn::IConnectableLayer* const detectionLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000866 network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000867
868 for (unsigned int i = 0; i < 2; i++)
869 {
870 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
871 inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
872 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
873 }
874
875 for (unsigned int i = 0; i < 4; i++)
876 {
877 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
878 detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
879 detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
880 }
881
882 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
883 BOOST_CHECK(deserializedNetwork);
884
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000885 DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors);
886 deserializedNetwork->Accept(verifier);
887}
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000888
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000889BOOST_AUTO_TEST_CASE(SerializeDivision)
890{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100891 DECLARE_LAYER_VERIFIER_CLASS(Division)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000892
893 const std::string layerName("division");
894 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
895
896 armnn::INetworkPtr network = armnn::INetwork::Create();
897 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
898 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
899 armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
900 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
901
902 inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
903 inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
904 divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
905
906 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
907 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
908 divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
909
910 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
911 BOOST_CHECK(deserializedNetwork);
912
913 DivisionLayerVerifier verifier(layerName, {info, info}, {info});
914 deserializedNetwork->Accept(verifier);
915}
916
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +0100917class EqualLayerVerifier : public LayerVerifierBase
918{
919public:
920 EqualLayerVerifier(const std::string& layerName,
921 const std::vector<armnn::TensorInfo>& inputInfos,
922 const std::vector<armnn::TensorInfo>& outputInfos)
923 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
924
925 void VisitComparisonLayer(const armnn::IConnectableLayer* layer,
926 const armnn::ComparisonDescriptor& descriptor,
927 const char* name) override
928 {
929 VerifyNameAndConnections(layer, name);
930 BOOST_CHECK(descriptor.m_Operation == armnn::ComparisonOperation::Equal);
931 }
932
Derek Lamberti859f9ce2019-12-10 22:05:21 +0000933 void VisitEqualLayer(const armnn::IConnectableLayer*, const char*) override
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +0100934 {
935 throw armnn::Exception("EqualLayer should have translated to ComparisonLayer");
936 }
937};
938
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100939// NOTE: Until the deprecated AddEqualLayer disappears this test checks that calling
940// AddEqualLayer places a ComparisonLayer into the serialized format and that
941// when this deserialises we have a ComparisonLayer
942BOOST_AUTO_TEST_CASE(SerializeEqual)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000943{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +0100944 const std::string layerName("equal");
945
946 const armnn::TensorShape shape{2, 1, 2, 4};
947
948 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
949 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
950
951 armnn::INetworkPtr network = armnn::INetwork::Create();
952 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
953 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
954 ARMNN_NO_DEPRECATE_WARN_BEGIN
955 armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str());
956 ARMNN_NO_DEPRECATE_WARN_END
957 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
958
959 inputLayer0->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
960 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
961 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
962
963 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
964 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
965 equalLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
966
967 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
968 BOOST_CHECK(deserializedNetwork);
969
970 EqualLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo });
971 deserializedNetwork->Accept(verifier);
972}
973
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +0100974BOOST_AUTO_TEST_CASE(EnsureEqualBackwardCompatibility)
975{
976 // The hex data below is a flat buffer containing a simple network with two inputs,
977 // an EqualLayer (now deprecated) and an output
978 //
979 // This test verifies that we can still deserialize this old-style model by replacing
980 // the EqualLayer with an equivalent ComparisonLayer
981 const std::vector<uint8_t> equalModel =
982 {
983 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
984 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
985 0xCC, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
986 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
987 0x60, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
988 0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xEA, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
989 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
990 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
991 0x64, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
992 0x00, 0x13, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
993 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
994 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x65, 0x71, 0x75, 0x61, 0x6C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
995 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
996 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00,
997 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
998 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
999 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1000 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1001 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1002 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1003 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1004 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1005 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1006 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1007 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1008 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1009 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
1010 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1011 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1012 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1013 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1014 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1015 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1016 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1017 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1018 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1019 0x04, 0x00, 0x00, 0x00
1020 };
1021
1022 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(equalModel.begin(), equalModel.end()));
1023 BOOST_CHECK(deserializedNetwork);
1024
1025 const armnn::TensorShape shape{ 2, 1, 2, 4 };
1026
1027 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1028 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1029
1030 EqualLayerVerifier verifier("equal", { inputInfo, inputInfo }, { outputInfo });
1031 deserializedNetwork->Accept(verifier);
1032}
1033
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001034BOOST_AUTO_TEST_CASE(SerializeFloor)
1035{
1036 DECLARE_LAYER_VERIFIER_CLASS(Floor)
1037
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001038 const std::string layerName("floor");
1039 const armnn::TensorInfo info({4,4}, armnn::DataType::Float32);
1040
1041 armnn::INetworkPtr network = armnn::INetwork::Create();
1042 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1043 armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
1044 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1045
1046 inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
1047 floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1048
1049 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1050 floorLayer->GetOutputSlot(0).SetTensorInfo(info);
1051
1052 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1053 BOOST_CHECK(deserializedNetwork);
1054
1055 FloorLayerVerifier verifier(layerName, {info}, {info});
1056 deserializedNetwork->Accept(verifier);
1057}
1058
1059BOOST_AUTO_TEST_CASE(SerializeFullyConnected)
1060{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001061 using Descriptor = armnn::FullyConnectedDescriptor;
1062 class FullyConnectedLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001063 {
1064 public:
1065 FullyConnectedLayerVerifier(const std::string& layerName,
1066 const std::vector<armnn::TensorInfo>& inputInfos,
1067 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001068 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001069 const armnn::ConstTensor& weight,
1070 const armnn::Optional<armnn::ConstTensor>& bias)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001071 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
1072 , m_Weight(weight)
1073 , m_Bias(bias) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001074
1075 void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001076 const Descriptor& descriptor,
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001077 const armnn::ConstTensor& weight,
1078 const armnn::Optional<armnn::ConstTensor>& bias,
1079 const char* name) override
1080 {
1081 VerifyNameAndConnections(layer, name);
1082 VerifyDescriptor(descriptor);
1083
1084 CompareConstTensor(weight, m_Weight);
1085
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001086 BOOST_TEST(bias.has_value() == descriptor.m_BiasEnabled);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001087 BOOST_TEST(bias.has_value() == m_Bias.has_value());
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001088
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001089 if (bias.has_value() && m_Bias.has_value())
1090 {
1091 CompareConstTensor(bias.value(), m_Bias.value());
1092 }
1093 }
1094
1095 private:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001096 armnn::ConstTensor m_Weight;
1097 armnn::Optional<armnn::ConstTensor> m_Bias;
1098 };
1099
1100 const std::string layerName("fullyConnected");
1101 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
1102 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
1103
1104 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
1105 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
1106 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
1107 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
1108 armnn::ConstTensor weights(weightsInfo, weightsData);
1109 armnn::ConstTensor biases(biasesInfo, biasesData);
1110
1111 armnn::FullyConnectedDescriptor descriptor;
1112 descriptor.m_BiasEnabled = true;
1113 descriptor.m_TransposeWeightMatrix = false;
1114
1115 armnn::INetworkPtr network = armnn::INetwork::Create();
1116 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1117 armnn::IConnectableLayer* const fullyConnectedLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +01001118 network->AddFullyConnectedLayer(descriptor,
1119 weights,
1120 armnn::Optional<armnn::ConstTensor>(biases),
1121 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001122 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1123
1124 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
1125 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1126
1127 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1128 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1129
1130 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1131 BOOST_CHECK(deserializedNetwork);
1132
1133 FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
1134 deserializedNetwork->Accept(verifier);
1135}
1136
1137BOOST_AUTO_TEST_CASE(SerializeGather)
1138{
1139 class GatherLayerVerifier : public LayerVerifierBase
1140 {
1141 public:
1142 GatherLayerVerifier(const std::string& layerName,
1143 const std::vector<armnn::TensorInfo>& inputInfos,
1144 const std::vector<armnn::TensorInfo>& outputInfos)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001145 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001146
1147 void VisitGatherLayer(const armnn::IConnectableLayer* layer, const char *name) override
1148 {
1149 VerifyNameAndConnections(layer, name);
1150 }
1151
Derek Lamberti859f9ce2019-12-10 22:05:21 +00001152 void VisitConstantLayer(const armnn::IConnectableLayer*,
1153 const armnn::ConstTensor&,
1154 const char*) override {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001155 };
1156
1157 const std::string layerName("gather");
Derek Lambertif90c56d2020-01-10 17:14:08 +00001158 armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QAsymmU8);
1159 armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QAsymmU8);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001160 const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
1161
1162 paramsInfo.SetQuantizationScale(1.0f);
1163 paramsInfo.SetQuantizationOffset(0);
1164 outputInfo.SetQuantizationScale(1.0f);
1165 outputInfo.SetQuantizationOffset(0);
1166
1167 const std::vector<int32_t>& indicesData = {7, 6, 5};
1168
1169 armnn::INetworkPtr network = armnn::INetwork::Create();
1170 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
1171 armnn::IConnectableLayer *const constantLayer =
1172 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
1173 armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(layerName.c_str());
1174 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
1175
1176 inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
1177 constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
1178 gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1179
1180 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
1181 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
1182 gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1183
1184 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1185 BOOST_CHECK(deserializedNetwork);
1186
1187 GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo});
1188 deserializedNetwork->Accept(verifier);
1189}
1190
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +01001191class GreaterLayerVerifier : public LayerVerifierBase
1192{
1193public:
1194 GreaterLayerVerifier(const std::string& layerName,
1195 const std::vector<armnn::TensorInfo>& inputInfos,
1196 const std::vector<armnn::TensorInfo>& outputInfos)
1197 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1198
1199 void VisitComparisonLayer(const armnn::IConnectableLayer* layer,
1200 const armnn::ComparisonDescriptor& descriptor,
1201 const char* name) override
1202 {
1203 VerifyNameAndConnections(layer, name);
1204 BOOST_CHECK(descriptor.m_Operation == armnn::ComparisonOperation::Greater);
1205 }
1206
Derek Lamberti859f9ce2019-12-10 22:05:21 +00001207 void VisitGreaterLayer(const armnn::IConnectableLayer*, const char*) override
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +01001208 {
1209 throw armnn::Exception("GreaterLayer should have translated to ComparisonLayer");
1210 }
1211};
1212
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001213// NOTE: Until the deprecated AddGreaterLayer disappears this test checks that calling
1214// AddGreaterLayer places a ComparisonLayer into the serialized format and that
1215// when this deserialises we have a ComparisonLayer
1216BOOST_AUTO_TEST_CASE(SerializeGreater)
Aron Virginas-Tar781ced92019-10-03 11:15:39 +01001217{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001218 const std::string layerName("greater");
1219
1220 const armnn::TensorShape shape{2, 1, 2, 4};
1221
1222 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1223 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1224
1225 armnn::INetworkPtr network = armnn::INetwork::Create();
1226 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1227 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1228 ARMNN_NO_DEPRECATE_WARN_BEGIN
1229 armnn::IConnectableLayer* const equalLayer = network->AddGreaterLayer(layerName.c_str());
1230 ARMNN_NO_DEPRECATE_WARN_END
1231 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1232
1233 inputLayer0->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
1234 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
1235 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1236
1237 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
1238 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
1239 equalLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1240
1241 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1242 BOOST_CHECK(deserializedNetwork);
1243
1244 GreaterLayerVerifier verifier(layerName, { inputInfo, inputInfo }, { outputInfo });
1245 deserializedNetwork->Accept(verifier);
1246}
1247
Aron Virginas-Tar6d2e6592019-10-22 11:44:47 +01001248BOOST_AUTO_TEST_CASE(EnsureGreaterBackwardCompatibility)
1249{
1250 // The hex data below is a flat buffer containing a simple network with two inputs,
1251 // an GreaterLayer (now deprecated) and an output
1252 //
1253 // This test verifies that we can still deserialize this old-style model by replacing
1254 // the GreaterLayer with an equivalent ComparisonLayer
1255 const std::vector<uint8_t> greaterModel =
1256 {
1257 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1258 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1259 0xCC, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1261 0x60, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1262 0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xEA, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1263 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1265 0x64, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1266 0x00, 0x19, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1267 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1268 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x00, 0x02, 0x00, 0x00, 0x00,
1269 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1270 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00,
1271 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1272 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1273 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1274 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1275 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1276 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1277 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1278 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1279 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1281 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1282 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1283 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1284 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1285 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1286 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1287 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1288 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1290 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1291 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1292 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1293 0x02, 0x00, 0x00, 0x00
1294 };
1295
1296 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(greaterModel.begin(), greaterModel.end()));
1297 BOOST_CHECK(deserializedNetwork);
1298
1299 const armnn::TensorShape shape{ 1, 2, 2, 2 };
1300
1301 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1302 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1303
1304 GreaterLayerVerifier verifier("greater", { inputInfo, inputInfo }, { outputInfo });
1305 deserializedNetwork->Accept(verifier);
1306}
1307
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001308BOOST_AUTO_TEST_CASE(SerializeInstanceNormalization)
1309{
1310 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(InstanceNormalization)
1311
Aron Virginas-Tar781ced92019-10-03 11:15:39 +01001312 const std::string layerName("instanceNormalization");
1313 const armnn::TensorInfo info({ 1, 2, 1, 5 }, armnn::DataType::Float32);
1314
1315 armnn::InstanceNormalizationDescriptor descriptor;
1316 descriptor.m_Gamma = 1.1f;
1317 descriptor.m_Beta = 0.1f;
1318 descriptor.m_Eps = 0.0001f;
1319 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
1320
1321 armnn::INetworkPtr network = armnn::INetwork::Create();
1322 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1323 armnn::IConnectableLayer* const instanceNormLayer =
1324 network->AddInstanceNormalizationLayer(descriptor, layerName.c_str());
1325 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1326
1327 inputLayer->GetOutputSlot(0).Connect(instanceNormLayer->GetInputSlot(0));
1328 instanceNormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1329
1330 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1331 instanceNormLayer->GetOutputSlot(0).SetTensorInfo(info);
1332
1333 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1334 BOOST_CHECK(deserializedNetwork);
1335
1336 InstanceNormalizationLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1337 deserializedNetwork->Accept(verifier);
1338}
1339
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001340DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(L2Normalization)
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001341
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001342BOOST_AUTO_TEST_CASE(SerializeL2Normalization)
1343{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001344 const std::string l2NormLayerName("l2Normalization");
1345 const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1346
1347 armnn::L2NormalizationDescriptor desc;
1348 desc.m_DataLayout = armnn::DataLayout::NCHW;
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001349 desc.m_Eps = 0.0001f;
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001350
1351 armnn::INetworkPtr network = armnn::INetwork::Create();
1352 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1353 armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1354 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1355
1356 inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1357 l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1358
1359 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1360 l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1361
1362 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1363 BOOST_CHECK(deserializedNetwork);
1364
1365 L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc);
1366 deserializedNetwork->Accept(verifier);
1367}
1368
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001369BOOST_AUTO_TEST_CASE(EnsureL2NormalizationBackwardCompatibility)
1370{
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001371 // The hex data below is a flat buffer containing a simple network with one input
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001372 // a L2Normalization layer and an output layer with dimensions as per the tensor infos below.
1373 //
1374 // This test verifies that we can still read back these old style
1375 // models without the normalization epsilon value.
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001376 const std::vector<uint8_t> l2NormalizationModel =
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001377 {
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001378 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1379 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1380 0x3C, 0x01, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1381 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xE8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
1382 0x04, 0x00, 0x00, 0x00, 0xD6, 0xFE, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
1383 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
1384 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1386 0x4C, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
1387 0x00, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1388 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1389 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1390 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x20, 0x00,
1391 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x6C, 0x32, 0x4E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x69, 0x7A, 0x61, 0x74,
1392 0x69, 0x6F, 0x6E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00,
1393 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1394 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
1395 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1396 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1397 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1398 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1399 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1400 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1401 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1402 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1403 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1404 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1405 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1406 0x05, 0x00, 0x00, 0x00, 0x00
1407 };
1408
1409 armnn::INetworkPtr deserializedNetwork =
1410 DeserializeNetwork(std::string(l2NormalizationModel.begin(), l2NormalizationModel.end()));
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001411 BOOST_CHECK(deserializedNetwork);
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001412
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001413 const std::string layerName("l2Normalization");
1414 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 2, 1, 5}, armnn::DataType::Float32);
1415
1416 armnn::L2NormalizationDescriptor desc;
1417 desc.m_DataLayout = armnn::DataLayout::NCHW;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001418 // Since this variable does not exist in the l2NormalizationModel dump, the default value will be loaded
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001419 desc.m_Eps = 1e-12f;
1420
1421 L2NormalizationLayerVerifier verifier(layerName, {inputInfo}, {inputInfo}, desc);
1422 deserializedNetwork->Accept(verifier);
1423}
1424
Sadik Armagan26257852019-10-14 13:00:47 +01001425BOOST_AUTO_TEST_CASE(SerializeLogSoftmax)
1426{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001427 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(LogSoftmax)
Sadik Armagan26257852019-10-14 13:00:47 +01001428
1429 const std::string layerName("log_softmax");
1430 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
1431
1432 armnn::LogSoftmaxDescriptor descriptor;
1433 descriptor.m_Beta = 1.0f;
1434 descriptor.m_Axis = -1;
1435
1436 armnn::INetworkPtr network = armnn::INetwork::Create();
1437 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1438 armnn::IConnectableLayer* const logSoftmaxLayer = network->AddLogSoftmaxLayer(descriptor, layerName.c_str());
1439 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1440
1441 inputLayer->GetOutputSlot(0).Connect(logSoftmaxLayer->GetInputSlot(0));
1442 logSoftmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1443
1444 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1445 logSoftmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
1446
1447 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1448 BOOST_CHECK(deserializedNetwork);
1449
1450 LogSoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1451 deserializedNetwork->Accept(verifier);
1452}
1453
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001454BOOST_AUTO_TEST_CASE(SerializeMaximum)
1455{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001456 DECLARE_LAYER_VERIFIER_CLASS(Maximum)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001457
1458 const std::string layerName("maximum");
1459 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1460
1461 armnn::INetworkPtr network = armnn::INetwork::Create();
1462 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1463 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1464 armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1465 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1466
1467 inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1468 inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1469 maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1470
1471 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1472 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1473 maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1474
1475 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1476 BOOST_CHECK(deserializedNetwork);
1477
1478 MaximumLayerVerifier verifier(layerName, {info, info}, {info});
1479 deserializedNetwork->Accept(verifier);
1480}
1481
1482BOOST_AUTO_TEST_CASE(SerializeMean)
1483{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001484 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Mean)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001485
1486 const std::string layerName("mean");
1487 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1488 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1489
1490 armnn::MeanDescriptor descriptor;
1491 descriptor.m_Axis = { 2 };
1492 descriptor.m_KeepDims = true;
1493
1494 armnn::INetworkPtr network = armnn::INetwork::Create();
1495 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1496 armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1497 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1498
1499 inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1500 meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1501
1502 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1503 meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1504
1505 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1506 BOOST_CHECK(deserializedNetwork);
1507
1508 MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1509 deserializedNetwork->Accept(verifier);
1510}
1511
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001512BOOST_AUTO_TEST_CASE(SerializeMerge)
1513{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001514 DECLARE_LAYER_VERIFIER_CLASS(Merge)
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001515
1516 const std::string layerName("merge");
1517 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1518
1519 armnn::INetworkPtr network = armnn::INetwork::Create();
1520 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1521 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1522 armnn::IConnectableLayer* const mergeLayer = network->AddMergeLayer(layerName.c_str());
1523 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1524
1525 inputLayer0->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(0));
1526 inputLayer1->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(1));
1527 mergeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1528
1529 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1530 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1531 mergeLayer->GetOutputSlot(0).SetTensorInfo(info);
1532
1533 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1534 BOOST_CHECK(deserializedNetwork);
1535
1536 MergeLayerVerifier verifier(layerName, {info, info}, {info});
1537 deserializedNetwork->Accept(verifier);
1538}
1539
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001540class MergerLayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::OriginsDescriptor>
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001541{
Jim Flynn5fa83932019-05-09 15:35:43 +01001542public:
1543 MergerLayerVerifier(const std::string& layerName,
1544 const std::vector<armnn::TensorInfo>& inputInfos,
1545 const std::vector<armnn::TensorInfo>& outputInfos,
1546 const armnn::OriginsDescriptor& descriptor)
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001547 : LayerVerifierBaseWithDescriptor<armnn::OriginsDescriptor>(layerName, inputInfos, outputInfos, descriptor) {}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001548
Derek Lamberti859f9ce2019-12-10 22:05:21 +00001549 void VisitMergerLayer(const armnn::IConnectableLayer*,
1550 const armnn::OriginsDescriptor&,
1551 const char*) override
Jim Flynn5fa83932019-05-09 15:35:43 +01001552 {
Jim Flynne242f2d2019-05-22 14:24:13 +01001553 throw armnn::Exception("MergerLayer should have translated to ConcatLayer");
1554 }
1555
1556 void VisitConcatLayer(const armnn::IConnectableLayer* layer,
1557 const armnn::OriginsDescriptor& descriptor,
1558 const char* name) override
1559 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001560 VerifyNameAndConnections(layer, name);
1561 VerifyDescriptor(descriptor);
1562 }
Jim Flynn5fa83932019-05-09 15:35:43 +01001563};
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001564
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001565// NOTE: Until the deprecated AddMergerLayer disappears this test checks that calling
Jim Flynne242f2d2019-05-22 14:24:13 +01001566// AddMergerLayer places a ConcatLayer into the serialized format and that
1567// when this deserialises we have a ConcatLayer
Jim Flynn5fa83932019-05-09 15:35:43 +01001568BOOST_AUTO_TEST_CASE(SerializeMerger)
1569{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001570 const std::string layerName("merger");
1571 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1572 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1573
1574 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1575
1576 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001577 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001578
1579 armnn::INetworkPtr network = armnn::INetwork::Create();
1580 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1581 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
Jim Flynn906f9462019-05-10 13:55:21 +01001582 ARMNN_NO_DEPRECATE_WARN_BEGIN
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001583 armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str());
Jim Flynn906f9462019-05-10 13:55:21 +01001584 ARMNN_NO_DEPRECATE_WARN_END
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001585 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1586
1587 inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
1588 inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
1589 mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1590
1591 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1592 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1593 mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1594
Jim Flynn5fa83932019-05-09 15:35:43 +01001595 std::string mergerLayerNetwork = SerializeNetwork(*network);
1596 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001597 BOOST_CHECK(deserializedNetwork);
1598
1599 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1600 deserializedNetwork->Accept(verifier);
1601}
1602
Jim Flynn5fa83932019-05-09 15:35:43 +01001603BOOST_AUTO_TEST_CASE(EnsureMergerLayerBackwardCompatibility)
1604{
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001605 // The hex data below is a flat buffer containing a simple network with two inputs
Jim Flynne242f2d2019-05-22 14:24:13 +01001606 // a merger layer (now deprecated) and an output layer with dimensions as per the tensor infos below.
1607 //
1608 // This test verifies that we can still read back these old style
Jim Flynn5fa83932019-05-09 15:35:43 +01001609 // models replacing the MergerLayers with ConcatLayers with the same parameters.
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001610 const std::vector<uint8_t> mergerModel =
Jim Flynn5fa83932019-05-09 15:35:43 +01001611 {
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001612 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1613 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1614 0x38, 0x02, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1616 0xF4, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1617 0x00, 0x00, 0x9A, 0xFE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1618 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1620 0xF8, 0xFE, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1621 0x00, 0x1F, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1622 0x68, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
1623 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1624 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0x04, 0x00,
1625 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1626 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1628 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1629 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6D, 0x65, 0x72, 0x67, 0x65, 0x72, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1630 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1631 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
1632 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00,
1633 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1634 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1635 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1636 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1637 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1638 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1639 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1640 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1642 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1643 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1644 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1645 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1646 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1647 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1648 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1649 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1651 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1652 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1653 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1654 0x02, 0x00, 0x00, 0x00
1655 };
1656
1657 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(mergerModel.begin(), mergerModel.end()));
Jim Flynn5fa83932019-05-09 15:35:43 +01001658 BOOST_CHECK(deserializedNetwork);
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001659
1660 const armnn::TensorInfo inputInfo = armnn::TensorInfo({ 2, 3, 2, 2 }, armnn::DataType::Float32);
1661 const armnn::TensorInfo outputInfo = armnn::TensorInfo({ 4, 3, 2, 2 }, armnn::DataType::Float32);
Jim Flynn5fa83932019-05-09 15:35:43 +01001662
1663 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1664
1665 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001666 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Jim Flynn5fa83932019-05-09 15:35:43 +01001667
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001668 MergerLayerVerifier verifier("merger", { inputInfo, inputInfo }, { outputInfo }, descriptor);
Jim Flynn5fa83932019-05-09 15:35:43 +01001669 deserializedNetwork->Accept(verifier);
1670}
1671
Jim Flynne242f2d2019-05-22 14:24:13 +01001672BOOST_AUTO_TEST_CASE(SerializeConcat)
1673{
1674 const std::string layerName("concat");
1675 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1676 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1677
1678 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1679
1680 armnn::OriginsDescriptor descriptor =
1681 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1682
1683 armnn::INetworkPtr network = armnn::INetwork::Create();
1684 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1685 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1686 armnn::IConnectableLayer* const concatLayer = network->AddConcatLayer(descriptor, layerName.c_str());
1687 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1688
1689 inputLayerOne->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
1690 inputLayerTwo->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
1691 concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1692
1693 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1694 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1695 concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1696
1697 std::string concatLayerNetwork = SerializeNetwork(*network);
1698 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(concatLayerNetwork);
1699 BOOST_CHECK(deserializedNetwork);
1700
1701 // NOTE: using the MergerLayerVerifier to ensure that it is a concat layer and not a
1702 // merger layer that gets placed into the graph.
1703 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1704 deserializedNetwork->Accept(verifier);
1705}
1706
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001707BOOST_AUTO_TEST_CASE(SerializeMinimum)
1708{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001709 DECLARE_LAYER_VERIFIER_CLASS(Minimum)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001710
1711 const std::string layerName("minimum");
1712 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1713
1714 armnn::INetworkPtr network = armnn::INetwork::Create();
1715 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1716 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1717 armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1718 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1719
1720 inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1721 inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1722 minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1723
1724 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1725 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1726 minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
1727
1728 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1729 BOOST_CHECK(deserializedNetwork);
1730
1731 MinimumLayerVerifier verifier(layerName, {info, info}, {info});
1732 deserializedNetwork->Accept(verifier);
1733}
1734
1735BOOST_AUTO_TEST_CASE(SerializeMultiplication)
1736{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001737 DECLARE_LAYER_VERIFIER_CLASS(Multiplication)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001738
1739 const std::string layerName("multiplication");
1740 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1741
1742 armnn::INetworkPtr network = armnn::INetwork::Create();
1743 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1744 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1745 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
1746 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1747
1748 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
1749 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
1750 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1751
1752 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1753 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1754 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
1755
1756 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1757 BOOST_CHECK(deserializedNetwork);
1758
1759 MultiplicationLayerVerifier verifier(layerName, {info, info}, {info});
1760 deserializedNetwork->Accept(verifier);
1761}
1762
Ellen Norris-Thompson51982472019-06-19 11:46:21 +01001763BOOST_AUTO_TEST_CASE(SerializePrelu)
1764{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001765 DECLARE_LAYER_VERIFIER_CLASS(Prelu)
Ellen Norris-Thompson51982472019-06-19 11:46:21 +01001766
1767 const std::string layerName("prelu");
1768
1769 armnn::TensorInfo inputTensorInfo ({ 4, 1, 2 }, armnn::DataType::Float32);
1770 armnn::TensorInfo alphaTensorInfo ({ 5, 4, 3, 1 }, armnn::DataType::Float32);
1771 armnn::TensorInfo outputTensorInfo({ 5, 4, 3, 2 }, armnn::DataType::Float32);
1772
1773 armnn::INetworkPtr network = armnn::INetwork::Create();
1774 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1775 armnn::IConnectableLayer* const alphaLayer = network->AddInputLayer(1);
1776 armnn::IConnectableLayer* const preluLayer = network->AddPreluLayer(layerName.c_str());
1777 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1778
1779 inputLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(0));
1780 alphaLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(1));
1781 preluLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1782
1783 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1784 alphaLayer->GetOutputSlot(0).SetTensorInfo(alphaTensorInfo);
1785 preluLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1786
1787 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1788 BOOST_CHECK(deserializedNetwork);
1789
1790 PreluLayerVerifier verifier(layerName, {inputTensorInfo, alphaTensorInfo}, {outputTensorInfo});
1791 deserializedNetwork->Accept(verifier);
1792}
1793
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001794BOOST_AUTO_TEST_CASE(SerializeNormalization)
1795{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001796 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Normalization)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001797
1798 const std::string layerName("normalization");
1799 const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
1800
1801 armnn::NormalizationDescriptor desc;
1802 desc.m_DataLayout = armnn::DataLayout::NCHW;
1803 desc.m_NormSize = 3;
1804 desc.m_Alpha = 1;
1805 desc.m_Beta = 1;
1806 desc.m_K = 1;
1807
1808 armnn::INetworkPtr network = armnn::INetwork::Create();
1809 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1810 armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
1811 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1812
1813 inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
1814 normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1815
1816 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1817 normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
1818
1819 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1820 BOOST_CHECK(deserializedNetwork);
1821
1822 NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc);
1823 deserializedNetwork->Accept(verifier);
1824}
1825
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001826DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Pad)
Jim Flynn965c7c62019-06-24 14:32:41 +01001827
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001828BOOST_AUTO_TEST_CASE(SerializePad)
1829{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001830 const std::string layerName("pad");
1831 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1832 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1833
1834 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1835
1836 armnn::INetworkPtr network = armnn::INetwork::Create();
1837 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1838 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
1839 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1840
1841 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
1842 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1843
1844 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1845 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1846
1847 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1848 BOOST_CHECK(deserializedNetwork);
1849
1850 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1851 deserializedNetwork->Accept(verifier);
1852}
1853
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001854BOOST_AUTO_TEST_CASE(EnsurePadBackwardCompatibility)
Jim Flynn965c7c62019-06-24 14:32:41 +01001855{
1856 // The PadDescriptor is being extended with a float PadValue (so a value other than 0
1857 // can be used to pad the tensor.
1858 //
1859 // This test contains a binary representation of a simple input->pad->output network
1860 // prior to this change to test that the descriptor has been updated in a backward
1861 // compatible way with respect to Deserialization of older binary dumps
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001862 const std::vector<uint8_t> padModel =
Jim Flynn965c7c62019-06-24 14:32:41 +01001863 {
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001864 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1865 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1866 0x54, 0x01, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1867 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD0, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
1868 0x04, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x04, 0x00,
1869 0x00, 0x00, 0x72, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1870 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
1871 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00,
1872 0x00, 0x00, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x16, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00,
1873 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
1874 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00,
1875 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1876 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
1877 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1878 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00,
1879 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1880 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
1881 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
1882 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00,
1883 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
1884 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00,
1885 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00,
1886 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1887 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00,
1888 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
1889 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
1890 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
1891 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1892 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
1893 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00
1894 };
1895
1896 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(padModel.begin(), padModel.end()));
Jim Flynn965c7c62019-06-24 14:32:41 +01001897 BOOST_CHECK(deserializedNetwork);
1898
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001899 const armnn::TensorInfo inputInfo = armnn::TensorInfo({ 1, 2, 3, 4 }, armnn::DataType::Float32);
1900 const armnn::TensorInfo outputInfo = armnn::TensorInfo({ 1, 3, 5, 7 }, armnn::DataType::Float32);
Jim Flynn965c7c62019-06-24 14:32:41 +01001901
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001902 armnn::PadDescriptor descriptor({{ 0, 0 }, { 1, 0 }, { 1, 1 }, { 1, 2 }});
Jim Flynn965c7c62019-06-24 14:32:41 +01001903
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01001904 PadLayerVerifier verifier("pad", { inputInfo }, { outputInfo }, descriptor);
Jim Flynn965c7c62019-06-24 14:32:41 +01001905 deserializedNetwork->Accept(verifier);
1906}
1907
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001908BOOST_AUTO_TEST_CASE(SerializePermute)
1909{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001910 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Permute)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001911
1912 const std::string layerName("permute");
1913 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
1914 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1915
1916 armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
1917
1918 armnn::INetworkPtr network = armnn::INetwork::Create();
1919 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1920 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
1921 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1922
1923 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
1924 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1925
1926 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1927 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1928
1929 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1930 BOOST_CHECK(deserializedNetwork);
1931
1932 PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
1933 deserializedNetwork->Accept(verifier);
1934}
1935
1936BOOST_AUTO_TEST_CASE(SerializePooling2d)
1937{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001938 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Pooling2d)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001939
1940 const std::string layerName("pooling2d");
1941 const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
1942 const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
1943
1944 armnn::Pooling2dDescriptor desc;
1945 desc.m_DataLayout = armnn::DataLayout::NHWC;
1946 desc.m_PadTop = 0;
1947 desc.m_PadBottom = 0;
1948 desc.m_PadLeft = 0;
1949 desc.m_PadRight = 0;
1950 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
1951 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1952 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1953 desc.m_PoolHeight = 2;
1954 desc.m_PoolWidth = 2;
1955 desc.m_StrideX = 2;
1956 desc.m_StrideY = 2;
1957
1958 armnn::INetworkPtr network = armnn::INetwork::Create();
1959 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1960 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
1961 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1962
1963 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
1964 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1965
1966 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1967 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1968
1969 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1970 BOOST_CHECK(deserializedNetwork);
1971
1972 Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1973 deserializedNetwork->Accept(verifier);
1974}
1975
Derek Lamberti87acb272019-03-27 16:51:31 +00001976BOOST_AUTO_TEST_CASE(SerializeQuantize)
1977{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01001978 DECLARE_LAYER_VERIFIER_CLASS(Quantize)
Derek Lamberti87acb272019-03-27 16:51:31 +00001979
1980 const std::string layerName("quantize");
1981 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1982
1983 armnn::INetworkPtr network = armnn::INetwork::Create();
1984 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1985 armnn::IConnectableLayer* const quantizeLayer = network->AddQuantizeLayer(layerName.c_str());
1986 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1987
1988 inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
1989 quantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1990
1991 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1992 quantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
1993
1994 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1995 BOOST_CHECK(deserializedNetwork);
1996
1997 QuantizeLayerVerifier verifier(layerName, {info}, {info});
1998 deserializedNetwork->Accept(verifier);
1999}
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002000
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002001BOOST_AUTO_TEST_CASE(SerializeReshape)
2002{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002003 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Reshape)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002004
2005 const std::string layerName("reshape");
2006 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
2007 const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
2008
2009 armnn::ReshapeDescriptor descriptor({3, 3});
2010
2011 armnn::INetworkPtr network = armnn::INetwork::Create();
2012 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2013 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
2014 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2015
2016 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
2017 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2018
2019 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2020 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2021
2022 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2023 BOOST_CHECK(deserializedNetwork);
2024
2025 ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2026 deserializedNetwork->Accept(verifier);
2027}
2028
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002029BOOST_AUTO_TEST_CASE(SerializeResize)
2030{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002031 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Resize)
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002032
2033 const std::string layerName("resize");
Aron Virginas-Tarfe414cf2019-10-31 14:35:58 +00002034 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002035 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2036
2037 armnn::ResizeDescriptor desc;
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002038 desc.m_TargetWidth = 4;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002039 desc.m_TargetHeight = 2;
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002040 desc.m_Method = armnn::ResizeMethod::NearestNeighbor;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002041
2042 armnn::INetworkPtr network = armnn::INetwork::Create();
2043 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2044 armnn::IConnectableLayer* const resizeLayer = network->AddResizeLayer(desc, layerName.c_str());
2045 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2046
2047 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2048 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2049
2050 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2051 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2052
2053 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2054 BOOST_CHECK(deserializedNetwork);
2055
2056 ResizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2057 deserializedNetwork->Accept(verifier);
2058}
2059
Aron Virginas-Tarfe414cf2019-10-31 14:35:58 +00002060class ResizeBilinearLayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::ResizeBilinearDescriptor>
2061{
2062public:
2063 ResizeBilinearLayerVerifier(const std::string& layerName,
2064 const std::vector<armnn::TensorInfo>& inputInfos,
2065 const std::vector<armnn::TensorInfo>& outputInfos,
2066 const armnn::ResizeBilinearDescriptor& descriptor)
2067 : LayerVerifierBaseWithDescriptor<armnn::ResizeBilinearDescriptor>(
2068 layerName, inputInfos, outputInfos, descriptor) {}
2069
2070 void VisitResizeLayer(const armnn::IConnectableLayer* layer,
2071 const armnn::ResizeDescriptor& descriptor,
2072 const char* name) override
2073 {
2074 VerifyNameAndConnections(layer, name);
2075
2076 BOOST_CHECK(descriptor.m_Method == armnn::ResizeMethod::Bilinear);
2077 BOOST_CHECK(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
2078 BOOST_CHECK(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
2079 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2080 }
2081
2082 void VisitResizeBilinearLayer(const armnn::IConnectableLayer*,
2083 const armnn::ResizeBilinearDescriptor&,
2084 const char*) override
2085 {
2086 throw armnn::Exception("ResizeBilinearLayer should have translated to ResizeLayer");
2087 }
2088};
2089
2090// NOTE: Until the deprecated AddResizeBilinearLayer disappears this test checks that
2091// calling AddResizeBilinearLayer places a ResizeLayer into the serialized format
2092// and that when this deserialises we have a ResizeLayer
2093BOOST_AUTO_TEST_CASE(SerializeResizeBilinear)
2094{
2095 const std::string layerName("resizeBilinear");
2096 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2097 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2098
2099 armnn::ResizeBilinearDescriptor desc;
2100 desc.m_TargetWidth = 4u;
2101 desc.m_TargetHeight = 2u;
2102
2103 armnn::INetworkPtr network = armnn::INetwork::Create();
2104 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2105 ARMNN_NO_DEPRECATE_WARN_BEGIN
2106 armnn::IConnectableLayer* const resizeLayer = network->AddResizeBilinearLayer(desc, layerName.c_str());
2107 ARMNN_NO_DEPRECATE_WARN_END
2108 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2109
2110 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2111 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2112
2113 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2114 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2115
2116 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2117 BOOST_CHECK(deserializedNetwork);
2118
2119 ResizeBilinearLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2120 deserializedNetwork->Accept(verifier);
2121}
2122
2123BOOST_AUTO_TEST_CASE(EnsureResizeBilinearBackwardCompatibility)
2124{
2125 // The hex data below is a flat buffer containing a simple network with an input,
2126 // a ResizeBilinearLayer (now deprecated) and an output
2127 //
2128 // This test verifies that we can still deserialize this old-style model by replacing
2129 // the ResizeBilinearLayer with an equivalent ResizeLayer
2130 const std::vector<uint8_t> resizeBilinearModel =
2131 {
2132 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
2133 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2134 0x50, 0x01, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2135 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD4, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
2136 0x04, 0x00, 0x00, 0x00, 0xC2, 0xFE, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
2137 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8A, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
2138 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
2139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2140 0x38, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
2141 0x00, 0x1A, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
2142 0x34, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x12, 0x00, 0x08, 0x00, 0x0C, 0x00,
2143 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2144 0x00, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00,
2145 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
2146 0x20, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x69, 0x7A, 0x65, 0x42, 0x69, 0x6C, 0x69,
2147 0x6E, 0x65, 0x61, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2148 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
2149 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2150 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
2151 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2152 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
2153 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
2154 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00,
2155 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
2156 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00,
2158 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
2159 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
2160 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00,
2161 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
2162 };
2163
2164 armnn::INetworkPtr deserializedNetwork =
2165 DeserializeNetwork(std::string(resizeBilinearModel.begin(), resizeBilinearModel.end()));
2166 BOOST_CHECK(deserializedNetwork);
2167
2168 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2169 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2170
2171 armnn::ResizeBilinearDescriptor descriptor;
2172 descriptor.m_TargetWidth = 4u;
2173 descriptor.m_TargetHeight = 2u;
2174
2175 ResizeBilinearLayerVerifier verifier("resizeBilinear", { inputInfo }, { outputInfo }, descriptor);
2176 deserializedNetwork->Accept(verifier);
2177}
2178
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002179BOOST_AUTO_TEST_CASE(SerializeRsqrt)
2180{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002181 DECLARE_LAYER_VERIFIER_CLASS(Rsqrt)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002182
2183 const std::string layerName("rsqrt");
2184 const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32);
2185
2186 armnn::INetworkPtr network = armnn::INetwork::Create();
2187 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2188 armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer(layerName.c_str());
2189 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2190
2191 inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0));
2192 rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2193
2194 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2195 rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2196
2197 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2198 BOOST_CHECK(deserializedNetwork);
2199
2200 RsqrtLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
2201 deserializedNetwork->Accept(verifier);
2202}
2203
Aron Virginas-Tar2fda80b2019-09-18 13:36:52 +01002204BOOST_AUTO_TEST_CASE(SerializeSlice)
2205{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002206 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Slice)
Aron Virginas-Tar2fda80b2019-09-18 13:36:52 +01002207
2208 const std::string layerName{"slice"};
2209
2210 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2211 const armnn::TensorInfo outputInfo = armnn::TensorInfo({2, 2, 2, 1}, armnn::DataType::Float32);
2212
2213 armnn::SliceDescriptor descriptor({ 0, 0, 1, 0}, {2, 2, 2, 1});
2214
2215 armnn::INetworkPtr network = armnn::INetwork::Create();
2216
2217 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2218 armnn::IConnectableLayer* const sliceLayer = network->AddSliceLayer(descriptor, layerName.c_str());
2219 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2220
2221 inputLayer->GetOutputSlot(0).Connect(sliceLayer->GetInputSlot(0));
2222 sliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2223
2224 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2225 sliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2226
2227 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2228 BOOST_CHECK(deserializedNetwork);
2229
2230 SliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2231 deserializedNetwork->Accept(verifier);
2232}
2233
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002234BOOST_AUTO_TEST_CASE(SerializeSoftmax)
2235{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002236 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Softmax)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002237
2238 const std::string layerName("softmax");
2239 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
2240
2241 armnn::SoftmaxDescriptor descriptor;
2242 descriptor.m_Beta = 1.0f;
2243
2244 armnn::INetworkPtr network = armnn::INetwork::Create();
2245 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2246 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
2247 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2248
2249 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
2250 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2251
2252 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2253 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
2254
2255 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2256 BOOST_CHECK(deserializedNetwork);
2257
2258 SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
2259 deserializedNetwork->Accept(verifier);
2260}
2261
2262BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
2263{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002264 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(SpaceToBatchNd)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002265
2266 const std::string layerName("spaceToBatchNd");
2267 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
2268 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
2269
2270 armnn::SpaceToBatchNdDescriptor desc;
2271 desc.m_DataLayout = armnn::DataLayout::NCHW;
2272 desc.m_BlockShape = {2, 2};
2273 desc.m_PadList = {{0, 0}, {2, 0}};
2274
2275 armnn::INetworkPtr network = armnn::INetwork::Create();
2276 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2277 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2278 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2279
2280 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
2281 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2282
2283 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2284 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2285
2286 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2287 BOOST_CHECK(deserializedNetwork);
2288
2289 SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2290 deserializedNetwork->Accept(verifier);
2291}
2292
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002293BOOST_AUTO_TEST_CASE(SerializeSpaceToDepth)
2294{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002295 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(SpaceToDepth)
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002296
2297 const std::string layerName("spaceToDepth");
2298
2299 const armnn::TensorInfo inputInfo ({ 1, 16, 8, 3 }, armnn::DataType::Float32);
2300 const armnn::TensorInfo outputInfo({ 1, 8, 4, 12 }, armnn::DataType::Float32);
2301
2302 armnn::SpaceToDepthDescriptor desc;
2303 desc.m_BlockSize = 2;
2304 desc.m_DataLayout = armnn::DataLayout::NHWC;
2305
2306 armnn::INetworkPtr network = armnn::INetwork::Create();
2307 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2308 armnn::IConnectableLayer* const spaceToDepthLayer = network->AddSpaceToDepthLayer(desc, layerName.c_str());
2309 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2310
2311 inputLayer->GetOutputSlot(0).Connect(spaceToDepthLayer->GetInputSlot(0));
2312 spaceToDepthLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2313
2314 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2315 spaceToDepthLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2316
2317 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2318 BOOST_CHECK(deserializedNetwork);
2319
2320 SpaceToDepthLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2321 deserializedNetwork->Accept(verifier);
2322}
2323
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002324BOOST_AUTO_TEST_CASE(SerializeSplitter)
2325{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002326 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Splitter)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002327
2328 const unsigned int numViews = 3;
2329 const unsigned int numDimensions = 4;
2330 const unsigned int inputShape[] = {1, 18, 4, 4};
2331 const unsigned int outputShape[] = {1, 6, 4, 4};
2332
2333 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
2334 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
2335 static_cast<unsigned int>(inputShape[1]),
2336 static_cast<unsigned int>(inputShape[2]),
2337 static_cast<unsigned int>(inputShape[3])};
2338 splitterDimSizes[1] /= numViews;
2339 armnn::ViewsDescriptor desc(numViews, numDimensions);
2340
2341 for (unsigned int g = 0; g < numViews; ++g)
2342 {
2343 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
2344
2345 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
2346 {
2347 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
2348 }
2349 }
2350
2351 const std::string layerName("splitter");
2352 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
2353 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
2354
2355 armnn::INetworkPtr network = armnn::INetwork::Create();
2356 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2357 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
2358 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2359 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2360 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
2361
2362 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
2363 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2364 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2365 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
2366
2367 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2368 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2369 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
2370 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2371
2372 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2373 BOOST_CHECK(deserializedNetwork);
2374
2375 SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
2376 deserializedNetwork->Accept(verifier);
2377}
2378
Matthew Jacksonb5433ee2019-07-11 15:54:20 +01002379BOOST_AUTO_TEST_CASE(SerializeStack)
2380{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002381 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(Stack)
Matthew Jacksonb5433ee2019-07-11 15:54:20 +01002382
2383 const std::string layerName("stack");
2384
2385 armnn::TensorInfo inputTensorInfo ({4, 3, 5}, armnn::DataType::Float32);
2386 armnn::TensorInfo outputTensorInfo({4, 3, 2, 5}, armnn::DataType::Float32);
2387
2388 armnn::StackDescriptor descriptor(2, 2, {4, 3, 5});
2389
2390 armnn::INetworkPtr network = armnn::INetwork::Create();
2391 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
2392 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
2393 armnn::IConnectableLayer* const stackLayer = network->AddStackLayer(descriptor, layerName.c_str());
2394 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2395
2396 inputLayer1->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(0));
2397 inputLayer2->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(1));
2398 stackLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2399
2400 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2401 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2402 stackLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2403
2404 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2405 BOOST_CHECK(deserializedNetwork);
2406
2407 StackLayerVerifier verifier(layerName, {inputTensorInfo, inputTensorInfo}, {outputTensorInfo}, descriptor);
2408 deserializedNetwork->Accept(verifier);
2409}
2410
Aron Virginas-Tar85121a22019-10-23 10:41:35 +01002411BOOST_AUTO_TEST_CASE(SerializeStandIn)
2412{
2413 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(StandIn)
2414
2415 const std::string layerName("standIn");
2416
2417 armnn::TensorInfo tensorInfo({ 1u }, armnn::DataType::Float32);
2418 armnn::StandInDescriptor descriptor(2u, 2u);
2419
2420 armnn::INetworkPtr network = armnn::INetwork::Create();
2421 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2422 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2423 armnn::IConnectableLayer* const standInLayer = network->AddStandInLayer(descriptor, layerName.c_str());
2424 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2425 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2426
2427 inputLayer0->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(0));
2428 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2429
2430 inputLayer1->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(1));
2431 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2432
2433 standInLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2434 standInLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2435
2436 standInLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2437 standInLayer->GetOutputSlot(1).SetTensorInfo(tensorInfo);
2438
2439 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2440 BOOST_CHECK(deserializedNetwork);
2441
2442 StandInLayerVerifier verifier(layerName, { tensorInfo, tensorInfo }, { tensorInfo, tensorInfo }, descriptor);
2443 deserializedNetwork->Accept(verifier);
2444}
2445
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002446BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
2447{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002448 DECLARE_LAYER_VERIFIER_CLASS_WITH_DESCRIPTOR(StridedSlice)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002449
2450 const std::string layerName("stridedSlice");
2451 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2452 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2453
2454 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2455 desc.m_EndMask = (1 << 4) - 1;
2456 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2457 desc.m_DataLayout = armnn::DataLayout::NCHW;
2458
2459 armnn::INetworkPtr network = armnn::INetwork::Create();
2460 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2461 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2462 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2463
2464 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2465 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2466
2467 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2468 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2469
2470 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2471 BOOST_CHECK(deserializedNetwork);
2472
2473 StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2474 deserializedNetwork->Accept(verifier);
2475}
2476
2477BOOST_AUTO_TEST_CASE(SerializeSubtraction)
2478{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002479 DECLARE_LAYER_VERIFIER_CLASS(Subtraction)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002480
2481 const std::string layerName("subtraction");
2482 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2483
2484 armnn::INetworkPtr network = armnn::INetwork::Create();
2485 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2486 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2487 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2488 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2489
2490 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2491 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2492 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2493
2494 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2495 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2496 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2497
2498 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2499 BOOST_CHECK(deserializedNetwork);
2500
2501 SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
2502 deserializedNetwork->Accept(verifier);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +00002503}
2504
Sadik Armaganeff363d2019-04-05 15:25:46 +01002505BOOST_AUTO_TEST_CASE(SerializeSwitch)
2506{
2507 class SwitchLayerVerifier : public LayerVerifierBase
2508 {
2509 public:
2510 SwitchLayerVerifier(const std::string& layerName,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002511 const std::vector<armnn::TensorInfo>& inputInfos,
2512 const std::vector<armnn::TensorInfo>& outputInfos)
Sadik Armaganeff363d2019-04-05 15:25:46 +01002513 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2514
2515 void VisitSwitchLayer(const armnn::IConnectableLayer* layer, const char* name) override
2516 {
2517 VerifyNameAndConnections(layer, name);
2518 }
2519
Derek Lamberti859f9ce2019-12-10 22:05:21 +00002520 void VisitConstantLayer(const armnn::IConnectableLayer*,
2521 const armnn::ConstTensor&,
2522 const char*) override {}
Sadik Armaganeff363d2019-04-05 15:25:46 +01002523 };
2524
2525 const std::string layerName("switch");
2526 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2527
2528 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2529 armnn::ConstTensor constTensor(info, constantData);
2530
2531 armnn::INetworkPtr network = armnn::INetwork::Create();
2532 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2533 armnn::IConnectableLayer* const constantLayer = network->AddConstantLayer(constTensor, "constant");
2534 armnn::IConnectableLayer* const switchLayer = network->AddSwitchLayer(layerName.c_str());
2535 armnn::IConnectableLayer* const trueOutputLayer = network->AddOutputLayer(0);
2536 armnn::IConnectableLayer* const falseOutputLayer = network->AddOutputLayer(1);
2537
2538 inputLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(0));
2539 constantLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(1));
2540 switchLayer->GetOutputSlot(0).Connect(trueOutputLayer->GetInputSlot(0));
2541 switchLayer->GetOutputSlot(1).Connect(falseOutputLayer->GetInputSlot(0));
2542
2543 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2544 constantLayer->GetOutputSlot(0).SetTensorInfo(info);
2545 switchLayer->GetOutputSlot(0).SetTensorInfo(info);
2546 switchLayer->GetOutputSlot(1).SetTensorInfo(info);
2547
2548 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2549 BOOST_CHECK(deserializedNetwork);
2550
2551 SwitchLayerVerifier verifier(layerName, {info, info}, {info, info});
2552 deserializedNetwork->Accept(verifier);
2553}
2554
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002555BOOST_AUTO_TEST_CASE(SerializeTransposeConvolution2d)
2556{
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002557 using Descriptor = armnn::TransposeConvolution2dDescriptor;
2558 class TransposeConvolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Descriptor>
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002559 {
2560 public:
2561 TransposeConvolution2dLayerVerifier(const std::string& layerName,
2562 const std::vector<armnn::TensorInfo>& inputInfos,
2563 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002564 const Descriptor& descriptor,
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002565 const armnn::ConstTensor& weights,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002566 const armnn::Optional<armnn::ConstTensor>& biases)
2567 : LayerVerifierBaseWithDescriptor<Descriptor>(layerName, inputInfos, outputInfos, descriptor)
2568 , m_Weights(weights)
2569 , m_Biases(biases)
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002570 {}
2571
2572 void VisitTransposeConvolution2dLayer(const armnn::IConnectableLayer* layer,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002573 const Descriptor& descriptor,
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002574 const armnn::ConstTensor& weights,
2575 const armnn::Optional<armnn::ConstTensor>& biases,
2576 const char* name) override
2577 {
2578 VerifyNameAndConnections(layer, name);
2579 VerifyDescriptor(descriptor);
2580
2581 // check weights
2582 CompareConstTensor(weights, m_Weights);
2583
2584 // check biases
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002585 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002586 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
2587
2588 if (biases.has_value() && m_Biases.has_value())
2589 {
2590 CompareConstTensor(biases.value(), m_Biases.value());
2591 }
2592 }
2593
2594 private:
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002595 armnn::ConstTensor m_Weights;
2596 armnn::Optional<armnn::ConstTensor> m_Biases;
2597 };
2598
2599 const std::string layerName("transposeConvolution2d");
2600 const armnn::TensorInfo inputInfo ({ 1, 7, 7, 1 }, armnn::DataType::Float32);
2601 const armnn::TensorInfo outputInfo({ 1, 9, 9, 1 }, armnn::DataType::Float32);
2602
2603 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
2604 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
2605
2606 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
2607 armnn::ConstTensor weights(weightsInfo, weightsData);
2608
2609 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
2610 armnn::ConstTensor biases(biasesInfo, biasesData);
2611
2612 armnn::TransposeConvolution2dDescriptor descriptor;
2613 descriptor.m_PadLeft = 1;
2614 descriptor.m_PadRight = 1;
2615 descriptor.m_PadTop = 1;
2616 descriptor.m_PadBottom = 1;
2617 descriptor.m_StrideX = 1;
2618 descriptor.m_StrideY = 1;
2619 descriptor.m_BiasEnabled = true;
2620 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
2621
2622 armnn::INetworkPtr network = armnn::INetwork::Create();
2623 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2624 armnn::IConnectableLayer* const convLayer =
2625 network->AddTransposeConvolution2dLayer(descriptor,
2626 weights,
2627 armnn::Optional<armnn::ConstTensor>(biases),
2628 layerName.c_str());
2629 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2630
2631 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
2632 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2633
2634 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2635 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2636
2637 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2638 BOOST_CHECK(deserializedNetwork);
2639
2640 TransposeConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
2641 deserializedNetwork->Accept(verifier);
2642}
2643
Sadik Armagandb059fd2019-03-20 12:28:32 +00002644BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
2645{
2646 class ConstantLayerVerifier : public LayerVerifierBase
2647 {
2648 public:
2649 ConstantLayerVerifier(const std::string& layerName,
2650 const std::vector<armnn::TensorInfo>& inputInfos,
2651 const std::vector<armnn::TensorInfo>& outputInfos,
2652 const armnn::ConstTensor& layerInput)
2653 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2654 , m_LayerInput(layerInput) {}
2655
2656 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2657 const armnn::ConstTensor& input,
2658 const char* name) override
2659 {
2660 VerifyNameAndConnections(layer, name);
Sadik Armagandb059fd2019-03-20 12:28:32 +00002661 CompareConstTensor(input, m_LayerInput);
2662 }
2663
Derek Lamberti859f9ce2019-12-10 22:05:21 +00002664 void VisitAdditionLayer(const armnn::IConnectableLayer*, const char*) override {}
Sadik Armagandb059fd2019-03-20 12:28:32 +00002665
2666 private:
2667 armnn::ConstTensor m_LayerInput;
2668 };
2669
2670 const std::string layerName("constant");
2671 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
2672
2673 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2674 armnn::ConstTensor constTensor(info, constantData);
2675
2676 armnn::INetworkPtr network(armnn::INetwork::Create());
2677 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2678 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2679 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2680 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2681
2682 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2683 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2684 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2685
2686 input->GetOutputSlot(0).SetTensorInfo(info);
2687 constant->GetOutputSlot(0).SetTensorInfo(info);
2688 add->GetOutputSlot(0).SetTensorInfo(info);
2689
2690 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2691 BOOST_CHECK(deserializedNetwork);
2692
2693 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
2694 deserializedNetwork->Accept(verifier);
2695}
2696
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002697class VerifyLstmLayer : public LayerVerifierBaseWithDescriptor<armnn::LstmDescriptor>
Jim Flynn11af3752019-03-19 17:22:29 +00002698{
2699public:
2700 VerifyLstmLayer(const std::string& layerName,
2701 const std::vector<armnn::TensorInfo>& inputInfos,
2702 const std::vector<armnn::TensorInfo>& outputInfos,
2703 const armnn::LstmDescriptor& descriptor,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002704 const armnn::LstmInputParams& inputParams)
2705 : LayerVerifierBaseWithDescriptor<armnn::LstmDescriptor>(layerName, inputInfos, outputInfos, descriptor)
2706 , m_InputParams(inputParams) {}
2707
Jim Flynn11af3752019-03-19 17:22:29 +00002708 void VisitLstmLayer(const armnn::IConnectableLayer* layer,
2709 const armnn::LstmDescriptor& descriptor,
2710 const armnn::LstmInputParams& params,
2711 const char* name)
2712 {
2713 VerifyNameAndConnections(layer, name);
2714 VerifyDescriptor(descriptor);
2715 VerifyInputParameters(params);
2716 }
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002717
Jim Flynn11af3752019-03-19 17:22:29 +00002718protected:
Jim Flynn11af3752019-03-19 17:22:29 +00002719 void VerifyInputParameters(const armnn::LstmInputParams& params)
2720 {
2721 VerifyConstTensors(
2722 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
2723 VerifyConstTensors(
2724 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
2725 VerifyConstTensors(
2726 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
2727 VerifyConstTensors(
2728 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
2729 VerifyConstTensors(
2730 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
2731 VerifyConstTensors(
2732 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
2733 VerifyConstTensors(
2734 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
2735 VerifyConstTensors(
2736 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
2737 VerifyConstTensors(
2738 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
2739 VerifyConstTensors(
2740 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
2741 VerifyConstTensors(
2742 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
2743 VerifyConstTensors(
2744 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
2745 VerifyConstTensors(
2746 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
2747 VerifyConstTensors(
2748 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
2749 VerifyConstTensors(
2750 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
2751 VerifyConstTensors(
2752 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
2753 VerifyConstTensors(
2754 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
Jan Eilersf8c62972019-07-17 11:07:49 +01002755 VerifyConstTensors(
2756 "m_InputLayerNormWeights", m_InputParams.m_InputLayerNormWeights, params.m_InputLayerNormWeights);
2757 VerifyConstTensors(
2758 "m_ForgetLayerNormWeights", m_InputParams.m_ForgetLayerNormWeights, params.m_ForgetLayerNormWeights);
2759 VerifyConstTensors(
2760 "m_CellLayerNormWeights", m_InputParams.m_CellLayerNormWeights, params.m_CellLayerNormWeights);
2761 VerifyConstTensors(
2762 "m_OutputLayerNormWeights", m_InputParams.m_OutputLayerNormWeights, params.m_OutputLayerNormWeights);
Jim Flynn11af3752019-03-19 17:22:29 +00002763 }
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01002764
Jim Flynn11af3752019-03-19 17:22:29 +00002765private:
Jim Flynn11af3752019-03-19 17:22:29 +00002766 armnn::LstmInputParams m_InputParams;
2767};
2768
2769BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
2770{
2771 armnn::LstmDescriptor descriptor;
2772 descriptor.m_ActivationFunc = 4;
2773 descriptor.m_ClippingThresProj = 0.0f;
2774 descriptor.m_ClippingThresCell = 0.0f;
2775 descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
2776 descriptor.m_ProjectionEnabled = false;
2777 descriptor.m_PeepholeEnabled = true;
2778
2779 const uint32_t batchSize = 1;
2780 const uint32_t inputSize = 2;
2781 const uint32_t numUnits = 4;
2782 const uint32_t outputSize = numUnits;
2783
2784 armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
2785 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2786 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
2787
2788 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2789 armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
2790
2791 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2792 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
2793
2794 armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
2795 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2796 armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
2797
2798 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2799 armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
2800
2801 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2802 armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
2803
2804 armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
2805 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2806 armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
2807
2808 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2809 armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
2810
2811 std::vector<float> forgetGateBiasData(numUnits, 1.0f);
2812 armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
2813
2814 std::vector<float> cellBiasData(numUnits, 0.0f);
2815 armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
2816
2817 std::vector<float> outputGateBiasData(numUnits, 0.0f);
2818 armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
2819
2820 armnn::LstmInputParams params;
2821 params.m_InputToForgetWeights = &inputToForgetWeights;
2822 params.m_InputToCellWeights = &inputToCellWeights;
2823 params.m_InputToOutputWeights = &inputToOutputWeights;
2824 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2825 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2826 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2827 params.m_ForgetGateBias = &forgetGateBias;
2828 params.m_CellBias = &cellBias;
2829 params.m_OutputGateBias = &outputGateBias;
2830 params.m_CellToForgetWeights = &cellToForgetWeights;
2831 params.m_CellToOutputWeights = &cellToOutputWeights;
2832
2833 armnn::INetworkPtr network = armnn::INetwork::Create();
2834 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2835 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2836 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2837 const std::string layerName("lstm");
2838 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2839 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2840 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2841 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2842 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2843
2844 // connect up
2845 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2846 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2847 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2848 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
2849
2850 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2851 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2852
2853 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2854 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2855
2856 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2857 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2858
2859 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2860 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2861
2862 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2863 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2864
2865 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2866 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2867
2868 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2869 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2870
2871 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2872 BOOST_CHECK(deserializedNetwork);
2873
2874 VerifyLstmLayer checker(
2875 layerName,
2876 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2877 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2878 descriptor,
2879 params);
2880 deserializedNetwork->Accept(checker);
2881}
2882
2883BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
2884{
2885 armnn::LstmDescriptor descriptor;
2886 descriptor.m_ActivationFunc = 4;
2887 descriptor.m_ClippingThresProj = 0.0f;
2888 descriptor.m_ClippingThresCell = 0.0f;
2889 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
2890 descriptor.m_ProjectionEnabled = true;
2891 descriptor.m_PeepholeEnabled = true;
2892
2893 const uint32_t batchSize = 2;
2894 const uint32_t inputSize = 5;
2895 const uint32_t numUnits = 20;
2896 const uint32_t outputSize = 16;
2897
2898 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
2899 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2900 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
2901
2902 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2903 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
2904
2905 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2906 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
2907
2908 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2909 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
2910
2911 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
2912 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2913 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
2914
2915 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2916 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
2917
2918 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2919 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
2920
2921 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2922 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
2923
2924 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
2925 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2926 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
2927
2928 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2929 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
2930
2931 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2932 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
2933
2934 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2935 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
2936
2937 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2938 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
2939
2940 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2941 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
2942
2943 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2944 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
2945
2946 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
2947 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
2948 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
2949
2950 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
2951 std::vector<float> projectionBiasData(outputSize, 0.f);
2952 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
2953
2954 armnn::LstmInputParams params;
2955 params.m_InputToForgetWeights = &inputToForgetWeights;
2956 params.m_InputToCellWeights = &inputToCellWeights;
2957 params.m_InputToOutputWeights = &inputToOutputWeights;
2958 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2959 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2960 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2961 params.m_ForgetGateBias = &forgetGateBias;
2962 params.m_CellBias = &cellBias;
2963 params.m_OutputGateBias = &outputGateBias;
2964
2965 // additional params because: descriptor.m_CifgEnabled = false
2966 params.m_InputToInputWeights = &inputToInputWeights;
2967 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
2968 params.m_CellToInputWeights = &cellToInputWeights;
2969 params.m_InputGateBias = &inputGateBias;
2970
2971 // additional params because: descriptor.m_ProjectionEnabled = true
2972 params.m_ProjectionWeights = &projectionWeights;
2973 params.m_ProjectionBias = &projectionBias;
2974
2975 // additional params because: descriptor.m_PeepholeEnabled = true
2976 params.m_CellToForgetWeights = &cellToForgetWeights;
2977 params.m_CellToOutputWeights = &cellToOutputWeights;
2978
2979 armnn::INetworkPtr network = armnn::INetwork::Create();
2980 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2981 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2982 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2983 const std::string layerName("lstm");
2984 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2985 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2986 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2987 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2988 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2989
2990 // connect up
2991 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2992 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2993 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2994 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
2995
2996 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2997 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2998
2999 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3000 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3001
3002 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3003 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3004
3005 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3006 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3007
3008 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3009 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3010
3011 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3012 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3013
3014 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3015 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3016
3017 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3018 BOOST_CHECK(deserializedNetwork);
3019
3020 VerifyLstmLayer checker(
3021 layerName,
3022 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3023 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3024 descriptor,
3025 params);
3026 deserializedNetwork->Accept(checker);
3027}
3028
Jan Eilersf8c62972019-07-17 11:07:49 +01003029BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeWithProjectionWithLayerNorm)
3030{
3031 armnn::LstmDescriptor descriptor;
3032 descriptor.m_ActivationFunc = 4;
3033 descriptor.m_ClippingThresProj = 0.0f;
3034 descriptor.m_ClippingThresCell = 0.0f;
3035 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
3036 descriptor.m_ProjectionEnabled = true;
3037 descriptor.m_PeepholeEnabled = true;
3038 descriptor.m_LayerNormEnabled = true;
3039
3040 const uint32_t batchSize = 2;
3041 const uint32_t inputSize = 5;
3042 const uint32_t numUnits = 20;
3043 const uint32_t outputSize = 16;
3044
3045 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3046 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3047 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3048
3049 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3050 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3051
3052 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3053 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3054
3055 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3056 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3057
3058 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3059 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3060 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3061
3062 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3063 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3064
3065 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3066 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3067
3068 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3069 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3070
3071 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3072 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3073 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3074
3075 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3076 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3077
3078 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3079 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3080
3081 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3082 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3083
3084 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3085 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3086
3087 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3088 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3089
3090 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3091 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3092
3093 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3094 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
3095 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3096
3097 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3098 std::vector<float> projectionBiasData(outputSize, 0.f);
3099 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3100
3101 std::vector<float> inputLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3102 armnn::ConstTensor inputLayerNormWeights(tensorInfo20, forgetGateBiasData);
3103
3104 std::vector<float> forgetLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3105 armnn::ConstTensor forgetLayerNormWeights(tensorInfo20, forgetGateBiasData);
3106
3107 std::vector<float> cellLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3108 armnn::ConstTensor cellLayerNormWeights(tensorInfo20, forgetGateBiasData);
3109
3110 std::vector<float> outLayerNormWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3111 armnn::ConstTensor outLayerNormWeights(tensorInfo20, forgetGateBiasData);
3112
3113 armnn::LstmInputParams params;
3114 params.m_InputToForgetWeights = &inputToForgetWeights;
3115 params.m_InputToCellWeights = &inputToCellWeights;
3116 params.m_InputToOutputWeights = &inputToOutputWeights;
3117 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3118 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3119 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3120 params.m_ForgetGateBias = &forgetGateBias;
3121 params.m_CellBias = &cellBias;
3122 params.m_OutputGateBias = &outputGateBias;
3123
3124 // additional params because: descriptor.m_CifgEnabled = false
3125 params.m_InputToInputWeights = &inputToInputWeights;
3126 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3127 params.m_CellToInputWeights = &cellToInputWeights;
3128 params.m_InputGateBias = &inputGateBias;
3129
3130 // additional params because: descriptor.m_ProjectionEnabled = true
3131 params.m_ProjectionWeights = &projectionWeights;
3132 params.m_ProjectionBias = &projectionBias;
3133
3134 // additional params because: descriptor.m_PeepholeEnabled = true
3135 params.m_CellToForgetWeights = &cellToForgetWeights;
3136 params.m_CellToOutputWeights = &cellToOutputWeights;
3137
3138 // additional params because: despriptor.m_LayerNormEnabled = true
3139 params.m_InputLayerNormWeights = &inputLayerNormWeights;
3140 params.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
3141 params.m_CellLayerNormWeights = &cellLayerNormWeights;
3142 params.m_OutputLayerNormWeights = &outLayerNormWeights;
3143
3144 armnn::INetworkPtr network = armnn::INetwork::Create();
3145 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3146 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3147 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3148 const std::string layerName("lstm");
3149 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3150 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3151 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3152 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3153 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3154
3155 // connect up
3156 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3157 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3158 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3159 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3160
3161 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3162 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3163
3164 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3165 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3166
3167 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3168 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3169
3170 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3171 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3172
3173 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3174 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3175
3176 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3177 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3178
3179 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3180 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3181
3182 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3183 BOOST_CHECK(deserializedNetwork);
3184
3185 VerifyLstmLayer checker(
3186 layerName,
3187 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3188 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3189 descriptor,
3190 params);
3191 deserializedNetwork->Accept(checker);
3192}
3193
3194BOOST_AUTO_TEST_CASE(EnsureLstmLayersBackwardCompatibility)
3195{
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003196 // The hex data below is a flat buffer containing a lstm layer with no Cifg, with peephole and projection
3197 // enabled. That data was obtained before additional layer normalization parameters where added to the
3198 // lstm serializer. That way it can be tested if a lstm model with the old parameter configuration can
3199 // still be loaded
3200 const std::vector<uint8_t> lstmNoCifgWithPeepholeAndProjectionModel =
Jan Eilersf8c62972019-07-17 11:07:49 +01003201 {
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003202 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
3203 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
3204 0xDC, 0x29, 0x00, 0x00, 0x38, 0x29, 0x00, 0x00, 0xB4, 0x28, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x3C, 0x01,
3205 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
3206 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
3207 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x70, 0xD6, 0xFF, 0xFF,
3208 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x06, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x88, 0xD7,
3209 0xFF, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF6, 0xD6, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,
3210 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
3211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3212 0xE8, 0xD7, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xC8, 0xD6, 0xFF, 0xFF, 0x00, 0x00,
3213 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x5E, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xE0, 0xD7, 0xFF, 0xFF,
3214 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4E, 0xD7, 0xFF, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
3215 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3216 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xD8,
3217 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
3218 0x04, 0x00, 0x00, 0x00, 0xB6, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x38, 0xD8, 0xFF, 0xFF, 0x08, 0x00,
3219 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA6, 0xD7, 0xFF, 0xFF, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3220 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3221 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xD8, 0xFF, 0xFF,
3222 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00,
3223 0x00, 0x00, 0x0E, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x16, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
3224 0xFA, 0xD7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00,
3225 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3226 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xD8, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
3227 0x00, 0x00, 0x6C, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
3228 0x12, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xE0, 0x25, 0x00, 0x00, 0xD0, 0x25,
3229 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x48, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00,
3230 0x10, 0x00, 0x14, 0x00, 0x18, 0x00, 0x1C, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2C, 0x00, 0x30, 0x00,
3231 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x40, 0x00, 0x44, 0x00, 0x26, 0x00, 0x00, 0x00, 0xC4, 0x23, 0x00, 0x00,
3232 0xF8, 0x21, 0x00, 0x00, 0x2C, 0x20, 0x00, 0x00, 0xF0, 0x1A, 0x00, 0x00, 0xB4, 0x15, 0x00, 0x00, 0x78, 0x10,
3233 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x68, 0x0F, 0x00, 0x00, 0xE0, 0x0E, 0x00, 0x00, 0x14, 0x0D, 0x00, 0x00,
3234 0xD8, 0x07, 0x00, 0x00, 0x50, 0x07, 0x00, 0x00, 0xC8, 0x06, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x14, 0x01,
3235 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xEE, 0xD7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3236 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFE, 0xD8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00,
3237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3242 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x72, 0xD8,
3243 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x82, 0xD9, 0xFF, 0xFF,
3244 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xD8,
3249 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3250 0x14, 0x00, 0x00, 0x00, 0xF6, 0xD8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x54, 0x00, 0x00, 0x00, 0x04, 0x00,
3251 0x00, 0x00, 0x06, 0xDA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xD9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3256 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6A, 0xD9, 0xFF, 0xFF, 0x00, 0x00,
3257 0x00, 0x03, 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7A, 0xDA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
3258 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3305 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3328 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xDE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3330 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xA2, 0xDE,
3331 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB2, 0xDF, 0xFF, 0xFF,
3332 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xDF,
3337 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3338 0x14, 0x00, 0x00, 0x00, 0x26, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00,
3339 0x00, 0x00, 0x36, 0xE0, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3344 0x00, 0x00, 0x00, 0x00, 0x92, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3345 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xAA, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3346 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xBA, 0xE0, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01,
3347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3381 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3387 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3399 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3407 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3418 0x00, 0x00, 0x00, 0x00, 0xC6, 0xE4, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3419 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xE2, 0xE4, 0xFF, 0xFF,
3420 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xE5, 0xFF, 0xFF, 0x04, 0x00,
3421 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xE6, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3444 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00,
3445 0x00, 0x00, 0xAA, 0xE6, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3446 0xBA, 0xE7, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3451 0x00, 0x00, 0x16, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3452 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x2E, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00,
3453 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3E, 0xE8, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
3454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xE7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xB2, 0xE7, 0xFF, 0xFF,
3460 0x00, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC2, 0xE8, 0xFF, 0xFF, 0x04, 0x00,
3461 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xE8, 0xFF, 0xFF,
3466 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00,
3467 0x00, 0x00, 0x36, 0xE8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3468 0x46, 0xE9, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3500 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3501 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xED, 0xFF, 0xFF,
3540 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00,
3541 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6E, 0xED, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x14, 0x05, 0x00, 0x00,
3542 0x04, 0x00, 0x00, 0x00, 0x7E, 0xEE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00,
3543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3614 0x8A, 0xF2, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3615 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xA6, 0xF2, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
3616 0x14, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB6, 0xF3, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x40, 0x01,
3617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3673 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3675 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3680 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3688 0x00, 0x00, 0x00, 0x00, 0xC2, 0xF7, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3689 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xDE, 0xF7, 0xFF, 0xFF,
3690 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xEE, 0xF8, 0xFF, 0xFF, 0x04, 0x00,
3691 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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,
3712 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, 0x8A, 0xF9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
3714 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00,
3715 0x00, 0x00, 0xA6, 0xF9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3716 0xB6, 0xFA, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3721 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3733 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3736 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,
3738 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xFB,
3739 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
3740 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x6E, 0xFB, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xA4, 0x01,
3741 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7E, 0xFC, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
3742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3750 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3752 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3754 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3755 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3757 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3758 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3759 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3760 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3761 0x00, 0x00, 0x00, 0x00, 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,
3763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3764 0x00, 0x00, 0x00, 0x00, 0x1A, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3765 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0C, 0x00,
3766 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
3767 0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x2E, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3768 0x22, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6C, 0x73,
3769 0x74, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x00,
3770 0xB4, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x30, 0x00,
3771 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3772 0xA6, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3773 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3C, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
3774 0x04, 0x00, 0x00, 0x00, 0xCE, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3775 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x64, 0xFF, 0xFF, 0xFF,
3776 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3778 0xB4, 0xFE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x1A, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3779 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
3780 0xF0, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
3781 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
3782 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3783 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00,
3784 0x7E, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00,
3785 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x76, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
3786 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
3787 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3788 0x68, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0xCE, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00,
3789 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3790 0x08, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00,
3791 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
3792 0x08, 0x00, 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00,
3793 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00,
3794 0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
3795 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3796 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
3797 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6E, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
3798 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00,
3799 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00,
3800 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00,
3801 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
3802 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00,
3803 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3804 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
3805 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00,
3806 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3807 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00
3808 };
3809
3810 armnn::INetworkPtr deserializedNetwork =
3811 DeserializeNetwork(std::string(lstmNoCifgWithPeepholeAndProjectionModel.begin(),
3812 lstmNoCifgWithPeepholeAndProjectionModel.end()));
3813
Jan Eilersf8c62972019-07-17 11:07:49 +01003814 BOOST_CHECK(deserializedNetwork);
3815
3816 // generating the same model parameters which where used to serialize the model (Layer norm is not specified)
3817 armnn::LstmDescriptor descriptor;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003818 descriptor.m_ActivationFunc = 4;
Jan Eilersf8c62972019-07-17 11:07:49 +01003819 descriptor.m_ClippingThresProj = 0.0f;
3820 descriptor.m_ClippingThresCell = 0.0f;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003821 descriptor.m_CifgEnabled = false;
Jan Eilersf8c62972019-07-17 11:07:49 +01003822 descriptor.m_ProjectionEnabled = true;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003823 descriptor.m_PeepholeEnabled = true;
Jan Eilersf8c62972019-07-17 11:07:49 +01003824
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003825 const uint32_t batchSize = 2u;
3826 const uint32_t inputSize = 5u;
3827 const uint32_t numUnits = 20u;
3828 const uint32_t outputSize = 16u;
Jan Eilersf8c62972019-07-17 11:07:49 +01003829
3830 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
3831 std::vector<float> inputToInputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3832 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
3833
3834 std::vector<float> inputToForgetWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3835 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3836
3837 std::vector<float> inputToCellWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3838 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3839
3840 std::vector<float> inputToOutputWeightsData(tensorInfo20x5.GetNumElements(), 0.0f);
3841 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3842
3843 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3844 std::vector<float> inputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3845 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3846
3847 std::vector<float> forgetGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3848 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3849
3850 std::vector<float> cellBiasData(tensorInfo20.GetNumElements(), 0.0f);
3851 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3852
3853 std::vector<float> outputGateBiasData(tensorInfo20.GetNumElements(), 0.0f);
3854 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3855
3856 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3857 std::vector<float> recurrentToInputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3858 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3859
3860 std::vector<float> recurrentToForgetWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3861 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3862
3863 std::vector<float> recurrentToCellWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3864 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3865
3866 std::vector<float> recurrentToOutputWeightsData(tensorInfo20x16.GetNumElements(), 0.0f);
3867 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3868
3869 std::vector<float> cellToInputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
3870 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3871
3872 std::vector<float> cellToForgetWeightsData(tensorInfo20.GetNumElements(), 0.0f);
3873 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3874
3875 std::vector<float> cellToOutputWeightsData(tensorInfo20.GetNumElements(), 0.0f);
3876 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3877
3878 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3879 std::vector<float> projectionWeightsData(tensorInfo16x20.GetNumElements(), 0.0f);
3880 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3881
3882 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3883 std::vector<float> projectionBiasData(outputSize, 0.0f);
3884 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3885
3886 armnn::LstmInputParams params;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003887 params.m_InputToForgetWeights = &inputToForgetWeights;
3888 params.m_InputToCellWeights = &inputToCellWeights;
3889 params.m_InputToOutputWeights = &inputToOutputWeights;
Jan Eilersf8c62972019-07-17 11:07:49 +01003890 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003891 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
Jan Eilersf8c62972019-07-17 11:07:49 +01003892 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003893 params.m_ForgetGateBias = &forgetGateBias;
3894 params.m_CellBias = &cellBias;
3895 params.m_OutputGateBias = &outputGateBias;
Jan Eilersf8c62972019-07-17 11:07:49 +01003896
3897 // additional params because: descriptor.m_CifgEnabled = false
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003898 params.m_InputToInputWeights = &inputToInputWeights;
3899 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3900 params.m_CellToInputWeights = &cellToInputWeights;
3901 params.m_InputGateBias = &inputGateBias;
Jan Eilersf8c62972019-07-17 11:07:49 +01003902
3903 // additional params because: descriptor.m_ProjectionEnabled = true
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003904 params.m_ProjectionWeights = &projectionWeights;
3905 params.m_ProjectionBias = &projectionBias;
Jan Eilersf8c62972019-07-17 11:07:49 +01003906
3907 // additional params because: descriptor.m_PeepholeEnabled = true
Aron Virginas-Tar6e0d9622019-10-22 16:24:48 +01003908 params.m_CellToForgetWeights = &cellToForgetWeights;
3909 params.m_CellToOutputWeights = &cellToOutputWeights;
Jan Eilersf8c62972019-07-17 11:07:49 +01003910
3911 const std::string layerName("lstm");
3912 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3913 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3914 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3915 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3916
Jan Eilersf8c62972019-07-17 11:07:49 +01003917 VerifyLstmLayer checker(
3918 layerName,
3919 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3920 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3921 descriptor,
3922 params);
3923 deserializedNetwork->Accept(checker);
3924}
Jan Eilers5b01a892019-07-23 09:47:43 +01003925class VerifyQuantizedLstmLayer : public LayerVerifierBase
3926{
3927
3928public:
3929 VerifyQuantizedLstmLayer(const std::string& layerName,
3930 const std::vector<armnn::TensorInfo>& inputInfos,
3931 const std::vector<armnn::TensorInfo>& outputInfos,
Aron Virginas-Tare80ebd12019-10-17 16:11:54 +01003932 const armnn::QuantizedLstmInputParams& inputParams)
3933 : LayerVerifierBase(layerName, inputInfos, outputInfos), m_InputParams(inputParams) {}
Jan Eilers5b01a892019-07-23 09:47:43 +01003934
3935 void VisitQuantizedLstmLayer(const armnn::IConnectableLayer* layer,
3936 const armnn::QuantizedLstmInputParams& params,
3937 const char* name)
3938 {
3939 VerifyNameAndConnections(layer, name);
3940 VerifyInputParameters(params);
3941 }
3942
3943protected:
3944 void VerifyInputParameters(const armnn::QuantizedLstmInputParams& params)
3945 {
3946 VerifyConstTensors("m_InputToInputWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003947 m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003948 VerifyConstTensors("m_InputToForgetWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003949 m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003950 VerifyConstTensors("m_InputToCellWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003951 m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003952 VerifyConstTensors("m_InputToOutputWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003953 m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003954 VerifyConstTensors("m_RecurrentToInputWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003955 m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003956 VerifyConstTensors("m_RecurrentToForgetWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003957 m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003958 VerifyConstTensors("m_RecurrentToCellWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003959 m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003960 VerifyConstTensors("m_RecurrentToOutputWeights",
alanhsu567886324fc2019-10-25 23:44:16 +08003961 m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
Jan Eilers5b01a892019-07-23 09:47:43 +01003962 VerifyConstTensors("m_InputGateBias",
alanhsu567886324fc2019-10-25 23:44:16 +08003963 m_InputParams.m_InputGateBias, params.m_InputGateBias);
Jan Eilers5b01a892019-07-23 09:47:43 +01003964 VerifyConstTensors("m_ForgetGateBias",
alanhsu567886324fc2019-10-25 23:44:16 +08003965 m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
Jan Eilers5b01a892019-07-23 09:47:43 +01003966 VerifyConstTensors("m_CellBias",
alanhsu567886324fc2019-10-25 23:44:16 +08003967 m_InputParams.m_CellBias, params.m_CellBias);
Jan Eilers5b01a892019-07-23 09:47:43 +01003968 VerifyConstTensors("m_OutputGateBias",
alanhsu567886324fc2019-10-25 23:44:16 +08003969 m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
Jan Eilers5b01a892019-07-23 09:47:43 +01003970 }
3971
3972private:
3973 armnn::QuantizedLstmInputParams m_InputParams;
3974};
3975
3976BOOST_AUTO_TEST_CASE(SerializeDeserializeQuantizedLstm)
3977{
3978 const uint32_t batchSize = 1;
3979 const uint32_t inputSize = 2;
3980 const uint32_t numUnits = 4;
3981 const uint32_t outputSize = numUnits;
3982
alanhsu567886324fc2019-10-25 23:44:16 +08003983 // Scale/Offset for input/output, cellState In/Out, weights, bias
3984 float inputOutputScale = 0.0078125f;
3985 int32_t inputOutputOffset = 128;
Jan Eilers5b01a892019-07-23 09:47:43 +01003986
alanhsu567886324fc2019-10-25 23:44:16 +08003987 float cellStateScale = 0.00048828125f;
3988 int32_t cellStateOffset = 0;
Jan Eilers5b01a892019-07-23 09:47:43 +01003989
alanhsu567886324fc2019-10-25 23:44:16 +08003990 float weightsScale = 0.00408021f;
3991 int32_t weightsOffset = 100;
Jan Eilers5b01a892019-07-23 09:47:43 +01003992
alanhsu567886324fc2019-10-25 23:44:16 +08003993 float biasScale = 3.1876640625e-05f;
3994 int32_t biasOffset = 0;
Jan Eilers5b01a892019-07-23 09:47:43 +01003995
alanhsu567886324fc2019-10-25 23:44:16 +08003996 // The shape of weight data is {outputSize, inputSize} = {4, 2}
3997 armnn::TensorShape inputToInputWeightsShape = {4, 2};
3998 std::vector<uint8_t> inputToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
3999 armnn::TensorInfo inputToInputWeightsInfo(inputToInputWeightsShape,
Derek Lambertif90c56d2020-01-10 17:14:08 +00004000 armnn::DataType::QAsymmU8,
alanhsu567886324fc2019-10-25 23:44:16 +08004001 weightsScale,
4002 weightsOffset);
4003 armnn::ConstTensor inputToInputWeights(inputToInputWeightsInfo, inputToInputWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004004
alanhsu567886324fc2019-10-25 23:44:16 +08004005 armnn::TensorShape inputToForgetWeightsShape = {4, 2};
4006 std::vector<uint8_t> inputToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4007 armnn::TensorInfo inputToForgetWeightsInfo(inputToForgetWeightsShape,
Derek Lambertif90c56d2020-01-10 17:14:08 +00004008 armnn::DataType::QAsymmU8,
alanhsu567886324fc2019-10-25 23:44:16 +08004009 weightsScale,
4010 weightsOffset);
4011 armnn::ConstTensor inputToForgetWeights(inputToForgetWeightsInfo, inputToForgetWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004012
alanhsu567886324fc2019-10-25 23:44:16 +08004013 armnn::TensorShape inputToCellWeightsShape = {4, 2};
4014 std::vector<uint8_t> inputToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4015 armnn::TensorInfo inputToCellWeightsInfo(inputToCellWeightsShape,
Derek Lambertif90c56d2020-01-10 17:14:08 +00004016 armnn::DataType::QAsymmU8,
alanhsu567886324fc2019-10-25 23:44:16 +08004017 weightsScale,
4018 weightsOffset);
4019 armnn::ConstTensor inputToCellWeights(inputToCellWeightsInfo, inputToCellWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004020
alanhsu567886324fc2019-10-25 23:44:16 +08004021 armnn::TensorShape inputToOutputWeightsShape = {4, 2};
4022 std::vector<uint8_t> inputToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8};
4023 armnn::TensorInfo inputToOutputWeightsInfo(inputToOutputWeightsShape,
Derek Lambertif90c56d2020-01-10 17:14:08 +00004024 armnn::DataType::QAsymmU8,
alanhsu567886324fc2019-10-25 23:44:16 +08004025 weightsScale,
4026 weightsOffset);
4027 armnn::ConstTensor inputToOutputWeights(inputToOutputWeightsInfo, inputToOutputWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004028
alanhsu567886324fc2019-10-25 23:44:16 +08004029 // The shape of recurrent weight data is {outputSize, outputSize} = {4, 4}
4030 armnn::TensorShape recurrentToInputWeightsShape = {4, 4};
4031 std::vector<uint8_t> recurrentToInputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4032 armnn::TensorInfo recurrentToInputWeightsInfo(recurrentToInputWeightsShape,
Derek Lambertif90c56d2020-01-10 17:14:08 +00004033 armnn::DataType::QAsymmU8,
alanhsu567886324fc2019-10-25 23:44:16 +08004034 weightsScale,
4035 weightsOffset);
4036 armnn::ConstTensor recurrentToInputWeights(recurrentToInputWeightsInfo, recurrentToInputWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004037
alanhsu567886324fc2019-10-25 23:44:16 +08004038 armnn::TensorShape recurrentToForgetWeightsShape = {4, 4};
4039 std::vector<uint8_t> recurrentToForgetWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4040 armnn::TensorInfo recurrentToForgetWeightsInfo(recurrentToForgetWeightsShape,
Derek Lambertif90c56d2020-01-10 17:14:08 +00004041 armnn::DataType::QAsymmU8,
alanhsu567886324fc2019-10-25 23:44:16 +08004042 weightsScale,
4043 weightsOffset);
4044 armnn::ConstTensor recurrentToForgetWeights(recurrentToForgetWeightsInfo, recurrentToForgetWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004045
alanhsu567886324fc2019-10-25 23:44:16 +08004046 armnn::TensorShape recurrentToCellWeightsShape = {4, 4};
4047 std::vector<uint8_t> recurrentToCellWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4048 armnn::TensorInfo recurrentToCellWeightsInfo(recurrentToCellWeightsShape,
Derek Lambertif90c56d2020-01-10 17:14:08 +00004049 armnn::DataType::QAsymmU8,
alanhsu567886324fc2019-10-25 23:44:16 +08004050 weightsScale,
4051 weightsOffset);
4052 armnn::ConstTensor recurrentToCellWeights(recurrentToCellWeightsInfo, recurrentToCellWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004053
alanhsu567886324fc2019-10-25 23:44:16 +08004054 armnn::TensorShape recurrentToOutputWeightsShape = {4, 4};
4055 std::vector<uint8_t> recurrentToOutputWeightsData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4056 armnn::TensorInfo recurrentToOutputWeightsInfo(recurrentToOutputWeightsShape,
Derek Lambertif90c56d2020-01-10 17:14:08 +00004057 armnn::DataType::QAsymmU8,
alanhsu567886324fc2019-10-25 23:44:16 +08004058 weightsScale,
4059 weightsOffset);
4060 armnn::ConstTensor recurrentToOutputWeights(recurrentToOutputWeightsInfo, recurrentToOutputWeightsData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004061
alanhsu567886324fc2019-10-25 23:44:16 +08004062 // The shape of bias data is {outputSize} = {4}
4063 armnn::TensorShape inputGateBiasShape = {4};
4064 std::vector<int32_t> inputGateBiasData = {1, 2, 3, 4};
4065 armnn::TensorInfo inputGateBiasInfo(inputGateBiasShape,
4066 armnn::DataType::Signed32,
4067 biasScale,
4068 biasOffset);
4069 armnn::ConstTensor inputGateBias(inputGateBiasInfo, inputGateBiasData);
4070
4071 armnn::TensorShape forgetGateBiasShape = {4};
4072 std::vector<int32_t> forgetGateBiasData = {1, 2, 3, 4};
4073 armnn::TensorInfo forgetGateBiasInfo(forgetGateBiasShape,
4074 armnn::DataType::Signed32,
4075 biasScale,
4076 biasOffset);
4077 armnn::ConstTensor forgetGateBias(forgetGateBiasInfo, forgetGateBiasData);
4078
4079 armnn::TensorShape cellBiasShape = {4};
4080 std::vector<int32_t> cellBiasData = {1, 2, 3, 4};
4081 armnn::TensorInfo cellBiasInfo(cellBiasShape,
4082 armnn::DataType::Signed32,
4083 biasScale,
4084 biasOffset);
4085 armnn::ConstTensor cellBias(cellBiasInfo, cellBiasData);
4086
4087 armnn::TensorShape outputGateBiasShape = {4};
4088 std::vector<int32_t> outputGateBiasData = {1, 2, 3, 4};
4089 armnn::TensorInfo outputGateBiasInfo(outputGateBiasShape,
4090 armnn::DataType::Signed32,
4091 biasScale,
4092 biasOffset);
4093 armnn::ConstTensor outputGateBias(outputGateBiasInfo, outputGateBiasData);
Jan Eilers5b01a892019-07-23 09:47:43 +01004094
4095 armnn::QuantizedLstmInputParams params;
4096 params.m_InputToInputWeights = &inputToInputWeights;
4097 params.m_InputToForgetWeights = &inputToForgetWeights;
4098 params.m_InputToCellWeights = &inputToCellWeights;
4099 params.m_InputToOutputWeights = &inputToOutputWeights;
4100 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
4101 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
4102 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
4103 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
4104 params.m_InputGateBias = &inputGateBias;
4105 params.m_ForgetGateBias = &forgetGateBias;
4106 params.m_CellBias = &cellBias;
4107 params.m_OutputGateBias = &outputGateBias;
4108
4109 armnn::INetworkPtr network = armnn::INetwork::Create();
alanhsu567886324fc2019-10-25 23:44:16 +08004110 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
Jan Eilers5b01a892019-07-23 09:47:43 +01004111 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
4112 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
4113 const std::string layerName("QuantizedLstm");
4114 armnn::IConnectableLayer* const quantizedLstmLayer = network->AddQuantizedLstmLayer(params, layerName.c_str());
alanhsu567886324fc2019-10-25 23:44:16 +08004115 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(0);
4116 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(1);
Jan Eilers5b01a892019-07-23 09:47:43 +01004117
alanhsu567886324fc2019-10-25 23:44:16 +08004118 // Connect up
4119 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize },
Derek Lambertif90c56d2020-01-10 17:14:08 +00004120 armnn::DataType::QAsymmU8,
alanhsu567886324fc2019-10-25 23:44:16 +08004121 inputOutputScale,
4122 inputOutputOffset);
4123 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits },
Derek Lambertif90c56d2020-01-10 17:14:08 +00004124 armnn::DataType::QSymmS16,
alanhsu567886324fc2019-10-25 23:44:16 +08004125 cellStateScale,
4126 cellStateOffset);
4127 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize },
Derek Lambertif90c56d2020-01-10 17:14:08 +00004128 armnn::DataType::QAsymmU8,
alanhsu567886324fc2019-10-25 23:44:16 +08004129 inputOutputScale,
4130 inputOutputOffset);
Jan Eilers5b01a892019-07-23 09:47:43 +01004131
4132 inputLayer->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(0));
4133 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
4134
4135 cellStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(1));
4136 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
4137
4138 outputStateIn->GetOutputSlot(0).Connect(quantizedLstmLayer->GetInputSlot(2));
4139 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
4140
4141 quantizedLstmLayer->GetOutputSlot(0).Connect(cellStateOut->GetInputSlot(0));
4142 quantizedLstmLayer->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
4143
4144 quantizedLstmLayer->GetOutputSlot(1).Connect(outputLayer->GetInputSlot(0));
4145 quantizedLstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
4146
4147 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
4148 BOOST_CHECK(deserializedNetwork);
4149
alanhsu567886324fc2019-10-25 23:44:16 +08004150 VerifyQuantizedLstmLayer checker(layerName,
4151 {inputTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
4152 {cellStateTensorInfo, outputStateTensorInfo},
4153 params);
Jan Eilers5b01a892019-07-23 09:47:43 +01004154
4155 deserializedNetwork->Accept(checker);
4156}
4157
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00004158BOOST_AUTO_TEST_SUITE_END()