You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
276 lines
10 KiB
276 lines
10 KiB
//
|
|
// Copyright © 2017 Arm Ltd. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
//
|
|
#include "DriverTestHelpers.hpp"
|
|
|
|
#include "../1.0/HalPolicy.hpp"
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
#include <log/log.h>
|
|
|
|
BOOST_AUTO_TEST_SUITE(GenericLayerTests)
|
|
|
|
using namespace android::hardware;
|
|
using namespace driverTestHelpers;
|
|
using namespace armnn_driver;
|
|
|
|
using HalPolicy = hal_1_0::HalPolicy;
|
|
|
|
BOOST_AUTO_TEST_CASE(GetSupportedOperations)
|
|
{
|
|
auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
|
|
|
|
V1_0::ErrorStatus errorStatus;
|
|
std::vector<bool> supported;
|
|
|
|
auto cb = [&](V1_0::ErrorStatus _errorStatus, const std::vector<bool>& _supported)
|
|
{
|
|
errorStatus = _errorStatus;
|
|
supported = _supported;
|
|
};
|
|
|
|
HalPolicy::Model model0 = {};
|
|
|
|
// Add operands
|
|
int32_t actValue = 0;
|
|
float weightValue[] = {2, 4, 1};
|
|
float biasValue[] = {4};
|
|
|
|
AddInputOperand<HalPolicy>(model0, hidl_vec<uint32_t>{1, 3});
|
|
AddTensorOperand<HalPolicy>(model0, hidl_vec<uint32_t>{1, 3}, weightValue);
|
|
AddTensorOperand<HalPolicy>(model0, hidl_vec<uint32_t>{1}, biasValue);
|
|
AddIntOperand<HalPolicy>(model0, actValue);
|
|
AddOutputOperand<HalPolicy>(model0, hidl_vec<uint32_t>{1, 1});
|
|
|
|
model0.operations.resize(1);
|
|
|
|
// Make a correct fully connected operation
|
|
model0.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
|
|
model0.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2, 3};
|
|
model0.operations[0].outputs = hidl_vec<uint32_t>{4};
|
|
|
|
driver->getSupportedOperations(model0, cb);
|
|
BOOST_TEST((int)errorStatus == (int)V1_0::ErrorStatus::NONE);
|
|
BOOST_TEST(supported.size() == (size_t)1);
|
|
BOOST_TEST(supported[0] == true);
|
|
|
|
V1_0::Model model1 = {};
|
|
|
|
AddInputOperand<HalPolicy>(model1, hidl_vec<uint32_t>{1, 3});
|
|
AddTensorOperand<HalPolicy>(model1, hidl_vec<uint32_t>{1, 3}, weightValue);
|
|
AddTensorOperand<HalPolicy>(model1, hidl_vec<uint32_t>{1}, biasValue);
|
|
AddIntOperand<HalPolicy>(model1, actValue);
|
|
AddOutputOperand<HalPolicy>(model1, hidl_vec<uint32_t>{1, 1});
|
|
|
|
model1.operations.resize(2);
|
|
|
|
// Make a correct fully connected operation
|
|
model1.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
|
|
model1.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2, 3};
|
|
model1.operations[0].outputs = hidl_vec<uint32_t>{4};
|
|
|
|
// Add an incorrect fully connected operation
|
|
AddIntOperand<HalPolicy>(model1, actValue);
|
|
AddOutputOperand<HalPolicy>(model1, hidl_vec<uint32_t>{1, 1});
|
|
|
|
model1.operations[1].type = HalPolicy::OperationType::FULLY_CONNECTED;
|
|
model1.operations[1].inputs = hidl_vec<uint32_t>{4}; // Only 1 input operand, expected 4
|
|
model1.operations[1].outputs = hidl_vec<uint32_t>{5};
|
|
|
|
driver->getSupportedOperations(model1, cb);
|
|
|
|
BOOST_TEST((int)errorStatus == (int)V1_0::ErrorStatus::INVALID_ARGUMENT);
|
|
BOOST_TEST(supported.empty());
|
|
|
|
// Test Broadcast on add/mul operators
|
|
HalPolicy::Model model2 = {};
|
|
|
|
AddInputOperand<HalPolicy>(model2,
|
|
hidl_vec<uint32_t>{1, 1, 3, 4},
|
|
HalPolicy::OperandType::TENSOR_FLOAT32,
|
|
0.0f,
|
|
0,
|
|
2);
|
|
AddInputOperand<HalPolicy>(model2,
|
|
hidl_vec<uint32_t>{4},
|
|
HalPolicy::OperandType::TENSOR_FLOAT32,
|
|
0.0f,
|
|
0,
|
|
2);
|
|
AddIntOperand<HalPolicy>(model2, actValue, 2);
|
|
AddOutputOperand<HalPolicy>(model2, hidl_vec<uint32_t>{1, 1, 3, 4});
|
|
AddOutputOperand<HalPolicy>(model2, hidl_vec<uint32_t>{1, 1, 3, 4});
|
|
|
|
model2.operations.resize(2);
|
|
|
|
model2.operations[0].type = HalPolicy::OperationType::ADD;
|
|
model2.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2};
|
|
model2.operations[0].outputs = hidl_vec<uint32_t>{3};
|
|
|
|
model2.operations[1].type = HalPolicy::OperationType::MUL;
|
|
model2.operations[1].inputs = hidl_vec<uint32_t>{0, 1, 2};
|
|
model2.operations[1].outputs = hidl_vec<uint32_t>{4};
|
|
|
|
driver->getSupportedOperations(model2, cb);
|
|
BOOST_TEST((int)errorStatus == (int)V1_0::ErrorStatus::NONE);
|
|
BOOST_TEST(supported.size() == (size_t)2);
|
|
BOOST_TEST(supported[0] == true);
|
|
BOOST_TEST(supported[1] == true);
|
|
|
|
V1_0::Model model3 = {};
|
|
|
|
AddInputOperand<HalPolicy>(model3,
|
|
hidl_vec<uint32_t>{1, 1, 3, 4},
|
|
HalPolicy::OperandType::TENSOR_INT32);
|
|
AddInputOperand<HalPolicy>(model3,
|
|
hidl_vec<uint32_t>{4},
|
|
HalPolicy::OperandType::TENSOR_INT32);
|
|
AddInputOperand<HalPolicy>(model3, hidl_vec<uint32_t>{1, 1, 3, 4});
|
|
|
|
AddOutputOperand<HalPolicy>(model3, hidl_vec<uint32_t>{1, 1, 3, 4});
|
|
AddOutputOperand<HalPolicy>(model3,
|
|
hidl_vec<uint32_t>{1, 1, 3, 4},
|
|
HalPolicy::OperandType::TENSOR_QUANT8_ASYMM,
|
|
1.f / 225.f);
|
|
|
|
model3.operations.resize(1);
|
|
|
|
// Add unsupported operation, should return no error but we don't support it
|
|
model3.operations[0].type = HalPolicy::OperationType::HASHTABLE_LOOKUP;
|
|
model3.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2};
|
|
model3.operations[0].outputs = hidl_vec<uint32_t>{3, 4};
|
|
|
|
driver->getSupportedOperations(model3, cb);
|
|
BOOST_TEST((int)errorStatus == (int)V1_0::ErrorStatus::NONE);
|
|
BOOST_TEST(supported.size() == (size_t)1);
|
|
BOOST_TEST(supported[0] == false);
|
|
|
|
HalPolicy::Model model4 = {};
|
|
|
|
AddIntOperand<HalPolicy>(model4, 0);
|
|
|
|
model4.operations.resize(1);
|
|
|
|
// Add invalid operation
|
|
model4.operations[0].type = static_cast<HalPolicy::OperationType>(100);
|
|
model4.operations[0].outputs = hidl_vec<uint32_t>{0};
|
|
|
|
driver->getSupportedOperations(model4, cb);
|
|
BOOST_TEST((int)errorStatus == (int)V1_0::ErrorStatus::INVALID_ARGUMENT);
|
|
BOOST_TEST(supported.empty());
|
|
}
|
|
|
|
// The purpose of this test is to ensure that when encountering an unsupported operation
|
|
// it is skipped and getSupportedOperations() continues (rather than failing and stopping).
|
|
// As per IVGCVSW-710.
|
|
BOOST_AUTO_TEST_CASE(UnsupportedLayerContinueOnFailure)
|
|
{
|
|
auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
|
|
|
|
V1_0::ErrorStatus errorStatus;
|
|
std::vector<bool> supported;
|
|
|
|
auto cb = [&](V1_0::ErrorStatus _errorStatus, const std::vector<bool>& _supported)
|
|
{
|
|
errorStatus = _errorStatus;
|
|
supported = _supported;
|
|
};
|
|
|
|
HalPolicy::Model model = {};
|
|
|
|
// Operands
|
|
int32_t actValue = 0;
|
|
float weightValue[] = {2, 4, 1};
|
|
float biasValue[] = {4};
|
|
|
|
// HASHTABLE_LOOKUP is unsupported at the time of writing this test, but any unsupported layer will do
|
|
AddInputOperand<HalPolicy>(model,
|
|
hidl_vec<uint32_t>{1, 1, 3, 4},
|
|
HalPolicy::OperandType::TENSOR_INT32);
|
|
AddInputOperand<HalPolicy>(model,
|
|
hidl_vec<uint32_t>{4},
|
|
HalPolicy::OperandType::TENSOR_INT32,
|
|
0.0f,
|
|
0,
|
|
2);
|
|
AddInputOperand<HalPolicy>(model,
|
|
hidl_vec<uint32_t>{1, 1, 3, 4},
|
|
HalPolicy::OperandType::TENSOR_FLOAT32,
|
|
0.0f,
|
|
0,
|
|
2);
|
|
|
|
AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1, 3, 4});
|
|
AddOutputOperand<HalPolicy>(model,
|
|
hidl_vec<uint32_t>{1, 1, 3, 4},
|
|
HalPolicy::OperandType::TENSOR_QUANT8_ASYMM,
|
|
1.f / 225.f);
|
|
|
|
// Fully connected is supported
|
|
AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 3});
|
|
|
|
AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 3}, weightValue);
|
|
AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{1}, biasValue);
|
|
|
|
AddIntOperand<HalPolicy>(model, actValue);
|
|
|
|
AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1});
|
|
|
|
// EMBEDDING_LOOKUP is unsupported
|
|
AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1, 3, 4});
|
|
|
|
model.operations.resize(3);
|
|
|
|
// Unsupported
|
|
model.operations[0].type = HalPolicy::OperationType::HASHTABLE_LOOKUP;
|
|
model.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2};
|
|
model.operations[0].outputs = hidl_vec<uint32_t>{3, 4};
|
|
|
|
// Supported
|
|
model.operations[1].type = HalPolicy::OperationType::FULLY_CONNECTED;
|
|
model.operations[1].inputs = hidl_vec<uint32_t>{5, 6, 7, 8};
|
|
model.operations[1].outputs = hidl_vec<uint32_t>{9};
|
|
|
|
// Unsupported
|
|
model.operations[2].type = HalPolicy::OperationType::EMBEDDING_LOOKUP;
|
|
model.operations[2].inputs = hidl_vec<uint32_t>{1, 2};
|
|
model.operations[2].outputs = hidl_vec<uint32_t>{10};
|
|
|
|
// We are testing that the unsupported layers return false and the test continues rather than failing and stopping
|
|
driver->getSupportedOperations(model, cb);
|
|
BOOST_TEST((int)errorStatus == (int)V1_0::ErrorStatus::NONE);
|
|
BOOST_TEST(supported.size() == (size_t)3);
|
|
BOOST_TEST(supported[0] == false);
|
|
BOOST_TEST(supported[1] == true);
|
|
BOOST_TEST(supported[2] == false);
|
|
}
|
|
|
|
// The purpose of this test is to ensure that when encountering an failure
|
|
// during mem pool mapping we properly report an error to the framework via a callback
|
|
BOOST_AUTO_TEST_CASE(ModelToINetworkConverterMemPoolFail)
|
|
{
|
|
auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
|
|
|
|
V1_0::ErrorStatus errorStatus;
|
|
std::vector<bool> supported;
|
|
|
|
auto cb = [&](V1_0::ErrorStatus _errorStatus, const std::vector<bool>& _supported)
|
|
{
|
|
errorStatus = _errorStatus;
|
|
supported = _supported;
|
|
};
|
|
|
|
HalPolicy::Model model = {};
|
|
|
|
model.pools = hidl_vec<hidl_memory>{hidl_memory("Unsuported hidl memory type", nullptr, 0)};
|
|
|
|
// Memory pool mapping should fail, we should report an error
|
|
driver->getSupportedOperations(model, cb);
|
|
BOOST_TEST((int)errorStatus != (int)V1_0::ErrorStatus::NONE);
|
|
BOOST_TEST(supported.empty());
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|