blob: e3ce6d29d3c80b220fe34b6a996adcf6d9388d37 [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{
24 static void Apply()
25 {
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()));
62 }
63
64 for (unsigned int i = 0; i < m_OutputTensorInfos.size(); i++)
65 {
66 const armnn::TensorInfo& outputInfo = layer->GetOutputSlot(i).GetTensorInfo();
67 BOOST_TEST(outputInfo.GetShape() == m_OutputTensorInfos[i].GetShape());
68 BOOST_TEST(
69 GetDataTypeName(outputInfo.GetDataType()) == GetDataTypeName(m_OutputTensorInfos[i].GetDataType()));
70 }
71 }
72
73private:
74 std::string m_LayerName;
75 std::vector<armnn::TensorInfo> m_InputTensorInfos;
76 std::vector<armnn::TensorInfo> m_OutputTensorInfos;
77};
78
79template<typename T>
80void CompareConstTensorData(const void* data1, const void* data2, unsigned int numElements)
81{
82 T typedData1 = static_cast<T>(data1);
83 T typedData2 = static_cast<T>(data2);
84 BOOST_CHECK(typedData1);
85 BOOST_CHECK(typedData2);
86
87 for (unsigned int i = 0; i < numElements; i++)
88 {
89 BOOST_TEST(typedData1[i] == typedData2[i]);
90 }
91}
92
93void CompareConstTensor(const armnn::ConstTensor& tensor1, const armnn::ConstTensor& tensor2)
94{
95 BOOST_TEST(tensor1.GetShape() == tensor2.GetShape());
96 BOOST_TEST(GetDataTypeName(tensor1.GetDataType()) == GetDataTypeName(tensor2.GetDataType()));
97
98 switch (tensor1.GetDataType())
99 {
100 case armnn::DataType::Float32:
101 CompareConstTensorData<const float*>(
102 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
103 break;
104 case armnn::DataType::QuantisedAsymm8:
105 case armnn::DataType::Boolean:
106 CompareConstTensorData<const uint8_t*>(
107 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
108 break;
109 case armnn::DataType::Signed32:
110 CompareConstTensorData<const int32_t*>(
111 tensor1.GetMemoryArea(), tensor2.GetMemoryArea(), tensor1.GetNumElements());
112 break;
113 default:
114 // Note that Float16 is not yet implemented
115 BOOST_TEST_MESSAGE("Unexpected datatype");
116 BOOST_TEST(false);
117 }
118}
119
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000120armnn::INetworkPtr DeserializeNetwork(const std::string& serializerString)
121{
122 std::vector<std::uint8_t> const serializerVector{serializerString.begin(), serializerString.end()};
Derek Lamberti0028d1b2019-02-20 13:57:42 +0000123 return IDeserializer::Create()->CreateNetworkFromBinary(serializerVector);
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000124}
125
126std::string SerializeNetwork(const armnn::INetwork& network)
127{
128 armnnSerializer::Serializer serializer;
129 serializer.Serialize(network);
130
131 std::stringstream stream;
132 serializer.SaveSerializedToStream(stream);
133
134 std::string serializerString{stream.str()};
135 return serializerString;
136}
137
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000138template<typename DataType>
139static std::vector<DataType> GenerateRandomData(size_t size)
140{
141 constexpr bool isIntegerType = std::is_integral<DataType>::value;
142 using Distribution =
143 typename std::conditional<isIntegerType,
144 std::uniform_int_distribution<DataType>,
145 std::uniform_real_distribution<DataType>>::type;
146
147 static constexpr DataType lowerLimit = std::numeric_limits<DataType>::min();
148 static constexpr DataType upperLimit = std::numeric_limits<DataType>::max();
149
150 static Distribution distribution(lowerLimit, upperLimit);
151 static std::default_random_engine generator;
152
153 std::vector<DataType> randomData(size);
154 std::generate(randomData.begin(), randomData.end(), []() { return distribution(generator); });
155
156 return randomData;
157}
158
Saoirse Stewart3166c3e2019-02-18 15:24:53 +0000159} // anonymous namespace
160
161BOOST_AUTO_TEST_SUITE(SerializerTests)
Aron Virginas-Tarfc413c02019-02-13 15:41:52 +0000162
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000163BOOST_AUTO_TEST_CASE(SerializeAddition)
Mike Kelly8c1701a2019-02-11 17:01:27 +0000164{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000165 class AdditionLayerVerifier : public LayerVerifierBase
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000166 {
167 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000168 AdditionLayerVerifier(const std::string& layerName,
169 const std::vector<armnn::TensorInfo>& inputInfos,
170 const std::vector<armnn::TensorInfo>& outputInfos)
171 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
172
173 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name) override
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000174 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000175 VerifyNameAndConnections(layer, name);
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000176 }
177 };
178
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000179 const std::string layerName("addition");
180 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
181
Mike Kelly8c1701a2019-02-11 17:01:27 +0000182 armnn::INetworkPtr network = armnn::INetwork::Create();
183 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
184 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000185 armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer(layerName.c_str());
186 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000187
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000188 inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
189 inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000190 additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Mike Kelly8c1701a2019-02-11 17:01:27 +0000191
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000192 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
193 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
194 additionLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
Jim Flynn3091b062019-02-15 14:45:04 +0000195
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000196 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000197 BOOST_CHECK(deserializedNetwork);
198
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000199 AdditionLayerVerifier verifier(layerName, {tensorInfo, tensorInfo}, {tensorInfo});
200 deserializedNetwork->Accept(verifier);
201}
Jim Flynnac25a1b2019-02-28 10:40:49 +0000202
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000203BOOST_AUTO_TEST_CASE(SerializeBatchNormalization)
204{
205 class BatchNormalizationLayerVerifier : public LayerVerifierBase
206 {
207 public:
208 BatchNormalizationLayerVerifier(const std::string& layerName,
209 const std::vector<armnn::TensorInfo>& inputInfos,
210 const std::vector<armnn::TensorInfo>& outputInfos,
211 const armnn::BatchNormalizationDescriptor& descriptor,
212 const armnn::ConstTensor& mean,
213 const armnn::ConstTensor& variance,
214 const armnn::ConstTensor& beta,
215 const armnn::ConstTensor& gamma)
216 : LayerVerifierBase(layerName, inputInfos, outputInfos)
217 , m_Descriptor(descriptor)
218 , m_Mean(mean)
219 , m_Variance(variance)
220 , m_Beta(beta)
221 , m_Gamma(gamma) {}
222
223 void VisitBatchNormalizationLayer(const armnn::IConnectableLayer* layer,
224 const armnn::BatchNormalizationDescriptor& descriptor,
225 const armnn::ConstTensor& mean,
226 const armnn::ConstTensor& variance,
227 const armnn::ConstTensor& beta,
228 const armnn::ConstTensor& gamma,
229 const char* name) override
230 {
231 VerifyNameAndConnections(layer, name);
232 VerifyDescriptor(descriptor);
233
234 CompareConstTensor(mean, m_Mean);
235 CompareConstTensor(variance, m_Variance);
236 CompareConstTensor(beta, m_Beta);
237 CompareConstTensor(gamma, m_Gamma);
238 }
239
240 private:
241 void VerifyDescriptor(const armnn::BatchNormalizationDescriptor& descriptor)
242 {
243 BOOST_TEST(descriptor.m_Eps == m_Descriptor.m_Eps);
244 BOOST_TEST(static_cast<int>(descriptor.m_DataLayout) == static_cast<int>(m_Descriptor.m_DataLayout));
245 }
246
247 armnn::BatchNormalizationDescriptor m_Descriptor;
248 armnn::ConstTensor m_Mean;
249 armnn::ConstTensor m_Variance;
250 armnn::ConstTensor m_Beta;
251 armnn::ConstTensor m_Gamma;
252 };
253
254 const std::string layerName("batchNormalization");
255 const armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32);
256 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
257
258 const armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32);
259 const armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32);
260 const armnn::TensorInfo betaInfo({1}, armnn::DataType::Float32);
261 const armnn::TensorInfo gammaInfo({1}, armnn::DataType::Float32);
262
263 armnn::BatchNormalizationDescriptor descriptor;
264 descriptor.m_Eps = 0.0010000000475f;
265 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
266
267 std::vector<float> meanData({5.0});
268 std::vector<float> varianceData({2.0});
269 std::vector<float> betaData({1.0});
270 std::vector<float> gammaData({0.0});
271
272 armnn::ConstTensor mean(meanInfo, meanData);
273 armnn::ConstTensor variance(varianceInfo, varianceData);
274 armnn::ConstTensor beta(betaInfo, betaData);
275 armnn::ConstTensor gamma(gammaInfo, gammaData);
276
277 armnn::INetworkPtr network = armnn::INetwork::Create();
278 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
279 armnn::IConnectableLayer* const batchNormalizationLayer =
280 network->AddBatchNormalizationLayer(descriptor, mean, variance, beta, gamma, layerName.c_str());
281 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
282
283 inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0));
284 batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
285
286 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
287 batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
288
289 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
290 BOOST_CHECK(deserializedNetwork);
291
292 BatchNormalizationLayerVerifier verifier(
293 layerName, {inputInfo}, {outputInfo}, descriptor, mean, variance, beta, gamma);
294 deserializedNetwork->Accept(verifier);
295}
296
297BOOST_AUTO_TEST_CASE(SerializeBatchToSpaceNd)
298{
299 class BatchToSpaceNdLayerVerifier : public LayerVerifierBase
300 {
301 public:
302 BatchToSpaceNdLayerVerifier(const std::string& layerName,
303 const std::vector<armnn::TensorInfo>& inputInfos,
304 const std::vector<armnn::TensorInfo>& outputInfos,
305 const armnn::BatchToSpaceNdDescriptor& descriptor)
306 : LayerVerifierBase(layerName, inputInfos, outputInfos)
307 , m_Descriptor(descriptor) {}
308
309 void VisitBatchToSpaceNdLayer(const armnn::IConnectableLayer* layer,
310 const armnn::BatchToSpaceNdDescriptor& descriptor,
311 const char* name) override
312 {
313 VerifyNameAndConnections(layer, name);
314 VerifyDescriptor(descriptor);
315 }
316
317 private:
318 void VerifyDescriptor(const armnn::BatchToSpaceNdDescriptor& descriptor)
319 {
320 BOOST_TEST(descriptor.m_Crops == m_Descriptor.m_Crops);
321 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
322 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
323 }
324
325 armnn::BatchToSpaceNdDescriptor m_Descriptor;
326 };
327
328 const std::string layerName("spaceToBatchNd");
329 const armnn::TensorInfo inputInfo({4, 1, 2, 2}, armnn::DataType::Float32);
330 const armnn::TensorInfo outputInfo({1, 1, 4, 4}, armnn::DataType::Float32);
331
332 armnn::BatchToSpaceNdDescriptor desc;
333 desc.m_DataLayout = armnn::DataLayout::NCHW;
334 desc.m_BlockShape = {2, 2};
335 desc.m_Crops = {{0, 0}, {0, 0}};
336
337 armnn::INetworkPtr network = armnn::INetwork::Create();
338 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
339 armnn::IConnectableLayer* const batchToSpaceNdLayer = network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
340 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
341
342 inputLayer->GetOutputSlot(0).Connect(batchToSpaceNdLayer->GetInputSlot(0));
343 batchToSpaceNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
344
345 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
346 batchToSpaceNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
347
348 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
349 BOOST_CHECK(deserializedNetwork);
350
351 BatchToSpaceNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
352 deserializedNetwork->Accept(verifier);
Mike Kelly8c1701a2019-02-11 17:01:27 +0000353}
354
Conor Kennedy76277882019-02-26 08:29:54 +0000355BOOST_AUTO_TEST_CASE(SerializeConstant)
356{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000357 class ConstantLayerVerifier : public LayerVerifierBase
Conor Kennedy76277882019-02-26 08:29:54 +0000358 {
359 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000360 ConstantLayerVerifier(const std::string& layerName,
361 const std::vector<armnn::TensorInfo>& inputInfos,
362 const std::vector<armnn::TensorInfo>& outputInfos,
363 const armnn::ConstTensor& layerInput)
364 : LayerVerifierBase(layerName, inputInfos, outputInfos)
365 , m_LayerInput(layerInput) {}
366
367 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
368 const armnn::ConstTensor& input,
369 const char* name) override
Conor Kennedy76277882019-02-26 08:29:54 +0000370 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000371 VerifyNameAndConnections(layer, name);
372
373 CompareConstTensor(input, m_LayerInput);
Conor Kennedy76277882019-02-26 08:29:54 +0000374 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000375
376 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
377
378 private:
379 armnn::ConstTensor m_LayerInput;
Conor Kennedy76277882019-02-26 08:29:54 +0000380 };
381
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000382 const std::string layerName("constant");
383 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
Conor Kennedy76277882019-02-26 08:29:54 +0000384
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000385 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
386 armnn::ConstTensor constTensor(info, constantData);
Conor Kennedy76277882019-02-26 08:29:54 +0000387
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000388 armnn::INetworkPtr network(armnn::INetwork::Create());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000389 armnn::IConnectableLayer* input = network->AddInputLayer(0);
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000390 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000391 armnn::IConnectableLayer* add = network->AddAdditionLayer();
392 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
Conor Kennedy76277882019-02-26 08:29:54 +0000393
394 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
395 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
396 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
397
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000398 input->GetOutputSlot(0).SetTensorInfo(info);
399 constant->GetOutputSlot(0).SetTensorInfo(info);
400 add->GetOutputSlot(0).SetTensorInfo(info);
Conor Kennedy76277882019-02-26 08:29:54 +0000401
Matteo Martincighf81edaa2019-03-04 14:34:30 +0000402 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
Conor Kennedy76277882019-02-26 08:29:54 +0000403 BOOST_CHECK(deserializedNetwork);
404
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000405 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
406 deserializedNetwork->Accept(verifier);
Conor Kennedy76277882019-02-26 08:29:54 +0000407}
408
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000409BOOST_AUTO_TEST_CASE(SerializeConvolution2d)
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000410{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000411 class Convolution2dLayerVerifier : public LayerVerifierBase
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000412 {
413 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000414 Convolution2dLayerVerifier(const std::string& layerName,
415 const std::vector<armnn::TensorInfo>& inputInfos,
416 const std::vector<armnn::TensorInfo>& outputInfos,
417 const armnn::Convolution2dDescriptor& descriptor,
418 const armnn::ConstTensor& weight,
419 const armnn::Optional<armnn::ConstTensor>& bias)
420 : LayerVerifierBase(layerName, inputInfos, outputInfos)
421 , m_Descriptor(descriptor)
422 , m_Weight(weight)
423 , m_Bias(bias) {}
Finn Williamsdd2ba7e2019-03-01 11:51:52 +0000424
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000425 void VisitConvolution2dLayer(const armnn::IConnectableLayer* layer,
426 const armnn::Convolution2dDescriptor& descriptor,
427 const armnn::ConstTensor& weight,
428 const armnn::Optional<armnn::ConstTensor>& bias,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000429 const char* name) override
430 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000431 VerifyNameAndConnections(layer, name);
432 VerifyDescriptor(descriptor);
433
434 CompareConstTensor(weight, m_Weight);
435
436 BOOST_TEST(bias.has_value() == m_Bias.has_value());
437 if (bias.has_value() && m_Bias.has_value())
438 {
439 CompareConstTensor(bias.value(), m_Bias.value());
440 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000441 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000442
443 private:
444 void VerifyDescriptor(const armnn::Convolution2dDescriptor& descriptor)
445 {
446 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
447 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
448 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
449 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
450 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
451 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
452 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
453 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
454 }
455
456 armnn::Convolution2dDescriptor m_Descriptor;
457 armnn::ConstTensor m_Weight;
458 armnn::Optional<armnn::ConstTensor> m_Bias;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000459 };
460
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000461 const std::string layerName("convolution2d");
462 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
463 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
Saoirse Stewart263829c2019-02-19 15:54:14 +0000464
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000465 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
466 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000467
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000468 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
469 armnn::ConstTensor weights(weightsInfo, weightsData);
470
471 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
472 armnn::ConstTensor biases(biasesInfo, biasesData);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000473
474 armnn::Convolution2dDescriptor descriptor;
475 descriptor.m_PadLeft = 1;
476 descriptor.m_PadRight = 1;
477 descriptor.m_PadTop = 1;
478 descriptor.m_PadBottom = 1;
479 descriptor.m_StrideX = 2;
480 descriptor.m_StrideY = 2;
481 descriptor.m_BiasEnabled = true;
482 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
483
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000484 armnn::INetworkPtr network = armnn::INetwork::Create();
485 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000486 armnn::IConnectableLayer* const convLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000487 network->AddConvolution2dLayer(descriptor, weights, biases, layerName.c_str());
488 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000489
490 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000491 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000492
493 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000494 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
495
496 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
497 BOOST_CHECK(deserializedNetwork);
498
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000499 Convolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
500 deserializedNetwork->Accept(verifier);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000501}
502
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000503BOOST_AUTO_TEST_CASE(SerializeDepthwiseConvolution2d)
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000504{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000505 class DepthwiseConvolution2dLayerVerifier : public LayerVerifierBase
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000506 {
507 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000508 DepthwiseConvolution2dLayerVerifier(const std::string& layerName,
509 const std::vector<armnn::TensorInfo>& inputInfos,
510 const std::vector<armnn::TensorInfo>& outputInfos,
511 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
512 const armnn::ConstTensor& weight,
513 const armnn::Optional<armnn::ConstTensor>& bias)
514 : LayerVerifierBase(layerName, inputInfos, outputInfos)
515 , m_Descriptor(descriptor)
516 , m_Weight(weight)
517 , m_Bias(bias) {}
Conor Kennedy79ffdf52019-03-01 14:24:54 +0000518
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000519 void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
520 const armnn::DepthwiseConvolution2dDescriptor& descriptor,
521 const armnn::ConstTensor& weight,
522 const armnn::Optional<armnn::ConstTensor>& bias,
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000523 const char* name) override
524 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000525 VerifyNameAndConnections(layer, name);
526 VerifyDescriptor(descriptor);
527
528 CompareConstTensor(weight, m_Weight);
529
530 BOOST_TEST(bias.has_value() == m_Bias.has_value());
531 if (bias.has_value() && m_Bias.has_value())
532 {
533 CompareConstTensor(bias.value(), m_Bias.value());
534 }
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000535 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000536
537 private:
538 void VerifyDescriptor(const armnn::DepthwiseConvolution2dDescriptor& descriptor)
539 {
540 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
541 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
542 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
543 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
544 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
545 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
546 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
547 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
548 }
549
550 armnn::DepthwiseConvolution2dDescriptor m_Descriptor;
551 armnn::ConstTensor m_Weight;
552 armnn::Optional<armnn::ConstTensor> m_Bias;
Éanna Ó Catháin633f8592019-02-25 16:26:29 +0000553 };
554
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000555 const std::string layerName("depwiseConvolution2d");
556 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
557 const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000558
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000559 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
560 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000561
562 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
563 armnn::ConstTensor weights(weightsInfo, weightsData);
564
565 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
566 armnn::ConstTensor biases(biasesInfo, biasesData);
567
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000568 armnn::DepthwiseConvolution2dDescriptor descriptor;
569 descriptor.m_StrideX = 1;
570 descriptor.m_StrideY = 1;
571 descriptor.m_BiasEnabled = true;
572 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
573
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000574 armnn::INetworkPtr network = armnn::INetwork::Create();
575 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
576 armnn::IConnectableLayer* const depthwiseConvLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000577 network->AddDepthwiseConvolution2dLayer(descriptor, weights, biases, layerName.c_str());
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000578 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
579
580 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000581 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000582
583 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
Aron Virginas-Tarc04125f2019-02-19 16:31:08 +0000584 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
585
586 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
587 BOOST_CHECK(deserializedNetwork);
588
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000589 DepthwiseConvolution2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
590 deserializedNetwork->Accept(verifier);
Jim Flynn18ce3382019-03-08 11:08:30 +0000591}
592
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000593BOOST_AUTO_TEST_CASE(SerializeDeserializeDetectionPostProcess)
594{
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000595 class DetectionPostProcessLayerVerifier : public LayerVerifierBase
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000596 {
597 public:
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000598 DetectionPostProcessLayerVerifier(const std::string& layerName,
599 const std::vector<armnn::TensorInfo>& inputInfos,
600 const std::vector<armnn::TensorInfo>& outputInfos,
601 const armnn::DetectionPostProcessDescriptor& descriptor,
602 const armnn::ConstTensor& anchors)
603 : LayerVerifierBase(layerName, inputInfos, outputInfos)
604 , m_Descriptor(descriptor)
605 , m_Anchors(anchors) {}
606
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000607 void VisitDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
608 const armnn::DetectionPostProcessDescriptor& descriptor,
609 const armnn::ConstTensor& anchors,
610 const char* name) override
611 {
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000612 VerifyNameAndConnections(layer, name);
613 VerifyDescriptor(descriptor);
614
615 CompareConstTensor(anchors, m_Anchors);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000616 }
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000617
618 private:
619 void VerifyDescriptor(const armnn::DetectionPostProcessDescriptor& descriptor)
620 {
621 BOOST_TEST(descriptor.m_UseRegularNms == m_Descriptor.m_UseRegularNms);
622 BOOST_TEST(descriptor.m_MaxDetections == m_Descriptor.m_MaxDetections);
623 BOOST_TEST(descriptor.m_MaxClassesPerDetection == m_Descriptor.m_MaxClassesPerDetection);
624 BOOST_TEST(descriptor.m_DetectionsPerClass == m_Descriptor.m_DetectionsPerClass);
625 BOOST_TEST(descriptor.m_NmsScoreThreshold == m_Descriptor.m_NmsScoreThreshold);
626 BOOST_TEST(descriptor.m_NmsIouThreshold == m_Descriptor.m_NmsIouThreshold);
627 BOOST_TEST(descriptor.m_NumClasses == m_Descriptor.m_NumClasses);
628 BOOST_TEST(descriptor.m_ScaleY == m_Descriptor.m_ScaleY);
629 BOOST_TEST(descriptor.m_ScaleX == m_Descriptor.m_ScaleX);
630 BOOST_TEST(descriptor.m_ScaleH == m_Descriptor.m_ScaleH);
631 BOOST_TEST(descriptor.m_ScaleW == m_Descriptor.m_ScaleW);
632 }
633
634 armnn::DetectionPostProcessDescriptor m_Descriptor;
635 armnn::ConstTensor m_Anchors;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000636 };
637
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000638 const std::string layerName("detectionPostProcess");
639
640 const std::vector<armnn::TensorInfo> inputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000641 armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32),
642 armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000643 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000644
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000645 const std::vector<armnn::TensorInfo> outputInfos({
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000646 armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32),
647 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
648 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
649 armnn::TensorInfo({ 1 }, armnn::DataType::Float32)
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000650 });
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000651
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000652 armnn::DetectionPostProcessDescriptor descriptor;
653 descriptor.m_UseRegularNms = true;
654 descriptor.m_MaxDetections = 3;
655 descriptor.m_MaxClassesPerDetection = 1;
656 descriptor.m_DetectionsPerClass =1;
657 descriptor.m_NmsScoreThreshold = 0.0;
658 descriptor.m_NmsIouThreshold = 0.5;
659 descriptor.m_NumClasses = 2;
660 descriptor.m_ScaleY = 10.0;
661 descriptor.m_ScaleX = 10.0;
662 descriptor.m_ScaleH = 5.0;
663 descriptor.m_ScaleW = 5.0;
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000664
665 const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
666 const std::vector<float> anchorsData({
667 0.5f, 0.5f, 1.0f, 1.0f,
668 0.5f, 0.5f, 1.0f, 1.0f,
669 0.5f, 0.5f, 1.0f, 1.0f,
670 0.5f, 10.5f, 1.0f, 1.0f,
671 0.5f, 10.5f, 1.0f, 1.0f,
672 0.5f, 100.5f, 1.0f, 1.0f
673 });
674 armnn::ConstTensor anchors(anchorsInfo, anchorsData);
675
676 armnn::INetworkPtr network = armnn::INetwork::Create();
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000677 armnn::IConnectableLayer* const detectionLayer =
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000678 network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000679
680 for (unsigned int i = 0; i < 2; i++)
681 {
682 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
683 inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
684 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
685 }
686
687 for (unsigned int i = 0; i < 4; i++)
688 {
689 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
690 detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
691 detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
692 }
693
694 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
695 BOOST_CHECK(deserializedNetwork);
696
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000697 DetectionPostProcessLayerVerifier verifier(layerName, inputInfos, outputInfos, descriptor, anchors);
698 deserializedNetwork->Accept(verifier);
699}
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +0000700
Nattapat Chaimanowong03acd682019-03-20 11:19:52 +0000701BOOST_AUTO_TEST_CASE(SerializeDivision)
702{
703 class DivisionLayerVerifier : public LayerVerifierBase
704 {
705 public:
706 DivisionLayerVerifier(const std::string& layerName,
707 const std::vector<armnn::TensorInfo>& inputInfos,
708 const std::vector<armnn::TensorInfo>& outputInfos)
709 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
710
711 void VisitDivisionLayer(const armnn::IConnectableLayer* layer, const char* name) override
712 {
713 VerifyNameAndConnections(layer, name);
714 }
715 };
716
717 const std::string layerName("division");
718 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
719
720 armnn::INetworkPtr network = armnn::INetwork::Create();
721 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
722 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
723 armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
724 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
725
726 inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
727 inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
728 divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
729
730 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
731 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
732 divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
733
734 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
735 BOOST_CHECK(deserializedNetwork);
736
737 DivisionLayerVerifier verifier(layerName, {info, info}, {info});
738 deserializedNetwork->Accept(verifier);
739}
740
741BOOST_AUTO_TEST_CASE(SerializeEqual)
742{
743 class EqualLayerVerifier : public LayerVerifierBase
744 {
745 public:
746 EqualLayerVerifier(const std::string& layerName,
747 const std::vector<armnn::TensorInfo>& inputInfos,
748 const std::vector<armnn::TensorInfo>& outputInfos)
749 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
750
751 void VisitEqualLayer(const armnn::IConnectableLayer* layer, const char* name) override
752 {
753 VerifyNameAndConnections(layer, name);
754 }
755 };
756
757 const std::string layerName("equal");
758 const armnn::TensorInfo inputTensorInfo1 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
759 const armnn::TensorInfo inputTensorInfo2 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
760 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Boolean);
761
762 armnn::INetworkPtr network = armnn::INetwork::Create();
763 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
764 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
765 armnn::IConnectableLayer* const equalLayer = network->AddEqualLayer(layerName.c_str());
766 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
767
768 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
769 inputLayer2->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
770 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
771
772 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
773 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
774 equalLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
775
776 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
777 BOOST_CHECK(deserializedNetwork);
778
779 EqualLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
780 deserializedNetwork->Accept(verifier);
781}
782
783BOOST_AUTO_TEST_CASE(SerializeFloor)
784{
785 class FloorLayerVerifier : public LayerVerifierBase
786 {
787 public:
788 FloorLayerVerifier(const std::string& layerName,
789 const std::vector<armnn::TensorInfo>& inputInfos,
790 const std::vector<armnn::TensorInfo>& outputInfos)
791 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
792
793 void VisitFloorLayer(const armnn::IConnectableLayer* layer, const char* name) override
794 {
795 VerifyNameAndConnections(layer, name);
796 }
797 };
798
799 const std::string layerName("floor");
800 const armnn::TensorInfo info({4,4}, armnn::DataType::Float32);
801
802 armnn::INetworkPtr network = armnn::INetwork::Create();
803 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
804 armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
805 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
806
807 inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
808 floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
809
810 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
811 floorLayer->GetOutputSlot(0).SetTensorInfo(info);
812
813 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
814 BOOST_CHECK(deserializedNetwork);
815
816 FloorLayerVerifier verifier(layerName, {info}, {info});
817 deserializedNetwork->Accept(verifier);
818}
819
820BOOST_AUTO_TEST_CASE(SerializeFullyConnected)
821{
822 class FullyConnectedLayerVerifier : public LayerVerifierBase
823 {
824 public:
825 FullyConnectedLayerVerifier(const std::string& layerName,
826 const std::vector<armnn::TensorInfo>& inputInfos,
827 const std::vector<armnn::TensorInfo>& outputInfos,
828 const armnn::FullyConnectedDescriptor& descriptor,
829 const armnn::ConstTensor& weight,
830 const armnn::Optional<armnn::ConstTensor>& bias)
831 : LayerVerifierBase(layerName, inputInfos, outputInfos)
832 , m_Descriptor(descriptor)
833 , m_Weight(weight)
834 , m_Bias(bias) {}
835
836 void VisitFullyConnectedLayer(const armnn::IConnectableLayer* layer,
837 const armnn::FullyConnectedDescriptor& descriptor,
838 const armnn::ConstTensor& weight,
839 const armnn::Optional<armnn::ConstTensor>& bias,
840 const char* name) override
841 {
842 VerifyNameAndConnections(layer, name);
843 VerifyDescriptor(descriptor);
844
845 CompareConstTensor(weight, m_Weight);
846
847 BOOST_TEST(bias.has_value() == m_Bias.has_value());
848 if (bias.has_value() && m_Bias.has_value())
849 {
850 CompareConstTensor(bias.value(), m_Bias.value());
851 }
852 }
853
854 private:
855 void VerifyDescriptor(const armnn::FullyConnectedDescriptor& descriptor)
856 {
857 BOOST_TEST(descriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
858 BOOST_TEST(descriptor.m_TransposeWeightMatrix == m_Descriptor.m_TransposeWeightMatrix);
859 }
860
861 armnn::FullyConnectedDescriptor m_Descriptor;
862 armnn::ConstTensor m_Weight;
863 armnn::Optional<armnn::ConstTensor> m_Bias;
864 };
865
866 const std::string layerName("fullyConnected");
867 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
868 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
869
870 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
871 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
872 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
873 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
874 armnn::ConstTensor weights(weightsInfo, weightsData);
875 armnn::ConstTensor biases(biasesInfo, biasesData);
876
877 armnn::FullyConnectedDescriptor descriptor;
878 descriptor.m_BiasEnabled = true;
879 descriptor.m_TransposeWeightMatrix = false;
880
881 armnn::INetworkPtr network = armnn::INetwork::Create();
882 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
883 armnn::IConnectableLayer* const fullyConnectedLayer =
884 network->AddFullyConnectedLayer(descriptor, weights, biases, layerName.c_str());
885 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
886
887 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
888 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
889
890 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
891 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
892
893 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
894 BOOST_CHECK(deserializedNetwork);
895
896 FullyConnectedLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor, weights, biases);
897 deserializedNetwork->Accept(verifier);
898}
899
900BOOST_AUTO_TEST_CASE(SerializeGather)
901{
902 class GatherLayerVerifier : public LayerVerifierBase
903 {
904 public:
905 GatherLayerVerifier(const std::string& layerName,
906 const std::vector<armnn::TensorInfo>& inputInfos,
907 const std::vector<armnn::TensorInfo>& outputInfos)
908 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
909
910 void VisitGatherLayer(const armnn::IConnectableLayer* layer, const char *name) override
911 {
912 VerifyNameAndConnections(layer, name);
913 }
914
915 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
916 const armnn::ConstTensor& input,
917 const char *name) override {}
918 };
919
920 const std::string layerName("gather");
921 armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QuantisedAsymm8);
922 armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QuantisedAsymm8);
923 const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32);
924
925 paramsInfo.SetQuantizationScale(1.0f);
926 paramsInfo.SetQuantizationOffset(0);
927 outputInfo.SetQuantizationScale(1.0f);
928 outputInfo.SetQuantizationOffset(0);
929
930 const std::vector<int32_t>& indicesData = {7, 6, 5};
931
932 armnn::INetworkPtr network = armnn::INetwork::Create();
933 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
934 armnn::IConnectableLayer *const constantLayer =
935 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
936 armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(layerName.c_str());
937 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
938
939 inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
940 constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
941 gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
942
943 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
944 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
945 gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
946
947 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
948 BOOST_CHECK(deserializedNetwork);
949
950 GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo});
951 deserializedNetwork->Accept(verifier);
952}
953
954BOOST_AUTO_TEST_CASE(SerializeGreater)
955{
956 class GreaterLayerVerifier : public LayerVerifierBase
957 {
958 public:
959 GreaterLayerVerifier(const std::string& layerName,
960 const std::vector<armnn::TensorInfo>& inputInfos,
961 const std::vector<armnn::TensorInfo>& outputInfos)
962 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
963
964 void VisitGreaterLayer(const armnn::IConnectableLayer* layer, const char* name) override
965 {
966 VerifyNameAndConnections(layer, name);
967 }
968 };
969
970 const std::string layerName("greater");
971 const armnn::TensorInfo inputTensorInfo1({ 1, 2, 2, 2 }, armnn::DataType::Float32);
972 const armnn::TensorInfo inputTensorInfo2({ 1, 2, 2, 2 }, armnn::DataType::Float32);
973 const armnn::TensorInfo outputTensorInfo({ 1, 2, 2, 2 }, armnn::DataType::Boolean);
974
975 armnn::INetworkPtr network = armnn::INetwork::Create();
976 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
977 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
978 armnn::IConnectableLayer* const greaterLayer = network->AddGreaterLayer(layerName.c_str());
979 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
980
981 inputLayer1->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(0));
982 inputLayer2->GetOutputSlot(0).Connect(greaterLayer->GetInputSlot(1));
983 greaterLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
984
985 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
986 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
987 greaterLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
988
989 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
990 BOOST_CHECK(deserializedNetwork);
991
992 GreaterLayerVerifier verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
993 deserializedNetwork->Accept(verifier);
994}
995
996BOOST_AUTO_TEST_CASE(SerializeL2Normalization)
997{
998 class L2NormalizationLayerVerifier : public LayerVerifierBase
999 {
1000 public:
1001 L2NormalizationLayerVerifier(const std::string& layerName,
1002 const std::vector<armnn::TensorInfo>& inputInfos,
1003 const std::vector<armnn::TensorInfo>& outputInfos,
1004 const armnn::L2NormalizationDescriptor& descriptor)
1005 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1006 , m_Descriptor(descriptor) {}
1007
1008 void VisitL2NormalizationLayer(const armnn::IConnectableLayer* layer,
1009 const armnn::L2NormalizationDescriptor& descriptor,
1010 const char* name) override
1011 {
1012 VerifyNameAndConnections(layer, name);
1013 VerifyDescriptor(descriptor);
1014 }
1015 private:
1016 void VerifyDescriptor(const armnn::L2NormalizationDescriptor& descriptor)
1017 {
1018 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1019 }
1020
1021 armnn::L2NormalizationDescriptor m_Descriptor;
1022 };
1023
1024 const std::string l2NormLayerName("l2Normalization");
1025 const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1026
1027 armnn::L2NormalizationDescriptor desc;
1028 desc.m_DataLayout = armnn::DataLayout::NCHW;
1029
1030 armnn::INetworkPtr network = armnn::INetwork::Create();
1031 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1032 armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1033 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1034
1035 inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1036 l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1037
1038 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1039 l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1040
1041 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1042 BOOST_CHECK(deserializedNetwork);
1043
1044 L2NormalizationLayerVerifier verifier(l2NormLayerName, {info}, {info}, desc);
1045 deserializedNetwork->Accept(verifier);
1046}
1047
1048BOOST_AUTO_TEST_CASE(SerializeMaximum)
1049{
1050 class MaximumLayerVerifier : public LayerVerifierBase
1051 {
1052 public:
1053 MaximumLayerVerifier(const std::string& layerName,
1054 const std::vector<armnn::TensorInfo>& inputInfos,
1055 const std::vector<armnn::TensorInfo>& outputInfos)
1056 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1057
1058 void VisitMaximumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1059 {
1060 VerifyNameAndConnections(layer, name);
1061 }
1062 };
1063
1064 const std::string layerName("maximum");
1065 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1066
1067 armnn::INetworkPtr network = armnn::INetwork::Create();
1068 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1069 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1070 armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1071 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1072
1073 inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1074 inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1075 maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1076
1077 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1078 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1079 maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1080
1081 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1082 BOOST_CHECK(deserializedNetwork);
1083
1084 MaximumLayerVerifier verifier(layerName, {info, info}, {info});
1085 deserializedNetwork->Accept(verifier);
1086}
1087
1088BOOST_AUTO_TEST_CASE(SerializeMean)
1089{
1090 class MeanLayerVerifier : public LayerVerifierBase
1091 {
1092 public:
1093 MeanLayerVerifier(const std::string& layerName,
1094 const std::vector<armnn::TensorInfo>& inputInfos,
1095 const std::vector<armnn::TensorInfo>& outputInfos,
1096 const armnn::MeanDescriptor& descriptor)
1097 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1098 , m_Descriptor(descriptor) {}
1099
1100 void VisitMeanLayer(const armnn::IConnectableLayer* layer,
1101 const armnn::MeanDescriptor& descriptor,
1102 const char* name) override
1103 {
1104 VerifyNameAndConnections(layer, name);
1105 VerifyDescriptor(descriptor);
1106 }
1107
1108 private:
1109 void VerifyDescriptor(const armnn::MeanDescriptor& descriptor)
1110 {
1111 BOOST_TEST(descriptor.m_Axis == m_Descriptor.m_Axis);
1112 BOOST_TEST(descriptor.m_KeepDims == m_Descriptor.m_KeepDims);
1113 }
1114
1115 armnn::MeanDescriptor m_Descriptor;
1116 };
1117
1118 const std::string layerName("mean");
1119 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1120 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1121
1122 armnn::MeanDescriptor descriptor;
1123 descriptor.m_Axis = { 2 };
1124 descriptor.m_KeepDims = true;
1125
1126 armnn::INetworkPtr network = armnn::INetwork::Create();
1127 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1128 armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1129 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1130
1131 inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1132 meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1133
1134 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1135 meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1136
1137 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1138 BOOST_CHECK(deserializedNetwork);
1139
1140 MeanLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1141 deserializedNetwork->Accept(verifier);
1142}
1143
1144BOOST_AUTO_TEST_CASE(SerializeMerger)
1145{
1146 class MergerLayerVerifier : public LayerVerifierBase
1147 {
1148 public:
1149 MergerLayerVerifier(const std::string& layerName,
1150 const std::vector<armnn::TensorInfo>& inputInfos,
1151 const std::vector<armnn::TensorInfo>& outputInfos,
1152 const armnn::OriginsDescriptor& descriptor)
1153 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1154 , m_Descriptor(descriptor) {}
1155
1156 void VisitMergerLayer(const armnn::IConnectableLayer* layer,
1157 const armnn::OriginsDescriptor& descriptor,
1158 const char* name) override
1159 {
1160 VerifyNameAndConnections(layer, name);
1161 VerifyDescriptor(descriptor);
1162 }
1163
1164 private:
1165 void VerifyDescriptor(const armnn::OriginsDescriptor& descriptor)
1166 {
1167 BOOST_TEST(descriptor.GetConcatAxis() == m_Descriptor.GetConcatAxis());
1168 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
1169 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
1170
1171 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
1172 {
1173 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
1174 {
1175 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
1176 }
1177 }
1178 }
1179
1180 armnn::OriginsDescriptor m_Descriptor;
1181 };
1182
1183 const std::string layerName("merger");
1184 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1185 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1186
1187 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1188
1189 armnn::OriginsDescriptor descriptor =
1190 armnn::CreateMergerDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1191
1192 armnn::INetworkPtr network = armnn::INetwork::Create();
1193 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1194 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1195 armnn::IConnectableLayer* const mergerLayer = network->AddMergerLayer(descriptor, layerName.c_str());
1196 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1197
1198 inputLayerOne->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(0));
1199 inputLayerTwo->GetOutputSlot(0).Connect(mergerLayer->GetInputSlot(1));
1200 mergerLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1201
1202 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1203 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1204 mergerLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1205
1206 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1207 BOOST_CHECK(deserializedNetwork);
1208
1209 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1210 deserializedNetwork->Accept(verifier);
1211}
1212
1213BOOST_AUTO_TEST_CASE(SerializeMinimum)
1214{
1215 class MinimumLayerVerifier : public LayerVerifierBase
1216 {
1217 public:
1218 MinimumLayerVerifier(const std::string& layerName,
1219 const std::vector<armnn::TensorInfo>& inputInfos,
1220 const std::vector<armnn::TensorInfo>& outputInfos)
1221 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1222
1223 void VisitMinimumLayer(const armnn::IConnectableLayer* layer, const char* name) override
1224 {
1225 VerifyNameAndConnections(layer, name);
1226 }
1227 };
1228
1229 const std::string layerName("minimum");
1230 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1231
1232 armnn::INetworkPtr network = armnn::INetwork::Create();
1233 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1234 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1235 armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1236 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1237
1238 inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1239 inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1240 minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1241
1242 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1243 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1244 minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
1245
1246 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1247 BOOST_CHECK(deserializedNetwork);
1248
1249 MinimumLayerVerifier verifier(layerName, {info, info}, {info});
1250 deserializedNetwork->Accept(verifier);
1251}
1252
1253BOOST_AUTO_TEST_CASE(SerializeMultiplication)
1254{
1255 class MultiplicationLayerVerifier : public LayerVerifierBase
1256 {
1257 public:
1258 MultiplicationLayerVerifier(const std::string& layerName,
1259 const std::vector<armnn::TensorInfo>& inputInfos,
1260 const std::vector<armnn::TensorInfo>& outputInfos)
1261 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1262
1263 void VisitMultiplicationLayer(const armnn::IConnectableLayer* layer, const char* name) override
1264 {
1265 VerifyNameAndConnections(layer, name);
1266 }
1267 };
1268
1269 const std::string layerName("multiplication");
1270 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1271
1272 armnn::INetworkPtr network = armnn::INetwork::Create();
1273 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1274 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1275 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
1276 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1277
1278 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
1279 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
1280 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1281
1282 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1283 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1284 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
1285
1286 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1287 BOOST_CHECK(deserializedNetwork);
1288
1289 MultiplicationLayerVerifier verifier(layerName, {info, info}, {info});
1290 deserializedNetwork->Accept(verifier);
1291}
1292
1293BOOST_AUTO_TEST_CASE(SerializeNormalization)
1294{
1295 class NormalizationLayerVerifier : public LayerVerifierBase
1296 {
1297 public:
1298 NormalizationLayerVerifier(const std::string& layerName,
1299 const std::vector<armnn::TensorInfo>& inputInfos,
1300 const std::vector<armnn::TensorInfo>& outputInfos,
1301 const armnn::NormalizationDescriptor& descriptor)
1302 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1303 , m_Descriptor(descriptor) {}
1304
1305 void VisitNormalizationLayer(const armnn::IConnectableLayer* layer,
1306 const armnn::NormalizationDescriptor& descriptor,
1307 const char* name) override
1308 {
1309 VerifyNameAndConnections(layer, name);
1310 VerifyDescriptor(descriptor);
1311 }
1312
1313 private:
1314 void VerifyDescriptor(const armnn::NormalizationDescriptor& descriptor)
1315 {
1316 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1317 BOOST_TEST(descriptor.m_NormSize == m_Descriptor.m_NormSize);
1318 BOOST_TEST(descriptor.m_Alpha == m_Descriptor.m_Alpha);
1319 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
1320 BOOST_TEST(descriptor.m_K == m_Descriptor.m_K);
1321 BOOST_TEST(
1322 static_cast<int>(descriptor.m_NormChannelType) == static_cast<int>(m_Descriptor.m_NormChannelType));
1323 BOOST_TEST(
1324 static_cast<int>(descriptor.m_NormMethodType) == static_cast<int>(m_Descriptor.m_NormMethodType));
1325 }
1326
1327 armnn::NormalizationDescriptor m_Descriptor;
1328 };
1329
1330 const std::string layerName("normalization");
1331 const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
1332
1333 armnn::NormalizationDescriptor desc;
1334 desc.m_DataLayout = armnn::DataLayout::NCHW;
1335 desc.m_NormSize = 3;
1336 desc.m_Alpha = 1;
1337 desc.m_Beta = 1;
1338 desc.m_K = 1;
1339
1340 armnn::INetworkPtr network = armnn::INetwork::Create();
1341 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1342 armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
1343 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1344
1345 inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
1346 normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1347
1348 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1349 normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
1350
1351 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1352 BOOST_CHECK(deserializedNetwork);
1353
1354 NormalizationLayerVerifier verifier(layerName, {info}, {info}, desc);
1355 deserializedNetwork->Accept(verifier);
1356}
1357
1358BOOST_AUTO_TEST_CASE(SerializePad)
1359{
1360 class PadLayerVerifier : public LayerVerifierBase
1361 {
1362 public:
1363 PadLayerVerifier(const std::string& layerName,
1364 const std::vector<armnn::TensorInfo>& inputInfos,
1365 const std::vector<armnn::TensorInfo>& outputInfos,
1366 const armnn::PadDescriptor& descriptor)
1367 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1368 , m_Descriptor(descriptor) {}
1369
1370 void VisitPadLayer(const armnn::IConnectableLayer* layer,
1371 const armnn::PadDescriptor& descriptor,
1372 const char* name) override
1373 {
1374 VerifyNameAndConnections(layer, name);
1375 VerifyDescriptor(descriptor);
1376 }
1377
1378 private:
1379 void VerifyDescriptor(const armnn::PadDescriptor& descriptor)
1380 {
1381 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
1382 }
1383
1384 armnn::PadDescriptor m_Descriptor;
1385 };
1386
1387 const std::string layerName("pad");
1388 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1389 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1390
1391 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1392
1393 armnn::INetworkPtr network = armnn::INetwork::Create();
1394 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1395 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
1396 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1397
1398 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
1399 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1400
1401 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1402 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1403
1404 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1405 BOOST_CHECK(deserializedNetwork);
1406
1407 PadLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, desc);
1408 deserializedNetwork->Accept(verifier);
1409}
1410
1411BOOST_AUTO_TEST_CASE(SerializePermute)
1412{
1413 class PermuteLayerVerifier : public LayerVerifierBase
1414 {
1415 public:
1416 PermuteLayerVerifier(const std::string& layerName,
1417 const std::vector<armnn::TensorInfo>& inputInfos,
1418 const std::vector<armnn::TensorInfo>& outputInfos,
1419 const armnn::PermuteDescriptor& descriptor)
1420 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1421 , m_Descriptor(descriptor) {}
1422
1423 void VisitPermuteLayer(const armnn::IConnectableLayer* layer,
1424 const armnn::PermuteDescriptor& descriptor,
1425 const char* name) override
1426 {
1427 VerifyNameAndConnections(layer, name);
1428 VerifyDescriptor(descriptor);
1429 }
1430
1431 private:
1432 void VerifyDescriptor(const armnn::PermuteDescriptor& descriptor)
1433 {
1434 BOOST_TEST(descriptor.m_DimMappings.IsEqual(m_Descriptor.m_DimMappings));
1435 }
1436
1437 armnn::PermuteDescriptor m_Descriptor;
1438 };
1439
1440 const std::string layerName("permute");
1441 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
1442 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1443
1444 armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
1445
1446 armnn::INetworkPtr network = armnn::INetwork::Create();
1447 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1448 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
1449 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1450
1451 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
1452 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1453
1454 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1455 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1456
1457 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1458 BOOST_CHECK(deserializedNetwork);
1459
1460 PermuteLayerVerifier verifier(layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
1461 deserializedNetwork->Accept(verifier);
1462}
1463
1464BOOST_AUTO_TEST_CASE(SerializePooling2d)
1465{
1466 class Pooling2dLayerVerifier : public LayerVerifierBase
1467 {
1468 public:
1469 Pooling2dLayerVerifier(const std::string& layerName,
1470 const std::vector<armnn::TensorInfo>& inputInfos,
1471 const std::vector<armnn::TensorInfo>& outputInfos,
1472 const armnn::Pooling2dDescriptor& descriptor)
1473 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1474 , m_Descriptor(descriptor) {}
1475
1476 void VisitPooling2dLayer(const armnn::IConnectableLayer* layer,
1477 const armnn::Pooling2dDescriptor& descriptor,
1478 const char* name) override
1479 {
1480 VerifyNameAndConnections(layer, name);
1481 VerifyDescriptor(descriptor);
1482 }
1483
1484 private:
1485 void VerifyDescriptor(const armnn::Pooling2dDescriptor& descriptor)
1486 {
1487 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1488 BOOST_TEST(descriptor.m_PadLeft == m_Descriptor.m_PadLeft);
1489 BOOST_TEST(descriptor.m_PadRight == m_Descriptor.m_PadRight);
1490 BOOST_TEST(descriptor.m_PadTop == m_Descriptor.m_PadTop);
1491 BOOST_TEST(descriptor.m_PadBottom == m_Descriptor.m_PadBottom);
1492 BOOST_TEST(descriptor.m_PoolWidth == m_Descriptor.m_PoolWidth);
1493 BOOST_TEST(descriptor.m_PoolHeight == m_Descriptor.m_PoolHeight);
1494 BOOST_TEST(descriptor.m_StrideX == m_Descriptor.m_StrideX);
1495 BOOST_TEST(descriptor.m_StrideY == m_Descriptor.m_StrideY);
1496
1497 BOOST_TEST(
1498 static_cast<int>(descriptor.m_PaddingMethod) == static_cast<int>(m_Descriptor.m_PaddingMethod));
1499 BOOST_TEST(
1500 static_cast<int>(descriptor.m_PoolType) == static_cast<int>(m_Descriptor.m_PoolType));
1501 BOOST_TEST(
1502 static_cast<int>(descriptor.m_OutputShapeRounding) ==
1503 static_cast<int>(m_Descriptor.m_OutputShapeRounding));
1504 }
1505
1506 armnn::Pooling2dDescriptor m_Descriptor;
1507 };
1508
1509 const std::string layerName("pooling2d");
1510 const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
1511 const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
1512
1513 armnn::Pooling2dDescriptor desc;
1514 desc.m_DataLayout = armnn::DataLayout::NHWC;
1515 desc.m_PadTop = 0;
1516 desc.m_PadBottom = 0;
1517 desc.m_PadLeft = 0;
1518 desc.m_PadRight = 0;
1519 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
1520 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1521 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1522 desc.m_PoolHeight = 2;
1523 desc.m_PoolWidth = 2;
1524 desc.m_StrideX = 2;
1525 desc.m_StrideY = 2;
1526
1527 armnn::INetworkPtr network = armnn::INetwork::Create();
1528 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1529 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
1530 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1531
1532 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
1533 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1534
1535 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1536 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1537
1538 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1539 BOOST_CHECK(deserializedNetwork);
1540
1541 Pooling2dLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1542 deserializedNetwork->Accept(verifier);
1543}
1544
1545BOOST_AUTO_TEST_CASE(SerializeReshape)
1546{
1547 class ReshapeLayerVerifier : public LayerVerifierBase
1548 {
1549 public:
1550 ReshapeLayerVerifier(const std::string& layerName,
1551 const std::vector<armnn::TensorInfo>& inputInfos,
1552 const std::vector<armnn::TensorInfo>& outputInfos,
1553 const armnn::ReshapeDescriptor& descriptor)
1554 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1555 , m_Descriptor(descriptor) {}
1556
1557 void VisitReshapeLayer(const armnn::IConnectableLayer* layer,
1558 const armnn::ReshapeDescriptor& descriptor,
1559 const char* name) override
1560 {
1561 VerifyNameAndConnections(layer, name);
1562 VerifyDescriptor(descriptor);
1563 }
1564
1565 private:
1566 void VerifyDescriptor(const armnn::ReshapeDescriptor& descriptor)
1567 {
1568 BOOST_TEST(descriptor.m_TargetShape == m_Descriptor.m_TargetShape);
1569 }
1570
1571 armnn::ReshapeDescriptor m_Descriptor;
1572 };
1573
1574 const std::string layerName("reshape");
1575 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
1576 const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
1577
1578 armnn::ReshapeDescriptor descriptor({3, 3});
1579
1580 armnn::INetworkPtr network = armnn::INetwork::Create();
1581 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1582 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
1583 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1584
1585 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
1586 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1587
1588 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1589 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1590
1591 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1592 BOOST_CHECK(deserializedNetwork);
1593
1594 ReshapeLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1595 deserializedNetwork->Accept(verifier);
1596}
1597
1598BOOST_AUTO_TEST_CASE(SerializeResizeBilinear)
1599{
1600 class ResizeBilinearLayerVerifier : public LayerVerifierBase
1601 {
1602 public:
1603 ResizeBilinearLayerVerifier(const std::string& layerName,
1604 const std::vector<armnn::TensorInfo>& inputInfos,
1605 const std::vector<armnn::TensorInfo>& outputInfos,
1606 const armnn::ResizeBilinearDescriptor& descriptor)
1607 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1608 , m_Descriptor(descriptor) {}
1609
1610 void VisitResizeBilinearLayer(const armnn::IConnectableLayer* layer,
1611 const armnn::ResizeBilinearDescriptor& descriptor,
1612 const char* name) override
1613 {
1614 VerifyNameAndConnections(layer, name);
1615 VerifyDescriptor(descriptor);
1616 }
1617
1618 private:
1619 void VerifyDescriptor(const armnn::ResizeBilinearDescriptor& descriptor)
1620 {
1621 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1622 BOOST_TEST(descriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
1623 BOOST_TEST(descriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
1624 }
1625
1626 armnn::ResizeBilinearDescriptor m_Descriptor;
1627 };
1628
1629 const std::string layerName("resizeBilinear");
1630 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
1631 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
1632
1633 armnn::ResizeBilinearDescriptor desc;
1634 desc.m_TargetWidth = 4;
1635 desc.m_TargetHeight = 2;
1636
1637 armnn::INetworkPtr network = armnn::INetwork::Create();
1638 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1639 armnn::IConnectableLayer* const resizeLayer = network->AddResizeBilinearLayer(desc, layerName.c_str());
1640 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1641
1642 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
1643 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1644
1645 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1646 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1647
1648 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1649 BOOST_CHECK(deserializedNetwork);
1650
1651 ResizeBilinearLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1652 deserializedNetwork->Accept(verifier);
1653}
1654
1655BOOST_AUTO_TEST_CASE(SerializeRsqrt)
1656{
1657 class RsqrtLayerVerifier : public LayerVerifierBase
1658 {
1659 public:
1660 RsqrtLayerVerifier(const std::string& layerName,
1661 const std::vector<armnn::TensorInfo>& inputInfos,
1662 const std::vector<armnn::TensorInfo>& outputInfos)
1663 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1664
1665 void VisitRsqrtLayer(const armnn::IConnectableLayer* layer, const char* name) override
1666 {
1667 VerifyNameAndConnections(layer, name);
1668 }
1669 };
1670
1671 const std::string layerName("rsqrt");
1672 const armnn::TensorInfo tensorInfo({ 3, 1, 2 }, armnn::DataType::Float32);
1673
1674 armnn::INetworkPtr network = armnn::INetwork::Create();
1675 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1676 armnn::IConnectableLayer* const rsqrtLayer = network->AddRsqrtLayer(layerName.c_str());
1677 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1678
1679 inputLayer->GetOutputSlot(0).Connect(rsqrtLayer->GetInputSlot(0));
1680 rsqrtLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1681
1682 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1683 rsqrtLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1684
1685 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1686 BOOST_CHECK(deserializedNetwork);
1687
1688 RsqrtLayerVerifier verifier(layerName, {tensorInfo}, {tensorInfo});
1689 deserializedNetwork->Accept(verifier);
1690}
1691
1692BOOST_AUTO_TEST_CASE(SerializeSoftmax)
1693{
1694 class SoftmaxLayerVerifier : public LayerVerifierBase
1695 {
1696 public:
1697 SoftmaxLayerVerifier(const std::string& layerName,
1698 const std::vector<armnn::TensorInfo>& inputInfos,
1699 const std::vector<armnn::TensorInfo>& outputInfos,
1700 const armnn::SoftmaxDescriptor& descriptor)
1701 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1702 , m_Descriptor(descriptor) {}
1703
1704 void VisitSoftmaxLayer(const armnn::IConnectableLayer* layer,
1705 const armnn::SoftmaxDescriptor& descriptor,
1706 const char* name) override
1707 {
1708 VerifyNameAndConnections(layer, name);
1709 VerifyDescriptor(descriptor);
1710 }
1711
1712 private:
1713 void VerifyDescriptor(const armnn::SoftmaxDescriptor& descriptor)
1714 {
1715 BOOST_TEST(descriptor.m_Beta == m_Descriptor.m_Beta);
1716 }
1717
1718 armnn::SoftmaxDescriptor m_Descriptor;
1719 };
1720
1721 const std::string layerName("softmax");
1722 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
1723
1724 armnn::SoftmaxDescriptor descriptor;
1725 descriptor.m_Beta = 1.0f;
1726
1727 armnn::INetworkPtr network = armnn::INetwork::Create();
1728 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1729 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
1730 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1731
1732 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
1733 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1734
1735 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1736 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
1737
1738 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1739 BOOST_CHECK(deserializedNetwork);
1740
1741 SoftmaxLayerVerifier verifier(layerName, {info}, {info}, descriptor);
1742 deserializedNetwork->Accept(verifier);
1743}
1744
1745BOOST_AUTO_TEST_CASE(SerializeSpaceToBatchNd)
1746{
1747 class SpaceToBatchNdLayerVerifier : public LayerVerifierBase
1748 {
1749 public:
1750 SpaceToBatchNdLayerVerifier(const std::string& layerName,
1751 const std::vector<armnn::TensorInfo>& inputInfos,
1752 const std::vector<armnn::TensorInfo>& outputInfos,
1753 const armnn::SpaceToBatchNdDescriptor& descriptor)
1754 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1755 , m_Descriptor(descriptor) {}
1756
1757 void VisitSpaceToBatchNdLayer(const armnn::IConnectableLayer* layer,
1758 const armnn::SpaceToBatchNdDescriptor& descriptor,
1759 const char* name) override
1760 {
1761 VerifyNameAndConnections(layer, name);
1762 VerifyDescriptor(descriptor);
1763 }
1764
1765 private:
1766 void VerifyDescriptor(const armnn::SpaceToBatchNdDescriptor& descriptor)
1767 {
1768 BOOST_TEST(descriptor.m_PadList == m_Descriptor.m_PadList);
1769 BOOST_TEST(descriptor.m_BlockShape == m_Descriptor.m_BlockShape);
1770 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1771 }
1772
1773 armnn::SpaceToBatchNdDescriptor m_Descriptor;
1774 };
1775
1776 const std::string layerName("spaceToBatchNd");
1777 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
1778 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
1779
1780 armnn::SpaceToBatchNdDescriptor desc;
1781 desc.m_DataLayout = armnn::DataLayout::NCHW;
1782 desc.m_BlockShape = {2, 2};
1783 desc.m_PadList = {{0, 0}, {2, 0}};
1784
1785 armnn::INetworkPtr network = armnn::INetwork::Create();
1786 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1787 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
1788 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1789
1790 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
1791 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1792
1793 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1794 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1795
1796 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1797 BOOST_CHECK(deserializedNetwork);
1798
1799 SpaceToBatchNdLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1800 deserializedNetwork->Accept(verifier);
1801}
1802
1803BOOST_AUTO_TEST_CASE(SerializeSplitter)
1804{
1805 class SplitterLayerVerifier : public LayerVerifierBase
1806 {
1807 public:
1808 SplitterLayerVerifier(const std::string& layerName,
1809 const std::vector<armnn::TensorInfo>& inputInfos,
1810 const std::vector<armnn::TensorInfo>& outputInfos,
1811 const armnn::ViewsDescriptor& descriptor)
1812 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1813 , m_Descriptor(descriptor) {}
1814
1815 void VisitSplitterLayer(const armnn::IConnectableLayer* layer,
1816 const armnn::ViewsDescriptor& descriptor,
1817 const char* name) override
1818 {
1819 VerifyNameAndConnections(layer, name);
1820 VerifyDescriptor(descriptor);
1821 }
1822
1823 private:
1824 void VerifyDescriptor(const armnn::ViewsDescriptor& descriptor)
1825 {
1826 BOOST_TEST(descriptor.GetNumViews() == m_Descriptor.GetNumViews());
1827 BOOST_TEST(descriptor.GetNumDimensions() == m_Descriptor.GetNumDimensions());
1828
1829 for (uint32_t i = 0; i < descriptor.GetNumViews(); i++)
1830 {
1831 for (uint32_t j = 0; j < descriptor.GetNumDimensions(); j++)
1832 {
1833 BOOST_TEST(descriptor.GetViewOrigin(i)[j] == m_Descriptor.GetViewOrigin(i)[j]);
1834 BOOST_TEST(descriptor.GetViewSizes(i)[j] == m_Descriptor.GetViewSizes(i)[j]);
1835 }
1836 }
1837 }
1838
1839 armnn::ViewsDescriptor m_Descriptor;
1840 };
1841
1842 const unsigned int numViews = 3;
1843 const unsigned int numDimensions = 4;
1844 const unsigned int inputShape[] = {1, 18, 4, 4};
1845 const unsigned int outputShape[] = {1, 6, 4, 4};
1846
1847 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
1848 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
1849 static_cast<unsigned int>(inputShape[1]),
1850 static_cast<unsigned int>(inputShape[2]),
1851 static_cast<unsigned int>(inputShape[3])};
1852 splitterDimSizes[1] /= numViews;
1853 armnn::ViewsDescriptor desc(numViews, numDimensions);
1854
1855 for (unsigned int g = 0; g < numViews; ++g)
1856 {
1857 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
1858
1859 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
1860 {
1861 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
1862 }
1863 }
1864
1865 const std::string layerName("splitter");
1866 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
1867 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
1868
1869 armnn::INetworkPtr network = armnn::INetwork::Create();
1870 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1871 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
1872 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
1873 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
1874 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
1875
1876 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
1877 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
1878 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
1879 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
1880
1881 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1882 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1883 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
1884 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
1885
1886 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1887 BOOST_CHECK(deserializedNetwork);
1888
1889 SplitterLayerVerifier verifier(layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
1890 deserializedNetwork->Accept(verifier);
1891}
1892
1893BOOST_AUTO_TEST_CASE(SerializeStridedSlice)
1894{
1895 class StridedSliceLayerVerifier : public LayerVerifierBase
1896 {
1897 public:
1898 StridedSliceLayerVerifier(const std::string& layerName,
1899 const std::vector<armnn::TensorInfo>& inputInfos,
1900 const std::vector<armnn::TensorInfo>& outputInfos,
1901 const armnn::StridedSliceDescriptor& descriptor)
1902 : LayerVerifierBase(layerName, inputInfos, outputInfos)
1903 , m_Descriptor(descriptor) {}
1904
1905 void VisitStridedSliceLayer(const armnn::IConnectableLayer* layer,
1906 const armnn::StridedSliceDescriptor& descriptor,
1907 const char* name) override
1908 {
1909 VerifyNameAndConnections(layer, name);
1910 VerifyDescriptor(descriptor);
1911 }
1912
1913 private:
1914 void VerifyDescriptor(const armnn::StridedSliceDescriptor& descriptor)
1915 {
1916 BOOST_TEST(descriptor.m_Begin == m_Descriptor.m_Begin);
1917 BOOST_TEST(descriptor.m_End == m_Descriptor.m_End);
1918 BOOST_TEST(descriptor.m_Stride == m_Descriptor.m_Stride);
1919 BOOST_TEST(descriptor.m_BeginMask == m_Descriptor.m_BeginMask);
1920 BOOST_TEST(descriptor.m_EndMask == m_Descriptor.m_EndMask);
1921 BOOST_TEST(descriptor.m_ShrinkAxisMask == m_Descriptor.m_ShrinkAxisMask);
1922 BOOST_TEST(descriptor.m_EllipsisMask == m_Descriptor.m_EllipsisMask);
1923 BOOST_TEST(descriptor.m_NewAxisMask == m_Descriptor.m_NewAxisMask);
1924 BOOST_TEST(GetDataLayoutName(descriptor.m_DataLayout) == GetDataLayoutName(m_Descriptor.m_DataLayout));
1925 }
1926 armnn::StridedSliceDescriptor m_Descriptor;
1927 };
1928
1929 const std::string layerName("stridedSlice");
1930 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
1931 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
1932
1933 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
1934 desc.m_EndMask = (1 << 4) - 1;
1935 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
1936 desc.m_DataLayout = armnn::DataLayout::NCHW;
1937
1938 armnn::INetworkPtr network = armnn::INetwork::Create();
1939 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1940 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
1941 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1942
1943 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
1944 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1945
1946 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1947 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1948
1949 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1950 BOOST_CHECK(deserializedNetwork);
1951
1952 StridedSliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
1953 deserializedNetwork->Accept(verifier);
1954}
1955
1956BOOST_AUTO_TEST_CASE(SerializeSubtraction)
1957{
1958 class SubtractionLayerVerifier : public LayerVerifierBase
1959 {
1960 public:
1961 SubtractionLayerVerifier(const std::string& layerName,
1962 const std::vector<armnn::TensorInfo>& inputInfos,
1963 const std::vector<armnn::TensorInfo>& outputInfos)
1964 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1965
1966 void VisitSubtractionLayer(const armnn::IConnectableLayer* layer, const char* name) override
1967 {
1968 VerifyNameAndConnections(layer, name);
1969 }
1970 };
1971
1972 const std::string layerName("subtraction");
1973 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
1974
1975 armnn::INetworkPtr network = armnn::INetwork::Create();
1976 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1977 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1978 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
1979 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1980
1981 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
1982 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
1983 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1984
1985 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1986 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1987 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
1988
1989 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1990 BOOST_CHECK(deserializedNetwork);
1991
1992 SubtractionLayerVerifier verifier(layerName, {info, info}, {info});
1993 deserializedNetwork->Accept(verifier);
Nattapat Chaimanowong3e14a9d2019-03-18 12:37:06 +00001994}
1995
Sadik Armagandb059fd2019-03-20 12:28:32 +00001996BOOST_AUTO_TEST_CASE(SerializeDeserializeNonLinearNetwork)
1997{
1998 class ConstantLayerVerifier : public LayerVerifierBase
1999 {
2000 public:
2001 ConstantLayerVerifier(const std::string& layerName,
2002 const std::vector<armnn::TensorInfo>& inputInfos,
2003 const std::vector<armnn::TensorInfo>& outputInfos,
2004 const armnn::ConstTensor& layerInput)
2005 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2006 , m_LayerInput(layerInput) {}
2007
2008 void VisitConstantLayer(const armnn::IConnectableLayer* layer,
2009 const armnn::ConstTensor& input,
2010 const char* name) override
2011 {
2012 VerifyNameAndConnections(layer, name);
2013
2014 CompareConstTensor(input, m_LayerInput);
2015 }
2016
2017 void VisitAdditionLayer(const armnn::IConnectableLayer* layer, const char* name = nullptr) override {}
2018
2019 private:
2020 armnn::ConstTensor m_LayerInput;
2021 };
2022
2023 const std::string layerName("constant");
2024 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32);
2025
2026 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2027 armnn::ConstTensor constTensor(info, constantData);
2028
2029 armnn::INetworkPtr network(armnn::INetwork::Create());
2030 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2031 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2032 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2033 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2034
2035 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2036 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2037 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2038
2039 input->GetOutputSlot(0).SetTensorInfo(info);
2040 constant->GetOutputSlot(0).SetTensorInfo(info);
2041 add->GetOutputSlot(0).SetTensorInfo(info);
2042
2043 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2044 BOOST_CHECK(deserializedNetwork);
2045
2046 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
2047 deserializedNetwork->Accept(verifier);
2048}
2049
Jim Flynn11af3752019-03-19 17:22:29 +00002050class VerifyLstmLayer : public LayerVerifierBase
2051{
2052public:
2053 VerifyLstmLayer(const std::string& layerName,
2054 const std::vector<armnn::TensorInfo>& inputInfos,
2055 const std::vector<armnn::TensorInfo>& outputInfos,
2056 const armnn::LstmDescriptor& descriptor,
2057 const armnn::LstmInputParams& inputParams) :
2058 LayerVerifierBase(layerName, inputInfos, outputInfos), m_Descriptor(descriptor), m_InputParams(inputParams)
2059 {
2060 }
2061 void VisitLstmLayer(const armnn::IConnectableLayer* layer,
2062 const armnn::LstmDescriptor& descriptor,
2063 const armnn::LstmInputParams& params,
2064 const char* name)
2065 {
2066 VerifyNameAndConnections(layer, name);
2067 VerifyDescriptor(descriptor);
2068 VerifyInputParameters(params);
2069 }
2070protected:
2071 void VerifyDescriptor(const armnn::LstmDescriptor& descriptor)
2072 {
2073 BOOST_TEST(m_Descriptor.m_ActivationFunc == descriptor.m_ActivationFunc);
2074 BOOST_TEST(m_Descriptor.m_ClippingThresCell == descriptor.m_ClippingThresCell);
2075 BOOST_TEST(m_Descriptor.m_ClippingThresProj == descriptor.m_ClippingThresProj);
2076 BOOST_TEST(m_Descriptor.m_CifgEnabled == descriptor.m_CifgEnabled);
2077 BOOST_TEST(m_Descriptor.m_PeepholeEnabled = descriptor.m_PeepholeEnabled);
2078 BOOST_TEST(m_Descriptor.m_ProjectionEnabled == descriptor.m_ProjectionEnabled);
2079 }
2080 void VerifyInputParameters(const armnn::LstmInputParams& params)
2081 {
2082 VerifyConstTensors(
2083 "m_InputToInputWeights", m_InputParams.m_InputToInputWeights, params.m_InputToInputWeights);
2084 VerifyConstTensors(
2085 "m_InputToForgetWeights", m_InputParams.m_InputToForgetWeights, params.m_InputToForgetWeights);
2086 VerifyConstTensors(
2087 "m_InputToCellWeights", m_InputParams.m_InputToCellWeights, params.m_InputToCellWeights);
2088 VerifyConstTensors(
2089 "m_InputToOutputWeights", m_InputParams.m_InputToOutputWeights, params.m_InputToOutputWeights);
2090 VerifyConstTensors(
2091 "m_RecurrentToInputWeights", m_InputParams.m_RecurrentToInputWeights, params.m_RecurrentToInputWeights);
2092 VerifyConstTensors(
2093 "m_RecurrentToForgetWeights", m_InputParams.m_RecurrentToForgetWeights, params.m_RecurrentToForgetWeights);
2094 VerifyConstTensors(
2095 "m_RecurrentToCellWeights", m_InputParams.m_RecurrentToCellWeights, params.m_RecurrentToCellWeights);
2096 VerifyConstTensors(
2097 "m_RecurrentToOutputWeights", m_InputParams.m_RecurrentToOutputWeights, params.m_RecurrentToOutputWeights);
2098 VerifyConstTensors(
2099 "m_CellToInputWeights", m_InputParams.m_CellToInputWeights, params.m_CellToInputWeights);
2100 VerifyConstTensors(
2101 "m_CellToForgetWeights", m_InputParams.m_CellToForgetWeights, params.m_CellToForgetWeights);
2102 VerifyConstTensors(
2103 "m_CellToOutputWeights", m_InputParams.m_CellToOutputWeights, params.m_CellToOutputWeights);
2104 VerifyConstTensors(
2105 "m_InputGateBias", m_InputParams.m_InputGateBias, params.m_InputGateBias);
2106 VerifyConstTensors(
2107 "m_ForgetGateBias", m_InputParams.m_ForgetGateBias, params.m_ForgetGateBias);
2108 VerifyConstTensors(
2109 "m_CellBias", m_InputParams.m_CellBias, params.m_CellBias);
2110 VerifyConstTensors(
2111 "m_OutputGateBias", m_InputParams.m_OutputGateBias, params.m_OutputGateBias);
2112 VerifyConstTensors(
2113 "m_ProjectionWeights", m_InputParams.m_ProjectionWeights, params.m_ProjectionWeights);
2114 VerifyConstTensors(
2115 "m_ProjectionBias", m_InputParams.m_ProjectionBias, params.m_ProjectionBias);
2116 }
2117 void VerifyConstTensors(const std::string& tensorName,
2118 const armnn::ConstTensor* expectedPtr,
2119 const armnn::ConstTensor* actualPtr)
2120 {
2121 if (expectedPtr == nullptr)
2122 {
2123 BOOST_CHECK_MESSAGE(actualPtr == nullptr, tensorName + " should not exist");
2124 }
2125 else
2126 {
2127 BOOST_CHECK_MESSAGE(actualPtr != nullptr, tensorName + " should have been set");
2128 if (actualPtr != nullptr)
2129 {
2130 const armnn::TensorInfo& expectedInfo = expectedPtr->GetInfo();
2131 const armnn::TensorInfo& actualInfo = actualPtr->GetInfo();
2132
2133 BOOST_CHECK_MESSAGE(expectedInfo.GetShape() == actualInfo.GetShape(),
2134 tensorName + " shapes don't match");
2135 BOOST_CHECK_MESSAGE(
2136 GetDataTypeName(expectedInfo.GetDataType()) == GetDataTypeName(actualInfo.GetDataType()),
2137 tensorName + " data types don't match");
2138
2139 BOOST_CHECK_MESSAGE(expectedPtr->GetNumBytes() == actualPtr->GetNumBytes(),
2140 tensorName + " (GetNumBytes) data sizes do not match");
2141 if (expectedPtr->GetNumBytes() == actualPtr->GetNumBytes())
2142 {
2143 //check the data is identical
2144 const char* expectedData = static_cast<const char*>(expectedPtr->GetMemoryArea());
2145 const char* actualData = static_cast<const char*>(actualPtr->GetMemoryArea());
2146 bool same = true;
2147 for (unsigned int i = 0; i < expectedPtr->GetNumBytes(); ++i)
2148 {
2149 same = expectedData[i] == actualData[i];
2150 if (!same)
2151 {
2152 break;
2153 }
2154 }
2155 BOOST_CHECK_MESSAGE(same, tensorName + " data does not match");
2156 }
2157 }
2158 }
2159 }
2160private:
2161 armnn::LstmDescriptor m_Descriptor;
2162 armnn::LstmInputParams m_InputParams;
2163};
2164
2165BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmCifgPeepholeNoProjection)
2166{
2167 armnn::LstmDescriptor descriptor;
2168 descriptor.m_ActivationFunc = 4;
2169 descriptor.m_ClippingThresProj = 0.0f;
2170 descriptor.m_ClippingThresCell = 0.0f;
2171 descriptor.m_CifgEnabled = true; // if this is true then we DON'T need to set the OptCifgParams
2172 descriptor.m_ProjectionEnabled = false;
2173 descriptor.m_PeepholeEnabled = true;
2174
2175 const uint32_t batchSize = 1;
2176 const uint32_t inputSize = 2;
2177 const uint32_t numUnits = 4;
2178 const uint32_t outputSize = numUnits;
2179
2180 armnn::TensorInfo inputWeightsInfo1({numUnits, inputSize}, armnn::DataType::Float32);
2181 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2182 armnn::ConstTensor inputToForgetWeights(inputWeightsInfo1, inputToForgetWeightsData);
2183
2184 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2185 armnn::ConstTensor inputToCellWeights(inputWeightsInfo1, inputToCellWeightsData);
2186
2187 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo1.GetNumElements());
2188 armnn::ConstTensor inputToOutputWeights(inputWeightsInfo1, inputToOutputWeightsData);
2189
2190 armnn::TensorInfo inputWeightsInfo2({numUnits, outputSize}, armnn::DataType::Float32);
2191 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2192 armnn::ConstTensor recurrentToForgetWeights(inputWeightsInfo2, recurrentToForgetWeightsData);
2193
2194 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2195 armnn::ConstTensor recurrentToCellWeights(inputWeightsInfo2, recurrentToCellWeightsData);
2196
2197 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo2.GetNumElements());
2198 armnn::ConstTensor recurrentToOutputWeights(inputWeightsInfo2, recurrentToOutputWeightsData);
2199
2200 armnn::TensorInfo inputWeightsInfo3({numUnits}, armnn::DataType::Float32);
2201 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2202 armnn::ConstTensor cellToForgetWeights(inputWeightsInfo3, cellToForgetWeightsData);
2203
2204 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(inputWeightsInfo3.GetNumElements());
2205 armnn::ConstTensor cellToOutputWeights(inputWeightsInfo3, cellToOutputWeightsData);
2206
2207 std::vector<float> forgetGateBiasData(numUnits, 1.0f);
2208 armnn::ConstTensor forgetGateBias(inputWeightsInfo3, forgetGateBiasData);
2209
2210 std::vector<float> cellBiasData(numUnits, 0.0f);
2211 armnn::ConstTensor cellBias(inputWeightsInfo3, cellBiasData);
2212
2213 std::vector<float> outputGateBiasData(numUnits, 0.0f);
2214 armnn::ConstTensor outputGateBias(inputWeightsInfo3, outputGateBiasData);
2215
2216 armnn::LstmInputParams params;
2217 params.m_InputToForgetWeights = &inputToForgetWeights;
2218 params.m_InputToCellWeights = &inputToCellWeights;
2219 params.m_InputToOutputWeights = &inputToOutputWeights;
2220 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2221 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2222 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2223 params.m_ForgetGateBias = &forgetGateBias;
2224 params.m_CellBias = &cellBias;
2225 params.m_OutputGateBias = &outputGateBias;
2226 params.m_CellToForgetWeights = &cellToForgetWeights;
2227 params.m_CellToOutputWeights = &cellToOutputWeights;
2228
2229 armnn::INetworkPtr network = armnn::INetwork::Create();
2230 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2231 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2232 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2233 const std::string layerName("lstm");
2234 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2235 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2236 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2237 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2238 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2239
2240 // connect up
2241 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2242 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2243 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2244 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 3 }, armnn::DataType::Float32);
2245
2246 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2247 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2248
2249 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2250 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2251
2252 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2253 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2254
2255 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2256 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2257
2258 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2259 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2260
2261 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2262 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2263
2264 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2265 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2266
2267 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2268 BOOST_CHECK(deserializedNetwork);
2269
2270 VerifyLstmLayer checker(
2271 layerName,
2272 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2273 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2274 descriptor,
2275 params);
2276 deserializedNetwork->Accept(checker);
2277}
2278
2279BOOST_AUTO_TEST_CASE(SerializeDeserializeLstmNoCifgWithPeepholeAndProjection)
2280{
2281 armnn::LstmDescriptor descriptor;
2282 descriptor.m_ActivationFunc = 4;
2283 descriptor.m_ClippingThresProj = 0.0f;
2284 descriptor.m_ClippingThresCell = 0.0f;
2285 descriptor.m_CifgEnabled = false; // if this is true then we DON'T need to set the OptCifgParams
2286 descriptor.m_ProjectionEnabled = true;
2287 descriptor.m_PeepholeEnabled = true;
2288
2289 const uint32_t batchSize = 2;
2290 const uint32_t inputSize = 5;
2291 const uint32_t numUnits = 20;
2292 const uint32_t outputSize = 16;
2293
2294 armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
2295 std::vector<float> inputToInputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2296 armnn::ConstTensor inputToInputWeights(tensorInfo20x5, inputToInputWeightsData);
2297
2298 std::vector<float> inputToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2299 armnn::ConstTensor inputToForgetWeights(tensorInfo20x5, inputToForgetWeightsData);
2300
2301 std::vector<float> inputToCellWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2302 armnn::ConstTensor inputToCellWeights(tensorInfo20x5, inputToCellWeightsData);
2303
2304 std::vector<float> inputToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x5.GetNumElements());
2305 armnn::ConstTensor inputToOutputWeights(tensorInfo20x5, inputToOutputWeightsData);
2306
2307 armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
2308 std::vector<float> inputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2309 armnn::ConstTensor inputGateBias(tensorInfo20, inputGateBiasData);
2310
2311 std::vector<float> forgetGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2312 armnn::ConstTensor forgetGateBias(tensorInfo20, forgetGateBiasData);
2313
2314 std::vector<float> cellBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2315 armnn::ConstTensor cellBias(tensorInfo20, cellBiasData);
2316
2317 std::vector<float> outputGateBiasData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2318 armnn::ConstTensor outputGateBias(tensorInfo20, outputGateBiasData);
2319
2320 armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
2321 std::vector<float> recurrentToInputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2322 armnn::ConstTensor recurrentToInputWeights(tensorInfo20x16, recurrentToInputWeightsData);
2323
2324 std::vector<float> recurrentToForgetWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2325 armnn::ConstTensor recurrentToForgetWeights(tensorInfo20x16, recurrentToForgetWeightsData);
2326
2327 std::vector<float> recurrentToCellWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2328 armnn::ConstTensor recurrentToCellWeights(tensorInfo20x16, recurrentToCellWeightsData);
2329
2330 std::vector<float> recurrentToOutputWeightsData = GenerateRandomData<float>(tensorInfo20x16.GetNumElements());
2331 armnn::ConstTensor recurrentToOutputWeights(tensorInfo20x16, recurrentToOutputWeightsData);
2332
2333 std::vector<float> cellToInputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2334 armnn::ConstTensor cellToInputWeights(tensorInfo20, cellToInputWeightsData);
2335
2336 std::vector<float> cellToForgetWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2337 armnn::ConstTensor cellToForgetWeights(tensorInfo20, cellToForgetWeightsData);
2338
2339 std::vector<float> cellToOutputWeightsData = GenerateRandomData<float>(tensorInfo20.GetNumElements());
2340 armnn::ConstTensor cellToOutputWeights(tensorInfo20, cellToOutputWeightsData);
2341
2342 armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
2343 std::vector<float> projectionWeightsData = GenerateRandomData<float>(tensorInfo16x20.GetNumElements());
2344 armnn::ConstTensor projectionWeights(tensorInfo16x20, projectionWeightsData);
2345
2346 armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
2347 std::vector<float> projectionBiasData(outputSize, 0.f);
2348 armnn::ConstTensor projectionBias(tensorInfo16, projectionBiasData);
2349
2350 armnn::LstmInputParams params;
2351 params.m_InputToForgetWeights = &inputToForgetWeights;
2352 params.m_InputToCellWeights = &inputToCellWeights;
2353 params.m_InputToOutputWeights = &inputToOutputWeights;
2354 params.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2355 params.m_RecurrentToCellWeights = &recurrentToCellWeights;
2356 params.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2357 params.m_ForgetGateBias = &forgetGateBias;
2358 params.m_CellBias = &cellBias;
2359 params.m_OutputGateBias = &outputGateBias;
2360
2361 // additional params because: descriptor.m_CifgEnabled = false
2362 params.m_InputToInputWeights = &inputToInputWeights;
2363 params.m_RecurrentToInputWeights = &recurrentToInputWeights;
2364 params.m_CellToInputWeights = &cellToInputWeights;
2365 params.m_InputGateBias = &inputGateBias;
2366
2367 // additional params because: descriptor.m_ProjectionEnabled = true
2368 params.m_ProjectionWeights = &projectionWeights;
2369 params.m_ProjectionBias = &projectionBias;
2370
2371 // additional params because: descriptor.m_PeepholeEnabled = true
2372 params.m_CellToForgetWeights = &cellToForgetWeights;
2373 params.m_CellToOutputWeights = &cellToOutputWeights;
2374
2375 armnn::INetworkPtr network = armnn::INetwork::Create();
2376 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2377 armnn::IConnectableLayer* const cellStateIn = network->AddInputLayer(1);
2378 armnn::IConnectableLayer* const outputStateIn = network->AddInputLayer(2);
2379 const std::string layerName("lstm");
2380 armnn::IConnectableLayer* const lstmLayer = network->AddLstmLayer(descriptor, params, layerName.c_str());
2381 armnn::IConnectableLayer* const scratchBuffer = network->AddOutputLayer(0);
2382 armnn::IConnectableLayer* const outputStateOut = network->AddOutputLayer(1);
2383 armnn::IConnectableLayer* const cellStateOut = network->AddOutputLayer(2);
2384 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(3);
2385
2386 // connect up
2387 armnn::TensorInfo inputTensorInfo({ batchSize, inputSize }, armnn::DataType::Float32);
2388 armnn::TensorInfo cellStateTensorInfo({ batchSize, numUnits}, armnn::DataType::Float32);
2389 armnn::TensorInfo outputStateTensorInfo({ batchSize, outputSize }, armnn::DataType::Float32);
2390 armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * 4 }, armnn::DataType::Float32);
2391
2392 inputLayer->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(0));
2393 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2394
2395 outputStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(1));
2396 outputStateIn->GetOutputSlot(0).SetTensorInfo(outputStateTensorInfo);
2397
2398 cellStateIn->GetOutputSlot(0).Connect(lstmLayer->GetInputSlot(2));
2399 cellStateIn->GetOutputSlot(0).SetTensorInfo(cellStateTensorInfo);
2400
2401 lstmLayer->GetOutputSlot(0).Connect(scratchBuffer->GetInputSlot(0));
2402 lstmLayer->GetOutputSlot(0).SetTensorInfo(lstmTensorInfoScratchBuff);
2403
2404 lstmLayer->GetOutputSlot(1).Connect(outputStateOut->GetInputSlot(0));
2405 lstmLayer->GetOutputSlot(1).SetTensorInfo(outputStateTensorInfo);
2406
2407 lstmLayer->GetOutputSlot(2).Connect(cellStateOut->GetInputSlot(0));
2408 lstmLayer->GetOutputSlot(2).SetTensorInfo(cellStateTensorInfo);
2409
2410 lstmLayer->GetOutputSlot(3).Connect(outputLayer->GetInputSlot(0));
2411 lstmLayer->GetOutputSlot(3).SetTensorInfo(outputStateTensorInfo);
2412
2413 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2414 BOOST_CHECK(deserializedNetwork);
2415
2416 VerifyLstmLayer checker(
2417 layerName,
2418 {inputTensorInfo, outputStateTensorInfo, cellStateTensorInfo},
2419 {lstmTensorInfoScratchBuff, outputStateTensorInfo, cellStateTensorInfo, outputStateTensorInfo},
2420 descriptor,
2421 params);
2422 deserializedNetwork->Accept(checker);
2423}
2424
Nattapat Chaimanowong30b00202019-02-20 17:31:34 +00002425BOOST_AUTO_TEST_SUITE_END()