blob: 9dece9be3bac09483ea6f7bb6059b797710f6da7 [file] [log] [blame]
Teresa Charlin9145e382023-08-17 18:44:58 +01001//
2// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
8#include <armnnTestUtils/LayerTestResult.hpp>
9
10#include <armnnUtils/QuantizeHelper.hpp>
11#include <ResolveType.hpp>
12
13#include <armnn/backends/IBackendInternal.hpp>
14#include <armnn/backends/WorkloadFactory.hpp>
15
16#include <armnnTestUtils/TensorCopyUtils.hpp>
17#include <backendsCommon/test/WorkloadFactoryHelper.hpp>
18#include <armnnTestUtils/WorkloadTestUtils.hpp>
19
20#include <armnnTestUtils/TensorHelpers.hpp>
21
22template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
23std::vector<LayerTestResult<T,4>> AddMulAddTest(armnn::IWorkloadFactory& workloadFactory,
24 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
25 const armnn::ITensorHandleFactory& tensorHandleFactory,
26 bool addOutput)
27{
28 using namespace armnn;
29 IgnoreUnused(memoryManager);
30
31 TensorInfo input0TensorInfo({ 1, 2, 2, 3 }, ArmnnType);
32 TensorInfo input1TensorInfo({ 1, 2, 2, 3 }, ArmnnType);
33 TensorInfo mulInput1TensorInfo({ 3 }, ArmnnType);
34 TensorInfo addInput1TensorInfo({ 3 }, ArmnnType);
35
36 TensorInfo output0TensorInfo({ 1, 2, 2, 3 }, ArmnnType);
37 TensorInfo output1TensorInfo({ 1, 2, 2, 3 }, ArmnnType);
38
39 if (IsQuantizedType<T>())
40 {
41 input0TensorInfo.SetQuantizationScale(0.25f);
42 input0TensorInfo.SetQuantizationOffset(128);
43 input1TensorInfo.SetQuantizationScale(0.25f);
44 input1TensorInfo.SetQuantizationOffset(128);
45 mulInput1TensorInfo.SetQuantizationScale(0.25f);
46 mulInput1TensorInfo.SetQuantizationOffset(128);
47 addInput1TensorInfo.SetQuantizationScale(0.25f);
48 addInput1TensorInfo.SetQuantizationOffset(128);
49
50 output0TensorInfo.SetQuantizationScale(0.5f);
51 output0TensorInfo.SetQuantizationOffset(120);
52 output1TensorInfo.SetQuantizationScale(0.5f);
53 output1TensorInfo.SetQuantizationOffset(120);
54 }
55
56 std::vector<float> input0Data
57 {
58 0.0f, 0.0f, 0.0f,
59 1.0f, 1.0f, 1.0f,
60 -1.0f, -1.0f, -1.0f,
61 -2.0f, -2.0f, -2.0f
62 };
63 std::vector<float> input1Data
64 {
65 0.0f, 0.0f, 0.0f,
66 1.0f, 1.0f, 1.0f,
67 -1.0f, -1.0f, -1.0f,
68 -2.0f, -2.0f, -2.0f
69 };
70 std::vector<float> mulInput1Data
71 {
72 2.0f, 1.0f, 1.0f
73 };
74 std::vector<float> addInput1Data
75 {
76 3.0f, 0.0f, 0.0f
77 };
78 std::vector<float> output0ExpectedData =
79 {
80 0.0f, 0.0f, 0.0f,
81 2.0f, 2.0f, 2.0f,
82 -2.0f, -2.0f, -2.0f,
83 -4.0f, -4.0f, -4.0f
84 };
85
86 std::vector<float> output1ExpectedData =
87 {
88 3.0f, 0.0f, 0.0f,
89 7.0f, 2.0f, 2.0f,
90 -1.0f, -2.0f, -2.0f,
91 -5.0f, -4.0f, -4.0f
92 };
93
94 std::vector<T> input0 = armnnUtils::QuantizedVector<T>(input0Data,
95 input0TensorInfo.GetQuantizationScale(),
96 input0TensorInfo.GetQuantizationOffset());
97
98 std::vector<T> input1 = armnnUtils::QuantizedVector<T>(input1Data,
99 input1TensorInfo.GetQuantizationScale(),
100 input1TensorInfo.GetQuantizationOffset());
101
102 std::vector<T> mulInput1 = armnnUtils::QuantizedVector<T>(mulInput1Data,
103 mulInput1TensorInfo.GetQuantizationScale(),
104 mulInput1TensorInfo.GetQuantizationOffset());
105
106 std::vector<T> addInput1 = armnnUtils::QuantizedVector<T>(addInput1Data,
107 addInput1TensorInfo.GetQuantizationScale(),
108 addInput1TensorInfo.GetQuantizationOffset());
109
110 std::vector<T> output0Expected = armnnUtils::QuantizedVector<T>(output0ExpectedData,
111 output0TensorInfo.GetQuantizationScale(),
112 output0TensorInfo.GetQuantizationOffset());
113
114 std::vector<T> output1Expected = armnnUtils::QuantizedVector<T>(output1ExpectedData,
115 output1TensorInfo.GetQuantizationScale(),
116 output1TensorInfo.GetQuantizationOffset());
117
118 std::vector<T> output0Actual(output0TensorInfo.GetNumElements());
119 std::vector<T> output1Actual(output1TensorInfo.GetNumElements());
120
121 std::unique_ptr<ITensorHandle> input0Handle = tensorHandleFactory.CreateTensorHandle(input0TensorInfo);
122 std::unique_ptr<ITensorHandle> input1Handle = tensorHandleFactory.CreateTensorHandle(input1TensorInfo);
123 std::unique_ptr<ITensorHandle> mulInput1Handle = tensorHandleFactory.CreateTensorHandle(mulInput1TensorInfo);
124 std::unique_ptr<ITensorHandle> addInput1Handle = tensorHandleFactory.CreateTensorHandle(addInput1TensorInfo);
125 std::unique_ptr<ITensorHandle> output0Handle = tensorHandleFactory.CreateTensorHandle(output0TensorInfo);
126 std::unique_ptr<ITensorHandle> output1Handle = tensorHandleFactory.CreateTensorHandle(output1TensorInfo);
127
128 uint32_t numOutputs = addOutput ? 2 : 1;
129 FusedDescriptor descriptor(4, numOutputs, FusedKernelType::AddMulAdd);
130 FusedQueueDescriptor fusedQueueDescriptor;
131 fusedQueueDescriptor.m_Parameters = descriptor;
132 WorkloadInfo info;
133 AddInputToWorkload (fusedQueueDescriptor, info, input0TensorInfo, input0Handle.get());
134 AddInputToWorkload (fusedQueueDescriptor, info, input1TensorInfo, input1Handle.get());
135 AddInputToWorkload (fusedQueueDescriptor, info, mulInput1TensorInfo, mulInput1Handle.get());
136 AddInputToWorkload (fusedQueueDescriptor, info, addInput1TensorInfo, addInput1Handle.get());
137 if (addOutput)
138 {
139 AddOutputToWorkload(fusedQueueDescriptor, info, output0TensorInfo, output0Handle.get());
140 }
141 AddOutputToWorkload(fusedQueueDescriptor, info, output1TensorInfo, output1Handle.get());
142
143 std::unique_ptr<IWorkload> workload = workloadFactory.CreateWorkload(LayerType::Fused,
144 fusedQueueDescriptor,
145 info);
146
147 input0Handle->Allocate();
148 input1Handle->Allocate();
149 mulInput1Handle->Allocate();
150 addInput1Handle->Allocate();
151 if (addOutput)
152 {
153 output0Handle->Allocate();
154 }
155 output1Handle->Allocate();
156
157 CopyDataToITensorHandle(input0Handle.get(), input0.data());
158 CopyDataToITensorHandle(input1Handle.get(), input1.data());
159 CopyDataToITensorHandle(mulInput1Handle.get(), mulInput1.data());
160 CopyDataToITensorHandle(addInput1Handle.get(), addInput1.data());
161
162 workload->Execute();
163
164 CopyDataFromITensorHandle(output1Actual.data(), output1Handle.get());
165 LayerTestResult<T,4> ret1(output1Actual,
166 output1Expected,
167 output1Handle->GetShape(),
168 output1TensorInfo.GetShape());
169
170 std::vector<LayerTestResult<T,4>> ret = {ret1};
171
172 if (addOutput)
173 {
174 CopyDataFromITensorHandle(output0Actual.data(), output0Handle.get());
175 LayerTestResult<T,4> ret0(output0Actual,
176 output0Expected,
177 output0Handle->GetShape(),
178 output0TensorInfo.GetShape());
179 ret = {ret0, ret1};
180 }
181 return ret;
182}