/* * Copyright (c) 2020-2022 Arm Limited. * * SPDX-License-Identifier: Apache-2.0 * * 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 * * 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. */ #pragma once #include #include #include #include #include /* *The following undef are necessary to avoid clash with macros in GNU C Library * if removed the following warning/error are produced: * * In the GNU C Library, "major" ("minor") is defined * by . For historical compatibility, it is * currently defined by as well, but we plan to * remove this soon. To use "major" ("minor"), include * directly. If you did not intend to use a system-defined macro * "major" ("minor"), you should undefine it after including . */ #undef major #undef minor namespace EthosU { class Exception : public std::exception { public: Exception(const char *msg); virtual ~Exception() throw(); virtual const char *what() const throw(); private: std::string msg; }; /** * Sematic Version : major.minor.patch */ class SemanticVersion { public: SemanticVersion(uint32_t _major = 0, uint32_t _minor = 0, uint32_t _patch = 0) : major(_major), minor(_minor), patch(_patch){}; bool operator==(const SemanticVersion &other); bool operator<(const SemanticVersion &other); bool operator<=(const SemanticVersion &other); bool operator!=(const SemanticVersion &other); bool operator>(const SemanticVersion &other); bool operator>=(const SemanticVersion &other); uint32_t major; uint32_t minor; uint32_t patch; }; std::ostream &operator<<(std::ostream &out, const SemanticVersion &v); /* * Hardware Identifier * @versionStatus: Version status * @version: Version revision * @product: Product revision * @architecture: Architecture revison */ struct HardwareId { public: HardwareId(uint32_t _versionStatus, const SemanticVersion &_version, const SemanticVersion &_product, const SemanticVersion &_architecture) : versionStatus(_versionStatus), version(_version), product(_product), architecture(_architecture) {} uint32_t versionStatus; SemanticVersion version; SemanticVersion product; SemanticVersion architecture; }; /* * Hardware Configuration * @macsPerClockCycle: MACs per clock cycle * @cmdStreamVersion: NPU command stream version * @customDma: Custom DMA enabled */ struct HardwareConfiguration { public: HardwareConfiguration(uint32_t _macsPerClockCycle, uint32_t _cmdStreamVersion, bool _customDma) : macsPerClockCycle(_macsPerClockCycle), cmdStreamVersion(_cmdStreamVersion), customDma(_customDma) {} uint32_t macsPerClockCycle; uint32_t cmdStreamVersion; bool customDma; }; /** * Device capabilities * @hwId: Hardware * @driver: Driver revision * @hwCfg Hardware configuration */ class Capabilities { public: Capabilities(const HardwareId &_hwId, const HardwareConfiguration &_hwCfg, const SemanticVersion &_driver) : hwId(_hwId), hwCfg(_hwCfg), driver(_driver) {} HardwareId hwId; HardwareConfiguration hwCfg; SemanticVersion driver; }; class Device { public: Device(const char *device = "/dev/ethosu0"); virtual ~Device() noexcept(false); int ioctl(unsigned long cmd, void *data = nullptr) const; Capabilities capabilities() const; private: int fd; }; class Buffer { public: Buffer(const Device &device, const size_t capacity); virtual ~Buffer() noexcept(false); size_t capacity() const; void clear() const; char *data() const; void resize(size_t size, size_t offset = 0) const; size_t offset() const; size_t size() const; int getFd() const; private: int fd; char *dataPtr; const size_t dataCapacity; }; class Network { public: Network(const Device &device, std::shared_ptr &buffer); Network(const Device &device, const unsigned index); virtual ~Network() noexcept(false); int ioctl(unsigned long cmd, void *data = nullptr); std::shared_ptr getBuffer(); const std::vector &getIfmDims() const; size_t getIfmSize() const; const std::vector &getOfmDims() const; size_t getOfmSize() const; private: void collectNetworkInfo(); int fd; std::shared_ptr buffer; std::vector ifmDims; std::vector ofmDims; }; class Inference { public: template Inference(const std::shared_ptr &network, const T &ifmBegin, const T &ifmEnd, const T &ofmBegin, const T &ofmEnd) : network(network) { std::copy(ifmBegin, ifmEnd, std::back_inserter(ifmBuffers)); std::copy(ofmBegin, ofmEnd, std::back_inserter(ofmBuffers)); std::vector counterConfigs = initializeCounterConfig(); create(counterConfigs, false); } template Inference(const std::shared_ptr &network, const T &ifmBegin, const T &ifmEnd, const T &ofmBegin, const T &ofmEnd, const U &counters, bool enableCycleCounter) : network(network) { std::copy(ifmBegin, ifmEnd, std::back_inserter(ifmBuffers)); std::copy(ofmBegin, ofmEnd, std::back_inserter(ofmBuffers)); std::vector counterConfigs = initializeCounterConfig(); if (counters.size() > counterConfigs.size()) throw EthosU::Exception("PMU Counters argument to large."); std::copy(counters.begin(), counters.end(), counterConfigs.begin()); create(counterConfigs, enableCycleCounter); } virtual ~Inference() noexcept(false); int wait(int64_t timeoutNanos = -1) const; const std::vector getPmuCounters() const; uint64_t getCycleCounter() const; bool failed() const; int getFd() const; const std::shared_ptr getNetwork() const; std::vector> &getIfmBuffers(); std::vector> &getOfmBuffers(); static uint32_t getMaxPmuEventCounters(); private: void create(std::vector &counterConfigs, bool enableCycleCounter); std::vector initializeCounterConfig(); int fd; const std::shared_ptr network; std::vector> ifmBuffers; std::vector> ofmBuffers; }; } // namespace EthosU