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