blob: 752cf0c27a43a42228a9790e35da596e86623015 [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,
424 const armnn::ConstTensor& weight,
425 const armnn::Optional<armnn::ConstTensor>& bias)
426 : LayerVerifierBase(layerName, inputInfos, outputInfos)
427 , m_Descriptor(descriptor)
428 , m_Weight(weight)
429 , m_Bias(bias) {}
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000430
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000431 void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
432 const armnn::Convolution2dDescriptor& descriptor,
433 const armnn::ConstTensor& weight,
434 const armnn::Optional<armnn::ConstTensor>& bias,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000435 const char* name) override
436 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000437 VerifyNameAndConnections(layer, name);
438 VerifyDescriptor(descriptor);
439
440 CompareConstTensor(weight, m_Weight);
441
442 BOOST_TEST(bias.has_value() == m_Bias.has_value());
443 if (bias.has_value() && m_Bias.has_value())
444 {
445 CompareConstTensor(bias.value(), m_Bias.value());
446 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000447 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000448
449 private:
450 void VerifyDescriptor(const armnn::Convolution2dDescriptor& descriptor)
451 {
452 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
453 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
454 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
455 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
456 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
457 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
458 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
459 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
460 }
461
462 armnn::Convolution2dDescriptor m_Descriptor;
463 armnn::ConstTensor m_Weight;
464 armnn::Optional<armnn::ConstTensor> m_Bias;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000465 };
466
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000467 const std::string layerName("convolution2d");
468 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
469 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000470
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000471 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
472 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000473
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000474 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
475 armnn::ConstTensor weights(weightsInfo, weightsData);
476
477 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
478 armnn::ConstTensor biases(biasesInfo, biasesData);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000479
480 armnn::Convolution2dDescriptor descriptor;
481 descriptor.m_PadLeft = 1;
482 descriptor.m_PadRight = 1;
483 descriptor.m_PadTop = 1;
484 descriptor.m_PadBottom = 1;
485 descriptor.m_StrideX = 2;
486 descriptor.m_StrideY = 2;
487 descriptor.m_BiasEnabled = true;
488 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
489
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000490 armnn::INetworkPtr network = armnn::INetwork::Create();
491 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000492 armnn::IConnectableLayer* const convLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100493 network->AddConvolution2dLayer(descriptor,
494 weights,
495 armnn::Optional<armnn::ConstTensor>(biases),
496 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000497 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000498
499 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000500 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000501
502 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000503 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
504
505 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
506 BOOST_CHECK(deserializedNetwork);
507
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000508 Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
509 deserializedNetwork->Accept(verifier);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000510}
511
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000512BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d)
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000513{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000514 class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBase
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000515 {
516 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000517 DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
518 const std::vector<armnn::TensorInfo>& inputInfos,
519 const std::vector<armnn::TensorInfo>& outputInfos,
520 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
521 const armnn::ConstTensor& weight,
522 const armnn::Optional<armnn::ConstTensor>& bias)
523 : LayerVerifierBase(layerName, inputInfos, outputInfos)
524 , m_Descriptor(descriptor)
525 , m_Weight(weight)
526 , m_Bias(bias) {}
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000527
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000528 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
529 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
530 const armnn::ConstTensor& weight,
531 const armnn::Optional<armnn::ConstTensor>& bias,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000532 const char* name) override
533 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000534 VerifyNameAndConnections(layer, name);
535 VerifyDescriptor(descriptor);
536
537 CompareConstTensor(weight, m_Weight);
538
539 BOOST_TEST(bias.has_value() == m_Bias.has_value());
540 if (bias.has_value() && m_Bias.has_value())
541 {
542 CompareConstTensor(bias.value(), m_Bias.value());
543 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000544 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000545
546 private:
547 void VerifyDescriptor(const armnn::DepthwiseConvolution2dDescriptor& descriptor)
548 {
549 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
550 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
551 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
552 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
553 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
554 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
555 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
556 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
557 }
558
559 armnn::DepthwiseConvolution2dDescriptor m_Descriptor;
560 armnn::ConstTensor m_Weight;
561 armnn::Optional<armnn::ConstTensor> m_Bias;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000562 };
563
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000564 const std::string layerName("depwiseConvolution2d");
565 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
566 const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000567
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000568 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
569 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000570
571 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
572 armnn::ConstTensor weights(weightsInfo, weightsData);
573
574 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
575 armnn::ConstTensor biases(biasesInfo, biasesData);
576
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000577 armnn::DepthwiseConvolution2dDescriptor descriptor;
578 descriptor.m_StrideX = 1;
579 descriptor.m_StrideY = 1;
580 descriptor.m_BiasEnabled = true;
581 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
582
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000583 armnn::INetworkPtr network = armnn::INetwork::Create();
584 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
585 armnn::IConnectableLayer* const depthwiseConvLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100586 network->AddDepthwiseConvolution2dLayer(descriptor,
587 weights,
588 armnn::Optional<armnn::ConstTensor>(biases),
589 layerName.c_str());
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000590 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
591
592 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000593 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000594
595 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000596 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
597
598 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
599 BOOST_CHECK(deserializedNetwork);
600
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000601 DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
602 deserializedNetwork->Accept(verifier);
Jim Flynn18ce3382019-03-08 11:08:30 +0000603}
604
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +0000605BOOST_AUTO_TEST_CASE(SerializeDequantize)
606{
607 class DequantizeLayerVerifier : public LayerVerifierBase
608 {
609 public:
610 DequantizeLayerVerifier(const std::string& layerName,
611 const std::vector<armnn::TensorInfo>& inputInfos,
612 const std::vector<armnn::TensorInfo>& outputInfos)
613 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
614
615 void VisitDequantizeLayer(const armnn::IConnectableLayer* layer, const char* name) override
616 {
617 VerifyNameAndConnections(layer, name);
618 }
619 };
620
621 const std::string layerName("dequantize");
622 const armnn::TensorInfo inputInfo({ 1, 5, 2, 3 }, armnn::DataType::QuantisedAsymm8, 0.5f, 1);
623 const armnn::TensorInfo outputInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
624
625 armnn::INetworkPtr network = armnn::INetwork::Create();
626 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
627 armnn::IConnectableLayer* const dequantizeLayer = network->AddDequantizeLayer(layerName.c_str());
628 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
629
630 inputLayer->GetOutputSlot(0).Connect(dequantizeLayer->GetInputSlot(0));
631 dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
632
633 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
634 dequantizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
635
636 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
637 BOOST_CHECK(deserializedNetwork);
638
639 DequantizeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo});
640 deserializedNetwork->Accept(verifier);
641}
642
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000643BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess)
644{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000645 class DetectionPostProcessLayerVerifier : public LayerVerifierBase
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000646 {
647 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000648 DetectionPostProcessLayerVerifier(const std::string& layerName,
649 const std::vector<armnn::TensorInfo>& inputInfos,
650 const std::vector<armnn::TensorInfo>& outputInfos,
651 const armnn::DetectionPostProcessDescriptor& descriptor,
652 const armnn::ConstTensor& anchors)
653 : LayerVerifierBase(layerName, inputInfos, outputInfos)
654 , m_Descriptor(descriptor)
655 , m_Anchors(anchors) {}
656
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000657 void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
658 const armnn::DetectionPostProcessDescriptor& descriptor,
659 const armnn::ConstTensor& anchors,
660 const char* name) override
661 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000662 VerifyNameAndConnections(layer, name);
663 VerifyDescriptor(descriptor);
664
665 CompareConstTensor(anchors, m_Anchors);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000666 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000667
668 private:
669 void VerifyDescriptor(const armnn::DetectionPostProcessDescriptor& descriptor)
670 {
671 BOOST_TEST(descriptor.m_UseRegularNms == m_Descriptor.m_UseRegularNms);
672 BOOST_TEST(descriptor.m_MaxDetections == m_Descriptor.m_MaxDetections);
673 BOOST_TEST(descriptor.m_MaxClassesPerDetection == m_Descriptor.m_MaxClassesPerDetection);
674 BOOST_TEST(descriptor.m_DetectionsPerClass == m_Descriptor.m_DetectionsPerClass);
675 BOOST_TEST(descriptor.m_NmsScoreThreshold == m_Descriptor.m_NmsScoreThreshold);
676 BOOST_TEST(descriptor.m_NmsIouThreshold == m_Descriptor.m_NmsIouThreshold);
677 BOOST_TEST(descriptor.m_NumClasses == m_Descriptor.m_NumClasses);
678 BOOST_TEST(descriptor.m_ScaleY == m_Descriptor.m_ScaleY);
679 BOOST_TEST(descriptor.m_ScaleX == m_Descriptor.m_ScaleX);
680 BOOST_TEST(descriptor.m_ScaleH == m_Descriptor.m_ScaleH);
681 BOOST_TEST(descriptor.m_ScaleW == m_Descriptor.m_ScaleW);
682 }
683
684 armnn::DetectionPostProcessDescriptor m_Descriptor;
685 armnn::ConstTensor m_Anchors;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000686 };
687
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000688 const std::string layerName("detectionPostProcess");
689
690 const std::vector<armnn::TensorInfo> inputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000691 armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32),
692 armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000693 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000694
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000695 const std::vector<armnn::TensorInfo> outputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000696 armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32),
697 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
698 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
699 armnn::TensorInfo({ 1 }, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000700 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000701
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000702 armnn::DetectionPostProcessDescriptor descriptor;
703 descriptor.m_UseRegularNms = true;
704 descriptor.m_MaxDetections = 3;
705 descriptor.m_MaxClassesPerDetection = 1;
706 descriptor.m_DetectionsPerClass =1;
707 descriptor.m_NmsScoreThreshold = 0.0;
708 descriptor.m_NmsIouThreshold = 0.5;
709 descriptor.m_NumClasses = 2;
710 descriptor.m_ScaleY = 10.0;
711 descriptor.m_ScaleX = 10.0;
712 descriptor.m_ScaleH = 5.0;
713 descriptor.m_ScaleW = 5.0;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000714
715 const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
716 const std::vector<float> anchorsData({
717 0.5f, 0.5f, 1.0f, 1.0f,
718 0.5f, 0.5f, 1.0f, 1.0f,
719 0.5f, 0.5f, 1.0f, 1.0f,
720 0.5f, 10.5f, 1.0f, 1.0f,
721 0.5f, 10.5f, 1.0f, 1.0f,
722 0.5f, 100.5f, 1.0f, 1.0f
723 });
724 armnn::ConstTensor anchors(anchorsInfo, anchorsData);
725
726 armnn::INetworkPtr network = armnn::INetwork::Create();
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000727 armnn::IConnectableLayer* const detectionLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000728 network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000729
730 for (unsigned int i = 0; i < 2; i++)
731 {
732 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
733 inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
734 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
735 }
736
737 for (unsigned int i = 0; i < 4; i++)
738 {
739 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
740 detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
741 detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
742 }
743
744 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
745 BOOST_CHECK(deserializedNetwork);
746
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000747 DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors);
748 deserializedNetwork->Accept(verifier);
749}
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000750
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000751BOOST_AUTO_TEST_CASE(SerializeDivision)
752{
753 class DivisionLayerVerifier : public LayerVerifierBase
754 {
755 public:
756 DivisionLayerVerifier(const std::string& layerName,
757 const std::vector<armnn::TensorInfo>& inputInfos,
758 const std::vector<armnn::TensorInfo>& outputInfos)
759 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
760
761 void VisitDivisionLayer(const armnn::IConnectableLayer* layer, const char* name) override
762 {
763 VerifyNameAndConnections(layer, name);
764 }
765 };
766
767 const std::string layerName("division");
768 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
769
770 armnn::INetworkPtr network = armnn::INetwork::Create();
771 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
772 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
773 armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
774 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
775
776 inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
777 inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
778 divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
779
780 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
781 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
782 divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
783
784 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
785 BOOST_CHECK(deserializedNetwork);
786
787 DivisionLayerVerifier verifier(layerName, {info, info}, {info});
788 deserializedNetwork->Accept(verifier);
789}
790
791BOOST_AUTO_TEST_CASE(SerializeEqual)
792{
793 class EqualLayerVerifier : public LayerVerifierBase
794 {
795 public:
796 EqualLayerVerifier(const std::string& layerName,
797 const std::vector<armnn::TensorInfo>& inputInfos,
798 const std::vector<armnn::TensorInfo>& outputInfos)
799 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
800
801 void VisitEqualLayer(const armnn::IConnectableLayer* layer, const char* name) override
802 {
803 VerifyNameAndConnections(layer, name);
804 }
805 };
806
807 const std::string layerName("equal");
808 const armnn::TensorInfo inputTensorInfo1 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
809 const armnn::TensorInfo inputTensorInfo2 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
810 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Boolean);
811
812 armnn::INetworkPtr network = armnn::INetwork::Create();
813 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
814 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
815 armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str());
816 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
817
818 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
819 inputLayer2->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
820 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
821
822 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
823 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
824 equalLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
825
826 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
827 BOOST_CHECK(deserializedNetwork);
828
829 EqualLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
830 deserializedNetwork->Accept(verifier);
831}
832
833BOOST_AUTO_TEST_CASE(SerializeFloor)
834{
835 class FloorLayerVerifier : public LayerVerifierBase
836 {
837 public:
838 FloorLayerVerifier(const std::string& layerName,
839 const std::vector<armnn::TensorInfo>& inputInfos,
840 const std::vector<armnn::TensorInfo>& outputInfos)
841 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
842
843 void VisitFloorLayer(const armnn::IConnectableLayer* layer, const char* name) override
844 {
845 VerifyNameAndConnections(layer, name);
846 }
847 };
848
849 const std::string layerName("floor");
850 const armnn::TensorInfo info({4,4}, armnn::DataType::Float32);
851
852 armnn::INetworkPtr network = armnn::INetwork::Create();
853 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
854 armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
855 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
856
857 inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
858 floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
859
860 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
861 floorLayer->GetOutputSlot(0).SetTensorInfo(info);
862
863 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
864 BOOST_CHECK(deserializedNetwork);
865
866 FloorLayerVerifier verifier(layerName, {info}, {info});
867 deserializedNetwork->Accept(verifier);
868}
869
870BOOST_AUTO_TEST_CASE(SerializeFullyConnected)
871{
872 class FullyConnectedLayerVerifier : public LayerVerifierBase
873 {
874 public:
875 FullyConnectedLayerVerifier(const std::string& layerName,
876 const std::vector<armnn::TensorInfo>& inputInfos,
877 const std::vector<armnn::TensorInfo>& outputInfos,
878 const armnn::FullyConnectedDescriptor& descriptor,
879 const armnn::ConstTensor& weight,
880 const armnn::Optional<armnn::ConstTensor>& bias)
881 : LayerVerifierBase(layerName, inputInfos, outputInfos)
882 , m_Descriptor(descriptor)
883 , m_Weight(weight)
884 , m_Bias(bias) {}
885
886 void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
887 const armnn::FullyConnectedDescriptor& descriptor,
888 const armnn::ConstTensor& weight,
889 const armnn::Optional<armnn::ConstTensor>& bias,
890 const char* name) override
891 {
892 VerifyNameAndConnections(layer, name);
893 VerifyDescriptor(descriptor);
894
895 CompareConstTensor(weight, m_Weight);
896
897 BOOST_TEST(bias.has_value() == m_Bias.has_value());
898 if (bias.has_value() && m_Bias.has_value())
899 {
900 CompareConstTensor(bias.value(), m_Bias.value());
901 }
902 }
903
904 private:
905 void VerifyDescriptor(const armnn::FullyConnectedDescriptor& descriptor)
906 {
907 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
908 BOOST_TEST(descriptor.m_TransposeWeightMatrix == m_Descriptor.m_TransposeWeightMatrix);
909 }
910
911 armnn::FullyConnectedDescriptor m_Descriptor;
912 armnn::ConstTensor m_Weight;
913 armnn::Optional<armnn::ConstTensor> m_Bias;
914 };
915
916 const std::string layerName("fullyConnected");
917 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
918 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
919
920 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
921 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
922 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
923 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
924 armnn::ConstTensor weights(weightsInfo, weightsData);
925 armnn::ConstTensor biases(biasesInfo, biasesData);
926
927 armnn::FullyConnectedDescriptor descriptor;
928 descriptor.m_BiasEnabled = true;
929 descriptor.m_TransposeWeightMatrix = false;
930
931 armnn::INetworkPtr network = armnn::INetwork::Create();
932 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
933 armnn::IConnectableLayer* const fullyConnectedLayer =
Matteo Martincighfc598e12019-05-14 10:36:13 +0100934 network->AddFullyConnectedLayer(descriptor,
935 weights,
936 armnn::Optional<armnn::ConstTensor>(biases),
937 layerName.c_str());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000938 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
939
940 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
941 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
942
943 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
944 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
945
946 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
947 BOOST_CHECK(deserializedNetwork);
948
949 FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
950 deserializedNetwork->Accept(verifier);
951}
952
953BOOST_AUTO_TEST_CASE(SerializeGather)
954{
955 class GatherLayerVerifier : public LayerVerifierBase
956 {
957 public:
958 GatherLayerVerifier(const std::string& layerName,
959 const std::vector<armnn::TensorInfo>& inputInfos,
960 const std::vector<armnn::TensorInfo>& outputInfos)
961 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
962
963 void VisitGatherLayer(const armnn::IConnectableLayer* layer, const char *name) override
964 {
965 VerifyNameAndConnections(layer, name);
966 }
967
968 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
969 const armnn::ConstTensor& input,
970 const char *name) override {}
971 };
972
973 const std::string layerName("gather");
974 armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QuantisedAsymm8);
975 armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QuantisedAsymm8);
976 const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
977
978 paramsInfo.SetQuantizationScale(1.0f);
979 paramsInfo.SetQuantizationOffset(0);
980 outputInfo.SetQuantizationScale(1.0f);
981 outputInfo.SetQuantizationOffset(0);
982
983 const std::vector<int32_t>& indicesData = {7, 6, 5};
984
985 armnn::INetworkPtr network = armnn::INetwork::Create();
986 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
987 armnn::IConnectableLayer *const constantLayer =
988 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
989 armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(layerName.c_str());
990 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
991
992 inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
993 constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
994 gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
995
996 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
997 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
998 gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
999
1000 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1001 BOOST_CHECK(deserializedNetwork);
1002
1003 GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo});
1004 deserializedNetwork->Accept(verifier);
1005}
1006
1007BOOST_AUTO_TEST_CASE(SerializeGreater)
1008{
1009 class GreaterLayerVerifier : public LayerVerifierBase
1010 {
1011 public:
1012 GreaterLayerVerifier(const std::string& layerName,
1013 const std::vector<armnn::TensorInfo>& inputInfos,
1014 const std::vector<armnn::TensorInfo>& outputInfos)
1015 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1016
1017 void VisitGreaterLayer(const armnn::IConnectableLayer* layer, const char* name) override
1018 {
1019 VerifyNameAndConnections(layer, name);
1020 }
1021 };
1022
1023 const std::string layerName("greater");
1024 const armnn::TensorInfo inputTensorInfo1({ 1, 2, 2, 2 }, armnn::DataType::Float32);
1025 const armnn::TensorInfo inputTensorInfo2({ 1, 2, 2, 2 }, armnn::DataType::Float32);
1026 const armnn::TensorInfo outputTensorInfo({ 1, 2, 2, 2 }, armnn::DataType::Boolean);
1027
1028 armnn::INetworkPtr network = armnn::INetwork::Create();
1029 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
1030 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
1031 armnn::IConnectableLayer* const greaterLayer = network->AddGreaterLayer(layerName.c_str());
1032 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1033
1034 inputLayer1->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(0));
1035 inputLayer2->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(1));
1036 greaterLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1037
1038 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
1039 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
1040 greaterLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1041
1042 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1043 BOOST_CHECK(deserializedNetwork);
1044
1045 GreaterLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
1046 deserializedNetwork->Accept(verifier);
1047}
1048
1049BOOST_AUTO_TEST_CASE(SerializeL2Normalization)
1050{
1051 class L2NormalizationLayerVerifier : public LayerVerifierBase
1052 {
1053 public:
1054 L2NormalizationLayerVerifier(const std::string& layerName,
1055 const std::vector<armnn::TensorInfo>& inputInfos,
1056 const std::vector<armnn::TensorInfo>& outputInfos,
1057 const armnn::L2NormalizationDescriptor& descriptor)
1058 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1059 , m_Descriptor(descriptor) {}
1060
1061 void VisitL2NormalizationLayer(const armnn::IConnectableLayer* layer,
1062 const armnn::L2NormalizationDescriptor& descriptor,
1063 const char* name) override
1064 {
1065 VerifyNameAndConnections(layer, name);
1066 VerifyDescriptor(descriptor);
1067 }
1068 private:
1069 void VerifyDescriptor(const armnn::L2NormalizationDescriptor& descriptor)
1070 {
1071 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1072 }
1073
1074 armnn::L2NormalizationDescriptor m_Descriptor;
1075 };
1076
1077 const std::string l2NormLayerName("l2Normalization");
1078 const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1079
1080 armnn::L2NormalizationDescriptor desc;
1081 desc.m_DataLayout = armnn::DataLayout::NCHW;
1082
1083 armnn::INetworkPtr network = armnn::INetwork::Create();
1084 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1085 armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1086 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1087
1088 inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1089 l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1090
1091 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1092 l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1093
1094 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1095 BOOST_CHECK(deserializedNetwork);
1096
1097 L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc);
1098 deserializedNetwork->Accept(verifier);
1099}
1100
1101BOOST_AUTO_TEST_CASE(SerializeMaximum)
1102{
1103 class MaximumLayerVerifier : public LayerVerifierBase
1104 {
1105 public:
1106 MaximumLayerVerifier(const std::string& layerName,
1107 const std::vector<armnn::TensorInfo>& inputInfos,
1108 const std::vector<armnn::TensorInfo>& outputInfos)
1109 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1110
1111 void VisitMaximumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1112 {
1113 VerifyNameAndConnections(layer, name);
1114 }
1115 };
1116
1117 const std::string layerName("maximum");
1118 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1119
1120 armnn::INetworkPtr network = armnn::INetwork::Create();
1121 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1122 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1123 armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1124 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1125
1126 inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1127 inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1128 maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1129
1130 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1131 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1132 maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1133
1134 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1135 BOOST_CHECK(deserializedNetwork);
1136
1137 MaximumLayerVerifier verifier(layerName, {info, info}, {info});
1138 deserializedNetwork->Accept(verifier);
1139}
1140
1141BOOST_AUTO_TEST_CASE(SerializeMean)
1142{
1143 class MeanLayerVerifier : public LayerVerifierBase
1144 {
1145 public:
1146 MeanLayerVerifier(const std::string& layerName,
1147 const std::vector<armnn::TensorInfo>& inputInfos,
1148 const std::vector<armnn::TensorInfo>& outputInfos,
1149 const armnn::MeanDescriptor& descriptor)
1150 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1151 , m_Descriptor(descriptor) {}
1152
1153 void VisitMeanLayer(const armnn::IConnectableLayer* layer,
1154 const armnn::MeanDescriptor& descriptor,
1155 const char* name) override
1156 {
1157 VerifyNameAndConnections(layer, name);
1158 VerifyDescriptor(descriptor);
1159 }
1160
1161 private:
1162 void VerifyDescriptor(const armnn::MeanDescriptor& descriptor)
1163 {
1164 BOOST_TEST(descriptor.m_Axis == m_Descriptor.m_Axis);
1165 BOOST_TEST(descriptor.m_KeepDims == m_Descriptor.m_KeepDims);
1166 }
1167
1168 armnn::MeanDescriptor m_Descriptor;
1169 };
1170
1171 const std::string layerName("mean");
1172 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1173 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1174
1175 armnn::MeanDescriptor descriptor;
1176 descriptor.m_Axis = { 2 };
1177 descriptor.m_KeepDims = true;
1178
1179 armnn::INetworkPtr network = armnn::INetwork::Create();
1180 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1181 armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1182 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1183
1184 inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1185 meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1186
1187 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1188 meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1189
1190 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1191 BOOST_CHECK(deserializedNetwork);
1192
1193 MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1194 deserializedNetwork->Accept(verifier);
1195}
1196
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001197BOOST_AUTO_TEST_CASE(SerializeMerge)
1198{
1199 class MergeLayerVerifier : public LayerVerifierBase
1200 {
1201 public:
1202 MergeLayerVerifier(const std::string& layerName,
1203 const std::vector<armnn::TensorInfo>& inputInfos,
1204 const std::vector<armnn::TensorInfo>& outputInfos)
1205 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1206
1207 void VisitMergeLayer(const armnn::IConnectableLayer* layer, const char* name) override
1208 {
1209 VerifyNameAndConnections(layer, name);
1210 }
1211 };
1212
1213 const std::string layerName("merge");
1214 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1215
1216 armnn::INetworkPtr network = armnn::INetwork::Create();
1217 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1218 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1219 armnn::IConnectableLayer* const mergeLayer = network->AddMergeLayer(layerName.c_str());
1220 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1221
1222 inputLayer0->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(0));
1223 inputLayer1->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(1));
1224 mergeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1225
1226 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1227 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1228 mergeLayer->GetOutputSlot(0).SetTensorInfo(info);
1229
1230 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1231 BOOST_CHECK(deserializedNetwork);
1232
1233 MergeLayerVerifier verifier(layerName, {info, info}, {info});
1234 deserializedNetwork->Accept(verifier);
1235}
1236
Jim Flynn5fa83932019-05-09 15:35:43 +01001237class MergerLayerVerifier : public LayerVerifierBase
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001238{
Jim Flynn5fa83932019-05-09 15:35:43 +01001239public:
1240 MergerLayerVerifier(const std::string& layerName,
1241 const std::vector<armnn::TensorInfo>& inputInfos,
1242 const std::vector<armnn::TensorInfo>& outputInfos,
1243 const armnn::OriginsDescriptor& descriptor)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001244 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1245 , m_Descriptor(descriptor) {}
1246
Jim Flynn5fa83932019-05-09 15:35:43 +01001247 void VisitMergerLayer(const armnn::IConnectableLayer* layer,
1248 const armnn::OriginsDescriptor& descriptor,
1249 const char* name) override
1250 {
Jim Flynne242f2d2019-05-22 14:24:13 +01001251 throw armnn::Exception("MergerLayer should have translated to ConcatLayer");
1252 }
1253
1254 void VisitConcatLayer(const armnn::IConnectableLayer* layer,
1255 const armnn::OriginsDescriptor& descriptor,
1256 const char* name) override
1257 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001258 VerifyNameAndConnections(layer, name);
1259 VerifyDescriptor(descriptor);
1260 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001261
Jim Flynn5fa83932019-05-09 15:35:43 +01001262private:
1263 void VerifyDescriptor(const armnn::OriginsDescriptor& descriptor)
1264 {
1265 BOOST_TEST(descriptor.GetConcatAxis() == m_Descriptor.GetConcatAxis());
1266 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
1267 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001268
Jim Flynn5fa83932019-05-09 15:35:43 +01001269 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
1270 {
1271 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001272 {
Jim Flynn5fa83932019-05-09 15:35:43 +01001273 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001274 }
1275 }
Jim Flynn5fa83932019-05-09 15:35:43 +01001276 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001277
Jim Flynn5fa83932019-05-09 15:35:43 +01001278 armnn::OriginsDescriptor m_Descriptor;
1279};
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001280
Jim Flynne242f2d2019-05-22 14:24:13 +01001281// NOTE: until the deprecated AddMergerLayer disappears this test checks that calling
1282// AddMergerLayer places a ConcatLayer into the serialized format and that
1283// when this deserialises we have a ConcatLayer
Jim Flynn5fa83932019-05-09 15:35:43 +01001284BOOST_AUTO_TEST_CASE(SerializeMerger)
1285{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001286 const std::string layerName("merger");
1287 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1288 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1289
1290 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1291
1292 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001293 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001294
1295 armnn::INetworkPtr network = armnn::INetwork::Create();
1296 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1297 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
Jim Flynn906f9462019-05-10 13:55:21 +01001298 ARMNN_NO_DEPRECATE_WARN_BEGIN
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001299 armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str());
Jim Flynn906f9462019-05-10 13:55:21 +01001300 ARMNN_NO_DEPRECATE_WARN_END
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001301 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1302
1303 inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
1304 inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
1305 mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1306
1307 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1308 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1309 mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1310
Jim Flynn5fa83932019-05-09 15:35:43 +01001311 std::string mergerLayerNetwork = SerializeNetwork(*network);
1312 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001313 BOOST_CHECK(deserializedNetwork);
1314
1315 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1316 deserializedNetwork->Accept(verifier);
1317}
1318
Jim Flynn5fa83932019-05-09 15:35:43 +01001319BOOST_AUTO_TEST_CASE(EnsureMergerLayerBackwardCompatibility)
1320{
1321 // The hex array below is a flat buffer containing a simple network with two inputs
Jim Flynne242f2d2019-05-22 14:24:13 +01001322 // a merger layer (now deprecated) and an output layer with dimensions as per the tensor infos below.
1323 //
1324 // This test verifies that we can still read back these old style
Jim Flynn5fa83932019-05-09 15:35:43 +01001325 // models replacing the MergerLayers with ConcatLayers with the same parameters.
Jim Flynn5fa83932019-05-09 15:35:43 +01001326 unsigned int size = 760;
1327 const unsigned char mergerModel[] = {
1328 0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,
1329 0x0C,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x38,0x02,0x00,0x00,
1330 0x8C,0x01,0x00,0x00,0x70,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1331 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xF4,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x0B,
1332 0x04,0x00,0x00,0x00,0x92,0xFE,0xFF,0xFF,0x04,0x00,0x00,0x00,0x9A,0xFE,0xFF,0xFF,0x04,0x00,0x00,0x00,
1333 0x7E,0xFE,0xFF,0xFF,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1334 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
1335 0x00,0x00,0x00,0x00,0xF8,0xFE,0xFF,0xFF,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0xFE,0xFF,0xFF,
1336 0x00,0x00,0x00,0x1F,0x0C,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1337 0x68,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x0C,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,
1338 0x0C,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1339 0x24,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x22,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1340 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,
1341 0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1342 0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,
1343 0x14,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x6D,0x65,0x72,0x67,0x65,0x72,0x00,0x00,
1344 0x02,0x00,0x00,0x00,0x5C,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1345 0x34,0xFF,0xFF,0xFF,0x04,0x00,0x00,0x00,0x92,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,
1346 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1347 0x02,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1348 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,
1349 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,
1350 0x00,0x00,0x00,0x09,0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x00,0x00,
1351 0x0C,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,
1352 0x01,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x18,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x14,0x00,
1353 0x0E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1354 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1355 0x0C,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1356 0x66,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1357 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,
1358 0x07,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x00,0xF6,0xFF,0xFF,0xFF,
1359 0x0C,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0A,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1360 0x00,0x00,0x0E,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x0E,0x00,0x00,0x00,
1361 0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1362 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x0A,0x00,
1363 0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x10,0x00,0x08,0x00,
1364 0x07,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1365 0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00};
1366 std::stringstream ss;
1367 for (unsigned int i = 0; i < size; ++i)
1368 {
1369 ss << mergerModel[i];
1370 }
1371 std::string mergerLayerNetwork = ss.str();
1372 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(mergerLayerNetwork);
1373 BOOST_CHECK(deserializedNetwork);
1374 const std::string layerName("merger");
1375 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1376 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1377
1378 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1379
1380 armnn::OriginsDescriptor descriptor =
Jim Flynn825af452019-05-20 12:49:28 +01001381 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
Jim Flynn5fa83932019-05-09 15:35:43 +01001382
1383 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1384 deserializedNetwork->Accept(verifier);
1385}
1386
Jim Flynne242f2d2019-05-22 14:24:13 +01001387BOOST_AUTO_TEST_CASE(SerializeConcat)
1388{
1389 const std::string layerName("concat");
1390 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1391 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1392
1393 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1394
1395 armnn::OriginsDescriptor descriptor =
1396 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1397
1398 armnn::INetworkPtr network = armnn::INetwork::Create();
1399 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1400 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1401 armnn::IConnectableLayer* const concatLayer = network->AddConcatLayer(descriptor, layerName.c_str());
1402 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1403
1404 inputLayerOne->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
1405 inputLayerTwo->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
1406 concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1407
1408 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1409 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1410 concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1411
1412 std::string concatLayerNetwork = SerializeNetwork(*network);
1413 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(concatLayerNetwork);
1414 BOOST_CHECK(deserializedNetwork);
1415
1416 // NOTE: using the MergerLayerVerifier to ensure that it is a concat layer and not a
1417 // merger layer that gets placed into the graph.
1418 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1419 deserializedNetwork->Accept(verifier);
1420}
1421
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001422BOOST_AUTO_TEST_CASE(SerializeMinimum)
1423{
1424 class MinimumLayerVerifier : public LayerVerifierBase
1425 {
1426 public:
1427 MinimumLayerVerifier(const std::string& layerName,
1428 const std::vector<armnn::TensorInfo>& inputInfos,
1429 const std::vector<armnn::TensorInfo>& outputInfos)
1430 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1431
1432 void VisitMinimumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1433 {
1434 VerifyNameAndConnections(layer, name);
1435 }
1436 };
1437
1438 const std::string layerName("minimum");
1439 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1440
1441 armnn::INetworkPtr network = armnn::INetwork::Create();
1442 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1443 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1444 armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1445 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1446
1447 inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1448 inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1449 minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1450
1451 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1452 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1453 minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
1454
1455 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1456 BOOST_CHECK(deserializedNetwork);
1457
1458 MinimumLayerVerifier verifier(layerName, {info, info}, {info});
1459 deserializedNetwork->Accept(verifier);
1460}
1461
1462BOOST_AUTO_TEST_CASE(SerializeMultiplication)
1463{
1464 class MultiplicationLayerVerifier : public LayerVerifierBase
1465 {
1466 public:
1467 MultiplicationLayerVerifier(const std::string& layerName,
1468 const std::vector<armnn::TensorInfo>& inputInfos,
1469 const std::vector<armnn::TensorInfo>& outputInfos)
1470 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1471
1472 void VisitMultiplicationLayer(const armnn::IConnectableLayer* layer, const char* name) override
1473 {
1474 VerifyNameAndConnections(layer, name);
1475 }
1476 };
1477
1478 const std::string layerName("multiplication");
1479 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1480
1481 armnn::INetworkPtr network = armnn::INetwork::Create();
1482 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1483 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1484 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
1485 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1486
1487 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
1488 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
1489 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1490
1491 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1492 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1493 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
1494
1495 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1496 BOOST_CHECK(deserializedNetwork);
1497
1498 MultiplicationLayerVerifier verifier(layerName, {info, info}, {info});
1499 deserializedNetwork->Accept(verifier);
1500}
1501
1502BOOST_AUTO_TEST_CASE(SerializeNormalization)
1503{
1504 class NormalizationLayerVerifier : public LayerVerifierBase
1505 {
1506 public:
1507 NormalizationLayerVerifier(const std::string& layerName,
1508 const std::vector<armnn::TensorInfo>& inputInfos,
1509 const std::vector<armnn::TensorInfo>& outputInfos,
1510 const armnn::NormalizationDescriptor& descriptor)
1511 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1512 , m_Descriptor(descriptor) {}
1513
1514 void VisitNormalizationLayer(const armnn::IConnectableLayer* layer,
1515 const armnn::NormalizationDescriptor& descriptor,
1516 const char* name) override
1517 {
1518 VerifyNameAndConnections(layer, name);
1519 VerifyDescriptor(descriptor);
1520 }
1521
1522 private:
1523 void VerifyDescriptor(const armnn::NormalizationDescriptor& descriptor)
1524 {
1525 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1526 BOOST_TEST(descriptor.m_NormSize == m_Descriptor.m_NormSize);
1527 BOOST_TEST(descriptor.m_Alpha == m_Descriptor.m_Alpha);
1528 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
1529 BOOST_TEST(descriptor.m_K == m_Descriptor.m_K);
1530 BOOST_TEST(
1531 static_cast<int>(descriptor.m_NormChannelType) == static_cast<int>(m_Descriptor.m_NormChannelType));
1532 BOOST_TEST(
1533 static_cast<int>(descriptor.m_NormMethodType) == static_cast<int>(m_Descriptor.m_NormMethodType));
1534 }
1535
1536 armnn::NormalizationDescriptor m_Descriptor;
1537 };
1538
1539 const std::string layerName("normalization");
1540 const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
1541
1542 armnn::NormalizationDescriptor desc;
1543 desc.m_DataLayout = armnn::DataLayout::NCHW;
1544 desc.m_NormSize = 3;
1545 desc.m_Alpha = 1;
1546 desc.m_Beta = 1;
1547 desc.m_K = 1;
1548
1549 armnn::INetworkPtr network = armnn::INetwork::Create();
1550 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1551 armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
1552 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1553
1554 inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
1555 normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1556
1557 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1558 normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
1559
1560 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1561 BOOST_CHECK(deserializedNetwork);
1562
1563 NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc);
1564 deserializedNetwork->Accept(verifier);
1565}
1566
1567BOOST_AUTO_TEST_CASE(SerializePad)
1568{
1569 class PadLayerVerifier : public LayerVerifierBase
1570 {
1571 public:
1572 PadLayerVerifier(const std::string& layerName,
1573 const std::vector<armnn::TensorInfo>& inputInfos,
1574 const std::vector<armnn::TensorInfo>& outputInfos,
1575 const armnn::PadDescriptor& descriptor)
1576 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1577 , m_Descriptor(descriptor) {}
1578
1579 void VisitPadLayer(const armnn::IConnectableLayer* layer,
1580 const armnn::PadDescriptor& descriptor,
1581 const char* name) override
1582 {
1583 VerifyNameAndConnections(layer, name);
1584 VerifyDescriptor(descriptor);
1585 }
1586
1587 private:
1588 void VerifyDescriptor(const armnn::PadDescriptor& descriptor)
1589 {
1590 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
1591 }
1592
1593 armnn::PadDescriptor m_Descriptor;
1594 };
1595
1596 const std::string layerName("pad");
1597 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1598 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1599
1600 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1601
1602 armnn::INetworkPtr network = armnn::INetwork::Create();
1603 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1604 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
1605 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1606
1607 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
1608 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1609
1610 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1611 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1612
1613 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1614 BOOST_CHECK(deserializedNetwork);
1615
1616 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1617 deserializedNetwork->Accept(verifier);
1618}
1619
1620BOOST_AUTO_TEST_CASE(SerializePermute)
1621{
1622 class PermuteLayerVerifier : public LayerVerifierBase
1623 {
1624 public:
1625 PermuteLayerVerifier(const std::string& layerName,
1626 const std::vector<armnn::TensorInfo>& inputInfos,
1627 const std::vector<armnn::TensorInfo>& outputInfos,
1628 const armnn::PermuteDescriptor& descriptor)
1629 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1630 , m_Descriptor(descriptor) {}
1631
1632 void VisitPermuteLayer(const armnn::IConnectableLayer* layer,
1633 const armnn::PermuteDescriptor& descriptor,
1634 const char* name) override
1635 {
1636 VerifyNameAndConnections(layer, name);
1637 VerifyDescriptor(descriptor);
1638 }
1639
1640 private:
1641 void VerifyDescriptor(const armnn::PermuteDescriptor& descriptor)
1642 {
1643 BOOST_TEST(descriptor.m_DimMappings.IsEqual(m_Descriptor.m_DimMappings));
1644 }
1645
1646 armnn::PermuteDescriptor m_Descriptor;
1647 };
1648
1649 const std::string layerName("permute");
1650 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
1651 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1652
1653 armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
1654
1655 armnn::INetworkPtr network = armnn::INetwork::Create();
1656 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1657 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
1658 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1659
1660 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
1661 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1662
1663 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1664 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1665
1666 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1667 BOOST_CHECK(deserializedNetwork);
1668
1669 PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
1670 deserializedNetwork->Accept(verifier);
1671}
1672
1673BOOST_AUTO_TEST_CASE(SerializePooling2d)
1674{
1675 class Pooling2dLayerVerifier : public LayerVerifierBase
1676 {
1677 public:
1678 Pooling2dLayerVerifier(const std::string& layerName,
1679 const std::vector<armnn::TensorInfo>& inputInfos,
1680 const std::vector<armnn::TensorInfo>& outputInfos,
1681 const armnn::Pooling2dDescriptor& descriptor)
1682 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1683 , m_Descriptor(descriptor) {}
1684
1685 void VisitPooling2dLayer(const armnn::IConnectableLayer* layer,
1686 const armnn::Pooling2dDescriptor& descriptor,
1687 const char* name) override
1688 {
1689 VerifyNameAndConnections(layer, name);
1690 VerifyDescriptor(descriptor);
1691 }
1692
1693 private:
1694 void VerifyDescriptor(const armnn::Pooling2dDescriptor& descriptor)
1695 {
1696 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1697 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
1698 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
1699 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
1700 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
1701 BOOST_TEST(descriptor.m_PoolWidth == m_Descriptor.m_PoolWidth);
1702 BOOST_TEST(descriptor.m_PoolHeight == m_Descriptor.m_PoolHeight);
1703 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
1704 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
1705
1706 BOOST_TEST(
1707 static_cast<int>(descriptor.m_PaddingMethod) == static_cast<int>(m_Descriptor.m_PaddingMethod));
1708 BOOST_TEST(
1709 static_cast<int>(descriptor.m_PoolType) == static_cast<int>(m_Descriptor.m_PoolType));
1710 BOOST_TEST(
1711 static_cast<int>(descriptor.m_OutputShapeRounding) ==
1712 static_cast<int>(m_Descriptor.m_OutputShapeRounding));
1713 }
1714
1715 armnn::Pooling2dDescriptor m_Descriptor;
1716 };
1717
1718 const std::string layerName("pooling2d");
1719 const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
1720 const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
1721
1722 armnn::Pooling2dDescriptor desc;
1723 desc.m_DataLayout = armnn::DataLayout::NHWC;
1724 desc.m_PadTop = 0;
1725 desc.m_PadBottom = 0;
1726 desc.m_PadLeft = 0;
1727 desc.m_PadRight = 0;
1728 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
1729 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1730 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1731 desc.m_PoolHeight = 2;
1732 desc.m_PoolWidth = 2;
1733 desc.m_StrideX = 2;
1734 desc.m_StrideY = 2;
1735
1736 armnn::INetworkPtr network = armnn::INetwork::Create();
1737 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1738 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
1739 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1740
1741 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
1742 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1743
1744 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1745 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1746
1747 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1748 BOOST_CHECK(deserializedNetwork);
1749
1750 Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1751 deserializedNetwork->Accept(verifier);
1752}
1753
Derek Lamberti87acb272019-03-27 16:51:31 +00001754BOOST_AUTO_TEST_CASE(SerializeQuantize)
1755{
1756 class QuantizeLayerVerifier : public LayerVerifierBase
1757 {
1758 public:
1759 QuantizeLayerVerifier(const std::string& layerName,
1760 const std::vector<armnn::TensorInfo>& inputInfos,
1761 const std::vector<armnn::TensorInfo>& outputInfos)
1762 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1763
1764 void VisitQuantizeLayer(const armnn::IConnectableLayer* layer, const char* name) override
1765 {
1766 VerifyNameAndConnections(layer, name);
1767 }
1768 };
1769
1770 const std::string layerName("quantize");
1771 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1772
1773 armnn::INetworkPtr network = armnn::INetwork::Create();
1774 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1775 armnn::IConnectableLayer* const quantizeLayer = network->AddQuantizeLayer(layerName.c_str());
1776 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1777
1778 inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
1779 quantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1780
1781 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1782 quantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
1783
1784 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1785 BOOST_CHECK(deserializedNetwork);
1786
1787 QuantizeLayerVerifier verifier(layerName, {info}, {info});
1788 deserializedNetwork->Accept(verifier);
1789}
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +00001790BOOST_AUTO_TEST_CASE(SerializeReshape)
1791{
1792 class ReshapeLayerVerifier : public LayerVerifierBase
1793 {
1794 public:
1795 ReshapeLayerVerifier(const std::string& layerName,
1796 const std::vector<armnn::TensorInfo>& inputInfos,
1797 const std::vector<armnn::TensorInfo>& outputInfos,
1798 const armnn::ReshapeDescriptor& descriptor)
1799 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1800 , m_Descriptor(descriptor) {}
1801
1802 void VisitReshapeLayer(const armnn::IConnectableLayer* layer,
1803 const armnn::ReshapeDescriptor& descriptor,
1804 const char* name) override
1805 {
1806 VerifyNameAndConnections(layer, name);
1807 VerifyDescriptor(descriptor);
1808 }
1809
1810 private:
1811 void VerifyDescriptor(const armnn::ReshapeDescriptor& descriptor)
1812 {
1813 BOOST_TEST(descriptor.m_TargetShape == m_Descriptor.m_TargetShape);
1814 }
1815
1816 armnn::ReshapeDescriptor m_Descriptor;
1817 };
1818
1819 const std::string layerName("reshape");
1820 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
1821 const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
1822
1823 armnn::ReshapeDescriptor descriptor({3, 3});
1824
1825 armnn::INetworkPtr network = armnn::INetwork::Create();
1826 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1827 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
1828 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1829
1830 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
1831 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1832
1833 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1834 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1835
1836 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1837 BOOST_CHECK(deserializedNetwork);
1838
1839 ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1840 deserializedNetwork->Accept(verifier);
1841}
1842
1843BOOST_AUTO_TEST_CASE(SerializeResizeBilinear)
1844{
1845 class ResizeBilinearLayerVerifier : public LayerVerifierBase
1846 {
1847 public:
1848 ResizeBilinearLayerVerifier(const std::string& layerName,
1849 const std::vector<armnn::TensorInfo>& inputInfos,
1850 const std::vector<armnn::TensorInfo>& outputInfos,
1851 const armnn::ResizeBilinearDescriptor& descriptor)
1852 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1853 , m_Descriptor(descriptor) {}
1854
1855 void VisitResizeBilinearLayer(const armnn::IConnectableLayer* layer,
1856 const armnn::ResizeBilinearDescriptor& descriptor,
1857 const char* name) override
1858 {
1859 VerifyNameAndConnections(layer, name);
1860 VerifyDescriptor(descriptor);
1861 }
1862
1863 private:
1864 void VerifyDescriptor(const armnn::ResizeBilinearDescriptor& descriptor)
1865 {
1866 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1867 BOOST_TEST(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
1868 BOOST_TEST(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
1869 }
1870
1871 armnn::ResizeBilinearDescriptor m_Descriptor;
1872 };
1873
1874 const std::string layerName("resizeBilinear");
1875 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
1876 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
1877
1878 armnn::ResizeBilinearDescriptor desc;
1879 desc.m_TargetWidth = 4;
1880 desc.m_TargetHeight = 2;
1881
1882 armnn::INetworkPtr network = armnn::INetwork::Create();
1883 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1884 armnn::IConnectableLayer* const resizeLayer = network->AddResizeBilinearLayer(desc, layerName.c_str());
1885 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1886
1887 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
1888 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1889
1890 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1891 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1892
1893 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1894 BOOST_CHECK(deserializedNetwork);
1895
1896 ResizeBilinearLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1897 deserializedNetwork->Accept(verifier);
1898}
1899
1900BOOST_AUTO_TEST_CASE(SerializeRsqrt)
1901{
1902 class RsqrtLayerVerifier : public LayerVerifierBase
1903 {
1904 public:
1905 RsqrtLayerVerifier(const std::string& layerName,
1906 const std::vector<armnn::TensorInfo>& inputInfos,
1907 const std::vector<armnn::TensorInfo>& outputInfos)
1908 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1909
1910 void VisitRsqrtLayer(const armnn::IConnectableLayer* layer, const char* name) override
1911 {
1912 VerifyNameAndConnections(layer, name);
1913 }
1914 };
1915
1916 const std::string layerName("rsqrt");
1917 const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32);
1918
1919 armnn::INetworkPtr network = armnn::INetwork::Create();
1920 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1921 armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer(layerName.c_str());
1922 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1923
1924 inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0));
1925 rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1926
1927 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1928 rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1929
1930 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1931 BOOST_CHECK(deserializedNetwork);
1932
1933 RsqrtLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
1934 deserializedNetwork->Accept(verifier);
1935}
1936
1937BOOST_AUTO_TEST_CASE(SerializeSoftmax)
1938{
1939 class SoftmaxLayerVerifier : public LayerVerifierBase
1940 {
1941 public:
1942 SoftmaxLayerVerifier(const std::string& layerName,
1943 const std::vector<armnn::TensorInfo>& inputInfos,
1944 const std::vector<armnn::TensorInfo>& outputInfos,
1945 const armnn::SoftmaxDescriptor& descriptor)
1946 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1947 , m_Descriptor(descriptor) {}
1948
1949 void VisitSoftmaxLayer(const armnn::IConnectableLayer* layer,
1950 const armnn::SoftmaxDescriptor& descriptor,
1951 const char* name) override
1952 {
1953 VerifyNameAndConnections(layer, name);
1954 VerifyDescriptor(descriptor);
1955 }
1956
1957 private:
1958 void VerifyDescriptor(const armnn::SoftmaxDescriptor& descriptor)
1959 {
1960 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
1961 }
1962
1963 armnn::SoftmaxDescriptor m_Descriptor;
1964 };
1965
1966 const std::string layerName("softmax");
1967 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
1968
1969 armnn::SoftmaxDescriptor descriptor;
1970 descriptor.m_Beta = 1.0f;
1971
1972 armnn::INetworkPtr network = armnn::INetwork::Create();
1973 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1974 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
1975 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1976
1977 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
1978 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1979
1980 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1981 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
1982
1983 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1984 BOOST_CHECK(deserializedNetwork);
1985
1986 SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1987 deserializedNetwork->Accept(verifier);
1988}
1989
1990BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
1991{
1992 class SpaceToBatchNdLayerVerifier : public LayerVerifierBase
1993 {
1994 public:
1995 SpaceToBatchNdLayerVerifier(const std::string& layerName,
1996 const std::vector<armnn::TensorInfo>& inputInfos,
1997 const std::vector<armnn::TensorInfo>& outputInfos,
1998 const armnn::SpaceToBatchNdDescriptor& descriptor)
1999 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2000 , m_Descriptor(descriptor) {}
2001
2002 void VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer* layer,
2003 const armnn::SpaceToBatchNdDescriptor& descriptor,
2004 const char* name) override
2005 {
2006 VerifyNameAndConnections(layer, name);
2007 VerifyDescriptor(descriptor);
2008 }
2009
2010 private:
2011 void VerifyDescriptor(const armnn::SpaceToBatchNdDescriptor& descriptor)
2012 {
2013 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
2014 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
2015 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2016 }
2017
2018 armnn::SpaceToBatchNdDescriptor m_Descriptor;
2019 };
2020
2021 const std::string layerName("spaceToBatchNd");
2022 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
2023 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
2024
2025 armnn::SpaceToBatchNdDescriptor desc;
2026 desc.m_DataLayout = armnn::DataLayout::NCHW;
2027 desc.m_BlockShape = {2, 2};
2028 desc.m_PadList = {{0, 0}, {2, 0}};
2029
2030 armnn::INetworkPtr network = armnn::INetwork::Create();
2031 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2032 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2033 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2034
2035 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
2036 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2037
2038 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2039 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2040
2041 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2042 BOOST_CHECK(deserializedNetwork);
2043
2044 SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2045 deserializedNetwork->Accept(verifier);
2046}
2047
2048BOOST_AUTO_TEST_CASE(SerializeSplitter)
2049{
2050 class SplitterLayerVerifier : public LayerVerifierBase
2051 {
2052 public:
2053 SplitterLayerVerifier(const std::string& layerName,
2054 const std::vector<armnn::TensorInfo>& inputInfos,
2055 const std::vector<armnn::TensorInfo>& outputInfos,
2056 const armnn::ViewsDescriptor& descriptor)
2057 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2058 , m_Descriptor(descriptor) {}
2059
2060 void VisitSplitterLayer(const armnn::IConnectableLayer* layer,
2061 const armnn::ViewsDescriptor& descriptor,
2062 const char* name) override
2063 {
2064 VerifyNameAndConnections(layer, name);
2065 VerifyDescriptor(descriptor);
2066 }
2067
2068 private:
2069 void VerifyDescriptor(const armnn::ViewsDescriptor& descriptor)
2070 {
2071 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
2072 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
2073
2074 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
2075 {
2076 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
2077 {
2078 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
2079 BOOST_TEST(descriptor.GetViewSizes(i)[j] == m_Descriptor.GetViewSizes(i)[j]);
2080 }
2081 }
2082 }
2083
2084 armnn::ViewsDescriptor m_Descriptor;
2085 };
2086
2087 const unsigned int numViews = 3;
2088 const unsigned int numDimensions = 4;
2089 const unsigned int inputShape[] = {1, 18, 4, 4};
2090 const unsigned int outputShape[] = {1, 6, 4, 4};
2091
2092 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
2093 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
2094 static_cast<unsigned int>(inputShape[1]),
2095 static_cast<unsigned int>(inputShape[2]),
2096 static_cast<unsigned int>(inputShape[3])};
2097 splitterDimSizes[1] /= numViews;
2098 armnn::ViewsDescriptor desc(numViews, numDimensions);
2099
2100 for (unsigned int g = 0; g < numViews; ++g)
2101 {
2102 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
2103
2104 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
2105 {
2106 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
2107 }
2108 }
2109
2110 const std::string layerName("splitter");
2111 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
2112 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
2113
2114 armnn::INetworkPtr network = armnn::INetwork::Create();
2115 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2116 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
2117 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2118 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2119 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
2120
2121 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
2122 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2123 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2124 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
2125
2126 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2127 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2128 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
2129 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2130
2131 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2132 BOOST_CHECK(deserializedNetwork);
2133
2134 SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
2135 deserializedNetwork->Accept(verifier);
2136}
2137
2138BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
2139{
2140 class StridedSliceLayerVerifier : public LayerVerifierBase
2141 {
2142 public:
2143 StridedSliceLayerVerifier(const std::string& layerName,
2144 const std::vector<armnn::TensorInfo>& inputInfos,
2145 const std::vector<armnn::TensorInfo>& outputInfos,
2146 const armnn::StridedSliceDescriptor& descriptor)
2147 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2148 , m_Descriptor(descriptor) {}
2149
2150 void VisitStridedSliceLayer(const armnn::IConnectableLayer* layer,
2151 const armnn::StridedSliceDescriptor& descriptor,
2152 const char* name) override
2153 {
2154 VerifyNameAndConnections(layer, name);
2155 VerifyDescriptor(descriptor);
2156 }
2157
2158 private:
2159 void VerifyDescriptor(const armnn::StridedSliceDescriptor& descriptor)
2160 {
2161 BOOST_TEST(descriptor.m_Begin == m_Descriptor.m_Begin);
2162 BOOST_TEST(descriptor.m_End == m_Descriptor.m_End);
2163 BOOST_TEST(descriptor.m_Stride == m_Descriptor.m_Stride);
2164 BOOST_TEST(descriptor.m_BeginMask == m_Descriptor.m_BeginMask);
2165 BOOST_TEST(descriptor.m_EndMask == m_Descriptor.m_EndMask);
2166 BOOST_TEST(descriptor.m_ShrinkAxisMask == m_Descriptor.m_ShrinkAxisMask);
2167 BOOST_TEST(descriptor.m_EllipsisMask == m_Descriptor.m_EllipsisMask);
2168 BOOST_TEST(descriptor.m_NewAxisMask == m_Descriptor.m_NewAxisMask);
2169 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
2170 }
2171 armnn::StridedSliceDescriptor m_Descriptor;
2172 };
2173
2174 const std::string layerName("stridedSlice");
2175 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2176 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2177
2178 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2179 desc.m_EndMask = (1 << 4) - 1;
2180 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2181 desc.m_DataLayout = armnn::DataLayout::NCHW;
2182
2183 armnn::INetworkPtr network = armnn::INetwork::Create();
2184 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2185 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2186 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2187
2188 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2189 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2190
2191 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2192 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2193
2194 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2195 BOOST_CHECK(deserializedNetwork);
2196
2197 StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2198 deserializedNetwork->Accept(verifier);
2199}
2200
2201BOOST_AUTO_TEST_CASE(SerializeSubtraction)
2202{
2203 class SubtractionLayerVerifier : public LayerVerifierBase
2204 {
2205 public:
2206 SubtractionLayerVerifier(const std::string& layerName,
2207 const std::vector<armnn::TensorInfo>& inputInfos,
2208 const std::vector<armnn::TensorInfo>& outputInfos)
2209 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2210
2211 void VisitSubtractionLayer(const armnn::IConnectableLayer* layer, const char* name) override
2212 {
2213 VerifyNameAndConnections(layer, name);
2214 }
2215 };
2216
2217 const std::string layerName("subtraction");
2218 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2219
2220 armnn::INetworkPtr network = armnn::INetwork::Create();
2221 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2222 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2223 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2224 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2225
2226 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2227 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2228 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2229
2230 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2231 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2232 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2233
2234 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2235 BOOST_CHECK(deserializedNetwork);
2236
2237 SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
2238 deserializedNetwork->Accept(verifier);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +00002239}
2240
Sadik Armaganeff363d2019-04-05 15:25:46 +01002241BOOST_AUTO_TEST_CASE(SerializeSwitch)
2242{
2243 class SwitchLayerVerifier : public LayerVerifierBase
2244 {
2245 public:
2246 SwitchLayerVerifier(const std::string& layerName,
2247 const std::vector<armnn::TensorInfo>& inputInfos,
2248 const std::vector<armnn::TensorInfo>& outputInfos)
2249 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2250
2251 void VisitSwitchLayer(const armnn::IConnectableLayer* layer, const char* name) override
2252 {
2253 VerifyNameAndConnections(layer, name);
2254 }
2255
2256 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2257 const armnn::ConstTensor& input,
2258 const char *name) override {}
2259 };
2260
2261 const std::string layerName("switch");
2262 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2263
2264 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2265 armnn::ConstTensor constTensor(info, constantData);
2266
2267 armnn::INetworkPtr network = armnn::INetwork::Create();
2268 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2269 armnn::IConnectableLayer* const constantLayer = network->AddConstantLayer(constTensor, "constant");
2270 armnn::IConnectableLayer* const switchLayer = network->AddSwitchLayer(layerName.c_str());
2271 armnn::IConnectableLayer* const trueOutputLayer = network->AddOutputLayer(0);
2272 armnn::IConnectableLayer* const falseOutputLayer = network->AddOutputLayer(1);
2273
2274 inputLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(0));
2275 constantLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(1));
2276 switchLayer->GetOutputSlot(0).Connect(trueOutputLayer->GetInputSlot(0));
2277 switchLayer->GetOutputSlot(1).Connect(falseOutputLayer->GetInputSlot(0));
2278
2279 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2280 constantLayer->GetOutputSlot(0).SetTensorInfo(info);
2281 switchLayer->GetOutputSlot(0).SetTensorInfo(info);
2282 switchLayer->GetOutputSlot(1).SetTensorInfo(info);
2283
2284 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2285 BOOST_CHECK(deserializedNetwork);
2286
2287 SwitchLayerVerifier verifier(layerName, {info, info}, {info, info});
2288 deserializedNetwork->Accept(verifier);
2289}
2290
Sadik Armagandb059fd2019-03-20 12:28:32 +00002291BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
2292{
2293 class ConstantLayerVerifier : public LayerVerifierBase
2294 {
2295 public:
2296 ConstantLayerVerifier(const std::string& layerName,
2297 const std::vector<armnn::TensorInfo>& inputInfos,
2298 const std::vector<armnn::TensorInfo>& outputInfos,
2299 const armnn::ConstTensor& layerInput)
2300 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2301 , m_LayerInput(layerInput) {}
2302
2303 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2304 const armnn::ConstTensor& input,
2305 const char* name) override
2306 {
2307 VerifyNameAndConnections(layer, name);
2308
2309 CompareConstTensor(input, m_LayerInput);
2310 }
2311
2312 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
2313
2314 private:
2315 armnn::ConstTensor m_LayerInput;
2316 };
2317
2318 const std::string layerName("constant");
2319 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
2320
2321 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2322 armnn::ConstTensor constTensor(info, constantData);
2323
2324 armnn::INetworkPtr network(armnn::INetwork::Create());
2325 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2326 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2327 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2328 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2329
2330 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2331 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2332 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2333
2334 input->GetOutputSlot(0).SetTensorInfo(info);
2335 constant->GetOutputSlot(0).SetTensorInfo(info);
2336 add->GetOutputSlot(0).SetTensorInfo(info);
2337
2338 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2339 BOOST_CHECK(deserializedNetwork);
2340
2341 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
2342 deserializedNetwork->Accept(verifier);
2343}
2344
Jim Flynn11af3752019-03-19 17:22:29 +00002345class VerifyLstmLayer : public LayerVerifierBase
2346{
2347public:
2348 VerifyLstmLayer(const std::string& layerName,
2349 const std::vector<armnn::TensorInfo>& inputInfos,
2350 const std::vector<armnn::TensorInfo>& outputInfos,
2351 const armnn::LstmDescriptor& descriptor,
2352 const armnn::LstmInputParams& inputParams) :
2353 LayerVerifierBase(layerName, inputInfos, outputInfos), m_Descriptor(descriptor), m_InputParams(inputParams)
2354 {
2355 }
2356 void VisitLstmLayer(const armnn::IConnectableLayer* layer,
2357 const armnn::LstmDescriptor& descriptor,
2358 const armnn::LstmInputParams& params,
2359 const char* name)
2360 {
2361 VerifyNameAndConnections(layer, name);
2362 VerifyDescriptor(descriptor);
2363 VerifyInputParameters(params);
2364 }
2365protected:
2366 void VerifyDescriptor(const armnn::LstmDescriptor& descriptor)
2367 {
2368 BOOST_TEST(m_Descriptor.m_ActivationFunc == descriptor.m_ActivationFunc);
2369 BOOST_TEST(m_Descriptor.m_ClippingThresCell == descriptor.m_ClippingThresCell);
2370 BOOST_TEST(m_Descriptor.m_ClippingThresProj == descriptor.m_ClippingThresProj);
2371 BOOST_TEST(m_Descriptor.m_CifgEnabled == descriptor.m_CifgEnabled);
2372 BOOST_TEST(m_Descriptor.m_PeepholeEnabled = descriptor.m_PeepholeEnabled);
2373 BOOST_TEST(m_Descriptor.m_ProjectionEnabled == descriptor.m_ProjectionEnabled);
2374 }
2375 void VerifyInputParameters(const armnn::LstmInputParams& params)
2376 {
2377 VerifyConstTensors(
2378 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
2379 VerifyConstTensors(
2380 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
2381 VerifyConstTensors(
2382 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
2383 VerifyConstTensors(
2384 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
2385 VerifyConstTensors(
2386 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
2387 VerifyConstTensors(
2388 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
2389 VerifyConstTensors(
2390 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
2391 VerifyConstTensors(
2392 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
2393 VerifyConstTensors(
2394 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
2395 VerifyConstTensors(
2396 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
2397 VerifyConstTensors(
2398 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
2399 VerifyConstTensors(
2400 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
2401 VerifyConstTensors(
2402 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
2403 VerifyConstTensors(
2404 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
2405 VerifyConstTensors(
2406 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
2407 VerifyConstTensors(
2408 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
2409 VerifyConstTensors(
2410 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
2411 }
2412 void VerifyConstTensors(const std::string& tensorName,
2413 const armnn::ConstTensor* expectedPtr,
2414 const armnn::ConstTensor* actualPtr)
2415 {
2416 if (expectedPtr == nullptr)
2417 {
2418 BOOST_CHECK_MESSAGE(actualPtr == nullptr, tensorName + " should not exist");
2419 }
2420 else
2421 {
2422 BOOST_CHECK_MESSAGE(actualPtr != nullptr, tensorName + " should have been set");
2423 if (actualPtr != nullptr)
2424 {
2425 const armnn::TensorInfo& expectedInfo = expectedPtr->GetInfo();
2426 const armnn::TensorInfo& actualInfo = actualPtr->GetInfo();
2427
2428 BOOST_CHECK_MESSAGE(expectedInfo.GetShape() == actualInfo.GetShape(),
2429 tensorName + " shapes don't match");
2430 BOOST_CHECK_MESSAGE(
2431 GetDataTypeName(expectedInfo.GetDataType()) == GetDataTypeName(actualInfo.GetDataType()),
2432 tensorName + " data types don't match");
2433
2434 BOOST_CHECK_MESSAGE(expectedPtr->GetNumBytes() == actualPtr->GetNumBytes(),
2435 tensorName + " (GetNumBytes) data sizes do not match");
2436 if (expectedPtr->GetNumBytes() == actualPtr->GetNumBytes())
2437 {
2438 //check the data is identical
2439 const char* expectedData = static_cast<const char*>(expectedPtr->GetMemoryArea());
2440 const char* actualData = static_cast<const char*>(actualPtr->GetMemoryArea());
2441 bool same = true;
2442 for (unsigned int i = 0; i < expectedPtr->GetNumBytes(); ++i)
2443 {
2444 same = expectedData[i] == actualData[i];
2445 if (!same)
2446 {
2447 break;
2448 }
2449 }
2450 BOOST_CHECK_MESSAGE(same, tensorName + " data does not match");
2451 }
2452 }
2453 }
2454 }
2455private:
2456 armnn::LstmDescriptor m_Descriptor;
2457 armnn::LstmInputParams m_InputParams;
2458};
2459
2460BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
2461{
2462 armnn::LstmDescriptor descriptor;
2463 descriptor.m_ActivationFunc = 4;
2464 descriptor.m_ClippingThresProj = 0.0f;
2465 descriptor.m_ClippingThresCell = 0.0f;
2466 descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
2467 descriptor.m_ProjectionEnabled = false;
2468 descriptor.m_PeepholeEnabled = true;
2469
2470 const uint32_t batchSize = 1;
2471 const uint32_t inputSize = 2;
2472 const uint32_t numUnits = 4;
2473 const uint32_t outputSize = numUnits;
2474
2475 armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
2476 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2477 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
2478
2479 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2480 armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
2481
2482 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2483 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
2484
2485 armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
2486 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2487 armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
2488
2489 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2490 armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
2491
2492 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2493 armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
2494
2495 armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
2496 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2497 armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
2498
2499 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2500 armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
2501
2502 std::vector<float> forgetGateBiasData(numUnits, 1.0f);
2503 armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
2504
2505 std::vector<float> cellBiasData(numUnits, 0.0f);
2506 armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
2507
2508 std::vector<float> outputGateBiasData(numUnits, 0.0f);
2509 armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
2510
2511 armnn::LstmInputParams params;
2512 params.m_InputToForgetWeights = &inputToForgetWeights;
2513 params.m_InputToCellWeights = &inputToCellWeights;
2514 params.m_InputToOutputWeights = &inputToOutputWeights;
2515 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2516 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2517 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2518 params.m_ForgetGateBias = &forgetGateBias;
2519 params.m_CellBias = &cellBias;
2520 params.m_OutputGateBias = &outputGateBias;
2521 params.m_CellToForgetWeights = &cellToForgetWeights;
2522 params.m_CellToOutputWeights = &cellToOutputWeights;
2523
2524 armnn::INetworkPtr network = armnn::INetwork::Create();
2525 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2526 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2527 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2528 const std::string layerName("lstm");
2529 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2530 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2531 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2532 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2533 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2534
2535 // connect up
2536 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2537 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2538 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2539 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
2540
2541 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2542 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2543
2544 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2545 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2546
2547 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2548 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2549
2550 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2551 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2552
2553 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2554 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2555
2556 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2557 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2558
2559 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2560 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2561
2562 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2563 BOOST_CHECK(deserializedNetwork);
2564
2565 VerifyLstmLayer checker(
2566 layerName,
2567 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2568 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2569 descriptor,
2570 params);
2571 deserializedNetwork->Accept(checker);
2572}
2573
2574BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
2575{
2576 armnn::LstmDescriptor descriptor;
2577 descriptor.m_ActivationFunc = 4;
2578 descriptor.m_ClippingThresProj = 0.0f;
2579 descriptor.m_ClippingThresCell = 0.0f;
2580 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
2581 descriptor.m_ProjectionEnabled = true;
2582 descriptor.m_PeepholeEnabled = true;
2583
2584 const uint32_t batchSize = 2;
2585 const uint32_t inputSize = 5;
2586 const uint32_t numUnits = 20;
2587 const uint32_t outputSize = 16;
2588
2589 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
2590 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2591 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
2592
2593 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2594 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
2595
2596 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2597 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
2598
2599 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2600 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
2601
2602 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
2603 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2604 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
2605
2606 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2607 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
2608
2609 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2610 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
2611
2612 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2613 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
2614
2615 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
2616 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2617 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
2618
2619 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2620 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
2621
2622 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2623 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
2624
2625 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2626 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
2627
2628 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2629 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
2630
2631 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2632 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
2633
2634 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2635 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
2636
2637 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
2638 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
2639 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
2640
2641 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
2642 std::vector<float> projectionBiasData(outputSize, 0.f);
2643 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
2644
2645 armnn::LstmInputParams params;
2646 params.m_InputToForgetWeights = &inputToForgetWeights;
2647 params.m_InputToCellWeights = &inputToCellWeights;
2648 params.m_InputToOutputWeights = &inputToOutputWeights;
2649 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2650 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2651 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2652 params.m_ForgetGateBias = &forgetGateBias;
2653 params.m_CellBias = &cellBias;
2654 params.m_OutputGateBias = &outputGateBias;
2655
2656 // additional params because: descriptor.m_CifgEnabled = false
2657 params.m_InputToInputWeights = &inputToInputWeights;
2658 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
2659 params.m_CellToInputWeights = &cellToInputWeights;
2660 params.m_InputGateBias = &inputGateBias;
2661
2662 // additional params because: descriptor.m_ProjectionEnabled = true
2663 params.m_ProjectionWeights = &projectionWeights;
2664 params.m_ProjectionBias = &projectionBias;
2665
2666 // additional params because: descriptor.m_PeepholeEnabled = true
2667 params.m_CellToForgetWeights = &cellToForgetWeights;
2668 params.m_CellToOutputWeights = &cellToOutputWeights;
2669
2670 armnn::INetworkPtr network = armnn::INetwork::Create();
2671 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2672 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2673 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2674 const std::string layerName("lstm");
2675 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2676 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2677 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2678 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2679 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2680
2681 // connect up
2682 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2683 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2684 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2685 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
2686
2687 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2688 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2689
2690 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2691 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2692
2693 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2694 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2695
2696 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2697 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2698
2699 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2700 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2701
2702 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2703 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2704
2705 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2706 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2707
2708 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2709 BOOST_CHECK(deserializedNetwork);
2710
2711 VerifyLstmLayer checker(
2712 layerName,
2713 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2714 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2715 descriptor,
2716 params);
2717 deserializedNetwork->Accept(checker);
2718}
2719
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002720BOOST_AUTO_TEST_SUITE_END()