blob: 33f10ef435b6ee6ebb9e72084090fe8380151cfe [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);
Aron Virginas-Tarf3569052019-07-05 16:01:08 +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 {
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002051 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2052 BOOST_CHECK(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002053 BOOST_CHECK(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002054 BOOST_CHECK(descriptor.m_Method == m_Descriptor.m_Method);
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002055 }
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;
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002065 desc.m_TargetWidth = 4;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002066 desc.m_TargetHeight = 2;
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01002067 desc.m_Method = armnn::ResizeMethod::NearestNeighbor;
FinnWilliamsArm6fb339a2019-06-28 15:07:10 +01002068
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(SerializeRsqrt)
2088{
2089 class RsqrtLayerVerifier : public LayerVerifierBase
2090 {
2091 public:
2092 RsqrtLayerVerifier(const std::string& layerName,
2093 const std::vector<armnn::TensorInfo>& inputInfos,
2094 const std::vector<armnn::TensorInfo>& outputInfos)
2095 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2096
2097 void VisitRsqrtLayer(const armnn::IConnectableLayer* layer, const char* name) override
2098 {
2099 VerifyNameAndConnections(layer, name);
2100 }
2101 };
2102
2103 const std::string layerName("rsqrt");
2104 const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32);
2105
2106 armnn::INetworkPtr network = armnn::INetwork::Create();
2107 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2108 armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer(layerName.c_str());
2109 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2110
2111 inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0));
2112 rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2113
2114 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2115 rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2116
2117 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2118 BOOST_CHECK(deserializedNetwork);
2119
2120 RsqrtLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
2121 deserializedNetwork->Accept(verifier);
2122}
2123
2124BOOST_AUTO_TEST_CASE(SerializeSoftmax)
2125{
2126 class SoftmaxLayerVerifier : public LayerVerifierBase
2127 {
2128 public:
2129 SoftmaxLayerVerifier(const std::string& layerName,
2130 const std::vector<armnn::TensorInfo>& inputInfos,
2131 const std::vector<armnn::TensorInfo>& outputInfos,
2132 const armnn::SoftmaxDescriptor& descriptor)
2133 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2134 , m_Descriptor(descriptor) {}
2135
2136 void VisitSoftmaxLayer(const armnn::IConnectableLayer* layer,
2137 const armnn::SoftmaxDescriptor& descriptor,
2138 const char* name) override
2139 {
2140 VerifyNameAndConnections(layer, name);
2141 VerifyDescriptor(descriptor);
2142 }
2143
2144 private:
2145 void VerifyDescriptor(const armnn::SoftmaxDescriptor& descriptor)
2146 {
2147 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
2148 }
2149
2150 armnn::SoftmaxDescriptor m_Descriptor;
2151 };
2152
2153 const std::string layerName("softmax");
2154 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
2155
2156 armnn::SoftmaxDescriptor descriptor;
2157 descriptor.m_Beta = 1.0f;
2158
2159 armnn::INetworkPtr network = armnn::INetwork::Create();
2160 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2161 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
2162 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2163
2164 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
2165 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2166
2167 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2168 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
2169
2170 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2171 BOOST_CHECK(deserializedNetwork);
2172
2173 SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
2174 deserializedNetwork->Accept(verifier);
2175}
2176
2177BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
2178{
2179 class SpaceToBatchNdLayerVerifier : public LayerVerifierBase
2180 {
2181 public:
2182 SpaceToBatchNdLayerVerifier(const std::string& layerName,
2183 const std::vector<armnn::TensorInfo>& inputInfos,
2184 const std::vector<armnn::TensorInfo>& outputInfos,
2185 const armnn::SpaceToBatchNdDescriptor& descriptor)
2186 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2187 , m_Descriptor(descriptor) {}
2188
2189 void VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer* layer,
2190 const armnn::SpaceToBatchNdDescriptor& descriptor,
2191 const char* name) override
2192 {
2193 VerifyNameAndConnections(layer, name);
2194 VerifyDescriptor(descriptor);
2195 }
2196
2197 private:
2198 void VerifyDescriptor(const armnn::SpaceToBatchNdDescriptor& descriptor)
2199 {
2200 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
2201 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
2202 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2203 }
2204
2205 armnn::SpaceToBatchNdDescriptor m_Descriptor;
2206 };
2207
2208 const std::string layerName("spaceToBatchNd");
2209 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
2210 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
2211
2212 armnn::SpaceToBatchNdDescriptor desc;
2213 desc.m_DataLayout = armnn::DataLayout::NCHW;
2214 desc.m_BlockShape = {2, 2};
2215 desc.m_PadList = {{0, 0}, {2, 0}};
2216
2217 armnn::INetworkPtr network = armnn::INetwork::Create();
2218 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2219 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2220 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2221
2222 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
2223 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2224
2225 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2226 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2227
2228 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2229 BOOST_CHECK(deserializedNetwork);
2230
2231 SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2232 deserializedNetwork->Accept(verifier);
2233}
2234
Aron Virginas-Taraa067142019-06-11 16:01:44 +01002235BOOST_AUTO_TEST_CASE(SerializeSpaceToDepth)
2236{
2237 class SpaceToDepthLayerVerifier : public LayerVerifierBase
2238 {
2239 public:
2240 SpaceToDepthLayerVerifier(const std::string& layerName,
2241 const std::vector<armnn::TensorInfo>& inputInfos,
2242 const std::vector<armnn::TensorInfo>& outputInfos,
2243 const armnn::SpaceToDepthDescriptor& descriptor)
2244 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2245 , m_Descriptor(descriptor) {}
2246
2247 void VisitSpaceToDepthLayer(const armnn::IConnectableLayer* layer,
2248 const armnn::SpaceToDepthDescriptor& descriptor,
2249 const char* name) override
2250 {
2251 VerifyNameAndConnections(layer, name);
2252 VerifyDescriptor(descriptor);
2253 }
2254
2255 private:
2256 void VerifyDescriptor(const armnn::SpaceToDepthDescriptor& descriptor)
2257 {
2258 BOOST_TEST(descriptor.m_BlockSize == m_Descriptor.m_BlockSize);
2259 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2260 }
2261
2262 armnn::SpaceToDepthDescriptor m_Descriptor;
2263 };
2264
2265 const std::string layerName("spaceToDepth");
2266
2267 const armnn::TensorInfo inputInfo ({ 1, 16, 8, 3 }, armnn::DataType::Float32);
2268 const armnn::TensorInfo outputInfo({ 1, 8, 4, 12 }, armnn::DataType::Float32);
2269
2270 armnn::SpaceToDepthDescriptor desc;
2271 desc.m_BlockSize = 2;
2272 desc.m_DataLayout = armnn::DataLayout::NHWC;
2273
2274 armnn::INetworkPtr network = armnn::INetwork::Create();
2275 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2276 armnn::IConnectableLayer* const spaceToDepthLayer = network->AddSpaceToDepthLayer(desc, layerName.c_str());
2277 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2278
2279 inputLayer->GetOutputSlot(0).Connect(spaceToDepthLayer->GetInputSlot(0));
2280 spaceToDepthLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2281
2282 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2283 spaceToDepthLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2284
2285 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2286 BOOST_CHECK(deserializedNetwork);
2287
2288 SpaceToDepthLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2289 deserializedNetwork->Accept(verifier);
2290}
2291
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00002292BOOST_AUTO_TEST_CASE(SerializeSplitter)
2293{
2294 class SplitterLayerVerifier : public LayerVerifierBase
2295 {
2296 public:
2297 SplitterLayerVerifier(const std::string& layerName,
2298 const std::vector<armnn::TensorInfo>& inputInfos,
2299 const std::vector<armnn::TensorInfo>& outputInfos,
2300 const armnn::ViewsDescriptor& descriptor)
2301 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2302 , m_Descriptor(descriptor) {}
2303
2304 void VisitSplitterLayer(const armnn::IConnectableLayer* layer,
2305 const armnn::ViewsDescriptor& descriptor,
2306 const char* name) override
2307 {
2308 VerifyNameAndConnections(layer, name);
2309 VerifyDescriptor(descriptor);
2310 }
2311
2312 private:
2313 void VerifyDescriptor(const armnn::ViewsDescriptor& descriptor)
2314 {
2315 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
2316 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
2317
2318 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
2319 {
2320 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
2321 {
2322 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
2323 BOOST_TEST(descriptor.GetViewSizes(i)[j] == m_Descriptor.GetViewSizes(i)[j]);
2324 }
2325 }
2326 }
2327
2328 armnn::ViewsDescriptor m_Descriptor;
2329 };
2330
2331 const unsigned int numViews = 3;
2332 const unsigned int numDimensions = 4;
2333 const unsigned int inputShape[] = {1, 18, 4, 4};
2334 const unsigned int outputShape[] = {1, 6, 4, 4};
2335
2336 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
2337 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
2338 static_cast<unsigned int>(inputShape[1]),
2339 static_cast<unsigned int>(inputShape[2]),
2340 static_cast<unsigned int>(inputShape[3])};
2341 splitterDimSizes[1] /= numViews;
2342 armnn::ViewsDescriptor desc(numViews, numDimensions);
2343
2344 for (unsigned int g = 0; g < numViews; ++g)
2345 {
2346 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
2347
2348 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
2349 {
2350 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
2351 }
2352 }
2353
2354 const std::string layerName("splitter");
2355 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
2356 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
2357
2358 armnn::INetworkPtr network = armnn::INetwork::Create();
2359 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2360 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
2361 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2362 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2363 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
2364
2365 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
2366 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2367 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2368 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
2369
2370 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2371 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2372 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
2373 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2374
2375 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2376 BOOST_CHECK(deserializedNetwork);
2377
2378 SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
2379 deserializedNetwork->Accept(verifier);
2380}
2381
2382BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
2383{
2384 class StridedSliceLayerVerifier : public LayerVerifierBase
2385 {
2386 public:
2387 StridedSliceLayerVerifier(const std::string& layerName,
2388 const std::vector<armnn::TensorInfo>& inputInfos,
2389 const std::vector<armnn::TensorInfo>& outputInfos,
2390 const armnn::StridedSliceDescriptor& descriptor)
2391 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2392 , m_Descriptor(descriptor) {}
2393
2394 void VisitStridedSliceLayer(const armnn::IConnectableLayer* layer,
2395 const armnn::StridedSliceDescriptor& descriptor,
2396 const char* name) override
2397 {
2398 VerifyNameAndConnections(layer, name);
2399 VerifyDescriptor(descriptor);
2400 }
2401
2402 private:
2403 void VerifyDescriptor(const armnn::StridedSliceDescriptor& descriptor)
2404 {
2405 BOOST_TEST(descriptor.m_Begin == m_Descriptor.m_Begin);
2406 BOOST_TEST(descriptor.m_End == m_Descriptor.m_End);
2407 BOOST_TEST(descriptor.m_Stride == m_Descriptor.m_Stride);
2408 BOOST_TEST(descriptor.m_BeginMask == m_Descriptor.m_BeginMask);
2409 BOOST_TEST(descriptor.m_EndMask == m_Descriptor.m_EndMask);
2410 BOOST_TEST(descriptor.m_ShrinkAxisMask == m_Descriptor.m_ShrinkAxisMask);
2411 BOOST_TEST(descriptor.m_EllipsisMask == m_Descriptor.m_EllipsisMask);
2412 BOOST_TEST(descriptor.m_NewAxisMask == m_Descriptor.m_NewAxisMask);
2413 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2414 }
2415 armnn::StridedSliceDescriptor m_Descriptor;
2416 };
2417
2418 const std::string layerName("stridedSlice");
2419 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2420 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2421
2422 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2423 desc.m_EndMask = (1 << 4) - 1;
2424 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2425 desc.m_DataLayout = armnn::DataLayout::NCHW;
2426
2427 armnn::INetworkPtr network = armnn::INetwork::Create();
2428 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2429 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2430 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2431
2432 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2433 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2434
2435 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2436 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2437
2438 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2439 BOOST_CHECK(deserializedNetwork);
2440
2441 StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2442 deserializedNetwork->Accept(verifier);
2443}
2444
2445BOOST_AUTO_TEST_CASE(SerializeSubtraction)
2446{
2447 class SubtractionLayerVerifier : public LayerVerifierBase
2448 {
2449 public:
2450 SubtractionLayerVerifier(const std::string& layerName,
2451 const std::vector<armnn::TensorInfo>& inputInfos,
2452 const std::vector<armnn::TensorInfo>& outputInfos)
2453 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2454
2455 void VisitSubtractionLayer(const armnn::IConnectableLayer* layer, const char* name) override
2456 {
2457 VerifyNameAndConnections(layer, name);
2458 }
2459 };
2460
2461 const std::string layerName("subtraction");
2462 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2463
2464 armnn::INetworkPtr network = armnn::INetwork::Create();
2465 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2466 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2467 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2468 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2469
2470 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2471 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2472 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2473
2474 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2475 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2476 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2477
2478 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2479 BOOST_CHECK(deserializedNetwork);
2480
2481 SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
2482 deserializedNetwork->Accept(verifier);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +00002483}
2484
Sadik Armaganeff363d2019-04-05 15:25:46 +01002485BOOST_AUTO_TEST_CASE(SerializeSwitch)
2486{
2487 class SwitchLayerVerifier : public LayerVerifierBase
2488 {
2489 public:
2490 SwitchLayerVerifier(const std::string& layerName,
2491 const std::vector<armnn::TensorInfo>& inputInfos,
2492 const std::vector<armnn::TensorInfo>& outputInfos)
2493 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2494
2495 void VisitSwitchLayer(const armnn::IConnectableLayer* layer, const char* name) override
2496 {
2497 VerifyNameAndConnections(layer, name);
2498 }
2499
2500 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2501 const armnn::ConstTensor& input,
2502 const char *name) override {}
2503 };
2504
2505 const std::string layerName("switch");
2506 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2507
2508 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2509 armnn::ConstTensor constTensor(info, constantData);
2510
2511 armnn::INetworkPtr network = armnn::INetwork::Create();
2512 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2513 armnn::IConnectableLayer* const constantLayer = network->AddConstantLayer(constTensor, "constant");
2514 armnn::IConnectableLayer* const switchLayer = network->AddSwitchLayer(layerName.c_str());
2515 armnn::IConnectableLayer* const trueOutputLayer = network->AddOutputLayer(0);
2516 armnn::IConnectableLayer* const falseOutputLayer = network->AddOutputLayer(1);
2517
2518 inputLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(0));
2519 constantLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(1));
2520 switchLayer->GetOutputSlot(0).Connect(trueOutputLayer->GetInputSlot(0));
2521 switchLayer->GetOutputSlot(1).Connect(falseOutputLayer->GetInputSlot(0));
2522
2523 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2524 constantLayer->GetOutputSlot(0).SetTensorInfo(info);
2525 switchLayer->GetOutputSlot(0).SetTensorInfo(info);
2526 switchLayer->GetOutputSlot(1).SetTensorInfo(info);
2527
2528 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2529 BOOST_CHECK(deserializedNetwork);
2530
2531 SwitchLayerVerifier verifier(layerName, {info, info}, {info, info});
2532 deserializedNetwork->Accept(verifier);
2533}
2534
Aron Virginas-Tarcb549302019-06-21 13:53:38 +01002535BOOST_AUTO_TEST_CASE(SerializeTransposeConvolution2d)
2536{
2537 class TransposeConvolution2dLayerVerifier : public LayerVerifierBase
2538 {
2539 public:
2540 TransposeConvolution2dLayerVerifier(const std::string& layerName,
2541 const std::vector<armnn::TensorInfo>& inputInfos,
2542 const std::vector<armnn::TensorInfo>& outputInfos,
2543 const armnn::TransposeConvolution2dDescriptor& descriptor,
2544 const armnn::ConstTensor& weights,
2545 const armnn::Optional<armnn::ConstTensor>& biases) :
2546 LayerVerifierBase(layerName, inputInfos, outputInfos),
2547 m_Descriptor(descriptor),
2548 m_Weights(weights),
2549 m_Biases(biases)
2550 {}
2551
2552 void VisitTransposeConvolution2dLayer(const armnn::IConnectableLayer* layer,
2553 const armnn::TransposeConvolution2dDescriptor& descriptor,
2554 const armnn::ConstTensor& weights,
2555 const armnn::Optional<armnn::ConstTensor>& biases,
2556 const char* name) override
2557 {
2558 VerifyNameAndConnections(layer, name);
2559 VerifyDescriptor(descriptor);
2560
2561 // check weights
2562 CompareConstTensor(weights, m_Weights);
2563
2564 // check biases
2565 BOOST_CHECK(biases.has_value() == descriptor.m_BiasEnabled);
2566 BOOST_CHECK(m_Biases.has_value() == m_Descriptor.m_BiasEnabled);
2567
2568 BOOST_CHECK(biases.has_value() == m_Biases.has_value());
2569
2570 if (biases.has_value() && m_Biases.has_value())
2571 {
2572 CompareConstTensor(biases.value(), m_Biases.value());
2573 }
2574 }
2575
2576 private:
2577 void VerifyDescriptor(const armnn::TransposeConvolution2dDescriptor& descriptor)
2578 {
2579 BOOST_CHECK(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
2580 BOOST_CHECK(descriptor.m_PadRight == m_Descriptor.m_PadRight);
2581 BOOST_CHECK(descriptor.m_PadTop == m_Descriptor.m_PadTop);
2582 BOOST_CHECK(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
2583 BOOST_CHECK(descriptor.m_StrideX == m_Descriptor.m_StrideX);
2584 BOOST_CHECK(descriptor.m_StrideY == m_Descriptor.m_StrideY);
2585 BOOST_CHECK(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
2586 BOOST_CHECK(descriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2587 }
2588
2589 armnn::TransposeConvolution2dDescriptor m_Descriptor;
2590 armnn::ConstTensor m_Weights;
2591 armnn::Optional<armnn::ConstTensor> m_Biases;
2592 };
2593
2594 const std::string layerName("transposeConvolution2d");
2595 const armnn::TensorInfo inputInfo ({ 1, 7, 7, 1 }, armnn::DataType::Float32);
2596 const armnn::TensorInfo outputInfo({ 1, 9, 9, 1 }, armnn::DataType::Float32);
2597
2598 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
2599 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
2600
2601 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
2602 armnn::ConstTensor weights(weightsInfo, weightsData);
2603
2604 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
2605 armnn::ConstTensor biases(biasesInfo, biasesData);
2606
2607 armnn::TransposeConvolution2dDescriptor descriptor;
2608 descriptor.m_PadLeft = 1;
2609 descriptor.m_PadRight = 1;
2610 descriptor.m_PadTop = 1;
2611 descriptor.m_PadBottom = 1;
2612 descriptor.m_StrideX = 1;
2613 descriptor.m_StrideY = 1;
2614 descriptor.m_BiasEnabled = true;
2615 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
2616
2617 armnn::INetworkPtr network = armnn::INetwork::Create();
2618 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2619 armnn::IConnectableLayer* const convLayer =
2620 network->AddTransposeConvolution2dLayer(descriptor,
2621 weights,
2622 armnn::Optional<armnn::ConstTensor>(biases),
2623 layerName.c_str());
2624 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2625
2626 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
2627 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2628
2629 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2630 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2631
2632 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2633 BOOST_CHECK(deserializedNetwork);
2634
2635 TransposeConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
2636 deserializedNetwork->Accept(verifier);
2637}
2638
Sadik Armagandb059fd2019-03-20 12:28:32 +00002639BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
2640{
2641 class ConstantLayerVerifier : public LayerVerifierBase
2642 {
2643 public:
2644 ConstantLayerVerifier(const std::string& layerName,
2645 const std::vector<armnn::TensorInfo>& inputInfos,
2646 const std::vector<armnn::TensorInfo>& outputInfos,
2647 const armnn::ConstTensor& layerInput)
2648 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2649 , m_LayerInput(layerInput) {}
2650
2651 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2652 const armnn::ConstTensor& input,
2653 const char* name) override
2654 {
2655 VerifyNameAndConnections(layer, name);
2656
2657 CompareConstTensor(input, m_LayerInput);
2658 }
2659
2660 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
2661
2662 private:
2663 armnn::ConstTensor m_LayerInput;
2664 };
2665
2666 const std::string layerName("constant");
2667 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
2668
2669 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2670 armnn::ConstTensor constTensor(info, constantData);
2671
2672 armnn::INetworkPtr network(armnn::INetwork::Create());
2673 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2674 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2675 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2676 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2677
2678 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2679 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2680 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2681
2682 input->GetOutputSlot(0).SetTensorInfo(info);
2683 constant->GetOutputSlot(0).SetTensorInfo(info);
2684 add->GetOutputSlot(0).SetTensorInfo(info);
2685
2686 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2687 BOOST_CHECK(deserializedNetwork);
2688
2689 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
2690 deserializedNetwork->Accept(verifier);
2691}
2692
Jim Flynn11af3752019-03-19 17:22:29 +00002693class VerifyLstmLayer : public LayerVerifierBase
2694{
2695public:
2696 VerifyLstmLayer(const std::string& layerName,
2697 const std::vector<armnn::TensorInfo>& inputInfos,
2698 const std::vector<armnn::TensorInfo>& outputInfos,
2699 const armnn::LstmDescriptor& descriptor,
2700 const armnn::LstmInputParams& inputParams) :
2701 LayerVerifierBase(layerName, inputInfos, outputInfos), m_Descriptor(descriptor), m_InputParams(inputParams)
2702 {
2703 }
2704 void VisitLstmLayer(const armnn::IConnectableLayer* layer,
2705 const armnn::LstmDescriptor& descriptor,
2706 const armnn::LstmInputParams& params,
2707 const char* name)
2708 {
2709 VerifyNameAndConnections(layer, name);
2710 VerifyDescriptor(descriptor);
2711 VerifyInputParameters(params);
2712 }
2713protected:
2714 void VerifyDescriptor(const armnn::LstmDescriptor& descriptor)
2715 {
2716 BOOST_TEST(m_Descriptor.m_ActivationFunc == descriptor.m_ActivationFunc);
2717 BOOST_TEST(m_Descriptor.m_ClippingThresCell == descriptor.m_ClippingThresCell);
2718 BOOST_TEST(m_Descriptor.m_ClippingThresProj == descriptor.m_ClippingThresProj);
2719 BOOST_TEST(m_Descriptor.m_CifgEnabled == descriptor.m_CifgEnabled);
2720 BOOST_TEST(m_Descriptor.m_PeepholeEnabled = descriptor.m_PeepholeEnabled);
2721 BOOST_TEST(m_Descriptor.m_ProjectionEnabled == descriptor.m_ProjectionEnabled);
2722 }
2723 void VerifyInputParameters(const armnn::LstmInputParams& params)
2724 {
2725 VerifyConstTensors(
2726 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
2727 VerifyConstTensors(
2728 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
2729 VerifyConstTensors(
2730 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
2731 VerifyConstTensors(
2732 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
2733 VerifyConstTensors(
2734 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
2735 VerifyConstTensors(
2736 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
2737 VerifyConstTensors(
2738 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
2739 VerifyConstTensors(
2740 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
2741 VerifyConstTensors(
2742 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
2743 VerifyConstTensors(
2744 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
2745 VerifyConstTensors(
2746 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
2747 VerifyConstTensors(
2748 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
2749 VerifyConstTensors(
2750 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
2751 VerifyConstTensors(
2752 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
2753 VerifyConstTensors(
2754 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
2755 VerifyConstTensors(
2756 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
2757 VerifyConstTensors(
2758 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
2759 }
2760 void VerifyConstTensors(const std::string& tensorName,
2761 const armnn::ConstTensor* expectedPtr,
2762 const armnn::ConstTensor* actualPtr)
2763 {
2764 if (expectedPtr == nullptr)
2765 {
2766 BOOST_CHECK_MESSAGE(actualPtr == nullptr, tensorName + " should not exist");
2767 }
2768 else
2769 {
2770 BOOST_CHECK_MESSAGE(actualPtr != nullptr, tensorName + " should have been set");
2771 if (actualPtr != nullptr)
2772 {
2773 const armnn::TensorInfo& expectedInfo = expectedPtr->GetInfo();
2774 const armnn::TensorInfo& actualInfo = actualPtr->GetInfo();
2775
2776 BOOST_CHECK_MESSAGE(expectedInfo.GetShape() == actualInfo.GetShape(),
2777 tensorName + " shapes don't match");
2778 BOOST_CHECK_MESSAGE(
2779 GetDataTypeName(expectedInfo.GetDataType()) == GetDataTypeName(actualInfo.GetDataType()),
2780 tensorName + " data types don't match");
2781
2782 BOOST_CHECK_MESSAGE(expectedPtr->GetNumBytes() == actualPtr->GetNumBytes(),
2783 tensorName + " (GetNumBytes) data sizes do not match");
2784 if (expectedPtr->GetNumBytes() == actualPtr->GetNumBytes())
2785 {
2786 //check the data is identical
2787 const char* expectedData = static_cast<const char*>(expectedPtr->GetMemoryArea());
2788 const char* actualData = static_cast<const char*>(actualPtr->GetMemoryArea());
2789 bool same = true;
2790 for (unsigned int i = 0; i < expectedPtr->GetNumBytes(); ++i)
2791 {
2792 same = expectedData[i] == actualData[i];
2793 if (!same)
2794 {
2795 break;
2796 }
2797 }
2798 BOOST_CHECK_MESSAGE(same, tensorName + " data does not match");
2799 }
2800 }
2801 }
2802 }
2803private:
2804 armnn::LstmDescriptor m_Descriptor;
2805 armnn::LstmInputParams m_InputParams;
2806};
2807
2808BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
2809{
2810 armnn::LstmDescriptor descriptor;
2811 descriptor.m_ActivationFunc = 4;
2812 descriptor.m_ClippingThresProj = 0.0f;
2813 descriptor.m_ClippingThresCell = 0.0f;
2814 descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
2815 descriptor.m_ProjectionEnabled = false;
2816 descriptor.m_PeepholeEnabled = true;
2817
2818 const uint32_t batchSize = 1;
2819 const uint32_t inputSize = 2;
2820 const uint32_t numUnits = 4;
2821 const uint32_t outputSize = numUnits;
2822
2823 armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
2824 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2825 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
2826
2827 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2828 armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
2829
2830 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2831 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
2832
2833 armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
2834 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2835 armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
2836
2837 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2838 armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
2839
2840 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2841 armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
2842
2843 armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
2844 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2845 armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
2846
2847 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2848 armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
2849
2850 std::vector<float> forgetGateBiasData(numUnits, 1.0f);
2851 armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
2852
2853 std::vector<float> cellBiasData(numUnits, 0.0f);
2854 armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
2855
2856 std::vector<float> outputGateBiasData(numUnits, 0.0f);
2857 armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
2858
2859 armnn::LstmInputParams params;
2860 params.m_InputToForgetWeights = &inputToForgetWeights;
2861 params.m_InputToCellWeights = &inputToCellWeights;
2862 params.m_InputToOutputWeights = &inputToOutputWeights;
2863 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2864 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2865 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2866 params.m_ForgetGateBias = &forgetGateBias;
2867 params.m_CellBias = &cellBias;
2868 params.m_OutputGateBias = &outputGateBias;
2869 params.m_CellToForgetWeights = &cellToForgetWeights;
2870 params.m_CellToOutputWeights = &cellToOutputWeights;
2871
2872 armnn::INetworkPtr network = armnn::INetwork::Create();
2873 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2874 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2875 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2876 const std::string layerName("lstm");
2877 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2878 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2879 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2880 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2881 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2882
2883 // connect up
2884 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2885 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2886 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2887 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
2888
2889 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2890 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2891
2892 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2893 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2894
2895 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2896 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2897
2898 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2899 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2900
2901 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2902 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2903
2904 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2905 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2906
2907 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2908 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2909
2910 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2911 BOOST_CHECK(deserializedNetwork);
2912
2913 VerifyLstmLayer checker(
2914 layerName,
2915 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2916 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2917 descriptor,
2918 params);
2919 deserializedNetwork->Accept(checker);
2920}
2921
2922BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
2923{
2924 armnn::LstmDescriptor descriptor;
2925 descriptor.m_ActivationFunc = 4;
2926 descriptor.m_ClippingThresProj = 0.0f;
2927 descriptor.m_ClippingThresCell = 0.0f;
2928 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
2929 descriptor.m_ProjectionEnabled = true;
2930 descriptor.m_PeepholeEnabled = true;
2931
2932 const uint32_t batchSize = 2;
2933 const uint32_t inputSize = 5;
2934 const uint32_t numUnits = 20;
2935 const uint32_t outputSize = 16;
2936
2937 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
2938 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2939 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
2940
2941 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2942 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
2943
2944 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2945 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
2946
2947 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2948 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
2949
2950 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
2951 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2952 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
2953
2954 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2955 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
2956
2957 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2958 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
2959
2960 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2961 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
2962
2963 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
2964 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2965 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
2966
2967 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2968 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
2969
2970 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2971 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
2972
2973 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2974 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
2975
2976 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2977 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
2978
2979 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2980 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
2981
2982 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2983 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
2984
2985 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
2986 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
2987 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
2988
2989 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
2990 std::vector<float> projectionBiasData(outputSize, 0.f);
2991 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
2992
2993 armnn::LstmInputParams params;
2994 params.m_InputToForgetWeights = &inputToForgetWeights;
2995 params.m_InputToCellWeights = &inputToCellWeights;
2996 params.m_InputToOutputWeights = &inputToOutputWeights;
2997 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2998 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2999 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3000 params.m_ForgetGateBias = &forgetGateBias;
3001 params.m_CellBias = &cellBias;
3002 params.m_OutputGateBias = &outputGateBias;
3003
3004 // additional params because: descriptor.m_CifgEnabled = false
3005 params.m_InputToInputWeights = &inputToInputWeights;
3006 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
3007 params.m_CellToInputWeights = &cellToInputWeights;
3008 params.m_InputGateBias = &inputGateBias;
3009
3010 // additional params because: descriptor.m_ProjectionEnabled = true
3011 params.m_ProjectionWeights = &projectionWeights;
3012 params.m_ProjectionBias = &projectionBias;
3013
3014 // additional params because: descriptor.m_PeepholeEnabled = true
3015 params.m_CellToForgetWeights = &cellToForgetWeights;
3016 params.m_CellToOutputWeights = &cellToOutputWeights;
3017
3018 armnn::INetworkPtr network = armnn::INetwork::Create();
3019 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
3020 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
3021 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
3022 const std::string layerName("lstm");
3023 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
3024 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
3025 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
3026 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
3027 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
3028
3029 // connect up
3030 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
3031 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
3032 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
3033 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
3034
3035 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
3036 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
3037
3038 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
3039 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
3040
3041 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
3042 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
3043
3044 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
3045 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
3046
3047 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
3048 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
3049
3050 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
3051 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
3052
3053 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
3054 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
3055
3056 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
3057 BOOST_CHECK(deserializedNetwork);
3058
3059 VerifyLstmLayer checker(
3060 layerName,
3061 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
3062 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
3063 descriptor,
3064 params);
3065 deserializedNetwork->Accept(checker);
3066}
3067
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00003068BOOST_AUTO_TEST_SUITE_END()