196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet/*
296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * Copyright (C) 2017 The Android Open Source Project
396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet *
496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * Licensed under the Apache License, Version 2.0 (the "License");
596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * you may not use this file except in compliance with the License.
696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * You may obtain a copy of the License at
796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet *
896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet *      http://www.apache.org/licenses/LICENSE-2.0
996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet *
1096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * Unless required by applicable law or agreed to in writing, software
1196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * distributed under the License is distributed on an "AS IS" BASIS,
1296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * See the License for the specific language governing permissions and
1496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet * limitations under the License.
1596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet */
1696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
1796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet#define LOG_TAG "ModelBuilder"
1896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
1996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet#include "ModelBuilder.h"
2096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
2183e24dc4706a5b7089881a55daf05b3924fab3b7David Gross#include "CompilationBuilder.h"
2296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet#include "Utils.h"
2396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
2496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet#include <map>
2596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet#include <utility>
2696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
2796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouilletnamespace android {
2896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouilletnamespace nn {
2996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
30c1ab6fc5e953a61811e9f25d2afff06bfa571f0eJean-Luc Brouillet// The maximum number of operands and operations that a model may have.
31c1ab6fc5e953a61811e9f25d2afff06bfa571f0eJean-Luc Brouilletconst uint32_t MAX_NUMBER_OF_OPERANDS = 0xFFFFFFFE;
32c1ab6fc5e953a61811e9f25d2afff06bfa571f0eJean-Luc Brouilletconst uint32_t MAX_NUMBER_OF_OPERATIONS = 0xFFFFFFFE;
33c1ab6fc5e953a61811e9f25d2afff06bfa571f0eJean-Luc Brouillet
3496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouilletint ModelBuilder::addOperand(const ANeuralNetworksOperandType& type) {
3596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    if (mCompletedModel) {
36544739620cd7f37d40524d2407c92042e485c73fDavid Gross        LOG(ERROR) << "ANeuralNetworksModel_addOperand can't modify after model finished";
3796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        return ANEURALNETWORKS_BAD_DATA;
3896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    }
39e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    int n = validateOperandType(type, "ANeuralNetworksModel_addOperand", true);
40e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (n != ANEURALNETWORKS_NO_ERROR) {
41e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return n;
42e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
43707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet    size_t idx = mOperands.size();
4496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    if (idx >= MAX_NUMBER_OF_OPERANDS) {
45707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet        LOG(ERROR) << "ANeuralNetworksModel_addOperand exceed max operands";
4696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        return ANEURALNETWORKS_BAD_DATA;
4796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    }
4896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    mOperands.resize(idx + 1);
49a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    auto& operand = mOperands[idx];
50a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    operand.type = static_cast<OperandType>(type.type);
51d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet    setFromIntList(&operand.dimensions, type.dimensionCount, type.dimensions);
52a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    operand.numberOfConsumers = 0;
53a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    operand.scale = type.scale;
54a5c16e4e73a34e6776a8f071ab884444c28b6893Miao Wang    operand.zeroPoint = type.zeroPoint;
55a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    operand.lifetime = OperandLifeTime::TEMPORARY_VARIABLE;
56a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    operand.location = {.poolIndex = 0, .offset = 0, .length = 0};
5796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    return ANEURALNETWORKS_NO_ERROR;
5896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet}
5996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
6096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouilletint ModelBuilder::setOperandValue(uint32_t index, const void* buffer, size_t length) {
611da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet    VLOG(MODEL) << __func__ << " for operand " << index << " size " << length;
6296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    if (index >= operandCount()) {
63707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet        LOG(ERROR) << "ANeuralNetworksModel_setOperandValue setting operand " << index << " of "
64707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet                   << operandCount();
6596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        return ANEURALNETWORKS_BAD_DATA;
6696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    }
67707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet    Operand& operand = mOperands[index];
6862cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet    if (buffer == nullptr) {
6962cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet        if (length) {
7062cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet            LOG(ERROR) << "ANeuralNetworksModel_setOperandValue buffer is nullptr but length is "
7162cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet                          "not 0";
7262cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet            return ANEURALNETWORKS_BAD_DATA;
7362cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet        }
7462cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet        operand.lifetime = OperandLifeTime::NO_VALUE;
7562cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet        // The location is unused and is set to zeros.
7662cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet        operand.location = {.poolIndex = 0,
7762cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet                            .offset = 0,
7862cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet                            .length = 0};
7962cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet    } else {
801da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        if (length > 0xFFFFFFFF) {
811da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            LOG(ERROR) << "ANeuralNetworksModel_setOperandValue value length of " << length
821da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet                       << " exceeds max size";
831da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            return ANEURALNETWORKS_BAD_DATA;
841da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        }
851da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        uint32_t valueLength = static_cast<uint32_t>(length);
8662cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet        uint32_t neededLength = sizeOfData(operand.type, operand.dimensions);
871da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        if (neededLength != valueLength) {
881da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            LOG(ERROR) << "ANeuralNetworksModel_setOperandValue setting " << valueLength
8962cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet                       << " bytes when needing " << neededLength;
9062cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet            return ANEURALNETWORKS_BAD_DATA;
9162cc2758c1c2d303861e209f26bddcf4d7564b73Jean-Luc Brouillet        }
921da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        if (valueLength <= ANEURALNETWORKS_MAX_SIZE_OF_IMMEDIATELY_COPIED_VALUES) {
931da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            uint32_t existingSize = static_cast<uint32_t>(mSmallOperandValues.size());
941da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            uint32_t extraBytes = alignBytesNeeded(existingSize, valueLength);
951da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            mSmallOperandValues.resize(existingSize + extraBytes + valueLength);
961da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            operand.lifetime = OperandLifeTime::CONSTANT_COPY;
971da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            operand.location = {
981da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet                .poolIndex = 0, .offset = existingSize + extraBytes, .length = neededLength};
991da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            memcpy(&mSmallOperandValues[operand.location.offset], buffer, valueLength);
1001da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            VLOG(MODEL) << "Copied small value to offset " << operand.location.offset;
1011da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        } else {
1021da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            VLOG(MODEL) << "Saving large value";
1031da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            operand.lifetime = OperandLifeTime::CONSTANT_REFERENCE;
1041da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            // The values for poolIndex and offset will be set when the model is finished.
1051da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            operand.location = {.poolIndex = 0, .offset = 0, .length = valueLength};
1061da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            // We keep track of the buffers. We'll allocate the shared memory only
1071da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            // once we know the total size, to avoid needless copies.
1081da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            mLargeOperandValues.push_back(LargeValue{.operandIndex = index, .buffer = buffer});
1091da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        }
1101da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet    }
1111da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet    return ANEURALNETWORKS_NO_ERROR;
1121da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet}
1131da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet
1141da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouilletint ModelBuilder::copyLargeValuesToSharedMemory() {
1151da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet    VLOG(MODEL) << __func__ << " has " << mLargeOperandValues.size() << " values.";
1161da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet    if (!mLargeOperandValues.empty()) {
1171da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        // Calculate the size of the shared memory needed for all the large values.
1181da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        // Also sets the offset for each value within the memory.
1191da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        size_t poolSize = 0;
1201da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        for (LargeValue& l: mLargeOperandValues) {
1211da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            Operand& operand = mOperands[l.operandIndex];
1221da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            nnAssert(operand.lifetime == OperandLifeTime::CONSTANT_REFERENCE);
1231da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            poolSize += alignBytesNeeded(poolSize, operand.location.length);
1241da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            operand.location.offset = poolSize;
1251da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            poolSize += operand.location.length;
1261da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        }
1271da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet
1281da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        // Allocated the shared memory.
1291da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        int n = mLargeValueMemory.create(poolSize);
1301da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        if (n != ANEURALNETWORKS_NO_ERROR) {
1311da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            return n;
1321da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        }
1331da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        uint8_t* memoryPointer = nullptr;
1341da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        n = mLargeValueMemory.getPointer(&memoryPointer);
1351da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        if (n != ANEURALNETWORKS_NO_ERROR) {
1361da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            return n;
1371da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        }
1381da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        uint32_t poolIndex = mMemories.add(&mLargeValueMemory);
1391da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        VLOG(MODEL) << "Allocated large value pool of size " << poolSize << " at index "
1401da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet                    << poolIndex;
1411da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet
1421da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        // Copy the values to this memory.
1431da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        for (LargeValue& l: mLargeOperandValues) {
1441da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            Operand& operand = mOperands[l.operandIndex];
1451da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            operand.location.poolIndex = poolIndex;
1461da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet            memcpy(memoryPointer + operand.location.offset, l.buffer, operand.location.length);
1471da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        }
14896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    }
14996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    return ANEURALNETWORKS_NO_ERROR;
15096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet}
15196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
1528b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletint ModelBuilder::setOperandValueFromMemory(uint32_t index, const Memory* memory, uint32_t offset,
1538b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet                                            size_t length) {
1541da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet    VLOG(MODEL) << __func__ << " for operand " << index << " offset " << offset << " size " << length;
1558b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    if (index >= operandCount()) {
1568b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet        LOG(ERROR) << "ANeuralNetworksModel_setOperandValueFromMemory setting operand " << index
1578b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet                   << " of " << operandCount();
1588b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet        return ANEURALNETWORKS_BAD_DATA;
1598b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    }
1608b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    Operand& operand = mOperands[index];
1618b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    uint32_t neededLength = sizeOfData(operand.type, operand.dimensions);
1628b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    if (neededLength != length) {
1638b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet        LOG(ERROR) << "ANeuralNetworksModel_setOperandValueFromMemory setting " << length
1648b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet                   << " bytes when needing " << neededLength;
1658b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet        return ANEURALNETWORKS_BAD_DATA;
1668b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    }
1678b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    // TODO validate does not exceed length of memory
168a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    operand.lifetime = OperandLifeTime::CONSTANT_REFERENCE;
169d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet    operand.location = {
170d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet                .poolIndex = mMemories.add(memory), .offset = offset, .length = neededLength};
1718b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    return ANEURALNETWORKS_NO_ERROR;
1728b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet}
1738b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet
174d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouilletint ModelBuilder::addOperation(ANeuralNetworksOperationType type, uint32_t inputCount,
175d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet                               const uint32_t* inputs, uint32_t outputCount,
176d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet                               const uint32_t* outputs) {
17796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    if (mCompletedModel) {
178544739620cd7f37d40524d2407c92042e485c73fDavid Gross        LOG(ERROR) << "ANeuralNetworksModel_addOperation can't modify after model finished";
17996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        return ANEURALNETWORKS_BAD_DATA;
18096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    }
181e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (!validCode(kNumberOfOperationTypes, kNumberOfOperationTypesOEM, type)) {
182e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        LOG(ERROR) << "ANeuralNetworksModel_addOperation invalid operations type " << type;
183e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return ANEURALNETWORKS_BAD_DATA;
184e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
185e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    int n = validateOperandList(inputCount, inputs, operandCount(),
186e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet                                "ANeuralNetworksModel_addOperation inputs");
187e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (n != ANEURALNETWORKS_NO_ERROR) {
188e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return n;
189e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
190e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    n = validateOperandList(outputCount, outputs, operandCount(),
191e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet                            "ANeuralNetworksModel_addOperation outputs");
192e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (n != ANEURALNETWORKS_NO_ERROR) {
193e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return n;
194e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
195e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet
19696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    uint32_t operationIndex = operationCount();
19796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    if (operationIndex >= MAX_NUMBER_OF_OPERATIONS) {
198707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet        LOG(ERROR) << "ANeuralNetworksModel_addOperation exceed max operations";
19996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        return ANEURALNETWORKS_BAD_DATA;
20096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    }
20196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    mOperations.resize(operationIndex + 1);
20296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    auto& entry = mOperations[operationIndex];
2037d6ac906f000f3afe418e92c0a4ae36b2ea1143eJean-Luc Brouillet    entry.type = static_cast<OperationType>(type);
20496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
205d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet    setFromIntList(&entry.inputs, inputCount, inputs);
206d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet    setFromIntList(&entry.outputs, outputCount, outputs);
207707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet    for (uint32_t i : entry.inputs) {
208707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet        mOperands[i].numberOfConsumers++;
209707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet        // TODO mOperands[i].consumers.push_back(operationIndex);
21096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    }
21196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    return ANEURALNETWORKS_NO_ERROR;
21296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet}
21396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
21466d5cb6e3a90aefc8d545f6369080ab88de9d667Jean-Luc Brouilletint ModelBuilder::identifyInputsAndOutputs(uint32_t inputCount, const uint32_t* inputs,
215d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet                                      uint32_t outputCount, const uint32_t* outputs) {
21696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    if (mCompletedModel) {
21766d5cb6e3a90aefc8d545f6369080ab88de9d667Jean-Luc Brouillet        LOG(ERROR) << "ANeuralNetworksModel_identifyInputsAndOutputs can't modify after model finished";
21896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        return ANEURALNETWORKS_BAD_DATA;
21996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    }
220e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    int n = validateOperandList(inputCount, inputs, operandCount(),
22166d5cb6e3a90aefc8d545f6369080ab88de9d667Jean-Luc Brouillet                                "ANeuralNetworksModel_identifyInputsAndOutputs inputs");
222e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (n != ANEURALNETWORKS_NO_ERROR) {
223e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return n;
224e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
225e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    n = validateOperandList(outputCount, outputs, operandCount(),
22666d5cb6e3a90aefc8d545f6369080ab88de9d667Jean-Luc Brouillet                            "ANeuralNetworksModel_identifyInputsAndOutputs outputs");
227e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (n != ANEURALNETWORKS_NO_ERROR) {
228e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return n;
229e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
230a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet
231a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    // Makes a copy of the index list, validates the arguments, and changes
232a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    // the lifetime info of the corresponding operand.
233d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet    auto setArguments = [&](std::vector<uint32_t>* indexVector, uint32_t indexCount,
234d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet                            const uint32_t* indexList, OperandLifeTime lifetime) -> bool {
235d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet        indexVector->resize(indexCount);
236d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet        for (uint32_t i = 0; i < indexCount; i++) {
237d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet            const uint32_t operandIndex = indexList[i];
238a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet            if (operandIndex >= mOperands.size()) {
23966d5cb6e3a90aefc8d545f6369080ab88de9d667Jean-Luc Brouillet                LOG(ERROR) << "ANeuralNetworksModel_identifyInputsAndOutputs Can't set input or output "
240a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet                              "to be "
241a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet                           << operandIndex << " as this exceeds the numbe of operands "
242a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet                           << mOperands.size();
243a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet                return false;
244a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet            }
245a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet            (*indexVector)[i] = operandIndex;
246a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet            Operand& operand = mOperands[operandIndex];
247a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet            if (operand.lifetime != OperandLifeTime::TEMPORARY_VARIABLE) {
24866d5cb6e3a90aefc8d545f6369080ab88de9d667Jean-Luc Brouillet                LOG(ERROR) << "ANeuralNetworksModel_identifyInputsAndOutputs Can't set operand "
249a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet                           << operandIndex
250a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet                           << " to be an input or output.  Check that it's not a constant or "
251a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet                              "already an input or output";
252a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet                return false;
253a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet            }
254a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet            operand.lifetime = lifetime;
255a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet        }
256a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet        return true;
257a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    };
258a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet
259d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet    if (!setArguments(&mInputIndexes, inputCount, inputs, OperandLifeTime::MODEL_INPUT) ||
260d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet        !setArguments(&mOutputIndexes, outputCount, outputs, OperandLifeTime::MODEL_OUTPUT)) {
261a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet        return ANEURALNETWORKS_BAD_DATA;
262a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet    }
263a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet
26496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    return ANEURALNETWORKS_NO_ERROR;
26596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet}
26696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
267544739620cd7f37d40524d2407c92042e485c73fDavid Grossint ModelBuilder::createCompilation(CompilationBuilder** compilation) {
268544739620cd7f37d40524d2407c92042e485c73fDavid Gross    if (!mCompletedModel) {
269544739620cd7f37d40524d2407c92042e485c73fDavid Gross        LOG(ERROR) << "ANeuralNetworksCompilation_create passed an unfinished model";
270544739620cd7f37d40524d2407c92042e485c73fDavid Gross        *compilation = nullptr;
271544739620cd7f37d40524d2407c92042e485c73fDavid Gross        return ANEURALNETWORKS_BAD_STATE;
272544739620cd7f37d40524d2407c92042e485c73fDavid Gross    }
273544739620cd7f37d40524d2407c92042e485c73fDavid Gross    *compilation = new CompilationBuilder(this);
274544739620cd7f37d40524d2407c92042e485c73fDavid Gross    return (*compilation ? ANEURALNETWORKS_NO_ERROR : ANEURALNETWORKS_OUT_OF_MEMORY);
27596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet}
27696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
277544739620cd7f37d40524d2407c92042e485c73fDavid Grossint ModelBuilder::finish() {
278544739620cd7f37d40524d2407c92042e485c73fDavid Gross    if (mCompletedModel) {
279544739620cd7f37d40524d2407c92042e485c73fDavid Gross        LOG(ERROR) << "ANeuralNetworksModel_finish called more than once";
280544739620cd7f37d40524d2407c92042e485c73fDavid Gross        return ANEURALNETWORKS_BAD_STATE;
28196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    }
282544739620cd7f37d40524d2407c92042e485c73fDavid Gross
2831da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet    int n = copyLargeValuesToSharedMemory();
2841da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet    if (n != ANEURALNETWORKS_NO_ERROR) {
2851da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet        return n;
2861da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet    }
2871da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet
288544739620cd7f37d40524d2407c92042e485c73fDavid Gross    // We sort the operations so that they will be in the appropriate
289544739620cd7f37d40524d2407c92042e485c73fDavid Gross    // order for a single-threaded, op at a time execution.
2901da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet    // TODO: we don't need this if we always run the partitioner.
291544739620cd7f37d40524d2407c92042e485c73fDavid Gross    sortIntoRunOrder();
292544739620cd7f37d40524d2407c92042e485c73fDavid Gross    mCompletedModel = true;
293544739620cd7f37d40524d2407c92042e485c73fDavid Gross    return ANEURALNETWORKS_NO_ERROR;
29496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet}
29596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
29696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouilletvoid ModelBuilder::sortIntoRunOrder() {
29796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    // Tracks the operations that can be executed.
29896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    std::vector<uint32_t> opsReadyToRun;
299707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet    std::vector<Operation> runOrder;
30096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
30196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    // Tracks how many inputs are needed for each operation to be ready to run.
30296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    std::multimap<uint32_t, uint32_t> operandToOperations;
30396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    std::vector<uint32_t> unknownInputCount(operationCount());
30496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    for (uint32_t operationIndex = 0; operationIndex < operationCount(); operationIndex++) {
30596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        uint32_t& count = unknownInputCount[operationIndex];
30696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        count = 0;
307707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet        for (uint32_t operandIndex : mOperations[operationIndex].inputs) {
308a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet            auto lifetime = mOperands[operandIndex].lifetime;
309a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet            if (lifetime == OperandLifeTime::TEMPORARY_VARIABLE ||
310a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet                lifetime == OperandLifeTime::MODEL_OUTPUT) {
31196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet                count++;
31296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet                operandToOperations.insert(
313d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet                            std::pair<uint32_t, uint32_t>(operandIndex, operationIndex));
31496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet            }
31596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        }
31696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        if (count == 0) {
31796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet            opsReadyToRun.push_back(operationIndex);
31896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        }
31996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    }
32096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
32196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    while (opsReadyToRun.size() > 0) {
32296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        // Execute the next op
32396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        int opIndex = opsReadyToRun.back();
32496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        opsReadyToRun.pop_back();
325707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet        const Operation& operation = mOperations[opIndex];
32696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
32796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        runOrder.push_back(mOperations[opIndex]);
32896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
329a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet        // Mark all its outputs as known.
330707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet        for (uint32_t operandIndex : operation.outputs) {
33196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet            auto range = operandToOperations.equal_range(operandIndex);
33296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet            for (auto i = range.first; i != range.second; i++) {
33396775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet                uint32_t& count = unknownInputCount[i->second];
33496775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet                if (--count == 0) {
33596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet                    opsReadyToRun.push_back(i->second);
33696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet                }
33796775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet            }
33896775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet        }
33996775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    }
34096775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet    mOperations = runOrder;
34196775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet}
34296775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
343707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletvoid ModelBuilder::setHidlModel(Model* model) const {
344707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet    model->operands = mOperands;
345707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet    model->operations = mOperations;
346707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet    model->inputIndexes = mInputIndexes;
347707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet    model->outputIndexes = mOutputIndexes;
3481da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet    model->operandValues = mSmallOperandValues;
3498b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet
3508b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    uint32_t count = mMemories.size();
3518b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    model->pools.resize(count);
3528b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    for (uint32_t i = 0; i < count; i++) {
3538b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet        model->pools[i] = mMemories[i]->getHidlMemory();
3548b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    }
35596775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet}
35696775128e3bcfdc5be51b62edc50309c83861fe8Jean-Luc Brouillet
357d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet}  // namespace nn
358d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet}  // namespace android
359