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