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