blob: e51f76bd336b54d751b6475a2151ffe39b402686 [file] [log] [blame]
Mike Kelly8c1701a2019-02-11 17:01:27 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
Mike Kelly8c1701a2019-02-11 17:01:27 +00006#include "../Serializer.hpp"
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +00007
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00008#include <armnn/ArmNN.hpp>
9#include <armnn/INetwork.hpp>
Derek Lamberti0028d1b2019-02-20 13:57:42 +000010#include <armnnDeserializer/IDeserializer.hpp>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000011
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +000012#include <random>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000013#include <vector>
14
Mike Kelly8c1701a2019-02-11 17:01:27 +000015#include <boost/test/unit_test.hpp>
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +000016
Derek Lamberti0028d1b2019-02-20 13:57:42 +000017using armnnDeserializer::IDeserializer;
Mike Kelly8c1701a2019-02-11 17:01:27 +000018
Saoirse Stewart3166c3e2019-02-18 15:24:53 +000019namespace
20{
21
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000022struct DefaultLayerVerifierPolicy
23{
Les Belle0ca8612019-05-17 16:17:12 +010024 static void Apply(const std::string s = "")
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000025 {
26 BOOST_TEST_MESSAGE("Unexpected layer found in network");
27 BOOST_TEST(false);
28 }
29};
30
31class LayerVerifierBase : public armnn::LayerVisitorBase<DefaultLayerVerifierPolicy>
32{
33public:
34 LayerVerifierBase(const std::string& layerName,
35 const std::vector<armnn::TensorInfo>& inputInfos,
36 const std::vector<armnn::TensorInfo>& outputInfos)
37 : m_LayerName(layerName)
38 , m_InputTensorInfos(inputInfos)
39 , m_OutputTensorInfos(outputInfos) {}
40
41 void VisitInputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId, const char*) override {}
42
43 void VisitOutputLayer(const armnn::IConnectableLayer*, armnn::LayerBindingId id, const char*) override {}
44
45protected:
46 void VerifyNameAndConnections(const armnn::IConnectableLayer* layer, const char* name)
47 {
48 BOOST_TEST(name == m_LayerName.c_str());
49
50 BOOST_TEST(layer->GetNumInputSlots() == m_InputTensorInfos.size());
51 BOOST_TEST(layer->GetNumOutputSlots() == m_OutputTensorInfos.size());
52
53 for (unsigned int i = 0; i < m_InputTensorInfos.size(); i++)
54 {
55 const armnn::IOutputSlot* connectedOutput = layer->GetInputSlot(i).GetConnection();
56 BOOST_CHECK(connectedOutput);
57
58 const armnn::TensorInfo& connectedInfo = connectedOutput->GetTensorInfo();
59 BOOST_TEST(connectedInfo.GetShape() == m_InputTensorInfos[i].GetShape());
60 BOOST_TEST(
61 GetDataTypeName(connectedInfo.GetDataType()) == GetDataTypeName(m_InputTensorInfos[i].GetDataType()));
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +000062
63 BOOST_TEST(connectedInfo.GetQuantizationScale() == m_InputTensorInfos[i].GetQuantizationScale());
64 BOOST_TEST(connectedInfo.GetQuantizationOffset() == m_InputTensorInfos[i].GetQuantizationOffset());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000065 }
66
67 for (unsigned int i = 0; i < m_OutputTensorInfos.size(); i++)
68 {
69 const armnn::TensorInfo& outputInfo = layer->GetOutputSlot(i).GetTensorInfo();
70 BOOST_TEST(outputInfo.GetShape() == m_OutputTensorInfos[i].GetShape());
71 BOOST_TEST(
72 GetDataTypeName(outputInfo.GetDataType()) == GetDataTypeName(m_OutputTensorInfos[i].GetDataType()));
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +000073
74 BOOST_TEST(outputInfo.GetQuantizationScale() == m_OutputTensorInfos[i].GetQuantizationScale());
75 BOOST_TEST(outputInfo.GetQuantizationOffset() == m_OutputTensorInfos[i].GetQuantizationOffset());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +000076 }
77 }
78
79private:
80 std::string m_LayerName;
81 std::vector<armnn::TensorInfo> m_InputTensorInfos;
82 std::vector<armnn::TensorInfo> m_OutputTensorInfos;
83};
84
85template<typename T>
86void CompareConstTensorData(const void* data1, const void* data2, unsigned int numElements)
87{
88 T typedData1 = static_cast<T>(data1);
89 T typedData2 = static_cast<T>(data2);
90 BOOST_CHECK(typedData1);
91 BOOST_CHECK(typedData2);
92
93 for (unsigned int i = 0; i < numElements; i++)
94 {
95 BOOST_TEST(typedData1[i] == typedData2[i]);
96 }
97}
98
99void CompareConstTensor(const armnn::ConstTensor& tensor1, const armnn::ConstTensor& tensor2)
100{
101 BOOST_TEST(tensor1.GetShape() == tensor2.GetShape());
102 BOOST_TEST(GetDataTypeName(tensor1.GetDataType()) == GetDataTypeName(tensor2.GetDataType()));
103
104 switch (tensor1.GetDataType())
105 {
106 case armnn::DataType::Float32:
107 CompareConstTensorData<const float*>(
108 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
109 break;
110 case armnn::DataType::QuantisedAsymm8:
111 case armnn::DataType::Boolean:
112 CompareConstTensorData<const uint8_t*>(
113 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
114 break;
115 case armnn::DataType::Signed32:
116 CompareConstTensorData<const int32_t*>(
117 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
118 break;
119 default:
120 // Note that Float16 is not yet implemented
121 BOOST_TEST_MESSAGE("Unexpected datatype");
122 BOOST_TEST(false);
123 }
124}
125
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000126armnn::INetworkPtr DeserializeNetwork(const std::string& serializerString)
127{
128 std::vector<std::uint8_t> const serializerVector{serializerString.begin(), serializerString.end()};
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000129 return IDeserializer::Create()->CreateNetworkFromBinary(serializerVector);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000130}
131
132std::string SerializeNetwork(const armnn::INetwork& network)
133{
134 armnnSerializer::Serializer serializer;
135 serializer.Serialize(network);
136
137 std::stringstream stream;
138 serializer.SaveSerializedToStream(stream);
139
140 std::string serializerString{stream.str()};
141 return serializerString;
142}
143
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000144template<typename DataType>
145static std::vector<DataType> GenerateRandomData(size_t size)
146{
147 constexpr bool isIntegerType = std::is_integral<DataType>::value;
148 using Distribution =
149 typename std::conditional<isIntegerType,
150 std::uniform_int_distribution<DataType>,
151 std::uniform_real_distribution<DataType>>::type;
152
153 static constexpr DataType lowerLimit = std::numeric_limits<DataType>::min();
154 static constexpr DataType upperLimit = std::numeric_limits<DataType>::max();
155
156 static Distribution distribution(lowerLimit, upperLimit);
157 static std::default_random_engine generator;
158
159 std::vector<DataType> randomData(size);
160 std::generate(randomData.begin(), randomData.end(), []() { return distribution(generator); });
161
162 return randomData;
163}
164
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000165} // anonymous namespace
166
167BOOST_AUTO_TEST_SUITE(SerializerTests)
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000168
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000169BOOST_AUTO_TEST_CASE(SerializeAddition)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000170{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000171 class AdditionLayerVerifier : public LayerVerifierBase
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000172 {
173 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000174 AdditionLayerVerifier(const std::string& layerName,
175 const std::vector<armnn::TensorInfo>& inputInfos,
176 const std::vector<armnn::TensorInfo>& outputInfos)
177 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
178
179 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name) override
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000180 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000181 VerifyNameAndConnections(layer, name);
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000182 }
183 };
184
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000185 const std::string layerName("addition");
186 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
187
Mike Kelly8c1701a2019-02-11 17:01:27 +0000188 armnn::INetworkPtr network = armnn::INetwork::Create();
189 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
190 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000191 armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer(layerName.c_str());
192 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000193
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000194 inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
195 inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000196 additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Mike Kelly8c1701a2019-02-11 17:01:27 +0000197
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000198 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
199 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
200 additionLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
Jim Flynn3091b062019-02-15 14:45:04 +0000201
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000202 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000203 BOOST_CHECK(deserializedNetwork);
204
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000205 AdditionLayerVerifier verifier(layerName, {tensorInfo, tensorInfo}, {tensorInfo});
206 deserializedNetwork->Accept(verifier);
207}
Jim Flynnac25a1b2019-02-28 10:40:49 +0000208
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000209BOOST_AUTO_TEST_CASE(SerializeBatchNormalization)
210{
211 class BatchNormalizationLayerVerifier : public LayerVerifierBase
212 {
213 public:
214 BatchNormalizationLayerVerifier(const std::string& layerName,
215 const std::vector<armnn::TensorInfo>& inputInfos,
216 const std::vector<armnn::TensorInfo>& outputInfos,
217 const armnn::BatchNormalizationDescriptor& descriptor,
218 const armnn::ConstTensor& mean,
219 const armnn::ConstTensor& variance,
220 const armnn::ConstTensor& beta,
221 const armnn::ConstTensor& gamma)
222 : LayerVerifierBase(layerName, inputInfos, outputInfos)
223 , m_Descriptor(descriptor)
224 , m_Mean(mean)
225 , m_Variance(variance)
226 , m_Beta(beta)
227 , m_Gamma(gamma) {}
228
229 void VisitBatchNormalizationLayer(const armnn::IConnectableLayer* layer,
230 const armnn::BatchNormalizationDescriptor& descriptor,
231 const armnn::ConstTensor& mean,
232 const armnn::ConstTensor& variance,
233 const armnn::ConstTensor& beta,
234 const armnn::ConstTensor& gamma,
235 const char* name) override
236 {
237 VerifyNameAndConnections(layer, name);
238 VerifyDescriptor(descriptor);
239
240 CompareConstTensor(mean, m_Mean);
241 CompareConstTensor(variance, m_Variance);
242 CompareConstTensor(beta, m_Beta);
243 CompareConstTensor(gamma, m_Gamma);
244 }
245
246 private:
247 void VerifyDescriptor(const armnn::BatchNormalizationDescriptor& descriptor)
248 {
249 BOOST_TEST(descriptor.m_Eps == m_Descriptor.m_Eps);
250 BOOST_TEST(static_cast<int>(descriptor.m_DataLayout) == static_cast<int>(m_Descriptor.m_DataLayout));
251 }
252
253 armnn::BatchNormalizationDescriptor m_Descriptor;
254 armnn::ConstTensor m_Mean;
255 armnn::ConstTensor m_Variance;
256 armnn::ConstTensor m_Beta;
257 armnn::ConstTensor m_Gamma;
258 };
259
260 const std::string layerName("batchNormalization");
261 const armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32);
262 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
263
264 const armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32);
265 const armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32);
266 const armnn::TensorInfo betaInfo({1}, armnn::DataType::Float32);
267 const armnn::TensorInfo gammaInfo({1}, armnn::DataType::Float32);
268
269 armnn::BatchNormalizationDescriptor descriptor;
270 descriptor.m_Eps = 0.0010000000475f;
271 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
272
273 std::vector<float> meanData({5.0});
274 std::vector<float> varianceData({2.0});
275 std::vector<float> betaData({1.0});
276 std::vector<float> gammaData({0.0});
277
278 armnn::ConstTensor mean(meanInfo, meanData);
279 armnn::ConstTensor variance(varianceInfo, varianceData);
280 armnn::ConstTensor beta(betaInfo, betaData);
281 armnn::ConstTensor gamma(gammaInfo, gammaData);
282
283 armnn::INetworkPtr network = armnn::INetwork::Create();
284 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
285 armnn::IConnectableLayer* const batchNormalizationLayer =
286 network->AddBatchNormalizationLayer(descriptor, mean, variance, beta, gamma, layerName.c_str());
287 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
288
289 inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0));
290 batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
291
292 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
293 batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
294
295 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
296 BOOST_CHECK(deserializedNetwork);
297
298 BatchNormalizationLayerVerifier verifier(
299 layerName, {inputInfo}, {outputInfo}, descriptor, mean, variance, beta, gamma);
300 deserializedNetwork->Accept(verifier);
301}
302
303BOOST_AUTO_TEST_CASE(SerializeBatchToSpaceNd)
304{
305 class BatchToSpaceNdLayerVerifier : public LayerVerifierBase
306 {
307 public:
308 BatchToSpaceNdLayerVerifier(const std::string& layerName,
309 const std::vector<armnn::TensorInfo>& inputInfos,
310 const std::vector<armnn::TensorInfo>& outputInfos,
311 const armnn::BatchToSpaceNdDescriptor& descriptor)
312 : LayerVerifierBase(layerName, inputInfos, outputInfos)
313 , m_Descriptor(descriptor) {}
314
315 void VisitBatchToSpaceNdLayer(const armnn::IConnectableLayer* layer,
316 const armnn::BatchToSpaceNdDescriptor& descriptor,
317 const char* name) override
318 {
319 VerifyNameAndConnections(layer, name);
320 VerifyDescriptor(descriptor);
321 }
322
323 private:
324 void VerifyDescriptor(const armnn::BatchToSpaceNdDescriptor& descriptor)
325 {
326 BOOST_TEST(descriptor.m_Crops == m_Descriptor.m_Crops);
327 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
328 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
329 }
330
331 armnn::BatchToSpaceNdDescriptor m_Descriptor;
332 };
333
334 const std::string layerName("spaceToBatchNd");
335 const armnn::TensorInfo inputInfo({4, 1, 2, 2}, armnn::DataType::Float32);
336 const armnn::TensorInfo outputInfo({1, 1, 4, 4}, armnn::DataType::Float32);
337
338 armnn::BatchToSpaceNdDescriptor desc;
339 desc.m_DataLayout = armnn::DataLayout::NCHW;
340 desc.m_BlockShape = {2, 2};
341 desc.m_Crops = {{0, 0}, {0, 0}};
342
343 armnn::INetworkPtr network = armnn::INetwork::Create();
344 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
345 armnn::IConnectableLayer* const batchToSpaceNdLayer = network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
346 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
347
348 inputLayer->GetOutputSlot(0).Connect(batchToSpaceNdLayer->GetInputSlot(0));
349 batchToSpaceNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
350
351 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
352 batchToSpaceNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
353
354 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
355 BOOST_CHECK(deserializedNetwork);
356
357 BatchToSpaceNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
358 deserializedNetwork->Accept(verifier);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000359}
360
Conor Kennedy76277882019-02-26 08:29:54 +0000361BOOST_AUTO_TEST_CASE(SerializeConstant)
362{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000363 class ConstantLayerVerifier : public LayerVerifierBase
Conor Kennedy76277882019-02-26 08:29:54 +0000364 {
365 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000366 ConstantLayerVerifier(const std::string& layerName,
367 const std::vector<armnn::TensorInfo>& inputInfos,
368 const std::vector<armnn::TensorInfo>& outputInfos,
369 const armnn::ConstTensor& layerInput)
370 : LayerVerifierBase(layerName, inputInfos, outputInfos)
371 , m_LayerInput(layerInput) {}
372
373 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
374 const armnn::ConstTensor& input,
375 const char* name) override
Conor Kennedy76277882019-02-26 08:29:54 +0000376 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000377 VerifyNameAndConnections(layer, name);
378
379 CompareConstTensor(input, m_LayerInput);
Conor Kennedy76277882019-02-26 08:29:54 +0000380 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000381
382 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
383
384 private:
385 armnn::ConstTensor m_LayerInput;
Conor Kennedy76277882019-02-26 08:29:54 +0000386 };
387
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000388 const std::string layerName("constant");
389 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
Conor Kennedy76277882019-02-26 08:29:54 +0000390
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000391 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
392 armnn::ConstTensor constTensor(info, constantData);
Conor Kennedy76277882019-02-26 08:29:54 +0000393
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000394 armnn::INetworkPtr network(armnn::INetwork::Create());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000395 armnn::IConnectableLayer* input = network->AddInputLayer(0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000396 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000397 armnn::IConnectableLayer* add = network->AddAdditionLayer();
398 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
Conor Kennedy76277882019-02-26 08:29:54 +0000399
400 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
401 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
402 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
403
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000404 input->GetOutputSlot(0).SetTensorInfo(info);
405 constant->GetOutputSlot(0).SetTensorInfo(info);
406 add->GetOutputSlot(0).SetTensorInfo(info);
Conor Kennedy76277882019-02-26 08:29:54 +0000407
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000408 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Conor Kennedy76277882019-02-26 08:29:54 +0000409 BOOST_CHECK(deserializedNetwork);
410
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000411 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
412 deserializedNetwork->Accept(verifier);
Conor Kennedy76277882019-02-26 08:29:54 +0000413}
414
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000415BOOST_AUTO_TEST_CASE(SerializeConvolution2d)
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000416{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000417 class Convolution2dLayerVerifier : public LayerVerifierBase
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000418 {
419 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000420 Convolution2dLayerVerifier(const std::string& layerName,
421 const std::vector<armnn::TensorInfo>& inputInfos,
422 const std::vector<armnn::TensorInfo>& outputInfos,
423 const armnn::Convolution2dDescriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100424 const armnn::ConstTensor& weights,
425 const armnn::Optional<armnn::ConstTensor>& biases) :
426 LayerVerifierBase(layerName, inputInfos, outputInfos),
427 m_Descriptor(descriptor),
428 m_Weights(weights),
429 m_Biases(biases)
430 {}
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000431
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000432 void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
433 const armnn::Convolution2dDescriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100434 const armnn::ConstTensor& weights,
435 const armnn::Optional<armnn::ConstTensor>& biases,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000436 const char* name) override
437 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000438 VerifyNameAndConnections(layer, name);
439 VerifyDescriptor(descriptor);
440
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100441 // check weights
442 CompareConstTensor(weights, m_Weights);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000443
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100444 // check biases
445 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
446 BOOST_CHECK(m_Biases.has_value() == m_Descriptor.m_BiasEnabled);
447
448 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
449
450 if (biases.has_value() && m_Biases.has_value())
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000451 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100452 CompareConstTensor(biases.value(), m_Biases.value());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000453 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000454 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000455
456 private:
457 void VerifyDescriptor(const armnn::Convolution2dDescriptor& descriptor)
458 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100459 BOOST_CHECK(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
460 BOOST_CHECK(descriptor.m_PadRight == m_Descriptor.m_PadRight);
461 BOOST_CHECK(descriptor.m_PadTop == m_Descriptor.m_PadTop);
462 BOOST_CHECK(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
463 BOOST_CHECK(descriptor.m_StrideX == m_Descriptor.m_StrideX);
464 BOOST_CHECK(descriptor.m_StrideY == m_Descriptor.m_StrideY);
465 BOOST_CHECK(descriptor.m_DilationX == m_Descriptor.m_DilationX);
466 BOOST_CHECK(descriptor.m_DilationY == m_Descriptor.m_DilationY);
467 BOOST_CHECK(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
468 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000469 }
470
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100471 armnn::Convolution2dDescriptor m_Descriptor;
472 armnn::ConstTensor m_Weights;
473 armnn::Optional<armnn::ConstTensor> m_Biases;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000474 };
475
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000476 const std::string layerName("convolution2d");
477 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
478 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000479
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000480 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
481 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000482
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000483 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
484 armnn::ConstTensor weights(weightsInfo, weightsData);
485
486 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
487 armnn::ConstTensor biases(biasesInfo, biasesData);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000488
489 armnn::Convolution2dDescriptor descriptor;
490 descriptor.m_PadLeft = 1;
491 descriptor.m_PadRight = 1;
492 descriptor.m_PadTop = 1;
493 descriptor.m_PadBottom = 1;
494 descriptor.m_StrideX = 2;
495 descriptor.m_StrideY = 2;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100496 descriptor.m_DilationX = 2;
497 descriptor.m_DilationY = 2;
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000498 descriptor.m_BiasEnabled = true;
499 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
500
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000501 armnn::INetworkPtr network = armnn::INetwork::Create();
502 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000503 armnn::IConnectableLayer* const convLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100504 network->AddConvolution2dLayer(descriptor,
505 weights,
506 armnn::Optional<armnn::ConstTensor>(biases),
507 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000508 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000509
510 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000511 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000512
513 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000514 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
515
516 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
517 BOOST_CHECK(deserializedNetwork);
518
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000519 Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
520 deserializedNetwork->Accept(verifier);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000521}
522
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000523BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d)
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000524{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000525 class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBase
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000526 {
527 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000528 DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
529 const std::vector<armnn::TensorInfo>& inputInfos,
530 const std::vector<armnn::TensorInfo>& outputInfos,
531 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100532 const armnn::ConstTensor& weights,
533 const armnn::Optional<armnn::ConstTensor>& biases) :
534 LayerVerifierBase(layerName, inputInfos, outputInfos),
535 m_Descriptor(descriptor),
536 m_Weights(weights),
537 m_Biases(biases)
538 {}
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000539
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000540 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
541 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100542 const armnn::ConstTensor& weights,
543 const armnn::Optional<armnn::ConstTensor>& biases,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000544 const char* name) override
545 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000546 VerifyNameAndConnections(layer, name);
547 VerifyDescriptor(descriptor);
548
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100549 // check weights
550 CompareConstTensor(weights, m_Weights);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000551
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100552 // check biases
553 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
554 BOOST_CHECK(m_Biases.has_value() == m_Descriptor.m_BiasEnabled);
555
556 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
557
558 if (biases.has_value() && m_Biases.has_value())
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000559 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100560 CompareConstTensor(biases.value(), m_Biases.value());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000561 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000562 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000563
564 private:
565 void VerifyDescriptor(const armnn::DepthwiseConvolution2dDescriptor& descriptor)
566 {
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100567 BOOST_CHECK(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
568 BOOST_CHECK(descriptor.m_PadRight == m_Descriptor.m_PadRight);
569 BOOST_CHECK(descriptor.m_PadTop == m_Descriptor.m_PadTop);
570 BOOST_CHECK(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
571 BOOST_CHECK(descriptor.m_StrideX == m_Descriptor.m_StrideX);
572 BOOST_CHECK(descriptor.m_StrideY == m_Descriptor.m_StrideY);
573 BOOST_CHECK(descriptor.m_DilationX == m_Descriptor.m_DilationX);
574 BOOST_CHECK(descriptor.m_DilationY == m_Descriptor.m_DilationY);
575 BOOST_CHECK(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
576 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000577 }
578
579 armnn::DepthwiseConvolution2dDescriptor m_Descriptor;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100580 armnn::ConstTensor m_Weights;
581 armnn::Optional<armnn::ConstTensor> m_Biases;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000582 };
583
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000584 const std::string layerName("depwiseConvolution2d");
585 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
586 const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000587
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000588 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
589 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000590
591 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
592 armnn::ConstTensor weights(weightsInfo, weightsData);
593
594 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
595 armnn::ConstTensor biases(biasesInfo, biasesData);
596
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000597 armnn::DepthwiseConvolution2dDescriptor descriptor;
Aron Virginas-Tar5e1b0cf2019-06-21 14:20:11 +0100598 descriptor.m_PadLeft = 1;
599 descriptor.m_PadRight = 1;
600 descriptor.m_PadTop = 1;
601 descriptor.m_PadBottom = 1;
602 descriptor.m_StrideX = 2;
603 descriptor.m_StrideY = 2;
604 descriptor.m_DilationX = 2;
605 descriptor.m_DilationY = 2;
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000606 descriptor.m_BiasEnabled = true;
607 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
608
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000609 armnn::INetworkPtr network = armnn::INetwork::Create();
610 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
611 armnn::IConnectableLayer* const depthwiseConvLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100612 network->AddDepthwiseConvolution2dLayer(descriptor,
613 weights,
614 armnn::Optional<armnn::ConstTensor>(biases),
615 layerName.c_str());
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000616 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
617
618 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000619 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000620
621 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000622 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
623
624 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
625 BOOST_CHECK(deserializedNetwork);
626
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000627 DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
628 deserializedNetwork->Accept(verifier);
Jim Flynn18ce3382019-03-08 11:08:30 +0000629}
630
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000631BOOST_AUTO_TEST_CASE(SerializeDequantize)
632{
633 class DequantizeLayerVerifier : public LayerVerifierBase
634 {
635 public:
636 DequantizeLayerVerifier(const std::string& layerName,
637 const std::vector<armnn::TensorInfo>& inputInfos,
638 const std::vector<armnn::TensorInfo>& outputInfos)
639 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
640
641 void VisitDequantizeLayer(const armnn::IConnectableLayer* layer, const char* name) override
642 {
643 VerifyNameAndConnections(layer, name);
644 }
645 };
646
647 const std::string layerName("dequantize");
648 const armnn::TensorInfo inputInfo({ 1, 5, 2, 3 }, armnn::DataType::QuantisedAsymm8, 0.5f, 1);
649 const armnn::TensorInfo outputInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
650
651 armnn::INetworkPtr network = armnn::INetwork::Create();
652 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
653 armnn::IConnectableLayer* const dequantizeLayer = network->AddDequantizeLayer(layerName.c_str());
654 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
655
656 inputLayer->GetOutputSlot(0).Connect(dequantizeLayer->GetInputSlot(0));
657 dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
658
659 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
660 dequantizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
661
662 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
663 BOOST_CHECK(deserializedNetwork);
664
665 DequantizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
666 deserializedNetwork->Accept(verifier);
667}
668
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000669BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess)
670{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000671 class DetectionPostProcessLayerVerifier : public LayerVerifierBase
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000672 {
673 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000674 DetectionPostProcessLayerVerifier(const std::string& layerName,
675 const std::vector<armnn::TensorInfo>& inputInfos,
676 const std::vector<armnn::TensorInfo>& outputInfos,
677 const armnn::DetectionPostProcessDescriptor& descriptor,
678 const armnn::ConstTensor& anchors)
679 : LayerVerifierBase(layerName, inputInfos, outputInfos)
680 , m_Descriptor(descriptor)
681 , m_Anchors(anchors) {}
682
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000683 void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
684 const armnn::DetectionPostProcessDescriptor& descriptor,
685 const armnn::ConstTensor& anchors,
686 const char* name) override
687 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000688 VerifyNameAndConnections(layer, name);
689 VerifyDescriptor(descriptor);
690
691 CompareConstTensor(anchors, m_Anchors);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000692 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000693
694 private:
695 void VerifyDescriptor(const armnn::DetectionPostProcessDescriptor& descriptor)
696 {
697 BOOST_TEST(descriptor.m_UseRegularNms == m_Descriptor.m_UseRegularNms);
698 BOOST_TEST(descriptor.m_MaxDetections == m_Descriptor.m_MaxDetections);
699 BOOST_TEST(descriptor.m_MaxClassesPerDetection == m_Descriptor.m_MaxClassesPerDetection);
700 BOOST_TEST(descriptor.m_DetectionsPerClass == m_Descriptor.m_DetectionsPerClass);
701 BOOST_TEST(descriptor.m_NmsScoreThreshold == m_Descriptor.m_NmsScoreThreshold);
702 BOOST_TEST(descriptor.m_NmsIouThreshold == m_Descriptor.m_NmsIouThreshold);
703 BOOST_TEST(descriptor.m_NumClasses == m_Descriptor.m_NumClasses);
704 BOOST_TEST(descriptor.m_ScaleY == m_Descriptor.m_ScaleY);
705 BOOST_TEST(descriptor.m_ScaleX == m_Descriptor.m_ScaleX);
706 BOOST_TEST(descriptor.m_ScaleH == m_Descriptor.m_ScaleH);
707 BOOST_TEST(descriptor.m_ScaleW == m_Descriptor.m_ScaleW);
708 }
709
710 armnn::DetectionPostProcessDescriptor m_Descriptor;
711 armnn::ConstTensor m_Anchors;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000712 };
713
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000714 const std::string layerName("detectionPostProcess");
715
716 const std::vector<armnn::TensorInfo> inputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000717 armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32),
718 armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000719 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000720
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000721 const std::vector<armnn::TensorInfo> outputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000722 armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32),
723 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
724 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
725 armnn::TensorInfo({ 1 }, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000726 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000727
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000728 armnn::DetectionPostProcessDescriptor descriptor;
729 descriptor.m_UseRegularNms = true;
730 descriptor.m_MaxDetections = 3;
731 descriptor.m_MaxClassesPerDetection = 1;
732 descriptor.m_DetectionsPerClass =1;
733 descriptor.m_NmsScoreThreshold = 0.0;
734 descriptor.m_NmsIouThreshold = 0.5;
735 descriptor.m_NumClasses = 2;
736 descriptor.m_ScaleY = 10.0;
737 descriptor.m_ScaleX = 10.0;
738 descriptor.m_ScaleH = 5.0;
739 descriptor.m_ScaleW = 5.0;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000740
741 const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
742 const std::vector<float> anchorsData({
743 0.5f, 0.5f, 1.0f, 1.0f,
744 0.5f, 0.5f, 1.0f, 1.0f,
745 0.5f, 0.5f, 1.0f, 1.0f,
746 0.5f, 10.5f, 1.0f, 1.0f,
747 0.5f, 10.5f, 1.0f, 1.0f,
748 0.5f, 100.5f, 1.0f, 1.0f
749 });
750 armnn::ConstTensor anchors(anchorsInfo, anchorsData);
751
752 armnn::INetworkPtr network = armnn::INetwork::Create();
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000753 armnn::IConnectableLayer* const detectionLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000754 network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000755
756 for (unsigned int i = 0; i < 2; i++)
757 {
758 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
759 inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
760 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
761 }
762
763 for (unsigned int i = 0; i < 4; i++)
764 {
765 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
766 detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
767 detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
768 }
769
770 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
771 BOOST_CHECK(deserializedNetwork);
772
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000773 DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors);
774 deserializedNetwork->Accept(verifier);
775}
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000776
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000777BOOST_AUTO_TEST_CASE(SerializeDivision)
778{
779 class DivisionLayerVerifier : public LayerVerifierBase
780 {
781 public:
782 DivisionLayerVerifier(const std::string& layerName,
783 const std::vector<armnn::TensorInfo>& inputInfos,
784 const std::vector<armnn::TensorInfo>& outputInfos)
785 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
786
787 void VisitDivisionLayer(const armnn::IConnectableLayer* layer, const char* name) override
788 {
789 VerifyNameAndConnections(layer, name);
790 }
791 };
792
793 const std::string layerName("division");
794 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
795
796 armnn::INetworkPtr network = armnn::INetwork::Create();
797 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
798 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
799 armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
800 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
801
802 inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
803 inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
804 divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
805
806 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
807 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
808 divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
809
810 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
811 BOOST_CHECK(deserializedNetwork);
812
813 DivisionLayerVerifier verifier(layerName, {info, info}, {info});
814 deserializedNetwork->Accept(verifier);
815}
816
817BOOST_AUTO_TEST_CASE(SerializeEqual)
818{
819 class EqualLayerVerifier : public LayerVerifierBase
820 {
821 public:
822 EqualLayerVerifier(const std::string& layerName,
823 const std::vector<armnn::TensorInfo>& inputInfos,
824 const std::vector<armnn::TensorInfo>& outputInfos)
825 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
826
827 void VisitEqualLayer(const armnn::IConnectableLayer* layer, const char* name) override
828 {
829 VerifyNameAndConnections(layer, name);
830 }
831 };
832
833 const std::string layerName("equal");
834 const armnn::TensorInfo inputTensorInfo1 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
835 const armnn::TensorInfo inputTensorInfo2 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
836 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Boolean);
837
838 armnn::INetworkPtr network = armnn::INetwork::Create();
839 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
840 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
841 armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str());
842 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
843
844 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
845 inputLayer2->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
846 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
847
848 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
849 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
850 equalLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
851
852 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
853 BOOST_CHECK(deserializedNetwork);
854
855 EqualLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
856 deserializedNetwork->Accept(verifier);
857}
858
859BOOST_AUTO_TEST_CASE(SerializeFloor)
860{
861 class FloorLayerVerifier : public LayerVerifierBase
862 {
863 public:
864 FloorLayerVerifier(const std::string& layerName,
865 const std::vector<armnn::TensorInfo>& inputInfos,
866 const std::vector<armnn::TensorInfo>& outputInfos)
867 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
868
869 void VisitFloorLayer(const armnn::IConnectableLayer* layer, const char* name) override
870 {
871 VerifyNameAndConnections(layer, name);
872 }
873 };
874
875 const std::string layerName("floor");
876 const armnn::TensorInfo info({4,4}, armnn::DataType::Float32);
877
878 armnn::INetworkPtr network = armnn::INetwork::Create();
879 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
880 armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
881 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
882
883 inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
884 floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
885
886 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
887 floorLayer->GetOutputSlot(0).SetTensorInfo(info);
888
889 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
890 BOOST_CHECK(deserializedNetwork);
891
892 FloorLayerVerifier verifier(layerName, {info}, {info});
893 deserializedNetwork->Accept(verifier);
894}
895
896BOOST_AUTO_TEST_CASE(SerializeFullyConnected)
897{
898 class FullyConnectedLayerVerifier : public LayerVerifierBase
899 {
900 public:
901 FullyConnectedLayerVerifier(const std::string& layerName,
902 const std::vector<armnn::TensorInfo>& inputInfos,
903 const std::vector<armnn::TensorInfo>& outputInfos,
904 const armnn::FullyConnectedDescriptor& descriptor,
905 const armnn::ConstTensor& weight,
906 const armnn::Optional<armnn::ConstTensor>& bias)
907 : LayerVerifierBase(layerName, inputInfos, outputInfos)
908 , m_Descriptor(descriptor)
909 , m_Weight(weight)
910 , m_Bias(bias) {}
911
912 void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
913 const armnn::FullyConnectedDescriptor& descriptor,
914 const armnn::ConstTensor& weight,
915 const armnn::Optional<armnn::ConstTensor>& bias,
916 const char* name) override
917 {
918 VerifyNameAndConnections(layer, name);
919 VerifyDescriptor(descriptor);
920
921 CompareConstTensor(weight, m_Weight);
922
923 BOOST_TEST(bias.has_value() == m_Bias.has_value());
924 if (bias.has_value() && m_Bias.has_value())
925 {
926 CompareConstTensor(bias.value(), m_Bias.value());
927 }
928 }
929
930 private:
931 void VerifyDescriptor(const armnn::FullyConnectedDescriptor& descriptor)
932 {
933 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
934 BOOST_TEST(descriptor.m_TransposeWeightMatrix == m_Descriptor.m_TransposeWeightMatrix);
935 }
936
937 armnn::FullyConnectedDescriptor m_Descriptor;
938 armnn::ConstTensor m_Weight;
939 armnn::Optional<armnn::ConstTensor> m_Bias;
940 };
941
942 const std::string layerName("fullyConnected");
943 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
944 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
945
946 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
947 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
948 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
949 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
950 armnn::ConstTensor weights(weightsInfo, weightsData);
951 armnn::ConstTensor biases(biasesInfo, biasesData);
952
953 armnn::FullyConnectedDescriptor descriptor;
954 descriptor.m_BiasEnabled = true;
955 descriptor.m_TransposeWeightMatrix = false;
956
957 armnn::INetworkPtr network = armnn::INetwork::Create();
958 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
959 armnn::IConnectableLayer* const fullyConnectedLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100960 network->AddFullyConnectedLayer(descriptor,
961 weights,
962 armnn::Optional<armnn::ConstTensor>(biases),
963 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000964 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
965
966 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
967 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
968
969 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
970 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
971
972 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
973 BOOST_CHECK(deserializedNetwork);
974
975 FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
976 deserializedNetwork->Accept(verifier);
977}
978
979BOOST_AUTO_TEST_CASE(SerializeGather)
980{
981 class GatherLayerVerifier : public LayerVerifierBase
982 {
983 public:
984 GatherLayerVerifier(const std::string& layerName,
985 const std::vector<armnn::TensorInfo>& inputInfos,
986 const std::vector<armnn::TensorInfo>& outputInfos)
987 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
988
989 void VisitGatherLayer(const armnn::IConnectableLayer* layer, const char *name) override
990 {
991 VerifyNameAndConnections(layer, name);
992 }
993
994 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
995 const armnn::ConstTensor& input,
996 const char *name) override {}
997 };
998
999 const std::string layerName("gather");
1000 armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QuantisedAsymm8);
1001 armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QuantisedAsymm8);
1002 const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
1003
1004 paramsInfo.SetQuantizationScale(1.0f);
1005 paramsInfo.SetQuantizationOffset(0);
1006 outputInfo.SetQuantizationScale(1.0f);
1007 outputInfo.SetQuantizationOffset(0);
1008
1009 const std::vector<int32_t>& indicesData = {7, 6, 5};
1010
1011 armnn::INetworkPtr network = armnn::INetwork::Create();
1012 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
1013 armnn::IConnectableLayer *const constantLayer =
1014 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
1015 armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(layerName.c_str());
1016 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
1017
1018 inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
1019 constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
1020 gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1021
1022 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
1023 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
1024 gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1025
1026 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1027 BOOST_CHECK(deserializedNetwork);
1028
1029 GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo});
1030 deserializedNetwork->Accept(verifier);
1031}
1032
1033BOOST_AUTO_TEST_CASE(SerializeGreater)
1034{
1035 class GreaterLayerVerifier : public LayerVerifierBase
1036 {
1037 public:
1038 GreaterLayerVerifier(const std::string& layerName,
1039 const std::vector<armnn::TensorInfo>& inputInfos,
1040 const std::vector<armnn::TensorInfo>& outputInfos)
1041 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1042
1043 void VisitGreaterLayer(const armnn::IConnectableLayer* layer, const char* name) override
1044 {
1045 VerifyNameAndConnections(layer, name);
1046 }
1047 };
1048
1049 const std::string layerName("greater");
1050 const armnn::TensorInfo inputTensorInfo1({ 1, 2, 2, 2 }, armnn::DataType::Float32);
1051 const armnn::TensorInfo inputTensorInfo2({ 1, 2, 2, 2 }, armnn::DataType::Float32);
1052 const armnn::TensorInfo outputTensorInfo({ 1, 2, 2, 2 }, armnn::DataType::Boolean);
1053
1054 armnn::INetworkPtr network = armnn::INetwork::Create();
1055 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
1056 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
1057 armnn::IConnectableLayer* const greaterLayer = network->AddGreaterLayer(layerName.c_str());
1058 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1059
1060 inputLayer1->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(0));
1061 inputLayer2->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(1));
1062 greaterLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1063
1064 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
1065 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
1066 greaterLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1067
1068 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1069 BOOST_CHECK(deserializedNetwork);
1070
1071 GreaterLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
1072 deserializedNetwork->Accept(verifier);
1073}
1074
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001075class L2NormalizationLayerVerifier : public LayerVerifierBase
1076{
1077public:
1078 L2NormalizationLayerVerifier(const std::string& layerName,
1079 const std::vector<armnn::TensorInfo>& inputInfos,
1080 const std::vector<armnn::TensorInfo>& outputInfos,
1081 const armnn::L2NormalizationDescriptor& descriptor)
1082 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1083 , m_Descriptor(descriptor) {}
1084
1085 void VisitL2NormalizationLayer(const armnn::IConnectableLayer* layer,
1086 const armnn::L2NormalizationDescriptor& descriptor,
1087 const char* name) override
1088 {
1089 VerifyNameAndConnections(layer, name);
1090 VerifyDescriptor(descriptor);
1091 }
1092private:
1093 void VerifyDescriptor(const armnn::L2NormalizationDescriptor& descriptor)
1094 {
1095 BOOST_TEST(descriptor.m_Eps == m_Descriptor.m_Eps);
1096 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1097 }
1098
1099 armnn::L2NormalizationDescriptor m_Descriptor;
1100};
1101
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001102BOOST_AUTO_TEST_CASE(SerializeL2Normalization)
1103{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001104 const std::string l2NormLayerName("l2Normalization");
1105 const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1106
1107 armnn::L2NormalizationDescriptor desc;
1108 desc.m_DataLayout = armnn::DataLayout::NCHW;
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001109 desc.m_Eps = 0.0001f;
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001110
1111 armnn::INetworkPtr network = armnn::INetwork::Create();
1112 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1113 armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1114 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1115
1116 inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1117 l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1118
1119 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1120 l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1121
1122 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1123 BOOST_CHECK(deserializedNetwork);
1124
1125 L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc);
1126 deserializedNetwork->Accept(verifier);
1127}
1128
Ferran Balaguer0dcffec2019-06-18 16:25:06 +01001129BOOST_AUTO_TEST_CASE(EnsureL2NormalizationBackwardCompatibility)
1130{
1131 // The hex array below is a flat buffer containing a simple network with one input
1132 // a L2Normalization layer and an output layer with dimensions as per the tensor infos below.
1133 //
1134 // This test verifies that we can still read back these old style
1135 // models without the normalization epsilon value.
1136 unsigned int size = 508;
1137 const unsigned char l2NormalizationModel[] = {
1138 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1139 0x0C,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x3C,0x01,0x00,0x00,
1140 0x74,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1141 0x02,0x00,0x00,0x00,0xE8,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x0B,0x04,0x00,0x00,0x00,0xD6,0xFE,0xFF,0xFF,
1142 0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1143 0x9E,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1144 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
1145 0x00,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0xFF,0xFF,0xFF,
1146 0x00,0x00,0x00,0x20,0x0C,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1147 0x20,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x06,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,
1148 0x18,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,0x0E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1149 0x10,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,
1150 0x6C,0x32,0x4E,0x6F,0x72,0x6D,0x61,0x6C,0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x00,0x01,0x00,0x00,0x00,
1151 0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x04,0x00,
1152 0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x52,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
1153 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1154 0x05,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1155 0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x09,
1156 0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0A,0x00,0x04,0x00,
1157 0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x08,0x00,
1158 0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1159 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1160 0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1161 0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
1162 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1163 0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0 };
1164
1165 std::stringstream ss;
1166 for (unsigned int i = 0; i < size; ++i)
1167 {
1168 ss << l2NormalizationModel[i];
1169 }
1170 std::string l2NormalizationLayerNetwork = ss.str();
1171 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(l2NormalizationLayerNetwork);
1172 BOOST_CHECK(deserializedNetwork);
1173 const std::string layerName("l2Normalization");
1174 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 2, 1, 5}, armnn::DataType::Float32);
1175
1176 armnn::L2NormalizationDescriptor desc;
1177 desc.m_DataLayout = armnn::DataLayout::NCHW;
1178 // Since this variable does not exist in the l2NormalizationModel[] dump, the default value will be loaded.
1179 desc.m_Eps = 1e-12f;
1180
1181 L2NormalizationLayerVerifier verifier(layerName, {inputInfo}, {inputInfo}, desc);
1182 deserializedNetwork->Accept(verifier);
1183}
1184
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001185BOOST_AUTO_TEST_CASE(SerializeMaximum)
1186{
1187 class MaximumLayerVerifier : public LayerVerifierBase
1188 {
1189 public:
1190 MaximumLayerVerifier(const std::string& layerName,
1191 const std::vector<armnn::TensorInfo>& inputInfos,
1192 const std::vector<armnn::TensorInfo>& outputInfos)
1193 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1194
1195 void VisitMaximumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1196 {
1197 VerifyNameAndConnections(layer, name);
1198 }
1199 };
1200
1201 const std::string layerName("maximum");
1202 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1203
1204 armnn::INetworkPtr network = armnn::INetwork::Create();
1205 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1206 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1207 armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1208 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1209
1210 inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1211 inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1212 maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1213
1214 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1215 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1216 maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1217
1218 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1219 BOOST_CHECK(deserializedNetwork);
1220
1221 MaximumLayerVerifier verifier(layerName, {info, info}, {info});
1222 deserializedNetwork->Accept(verifier);
1223}
1224
1225BOOST_AUTO_TEST_CASE(SerializeMean)
1226{
1227 class MeanLayerVerifier : public LayerVerifierBase
1228 {
1229 public:
1230 MeanLayerVerifier(const std::string& layerName,
1231 const std::vector<armnn::TensorInfo>& inputInfos,
1232 const std::vector<armnn::TensorInfo>& outputInfos,
1233 const armnn::MeanDescriptor& descriptor)
1234 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1235 , m_Descriptor(descriptor) {}
1236
1237 void VisitMeanLayer(const armnn::IConnectableLayer* layer,
1238 const armnn::MeanDescriptor& descriptor,
1239 const char* name) override
1240 {
1241 VerifyNameAndConnections(layer, name);
1242 VerifyDescriptor(descriptor);
1243 }
1244
1245 private:
1246 void VerifyDescriptor(const armnn::MeanDescriptor& descriptor)
1247 {
1248 BOOST_TEST(descriptor.m_Axis == m_Descriptor.m_Axis);
1249 BOOST_TEST(descriptor.m_KeepDims == m_Descriptor.m_KeepDims);
1250 }
1251
1252 armnn::MeanDescriptor m_Descriptor;
1253 };
1254
1255 const std::string layerName("mean");
1256 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1257 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1258
1259 armnn::MeanDescriptor descriptor;
1260 descriptor.m_Axis = { 2 };
1261 descriptor.m_KeepDims = true;
1262
1263 armnn::INetworkPtr network = armnn::INetwork::Create();
1264 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1265 armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1266 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1267
1268 inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1269 meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1270
1271 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1272 meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1273
1274 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1275 BOOST_CHECK(deserializedNetwork);
1276
1277 MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1278 deserializedNetwork->Accept(verifier);
1279}
1280
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001281BOOST_AUTO_TEST_CASE(SerializeMerge)
1282{
1283 class MergeLayerVerifier : public LayerVerifierBase
1284 {
1285 public:
1286 MergeLayerVerifier(const std::string& layerName,
1287 const std::vector<armnn::TensorInfo>& inputInfos,
1288 const std::vector<armnn::TensorInfo>& outputInfos)
1289 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1290
1291 void VisitMergeLayer(const armnn::IConnectableLayer* layer, const char* name) override
1292 {
1293 VerifyNameAndConnections(layer, name);
1294 }
1295 };
1296
1297 const std::string layerName("merge");
1298 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1299
1300 armnn::INetworkPtr network = armnn::INetwork::Create();
1301 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1302 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1303 armnn::IConnectableLayer* const mergeLayer = network->AddMergeLayer(layerName.c_str());
1304 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1305
1306 inputLayer0->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(0));
1307 inputLayer1->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(1));
1308 mergeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1309
1310 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1311 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1312 mergeLayer->GetOutputSlot(0).SetTensorInfo(info);
1313
1314 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1315 BOOST_CHECK(deserializedNetwork);
1316
1317 MergeLayerVerifier verifier(layerName, {info, info}, {info});
1318 deserializedNetwork->Accept(verifier);
1319}
1320
Jim Flynn5fa83932019-05-09 15:35:43 +01001321class MergerLayerVerifier : public LayerVerifierBase
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001322{
Jim Flynn5fa83932019-05-09 15:35:43 +01001323public:
1324 MergerLayerVerifier(const std::string& layerName,
1325 const std::vector<armnn::TensorInfo>& inputInfos,
1326 const std::vector<armnn::TensorInfo>& outputInfos,
1327 const armnn::OriginsDescriptor& descriptor)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001328 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1329 , m_Descriptor(descriptor) {}
1330
Jim Flynn5fa83932019-05-09 15:35:43 +01001331 void VisitMergerLayer(const armnn::IConnectableLayer* layer,
1332 const armnn::OriginsDescriptor& descriptor,
1333 const char* name) override
1334 {
Jim Flynne242f2d2019-05-22 14:24:13 +01001335 throw armnn::Exception("MergerLayer should have translated to ConcatLayer");
1336 }
1337
1338 void VisitConcatLayer(const armnn::IConnectableLayer* layer,
1339 const armnn::OriginsDescriptor& descriptor,
1340 const char* name) override
1341 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001342 VerifyNameAndConnections(layer, name);
1343 VerifyDescriptor(descriptor);
1344 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001345
Jim Flynn5fa83932019-05-09 15:35:43 +01001346private:
1347 void VerifyDescriptor(const armnn::OriginsDescriptor& descriptor)
1348 {
1349 BOOST_TEST(descriptor.GetConcatAxis() == m_Descriptor.GetConcatAxis());
1350 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
1351 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001352
Jim Flynn5fa83932019-05-09 15:35:43 +01001353 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
1354 {
1355 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001356 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001357 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001358 }
1359 }
Jim Flynn5fa83932019-05-09 15:35:43 +01001360 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001361
Jim Flynn5fa83932019-05-09 15:35:43 +01001362 armnn::OriginsDescriptor m_Descriptor;
1363};
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001364
Jim Flynne242f2d2019-05-22 14:24:13 +01001365// NOTE: until the deprecated AddMergerLayer disappears this test checks that calling
1366// AddMergerLayer places a ConcatLayer into the serialized format and that
1367// when this deserialises we have a ConcatLayer
Jim Flynn5fa83932019-05-09 15:35:43 +01001368BOOST_AUTO_TEST_CASE(SerializeMerger)
1369{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001370 const std::string layerName("merger");
1371 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1372 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1373
1374 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1375
1376 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001377 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001378
1379 armnn::INetworkPtr network = armnn::INetwork::Create();
1380 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1381 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
Jim Flynn906f9462019-05-10 13:55:21 +01001382 ARMNN_NO_DEPRECATE_WARN_BEGIN
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001383 armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str());
Jim Flynn906f9462019-05-10 13:55:21 +01001384 ARMNN_NO_DEPRECATE_WARN_END
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001385 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1386
1387 inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
1388 inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
1389 mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1390
1391 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1392 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1393 mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1394
Jim Flynn5fa83932019-05-09 15:35:43 +01001395 std::string mergerLayerNetwork = SerializeNetwork(*network);
1396 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001397 BOOST_CHECK(deserializedNetwork);
1398
1399 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1400 deserializedNetwork->Accept(verifier);
1401}
1402
Jim Flynn5fa83932019-05-09 15:35:43 +01001403BOOST_AUTO_TEST_CASE(EnsureMergerLayerBackwardCompatibility)
1404{
1405 // The hex array below is a flat buffer containing a simple network with two inputs
Jim Flynne242f2d2019-05-22 14:24:13 +01001406 // a merger layer (now deprecated) and an output layer with dimensions as per the tensor infos below.
1407 //
1408 // This test verifies that we can still read back these old style
Jim Flynn5fa83932019-05-09 15:35:43 +01001409 // models replacing the MergerLayers with ConcatLayers with the same parameters.
Jim Flynn5fa83932019-05-09 15:35:43 +01001410 unsigned int size = 760;
1411 const unsigned char mergerModel[] = {
1412 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1413 0x0C,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x38,0x02,0x00,0x00,
1414 0x8C,0x01,0x00,0x00,0x70,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1415 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xF4,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x0B,
1416 0x04,0x00,0x00,0x00,0x92,0xFE,0xFF,0xFF,0x04,0x00,0x00,0x00,0x9A,0xFE,0xFF,0xFF,0x04,0x00,0x00,0x00,
1417 0x7E,0xFE,0xFF,0xFF,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1418 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
1419 0x00,0x00,0x00,0x00,0xF8,0xFE,0xFF,0xFF,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0xFE,0xFF,0xFF,
1420 0x00,0x00,0x00,0x1F,0x0C,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1421 0x68,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x0C,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,
1422 0x0C,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1423 0x24,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x22,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1424 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,
1425 0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1426 0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,
1427 0x14,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x6D,0x65,0x72,0x67,0x65,0x72,0x00,0x00,
1428 0x02,0x00,0x00,0x00,0x5C,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1429 0x34,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x92,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
1430 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1431 0x02,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1432 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,
1433 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1434 0x00,0x00,0x00,0x09,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,
1435 0x0C,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,
1436 0x01,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x18,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,
1437 0x0E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1438 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1439 0x0C,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1440 0x66,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1441 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,
1442 0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,
1443 0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0A,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1444 0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,
1445 0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1446 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,
1447 0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,
1448 0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1449 0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00};
1450 std::stringstream ss;
1451 for (unsigned int i = 0; i < size; ++i)
1452 {
1453 ss << mergerModel[i];
1454 }
1455 std::string mergerLayerNetwork = ss.str();
1456 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
1457 BOOST_CHECK(deserializedNetwork);
1458 const std::string layerName("merger");
1459 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1460 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1461
1462 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1463
1464 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001465 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Jim Flynn5fa83932019-05-09 15:35:43 +01001466
1467 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1468 deserializedNetwork->Accept(verifier);
1469}
1470
Jim Flynne242f2d2019-05-22 14:24:13 +01001471BOOST_AUTO_TEST_CASE(SerializeConcat)
1472{
1473 const std::string layerName("concat");
1474 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1475 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1476
1477 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1478
1479 armnn::OriginsDescriptor descriptor =
1480 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1481
1482 armnn::INetworkPtr network = armnn::INetwork::Create();
1483 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1484 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1485 armnn::IConnectableLayer* const concatLayer = network->AddConcatLayer(descriptor, layerName.c_str());
1486 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1487
1488 inputLayerOne->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
1489 inputLayerTwo->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
1490 concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1491
1492 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1493 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1494 concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1495
1496 std::string concatLayerNetwork = SerializeNetwork(*network);
1497 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(concatLayerNetwork);
1498 BOOST_CHECK(deserializedNetwork);
1499
1500 // NOTE: using the MergerLayerVerifier to ensure that it is a concat layer and not a
1501 // merger layer that gets placed into the graph.
1502 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1503 deserializedNetwork->Accept(verifier);
1504}
1505
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001506BOOST_AUTO_TEST_CASE(SerializeMinimum)
1507{
1508 class MinimumLayerVerifier : public LayerVerifierBase
1509 {
1510 public:
1511 MinimumLayerVerifier(const std::string& layerName,
1512 const std::vector<armnn::TensorInfo>& inputInfos,
1513 const std::vector<armnn::TensorInfo>& outputInfos)
1514 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1515
1516 void VisitMinimumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1517 {
1518 VerifyNameAndConnections(layer, name);
1519 }
1520 };
1521
1522 const std::string layerName("minimum");
1523 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1524
1525 armnn::INetworkPtr network = armnn::INetwork::Create();
1526 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1527 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1528 armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1529 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1530
1531 inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1532 inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1533 minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1534
1535 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1536 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1537 minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
1538
1539 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1540 BOOST_CHECK(deserializedNetwork);
1541
1542 MinimumLayerVerifier verifier(layerName, {info, info}, {info});
1543 deserializedNetwork->Accept(verifier);
1544}
1545
1546BOOST_AUTO_TEST_CASE(SerializeMultiplication)
1547{
1548 class MultiplicationLayerVerifier : public LayerVerifierBase
1549 {
1550 public:
1551 MultiplicationLayerVerifier(const std::string& layerName,
1552 const std::vector<armnn::TensorInfo>& inputInfos,
1553 const std::vector<armnn::TensorInfo>& outputInfos)
1554 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1555
1556 void VisitMultiplicationLayer(const armnn::IConnectableLayer* layer, const char* name) override
1557 {
1558 VerifyNameAndConnections(layer, name);
1559 }
1560 };
1561
1562 const std::string layerName("multiplication");
1563 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1564
1565 armnn::INetworkPtr network = armnn::INetwork::Create();
1566 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1567 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1568 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
1569 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1570
1571 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
1572 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
1573 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1574
1575 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1576 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1577 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
1578
1579 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1580 BOOST_CHECK(deserializedNetwork);
1581
1582 MultiplicationLayerVerifier verifier(layerName, {info, info}, {info});
1583 deserializedNetwork->Accept(verifier);
1584}
1585
Ellen Norris-Thompson51982472019-06-19 11:46:21 +01001586BOOST_AUTO_TEST_CASE(SerializePrelu)
1587{
1588 class PreluLayerVerifier : public LayerVerifierBase
1589 {
1590 public:
1591 PreluLayerVerifier(const std::string& layerName,
1592 const std::vector<armnn::TensorInfo>& inputInfos,
1593 const std::vector<armnn::TensorInfo>& outputInfos)
1594 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1595
1596 void VisitPreluLayer(const armnn::IConnectableLayer* layer, const char* name) override
1597 {
1598 VerifyNameAndConnections(layer, name);
1599 }
1600 };
1601
1602 const std::string layerName("prelu");
1603
1604 armnn::TensorInfo inputTensorInfo ({ 4, 1, 2 }, armnn::DataType::Float32);
1605 armnn::TensorInfo alphaTensorInfo ({ 5, 4, 3, 1 }, armnn::DataType::Float32);
1606 armnn::TensorInfo outputTensorInfo({ 5, 4, 3, 2 }, armnn::DataType::Float32);
1607
1608 armnn::INetworkPtr network = armnn::INetwork::Create();
1609 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1610 armnn::IConnectableLayer* const alphaLayer = network->AddInputLayer(1);
1611 armnn::IConnectableLayer* const preluLayer = network->AddPreluLayer(layerName.c_str());
1612 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1613
1614 inputLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(0));
1615 alphaLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(1));
1616 preluLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1617
1618 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1619 alphaLayer->GetOutputSlot(0).SetTensorInfo(alphaTensorInfo);
1620 preluLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1621
1622 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1623 BOOST_CHECK(deserializedNetwork);
1624
1625 PreluLayerVerifier verifier(layerName, {inputTensorInfo, alphaTensorInfo}, {outputTensorInfo});
1626 deserializedNetwork->Accept(verifier);
1627}
1628
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001629BOOST_AUTO_TEST_CASE(SerializeNormalization)
1630{
1631 class NormalizationLayerVerifier : public LayerVerifierBase
1632 {
1633 public:
1634 NormalizationLayerVerifier(const std::string& layerName,
1635 const std::vector<armnn::TensorInfo>& inputInfos,
1636 const std::vector<armnn::TensorInfo>& outputInfos,
1637 const armnn::NormalizationDescriptor& descriptor)
1638 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1639 , m_Descriptor(descriptor) {}
1640
1641 void VisitNormalizationLayer(const armnn::IConnectableLayer* layer,
1642 const armnn::NormalizationDescriptor& descriptor,
1643 const char* name) override
1644 {
1645 VerifyNameAndConnections(layer, name);
1646 VerifyDescriptor(descriptor);
1647 }
1648
1649 private:
1650 void VerifyDescriptor(const armnn::NormalizationDescriptor& descriptor)
1651 {
1652 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1653 BOOST_TEST(descriptor.m_NormSize == m_Descriptor.m_NormSize);
1654 BOOST_TEST(descriptor.m_Alpha == m_Descriptor.m_Alpha);
1655 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
1656 BOOST_TEST(descriptor.m_K == m_Descriptor.m_K);
1657 BOOST_TEST(
1658 static_cast<int>(descriptor.m_NormChannelType) == static_cast<int>(m_Descriptor.m_NormChannelType));
1659 BOOST_TEST(
1660 static_cast<int>(descriptor.m_NormMethodType) == static_cast<int>(m_Descriptor.m_NormMethodType));
1661 }
1662
1663 armnn::NormalizationDescriptor m_Descriptor;
1664 };
1665
1666 const std::string layerName("normalization");
1667 const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
1668
1669 armnn::NormalizationDescriptor desc;
1670 desc.m_DataLayout = armnn::DataLayout::NCHW;
1671 desc.m_NormSize = 3;
1672 desc.m_Alpha = 1;
1673 desc.m_Beta = 1;
1674 desc.m_K = 1;
1675
1676 armnn::INetworkPtr network = armnn::INetwork::Create();
1677 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1678 armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
1679 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1680
1681 inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
1682 normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1683
1684 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1685 normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
1686
1687 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1688 BOOST_CHECK(deserializedNetwork);
1689
1690 NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc);
1691 deserializedNetwork->Accept(verifier);
1692}
1693
Jim Flynn965c7c62019-06-24 14:32:41 +01001694class PadLayerVerifier : public LayerVerifierBase
1695{
1696public:
1697 PadLayerVerifier(const std::string& layerName,
1698 const std::vector<armnn::TensorInfo>& inputInfos,
1699 const std::vector<armnn::TensorInfo>& outputInfos,
1700 const armnn::PadDescriptor& descriptor)
1701 : LayerVerifierBase(layerName, inputInfos, outputInfos), m_Descriptor(descriptor) {}
1702
1703 void VisitPadLayer(const armnn::IConnectableLayer* layer,
1704 const armnn::PadDescriptor& descriptor,
1705 const char* name) override
1706 {
1707 VerifyNameAndConnections(layer, name);
1708 VerifyDescriptor(descriptor);
1709 }
1710
1711private:
1712 void VerifyDescriptor(const armnn::PadDescriptor& descriptor)
1713 {
1714 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
David Monahan34757812019-06-19 11:47:21 +01001715 BOOST_TEST(descriptor.m_padValue == m_Descriptor.m_padValue);
Jim Flynn965c7c62019-06-24 14:32:41 +01001716 }
1717
1718 armnn::PadDescriptor m_Descriptor;
1719};
1720
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001721BOOST_AUTO_TEST_CASE(SerializePad)
1722{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001723
1724 const std::string layerName("pad");
1725 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1726 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1727
1728 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1729
1730 armnn::INetworkPtr network = armnn::INetwork::Create();
1731 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1732 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
1733 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1734
1735 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
1736 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1737
1738 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1739 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1740
1741 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1742 BOOST_CHECK(deserializedNetwork);
1743
1744 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1745 deserializedNetwork->Accept(verifier);
1746}
1747
Jim Flynn965c7c62019-06-24 14:32:41 +01001748BOOST_AUTO_TEST_CASE(CheckSerializePadBackwardCompatibility)
1749{
1750 // The PadDescriptor is being extended with a float PadValue (so a value other than 0
1751 // can be used to pad the tensor.
1752 //
1753 // This test contains a binary representation of a simple input->pad->output network
1754 // prior to this change to test that the descriptor has been updated in a backward
1755 // compatible way with respect to Deserialization of older binary dumps
1756 unsigned int size = 532;
1757 const unsigned char padModel[] = {
1758 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1759 0x0C,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x54,0x01,0x00,0x00,
1760 0x6C,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1761 0x02,0x00,0x00,0x00,0xD0,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x0B,0x04,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,
1762 0x04,0x00,0x00,0x00,0x9E,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x72,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,
1763 0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1764 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2C,0xFF,0xFF,0xFF,
1765 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x16,0x0C,0x00,0x00,0x00,
1766 0x08,0x00,0x0E,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x4C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,
1767 0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
1768 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1769 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x18,0x00,0x04,0x00,
1770 0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,0x0E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1771 0x14,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x70,0x61,0x64,0x00,
1772 0x01,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x08,0x00,
1773 0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x52,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,
1774 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
1775 0x05,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,
1776 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1777 0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,
1778 0x0A,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,
1779 0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1780 0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1781 0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,
1782 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1783 0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1784 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0 };
1785
1786 std::stringstream ss;
1787 for (unsigned int i = 0; i < size; ++i)
1788 {
1789 ss << padModel[i];
1790 }
1791 std::string padNetwork = ss.str();
1792 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(padNetwork);
1793 BOOST_CHECK(deserializedNetwork);
1794
1795 const std::string layerName("pad");
1796 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1797 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1798
1799 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1800
1801 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1802 deserializedNetwork->Accept(verifier);
1803}
1804
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001805BOOST_AUTO_TEST_CASE(SerializePermute)
1806{
1807 class PermuteLayerVerifier : public LayerVerifierBase
1808 {
1809 public:
1810 PermuteLayerVerifier(const std::string& layerName,
1811 const std::vector<armnn::TensorInfo>& inputInfos,
1812 const std::vector<armnn::TensorInfo>& outputInfos,
1813 const armnn::PermuteDescriptor& descriptor)
1814 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1815 , m_Descriptor(descriptor) {}
1816
1817 void VisitPermuteLayer(const armnn::IConnectableLayer* layer,
1818 const armnn::PermuteDescriptor& descriptor,
1819 const char* name) override
1820 {
1821 VerifyNameAndConnections(layer, name);
1822 VerifyDescriptor(descriptor);
1823 }
1824
1825 private:
1826 void VerifyDescriptor(const armnn::PermuteDescriptor& descriptor)
1827 {
1828 BOOST_TEST(descriptor.m_DimMappings.IsEqual(m_Descriptor.m_DimMappings));
1829 }
1830
1831 armnn::PermuteDescriptor m_Descriptor;
1832 };
1833
1834 const std::string layerName("permute");
1835 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
1836 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1837
1838 armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
1839
1840 armnn::INetworkPtr network = armnn::INetwork::Create();
1841 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1842 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
1843 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1844
1845 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
1846 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1847
1848 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1849 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1850
1851 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1852 BOOST_CHECK(deserializedNetwork);
1853
1854 PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
1855 deserializedNetwork->Accept(verifier);
1856}
1857
1858BOOST_AUTO_TEST_CASE(SerializePooling2d)
1859{
1860 class Pooling2dLayerVerifier : public LayerVerifierBase
1861 {
1862 public:
1863 Pooling2dLayerVerifier(const std::string& layerName,
1864 const std::vector<armnn::TensorInfo>& inputInfos,
1865 const std::vector<armnn::TensorInfo>& outputInfos,
1866 const armnn::Pooling2dDescriptor& descriptor)
1867 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1868 , m_Descriptor(descriptor) {}
1869
1870 void VisitPooling2dLayer(const armnn::IConnectableLayer* layer,
1871 const armnn::Pooling2dDescriptor& descriptor,
1872 const char* name) override
1873 {
1874 VerifyNameAndConnections(layer, name);
1875 VerifyDescriptor(descriptor);
1876 }
1877
1878 private:
1879 void VerifyDescriptor(const armnn::Pooling2dDescriptor& descriptor)
1880 {
1881 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1882 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
1883 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
1884 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
1885 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
1886 BOOST_TEST(descriptor.m_PoolWidth == m_Descriptor.m_PoolWidth);
1887 BOOST_TEST(descriptor.m_PoolHeight == m_Descriptor.m_PoolHeight);
1888 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
1889 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
1890
1891 BOOST_TEST(
1892 static_cast<int>(descriptor.m_PaddingMethod) == static_cast<int>(m_Descriptor.m_PaddingMethod));
1893 BOOST_TEST(
1894 static_cast<int>(descriptor.m_PoolType) == static_cast<int>(m_Descriptor.m_PoolType));
1895 BOOST_TEST(
1896 static_cast<int>(descriptor.m_OutputShapeRounding) ==
1897 static_cast<int>(m_Descriptor.m_OutputShapeRounding));
1898 }
1899
1900 armnn::Pooling2dDescriptor m_Descriptor;
1901 };
1902
1903 const std::string layerName("pooling2d");
1904 const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
1905 const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
1906
1907 armnn::Pooling2dDescriptor desc;
1908 desc.m_DataLayout = armnn::DataLayout::NHWC;
1909 desc.m_PadTop = 0;
1910 desc.m_PadBottom = 0;
1911 desc.m_PadLeft = 0;
1912 desc.m_PadRight = 0;
1913 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
1914 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1915 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1916 desc.m_PoolHeight = 2;
1917 desc.m_PoolWidth = 2;
1918 desc.m_StrideX = 2;
1919 desc.m_StrideY = 2;
1920
1921 armnn::INetworkPtr network = armnn::INetwork::Create();
1922 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1923 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
1924 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1925
1926 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
1927 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1928
1929 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1930 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1931
1932 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1933 BOOST_CHECK(deserializedNetwork);
1934
1935 Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1936 deserializedNetwork->Accept(verifier);
1937}
1938
Derek Lamberti87acb272019-03-27 16:51:31 +00001939BOOST_AUTO_TEST_CASE(SerializeQuantize)
1940{
1941 class QuantizeLayerVerifier : public LayerVerifierBase
1942 {
1943 public:
1944 QuantizeLayerVerifier(const std::string& layerName,
1945 const std::vector<armnn::TensorInfo>& inputInfos,
1946 const std::vector<armnn::TensorInfo>& outputInfos)
1947 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1948
1949 void VisitQuantizeLayer(const armnn::IConnectableLayer* layer, const char* name) override
1950 {
1951 VerifyNameAndConnections(layer, name);
1952 }
1953 };
1954
1955 const std::string layerName("quantize");
1956 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1957
1958 armnn::INetworkPtr network = armnn::INetwork::Create();
1959 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1960 armnn::IConnectableLayer* const quantizeLayer = network->AddQuantizeLayer(layerName.c_str());
1961 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1962
1963 inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
1964 quantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1965
1966 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1967 quantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
1968
1969 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1970 BOOST_CHECK(deserializedNetwork);
1971
1972 QuantizeLayerVerifier verifier(layerName, {info}, {info});
1973 deserializedNetwork->Accept(verifier);
1974}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001975BOOST_AUTO_TEST_CASE(SerializeReshape)
1976{
1977 class ReshapeLayerVerifier : public LayerVerifierBase
1978 {
1979 public:
1980 ReshapeLayerVerifier(const std::string& layerName,
1981 const std::vector<armnn::TensorInfo>& inputInfos,
1982 const std::vector<armnn::TensorInfo>& outputInfos,
1983 const armnn::ReshapeDescriptor& descriptor)
1984 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1985 , m_Descriptor(descriptor) {}
1986
1987 void VisitReshapeLayer(const armnn::IConnectableLayer* layer,
1988 const armnn::ReshapeDescriptor& descriptor,
1989 const char* name) override
1990 {
1991 VerifyNameAndConnections(layer, name);
1992 VerifyDescriptor(descriptor);
1993 }
1994
1995 private:
1996 void VerifyDescriptor(const armnn::ReshapeDescriptor& descriptor)
1997 {
1998 BOOST_TEST(descriptor.m_TargetShape == m_Descriptor.m_TargetShape);
1999 }
2000
2001 armnn::ReshapeDescriptor m_Descriptor;
2002 };
2003
2004 const std::string layerName("reshape");
2005 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
2006 const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
2007
2008 armnn::ReshapeDescriptor descriptor({3, 3});
2009
2010 armnn::INetworkPtr network = armnn::INetwork::Create();
2011 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2012 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
2013 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2014
2015 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
2016 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2017
2018 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2019 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2020
2021 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2022 BOOST_CHECK(deserializedNetwork);
2023
2024 ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2025 deserializedNetwork->Accept(verifier);
2026}
2027
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002028BOOST_AUTO_TEST_CASE(SerializeResize)
2029{
2030 class ResizeLayerVerifier : public LayerVerifierBase
2031 {
2032 public:
2033 ResizeLayerVerifier(const std::string& layerName,
2034 const std::vector<armnn::TensorInfo>& inputInfos,
2035 const std::vector<armnn::TensorInfo>& outputInfos,
2036 const armnn::ResizeDescriptor& descriptor)
2037 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2038 , m_Descriptor(descriptor) {}
2039
2040 void VisitResizeLayer(const armnn::IConnectableLayer* layer,
2041 const armnn::ResizeDescriptor& descriptor,
2042 const char* name) override
2043 {
2044 VerifyNameAndConnections(layer, name);
2045 VerifyDescriptor(descriptor);
2046 }
2047
2048 private:
2049 void VerifyDescriptor(const armnn::ResizeDescriptor& descriptor)
2050 {
2051 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2052 BOOST_CHECK(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
2053 BOOST_CHECK(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
2054 BOOST_CHECK(descriptor.m_Method == m_Descriptor.m_Method);
2055 }
2056
2057 armnn::ResizeDescriptor m_Descriptor;
2058 };
2059
2060 const std::string layerName("resize");
2061 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2062 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2063
2064 armnn::ResizeDescriptor desc;
2065 desc.m_TargetWidth = 4;
2066 desc.m_TargetHeight = 2;
2067 desc.m_Method = armnn::ResizeMethod::NearestNeighbor;
2068
2069 armnn::INetworkPtr network = armnn::INetwork::Create();
2070 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2071 armnn::IConnectableLayer* const resizeLayer = network->AddResizeLayer(desc, layerName.c_str());
2072 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2073
2074 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2075 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2076
2077 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2078 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2079
2080 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2081 BOOST_CHECK(deserializedNetwork);
2082
2083 ResizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2084 deserializedNetwork->Accept(verifier);
2085}
2086
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002087BOOST_AUTO_TEST_CASE(SerializeResizeBilinear)
2088{
2089 class ResizeBilinearLayerVerifier : public LayerVerifierBase
2090 {
2091 public:
2092 ResizeBilinearLayerVerifier(const std::string& layerName,
2093 const std::vector<armnn::TensorInfo>& inputInfos,
2094 const std::vector<armnn::TensorInfo>& outputInfos,
2095 const armnn::ResizeBilinearDescriptor& descriptor)
2096 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2097 , m_Descriptor(descriptor) {}
2098
2099 void VisitResizeBilinearLayer(const armnn::IConnectableLayer* layer,
2100 const armnn::ResizeBilinearDescriptor& descriptor,
2101 const char* name) override
2102 {
2103 VerifyNameAndConnections(layer, name);
2104 VerifyDescriptor(descriptor);
2105 }
2106
2107 private:
2108 void VerifyDescriptor(const armnn::ResizeBilinearDescriptor& descriptor)
2109 {
2110 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2111 BOOST_TEST(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
2112 BOOST_TEST(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
2113 }
2114
2115 armnn::ResizeBilinearDescriptor m_Descriptor;
2116 };
2117
2118 const std::string layerName("resizeBilinear");
2119 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2120 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2121
2122 armnn::ResizeBilinearDescriptor desc;
2123 desc.m_TargetWidth = 4;
2124 desc.m_TargetHeight = 2;
2125
2126 armnn::INetworkPtr network = armnn::INetwork::Create();
2127 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2128 armnn::IConnectableLayer* const resizeLayer = network->AddResizeBilinearLayer(desc, layerName.c_str());
2129 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2130
2131 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2132 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2133
2134 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2135 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2136
2137 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2138 BOOST_CHECK(deserializedNetwork);
2139
2140 ResizeBilinearLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2141 deserializedNetwork->Accept(verifier);
2142}
2143
2144BOOST_AUTO_TEST_CASE(SerializeRsqrt)
2145{
2146 class RsqrtLayerVerifier : public LayerVerifierBase
2147 {
2148 public:
2149 RsqrtLayerVerifier(const std::string& layerName,
2150 const std::vector<armnn::TensorInfo>& inputInfos,
2151 const std::vector<armnn::TensorInfo>& outputInfos)
2152 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2153
2154 void VisitRsqrtLayer(const armnn::IConnectableLayer* layer, const char* name) override
2155 {
2156 VerifyNameAndConnections(layer, name);
2157 }
2158 };
2159
2160 const std::string layerName("rsqrt");
2161 const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32);
2162
2163 armnn::INetworkPtr network = armnn::INetwork::Create();
2164 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2165 armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer(layerName.c_str());
2166 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2167
2168 inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0));
2169 rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2170
2171 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2172 rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2173
2174 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2175 BOOST_CHECK(deserializedNetwork);
2176
2177 RsqrtLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
2178 deserializedNetwork->Accept(verifier);
2179}
2180
2181BOOST_AUTO_TEST_CASE(SerializeSoftmax)
2182{
2183 class SoftmaxLayerVerifier : public LayerVerifierBase
2184 {
2185 public:
2186 SoftmaxLayerVerifier(const std::string& layerName,
2187 const std::vector<armnn::TensorInfo>& inputInfos,
2188 const std::vector<armnn::TensorInfo>& outputInfos,
2189 const armnn::SoftmaxDescriptor& descriptor)
2190 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2191 , m_Descriptor(descriptor) {}
2192
2193 void VisitSoftmaxLayer(const armnn::IConnectableLayer* layer,
2194 const armnn::SoftmaxDescriptor& descriptor,
2195 const char* name) override
2196 {
2197 VerifyNameAndConnections(layer, name);
2198 VerifyDescriptor(descriptor);
2199 }
2200
2201 private:
2202 void VerifyDescriptor(const armnn::SoftmaxDescriptor& descriptor)
2203 {
2204 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
2205 }
2206
2207 armnn::SoftmaxDescriptor m_Descriptor;
2208 };
2209
2210 const std::string layerName("softmax");
2211 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
2212
2213 armnn::SoftmaxDescriptor descriptor;
2214 descriptor.m_Beta = 1.0f;
2215
2216 armnn::INetworkPtr network = armnn::INetwork::Create();
2217 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2218 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
2219 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2220
2221 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
2222 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2223
2224 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2225 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
2226
2227 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2228 BOOST_CHECK(deserializedNetwork);
2229
2230 SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
2231 deserializedNetwork->Accept(verifier);
2232}
2233
2234BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
2235{
2236 class SpaceToBatchNdLayerVerifier : public LayerVerifierBase
2237 {
2238 public:
2239 SpaceToBatchNdLayerVerifier(const std::string& layerName,
2240 const std::vector<armnn::TensorInfo>& inputInfos,
2241 const std::vector<armnn::TensorInfo>& outputInfos,
2242 const armnn::SpaceToBatchNdDescriptor& descriptor)
2243 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2244 , m_Descriptor(descriptor) {}
2245
2246 void VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer* layer,
2247 const armnn::SpaceToBatchNdDescriptor& descriptor,
2248 const char* name) override
2249 {
2250 VerifyNameAndConnections(layer, name);
2251 VerifyDescriptor(descriptor);
2252 }
2253
2254 private:
2255 void VerifyDescriptor(const armnn::SpaceToBatchNdDescriptor& descriptor)
2256 {
2257 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
2258 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
2259 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2260 }
2261
2262 armnn::SpaceToBatchNdDescriptor m_Descriptor;
2263 };
2264
2265 const std::string layerName("spaceToBatchNd");
2266 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
2267 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
2268
2269 armnn::SpaceToBatchNdDescriptor desc;
2270 desc.m_DataLayout = armnn::DataLayout::NCHW;
2271 desc.m_BlockShape = {2, 2};
2272 desc.m_PadList = {{0, 0}, {2, 0}};
2273
2274 armnn::INetworkPtr network = armnn::INetwork::Create();
2275 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2276 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2277 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2278
2279 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
2280 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2281
2282 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2283 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2284
2285 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2286 BOOST_CHECK(deserializedNetwork);
2287
2288 SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2289 deserializedNetwork->Accept(verifier);
2290}
2291
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002292BOOST_AUTO_TEST_CASE(SerializeSpaceToDepth)
2293{
2294 class SpaceToDepthLayerVerifier : public LayerVerifierBase
2295 {
2296 public:
2297 SpaceToDepthLayerVerifier(const std::string& layerName,
2298 const std::vector<armnn::TensorInfo>& inputInfos,
2299 const std::vector<armnn::TensorInfo>& outputInfos,
2300 const armnn::SpaceToDepthDescriptor& descriptor)
2301 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2302 , m_Descriptor(descriptor) {}
2303
2304 void VisitSpaceToDepthLayer(const armnn::IConnectableLayer* layer,
2305 const armnn::SpaceToDepthDescriptor& descriptor,
2306 const char* name) override
2307 {
2308 VerifyNameAndConnections(layer, name);
2309 VerifyDescriptor(descriptor);
2310 }
2311
2312 private:
2313 void VerifyDescriptor(const armnn::SpaceToDepthDescriptor& descriptor)
2314 {
2315 BOOST_TEST(descriptor.m_BlockSize == m_Descriptor.m_BlockSize);
2316 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2317 }
2318
2319 armnn::SpaceToDepthDescriptor m_Descriptor;
2320 };
2321
2322 const std::string layerName("spaceToDepth");
2323
2324 const armnn::TensorInfo inputInfo ({ 1, 16, 8, 3 }, armnn::DataType::Float32);
2325 const armnn::TensorInfo outputInfo({ 1, 8, 4, 12 }, armnn::DataType::Float32);
2326
2327 armnn::SpaceToDepthDescriptor desc;
2328 desc.m_BlockSize = 2;
2329 desc.m_DataLayout = armnn::DataLayout::NHWC;
2330
2331 armnn::INetworkPtr network = armnn::INetwork::Create();
2332 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2333 armnn::IConnectableLayer* const spaceToDepthLayer = network->AddSpaceToDepthLayer(desc, layerName.c_str());
2334 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2335
2336 inputLayer->GetOutputSlot(0).Connect(spaceToDepthLayer->GetInputSlot(0));
2337 spaceToDepthLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2338
2339 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2340 spaceToDepthLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2341
2342 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2343 BOOST_CHECK(deserializedNetwork);
2344
2345 SpaceToDepthLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2346 deserializedNetwork->Accept(verifier);
2347}
2348
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002349BOOST_AUTO_TEST_CASE(SerializeSplitter)
2350{
2351 class SplitterLayerVerifier : public LayerVerifierBase
2352 {
2353 public:
2354 SplitterLayerVerifier(const std::string& layerName,
2355 const std::vector<armnn::TensorInfo>& inputInfos,
2356 const std::vector<armnn::TensorInfo>& outputInfos,
2357 const armnn::ViewsDescriptor& descriptor)
2358 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2359 , m_Descriptor(descriptor) {}
2360
2361 void VisitSplitterLayer(const armnn::IConnectableLayer* layer,
2362 const armnn::ViewsDescriptor& descriptor,
2363 const char* name) override
2364 {
2365 VerifyNameAndConnections(layer, name);
2366 VerifyDescriptor(descriptor);
2367 }
2368
2369 private:
2370 void VerifyDescriptor(const armnn::ViewsDescriptor& descriptor)
2371 {
2372 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
2373 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
2374
2375 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
2376 {
2377 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
2378 {
2379 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
2380 BOOST_TEST(descriptor.GetViewSizes(i)[j] == m_Descriptor.GetViewSizes(i)[j]);
2381 }
2382 }
2383 }
2384
2385 armnn::ViewsDescriptor m_Descriptor;
2386 };
2387
2388 const unsigned int numViews = 3;
2389 const unsigned int numDimensions = 4;
2390 const unsigned int inputShape[] = {1, 18, 4, 4};
2391 const unsigned int outputShape[] = {1, 6, 4, 4};
2392
2393 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
2394 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
2395 static_cast<unsigned int>(inputShape[1]),
2396 static_cast<unsigned int>(inputShape[2]),
2397 static_cast<unsigned int>(inputShape[3])};
2398 splitterDimSizes[1] /= numViews;
2399 armnn::ViewsDescriptor desc(numViews, numDimensions);
2400
2401 for (unsigned int g = 0; g < numViews; ++g)
2402 {
2403 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
2404
2405 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
2406 {
2407 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
2408 }
2409 }
2410
2411 const std::string layerName("splitter");
2412 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
2413 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
2414
2415 armnn::INetworkPtr network = armnn::INetwork::Create();
2416 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2417 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
2418 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2419 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2420 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
2421
2422 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
2423 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2424 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2425 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
2426
2427 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2428 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2429 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
2430 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2431
2432 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2433 BOOST_CHECK(deserializedNetwork);
2434
2435 SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
2436 deserializedNetwork->Accept(verifier);
2437}
2438
2439BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
2440{
2441 class StridedSliceLayerVerifier : public LayerVerifierBase
2442 {
2443 public:
2444 StridedSliceLayerVerifier(const std::string& layerName,
2445 const std::vector<armnn::TensorInfo>& inputInfos,
2446 const std::vector<armnn::TensorInfo>& outputInfos,
2447 const armnn::StridedSliceDescriptor& descriptor)
2448 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2449 , m_Descriptor(descriptor) {}
2450
2451 void VisitStridedSliceLayer(const armnn::IConnectableLayer* layer,
2452 const armnn::StridedSliceDescriptor& descriptor,
2453 const char* name) override
2454 {
2455 VerifyNameAndConnections(layer, name);
2456 VerifyDescriptor(descriptor);
2457 }
2458
2459 private:
2460 void VerifyDescriptor(const armnn::StridedSliceDescriptor& descriptor)
2461 {
2462 BOOST_TEST(descriptor.m_Begin == m_Descriptor.m_Begin);
2463 BOOST_TEST(descriptor.m_End == m_Descriptor.m_End);
2464 BOOST_TEST(descriptor.m_Stride == m_Descriptor.m_Stride);
2465 BOOST_TEST(descriptor.m_BeginMask == m_Descriptor.m_BeginMask);
2466 BOOST_TEST(descriptor.m_EndMask == m_Descriptor.m_EndMask);
2467 BOOST_TEST(descriptor.m_ShrinkAxisMask == m_Descriptor.m_ShrinkAxisMask);
2468 BOOST_TEST(descriptor.m_EllipsisMask == m_Descriptor.m_EllipsisMask);
2469 BOOST_TEST(descriptor.m_NewAxisMask == m_Descriptor.m_NewAxisMask);
2470 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2471 }
2472 armnn::StridedSliceDescriptor m_Descriptor;
2473 };
2474
2475 const std::string layerName("stridedSlice");
2476 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2477 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2478
2479 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2480 desc.m_EndMask = (1 << 4) - 1;
2481 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2482 desc.m_DataLayout = armnn::DataLayout::NCHW;
2483
2484 armnn::INetworkPtr network = armnn::INetwork::Create();
2485 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2486 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2487 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2488
2489 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2490 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2491
2492 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2493 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2494
2495 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2496 BOOST_CHECK(deserializedNetwork);
2497
2498 StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2499 deserializedNetwork->Accept(verifier);
2500}
2501
2502BOOST_AUTO_TEST_CASE(SerializeSubtraction)
2503{
2504 class SubtractionLayerVerifier : public LayerVerifierBase
2505 {
2506 public:
2507 SubtractionLayerVerifier(const std::string& layerName,
2508 const std::vector<armnn::TensorInfo>& inputInfos,
2509 const std::vector<armnn::TensorInfo>& outputInfos)
2510 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2511
2512 void VisitSubtractionLayer(const armnn::IConnectableLayer* layer, const char* name) override
2513 {
2514 VerifyNameAndConnections(layer, name);
2515 }
2516 };
2517
2518 const std::string layerName("subtraction");
2519 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2520
2521 armnn::INetworkPtr network = armnn::INetwork::Create();
2522 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2523 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2524 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2525 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2526
2527 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2528 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2529 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2530
2531 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2532 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2533 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2534
2535 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2536 BOOST_CHECK(deserializedNetwork);
2537
2538 SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
2539 deserializedNetwork->Accept(verifier);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +00002540}
2541
Sadik Armaganeff363d2019-04-05 15:25:46 +01002542BOOST_AUTO_TEST_CASE(SerializeSwitch)
2543{
2544 class SwitchLayerVerifier : public LayerVerifierBase
2545 {
2546 public:
2547 SwitchLayerVerifier(const std::string& layerName,
2548 const std::vector<armnn::TensorInfo>& inputInfos,
2549 const std::vector<armnn::TensorInfo>& outputInfos)
2550 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2551
2552 void VisitSwitchLayer(const armnn::IConnectableLayer* layer, const char* name) override
2553 {
2554 VerifyNameAndConnections(layer, name);
2555 }
2556
2557 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2558 const armnn::ConstTensor& input,
2559 const char *name) override {}
2560 };
2561
2562 const std::string layerName("switch");
2563 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2564
2565 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2566 armnn::ConstTensor constTensor(info, constantData);
2567
2568 armnn::INetworkPtr network = armnn::INetwork::Create();
2569 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2570 armnn::IConnectableLayer* const constantLayer = network->AddConstantLayer(constTensor, "constant");
2571 armnn::IConnectableLayer* const switchLayer = network->AddSwitchLayer(layerName.c_str());
2572 armnn::IConnectableLayer* const trueOutputLayer = network->AddOutputLayer(0);
2573 armnn::IConnectableLayer* const falseOutputLayer = network->AddOutputLayer(1);
2574
2575 inputLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(0));
2576 constantLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(1));
2577 switchLayer->GetOutputSlot(0).Connect(trueOutputLayer->GetInputSlot(0));
2578 switchLayer->GetOutputSlot(1).Connect(falseOutputLayer->GetInputSlot(0));
2579
2580 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2581 constantLayer->GetOutputSlot(0).SetTensorInfo(info);
2582 switchLayer->GetOutputSlot(0).SetTensorInfo(info);
2583 switchLayer->GetOutputSlot(1).SetTensorInfo(info);
2584
2585 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2586 BOOST_CHECK(deserializedNetwork);
2587
2588 SwitchLayerVerifier verifier(layerName, {info, info}, {info, info});
2589 deserializedNetwork->Accept(verifier);
2590}
2591
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002592BOOST_AUTO_TEST_CASE(SerializeTransposeConvolution2d)
2593{
2594 class TransposeConvolution2dLayerVerifier : public LayerVerifierBase
2595 {
2596 public:
2597 TransposeConvolution2dLayerVerifier(const std::string& layerName,
2598 const std::vector<armnn::TensorInfo>& inputInfos,
2599 const std::vector<armnn::TensorInfo>& outputInfos,
2600 const armnn::TransposeConvolution2dDescriptor& descriptor,
2601 const armnn::ConstTensor& weights,
2602 const armnn::Optional<armnn::ConstTensor>& biases) :
2603 LayerVerifierBase(layerName, inputInfos, outputInfos),
2604 m_Descriptor(descriptor),
2605 m_Weights(weights),
2606 m_Biases(biases)
2607 {}
2608
2609 void VisitTransposeConvolution2dLayer(const armnn::IConnectableLayer* layer,
2610 const armnn::TransposeConvolution2dDescriptor& descriptor,
2611 const armnn::ConstTensor& weights,
2612 const armnn::Optional<armnn::ConstTensor>& biases,
2613 const char* name) override
2614 {
2615 VerifyNameAndConnections(layer, name);
2616 VerifyDescriptor(descriptor);
2617
2618 // check weights
2619 CompareConstTensor(weights, m_Weights);
2620
2621 // check biases
2622 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
2623 BOOST_CHECK(m_Biases.has_value() == m_Descriptor.m_BiasEnabled);
2624
2625 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
2626
2627 if (biases.has_value() && m_Biases.has_value())
2628 {
2629 CompareConstTensor(biases.value(), m_Biases.value());
2630 }
2631 }
2632
2633 private:
2634 void VerifyDescriptor(const armnn::TransposeConvolution2dDescriptor& descriptor)
2635 {
2636 BOOST_CHECK(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
2637 BOOST_CHECK(descriptor.m_PadRight == m_Descriptor.m_PadRight);
2638 BOOST_CHECK(descriptor.m_PadTop == m_Descriptor.m_PadTop);
2639 BOOST_CHECK(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
2640 BOOST_CHECK(descriptor.m_StrideX == m_Descriptor.m_StrideX);
2641 BOOST_CHECK(descriptor.m_StrideY == m_Descriptor.m_StrideY);
2642 BOOST_CHECK(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
2643 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2644 }
2645
2646 armnn::TransposeConvolution2dDescriptor m_Descriptor;
2647 armnn::ConstTensor m_Weights;
2648 armnn::Optional<armnn::ConstTensor> m_Biases;
2649 };
2650
2651 const std::string layerName("transposeConvolution2d");
2652 const armnn::TensorInfo inputInfo ({ 1, 7, 7, 1 }, armnn::DataType::Float32);
2653 const armnn::TensorInfo outputInfo({ 1, 9, 9, 1 }, armnn::DataType::Float32);
2654
2655 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
2656 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
2657
2658 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
2659 armnn::ConstTensor weights(weightsInfo, weightsData);
2660
2661 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
2662 armnn::ConstTensor biases(biasesInfo, biasesData);
2663
2664 armnn::TransposeConvolution2dDescriptor descriptor;
2665 descriptor.m_PadLeft = 1;
2666 descriptor.m_PadRight = 1;
2667 descriptor.m_PadTop = 1;
2668 descriptor.m_PadBottom = 1;
2669 descriptor.m_StrideX = 1;
2670 descriptor.m_StrideY = 1;
2671 descriptor.m_BiasEnabled = true;
2672 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
2673
2674 armnn::INetworkPtr network = armnn::INetwork::Create();
2675 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2676 armnn::IConnectableLayer* const convLayer =
2677 network->AddTransposeConvolution2dLayer(descriptor,
2678 weights,
2679 armnn::Optional<armnn::ConstTensor>(biases),
2680 layerName.c_str());
2681 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2682
2683 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
2684 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2685
2686 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2687 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2688
2689 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2690 BOOST_CHECK(deserializedNetwork);
2691
2692 TransposeConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
2693 deserializedNetwork->Accept(verifier);
2694}
2695
Sadik Armagandb059fd2019-03-20 12:28:32 +00002696BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
2697{
2698 class ConstantLayerVerifier : public LayerVerifierBase
2699 {
2700 public:
2701 ConstantLayerVerifier(const std::string& layerName,
2702 const std::vector<armnn::TensorInfo>& inputInfos,
2703 const std::vector<armnn::TensorInfo>& outputInfos,
2704 const armnn::ConstTensor& layerInput)
2705 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2706 , m_LayerInput(layerInput) {}
2707
2708 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2709 const armnn::ConstTensor& input,
2710 const char* name) override
2711 {
2712 VerifyNameAndConnections(layer, name);
2713
2714 CompareConstTensor(input, m_LayerInput);
2715 }
2716
2717 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
2718
2719 private:
2720 armnn::ConstTensor m_LayerInput;
2721 };
2722
2723 const std::string layerName("constant");
2724 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
2725
2726 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2727 armnn::ConstTensor constTensor(info, constantData);
2728
2729 armnn::INetworkPtr network(armnn::INetwork::Create());
2730 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2731 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2732 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2733 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2734
2735 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2736 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2737 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2738
2739 input->GetOutputSlot(0).SetTensorInfo(info);
2740 constant->GetOutputSlot(0).SetTensorInfo(info);
2741 add->GetOutputSlot(0).SetTensorInfo(info);
2742
2743 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2744 BOOST_CHECK(deserializedNetwork);
2745
2746 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
2747 deserializedNetwork->Accept(verifier);
2748}
2749
Jim Flynn11af3752019-03-19 17:22:29 +00002750class VerifyLstmLayer : public LayerVerifierBase
2751{
2752public:
2753 VerifyLstmLayer(const std::string& layerName,
2754 const std::vector<armnn::TensorInfo>& inputInfos,
2755 const std::vector<armnn::TensorInfo>& outputInfos,
2756 const armnn::LstmDescriptor& descriptor,
2757 const armnn::LstmInputParams& inputParams) :
2758 LayerVerifierBase(layerName, inputInfos, outputInfos), m_Descriptor(descriptor), m_InputParams(inputParams)
2759 {
2760 }
2761 void VisitLstmLayer(const armnn::IConnectableLayer* layer,
2762 const armnn::LstmDescriptor& descriptor,
2763 const armnn::LstmInputParams& params,
2764 const char* name)
2765 {
2766 VerifyNameAndConnections(layer, name);
2767 VerifyDescriptor(descriptor);
2768 VerifyInputParameters(params);
2769 }
2770protected:
2771 void VerifyDescriptor(const armnn::LstmDescriptor& descriptor)
2772 {
2773 BOOST_TEST(m_Descriptor.m_ActivationFunc == descriptor.m_ActivationFunc);
2774 BOOST_TEST(m_Descriptor.m_ClippingThresCell == descriptor.m_ClippingThresCell);
2775 BOOST_TEST(m_Descriptor.m_ClippingThresProj == descriptor.m_ClippingThresProj);
2776 BOOST_TEST(m_Descriptor.m_CifgEnabled == descriptor.m_CifgEnabled);
2777 BOOST_TEST(m_Descriptor.m_PeepholeEnabled = descriptor.m_PeepholeEnabled);
2778 BOOST_TEST(m_Descriptor.m_ProjectionEnabled == descriptor.m_ProjectionEnabled);
2779 }
2780 void VerifyInputParameters(const armnn::LstmInputParams& params)
2781 {
2782 VerifyConstTensors(
2783 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
2784 VerifyConstTensors(
2785 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
2786 VerifyConstTensors(
2787 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
2788 VerifyConstTensors(
2789 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
2790 VerifyConstTensors(
2791 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
2792 VerifyConstTensors(
2793 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
2794 VerifyConstTensors(
2795 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
2796 VerifyConstTensors(
2797 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
2798 VerifyConstTensors(
2799 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
2800 VerifyConstTensors(
2801 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
2802 VerifyConstTensors(
2803 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
2804 VerifyConstTensors(
2805 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
2806 VerifyConstTensors(
2807 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
2808 VerifyConstTensors(
2809 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
2810 VerifyConstTensors(
2811 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
2812 VerifyConstTensors(
2813 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
2814 VerifyConstTensors(
2815 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
2816 }
2817 void VerifyConstTensors(const std::string& tensorName,
2818 const armnn::ConstTensor* expectedPtr,
2819 const armnn::ConstTensor* actualPtr)
2820 {
2821 if (expectedPtr == nullptr)
2822 {
2823 BOOST_CHECK_MESSAGE(actualPtr == nullptr, tensorName + " should not exist");
2824 }
2825 else
2826 {
2827 BOOST_CHECK_MESSAGE(actualPtr != nullptr, tensorName + " should have been set");
2828 if (actualPtr != nullptr)
2829 {
2830 const armnn::TensorInfo& expectedInfo = expectedPtr->GetInfo();
2831 const armnn::TensorInfo& actualInfo = actualPtr->GetInfo();
2832
2833 BOOST_CHECK_MESSAGE(expectedInfo.GetShape() == actualInfo.GetShape(),
2834 tensorName + " shapes don't match");
2835 BOOST_CHECK_MESSAGE(
2836 GetDataTypeName(expectedInfo.GetDataType()) == GetDataTypeName(actualInfo.GetDataType()),
2837 tensorName + " data types don't match");
2838
2839 BOOST_CHECK_MESSAGE(expectedPtr->GetNumBytes() == actualPtr->GetNumBytes(),
2840 tensorName + " (GetNumBytes) data sizes do not match");
2841 if (expectedPtr->GetNumBytes() == actualPtr->GetNumBytes())
2842 {
2843 //check the data is identical
2844 const char* expectedData = static_cast<const char*>(expectedPtr->GetMemoryArea());
2845 const char* actualData = static_cast<const char*>(actualPtr->GetMemoryArea());
2846 bool same = true;
2847 for (unsigned int i = 0; i < expectedPtr->GetNumBytes(); ++i)
2848 {
2849 same = expectedData[i] == actualData[i];
2850 if (!same)
2851 {
2852 break;
2853 }
2854 }
2855 BOOST_CHECK_MESSAGE(same, tensorName + " data does not match");
2856 }
2857 }
2858 }
2859 }
2860private:
2861 armnn::LstmDescriptor m_Descriptor;
2862 armnn::LstmInputParams m_InputParams;
2863};
2864
2865BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
2866{
2867 armnn::LstmDescriptor descriptor;
2868 descriptor.m_ActivationFunc = 4;
2869 descriptor.m_ClippingThresProj = 0.0f;
2870 descriptor.m_ClippingThresCell = 0.0f;
2871 descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
2872 descriptor.m_ProjectionEnabled = false;
2873 descriptor.m_PeepholeEnabled = true;
2874
2875 const uint32_t batchSize = 1;
2876 const uint32_t inputSize = 2;
2877 const uint32_t numUnits = 4;
2878 const uint32_t outputSize = numUnits;
2879
2880 armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
2881 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2882 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
2883
2884 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2885 armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
2886
2887 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2888 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
2889
2890 armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
2891 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2892 armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
2893
2894 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2895 armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
2896
2897 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2898 armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
2899
2900 armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
2901 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2902 armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
2903
2904 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2905 armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
2906
2907 std::vector<float> forgetGateBiasData(numUnits, 1.0f);
2908 armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
2909
2910 std::vector<float> cellBiasData(numUnits, 0.0f);
2911 armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
2912
2913 std::vector<float> outputGateBiasData(numUnits, 0.0f);
2914 armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
2915
2916 armnn::LstmInputParams params;
2917 params.m_InputToForgetWeights = &inputToForgetWeights;
2918 params.m_InputToCellWeights = &inputToCellWeights;
2919 params.m_InputToOutputWeights = &inputToOutputWeights;
2920 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2921 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2922 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2923 params.m_ForgetGateBias = &forgetGateBias;
2924 params.m_CellBias = &cellBias;
2925 params.m_OutputGateBias = &outputGateBias;
2926 params.m_CellToForgetWeights = &cellToForgetWeights;
2927 params.m_CellToOutputWeights = &cellToOutputWeights;
2928
2929 armnn::INetworkPtr network = armnn::INetwork::Create();
2930 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2931 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2932 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2933 const std::string layerName("lstm");
2934 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2935 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2936 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2937 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2938 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2939
2940 // connect up
2941 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2942 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2943 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2944 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
2945
2946 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2947 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2948
2949 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2950 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2951
2952 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2953 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2954
2955 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2956 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2957
2958 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2959 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2960
2961 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2962 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2963
2964 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2965 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2966
2967 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2968 BOOST_CHECK(deserializedNetwork);
2969
2970 VerifyLstmLayer checker(
2971 layerName,
2972 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2973 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2974 descriptor,
2975 params);
2976 deserializedNetwork->Accept(checker);
2977}
2978
2979BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
2980{
2981 armnn::LstmDescriptor descriptor;
2982 descriptor.m_ActivationFunc = 4;
2983 descriptor.m_ClippingThresProj = 0.0f;
2984 descriptor.m_ClippingThresCell = 0.0f;
2985 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
2986 descriptor.m_ProjectionEnabled = true;
2987 descriptor.m_PeepholeEnabled = true;
2988
2989 const uint32_t batchSize = 2;
2990 const uint32_t inputSize = 5;
2991 const uint32_t numUnits = 20;
2992 const uint32_t outputSize = 16;
2993
2994 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
2995 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2996 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
2997
2998 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2999 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
3000
3001 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3002 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
3003
3004 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
3005 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
3006
3007 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
3008 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3009 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
3010
3011 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3012 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
3013
3014 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3015 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
3016
3017 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3018 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
3019
3020 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
3021 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3022 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
3023
3024 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3025 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
3026
3027 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3028 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
3029
3030 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
3031 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
3032
3033 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3034 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
3035
3036 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3037 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
3038
3039 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
3040 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
3041
3042 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
3043 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
3044 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
3045
3046 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
3047 std::vector<float> projectionBiasData(outputSize, 0.f);
3048 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
3049
3050 armnn::LstmInputParams params;
3051 params.m_InputToForgetWeights = &inputToForgetWeights;
3052 params.m_InputToCellWeights = &inputToCellWeights;
3053 params.m_InputToOutputWeights = &inputToOutputWeights;
3054 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3055 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
3056 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3057 params.m_ForgetGateBias = &forgetGateBias;
3058 params.m_CellBias = &cellBias;
3059 params.m_OutputGateBias = &outputGateBias;
3060
3061 // additional params because: descriptor.m_CifgEnabled = false
3062 params.m_InputToInputWeights = &inputToInputWeights;
3063 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3064 params.m_CellToInputWeights = &cellToInputWeights;
3065 params.m_InputGateBias = &inputGateBias;
3066
3067 // additional params because: descriptor.m_ProjectionEnabled = true
3068 params.m_ProjectionWeights = &projectionWeights;
3069 params.m_ProjectionBias = &projectionBias;
3070
3071 // additional params because: descriptor.m_PeepholeEnabled = true
3072 params.m_CellToForgetWeights = &cellToForgetWeights;
3073 params.m_CellToOutputWeights = &cellToOutputWeights;
3074
3075 armnn::INetworkPtr network = armnn::INetwork::Create();
3076 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3077 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3078 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3079 const std::string layerName("lstm");
3080 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3081 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3082 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3083 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3084 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3085
3086 // connect up
3087 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3088 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3089 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3090 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3091
3092 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3093 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3094
3095 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3096 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3097
3098 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3099 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3100
3101 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3102 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3103
3104 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3105 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3106
3107 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3108 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3109
3110 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3111 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3112
3113 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3114 BOOST_CHECK(deserializedNetwork);
3115
3116 VerifyLstmLayer checker(
3117 layerName,
3118 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3119 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3120 descriptor,
3121 params);
3122 deserializedNetwork->Accept(checker);
3123}
3124
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00003125BOOST_AUTO_TEST_SUITE_END()