blob: 29945b75e5acca3ea14e54719d300214cd25085c [file] [log] [blame]
Michael Butlerb98aa6d2020-02-22 22:37:59 -08001/*
2 * Copyright (C) 2020 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#include "Conversions.h"
18
19#include <android-base/logging.h>
20#include <android/hardware/neuralnetworks/1.2/types.h>
21#include <nnapi/OperandTypes.h>
22#include <nnapi/OperationTypes.h>
23#include <nnapi/Result.h>
24#include <nnapi/SharedMemory.h>
25#include <nnapi/TypeUtils.h>
26#include <nnapi/Types.h>
Michael Butler6547b2a2020-11-22 19:36:30 -080027#include <nnapi/Validation.h>
Michael Butlerb98aa6d2020-02-22 22:37:59 -080028#include <nnapi/hal/1.0/Conversions.h>
Michael Butler7fd03c22020-12-06 21:50:59 -080029#include <nnapi/hal/1.1/Conversions.h>
Michael Butlerb98aa6d2020-02-22 22:37:59 -080030#include <nnapi/hal/CommonUtils.h>
Michael Butler4b276a72020-08-06 23:22:35 -070031#include <nnapi/hal/HandleError.h>
Michael Butlerb98aa6d2020-02-22 22:37:59 -080032
33#include <algorithm>
34#include <functional>
35#include <iterator>
36#include <memory>
37#include <type_traits>
38#include <utility>
39
Michael Butler388bceb2021-02-03 15:15:43 -080040#include "Utils.h"
41
Michael Butlerb98aa6d2020-02-22 22:37:59 -080042namespace {
43
44template <typename Type>
45constexpr std::underlying_type_t<Type> underlyingType(Type value) {
46 return static_cast<std::underlying_type_t<Type>>(value);
47}
48
Michael Butler4024d8f2020-12-04 17:38:20 -080049using HalDuration = std::chrono::duration<uint64_t, std::micro>;
Michael Butler6547b2a2020-11-22 19:36:30 -080050
Michael Butlerb98aa6d2020-02-22 22:37:59 -080051} // namespace
52
53namespace android::nn {
54namespace {
55
Michael Butlerb98aa6d2020-02-22 22:37:59 -080056using hardware::hidl_handle;
57using hardware::hidl_vec;
58
59template <typename Input>
Michael Butler388bceb2021-02-03 15:15:43 -080060using UnvalidatedConvertOutput =
Michael Butler6547b2a2020-11-22 19:36:30 -080061 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080062
63template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -080064GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
Michael Butler6547b2a2020-11-22 19:36:30 -080065 const hidl_vec<Type>& arguments) {
Michael Butler388bceb2021-02-03 15:15:43 -080066 std::vector<UnvalidatedConvertOutput<Type>> canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080067 canonical.reserve(arguments.size());
68 for (const auto& argument : arguments) {
Michael Butler6547b2a2020-11-22 19:36:30 -080069 canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -080070 }
71 return canonical;
72}
73
74template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -080075GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& halObject) {
Michael Butler6547b2a2020-11-22 19:36:30 -080076 auto canonical = NN_TRY(nn::unvalidatedConvert(halObject));
Michael Butler388bceb2021-02-03 15:15:43 -080077 NN_TRY(hal::V1_2::utils::compliantVersion(canonical));
Michael Butler6547b2a2020-11-22 19:36:30 -080078 return canonical;
79}
80
81template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -080082GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> validatedConvert(
Michael Butler6547b2a2020-11-22 19:36:30 -080083 const hidl_vec<Type>& arguments) {
Michael Butler388bceb2021-02-03 15:15:43 -080084 std::vector<UnvalidatedConvertOutput<Type>> canonical;
Michael Butler6547b2a2020-11-22 19:36:30 -080085 canonical.reserve(arguments.size());
86 for (const auto& argument : arguments) {
87 canonical.push_back(NN_TRY(validatedConvert(argument)));
88 }
89 return canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080090}
91
92} // anonymous namespace
93
Michael Butler6547b2a2020-11-22 19:36:30 -080094GeneralResult<OperandType> unvalidatedConvert(const hal::V1_2::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -080095 return static_cast<OperandType>(operandType);
96}
97
Michael Butler6547b2a2020-11-22 19:36:30 -080098GeneralResult<OperationType> unvalidatedConvert(const hal::V1_2::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -080099 return static_cast<OperationType>(operationType);
100}
101
Michael Butler6547b2a2020-11-22 19:36:30 -0800102GeneralResult<DeviceType> unvalidatedConvert(const hal::V1_2::DeviceType& deviceType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800103 return static_cast<DeviceType>(deviceType);
104}
105
Michael Butler6547b2a2020-11-22 19:36:30 -0800106GeneralResult<Capabilities> unvalidatedConvert(const hal::V1_2::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800107 const bool validOperandTypes = std::all_of(
108 capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
109 [](const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
Michael Butler388bceb2021-02-03 15:15:43 -0800110 return validatedConvert(operandPerformance.type).has_value();
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800111 });
112 if (!validOperandTypes) {
Michael Butler4b276a72020-08-06 23:22:35 -0700113 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800114 << "Invalid OperandType when converting OperandPerformance in Capabilities";
115 }
116
117 const auto relaxedFloat32toFloat16PerformanceScalar =
Michael Butler6547b2a2020-11-22 19:36:30 -0800118 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800119 const auto relaxedFloat32toFloat16PerformanceTensor =
Michael Butler6547b2a2020-11-22 19:36:30 -0800120 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
121 auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800122
Michael Butler4b276a72020-08-06 23:22:35 -0700123 auto table = NN_TRY(hal::utils::makeGeneralFailure(
124 Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
125 nn::ErrorStatus::GENERAL_FAILURE));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800126
127 return Capabilities{
128 .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
129 .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
130 .operandPerformance = std::move(table),
131 };
132}
133
Michael Butler6547b2a2020-11-22 19:36:30 -0800134GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800135 const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
136 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800137 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
138 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800139 };
140}
141
Michael Butler6547b2a2020-11-22 19:36:30 -0800142GeneralResult<Operation> unvalidatedConvert(const hal::V1_2::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800143 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800144 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800145 .inputs = operation.inputs,
146 .outputs = operation.outputs,
147 };
148}
149
Michael Butler6547b2a2020-11-22 19:36:30 -0800150GeneralResult<Operand::SymmPerChannelQuantParams> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800151 const hal::V1_2::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
152 return Operand::SymmPerChannelQuantParams{
153 .scales = symmPerChannelQuantParams.scales,
154 .channelDim = symmPerChannelQuantParams.channelDim,
155 };
156}
157
Michael Butler6547b2a2020-11-22 19:36:30 -0800158GeneralResult<Operand> unvalidatedConvert(const hal::V1_2::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800159 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800160 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800161 .dimensions = operand.dimensions,
162 .scale = operand.scale,
163 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800164 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
165 .location = NN_TRY(unvalidatedConvert(operand.location)),
166 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800167 };
168}
169
Michael Butler6547b2a2020-11-22 19:36:30 -0800170GeneralResult<Operand::ExtraParams> unvalidatedConvert(
171 const hal::V1_2::Operand::ExtraParams& extraParams) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800172 using Discriminator = hal::V1_2::Operand::ExtraParams::hidl_discriminator;
173 switch (extraParams.getDiscriminator()) {
174 case Discriminator::none:
175 return Operand::NoParams{};
176 case Discriminator::channelQuant:
Michael Butler6547b2a2020-11-22 19:36:30 -0800177 return unvalidatedConvert(extraParams.channelQuant());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800178 case Discriminator::extension:
179 return extraParams.extension();
180 }
Michael Butler4b276a72020-08-06 23:22:35 -0700181 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
182 << "Unrecognized Operand::ExtraParams discriminator: "
183 << underlyingType(extraParams.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800184}
185
Michael Butler6547b2a2020-11-22 19:36:30 -0800186GeneralResult<Model> unvalidatedConvert(const hal::V1_2::Model& model) {
187 auto operations = NN_TRY(unvalidatedConvert(model.operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800188
189 // Verify number of consumers.
190 const auto numberOfConsumers =
Michael Butler68b69262021-02-09 15:36:11 -0800191 NN_TRY(hal::utils::countNumberOfConsumers(model.operands.size(), operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800192 CHECK(model.operands.size() == numberOfConsumers.size());
193 for (size_t i = 0; i < model.operands.size(); ++i) {
194 if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
Michael Butler4b276a72020-08-06 23:22:35 -0700195 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
196 << "Invalid numberOfConsumers for operand " << i << ", expected "
197 << numberOfConsumers[i] << " but found " << model.operands[i].numberOfConsumers;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800198 }
199 }
200
201 auto main = Model::Subgraph{
Michael Butler6547b2a2020-11-22 19:36:30 -0800202 .operands = NN_TRY(unvalidatedConvert(model.operands)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800203 .operations = std::move(operations),
204 .inputIndexes = model.inputIndexes,
205 .outputIndexes = model.outputIndexes,
206 };
207
208 return Model{
209 .main = std::move(main),
Michael Butler6547b2a2020-11-22 19:36:30 -0800210 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
211 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800212 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800213 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800214 };
215}
216
Michael Butler6547b2a2020-11-22 19:36:30 -0800217GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800218 const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
219 return Model::ExtensionNameAndPrefix{
220 .name = extensionNameAndPrefix.name,
221 .prefix = extensionNameAndPrefix.prefix,
222 };
223}
224
Michael Butler6547b2a2020-11-22 19:36:30 -0800225GeneralResult<OutputShape> unvalidatedConvert(const hal::V1_2::OutputShape& outputShape) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800226 return OutputShape{
227 .dimensions = outputShape.dimensions,
228 .isSufficient = outputShape.isSufficient,
229 };
230}
231
Michael Butler6547b2a2020-11-22 19:36:30 -0800232GeneralResult<MeasureTiming> unvalidatedConvert(const hal::V1_2::MeasureTiming& measureTiming) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800233 return static_cast<MeasureTiming>(measureTiming);
234}
235
Michael Butler6547b2a2020-11-22 19:36:30 -0800236GeneralResult<Timing> unvalidatedConvert(const hal::V1_2::Timing& timing) {
Michael Butler4024d8f2020-12-04 17:38:20 -0800237 constexpr uint64_t kMaxTiming = std::chrono::floor<HalDuration>(Duration::max()).count();
238 constexpr auto convertTiming = [](uint64_t halTiming) -> OptionalDuration {
Michael Butler388bceb2021-02-03 15:15:43 -0800239 constexpr uint64_t kNoTiming = std::numeric_limits<uint64_t>::max();
Michael Butler4024d8f2020-12-04 17:38:20 -0800240 if (halTiming == kNoTiming) {
241 return {};
242 }
243 if (halTiming > kMaxTiming) {
244 return Duration::max();
245 }
246 return HalDuration{halTiming};
247 };
248 return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
249 .timeInDriver = convertTiming(timing.timeInDriver)};
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800250}
251
Michael Butler6547b2a2020-11-22 19:36:30 -0800252GeneralResult<Extension> unvalidatedConvert(const hal::V1_2::Extension& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800253 return Extension{
254 .name = extension.name,
Michael Butler6547b2a2020-11-22 19:36:30 -0800255 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800256 };
257}
258
Michael Butler6547b2a2020-11-22 19:36:30 -0800259GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800260 const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation) {
261 return Extension::OperandTypeInformation{
262 .type = operandTypeInformation.type,
263 .isTensor = operandTypeInformation.isTensor,
264 .byteSize = operandTypeInformation.byteSize,
265 };
266}
267
Michael Butler6547b2a2020-11-22 19:36:30 -0800268GeneralResult<SharedHandle> unvalidatedConvert(const hidl_handle& hidlHandle) {
Michael Butlerab2f4822021-02-08 00:05:07 -0800269 if (hidlHandle.getNativeHandle() == nullptr) {
270 return nullptr;
271 }
272 auto handle = NN_TRY(hal::utils::sharedHandleFromNativeHandle(hidlHandle.getNativeHandle()));
273 return std::make_shared<const Handle>(std::move(handle));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800274}
275
Michael Butler6547b2a2020-11-22 19:36:30 -0800276GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType) {
277 return validatedConvert(deviceType);
278}
279
280GeneralResult<Capabilities> convert(const hal::V1_2::Capabilities& capabilities) {
281 return validatedConvert(capabilities);
282}
283
284GeneralResult<Model> convert(const hal::V1_2::Model& model) {
285 return validatedConvert(model);
286}
287
288GeneralResult<MeasureTiming> convert(const hal::V1_2::MeasureTiming& measureTiming) {
289 return validatedConvert(measureTiming);
290}
291
292GeneralResult<Timing> convert(const hal::V1_2::Timing& timing) {
293 return validatedConvert(timing);
294}
295
Michael Butler76e491f2020-12-19 01:55:32 -0800296GeneralResult<SharedMemory> convert(const hardware::hidl_memory& memory) {
297 return validatedConvert(memory);
298}
299
Michael Butler4b276a72020-08-06 23:22:35 -0700300GeneralResult<std::vector<Extension>> convert(const hidl_vec<hal::V1_2::Extension>& extensions) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800301 return validatedConvert(extensions);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800302}
303
Slava Shklyaev49817a02020-10-27 18:44:01 +0000304GeneralResult<std::vector<SharedHandle>> convert(const hidl_vec<hidl_handle>& handles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800305 return validatedConvert(handles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800306}
307
Michael Butler4b276a72020-08-06 23:22:35 -0700308GeneralResult<std::vector<OutputShape>> convert(
309 const hidl_vec<hal::V1_2::OutputShape>& outputShapes) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800310 return validatedConvert(outputShapes);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800311}
312
313} // namespace android::nn
314
315namespace android::hardware::neuralnetworks::V1_2::utils {
316namespace {
317
Michael Butler6547b2a2020-11-22 19:36:30 -0800318using utils::unvalidatedConvert;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800319
Michael Butler6547b2a2020-11-22 19:36:30 -0800320nn::GeneralResult<V1_0::OperandLifeTime> unvalidatedConvert(const nn::Operand::LifeTime& lifetime) {
321 return V1_0::utils::unvalidatedConvert(lifetime);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800322}
323
Michael Butler6547b2a2020-11-22 19:36:30 -0800324nn::GeneralResult<V1_0::PerformanceInfo> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800325 const nn::Capabilities::PerformanceInfo& performanceInfo) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800326 return V1_0::utils::unvalidatedConvert(performanceInfo);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800327}
328
Michael Butler6547b2a2020-11-22 19:36:30 -0800329nn::GeneralResult<V1_0::DataLocation> unvalidatedConvert(const nn::DataLocation& location) {
330 return V1_0::utils::unvalidatedConvert(location);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800331}
332
Michael Butler6547b2a2020-11-22 19:36:30 -0800333nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
334 const nn::Model::OperandValues& operandValues) {
335 return V1_0::utils::unvalidatedConvert(operandValues);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800336}
337
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800338nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800339 return V1_0::utils::unvalidatedConvert(memory);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800340}
341
342template <typename Input>
Michael Butler388bceb2021-02-03 15:15:43 -0800343using UnvalidatedConvertOutput =
Michael Butler6547b2a2020-11-22 19:36:30 -0800344 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800345
346template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -0800347nn::GeneralResult<hidl_vec<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
Michael Butler6547b2a2020-11-22 19:36:30 -0800348 const std::vector<Type>& arguments) {
Michael Butler388bceb2021-02-03 15:15:43 -0800349 hidl_vec<UnvalidatedConvertOutput<Type>> halObject(arguments.size());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800350 for (size_t i = 0; i < arguments.size(); ++i) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800351 halObject[i] = NN_TRY(unvalidatedConvert(arguments[i]));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800352 }
353 return halObject;
354}
355
Michael Butler4b276a72020-08-06 23:22:35 -0700356nn::GeneralResult<Operand::ExtraParams> makeExtraParams(nn::Operand::NoParams /*noParams*/) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800357 return Operand::ExtraParams{};
358}
359
Michael Butler4b276a72020-08-06 23:22:35 -0700360nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800361 const nn::Operand::SymmPerChannelQuantParams& channelQuant) {
362 Operand::ExtraParams ret;
Michael Butler6547b2a2020-11-22 19:36:30 -0800363 ret.channelQuant(NN_TRY(unvalidatedConvert(channelQuant)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800364 return ret;
365}
366
Michael Butler4b276a72020-08-06 23:22:35 -0700367nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
368 const nn::Operand::ExtensionParams& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800369 Operand::ExtraParams ret;
370 ret.extension(extension);
371 return ret;
372}
373
Michael Butler6547b2a2020-11-22 19:36:30 -0800374template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -0800375nn::GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& canonical) {
376 NN_TRY(compliantVersion(canonical));
377 return unvalidatedConvert(canonical);
Michael Butler6547b2a2020-11-22 19:36:30 -0800378}
379
380template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -0800381nn::GeneralResult<hidl_vec<UnvalidatedConvertOutput<Type>>> validatedConvert(
Michael Butler6547b2a2020-11-22 19:36:30 -0800382 const std::vector<Type>& arguments) {
Michael Butler388bceb2021-02-03 15:15:43 -0800383 hidl_vec<UnvalidatedConvertOutput<Type>> halObject(arguments.size());
Michael Butler6547b2a2020-11-22 19:36:30 -0800384 for (size_t i = 0; i < arguments.size(); ++i) {
385 halObject[i] = NN_TRY(validatedConvert(arguments[i]));
386 }
387 return halObject;
388}
389
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800390} // anonymous namespace
391
Michael Butler6547b2a2020-11-22 19:36:30 -0800392nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800393 return static_cast<OperandType>(operandType);
394}
395
Michael Butler6547b2a2020-11-22 19:36:30 -0800396nn::GeneralResult<OperationType> unvalidatedConvert(const nn::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800397 return static_cast<OperationType>(operationType);
398}
399
Michael Butler6547b2a2020-11-22 19:36:30 -0800400nn::GeneralResult<DeviceType> unvalidatedConvert(const nn::DeviceType& deviceType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800401 switch (deviceType) {
402 case nn::DeviceType::UNKNOWN:
Michael Butler4b276a72020-08-06 23:22:35 -0700403 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Invalid DeviceType UNKNOWN";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800404 case nn::DeviceType::OTHER:
405 case nn::DeviceType::CPU:
406 case nn::DeviceType::GPU:
407 case nn::DeviceType::ACCELERATOR:
408 return static_cast<DeviceType>(deviceType);
409 }
Michael Butler4b276a72020-08-06 23:22:35 -0700410 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
411 << "Invalid DeviceType " << underlyingType(deviceType);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800412}
413
Michael Butler6547b2a2020-11-22 19:36:30 -0800414nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800415 std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
416 operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
417 std::copy_if(capabilities.operandPerformance.asVector().begin(),
418 capabilities.operandPerformance.asVector().end(),
419 std::back_inserter(operandPerformance),
420 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
Michael Butler388bceb2021-02-03 15:15:43 -0800421 return compliantVersion(operandPerformance.type).has_value();
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800422 });
423
424 return Capabilities{
Michael Butler6547b2a2020-11-22 19:36:30 -0800425 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
426 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
427 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
428 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
429 .operandPerformance = NN_TRY(unvalidatedConvert(operandPerformance)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800430 };
431}
432
Michael Butler6547b2a2020-11-22 19:36:30 -0800433nn::GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800434 const nn::Capabilities::OperandPerformance& operandPerformance) {
435 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800436 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
437 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800438 };
439}
440
Michael Butler6547b2a2020-11-22 19:36:30 -0800441nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800442 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800443 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800444 .inputs = operation.inputs,
445 .outputs = operation.outputs,
446 };
447}
448
Michael Butler6547b2a2020-11-22 19:36:30 -0800449nn::GeneralResult<SymmPerChannelQuantParams> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800450 const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
451 return SymmPerChannelQuantParams{
452 .scales = symmPerChannelQuantParams.scales,
453 .channelDim = symmPerChannelQuantParams.channelDim,
454 };
455}
456
Michael Butler6547b2a2020-11-22 19:36:30 -0800457nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800458 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800459 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800460 .dimensions = operand.dimensions,
461 .numberOfConsumers = 0,
462 .scale = operand.scale,
463 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800464 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
465 .location = NN_TRY(unvalidatedConvert(operand.location)),
466 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800467 };
468}
469
Michael Butler6547b2a2020-11-22 19:36:30 -0800470nn::GeneralResult<Operand::ExtraParams> unvalidatedConvert(
471 const nn::Operand::ExtraParams& extraParams) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800472 return std::visit([](const auto& x) { return makeExtraParams(x); }, extraParams);
473}
474
Michael Butler6547b2a2020-11-22 19:36:30 -0800475nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800476 if (!hal::utils::hasNoPointerData(model)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700477 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800478 << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800479 }
480
Michael Butler6547b2a2020-11-22 19:36:30 -0800481 auto operands = NN_TRY(unvalidatedConvert(model.main.operands));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800482
483 // Update number of consumers.
484 const auto numberOfConsumers =
Michael Butler68b69262021-02-09 15:36:11 -0800485 NN_TRY(hal::utils::countNumberOfConsumers(operands.size(), model.main.operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800486 CHECK(operands.size() == numberOfConsumers.size());
487 for (size_t i = 0; i < operands.size(); ++i) {
488 operands[i].numberOfConsumers = numberOfConsumers[i];
489 }
490
491 return Model{
492 .operands = std::move(operands),
Michael Butler6547b2a2020-11-22 19:36:30 -0800493 .operations = NN_TRY(unvalidatedConvert(model.main.operations)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800494 .inputIndexes = model.main.inputIndexes,
495 .outputIndexes = model.main.outputIndexes,
Michael Butler6547b2a2020-11-22 19:36:30 -0800496 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
497 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800498 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800499 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800500 };
501}
502
Michael Butler6547b2a2020-11-22 19:36:30 -0800503nn::GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800504 const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
505 return Model::ExtensionNameAndPrefix{
506 .name = extensionNameAndPrefix.name,
507 .prefix = extensionNameAndPrefix.prefix,
508 };
509}
510
Michael Butler6547b2a2020-11-22 19:36:30 -0800511nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800512 return OutputShape{.dimensions = outputShape.dimensions,
513 .isSufficient = outputShape.isSufficient};
514}
515
Michael Butler6547b2a2020-11-22 19:36:30 -0800516nn::GeneralResult<MeasureTiming> unvalidatedConvert(const nn::MeasureTiming& measureTiming) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800517 return static_cast<MeasureTiming>(measureTiming);
518}
519
Michael Butler6547b2a2020-11-22 19:36:30 -0800520nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing) {
Michael Butler4024d8f2020-12-04 17:38:20 -0800521 constexpr auto convertTiming = [](nn::OptionalDuration canonicalTiming) -> uint64_t {
Michael Butler388bceb2021-02-03 15:15:43 -0800522 constexpr uint64_t kNoTiming = std::numeric_limits<uint64_t>::max();
Michael Butler4024d8f2020-12-04 17:38:20 -0800523 if (!canonicalTiming.has_value()) {
524 return kNoTiming;
525 }
526 return std::chrono::ceil<HalDuration>(*canonicalTiming).count();
527 };
528 return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
529 .timeInDriver = convertTiming(timing.timeInDriver)};
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800530}
531
Michael Butler6547b2a2020-11-22 19:36:30 -0800532nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800533 return Extension{
534 .name = extension.name,
Michael Butler6547b2a2020-11-22 19:36:30 -0800535 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800536 };
537}
538
Michael Butler6547b2a2020-11-22 19:36:30 -0800539nn::GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800540 const nn::Extension::OperandTypeInformation& operandTypeInformation) {
541 return Extension::OperandTypeInformation{
542 .type = operandTypeInformation.type,
543 .isTensor = operandTypeInformation.isTensor,
544 .byteSize = operandTypeInformation.byteSize,
545 };
546}
547
Michael Butler6547b2a2020-11-22 19:36:30 -0800548nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
Michael Butlerab2f4822021-02-08 00:05:07 -0800549 if (handle == nullptr) {
550 return {};
551 }
552 return hal::utils::hidlHandleFromSharedHandle(*handle);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800553}
554
Michael Butler6547b2a2020-11-22 19:36:30 -0800555nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
556 return validatedConvert(deviceType);
557}
558
559nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
560 return validatedConvert(capabilities);
561}
562
563nn::GeneralResult<Model> convert(const nn::Model& model) {
564 return validatedConvert(model);
565}
566
567nn::GeneralResult<MeasureTiming> convert(const nn::MeasureTiming& measureTiming) {
568 return validatedConvert(measureTiming);
569}
570
571nn::GeneralResult<Timing> convert(const nn::Timing& timing) {
572 return validatedConvert(timing);
573}
574
Michael Butler4b276a72020-08-06 23:22:35 -0700575nn::GeneralResult<hidl_vec<Extension>> convert(const std::vector<nn::Extension>& extensions) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800576 return validatedConvert(extensions);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800577}
578
Slava Shklyaev49817a02020-10-27 18:44:01 +0000579nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800580 return validatedConvert(handles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800581}
582
Michael Butler4b276a72020-08-06 23:22:35 -0700583nn::GeneralResult<hidl_vec<OutputShape>> convert(const std::vector<nn::OutputShape>& outputShapes) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800584 return validatedConvert(outputShapes);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800585}
586
Michael Butler7fd03c22020-12-06 21:50:59 -0800587nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus) {
588 return V1_1::utils::convert(deviceStatus);
589}
590
591nn::GeneralResult<V1_0::Request> convert(const nn::Request& request) {
592 return V1_1::utils::convert(request);
593}
594
595nn::GeneralResult<V1_0::ErrorStatus> convert(const nn::ErrorStatus& status) {
596 return V1_1::utils::convert(status);
597}
598
599nn::GeneralResult<V1_1::ExecutionPreference> convert(
600 const nn::ExecutionPreference& executionPreference) {
601 return V1_1::utils::convert(executionPreference);
602}
603
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800604} // namespace android::hardware::neuralnetworks::V1_2::utils