• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 #include "Converter.h"
18 
19 #include <android-base/logging.h>
20 #include <nnapi/TypeUtils.h>
21 
22 #include <algorithm>
23 #include <random>
24 #include <utility>
25 #include <vector>
26 
27 namespace android::nn::fuzz {
28 namespace {
29 
30 using namespace test_helper;
31 
32 constexpr uint32_t kMaxSize = 65536;
33 
convert(android_nn_fuzz::OperandType type)34 TestOperandType convert(android_nn_fuzz::OperandType type) {
35     return static_cast<TestOperandType>(type);
36 }
37 
convert(android_nn_fuzz::OperationType type)38 TestOperationType convert(android_nn_fuzz::OperationType type) {
39     return static_cast<TestOperationType>(type);
40 }
41 
convert(android_nn_fuzz::OperandLifeTime lifetime)42 TestOperandLifeTime convert(android_nn_fuzz::OperandLifeTime lifetime) {
43     return static_cast<TestOperandLifeTime>(lifetime);
44 }
45 
convert(const android_nn_fuzz::Scales & scales)46 std::vector<float> convert(const android_nn_fuzz::Scales& scales) {
47     const auto& repeatedScale = scales.scale();
48     return std::vector<float>(repeatedScale.begin(), repeatedScale.end());
49 }
50 
convert(const android_nn_fuzz::SymmPerChannelQuantParams & params)51 TestSymmPerChannelQuantParams convert(const android_nn_fuzz::SymmPerChannelQuantParams& params) {
52     std::vector<float> scales = convert(params.scales());
53     const uint32_t channelDim = params.channel_dim();
54     return {.scales = std::move(scales), .channelDim = channelDim};
55 }
56 
convert(const android_nn_fuzz::Dimensions & dimensions)57 std::vector<uint32_t> convert(const android_nn_fuzz::Dimensions& dimensions) {
58     const auto& repeatedDimension = dimensions.dimension();
59     return std::vector<uint32_t>(repeatedDimension.begin(), repeatedDimension.end());
60 }
61 
convert(size_t size,const android_nn_fuzz::Buffer & buffer)62 TestBuffer convert(size_t size, const android_nn_fuzz::Buffer& buffer) {
63     if (size == 0) {
64         return TestBuffer();
65     }
66     const uint32_t randomSeed = buffer.random_seed();
67     std::default_random_engine generator{randomSeed};
68     return TestBuffer::createRandom(size % kMaxSize, &generator);
69 }
70 
convert(const android_nn_fuzz::Operand & operand)71 TestOperand convert(const android_nn_fuzz::Operand& operand) {
72     const TestOperandType type = convert(operand.type());
73     std::vector<uint32_t> dimensions = convert(operand.dimensions());
74     const float scale = operand.scale();
75     const int32_t zeroPoint = operand.zero_point();
76     const TestOperandLifeTime lifetime = convert(operand.lifetime());
77     auto channelQuant = convert(operand.channel_quant());
78 
79     const bool isIgnored = false;
80     const auto opType = static_cast<OperandType>(type);
81     const size_t size = getNonExtensionSize(opType, dimensions).value_or(0);
82     const bool makeEmpty = (lifetime == TestOperandLifeTime::NO_VALUE ||
83                             lifetime == TestOperandLifeTime::TEMPORARY_VARIABLE);
84     const size_t bufferSize = makeEmpty ? 0 : size;
85     TestBuffer data = convert(bufferSize, operand.data());
86 
87     return {.type = type,
88             .dimensions = std::move(dimensions),
89             .numberOfConsumers = 0,
90             .scale = scale,
91             .zeroPoint = zeroPoint,
92             .lifetime = lifetime,
93             .channelQuant = std::move(channelQuant),
94             .isIgnored = isIgnored,
95             .data = std::move(data)};
96 }
97 
convert(const android_nn_fuzz::Operands & operands)98 std::vector<TestOperand> convert(const android_nn_fuzz::Operands& operands) {
99     std::vector<TestOperand> testOperands;
100     testOperands.reserve(operands.operand_size());
101     const auto& repeatedOperand = operands.operand();
102     std::transform(repeatedOperand.begin(), repeatedOperand.end(), std::back_inserter(testOperands),
103                    [](const auto& operand) { return convert(operand); });
104     return testOperands;
105 }
106 
convert(const android_nn_fuzz::Indexes & indexes)107 std::vector<uint32_t> convert(const android_nn_fuzz::Indexes& indexes) {
108     const auto& repeatedIndex = indexes.index();
109     return std::vector<uint32_t>(repeatedIndex.begin(), repeatedIndex.end());
110 }
111 
convert(const android_nn_fuzz::Operation & operation)112 TestOperation convert(const android_nn_fuzz::Operation& operation) {
113     const TestOperationType type = convert(operation.type());
114     std::vector<uint32_t> inputs = convert(operation.inputs());
115     std::vector<uint32_t> outputs = convert(operation.outputs());
116     return {.type = type, .inputs = std::move(inputs), .outputs = std::move(outputs)};
117 }
118 
convert(const android_nn_fuzz::Operations & operations)119 std::vector<TestOperation> convert(const android_nn_fuzz::Operations& operations) {
120     std::vector<TestOperation> testOperations;
121     testOperations.reserve(operations.operation_size());
122     const auto& repeatedOperation = operations.operation();
123     std::transform(repeatedOperation.begin(), repeatedOperation.end(),
124                    std::back_inserter(testOperations),
125                    [](const auto& operation) { return convert(operation); });
126     return testOperations;
127 }
128 
calculateNumberOfConsumers(const std::vector<TestOperation> & operations,std::vector<TestOperand> * operands)129 void calculateNumberOfConsumers(const std::vector<TestOperation>& operations,
130                                 std::vector<TestOperand>* operands) {
131     CHECK(operands != nullptr);
132     const auto addConsumer = [operands](uint32_t operand) {
133         if (operand < operands->size()) {
134             operands->at(operand).numberOfConsumers++;
135         }
136     };
137     const auto addAllConsumers = [&addConsumer](const TestOperation& operation) {
138         std::for_each(operation.inputs.begin(), operation.inputs.end(), addConsumer);
139     };
140     std::for_each(operations.begin(), operations.end(), addAllConsumers);
141 }
142 
convert(const android_nn_fuzz::Model & model)143 TestModel convert(const android_nn_fuzz::Model& model) {
144     std::vector<TestOperand> operands = convert(model.operands());
145     std::vector<TestOperation> operations = convert(model.operations());
146     std::vector<uint32_t> inputIndexes = convert(model.input_indexes());
147     std::vector<uint32_t> outputIndexes = convert(model.output_indexes());
148     const bool isRelaxed = model.is_relaxed();
149 
150     // Calculate number of consumers.
151     calculateNumberOfConsumers(operations, &operands);
152 
153     return {.main = {.operands = std::move(operands),
154                      .operations = std::move(operations),
155                      .inputIndexes = std::move(inputIndexes),
156                      .outputIndexes = std::move(outputIndexes)},
157             .isRelaxed = isRelaxed};
158 }
159 
160 }  // anonymous namespace
161 
convertToTestModel(const android_nn_fuzz::Test & model)162 TestModel convertToTestModel(const android_nn_fuzz::Test& model) {
163     return convert(model.model());
164 }
165 
166 }  // namespace android::nn::fuzz
167