// // Copyright © 2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once #include #include #include #include #include #include #include #include #include template> std::vector> AddMulAddTest(armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, const armnn::ITensorHandleFactory& tensorHandleFactory, bool addOutput) { using namespace armnn; IgnoreUnused(memoryManager); TensorInfo input0TensorInfo({ 1, 2, 2, 3 }, ArmnnType); TensorInfo input1TensorInfo({ 1, 2, 2, 3 }, ArmnnType); TensorInfo mulInput1TensorInfo({ 3 }, ArmnnType); TensorInfo addInput1TensorInfo({ 3 }, ArmnnType); TensorInfo output0TensorInfo({ 1, 2, 2, 3 }, ArmnnType); TensorInfo output1TensorInfo({ 1, 2, 2, 3 }, ArmnnType); if (IsQuantizedType()) { input0TensorInfo.SetQuantizationScale(0.25f); input0TensorInfo.SetQuantizationOffset(10); input1TensorInfo.SetQuantizationScale(0.25f); input1TensorInfo.SetQuantizationOffset(11); mulInput1TensorInfo.SetQuantizationScale(0.25f); mulInput1TensorInfo.SetQuantizationOffset(12); addInput1TensorInfo.SetQuantizationScale(0.25f); addInput1TensorInfo.SetQuantizationOffset(13); output0TensorInfo.SetQuantizationScale(0.5f); output0TensorInfo.SetQuantizationOffset(14); output1TensorInfo.SetQuantizationScale(0.5f); output1TensorInfo.SetQuantizationOffset(15); } std::vector input0Data { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -2.0f, -2.0f, -2.0f }; std::vector input1Data { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -2.0f, -2.0f, -2.0f }; std::vector mulInput1Data { 2.0f, 1.0f, 1.0f }; std::vector addInput1Data { 3.0f, 0.0f, 0.0f }; std::vector output0ExpectedData = { 0.0f, 0.0f, 0.0f, 2.0f, 2.0f, 2.0f, -2.0f, -2.0f, -2.0f, -4.0f, -4.0f, -4.0f }; std::vector output1ExpectedData = { 3.0f, 0.0f, 0.0f, 7.0f, 2.0f, 2.0f, -1.0f, -2.0f, -2.0f, -5.0f, -4.0f, -4.0f }; std::vector input0 = armnnUtils::QuantizedVector(input0Data, input0TensorInfo.GetQuantizationScale(), input0TensorInfo.GetQuantizationOffset()); std::vector input1 = armnnUtils::QuantizedVector(input1Data, input1TensorInfo.GetQuantizationScale(), input1TensorInfo.GetQuantizationOffset()); std::vector mulInput1 = armnnUtils::QuantizedVector(mulInput1Data, mulInput1TensorInfo.GetQuantizationScale(), mulInput1TensorInfo.GetQuantizationOffset()); std::vector addInput1 = armnnUtils::QuantizedVector(addInput1Data, addInput1TensorInfo.GetQuantizationScale(), addInput1TensorInfo.GetQuantizationOffset()); std::vector output0Expected = armnnUtils::QuantizedVector(output0ExpectedData, output0TensorInfo.GetQuantizationScale(), output0TensorInfo.GetQuantizationOffset()); std::vector output1Expected = armnnUtils::QuantizedVector(output1ExpectedData, output1TensorInfo.GetQuantizationScale(), output1TensorInfo.GetQuantizationOffset()); std::vector output0Actual(output0TensorInfo.GetNumElements()); std::vector output1Actual(output1TensorInfo.GetNumElements()); std::unique_ptr input0Handle = tensorHandleFactory.CreateTensorHandle(input0TensorInfo); std::unique_ptr input1Handle = tensorHandleFactory.CreateTensorHandle(input1TensorInfo); std::unique_ptr mulInput1Handle = tensorHandleFactory.CreateTensorHandle(mulInput1TensorInfo); std::unique_ptr addInput1Handle = tensorHandleFactory.CreateTensorHandle(addInput1TensorInfo); std::unique_ptr output0Handle = tensorHandleFactory.CreateTensorHandle(output0TensorInfo); std::unique_ptr output1Handle = tensorHandleFactory.CreateTensorHandle(output1TensorInfo); uint32_t numOutputs = addOutput ? 2 : 1; FusedDescriptor descriptor(4, numOutputs, FusedKernelType::AddMulAdd); FusedQueueDescriptor fusedQueueDescriptor; fusedQueueDescriptor.m_Parameters = descriptor; WorkloadInfo info; AddInputToWorkload (fusedQueueDescriptor, info, input0TensorInfo, input0Handle.get()); AddInputToWorkload (fusedQueueDescriptor, info, input1TensorInfo, input1Handle.get()); AddInputToWorkload (fusedQueueDescriptor, info, mulInput1TensorInfo, mulInput1Handle.get()); AddInputToWorkload (fusedQueueDescriptor, info, addInput1TensorInfo, addInput1Handle.get()); if (addOutput) { AddOutputToWorkload(fusedQueueDescriptor, info, output0TensorInfo, output0Handle.get()); } AddOutputToWorkload(fusedQueueDescriptor, info, output1TensorInfo, output1Handle.get()); if (addOutput) { AddOutputToWorkload(fusedQueueDescriptor, info, output0TensorInfo, output0Handle.get()); } AddOutputToWorkload(fusedQueueDescriptor, info, output1TensorInfo, output1Handle.get()); std::unique_ptr workload = workloadFactory.CreateWorkload(LayerType::Fused, fusedQueueDescriptor, info); input0Handle->Allocate(); input1Handle->Allocate(); mulInput1Handle->Allocate(); addInput1Handle->Allocate(); if (addOutput) { output0Handle->Allocate(); } output1Handle->Allocate(); CopyDataToITensorHandle(input0Handle.get(), input0.data()); CopyDataToITensorHandle(input1Handle.get(), input1.data()); CopyDataToITensorHandle(mulInput1Handle.get(), mulInput1.data()); CopyDataToITensorHandle(addInput1Handle.get(), addInput1.data()); workload->Execute(); CopyDataFromITensorHandle(output1Actual.data(), output1Handle.get()); LayerTestResult ret1(output1Actual, output1Expected, output1Handle->GetShape(), output1TensorInfo.GetShape()); std::vector> ret = {ret1}; if (addOutput) { CopyDataFromITensorHandle(output0Actual.data(), output0Handle.get()); LayerTestResult ret0(output0Actual, output0Expected, output0Handle->GetShape(), output0TensorInfo.GetShape()); ret = {ret0, ret1}; } return ret; }