blob: 180286a5b7b745636cec1d78f31e1095495241fd [file] [log] [blame]
Michael Butler2f499a92017-09-19 19:59:45 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "neuralnetworks_hidl_hal_test"
18
19#include "Models.h"
Miao Wang4862d612018-02-05 17:26:54 -080020#include "Utils.h"
21
22#include <android-base/logging.h>
23#include <android/hidl/allocator/1.0/IAllocator.h>
Michael Butler2f499a92017-09-19 19:59:45 -070024#include <android/hidl/memory/1.0/IMemory.h>
25#include <hidlmemory/mapping.h>
26#include <vector>
27
Miao Wang4862d612018-02-05 17:26:54 -080028using ::android::sp;
29
Michael Butler2f499a92017-09-19 19:59:45 -070030namespace android {
31namespace hardware {
32namespace neuralnetworks {
Michael Butler2f499a92017-09-19 19:59:45 -070033
34// create a valid model
Miao Wang4862d612018-02-05 17:26:54 -080035V1_1::Model createValidTestModel_1_1() {
Michael Butler2f499a92017-09-19 19:59:45 -070036 const std::vector<float> operand2Data = {5.0f, 6.0f, 7.0f, 8.0f};
37 const uint32_t size = operand2Data.size() * sizeof(float);
38
39 const uint32_t operand1 = 0;
40 const uint32_t operand2 = 1;
41 const uint32_t operand3 = 2;
42 const uint32_t operand4 = 3;
43
44 const std::vector<Operand> operands = {
45 {
46 .type = OperandType::TENSOR_FLOAT32,
47 .dimensions = {1, 2, 2, 1},
48 .numberOfConsumers = 1,
49 .scale = 0.0f,
50 .zeroPoint = 0,
51 .lifetime = OperandLifeTime::MODEL_INPUT,
52 .location = {.poolIndex = 0, .offset = 0, .length = 0},
53 },
54 {
55 .type = OperandType::TENSOR_FLOAT32,
56 .dimensions = {1, 2, 2, 1},
57 .numberOfConsumers = 1,
58 .scale = 0.0f,
59 .zeroPoint = 0,
60 .lifetime = OperandLifeTime::CONSTANT_COPY,
61 .location = {.poolIndex = 0, .offset = 0, .length = size},
62 },
63 {
64 .type = OperandType::INT32,
65 .dimensions = {},
66 .numberOfConsumers = 1,
67 .scale = 0.0f,
68 .zeroPoint = 0,
69 .lifetime = OperandLifeTime::CONSTANT_COPY,
70 .location = {.poolIndex = 0, .offset = size, .length = sizeof(int32_t)},
71 },
72 {
73 .type = OperandType::TENSOR_FLOAT32,
74 .dimensions = {1, 2, 2, 1},
75 .numberOfConsumers = 0,
76 .scale = 0.0f,
77 .zeroPoint = 0,
78 .lifetime = OperandLifeTime::MODEL_OUTPUT,
79 .location = {.poolIndex = 0, .offset = 0, .length = 0},
80 },
81 };
82
83 const std::vector<Operation> operations = {{
Jean-Luc Brouillet39ac22e2017-09-23 15:15:58 -070084 .type = OperationType::ADD, .inputs = {operand1, operand2, operand3}, .outputs = {operand4},
Michael Butler2f499a92017-09-19 19:59:45 -070085 }};
86
87 const std::vector<uint32_t> inputIndexes = {operand1};
88 const std::vector<uint32_t> outputIndexes = {operand4};
89 std::vector<uint8_t> operandValues(
90 reinterpret_cast<const uint8_t*>(operand2Data.data()),
91 reinterpret_cast<const uint8_t*>(operand2Data.data()) + size);
92 int32_t activation[1] = {static_cast<int32_t>(FusedActivationFunc::NONE)};
93 operandValues.insert(operandValues.end(), reinterpret_cast<const uint8_t*>(&activation[0]),
94 reinterpret_cast<const uint8_t*>(&activation[1]));
95
96 const std::vector<hidl_memory> pools = {};
97
98 return {
99 .operands = operands,
100 .operations = operations,
101 .inputIndexes = inputIndexes,
102 .outputIndexes = outputIndexes,
103 .operandValues = operandValues,
104 .pools = pools,
105 };
106}
107
108// create first invalid model
Miao Wang4862d612018-02-05 17:26:54 -0800109V1_1::Model createInvalidTestModel1_1_1() {
110 Model model = createValidTestModel_1_1();
Jean-Luc Brouillet39ac22e2017-09-23 15:15:58 -0700111 model.operations[0].type = static_cast<OperationType>(0xDEADBEEF); /* INVALID */
Michael Butler2f499a92017-09-19 19:59:45 -0700112 return model;
113}
114
115// create second invalid model
Miao Wang4862d612018-02-05 17:26:54 -0800116V1_1::Model createInvalidTestModel2_1_1() {
117 Model model = createValidTestModel_1_1();
Michael Butler2f499a92017-09-19 19:59:45 -0700118 const uint32_t operand1 = 0;
119 const uint32_t operand5 = 4; // INVALID OPERAND
120 model.inputIndexes = std::vector<uint32_t>({operand1, operand5 /* INVALID OPERAND */});
121 return model;
122}
123
Miao Wang4862d612018-02-05 17:26:54 -0800124V1_0::Model createValidTestModel_1_0() {
125 V1_1::Model model = createValidTestModel_1_1();
126 return nn::convertToV1_0(model);
127}
Michael Butler2f499a92017-09-19 19:59:45 -0700128
Miao Wang4862d612018-02-05 17:26:54 -0800129V1_0::Model createInvalidTestModel1_1_0() {
130 V1_1::Model model = createInvalidTestModel1_1_1();
131 return nn::convertToV1_0(model);
132}
Michael Butler2f499a92017-09-19 19:59:45 -0700133
Miao Wang4862d612018-02-05 17:26:54 -0800134V1_0::Model createInvalidTestModel2_1_0() {
135 V1_1::Model model = createInvalidTestModel2_1_1();
136 return nn::convertToV1_0(model);
Michael Butler2f499a92017-09-19 19:59:45 -0700137}
138
139// create a valid request
140Request createValidTestRequest() {
141 std::vector<float> inputData = {1.0f, 2.0f, 3.0f, 4.0f};
142 std::vector<float> outputData = {-1.0f, -1.0f, -1.0f, -1.0f};
143 const uint32_t INPUT = 0;
144 const uint32_t OUTPUT = 1;
145
146 // prepare inputs
147 uint32_t inputSize = static_cast<uint32_t>(inputData.size() * sizeof(float));
148 uint32_t outputSize = static_cast<uint32_t>(outputData.size() * sizeof(float));
149 std::vector<RequestArgument> inputs = {{
150 .location = {.poolIndex = INPUT, .offset = 0, .length = inputSize}, .dimensions = {},
151 }};
152 std::vector<RequestArgument> outputs = {{
153 .location = {.poolIndex = OUTPUT, .offset = 0, .length = outputSize}, .dimensions = {},
154 }};
Miao Wang4862d612018-02-05 17:26:54 -0800155 std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
156 nn::allocateSharedMemory(outputSize)};
Michael Butler2f499a92017-09-19 19:59:45 -0700157 if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
158 return {};
159 }
160
161 // load data
162 sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
163 sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
164 if (inputMemory.get() == nullptr || outputMemory.get() == nullptr) {
165 return {};
166 }
167 float* inputPtr = reinterpret_cast<float*>(static_cast<void*>(inputMemory->getPointer()));
168 float* outputPtr = reinterpret_cast<float*>(static_cast<void*>(outputMemory->getPointer()));
169 if (inputPtr == nullptr || outputPtr == nullptr) {
170 return {};
171 }
172 inputMemory->update();
173 outputMemory->update();
174 std::copy(inputData.begin(), inputData.end(), inputPtr);
175 std::copy(outputData.begin(), outputData.end(), outputPtr);
176 inputMemory->commit();
177 outputMemory->commit();
178
179 return {.inputs = inputs, .outputs = outputs, .pools = pools};
180}
181
182// create first invalid request
183Request createInvalidTestRequest1() {
184 Request request = createValidTestRequest();
185 const uint32_t INVALID = 2;
186 std::vector<float> inputData = {1.0f, 2.0f, 3.0f, 4.0f};
187 uint32_t inputSize = static_cast<uint32_t>(inputData.size() * sizeof(float));
188 request.inputs[0].location = {
189 .poolIndex = INVALID /* INVALID */, .offset = 0, .length = inputSize};
190 return request;
191}
192
193// create second invalid request
194Request createInvalidTestRequest2() {
195 Request request = createValidTestRequest();
196 request.inputs[0].dimensions = std::vector<uint32_t>({1, 2, 3, 4, 5, 6, 7, 8} /* INVALID */);
197 return request;
198}
199
Michael Butler2f499a92017-09-19 19:59:45 -0700200} // namespace neuralnetworks
201} // namespace hardware
202} // namespace android