blob: 307003cf4add7b63ca59548cacceb3cfcdb85a09 [file] [log] [blame]
Slava Shklyaev73ee79d2019-05-14 14:15:14 +01001/*
2 * Copyright (C) 2019 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
Xusong Wang7df43062019-08-09 16:38:14 -070017#include "1.0/Utils.h"
18
19#include "MemoryUtils.h"
Slava Shklyaev73ee79d2019-05-14 14:15:14 +010020#include "TestHarness.h"
21
Xusong Wang7df43062019-08-09 16:38:14 -070022#include <android-base/logging.h>
Slava Shklyaev73ee79d2019-05-14 14:15:14 +010023#include <android/hardware/neuralnetworks/1.0/types.h>
Xusong Wang7df43062019-08-09 16:38:14 -070024#include <android/hidl/allocator/1.0/IAllocator.h>
25#include <android/hidl/memory/1.0/IMemory.h>
26#include <hidlmemory/mapping.h>
Slava Shklyaev73ee79d2019-05-14 14:15:14 +010027
Xusong Wangead950d2019-08-09 16:45:24 -070028#include <algorithm>
Michael Butler13b05162019-08-29 22:17:24 -070029#include <iostream>
Slava Shklyaev73ee79d2019-05-14 14:15:14 +010030#include <vector>
31
Michael Butler62749b92019-08-26 23:55:47 -070032namespace android::hardware::neuralnetworks {
Slava Shklyaev73ee79d2019-05-14 14:15:14 +010033
Xusong Wang7df43062019-08-09 16:38:14 -070034using namespace test_helper;
Michael Butler62749b92019-08-26 23:55:47 -070035using hidl::memory::V1_0::IMemory;
36using V1_0::DataLocation;
37using V1_0::Request;
38using V1_0::RequestArgument;
Slava Shklyaev73ee79d2019-05-14 14:15:14 +010039
Xusong Wang7df43062019-08-09 16:38:14 -070040constexpr uint32_t kInputPoolIndex = 0;
41constexpr uint32_t kOutputPoolIndex = 1;
42
43Request createRequest(const TestModel& testModel) {
44 // Model inputs.
45 hidl_vec<RequestArgument> inputs(testModel.inputIndexes.size());
46 size_t inputSize = 0;
47 for (uint32_t i = 0; i < testModel.inputIndexes.size(); i++) {
48 const auto& op = testModel.operands[testModel.inputIndexes[i]];
49 if (op.data.size() == 0) {
50 // Omitted input.
51 inputs[i] = {.hasNoValue = true};
52 } else {
53 DataLocation loc = {.poolIndex = kInputPoolIndex,
54 .offset = static_cast<uint32_t>(inputSize),
55 .length = static_cast<uint32_t>(op.data.size())};
56 inputSize += op.data.alignedSize();
57 inputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
58 }
59 }
60
61 // Model outputs.
62 hidl_vec<RequestArgument> outputs(testModel.outputIndexes.size());
63 size_t outputSize = 0;
64 for (uint32_t i = 0; i < testModel.outputIndexes.size(); i++) {
65 const auto& op = testModel.operands[testModel.outputIndexes[i]];
Xusong Wangead950d2019-08-09 16:45:24 -070066
67 // In the case of zero-sized output, we should at least provide a one-byte buffer.
68 // This is because zero-sized tensors are only supported internally to the driver, or
69 // reported in output shapes. It is illegal for the client to pre-specify a zero-sized
70 // tensor as model output. Otherwise, we will have two semantic conflicts:
71 // - "Zero dimension" conflicts with "unspecified dimension".
72 // - "Omitted operand buffer" conflicts with "zero-sized operand buffer".
73 size_t bufferSize = std::max<size_t>(op.data.size(), 1);
74
Xusong Wang7df43062019-08-09 16:38:14 -070075 DataLocation loc = {.poolIndex = kOutputPoolIndex,
76 .offset = static_cast<uint32_t>(outputSize),
Xusong Wangead950d2019-08-09 16:45:24 -070077 .length = static_cast<uint32_t>(bufferSize)};
78 outputSize += op.data.size() == 0 ? TestBuffer::kAlignment : op.data.alignedSize();
Xusong Wang7df43062019-08-09 16:38:14 -070079 outputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
80 }
81
82 // Allocate memory pools.
83 hidl_vec<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
84 nn::allocateSharedMemory(outputSize)};
85 CHECK_NE(pools[kInputPoolIndex].size(), 0u);
86 CHECK_NE(pools[kOutputPoolIndex].size(), 0u);
87 sp<IMemory> inputMemory = mapMemory(pools[kInputPoolIndex]);
88 CHECK(inputMemory.get() != nullptr);
89 uint8_t* inputPtr = static_cast<uint8_t*>(static_cast<void*>(inputMemory->getPointer()));
90 CHECK(inputPtr != nullptr);
91
92 // Copy input data to the memory pool.
93 for (uint32_t i = 0; i < testModel.inputIndexes.size(); i++) {
94 const auto& op = testModel.operands[testModel.inputIndexes[i]];
95 if (op.data.size() > 0) {
96 const uint8_t* begin = op.data.get<uint8_t>();
97 const uint8_t* end = begin + op.data.size();
98 std::copy(begin, end, inputPtr + inputs[i].location.offset);
99 }
100 }
101
102 return {.inputs = std::move(inputs), .outputs = std::move(outputs), .pools = std::move(pools)};
Slava Shklyaev73ee79d2019-05-14 14:15:14 +0100103}
104
Xusong Wang7df43062019-08-09 16:38:14 -0700105std::vector<TestBuffer> getOutputBuffers(const Request& request) {
106 sp<IMemory> outputMemory = mapMemory(request.pools[kOutputPoolIndex]);
107 CHECK(outputMemory.get() != nullptr);
108 uint8_t* outputPtr = static_cast<uint8_t*>(static_cast<void*>(outputMemory->getPointer()));
109 CHECK(outputPtr != nullptr);
110
111 // Copy out output results.
112 std::vector<TestBuffer> outputBuffers;
113 for (const auto& output : request.outputs) {
114 outputBuffers.emplace_back(output.location.length, outputPtr + output.location.offset);
115 }
116
117 return outputBuffers;
Slava Shklyaev73ee79d2019-05-14 14:15:14 +0100118}
119
Michael Butler62749b92019-08-26 23:55:47 -0700120} // namespace android::hardware::neuralnetworks
Michael Butler13b05162019-08-29 22:17:24 -0700121
122namespace android::hardware::neuralnetworks::V1_0 {
123
124::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) {
125 return os << toString(errorStatus);
126}
127
128::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus) {
129 return os << toString(deviceStatus);
130}
131
132} // namespace android::hardware::neuralnetworks::V1_0