blob: 4c7739645a81fe1d994c92531f6cf09aae03ddf6 [file] [log] [blame]
//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//
#include "ConversionUtils.hpp"
#include <armnnUtils/Permute.hpp>
///
/// Helper classes
///
namespace armnn_driver
{
LayerInputHandle::LayerInputHandle()
: m_OutputSlot(nullptr)
, m_Valid(false)
{}
LayerInputHandle::LayerInputHandle(bool valid, armnn::IOutputSlot* outputSlot, armnn::TensorInfo tensorInfo)
: m_OutputSlot(outputSlot)
, m_Valid(valid)
, m_TensorInfo(tensorInfo)
{}
bool LayerInputHandle::IsValid() const
{
return m_Valid;
}
void LayerInputHandle::Connect(armnn::IInputSlot& inputSlot)
{
ARMNN_ASSERT(IsValid());
if (m_OutputSlot)
{
m_OutputSlot->Connect(inputSlot);
}
}
const armnn::TensorInfo& LayerInputHandle::GetTensorInfo() const
{
return m_TensorInfo;
}
ConstTensorPin::ConstTensorPin(bool optional)
: m_Optional(optional)
{}
ConstTensorPin::ConstTensorPin(const armnn::TensorInfo& tensorInfo,
const void* valueStart,
uint32_t numBytes,
const armnn::PermutationVector& mappings)
{
armnn::IgnoreUnused(numBytes);
assert(tensorInfo.GetNumBytes() == numBytes);
const bool needsSwizzling = (mappings.GetSize() > 0);
if (needsSwizzling)
{
m_SwizzledTensorData.resize(tensorInfo.GetNumBytes());
SwizzleAndroidNn4dTensorToArmNn(tensorInfo, valueStart, m_SwizzledTensorData.data(), mappings);
m_ConstTensor = armnn::ConstTensor(armnnUtils::Permuted(tensorInfo, mappings), m_SwizzledTensorData.data());
}
else
{
m_ConstTensor = armnn::ConstTensor(tensorInfo, valueStart);
}
}
bool ConstTensorPin::IsValid() const
{
return m_ConstTensor.GetMemoryArea() != nullptr;
}
bool ConstTensorPin::IsOptional() const
{
return m_Optional;
}
const armnn::ConstTensor& ConstTensorPin::GetConstTensor() const
{
return m_ConstTensor;
}
const armnn::ConstTensor* ConstTensorPin::GetConstTensorPtr() const
{
if (IsValid() && m_ConstTensor.GetNumElements() > 0)
{
return &m_ConstTensor;
}
// tensor is either invalid, or has no elements (indicating an optional tensor that was not provided)
return nullptr;
}
///
/// Utility functions
///
armnn::IConnectableLayer* ProcessActivation(const armnn::TensorInfo& tensorInfo,
ActivationFn activation,
armnn::IConnectableLayer* prevLayer,
ConversionData& data)
{
ARMNN_ASSERT(prevLayer->GetNumOutputSlots() == 1);
prevLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
armnn::IConnectableLayer* activationLayer = prevLayer;
if (activation != ActivationFn::kActivationNone)
{
armnn::ActivationDescriptor activationDesc;
switch (activation)
{
case ActivationFn::kActivationRelu:
{
activationDesc.m_Function = armnn::ActivationFunction::ReLu;
break;
}
case ActivationFn::kActivationRelu1:
{
activationDesc.m_Function = armnn::ActivationFunction::BoundedReLu;
activationDesc.m_A = 1.0f;
activationDesc.m_B = -1.0f;
break;
}
case ActivationFn::kActivationRelu6:
{
activationDesc.m_Function = armnn::ActivationFunction::BoundedReLu;
activationDesc.m_A = 6.0f;
break;
}
case ActivationFn::kActivationSigmoid:
{
activationDesc.m_Function = armnn::ActivationFunction::Sigmoid;
break;
}
case ActivationFn::kActivationTanh:
{
activationDesc.m_Function = armnn::ActivationFunction::TanH;
activationDesc.m_A = 1.0f;
activationDesc.m_B = 1.0f;
break;
}
default:
{
Fail("%s: Invalid activation enum value %i", __func__, activation);
return nullptr;
}
}
bool isSupported = false;
FORWARD_LAYER_SUPPORT_FUNC(__func__,
IsActivationSupported,
data.m_Backends,
isSupported,
prevLayer->GetOutputSlot(0).GetTensorInfo(),
tensorInfo,
activationDesc);
if (!isSupported)
{
return nullptr;
}
activationLayer = data.m_Network->AddActivationLayer(activationDesc);
prevLayer->GetOutputSlot(0).Connect(activationLayer->GetInputSlot(0));
activationLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
}
return activationLayer;
}
} // namespace armnn_driver