summaryrefslogtreecommitdiff
path: root/nn/common/include/LegacyUtils.h
diff options
context:
space:
mode:
Diffstat (limited to 'nn/common/include/LegacyUtils.h')
-rw-r--r--nn/common/include/LegacyUtils.h313
1 files changed, 313 insertions, 0 deletions
diff --git a/nn/common/include/LegacyUtils.h b/nn/common/include/LegacyUtils.h
new file mode 100644
index 000000000..64ee835f8
--- /dev/null
+++ b/nn/common/include/LegacyUtils.h
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// This file contains pre-canonical-types utility code and does not includes HAL
+// utilities. LegacyHalUtils.h is a superset of these utilities that includes
+// HAL utilities.
+
+#ifndef ANDROID_FRAMEWORKS_ML_NN_COMMON_LEGACY_UTILS_H
+#define ANDROID_FRAMEWORKS_ML_NN_COMMON_LEGACY_UTILS_H
+
+#include <android-base/logging.h>
+
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include "NeuralNetworks.h"
+#include "OperationResolver.h"
+
+namespace android {
+namespace nn {
+
+// The number of data types (OperandCode) defined in NeuralNetworks.h.
+const int kNumberOfDataTypes = 16;
+
+// The number of operation types (OperationCode) defined in NeuralNetworks.h.
+const int kNumberOfOperationTypes = 102;
+static_assert(kNumberOfOperationTypes == BuiltinOperationResolver::kNumberOfOperationTypes);
+
+// The number of execution preferences defined in NeuralNetworks.h.
+const int kNumberOfPreferences = 3;
+
+// The number of data types (OperandCode) defined in NeuralNetworksOEM.h.
+const int kNumberOfDataTypesOEM = 2;
+
+// The number of operation types (OperationCode) defined in NeuralNetworksOEM.h.
+const int kNumberOfOperationTypesOEM = 1;
+
+// The lowest number assigned to any OEM Code in NeuralNetworksOEM.h.
+const int kOEMCodeBase = 10000;
+
+/* IMPORTANT: if you change the following list, don't
+ * forget to update the corresponding 'tags' table in
+ * the initVlogMask() function implemented in Utils.cpp.
+ */
+enum VLogFlags { MODEL = 0, COMPILATION, EXECUTION, CPUEXE, MANAGER, DRIVER, MEMORY };
+
+#define VLOG_IS_ON(TAG) ((vLogMask & (1 << (TAG))) != 0)
+
+#define VLOG(TAG) \
+ if (LIKELY(!VLOG_IS_ON(TAG))) \
+ ; \
+ else \
+ LOG(INFO)
+
+extern int vLogMask;
+void initVLogMask();
+
+#ifdef NN_DEBUGGABLE
+#define SHOW_IF_DEBUG(msg) msg
+#else
+#define SHOW_IF_DEBUG(msg) ""
+#endif
+
+// DEPRECATED(b/118737105). Use CHECK.
+#define nnAssert(v) CHECK(v)
+
+#define NN_RETURN_IF_ERROR(expr) \
+ do { \
+ int _errorCode = (expr); \
+ if (_errorCode != ANEURALNETWORKS_NO_ERROR) { \
+ return _errorCode; \
+ } \
+ } while (0)
+
+// Make an TimeoutDuration from a duration in nanoseconds. If the value exceeds
+// the max duration, return the maximum expressible duration.
+TimeoutDuration makeTimeoutDuration(uint64_t nanoseconds);
+
+// Type to represent a deadline time point across processes.
+using Deadline = std::chrono::steady_clock::time_point;
+
+// Make an Deadline from a duration. If the sum of the current time and the
+// duration exceeds the max time, return a time point holding the maximum
+// expressible time.
+Deadline makeDeadline(TimeoutDuration duration);
+inline Deadline makeDeadline(uint64_t duration) {
+ return makeDeadline(makeTimeoutDuration(duration));
+}
+
+// Convenience function. If the duration is provided, this function creates a
+// Deadline using makeDeadline. If the duration is not provided, this function
+// returns std::nullopt.
+inline std::optional<Deadline> makeDeadline(OptionalTimeoutDuration duration) {
+ return duration.has_value() ? makeDeadline(*duration) : std::optional<Deadline>{};
+}
+inline std::optional<Deadline> makeDeadline(std::optional<uint64_t> duration) {
+ return duration.has_value() ? makeDeadline(*duration) : std::optional<Deadline>{};
+}
+
+// Returns true if the deadline has passed. Returns false if either the deadline
+// has not been exceeded or if the deadline is not present.
+bool hasDeadlinePassed(const std::optional<Deadline>& deadline);
+
+// Make an OptionalTimePoint from an optional Deadline. If the Deadline is not
+// provided, this function returns none for OptionalTimePoint.
+OptionalTimePoint makeTimePoint(const std::optional<Deadline>& deadline);
+
+// Returns true if an operand type is an extension type.
+bool isExtensionOperandType(OperandType type);
+
+// Returns true if an operation type is an extension type.
+bool isExtensionOperationType(OperationType type);
+
+// Returns the amount of space needed to store a value of the specified
+// dimensions and type. For a tensor with unspecified rank or at least one
+// unspecified dimension, returns zero.
+//
+// Aborts if the specified type is an extension type.
+// Aborts if the size would overflow the return type.
+//
+// See also TypeManager::getSizeOfData(OperandType, const std::vector<uint32_t>&).
+uint32_t nonExtensionOperandSizeOfData(OperandType type, const std::vector<uint32_t>& dimensions);
+
+// Returns the amount of space needed to store a value of the dimensions and
+// type of this operand. For a tensor with unspecified rank or at least one
+// unspecified dimension, returns zero.
+//
+// Aborts if the specified type is an extension type.
+// Aborts if the size would overflow the return type.
+//
+// See also TypeManager::getSizeOfData(const Operand&).
+inline uint32_t nonExtensionOperandSizeOfData(const Operand& operand) {
+ return nonExtensionOperandSizeOfData(operand.type, operand.dimensions);
+}
+
+// Returns the amount of space needed to store a value of the specified
+// dimensions and element size. For a tensor with unspecified rank or at least
+// one unspecified dimension, returns zero.
+//
+// Aborts if the size would overflow the return type.
+//
+// See also TypeManager::getSizeOfData(const Operand&).
+uint32_t sizeOfTensorData(uint32_t sizeOfElement, const std::vector<uint32_t>& dimensions);
+
+// Returns true if the amount of space needed to store a value of the specified
+// dimensions and element size overflows the uint32_t type.
+//
+// Aborts if the specified type is an extension type.
+//
+// See also TypeManager::sizeOfDataOverflowsUInt32(OperandType, const std::vector<uint32_t>&).
+bool nonExtensionOperandSizeOfDataOverflowsUInt32(OperandType type,
+ const std::vector<uint32_t>& dimensions);
+
+// Returns true if the amount of space needed to store a value of the specified
+// dimensions and element size overflows the uint32_t type.
+//
+// See also TypeManager::sizeOfDataOverflowsUInt32(OperandType, const std::vector<uint32_t>&).
+bool sizeOfTensorDataOverflowsUInt32(uint32_t elementSize, const std::vector<uint32_t>& dimensions);
+
+// Returns true if a non-extension operand type is a scalar type.
+//
+// Aborts if the specified type is an extension type.
+//
+// See also TypeManager::isTensorType(OperandType).
+bool nonExtensionOperandTypeIsScalar(int type);
+
+// Whether an operand of tensor type has unspecified dimensions.
+//
+// Undefined behavior if the operand type is a scalar type.
+bool tensorHasUnspecifiedDimensions(int type, const uint32_t* dim, uint32_t dimCount);
+bool tensorHasUnspecifiedDimensions(OperandType type, const std::vector<uint32_t>& dimensions);
+bool tensorHasUnspecifiedDimensions(OperandType type, const Dimensions& dimensions);
+bool tensorHasUnspecifiedDimensions(const Operand& operand);
+bool tensorHasUnspecifiedDimensions(const ANeuralNetworksOperandType* type);
+
+// Returns the number of padding bytes needed to align data of the
+// specified length. It aligns object of length:
+// 2, 3 on a 2 byte boundary,
+// 4+ on a 4 byte boundary.
+// We may want to have different alignments for tensors.
+// TODO: This is arbitrary, more a proof of concept. We need
+// to determine what this should be.
+uint32_t alignBytesNeeded(uint32_t index, size_t length);
+
+// Does a detailed LOG(INFO) of the model
+void logModelToInfo(const Model& model);
+
+inline std::string toString(uint32_t obj) {
+ return std::to_string(obj);
+}
+
+template <typename Type>
+std::string toString(const std::vector<Type>& range) {
+ std::string os = "[";
+ for (size_t i = 0; i < range.size(); ++i) {
+ os += (i == 0 ? "" : ", ") + toString(range[i]);
+ }
+ return os += "]";
+}
+
+template <typename A, typename B>
+std::string toString(const std::pair<A, B>& pair) {
+ std::ostringstream oss;
+ oss << "(" << pair.first << ", " << pair.second << ")";
+ return oss.str();
+}
+
+inline bool validCode(uint32_t codeCount, uint32_t codeCountOEM, uint32_t code) {
+ return (code < codeCount) || (code >= kOEMCodeBase && (code - kOEMCodeBase) < codeCountOEM);
+}
+
+// Validates an operand type.
+//
+// extensionOperandTypeInfo must be nullptr iff the type is not an extension type.
+//
+// If allowPartial is true, the dimensions may be underspecified.
+int validateOperandType(const ANeuralNetworksOperandType& type,
+ const Extension::OperandTypeInformation* const extensionOperandTypeInfo,
+ const char* tag, bool allowPartial);
+int validateOperandList(uint32_t count, const uint32_t* list, uint32_t operandCount,
+ const char* tag);
+
+// A set of functions to help validate models containing IF or WHILE operations.
+struct SubgraphValidationHelper {
+ // Checks if a given operand is a SUBGRAPH operand with a valid offset.
+ std::function<bool(const Operand&)> isValidSubgraphReference;
+ // Gets the input count of a subgraph referenced by a given operand.
+ std::function<uint32_t(const Operand&)> getSubgraphInputCount;
+ // Gets the output count of a subgraph referenced by a given operand.
+ std::function<uint32_t(const Operand&)> getSubgraphOutputCount;
+ // Gets the specified input operand of a subgraph referenced by a given operand.
+ std::function<const Operand*(const Operand&, uint32_t)> getSubgraphInputOperand;
+ // Gets the specified output operand of a subgraph referenced by a given operand.
+ std::function<const Operand*(const Operand&, uint32_t)> getSubgraphOutputOperand;
+ // Whether control flow operations with inner or outer input or output
+ // operands of unknown size are allowed.
+ bool allowControlFlowOperationWithOperandOfUnknownSize;
+};
+
+// Returns ANEURALNETWORKS_NO_ERROR if the corresponding operation is defined and can handle the
+// provided operand types in the given HAL version, otherwise returns ANEURALNETWORKS_BAD_DATA.
+// The last argument is only used for validating IF and WHILE operations.
+int validateOperation(ANeuralNetworksOperationType opType, uint32_t inputCount,
+ const uint32_t* inputIndexes, uint32_t outputCount,
+ const uint32_t* outputIndexes, const std::vector<Operand>& operands,
+ HalVersion halVersion, const SubgraphValidationHelper& helper);
+
+inline size_t getSizeFromInts(int lower, int higher) {
+ return (uint32_t)(lower) + ((uint64_t)(uint32_t)(higher) << 32);
+}
+
+// Convert ANEURALNETWORKS_* result code to ErrorStatus.
+// Not guaranteed to be a 1-to-1 mapping.
+ErrorStatus convertResultCodeToErrorStatus(int resultCode);
+
+// Convert ErrorStatus to ANEURALNETWORKS_* result code.
+// Not guaranteed to be a 1-to-1 mapping.
+int convertErrorStatusToResultCode(ErrorStatus status);
+
+// Convert execution results to runtime format. Additionally checks that the
+// returned results abide by the HAL specification, and logs an error if the
+// result violates the specification.
+std::tuple<int, std::vector<OutputShape>, Timing> getExecutionResult(
+ ErrorStatus status, std::vector<OutputShape> outputShapes, Timing timing);
+
+constexpr Priority convertToCanonicalPriority(int32_t priority) {
+ switch (priority) {
+ case ANEURALNETWORKS_PRIORITY_LOW:
+ return Priority::LOW;
+ case ANEURALNETWORKS_PRIORITY_MEDIUM:
+ return Priority::MEDIUM;
+ case ANEURALNETWORKS_PRIORITY_HIGH:
+ return Priority::HIGH;
+ }
+ LOG(FATAL) << "unrecognized priority: " << priority;
+ return {};
+}
+
+// The function syncWait() has the same semantics as the system function
+// ::sync_wait(), except that the syncWait() return value is semantically
+// richer. The timeout parameter is in msecs.
+enum class FenceState {
+ ACTIVE, // fence has not been signaled
+ SIGNALED, // fence has been signaled
+ ERROR, // fence has been placed in the error state
+ UNKNOWN, // either bad argument passed to syncWait(), or internal error
+};
+FenceState syncWait(int fd, int timeout);
+
+#ifdef NN_DEBUGGABLE
+uint32_t getProp(const char* str, uint32_t defaultValue = 0);
+#endif // NN_DEBUGGABLE
+
+} // namespace nn
+} // namespace android
+
+#endif // ANDROID_FRAMEWORKS_ML_NN_COMMON_LEGACY_UTILS_H