blob: 062f6f712fe2e2cda4212c1df192a08e5ec007af [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
40namespace {
41
42template <typename Type>
43constexpr std::underlying_type_t<Type> underlyingType(Type value) {
44 return static_cast<std::underlying_type_t<Type>>(value);
45}
46
Michael Butler4024d8f2020-12-04 17:38:20 -080047using HalDuration = std::chrono::duration<uint64_t, std::micro>;
Michael Butler6547b2a2020-11-22 19:36:30 -080048constexpr auto kVersion = android::nn::Version::ANDROID_Q;
Michael Butler4024d8f2020-12-04 17:38:20 -080049constexpr uint64_t kNoTiming = std::numeric_limits<uint64_t>::max();
Michael Butler6547b2a2020-11-22 19:36:30 -080050
Michael Butlerb98aa6d2020-02-22 22:37:59 -080051} // namespace
52
53namespace android::nn {
54namespace {
55
56constexpr bool validOperandType(OperandType operandType) {
57 switch (operandType) {
58 case OperandType::FLOAT32:
59 case OperandType::INT32:
60 case OperandType::UINT32:
61 case OperandType::TENSOR_FLOAT32:
62 case OperandType::TENSOR_INT32:
63 case OperandType::TENSOR_QUANT8_ASYMM:
64 case OperandType::BOOL:
65 case OperandType::TENSOR_QUANT16_SYMM:
66 case OperandType::TENSOR_FLOAT16:
67 case OperandType::TENSOR_BOOL8:
68 case OperandType::FLOAT16:
69 case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
70 case OperandType::TENSOR_QUANT16_ASYMM:
71 case OperandType::TENSOR_QUANT8_SYMM:
72 case OperandType::OEM:
73 case OperandType::TENSOR_OEM_BYTE:
74 return true;
75 default:
76 break;
77 }
78 return isExtension(operandType);
79}
80
81using hardware::hidl_handle;
82using hardware::hidl_vec;
83
84template <typename Input>
Michael Butler6547b2a2020-11-22 19:36:30 -080085using unvalidatedConvertOutput =
86 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080087
88template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -080089GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
90 const hidl_vec<Type>& arguments) {
91 std::vector<unvalidatedConvertOutput<Type>> canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080092 canonical.reserve(arguments.size());
93 for (const auto& argument : arguments) {
Michael Butler6547b2a2020-11-22 19:36:30 -080094 canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -080095 }
96 return canonical;
97}
98
99template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800100GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
101 const hidl_vec<Type>& arguments) {
102 return unvalidatedConvertVec(arguments);
103}
104
105template <typename Type>
106decltype(nn::unvalidatedConvert(std::declval<Type>())) validatedConvert(const Type& halObject) {
107 auto canonical = NN_TRY(nn::unvalidatedConvert(halObject));
108 const auto maybeVersion = validate(canonical);
109 if (!maybeVersion.has_value()) {
110 return error() << maybeVersion.error();
111 }
112 const auto version = maybeVersion.value();
113 if (version > kVersion) {
114 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
115 }
116 return canonical;
117}
118
119template <typename Type>
120GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> validatedConvert(
121 const hidl_vec<Type>& arguments) {
122 std::vector<unvalidatedConvertOutput<Type>> canonical;
123 canonical.reserve(arguments.size());
124 for (const auto& argument : arguments) {
125 canonical.push_back(NN_TRY(validatedConvert(argument)));
126 }
127 return canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800128}
129
130} // anonymous namespace
131
Michael Butler6547b2a2020-11-22 19:36:30 -0800132GeneralResult<OperandType> unvalidatedConvert(const hal::V1_2::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800133 return static_cast<OperandType>(operandType);
134}
135
Michael Butler6547b2a2020-11-22 19:36:30 -0800136GeneralResult<OperationType> unvalidatedConvert(const hal::V1_2::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800137 return static_cast<OperationType>(operationType);
138}
139
Michael Butler6547b2a2020-11-22 19:36:30 -0800140GeneralResult<DeviceType> unvalidatedConvert(const hal::V1_2::DeviceType& deviceType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800141 return static_cast<DeviceType>(deviceType);
142}
143
Michael Butler6547b2a2020-11-22 19:36:30 -0800144GeneralResult<Capabilities> unvalidatedConvert(const hal::V1_2::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800145 const bool validOperandTypes = std::all_of(
146 capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
147 [](const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800148 const auto maybeType = unvalidatedConvert(operandPerformance.type);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800149 return !maybeType.has_value() ? false : validOperandType(maybeType.value());
150 });
151 if (!validOperandTypes) {
Michael Butler4b276a72020-08-06 23:22:35 -0700152 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800153 << "Invalid OperandType when converting OperandPerformance in Capabilities";
154 }
155
156 const auto relaxedFloat32toFloat16PerformanceScalar =
Michael Butler6547b2a2020-11-22 19:36:30 -0800157 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800158 const auto relaxedFloat32toFloat16PerformanceTensor =
Michael Butler6547b2a2020-11-22 19:36:30 -0800159 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
160 auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800161
Michael Butler4b276a72020-08-06 23:22:35 -0700162 auto table = NN_TRY(hal::utils::makeGeneralFailure(
163 Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
164 nn::ErrorStatus::GENERAL_FAILURE));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800165
166 return Capabilities{
167 .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
168 .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
169 .operandPerformance = std::move(table),
170 };
171}
172
Michael Butler6547b2a2020-11-22 19:36:30 -0800173GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800174 const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
175 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800176 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
177 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800178 };
179}
180
Michael Butler6547b2a2020-11-22 19:36:30 -0800181GeneralResult<Operation> unvalidatedConvert(const hal::V1_2::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800182 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800183 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800184 .inputs = operation.inputs,
185 .outputs = operation.outputs,
186 };
187}
188
Michael Butler6547b2a2020-11-22 19:36:30 -0800189GeneralResult<Operand::SymmPerChannelQuantParams> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800190 const hal::V1_2::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
191 return Operand::SymmPerChannelQuantParams{
192 .scales = symmPerChannelQuantParams.scales,
193 .channelDim = symmPerChannelQuantParams.channelDim,
194 };
195}
196
Michael Butler6547b2a2020-11-22 19:36:30 -0800197GeneralResult<Operand> unvalidatedConvert(const hal::V1_2::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800198 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800199 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800200 .dimensions = operand.dimensions,
201 .scale = operand.scale,
202 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800203 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
204 .location = NN_TRY(unvalidatedConvert(operand.location)),
205 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800206 };
207}
208
Michael Butler6547b2a2020-11-22 19:36:30 -0800209GeneralResult<Operand::ExtraParams> unvalidatedConvert(
210 const hal::V1_2::Operand::ExtraParams& extraParams) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800211 using Discriminator = hal::V1_2::Operand::ExtraParams::hidl_discriminator;
212 switch (extraParams.getDiscriminator()) {
213 case Discriminator::none:
214 return Operand::NoParams{};
215 case Discriminator::channelQuant:
Michael Butler6547b2a2020-11-22 19:36:30 -0800216 return unvalidatedConvert(extraParams.channelQuant());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800217 case Discriminator::extension:
218 return extraParams.extension();
219 }
Michael Butler4b276a72020-08-06 23:22:35 -0700220 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
221 << "Unrecognized Operand::ExtraParams discriminator: "
222 << underlyingType(extraParams.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800223}
224
Michael Butler6547b2a2020-11-22 19:36:30 -0800225GeneralResult<Model> unvalidatedConvert(const hal::V1_2::Model& model) {
226 auto operations = NN_TRY(unvalidatedConvert(model.operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800227
228 // Verify number of consumers.
229 const auto numberOfConsumers =
230 hal::utils::countNumberOfConsumers(model.operands.size(), operations);
231 CHECK(model.operands.size() == numberOfConsumers.size());
232 for (size_t i = 0; i < model.operands.size(); ++i) {
233 if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
Michael Butler4b276a72020-08-06 23:22:35 -0700234 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
235 << "Invalid numberOfConsumers for operand " << i << ", expected "
236 << numberOfConsumers[i] << " but found " << model.operands[i].numberOfConsumers;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800237 }
238 }
239
240 auto main = Model::Subgraph{
Michael Butler6547b2a2020-11-22 19:36:30 -0800241 .operands = NN_TRY(unvalidatedConvert(model.operands)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800242 .operations = std::move(operations),
243 .inputIndexes = model.inputIndexes,
244 .outputIndexes = model.outputIndexes,
245 };
246
247 return Model{
248 .main = std::move(main),
Michael Butler6547b2a2020-11-22 19:36:30 -0800249 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
250 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800251 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800252 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800253 };
254}
255
Michael Butler6547b2a2020-11-22 19:36:30 -0800256GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800257 const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
258 return Model::ExtensionNameAndPrefix{
259 .name = extensionNameAndPrefix.name,
260 .prefix = extensionNameAndPrefix.prefix,
261 };
262}
263
Michael Butler6547b2a2020-11-22 19:36:30 -0800264GeneralResult<OutputShape> unvalidatedConvert(const hal::V1_2::OutputShape& outputShape) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800265 return OutputShape{
266 .dimensions = outputShape.dimensions,
267 .isSufficient = outputShape.isSufficient,
268 };
269}
270
Michael Butler6547b2a2020-11-22 19:36:30 -0800271GeneralResult<MeasureTiming> unvalidatedConvert(const hal::V1_2::MeasureTiming& measureTiming) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800272 return static_cast<MeasureTiming>(measureTiming);
273}
274
Michael Butler6547b2a2020-11-22 19:36:30 -0800275GeneralResult<Timing> unvalidatedConvert(const hal::V1_2::Timing& timing) {
Michael Butler4024d8f2020-12-04 17:38:20 -0800276 constexpr uint64_t kMaxTiming = std::chrono::floor<HalDuration>(Duration::max()).count();
277 constexpr auto convertTiming = [](uint64_t halTiming) -> OptionalDuration {
278 if (halTiming == kNoTiming) {
279 return {};
280 }
281 if (halTiming > kMaxTiming) {
282 return Duration::max();
283 }
284 return HalDuration{halTiming};
285 };
286 return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
287 .timeInDriver = convertTiming(timing.timeInDriver)};
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800288}
289
Michael Butler6547b2a2020-11-22 19:36:30 -0800290GeneralResult<Extension> unvalidatedConvert(const hal::V1_2::Extension& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800291 return Extension{
292 .name = extension.name,
Michael Butler6547b2a2020-11-22 19:36:30 -0800293 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800294 };
295}
296
Michael Butler6547b2a2020-11-22 19:36:30 -0800297GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800298 const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation) {
299 return Extension::OperandTypeInformation{
300 .type = operandTypeInformation.type,
301 .isTensor = operandTypeInformation.isTensor,
302 .byteSize = operandTypeInformation.byteSize,
303 };
304}
305
Michael Butler6547b2a2020-11-22 19:36:30 -0800306GeneralResult<SharedHandle> unvalidatedConvert(const hidl_handle& hidlHandle) {
Slava Shklyaev49817a02020-10-27 18:44:01 +0000307 return hal::utils::sharedHandleFromNativeHandle(hidlHandle.getNativeHandle());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800308}
309
Michael Butler6547b2a2020-11-22 19:36:30 -0800310GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType) {
311 return validatedConvert(deviceType);
312}
313
314GeneralResult<Capabilities> convert(const hal::V1_2::Capabilities& capabilities) {
315 return validatedConvert(capabilities);
316}
317
318GeneralResult<Model> convert(const hal::V1_2::Model& model) {
319 return validatedConvert(model);
320}
321
322GeneralResult<MeasureTiming> convert(const hal::V1_2::MeasureTiming& measureTiming) {
323 return validatedConvert(measureTiming);
324}
325
326GeneralResult<Timing> convert(const hal::V1_2::Timing& timing) {
327 return validatedConvert(timing);
328}
329
Michael Butler4b276a72020-08-06 23:22:35 -0700330GeneralResult<std::vector<Extension>> convert(const hidl_vec<hal::V1_2::Extension>& extensions) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800331 return validatedConvert(extensions);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800332}
333
Slava Shklyaev49817a02020-10-27 18:44:01 +0000334GeneralResult<std::vector<SharedHandle>> convert(const hidl_vec<hidl_handle>& handles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800335 return validatedConvert(handles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800336}
337
Michael Butler4b276a72020-08-06 23:22:35 -0700338GeneralResult<std::vector<OutputShape>> convert(
339 const hidl_vec<hal::V1_2::OutputShape>& outputShapes) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800340 return validatedConvert(outputShapes);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800341}
342
343} // namespace android::nn
344
345namespace android::hardware::neuralnetworks::V1_2::utils {
346namespace {
347
Michael Butler6547b2a2020-11-22 19:36:30 -0800348using utils::unvalidatedConvert;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800349
Michael Butler6547b2a2020-11-22 19:36:30 -0800350nn::GeneralResult<V1_0::OperandLifeTime> unvalidatedConvert(const nn::Operand::LifeTime& lifetime) {
351 return V1_0::utils::unvalidatedConvert(lifetime);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800352}
353
Michael Butler6547b2a2020-11-22 19:36:30 -0800354nn::GeneralResult<V1_0::PerformanceInfo> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800355 const nn::Capabilities::PerformanceInfo& performanceInfo) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800356 return V1_0::utils::unvalidatedConvert(performanceInfo);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800357}
358
Michael Butler6547b2a2020-11-22 19:36:30 -0800359nn::GeneralResult<V1_0::DataLocation> unvalidatedConvert(const nn::DataLocation& location) {
360 return V1_0::utils::unvalidatedConvert(location);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800361}
362
Michael Butler6547b2a2020-11-22 19:36:30 -0800363nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
364 const nn::Model::OperandValues& operandValues) {
365 return V1_0::utils::unvalidatedConvert(operandValues);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800366}
367
Michael Butler6547b2a2020-11-22 19:36:30 -0800368nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::Memory& memory) {
369 return V1_0::utils::unvalidatedConvert(memory);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800370}
371
372template <typename Input>
Michael Butler6547b2a2020-11-22 19:36:30 -0800373using unvalidatedConvertOutput =
374 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800375
376template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800377nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
378 const std::vector<Type>& arguments) {
379 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800380 for (size_t i = 0; i < arguments.size(); ++i) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800381 halObject[i] = NN_TRY(unvalidatedConvert(arguments[i]));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800382 }
383 return halObject;
384}
385
386template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800387nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
388 const std::vector<Type>& arguments) {
389 return unvalidatedConvertVec(arguments);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800390}
391
Michael Butler4b276a72020-08-06 23:22:35 -0700392nn::GeneralResult<Operand::ExtraParams> makeExtraParams(nn::Operand::NoParams /*noParams*/) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800393 return Operand::ExtraParams{};
394}
395
Michael Butler4b276a72020-08-06 23:22:35 -0700396nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800397 const nn::Operand::SymmPerChannelQuantParams& channelQuant) {
398 Operand::ExtraParams ret;
Michael Butler6547b2a2020-11-22 19:36:30 -0800399 ret.channelQuant(NN_TRY(unvalidatedConvert(channelQuant)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800400 return ret;
401}
402
Michael Butler4b276a72020-08-06 23:22:35 -0700403nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
404 const nn::Operand::ExtensionParams& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800405 Operand::ExtraParams ret;
406 ret.extension(extension);
407 return ret;
408}
409
Michael Butler6547b2a2020-11-22 19:36:30 -0800410template <typename Type>
411decltype(utils::unvalidatedConvert(std::declval<Type>())) validatedConvert(const Type& canonical) {
412 const auto maybeVersion = nn::validate(canonical);
413 if (!maybeVersion.has_value()) {
414 return nn::error() << maybeVersion.error();
415 }
416 const auto version = maybeVersion.value();
417 if (version > kVersion) {
418 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
419 }
420 return utils::unvalidatedConvert(canonical);
421}
422
423template <typename Type>
424nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> validatedConvert(
425 const std::vector<Type>& arguments) {
426 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
427 for (size_t i = 0; i < arguments.size(); ++i) {
428 halObject[i] = NN_TRY(validatedConvert(arguments[i]));
429 }
430 return halObject;
431}
432
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800433} // anonymous namespace
434
Michael Butler6547b2a2020-11-22 19:36:30 -0800435nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800436 return static_cast<OperandType>(operandType);
437}
438
Michael Butler6547b2a2020-11-22 19:36:30 -0800439nn::GeneralResult<OperationType> unvalidatedConvert(const nn::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800440 return static_cast<OperationType>(operationType);
441}
442
Michael Butler6547b2a2020-11-22 19:36:30 -0800443nn::GeneralResult<DeviceType> unvalidatedConvert(const nn::DeviceType& deviceType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800444 switch (deviceType) {
445 case nn::DeviceType::UNKNOWN:
Michael Butler4b276a72020-08-06 23:22:35 -0700446 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Invalid DeviceType UNKNOWN";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800447 case nn::DeviceType::OTHER:
448 case nn::DeviceType::CPU:
449 case nn::DeviceType::GPU:
450 case nn::DeviceType::ACCELERATOR:
451 return static_cast<DeviceType>(deviceType);
452 }
Michael Butler4b276a72020-08-06 23:22:35 -0700453 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
454 << "Invalid DeviceType " << underlyingType(deviceType);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800455}
456
Michael Butler6547b2a2020-11-22 19:36:30 -0800457nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800458 std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
459 operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
460 std::copy_if(capabilities.operandPerformance.asVector().begin(),
461 capabilities.operandPerformance.asVector().end(),
462 std::back_inserter(operandPerformance),
463 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
464 return nn::validOperandType(operandPerformance.type);
465 });
466
467 return Capabilities{
Michael Butler6547b2a2020-11-22 19:36:30 -0800468 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
469 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
470 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
471 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
472 .operandPerformance = NN_TRY(unvalidatedConvert(operandPerformance)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800473 };
474}
475
Michael Butler6547b2a2020-11-22 19:36:30 -0800476nn::GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800477 const nn::Capabilities::OperandPerformance& operandPerformance) {
478 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800479 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
480 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800481 };
482}
483
Michael Butler6547b2a2020-11-22 19:36:30 -0800484nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800485 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800486 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800487 .inputs = operation.inputs,
488 .outputs = operation.outputs,
489 };
490}
491
Michael Butler6547b2a2020-11-22 19:36:30 -0800492nn::GeneralResult<SymmPerChannelQuantParams> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800493 const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
494 return SymmPerChannelQuantParams{
495 .scales = symmPerChannelQuantParams.scales,
496 .channelDim = symmPerChannelQuantParams.channelDim,
497 };
498}
499
Michael Butler6547b2a2020-11-22 19:36:30 -0800500nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800501 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800502 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800503 .dimensions = operand.dimensions,
504 .numberOfConsumers = 0,
505 .scale = operand.scale,
506 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800507 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
508 .location = NN_TRY(unvalidatedConvert(operand.location)),
509 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800510 };
511}
512
Michael Butler6547b2a2020-11-22 19:36:30 -0800513nn::GeneralResult<Operand::ExtraParams> unvalidatedConvert(
514 const nn::Operand::ExtraParams& extraParams) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800515 return std::visit([](const auto& x) { return makeExtraParams(x); }, extraParams);
516}
517
Michael Butler6547b2a2020-11-22 19:36:30 -0800518nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800519 if (!hal::utils::hasNoPointerData(model)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700520 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800521 << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800522 }
523
Michael Butler6547b2a2020-11-22 19:36:30 -0800524 auto operands = NN_TRY(unvalidatedConvert(model.main.operands));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800525
526 // Update number of consumers.
527 const auto numberOfConsumers =
528 hal::utils::countNumberOfConsumers(operands.size(), model.main.operations);
529 CHECK(operands.size() == numberOfConsumers.size());
530 for (size_t i = 0; i < operands.size(); ++i) {
531 operands[i].numberOfConsumers = numberOfConsumers[i];
532 }
533
534 return Model{
535 .operands = std::move(operands),
Michael Butler6547b2a2020-11-22 19:36:30 -0800536 .operations = NN_TRY(unvalidatedConvert(model.main.operations)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800537 .inputIndexes = model.main.inputIndexes,
538 .outputIndexes = model.main.outputIndexes,
Michael Butler6547b2a2020-11-22 19:36:30 -0800539 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
540 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800541 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800542 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800543 };
544}
545
Michael Butler6547b2a2020-11-22 19:36:30 -0800546nn::GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800547 const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
548 return Model::ExtensionNameAndPrefix{
549 .name = extensionNameAndPrefix.name,
550 .prefix = extensionNameAndPrefix.prefix,
551 };
552}
553
Michael Butler6547b2a2020-11-22 19:36:30 -0800554nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800555 return OutputShape{.dimensions = outputShape.dimensions,
556 .isSufficient = outputShape.isSufficient};
557}
558
Michael Butler6547b2a2020-11-22 19:36:30 -0800559nn::GeneralResult<MeasureTiming> unvalidatedConvert(const nn::MeasureTiming& measureTiming) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800560 return static_cast<MeasureTiming>(measureTiming);
561}
562
Michael Butler6547b2a2020-11-22 19:36:30 -0800563nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing) {
Michael Butler4024d8f2020-12-04 17:38:20 -0800564 constexpr auto convertTiming = [](nn::OptionalDuration canonicalTiming) -> uint64_t {
565 if (!canonicalTiming.has_value()) {
566 return kNoTiming;
567 }
568 return std::chrono::ceil<HalDuration>(*canonicalTiming).count();
569 };
570 return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
571 .timeInDriver = convertTiming(timing.timeInDriver)};
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800572}
573
Michael Butler6547b2a2020-11-22 19:36:30 -0800574nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800575 return Extension{
576 .name = extension.name,
Michael Butler6547b2a2020-11-22 19:36:30 -0800577 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800578 };
579}
580
Michael Butler6547b2a2020-11-22 19:36:30 -0800581nn::GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800582 const nn::Extension::OperandTypeInformation& operandTypeInformation) {
583 return Extension::OperandTypeInformation{
584 .type = operandTypeInformation.type,
585 .isTensor = operandTypeInformation.isTensor,
586 .byteSize = operandTypeInformation.byteSize,
587 };
588}
589
Michael Butler6547b2a2020-11-22 19:36:30 -0800590nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
Slava Shklyaev49817a02020-10-27 18:44:01 +0000591 return hal::utils::hidlHandleFromSharedHandle(handle);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800592}
593
Michael Butler6547b2a2020-11-22 19:36:30 -0800594nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
595 return validatedConvert(deviceType);
596}
597
598nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
599 return validatedConvert(capabilities);
600}
601
602nn::GeneralResult<Model> convert(const nn::Model& model) {
603 return validatedConvert(model);
604}
605
606nn::GeneralResult<MeasureTiming> convert(const nn::MeasureTiming& measureTiming) {
607 return validatedConvert(measureTiming);
608}
609
610nn::GeneralResult<Timing> convert(const nn::Timing& timing) {
611 return validatedConvert(timing);
612}
613
Michael Butler4b276a72020-08-06 23:22:35 -0700614nn::GeneralResult<hidl_vec<Extension>> convert(const std::vector<nn::Extension>& extensions) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800615 return validatedConvert(extensions);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800616}
617
Slava Shklyaev49817a02020-10-27 18:44:01 +0000618nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800619 return validatedConvert(handles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800620}
621
Michael Butler4b276a72020-08-06 23:22:35 -0700622nn::GeneralResult<hidl_vec<OutputShape>> convert(const std::vector<nn::OutputShape>& outputShapes) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800623 return validatedConvert(outputShapes);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800624}
625
Michael Butler7fd03c22020-12-06 21:50:59 -0800626nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus) {
627 return V1_1::utils::convert(deviceStatus);
628}
629
630nn::GeneralResult<V1_0::Request> convert(const nn::Request& request) {
631 return V1_1::utils::convert(request);
632}
633
634nn::GeneralResult<V1_0::ErrorStatus> convert(const nn::ErrorStatus& status) {
635 return V1_1::utils::convert(status);
636}
637
638nn::GeneralResult<V1_1::ExecutionPreference> convert(
639 const nn::ExecutionPreference& executionPreference) {
640 return V1_1::utils::convert(executionPreference);
641}
642
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800643} // namespace android::hardware::neuralnetworks::V1_2::utils