```
NPU_SystemService/ Root directory
|-- src/
-| |-- core/ Source files for NPU Engine
-| |-- host/ Source files for Host Lib (not used currently)
+| |-- core/ Source files for NPU Engine Core
+| |-- host/ Source files for User APIs
|-- include/
| |-- common/ Definitions for Common Data
| |-- host/ Definitions for User APIs
#ifndef NPU_TYPEDEF_H__
#define NPU_TYPEDEF_H__
+#include <stdint.h>
+
#define DEVICETYPE_NPU (0x10000) /** SR-NPU 2019, RefineDet */
#define DEVICETYPE_ASR (0x20000) /** SR-ASR-IP 2019, Based on SRP */
#define DEVICETYPE_MASK (0xFFFF0000)
/**
+ * @brief Represents an "opened" single NPU device (e.g., TRIV2).
+ */
+typedef void *npudev_h;
+
+/**
* @brief Description of npu device types.
*/
typedef enum {
DATA_TYPE_MODEL, /**< use the same data type specified in model metadata */
} data_type;
+/* NNstreamer/GStreamer supports up to 16 bufs */
+#define NPU_TENSOR_CARDINALITY_MAX (16)
+
+/** @brief type of memory represented by the buffer */
+typedef enum {
+ BUFFER_FILE = 0, /**< buffer is a file */
+ BUFFER_MAPPED, /**< buffer is a memory-mapped ptr */
+ BUFFER_DMABUF, /**< buffer is a dmabuf fd, representing contiguous memory */
+ BUFFER_UNDEFINED /**< buffer type is undefined */
+} buffer_types;
+
+/**
+ * @brief Various kinds of buffer supported for input/output/model
+ * @note In case of BUFFER_FILE, 'size' indicates a file size.
+ */
+typedef struct {
+ union {
+ struct { /** BUFFER_FILE */
+ const char *filepath; /**< The filepath for the data */
+ };
+ struct { /** BUFFER_MAPPED/DMABUF */
+ void *addr; /**< Mapped address of the buffer */
+ struct { /** BUFFER_DMABUF only */
+ int dmabuf; /**< The dma-buf fd handle of the memory allocated */
+ uint64_t offset; /**< Offset to be applied to the base memory address */
+ };
+ };
+ };
+ uint64_t size; /**< The size of the buffer in bytes */
+ buffer_types type; /**< Type of memory in this buffer */
+} generic_buffer;
+
+/**
+ * @brief Multiple buffers to contain dis-contiguous tensor buffers.
+ * Each generic buffer can have different buffer types.
+ */
+typedef struct {
+ uint32_t num_buffers; /**< The number of tensors in this "buffer" */
+ generic_buffer bufs[NPU_TENSOR_CARDINALITY_MAX]; /**< Buffer struct for each tensor */
+} generic_buffers;
+
+/**
+ * @brief NPU input/output buffers are compatible with arbitrary other/tensors.
+ */
+typedef generic_buffers input_buffers;
+typedef generic_buffers output_buffers;
+
+/**
+ * @brief Description of tensor data info.
+ */
+typedef struct {
+ data_layout layout;
+ data_type type;
+} tensor_data_info;
+
+/**
+ * @brief Each tensor may have different data layout and type
+ */
+typedef struct {
+ uint32_t num_info;
+ tensor_data_info info[NPU_TENSOR_CARDINALITY_MAX];
+} tensors_data_info;
+
+/**
+ * @brief Receives NPU results.
+ * @param[in] output NPU results. callback() should free this.
+ * @param[in] sequence The sequence number returned with runNPU_async.
+ * @param[in] data The data given as a parameter to the runNPU_async call.
+ *
+ * @detail The callback function has the responsibility to free the given
+ * output buffer (output).
+ *
+ * Values of sequence grow monotonically with a given model.
+ * Therefore, if a sequence value is skipped, it means that
+ * the inference request has been preemptied.
+ *
+ * The API implementation should be aware of bottlenecks.
+ * Be prepared to handle if this callback takes too much time.
+ * Approach 1: timeout.
+ * Approach 2: thread pooling for callback invocation.
+ * Approach 3: 1 + 2.
+ */
+typedef void (*npuOutputNotify) (output_buffers *output, uint64_t sequence,
+ void *data);
+
+typedef enum {
+ NPUASYNC_DROP_OLD, /**< If there is an unprocessed input data
+ in the double buffer, overwrite it */
+ NPUASYNC_WAIT, /**< If there is an unprocessed input data in
+ the double buffer, wait for it processed */
+ NPUASYNC_DROP_NEW, /**< If there is an unprocessed input data in
+ the double buffer, return error "RETRY" */
+} npu_async_mode;
+
/**
* @brief Description of priority for NPU inference requests
* @details NPU Engine currently supports three priorities; low, mid, and high.
} npu_notimode;
/**
+ * @brief Constraints for NPU inferences (per model)
+ */
+typedef struct {
+ uint32_t timeout_ms;
+ npu_priority priority;
+ npu_notimode notimode;
+} npuConstraint;
+
+static const uint32_t default_timeout = 3000;
+static const npu_priority default_priority = NPU_PRIORITY_MID;
+static const npu_notimode default_notimode = NPU_INTERRUPT;
+
+/**
* @brief Description of npu device status
*/
typedef enum {
SMODEL_OPS_END,
} model_opmode;
+/** NPU Statistics (only for real-device envionment) */
+
/**
* @brief Description of npu app (per device open) status
*/
npu_stat_task *stat;
} npu_stat_tasks;
+/** NPU Profiling (both for emulated/real-device envionment) */
+
+#define NPU_OPNAME_MAX (32)
+
+typedef struct {
+ char name[NPU_OPNAME_MAX];
+
+ uint32_t latency_ms;
+ uint64_t latency_cycles;
+
+ uint64_t mem_read_bytes;
+ uint64_t mem_write_bytes;
+ /* TBD */
+} npu_profile_layer;
+
+typedef struct {
+ uint32_t num_layers;
+ npu_profile_layer *layers;
+} npu_profile;
+
#endif /* NPU_TYPEDEF_H__ */
extern "C" {
#endif
-/* NNstreamer/GStreamer supports up to 16 bufs */
-#define NPU_TENSOR_CARDINALITY_MAX (16)
-
-/** @brief type of memory represented by the buffer */
-typedef enum {
- BUFFER_FILE = 0, /**< buffer is a file */
- BUFFER_MAPPED, /**< buffer is a memory-mapped ptr */
- BUFFER_DMABUF, /**< buffer is a dmabuf fd, representing contiguous memory */
- BUFFER_UNDEFINED /**< buffer type is undefined */
-} buffer_types;
-
-/**
- * @brief Various kinds of buffer supported for input/output/model
- * @note In case of BUFFER_FILE, 'size' indicates a file size.
- */
-typedef struct {
- union {
- struct { /** BUFFER_FILE */
- const char *filepath; /**< The filepath for the data */
- };
- struct { /** BUFFER_MAPPED/DMABUF */
- void *addr; /**< Mapped address of the buffer */
- struct { /** BUFFER_DMABUF only */
- int dmabuf; /**< The dma-buf fd handle of the memory allocated */
- uint64_t offset; /**< Offset to be applied to the base memory address */
- };
- };
- };
- uint64_t size; /**< The size of the buffer in bytes */
- buffer_types type; /**< Type of memory in this buffer */
-} generic_buffer;
-
-/**
- * @brief Multiple buffers to contain dis-contiguous tensor buffers.
- * Each generic buffer can have different buffer types.
- */
-typedef struct {
- uint32_t num_buffers; /**< The number of tensors in this "buffer" */
- generic_buffer bufs[NPU_TENSOR_CARDINALITY_MAX]; /**< Buffer struct for each tensor */
-} generic_buffers;
-
-/**
- * @brief NPU input/output buffers are compatible with arbitrary other/tensors.
- */
-typedef generic_buffers input_buffers;
-typedef generic_buffers output_buffers;
-
-/**
- * @brief Description of tensor data info.
- */
-typedef struct {
- data_layout layout;
- data_type type;
-} tensor_data_info;
-
-/**
- * @brief Each tensor may have different data layout and type
- */
-typedef struct {
- uint32_t num_info;
- tensor_data_info info[NPU_TENSOR_CARDINALITY_MAX];
-} tensors_data_info;
-
-/**
- * @brief Represents an "opened" single NPU device (e.g., TRIV2).
- */
-typedef void *npudev_h;
-
/**
* @brief Get npu-engine libraray version
* @param[out] major major version
tensors_data_info *info_in, tensors_data_info *info_out);
/**
- * @brief Constraints for NPU inferences (per model)
- */
-typedef struct {
- uint32_t timeout_ms;
- npu_priority priority;
- npu_notimode notimode;
-} npuConstraint;
-
-static const uint32_t default_timeout = 3000;
-static const npu_priority default_priority = NPU_PRIORITY_MID;
-static const npu_notimode default_notimode = NPU_INTERRUPT;
-
-/**
* @brief [OPTIONAL] Set the inference constraint for next NPU inferences
* @param[in] dev The NPU device handle
* @param[in] modelid The target model id
output_buffers *output);
/**
- * @brief Receives NPU results.
- * @param[in] output NPU results. callback() should free this.
- * @param[in] sequence The sequence number returned with runNPU_async.
- * @param[in] data The data given as a parameter to the runNPU_async call.
- *
- * @detail The callback function has the responsibility to free the given
- * output buffer (output).
- *
- * Values of sequence grow monotonically with a given model.
- * Therefore, if a sequence value is skipped, it means that
- * the inference request has been preemptied.
- *
- * The API implementation should be aware of bottlenecks.
- * Be prepared to handle if this callback takes too much time.
- * Approach 1: timeout.
- * Approach 2: thread pooling for callback invocation.
- * Approach 3: 1 + 2.
- */
-typedef void (*npuOutputNotify) (output_buffers *output, uint64_t sequence,
- void *data);
-
-/**
* @brief Let NPU accept input frames from its internal source continuously
* @param[in] dev The NPU device handle
* @param[in] modelid The model to be inferred.
*/
int stopNPU_internalInput(npudev_h dev, int id);
-typedef enum {
- NPUASYNC_DROP_OLD, /**< If there is an unprocessed input data
- in the double buffer, overwrite it */
- NPUASYNC_WAIT, /**< If there is an unprocessed input data in
- the double buffer, wait for it processed */
- NPUASYNC_DROP_NEW, /**< If there is an unprocessed input data in
- the double buffer, return error "RETRY" */
-} npu_async_mode;
-
/**
* @brief Invoke NPU inference. Unblocking call.
* @param[in] dev The NPU device handle
*/
int cleanNPU_genericBuffers (npudev_h dev, generic_buffers * buffers);
-/** NPU Profiling (both for emulated/real-device envionment) */
-
-#define NPU_OPNAME_MAX (32)
-
-typedef struct {
- char name[NPU_OPNAME_MAX];
-
- uint32_t latency_ms;
- uint64_t latency_cycles;
-
- uint64_t mem_read_bytes;
- uint64_t mem_write_bytes;
- /* TBD */
-} npu_profile_layer;
-
-typedef struct {
- uint32_t num_layers;
- npu_profile_layer *layers;
-} npu_profile;
-
/**
* @brief Get the profile information from NPU
* @param[in] dev NPU device handle
#ifndef NE_COMM_H__
#define NE_COMM_H__
-#include <libnpuhost.h>
+#include <typedef.h>
#include <functional>
/** @brief the binded data manipulation function */
* @bug No known bugs except for NYI items
*/
-#include <libnpuhost.h>
-
#include "CommPlugin.h"
#include <cstring>
* Copyright (C) 2020 Dongju Chae <dongju.chae@samsung.com>
*/
/**
- * @file ne-host-handler.cc
+ * @file ne-handler.cc
* @date 03 Apr 2020
- * @brief Implementation of APIs to access NPU from Host
+ * @brief Impelemetation of NPU Engine entrypoint that handles APIs from host
* @see https://code.sec.samsung.net/confluence/display/ODLC/2020+Overall+Software+Stack
* @author Dongju Chae <dongju.chae@samsung.com>
* @bug No known bugs except for NYI items
#include "ne-handler.h"
#include "ne-data.h"
-#include <libnpuhost.h>
#include <npubinfmt.h>
#include <NPUdrvAPI.h>
#include <CommPlugin.h>
#define TAG _N2
-#define INIT_HOST_HANDLER(handler, dev) \
- Device *tdev = static_cast <Device *> (dev); \
- if (tdev == nullptr) return -EINVAL; \
- HostHandler *handler = tdev->getHostHandler (); \
- if (handler == nullptr) return -EINVAL;
-
-/** just for backward-compatability */
-npudev_h HostHandler::latest_dev_ = nullptr;
-
-/** implement libnpuhost APIs */
-
-/**
- * @brief Get npu-engine libraray version
- * @param[out] major major version
- * @param[out] minor minor version
- * @param[out] extra extra version
- */
-void getVersion (uint32_t *major, uint32_t *minor, uint32_t *extra)
-{
- if (major != nullptr)
- *major = VER_NE_MAJOR;
- if (minor != nullptr)
- *minor = VER_NE_MINOR;
- if (extra != nullptr)
- *extra = VER_NE_EXTRA;
-}
-
-/**
- * @brief Returns the number of available NPU devices.
- * @return @c The number of NPU devices.
- * @retval 0 if no NPU devices available. if positive (number of NPUs) if NPU devices available. otherwise, a negative error value.
- * @note the caller should call putNPUdevice() to release the device handle
- */
-int getnumNPUdeviceByType (dev_type type)
-{
- return HostHandler::getNumDevices (type);
-}
-
-/**
- * @brief Returns the handle of the chosen NPU devices.
- * @param[out] dev The NPU device handle
- * @param[in] id The NPU id to get the handle. 0 <= id < getnumNPUdeviceByType().
- * @return @c 0 if no error. otherwise a negative error value
- * @note the caller should call putNPUdevice() to release the device handle
- */
-int getNPUdeviceByType (npudev_h *dev, dev_type type, uint32_t id)
-{
- return HostHandler::getDevice (dev, type, id);
-}
-
-/**
- * @brief release the NPU device instance obtained by getDevice ()
- * @param[in] dev the NPU device handle
- */
-void putNPUdevice (npudev_h dev)
-{
- if (dev != nullptr)
- delete static_cast<Device *> (dev);
-}
-
-/**
- * @brief Get the driver API level that npu-engine library assumes (compiled)
- * @param[out] level driver API level
- * @note when this API level is lower than actual driver's one,
- * some operations might be not working.
- */
-void getDriverAPILevel (uint32_t *level)
-{
- if (level != nullptr)
- *level = DriverAPI::getCompiledAPILevel ();
-}
-
-/**
- * @brief Get the driver API level of opened NPU device
- * @param[in] dev the NPU device handle
- * @param[out] level driver API level
- * @return 0 if no error, otherwise a negative errno
- */
-int getNPU_driverAPILevel (npudev_h dev, uint32_t *level)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- if (level == nullptr)
- return -EINVAL;
-
- return host_handler->getAPILevel (level);
-}
-
-/**
- * @brief Get the TOPS of the opened NPU device
- * @param[in] dev the NPU device handle
- * @param[out] tops npu tops
- * @return 0 if no error, otherwise a negative errno
- * @note this does not support for emulated devices
- */
-int getNPU_tops (npudev_h dev, uint32_t *tops)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- if (tops == nullptr)
- return -EINVAL;
-
- return host_handler->getTops (tops);
-}
-
-/**
- * @brief Get the profile information from NPU
- * @param[in] dev The NPU device handle
- * @param[in] task_id The identifier for each inference
- * @param[out] profile The profile instance
- * @return 0 if no error, otherwise a negative errno.
- */
-int getNPU_profile (npudev_h dev, int task_id, npu_profile *profile)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->getProfile (task_id, profile);
-}
-
-/**
- * @brief Free the profile instance obtained by getNPU_profile().
- * @param[in] profile The profile instance
- */
-void putNPU_profile (npu_profile *profile)
-{
- if (profile != nullptr)
- free (profile);
-}
-
-/**
- * @brief get the stats for the latest apps of the target device
- * @param[in] dev The NPU device handle
- * @param[out] stat The instance of app stat
- * @note The caller has the responsibility to free the resources.
- * This API is not working on the emulated envionment.
- */
-int getNPU_statApps (npudev_h dev, npu_stat_apps *stat)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
-#ifdef ENABLE_EMUL
- logwarn (TAG, "we don't support statistics for the emulated envionment");
- if (stat) {
- stat->num = 0;
- stat->stat = nullptr;
- }
- return 0;
-#else
- return host_handler->getStatApps (stat);
-#endif
-}
-
-/**
- * @brief Free the stat instance obtained by getNPU_statApps().
- * @param[in] stat Stat instance
- */
-void putNPU_statApps (npu_stat_apps *stat)
-{
- if (stat) {
- delete [] stat->stat;
- stat->num = 0;
- }
-}
-
-/**
- * @brief get the stats for the latest tasks of the target app
- * @param[in] dev The NPU device handle
- * @param[in] appid The identifier of target app
- * @param[out] stat The instance of task stat
- * @note The caller has the responsibility to free the resources.
- * This API is not working on the emulated envionment.
- */
-int getNPU_statTasks (npudev_h dev, int appid, npu_stat_tasks *stat)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
-#ifdef ENABLE_EMUL
- logwarn (TAG, "we don't support statistics for the emulated envionment");
- if (stat) {
- stat->num = 0;
- stat->stat = nullptr;
- }
- return 0;
-#else
- return host_handler->getStatTasks (appid, stat);
-#endif
-}
-
-/**
- * @brief Free the stat instance obtained by getNPU_statTasks().
- * @param[in] stat Stat instance
- */
-void putNPU_statTasks (npu_stat_tasks *stat)
-{
- if (stat) {
- delete [] stat->stat;
- stat->num = 0;
- }
-}
-
-/**
- * @brief Send the NN model to NPU.
- * @param[in] dev The NPU device handle
- * @param[in] modelfile The filepath to the compiled NPU NN model in any buffer_type
- * @param[out] modelid The modelid allocated for this instance of NN model.
- * @return @c 0 if no error. otherwise a negative error value
- *
- * @detail For ASR devices, which do not accept models, but have models
- * embedded in devices, you do not need to call register and
- * register calls for ASR are ignored.
- *
- * @todo Add a variation: in-memory model register.
- */
-int registerNPUmodel (npudev_h dev, generic_buffer *modelfile, uint32_t *modelid)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->registerModel (modelfile, modelid);
-}
-
-/**
- * @brief Remove the NN model from NPU
- * @param[in] dev The NPU device handle
- * @param[in] modelid The model to be removed from the NPU.
- * @return @c 0 if no error. otherwise a negative error value
- * @detail This may incur some latency with memory compatcion.
- */
-int unregisterNPUmodel(npudev_h dev, uint32_t modelid)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->unregisterModel (modelid);
-}
-
-/**
- * @brief Remove all NN models from NPU
- * @param[in] dev The NPU device handle
- * @return @c 0 if no error. otherwise a negative error value
- */
-int unregisterNPUmodel_all(npudev_h dev)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->unregisterModels ();
-}
-
-/**
- * @brief [OPTIONAL] Set the data layout for input/output tensors
- * @param[in] dev The NPU device handle
- * @param[in] modelid The ID of model whose layouts are set
- * @param[in] info_in the layout/type info for input tensors
- * @param[in] info_out the layout/type info for output tensors
- * @return @c 0 if no error. otherwise a negative error value
- * @note if this function is not called, default layout/type will be used.
- */
-int setNPU_dataInfo(npudev_h dev, uint32_t modelid,
- tensors_data_info *info_in, tensors_data_info *info_out)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->setDataInfo (modelid, info_in, info_out);
-}
-
-/**
- * @brief [OPTIONAL] Set the inference constraint for next NPU inferences
- * @param[in] dev The NPU device handle
- * @param[in] modelid The target model id
- * @param[in] constraint inference constraint (e.g., timeout, priority)
- * @return @c 0 if no error. otherwise a negative error value
- * @note If this function is not called, default values are used.
- */
-int setNPU_constraint(npudev_h dev, uint32_t modelid, npuConstraint constraint)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->setConstraint (modelid, constraint);
-}
-
-/**
- * @brief Execute inference. Wait (block) until the output is available.
- * @param[in] dev The NPU device handle
- * @param[in] modelid The model to be inferred.
- * @param[in] input The input data to be inferred.
- * @param[out] output The output result. The caller MUST allocate appropriately before calling this.
- * @return @c 0 if no error. otherwise a negative error value
- *
- * @detail This is a syntactic sugar of runNPU_async().
- * CAUTION: There is a memcpy for the output buffer.
- */
-int runNPU_sync(npudev_h dev, uint32_t modelid, const input_buffers *input,
- output_buffers *output)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->runSync (modelid, input, output);
-}
-
-/**
- * @brief Invoke NPU inference. Unblocking call.
- * @param[in] dev The NPU device handle
- * @param[in] modelid The model to be inferred.
- * @param[in] input The input data to be inferred.
- * @param[in] cb The output buffer handler.
- * @param[out] sequence The sequence number returned with runNPU_async.
- * @param[in] data The data given as a parameter to the runNPU_async call.
- * @param[in] mode Configures how this operation works.
- * @return @c 0 if no error. otherwise a negative error value
- */
-int runNPU_async(npudev_h dev, uint32_t modelid, const input_buffers *input,
- npuOutputNotify cb, uint64_t *sequence, void *data,
- npu_async_mode mode)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->runAsync (modelid, input, cb, data, mode, sequence);
-}
-
-/**
- * @brief Let NPU accept input frames from its internal source continuously
- * @param[in] dev The NPU device handle
- * @param[in] modelid The model to be inferred.
- * @param[in] opmode NPU has different opmode with auto-inputs. Choose one.
- * @param[in] hw_dev The target device feeding input data
- * @return @c 0 if no error. otherwise a negative error value
- */
-int runNPU_internalInput(npudev_h dev, uint32_t modelid, npu_input_opmode opmode,
- const char * hw_dev)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->runInternal (modelid, opmode, hw_dev);
-}
-
-/**
- * @brief Stop the request with the given id
- * @param[in] dev The NPU device handle
- * @param[in] id The request id
- * @return @c 0 if no error. otherwise a negative error value
- */
-int stopNPU_internalInput(npudev_h dev, int id)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->stopInternal (id);
-}
-
-/**
- * @brief Allocate a generic buffer with the requested buffer type.
- * @param[in] dev The NPU device handle
- * @param[in/out] Buffer the buffer pointer where memory is allocated.
- * @return 0 if no error, otherwise a negative errno.
- */
-int allocNPU_genericBuffer (npudev_h dev, generic_buffer * buffer)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->allocGenericBuffer (buffer);
-}
-
-/**
- * @brief Free the generic buffer and remove the address mapping
- * @param[in] dev The NPU device handle
- * @param[in] buffer the model buffer
- * @return 0 if no error, otherwise a negative errno.
- */
-int cleanNPU_genericBuffer (npudev_h dev, generic_buffer * buffer)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->deallocGenericBuffer (buffer);
-}
-
-/**
- * @brief Allocate generic buffers, which have multiple instances of generic_buffer
- * @param[in] dev The NPU device handle
- * @param[in/out] buffers generic buffers.
- * @return 0 if no error, otherwise a negative errno.
- * @note it reuses allocGenericBuffer().
- */
-int allocNPU_genericBuffers (npudev_h dev, generic_buffers * buffers)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->allocGenericBuffer (buffers);
-}
-
-/**
- * @brief Free generic buffers allocated by allocGenericBuffers().
- * @param[in] dev The NPU device handle
- * @param[in/out] buffers generic buffers.
- * @note it reuses cleanGenericbuffer().
- * @return 0 if no error, otherwise a negative errno.
- */
-int cleanNPU_genericBuffers (npudev_h dev, generic_buffers * buffers)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->deallocGenericBuffer (buffers);
-}
-
-/**
- * @brief alias of allocNPU_genericBuffer for model buffer
- */
-int allocNPU_modelBuffer (npudev_h dev, generic_buffer * model)
-{
- return allocNPU_genericBuffer (dev, model);
-}
-
-/**
- * @brief alias of cleanNPU_genericBuffer for model buffer
- */
-int cleanNPU_modelBuffer (npudev_h dev, generic_buffer * model)
-{
- return cleanNPU_genericBuffer (dev, model);
-}
-
-/**
- * @brief alias of allocNPU_genericBuffer for input buffer
- */
-int allocNPU_inputBuffer (npudev_h dev, generic_buffer * input)
-{
- return allocNPU_genericBuffer (dev, input);
-}
-
-/**
- * @brief alias of cleanNPU_genericBuffer for input buffer
- */
-int cleanNPU_inputBuffer (npudev_h dev, generic_buffer * input)
-{
- return cleanNPU_genericBuffer (dev, input);
-}
-
-/**
- * @brief alias of allocNPU_genericBuffers for input buffers
- */
-int allocNPU_inputBuffers (npudev_h dev, input_buffers * input)
-{
- return allocNPU_genericBuffers (dev, input);
-}
-
-/**
- * @brief alias of cleanNPU_genericBuffers for input buffers
- */
-int cleanNPU_inputBuffers (npudev_h dev, input_buffers * input)
-{
- return cleanNPU_genericBuffers (dev, input);
-}
-
-/**
- * @brief get the current memory status for the given device
- * @param[in] dev The NPU device handle
- * @param[out] alloc_total The size of allocated memory until now
- * @param[out] free_total The size of freed memory until now
- * @return @c 0 if no error. otherwise a negatice error value
- */
-int getNPU_memoryStatus(npudev_h dev, size_t *alloc_total, size_t *free_total)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->getMemoryStatus (alloc_total, free_total);
-}
-
-/**
- * @brief Get the current device status to be used
- * @param[in] dev The NPU device handle
- * @param[out] status the device status
- * @param[out] num_requests the number of running requests (or pending)
- * @return 0 if no error, otherwise a negative errno.
- */
-int getNPU_deviceStatus(npudev_h dev, npu_status *status, uint32_t *num_requests)
-{
- INIT_HOST_HANDLER (host_handler, dev);
-
- return host_handler->getDeviceStatus (status, num_requests);
-}
-
-/**
- * @brief Get metadata for NPU model
- * @param[in] model The path of model binary file
- * @param[in] need_extra whether you want to extract the extra data in metadata
- * @return the metadata structure to be filled if no error, otherwise nullptr
- *
- * @note For most npu-engine users, the extra data is not useful because it will be
- * used for second-party users (e.g., compiler, simulator).
- * Also, the caller needs to free the metadata.
- *
- * @note the caller needs to free the metadata
- */
-npubin_meta * getNPUmodel_metadata (const char *model, bool need_extra)
-{
- npubin_meta *meta;
- FILE *fp;
- size_t ret;
-
- if (!model)
- return nullptr;
-
- fp = fopen (model, "rb");
- if (!fp) {
- logerr (TAG, "Failed to open the model binary: %d\n", -errno);
- return nullptr;
- }
-
- meta = (npubin_meta *) malloc (NPUBIN_META_SIZE);
- if (!meta) {
- logerr (TAG, "Failed to allocate metadata\n");
- goto exit_err;
- }
-
- ret = fread (meta, 1, NPUBIN_META_SIZE, fp);
- if (ret != NPUBIN_META_SIZE) {
- logerr (TAG, "Failed to read the metadata\n");
- goto exit_free;
- }
-
- if (!CHECK_NPUBIN (meta->magiccode)) {
- logerr (TAG, "Invalid metadata provided\n");
- goto exit_free;
- }
-
- if (need_extra && NPUBIN_META_EXTRA (meta->magiccode) > 0) {
- npubin_meta *new_meta;
-
- new_meta = (npubin_meta *) malloc (NPUBIN_META_TOTAL_SIZE(meta->magiccode));
- if (!new_meta) {
- logerr (TAG, "Failed to allocate extra metadata\n");
- goto exit_free;
- }
-
- memcpy (new_meta, meta, NPUBIN_META_TOTAL_SIZE(meta->magiccode));
- free (meta);
- meta = nullptr;
- ret = fread (new_meta->reserved_extra, 1, NPUBIN_META_EXTRA_SIZE (new_meta->magiccode), fp);
- if (ret != NPUBIN_META_EXTRA_SIZE (new_meta->magiccode)) {
- logerr (TAG, "Invalid extra metadata provided\n");
- free (new_meta);
- goto exit_err;
- }
-
- meta = new_meta;
- }
-
- fclose (fp);
-
- return meta;
-
-exit_free:
- free (meta);
-exit_err:
- fclose (fp);
-
- return nullptr;
-}
-
-/** implement methods of HostHandler class */
-
/** @brief host handler constructor */
HostHandler::HostHandler (Device *device)
: device_(device),
}
*dev = device;
- /** This is just for backward-compatility; we don't guarantee its corresness */
- latest_dev_ = *dev;
return 0;
}
#ifndef __NPU_ENGINE_HANDLER_H__
#define __NPU_ENGINE_HANDLER_H__
-#include <libnpuhost.h>
#include <typedef.h>
#include <CommPlugin.h>
static int getNumDevices (dev_type type);
static int getDevice (npudev_h *dev, dev_type type, uint32_t id);
- static npudev_h getLatestDevice () { return latest_dev_; }
-
private:
/** only Device can create a HostHandler instance */
HostHandler (Device *device);
#include <stdint.h>
#include <typedef.h>
-#include <libnpuhost.h>
#include <NPUdrvAPI.h>
#include "ne-common.h"
#include <stdint.h>
#include <stdbool.h>
-#include <libnpuhost.h>
#include <npubinfmt.h>
#include "ne-common.h"
#define __NE_MODEL_HH__
#include <npubinfmt.h>
-#include <libnpuhost.h>
#include "ne-hwmem.h"
#ifndef NE_SCHEDULER_H__
#define NE_SCHEDULER_H__
-#include <libnpuhost.h>
+#include <typedef.h>
#include <NPUdrvAPI.h>
#include "ne-model.h"
static const char *modulestr[_NEND] = {
[_N1] = "N1/CommPl",
[_N11] = "N11/IP ",
- [_N2] = "N2/HostHd",
+ [_N2] = "N2/Handlr",
+ [_N21] = "N21/Host ",
[_N3] = "N3/Sched ",
[_N4] = "N4/InputC",
[_N41] = "N41/HWrec",
_N1 = 0,
_N11,
_N2,
+ _N21,
_N3,
_N4,
_N41,
+++ /dev/null
-## This is not used in the current design (i.e., NPU-IP).
-## The function in libnpuhost are implemented in /src/core/ip/plugin-comm-ip.c
-
-libnpuhost_inc = include_directories('.')
-libnpuhost_dep = declare_dependency(include_directories: libnpuhost_inc)
-subdir('libnpuhost')
+ne_host_sources = [
+ 'ne-host.cc'
+]
-ne_host_dep = [libnpuhost_dep]
+ne_host_dep = declare_dependency(
+ sources : ne_host_sources,
+ dependencies : ne_core_dependencies,
+ include_directories : [ne_core_inc, ne_host_inc]
+)
--- /dev/null
+/**
+ * Proprietary
+ * Copyright (C) 2020 Samsung Electronics
+ * Copyright (C) 2020 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file ne-host.cc
+ * @date 03 Apr 2020
+ * @brief Implementation of User APIs to access NPU from Host
+ * @see https://code.sec.samsung.net/confluence/display/ODLC/2020+Overall+Software+Stack
+ * @author Dongju Chae <dongju.chae@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+
+#include <libnpuhost.h>
+#include <ne-handler.h>
+#include <ne-conf.h>
+
+#define TAG _N2
+
+#define INIT_HOST_HANDLER(handler, dev) \
+ Device *tdev = static_cast <Device *> (dev); \
+ if (tdev == nullptr) return -EINVAL; \
+ HostHandler *handler = tdev->getHostHandler (); \
+ if (handler == nullptr) return -EINVAL;
+
+/**
+ * @brief Get npu-engine libraray version
+ * @param[out] major major version
+ * @param[out] minor minor version
+ * @param[out] extra extra version
+ */
+void getVersion (uint32_t *major, uint32_t *minor, uint32_t *extra)
+{
+ if (major != nullptr)
+ *major = VER_NE_MAJOR;
+ if (minor != nullptr)
+ *minor = VER_NE_MINOR;
+ if (extra != nullptr)
+ *extra = VER_NE_EXTRA;
+}
+
+/**
+ * @brief Returns the number of available NPU devices.
+ * @return @c The number of NPU devices.
+ * @retval 0 if no NPU devices available. if positive (number of NPUs) if NPU devices available. otherwise, a negative error value.
+ * @note the caller should call putNPUdevice() to release the device handle
+ */
+int getnumNPUdeviceByType (dev_type type)
+{
+ return HostHandler::getNumDevices (type);
+}
+
+/**
+ * @brief Returns the handle of the chosen NPU devices.
+ * @param[out] dev The NPU device handle
+ * @param[in] id The NPU id to get the handle. 0 <= id < getnumNPUdeviceByType().
+ * @return @c 0 if no error. otherwise a negative error value
+ * @note the caller should call putNPUdevice() to release the device handle
+ */
+int getNPUdeviceByType (npudev_h *dev, dev_type type, uint32_t id)
+{
+ return HostHandler::getDevice (dev, type, id);
+}
+
+/**
+ * @brief release the NPU device instance obtained by getDevice ()
+ * @param[in] dev the NPU device handle
+ */
+void putNPUdevice (npudev_h dev)
+{
+ if (dev != nullptr)
+ delete static_cast<Device *> (dev);
+}
+
+/**
+ * @brief Get the driver API level that npu-engine library assumes (compiled)
+ * @param[out] level driver API level
+ * @note when this API level is lower than actual driver's one,
+ * some operations might be not working.
+ */
+void getDriverAPILevel (uint32_t *level)
+{
+ if (level != nullptr)
+ *level = DriverAPI::getCompiledAPILevel ();
+}
+
+/**
+ * @brief Get the driver API level of opened NPU device
+ * @param[in] dev the NPU device handle
+ * @param[out] level driver API level
+ * @return 0 if no error, otherwise a negative errno
+ */
+int getNPU_driverAPILevel (npudev_h dev, uint32_t *level)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ if (level == nullptr)
+ return -EINVAL;
+
+ return host_handler->getAPILevel (level);
+}
+
+/**
+ * @brief Get the TOPS of the opened NPU device
+ * @param[in] dev the NPU device handle
+ * @param[out] tops npu tops
+ * @return 0 if no error, otherwise a negative errno
+ * @note this does not support for emulated devices
+ */
+int getNPU_tops (npudev_h dev, uint32_t *tops)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ if (tops == nullptr)
+ return -EINVAL;
+
+ return host_handler->getTops (tops);
+}
+
+/**
+ * @brief Get the profile information from NPU
+ * @param[in] dev The NPU device handle
+ * @param[in] task_id The identifier for each inference
+ * @param[out] profile The profile instance
+ * @return 0 if no error, otherwise a negative errno.
+ */
+int getNPU_profile (npudev_h dev, int task_id, npu_profile *profile)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->getProfile (task_id, profile);
+}
+
+/**
+ * @brief Free the profile instance obtained by getNPU_profile().
+ * @param[in] profile The profile instance
+ */
+void putNPU_profile (npu_profile *profile)
+{
+ if (profile != nullptr)
+ free (profile);
+}
+
+/**
+ * @brief get the stats for the latest apps of the target device
+ * @param[in] dev The NPU device handle
+ * @param[out] stat The instance of app stat
+ * @note The caller has the responsibility to free the resources.
+ * This API is not working on the emulated envionment.
+ */
+int getNPU_statApps (npudev_h dev, npu_stat_apps *stat)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+#ifdef ENABLE_EMUL
+ logwarn (TAG, "we don't support statistics for the emulated envionment");
+ if (stat) {
+ stat->num = 0;
+ stat->stat = nullptr;
+ }
+ return 0;
+#else
+ return host_handler->getStatApps (stat);
+#endif
+}
+
+/**
+ * @brief Free the stat instance obtained by getNPU_statApps().
+ * @param[in] stat Stat instance
+ */
+void putNPU_statApps (npu_stat_apps *stat)
+{
+ if (stat) {
+ delete [] stat->stat;
+ stat->num = 0;
+ }
+}
+
+/**
+ * @brief get the stats for the latest tasks of the target app
+ * @param[in] dev The NPU device handle
+ * @param[in] appid The identifier of target app
+ * @param[out] stat The instance of task stat
+ * @note The caller has the responsibility to free the resources.
+ * This API is not working on the emulated envionment.
+ */
+int getNPU_statTasks (npudev_h dev, int appid, npu_stat_tasks *stat)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+#ifdef ENABLE_EMUL
+ logwarn (TAG, "we don't support statistics for the emulated envionment");
+ if (stat) {
+ stat->num = 0;
+ stat->stat = nullptr;
+ }
+ return 0;
+#else
+ return host_handler->getStatTasks (appid, stat);
+#endif
+}
+
+/**
+ * @brief Free the stat instance obtained by getNPU_statTasks().
+ * @param[in] stat Stat instance
+ */
+void putNPU_statTasks (npu_stat_tasks *stat)
+{
+ if (stat) {
+ delete [] stat->stat;
+ stat->num = 0;
+ }
+}
+
+/**
+ * @brief Send the NN model to NPU.
+ * @param[in] dev The NPU device handle
+ * @param[in] modelfile The filepath to the compiled NPU NN model in any buffer_type
+ * @param[out] modelid The modelid allocated for this instance of NN model.
+ * @return @c 0 if no error. otherwise a negative error value
+ *
+ * @detail For ASR devices, which do not accept models, but have models
+ * embedded in devices, you do not need to call register and
+ * register calls for ASR are ignored.
+ *
+ * @todo Add a variation: in-memory model register.
+ */
+int registerNPUmodel (npudev_h dev, generic_buffer *modelfile, uint32_t *modelid)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->registerModel (modelfile, modelid);
+}
+
+/**
+ * @brief Remove the NN model from NPU
+ * @param[in] dev The NPU device handle
+ * @param[in] modelid The model to be removed from the NPU.
+ * @return @c 0 if no error. otherwise a negative error value
+ * @detail This may incur some latency with memory compatcion.
+ */
+int unregisterNPUmodel(npudev_h dev, uint32_t modelid)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->unregisterModel (modelid);
+}
+
+/**
+ * @brief Remove all NN models from NPU
+ * @param[in] dev The NPU device handle
+ * @return @c 0 if no error. otherwise a negative error value
+ */
+int unregisterNPUmodel_all(npudev_h dev)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->unregisterModels ();
+}
+
+/**
+ * @brief [OPTIONAL] Set the data layout for input/output tensors
+ * @param[in] dev The NPU device handle
+ * @param[in] modelid The ID of model whose layouts are set
+ * @param[in] info_in the layout/type info for input tensors
+ * @param[in] info_out the layout/type info for output tensors
+ * @return @c 0 if no error. otherwise a negative error value
+ * @note if this function is not called, default layout/type will be used.
+ */
+int setNPU_dataInfo(npudev_h dev, uint32_t modelid,
+ tensors_data_info *info_in, tensors_data_info *info_out)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->setDataInfo (modelid, info_in, info_out);
+}
+
+/**
+ * @brief [OPTIONAL] Set the inference constraint for next NPU inferences
+ * @param[in] dev The NPU device handle
+ * @param[in] modelid The target model id
+ * @param[in] constraint inference constraint (e.g., timeout, priority)
+ * @return @c 0 if no error. otherwise a negative error value
+ * @note If this function is not called, default values are used.
+ */
+int setNPU_constraint(npudev_h dev, uint32_t modelid, npuConstraint constraint)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->setConstraint (modelid, constraint);
+}
+
+/**
+ * @brief Execute inference. Wait (block) until the output is available.
+ * @param[in] dev The NPU device handle
+ * @param[in] modelid The model to be inferred.
+ * @param[in] input The input data to be inferred.
+ * @param[out] output The output result. The caller MUST allocate appropriately before calling this.
+ * @return @c 0 if no error. otherwise a negative error value
+ *
+ * @detail This is a syntactic sugar of runNPU_async().
+ * CAUTION: There is a memcpy for the output buffer.
+ */
+int runNPU_sync(npudev_h dev, uint32_t modelid, const input_buffers *input,
+ output_buffers *output)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->runSync (modelid, input, output);
+}
+
+/**
+ * @brief Invoke NPU inference. Unblocking call.
+ * @param[in] dev The NPU device handle
+ * @param[in] modelid The model to be inferred.
+ * @param[in] input The input data to be inferred.
+ * @param[in] cb The output buffer handler.
+ * @param[out] sequence The sequence number returned with runNPU_async.
+ * @param[in] data The data given as a parameter to the runNPU_async call.
+ * @param[in] mode Configures how this operation works.
+ * @return @c 0 if no error. otherwise a negative error value
+ */
+int runNPU_async(npudev_h dev, uint32_t modelid, const input_buffers *input,
+ npuOutputNotify cb, uint64_t *sequence, void *data,
+ npu_async_mode mode)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->runAsync (modelid, input, cb, data, mode, sequence);
+}
+
+/**
+ * @brief Let NPU accept input frames from its internal source continuously
+ * @param[in] dev The NPU device handle
+ * @param[in] modelid The model to be inferred.
+ * @param[in] opmode NPU has different opmode with auto-inputs. Choose one.
+ * @param[in] hw_dev The target device feeding input data
+ * @return @c 0 if no error. otherwise a negative error value
+ */
+int runNPU_internalInput(npudev_h dev, uint32_t modelid, npu_input_opmode opmode,
+ const char * hw_dev)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->runInternal (modelid, opmode, hw_dev);
+}
+
+/**
+ * @brief Stop the request with the given id
+ * @param[in] dev The NPU device handle
+ * @param[in] id The request id
+ * @return @c 0 if no error. otherwise a negative error value
+ */
+int stopNPU_internalInput(npudev_h dev, int id)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->stopInternal (id);
+}
+
+/**
+ * @brief Allocate a generic buffer with the requested buffer type.
+ * @param[in] dev The NPU device handle
+ * @param[in/out] Buffer the buffer pointer where memory is allocated.
+ * @return 0 if no error, otherwise a negative errno.
+ */
+int allocNPU_genericBuffer (npudev_h dev, generic_buffer * buffer)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->allocGenericBuffer (buffer);
+}
+
+/**
+ * @brief Free the generic buffer and remove the address mapping
+ * @param[in] dev The NPU device handle
+ * @param[in] buffer the model buffer
+ * @return 0 if no error, otherwise a negative errno.
+ */
+int cleanNPU_genericBuffer (npudev_h dev, generic_buffer * buffer)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->deallocGenericBuffer (buffer);
+}
+
+/**
+ * @brief Allocate generic buffers, which have multiple instances of generic_buffer
+ * @param[in] dev The NPU device handle
+ * @param[in/out] buffers generic buffers.
+ * @return 0 if no error, otherwise a negative errno.
+ * @note it reuses allocGenericBuffer().
+ */
+int allocNPU_genericBuffers (npudev_h dev, generic_buffers * buffers)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->allocGenericBuffer (buffers);
+}
+
+/**
+ * @brief Free generic buffers allocated by allocGenericBuffers().
+ * @param[in] dev The NPU device handle
+ * @param[in/out] buffers generic buffers.
+ * @note it reuses cleanGenericbuffer().
+ * @return 0 if no error, otherwise a negative errno.
+ */
+int cleanNPU_genericBuffers (npudev_h dev, generic_buffers * buffers)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->deallocGenericBuffer (buffers);
+}
+
+/**
+ * @brief alias of allocNPU_genericBuffer for model buffer
+ */
+int allocNPU_modelBuffer (npudev_h dev, generic_buffer * model)
+{
+ return allocNPU_genericBuffer (dev, model);
+}
+
+/**
+ * @brief alias of cleanNPU_genericBuffer for model buffer
+ */
+int cleanNPU_modelBuffer (npudev_h dev, generic_buffer * model)
+{
+ return cleanNPU_genericBuffer (dev, model);
+}
+
+/**
+ * @brief alias of allocNPU_genericBuffer for input buffer
+ */
+int allocNPU_inputBuffer (npudev_h dev, generic_buffer * input)
+{
+ return allocNPU_genericBuffer (dev, input);
+}
+
+/**
+ * @brief alias of cleanNPU_genericBuffer for input buffer
+ */
+int cleanNPU_inputBuffer (npudev_h dev, generic_buffer * input)
+{
+ return cleanNPU_genericBuffer (dev, input);
+}
+
+/**
+ * @brief alias of allocNPU_genericBuffers for input buffers
+ */
+int allocNPU_inputBuffers (npudev_h dev, input_buffers * input)
+{
+ return allocNPU_genericBuffers (dev, input);
+}
+
+/**
+ * @brief alias of cleanNPU_genericBuffers for input buffers
+ */
+int cleanNPU_inputBuffers (npudev_h dev, input_buffers * input)
+{
+ return cleanNPU_genericBuffers (dev, input);
+}
+
+/**
+ * @brief get the current memory status for the given device
+ * @param[in] dev The NPU device handle
+ * @param[out] alloc_total The size of allocated memory until now
+ * @param[out] free_total The size of freed memory until now
+ * @return @c 0 if no error. otherwise a negatice error value
+ */
+int getNPU_memoryStatus(npudev_h dev, size_t *alloc_total, size_t *free_total)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->getMemoryStatus (alloc_total, free_total);
+}
+
+/**
+ * @brief Get the current device status to be used
+ * @param[in] dev The NPU device handle
+ * @param[out] status the device status
+ * @param[out] num_requests the number of running requests (or pending)
+ * @return 0 if no error, otherwise a negative errno.
+ */
+int getNPU_deviceStatus(npudev_h dev, npu_status *status, uint32_t *num_requests)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+ return host_handler->getDeviceStatus (status, num_requests);
+}
+
+/**
+ * @brief Get metadata for NPU model
+ * @param[in] model The path of model binary file
+ * @param[in] need_extra whether you want to extract the extra data in metadata
+ * @return the metadata structure to be filled if no error, otherwise nullptr
+ *
+ * @note For most npu-engine users, the extra data is not useful because it will be
+ * used for second-party users (e.g., compiler, simulator).
+ * Also, the caller needs to free the metadata.
+ *
+ * @note the caller needs to free the metadata
+ */
+npubin_meta * getNPUmodel_metadata (const char *model, bool need_extra)
+{
+ npubin_meta *meta;
+ FILE *fp;
+ size_t ret;
+
+ if (!model)
+ return nullptr;
+
+ fp = fopen (model, "rb");
+ if (!fp) {
+ logerr (TAG, "Failed to open the model binary: %d\n", -errno);
+ return nullptr;
+ }
+
+ meta = (npubin_meta *) malloc (NPUBIN_META_SIZE);
+ if (!meta) {
+ logerr (TAG, "Failed to allocate metadata\n");
+ goto exit_err;
+ }
+
+ ret = fread (meta, 1, NPUBIN_META_SIZE, fp);
+ if (ret != NPUBIN_META_SIZE) {
+ logerr (TAG, "Failed to read the metadata\n");
+ goto exit_free;
+ }
+
+ if (!CHECK_NPUBIN (meta->magiccode)) {
+ logerr (TAG, "Invalid metadata provided\n");
+ goto exit_free;
+ }
+
+ if (need_extra && NPUBIN_META_EXTRA (meta->magiccode) > 0) {
+ npubin_meta *new_meta;
+
+ new_meta = (npubin_meta *) malloc (NPUBIN_META_TOTAL_SIZE(meta->magiccode));
+ if (!new_meta) {
+ logerr (TAG, "Failed to allocate extra metadata\n");
+ goto exit_free;
+ }
+
+ memcpy (new_meta, meta, NPUBIN_META_TOTAL_SIZE(meta->magiccode));
+ free (meta);
+ meta = nullptr;
+ ret = fread (new_meta->reserved_extra, 1, NPUBIN_META_EXTRA_SIZE (new_meta->magiccode), fp);
+ if (ret != NPUBIN_META_EXTRA_SIZE (new_meta->magiccode)) {
+ logerr (TAG, "Invalid extra metadata provided\n");
+ free (new_meta);
+ goto exit_err;
+ }
+
+ meta = new_meta;
+ }
+
+ fclose (fp);
+
+ return meta;
+
+exit_free:
+ free (meta);
+exit_err:
+ fclose (fp);
+
+ return nullptr;
+}
# Final dependencies
ne_dependencies = [
ne_core_dep,
- ne_host_dep # not used yet
+ ne_host_dep
]
# Build library
unittest_ne_libnpuhost = executable('unittest_ne_libnpuhost',
['ne_libnpuhost_test.cc'],
include_directories: [ne_host_inc, ne_common_inc],
- dependencies: [gtest_dep, ne_core_dep, ne_test_utils_dep],
+ dependencies: [gtest_dep, ne_host_dep, ne_core_dep, ne_test_utils_dep],
install : true,
install_rpath : ne_libdir,
install_dir : join_paths(ne_bindir, 'unittests')
}
/**
- * @brief test HostHandler's getNPUmodel_metadata ()
- */
-TEST (ne_core_handler_test, handler_common_get_npumodel_metadata_01)
-{
- /* Constants */
- const size_t program_size = 4096;
- const size_t weight_size = 4096;
- const size_t buffer_size = 4096;
- const size_t input_offset = 0;
- const size_t input_size = 1024;
- const size_t output_offset = 512;
- const size_t output_size = 2048;
- const char tmp_dir_path[] = "/tmp";
- const char bin_name[] = "npumodel_metaonly.bin";
-
- npubin_meta *loaded_meta;
- npubin_meta meta;
- char bin_path[PATH_MAX];
- FILE *meta_only_bin_fp;
- DIR *dir;
- size_t cnt;
-
- memset (&meta, 0, sizeof(meta));
- /**
- * Since get_npumodel_metadata () is a common function regardless of the
- * devices, this test uses a simple TRIV1 meta data.
- */
- meta.magiccode = NPUBIN_MAGICCODE | 0x1;
- strncpy(meta.name, "handler_common_get_npumodel_metadata", 128);
- meta.model_id = 1;
- meta.model_version = 1;
- meta.buffer_size = buffer_size;
- meta.size = NPUBIN_META_SIZE + program_size + weight_size;
- meta.type = SMODEL_OPS_NPU;
- meta.input_offset = input_offset;
- meta.input_size = input_size;
- meta.output_offset = output_offset;
- meta.output_size = output_size;
- meta.program_size = program_size;
- meta.weight_size = weight_size;
-
- dir = opendir (tmp_dir_path);
-
- /** If /tmp does not exist, let's skip this test */
- if (!dir)
- return;
- closedir (dir);
-
- snprintf (bin_path, PATH_MAX, "%s/%s", tmp_dir_path, bin_name);
- meta_only_bin_fp = fopen (bin_path, "wb");
- if (!meta_only_bin_fp)
- return;
-
- cnt = fwrite (&meta, NPUBIN_META_SIZE, 1, meta_only_bin_fp);
- fclose (meta_only_bin_fp);
- if (cnt != 1)
- return;
-
- loaded_meta = getNPUmodel_metadata(bin_path, false);
- ASSERT_NE (loaded_meta, nullptr);
- EXPECT_EQ (meta.magiccode, loaded_meta->magiccode);
- EXPECT_EQ (meta.model_id, loaded_meta->model_id);
- EXPECT_EQ (meta.model_version, loaded_meta->model_version);
- EXPECT_EQ (meta.buffer_size, loaded_meta->buffer_size);
- EXPECT_EQ (meta.size, loaded_meta->size);
- EXPECT_EQ (meta.output_offset, loaded_meta->output_offset);
- EXPECT_EQ (meta.output_size, loaded_meta->output_size);
- EXPECT_EQ (meta.program_size, loaded_meta->program_size);
- EXPECT_EQ (meta.weight_size, loaded_meta->weight_size);
-
- free (loaded_meta);
-}
-
-/**
- * @brief test HostHandler's getNPUmodel_metadata () when the meta data includes extras
- */
-TEST (ne_core_handler_test, handler_common_get_npumodel_metadata_02)
-{
- /* Constants */
- const size_t program_size = 4096;
- const size_t weight_size = 4096;
- const size_t buffer_size = 4096;
- const size_t input_offset = 0;
- const size_t input_size = 1024;
- const size_t output_offset = 512;
- const size_t output_size = 2048;
- const char tmp_dir_path[] = "/tmp";
- const char bin_name[] = "npumodel_metaonly.bin";
- constexpr size_t extra_size = 0x1;
-
- npubin_meta *loaded_meta;
- npubin_meta meta;
- char bin_path[PATH_MAX];
- uint8_t *extra;
- FILE *meta_only_bin_fp;
- DIR *dir;
- size_t cnt;
-
- memset (&meta, 0, sizeof(meta));
- /**
- * Since get_npumodel_metadata () is a common function regardless of the
- * devices, this test uses a simple TRIV1 meta data.
- */
- meta.magiccode = NPUBIN_MAGICCODE | 0x1 | (extra_size << 8);
- strncpy(meta.name, "handler_common_get_npumodel_metadata", 128);
- meta.model_id = 1;
- meta.model_version = 1;
- meta.buffer_size = buffer_size;
- meta.size = NPUBIN_META_SIZE + program_size + weight_size;
- meta.type = SMODEL_OPS_NPU;
- meta.input_offset = input_offset;
- meta.input_size = input_size;
- meta.output_offset = output_offset;
- meta.output_size = output_size;
- meta.program_size = program_size;
- meta.weight_size = weight_size;
-
- dir = opendir (tmp_dir_path);
-
- /** If /tmp does not exist, let's skip this test */
- if (!dir)
- return;
- closedir (dir);
-
- snprintf (bin_path, PATH_MAX, "%s/%s", tmp_dir_path, bin_name);
- meta_only_bin_fp = fopen (bin_path, "wb");
- if (!meta_only_bin_fp)
- return;
-
- cnt = fwrite (&meta, NPUBIN_META_SIZE, 1, meta_only_bin_fp);
- if (cnt != 1) {
- fclose (meta_only_bin_fp);
- return;
- }
-
- /** Make it clear */
- if (fseek (meta_only_bin_fp, NPUBIN_META_SIZE, SEEK_SET) != 0) {
- fclose (meta_only_bin_fp);
- return;
- }
-
- extra = (uint8_t *) malloc (extra_size * NPUBIN_META_SIZE);
- memset (extra, 0, extra_size * NPUBIN_META_SIZE);
-
- cnt = fwrite (extra, extra_size * NPUBIN_META_SIZE, 1, meta_only_bin_fp);
- fclose (meta_only_bin_fp);
- free (extra);
- if (cnt != 1)
- return;
-
- loaded_meta = getNPUmodel_metadata(bin_path, true);
- ASSERT_NE (loaded_meta, nullptr);
- EXPECT_EQ (meta.magiccode, loaded_meta->magiccode);
- EXPECT_EQ (meta.model_id, loaded_meta->model_id);
- EXPECT_EQ (meta.model_version, loaded_meta->model_version);
- EXPECT_EQ (meta.buffer_size, loaded_meta->buffer_size);
- EXPECT_EQ (meta.size, loaded_meta->size);
- EXPECT_EQ (meta.output_offset, loaded_meta->output_offset);
- EXPECT_EQ (meta.output_size, loaded_meta->output_size);
- EXPECT_EQ (meta.program_size, loaded_meta->program_size);
- EXPECT_EQ (meta.weight_size, loaded_meta->weight_size);
-
- free (loaded_meta);
-}
-
-/**
- * @brief test HostHandler's getNPUmodel_metadata () with error handling #1
- */
-TEST (ne_core_handler_test, handler_common_get_npumodel_metadata_01_n)
-{
- npubin_meta *loaded_meta;
-
- /** The given path is nullptr */
- loaded_meta = getNPUmodel_metadata(nullptr, false);
- ASSERT_EQ (loaded_meta, nullptr);
-}
-
-/**
- * @brief test HostHandler's getNPUmodel_metadata () with error handling #2
- */
-TEST (ne_core_handler_test, handler_common_get_npumodel_metadata_02_n)
-{
- /* Constants */
- const char wrong_bin_path[] = "nowhere/notfile.bin";
- npubin_meta *loaded_meta;
-
- /** The given path is nullptr */
- loaded_meta = getNPUmodel_metadata(wrong_bin_path, false);
- ASSERT_EQ (loaded_meta, nullptr);
-}
-
-/**
- * @brief test HostHandler's getNPUmodel_metadata () with error handling #3
- */
-TEST (ne_core_handler_test, handler_common_get_npumodel_metadata_03_n)
-{
- /* Constants */
- const size_t program_size = 4096;
- const size_t weight_size = 4096;
- const size_t buffer_size = 4096;
- const size_t input_offset = 0;
- const size_t input_size = 1024;
- const size_t output_offset = 512;
- const size_t output_size = 2048;
- const char tmp_dir_path[] = "/tmp";
- const char bin_name[] = "npumodel_metaonly.bin";
-
- npubin_meta *loaded_meta;
- npubin_meta meta;
- char bin_path[PATH_MAX];
- FILE *meta_only_bin_fp;
- DIR *dir;
- size_t cnt;
-
- memset (&meta, 0, sizeof(meta));
- /**
- * Since get_npumodel_metadata () is a common function regardless of the
- * devices, this test uses a simple TRIV1 meta data.
- */
- /* Wrong magic code */
- meta.magiccode = 0xFF;
- strncpy(meta.name, "handler_common_get_npumodel_metadata", 128);
- meta.model_id = 1;
- meta.model_version = 1;
- meta.buffer_size = buffer_size;
- meta.size = NPUBIN_META_SIZE + program_size + weight_size;
- meta.type = SMODEL_OPS_NPU;
- meta.input_offset = input_offset;
- meta.input_size = input_size;
- meta.output_offset = output_offset;
- meta.output_size = output_size;
- meta.program_size = program_size;
- meta.weight_size = weight_size;
-
- dir = opendir (tmp_dir_path);
-
- /** If /tmp does not exist, let's skip this test */
- if (!dir)
- return;
- closedir (dir);
-
- snprintf (bin_path, PATH_MAX, "%s/%s", tmp_dir_path, bin_name);
- meta_only_bin_fp = fopen (bin_path, "wb");
- if (!meta_only_bin_fp)
- return;
-
- cnt = fwrite (&meta, NPUBIN_META_SIZE, 1, meta_only_bin_fp);
- fclose (meta_only_bin_fp);
- if (cnt != 1)
- return;
-
- loaded_meta = getNPUmodel_metadata(bin_path, false);
- ASSERT_EQ (loaded_meta, nullptr);
-}
-
-/**
- * @brief test HostHandler's getNPUmodel_metadata () with error handling #4
- */
-TEST (ne_core_handler_test, handler_common_get_npumodel_metadata_04_n)
-{
- /* Constants */
- const size_t program_size = 4096;
- const size_t weight_size = 4096;
- const size_t buffer_size = 4096;
- const size_t input_offset = 0;
- const size_t input_size = 1024;
- const size_t output_offset = 512;
- const size_t output_size = 2048;
- const char tmp_dir_path[] = "/tmp";
- const char bin_name[] = "npumodel_metaonly.bin";
- constexpr size_t extra_size = 0x1;
-
- npubin_meta *loaded_meta;
- npubin_meta meta;
- char bin_path[PATH_MAX];
- uint8_t *extra;
- FILE *meta_only_bin_fp;
- DIR *dir;
- size_t cnt;
-
- memset (&meta, 0, sizeof(meta));
- /**
- * Since get_npumodel_metadata () is a common function regardless of the
- * devices, this test uses a simple TRIV1 meta data.
- */
- meta.magiccode = NPUBIN_MAGICCODE | 0x1 | (extra_size << 8);
- strncpy(meta.name, "handler_common_get_npumodel_metadata", 128);
- meta.model_id = 1;
- meta.model_version = 1;
- meta.buffer_size = buffer_size;
- meta.size = NPUBIN_META_SIZE + program_size + weight_size;
- meta.type = SMODEL_OPS_NPU;
- meta.input_offset = input_offset;
- meta.input_size = input_size;
- meta.output_offset = output_offset;
- meta.output_size = output_size;
- meta.program_size = program_size;
- meta.weight_size = weight_size;
-
- dir = opendir (tmp_dir_path);
-
- /** If /tmp does not exist, let's skip this test */
- if (!dir)
- return;
- closedir (dir);
-
- snprintf (bin_path, PATH_MAX, "%s/%s", tmp_dir_path, bin_name);
- meta_only_bin_fp = fopen (bin_path, "wb");
- if (!meta_only_bin_fp)
- return;
-
- cnt = fwrite (&meta, NPUBIN_META_SIZE, 1, meta_only_bin_fp);
- if (cnt != 1) {
- fclose (meta_only_bin_fp);
- return;
- }
-
- /** Make it clear */
- if (fseek (meta_only_bin_fp, NPUBIN_META_SIZE, SEEK_SET) != 0) {
- fclose (meta_only_bin_fp);
- return;
- }
- /** Wrong meta data is given */
-
- extra = (uint8_t *) malloc (extra_size * NPUBIN_META_SIZE);
- memset (extra, 0, extra_size * NPUBIN_META_SIZE);
-
- cnt = fwrite (extra, extra_size * (NPUBIN_META_SIZE / 2), 1, meta_only_bin_fp);
- fclose (meta_only_bin_fp);
- free (extra);
- if (cnt != 1)
- return;
-
- loaded_meta = getNPUmodel_metadata(bin_path, true);
- ASSERT_EQ (loaded_meta, nullptr);
-}
-
-/**
- * @brief test getNPU_deviceStatus()
- */
-TEST (ne_core_handler_test, handler_common_get_npu_device_status)
-{
- dev_type type = NPUCOND_TRIV2_CONN_SOCIP;
- npudev_h dev;
- npu_status status;
- uint32_t num_requests;
- int num_devices;
- int ret;
-
- num_devices = HostHandler::getNumDevices (type);
- EXPECT_GT (num_devices, 0);
-
- ret = getNPUdeviceByType (&dev, type, 0);
- EXPECT_EQ (ret, 0);
-
- ret = getNPU_deviceStatus (dev, &status, &num_requests);
- EXPECT_EQ (ret, 0);
-}
-
-/**
- *@brief test getNPUdeviceByType with invalid dev_type
- */
-TEST (ne_core_handler_test, handler_common_get_npu_device_by_type_n)
-{
- npudev_h dev;
- int ret;
-
- ret = getNPUdeviceByType (&dev, static_cast<dev_type> (0x1111), 0);
- EXPECT_NE (ret, 0);
-}
-/**
- * @brief test getNPU_deviceStatus() with error handling
- */
-TEST (ne_core_handler_test, handler_common_get_npu_device_status_n)
-{
- npudev_h dev = nullptr;
- npu_status status;
- uint32_t num_requests;
- int ret;
-
- ret = getNPU_deviceStatus (dev, &status, &num_requests);
- EXPECT_NE (ret, 0);
-}
-
-/**
* @brief main function for unit test
*/
int
}
/**
+ * @brief test getNPUmodel_metadata ()
+ */
+TEST (ne_libnpuhost_test, get_npumodel_metadata_01)
+{
+ /* Constants */
+ const size_t program_size = 4096;
+ const size_t weight_size = 4096;
+ const size_t buffer_size = 4096;
+ const size_t input_offset = 0;
+ const size_t input_size = 1024;
+ const size_t output_offset = 512;
+ const size_t output_size = 2048;
+ const char tmp_dir_path[] = "/tmp";
+ const char bin_name[] = "npumodel_metaonly.bin";
+
+ npubin_meta *loaded_meta;
+ npubin_meta meta;
+ char bin_path[PATH_MAX];
+ FILE *meta_only_bin_fp;
+ DIR *dir;
+ size_t cnt;
+
+ memset (&meta, 0, sizeof(meta));
+ /**
+ * Since get_npumodel_metadata () is a common function regardless of the
+ * devices, this test uses a simple TRIV1 meta data.
+ */
+ meta.magiccode = NPUBIN_MAGICCODE | 0x1;
+ strncpy(meta.name, "get_npumodel_metadata", 128);
+ meta.model_id = 1;
+ meta.model_version = 1;
+ meta.buffer_size = buffer_size;
+ meta.size = NPUBIN_META_SIZE + program_size + weight_size;
+ meta.type = SMODEL_OPS_NPU;
+ meta.input_offset = input_offset;
+ meta.input_size = input_size;
+ meta.output_offset = output_offset;
+ meta.output_size = output_size;
+ meta.program_size = program_size;
+ meta.weight_size = weight_size;
+
+ dir = opendir (tmp_dir_path);
+
+ /** If /tmp does not exist, let's skip this test */
+ if (!dir)
+ return;
+ closedir (dir);
+
+ snprintf (bin_path, PATH_MAX, "%s/%s", tmp_dir_path, bin_name);
+ meta_only_bin_fp = fopen (bin_path, "wb");
+ if (!meta_only_bin_fp)
+ return;
+
+ cnt = fwrite (&meta, NPUBIN_META_SIZE, 1, meta_only_bin_fp);
+ fclose (meta_only_bin_fp);
+ if (cnt != 1)
+ return;
+
+ loaded_meta = getNPUmodel_metadata(bin_path, false);
+ ASSERT_NE (loaded_meta, nullptr);
+ EXPECT_EQ (meta.magiccode, loaded_meta->magiccode);
+ EXPECT_EQ (meta.model_id, loaded_meta->model_id);
+ EXPECT_EQ (meta.model_version, loaded_meta->model_version);
+ EXPECT_EQ (meta.buffer_size, loaded_meta->buffer_size);
+ EXPECT_EQ (meta.size, loaded_meta->size);
+ EXPECT_EQ (meta.output_offset, loaded_meta->output_offset);
+ EXPECT_EQ (meta.output_size, loaded_meta->output_size);
+ EXPECT_EQ (meta.program_size, loaded_meta->program_size);
+ EXPECT_EQ (meta.weight_size, loaded_meta->weight_size);
+
+ free (loaded_meta);
+}
+
+/**
+ * @brief test getNPUmodel_metadata () when the meta data includes extras
+ */
+TEST (ne_libnpuhost_test, get_npumodel_metadata_02)
+{
+ /* Constants */
+ const size_t program_size = 4096;
+ const size_t weight_size = 4096;
+ const size_t buffer_size = 4096;
+ const size_t input_offset = 0;
+ const size_t input_size = 1024;
+ const size_t output_offset = 512;
+ const size_t output_size = 2048;
+ const char tmp_dir_path[] = "/tmp";
+ const char bin_name[] = "npumodel_metaonly.bin";
+ constexpr size_t extra_size = 0x1;
+
+ npubin_meta *loaded_meta;
+ npubin_meta meta;
+ char bin_path[PATH_MAX];
+ uint8_t *extra;
+ FILE *meta_only_bin_fp;
+ DIR *dir;
+ size_t cnt;
+
+ memset (&meta, 0, sizeof(meta));
+ /**
+ * Since get_npumodel_metadata () is a common function regardless of the
+ * devices, this test uses a simple TRIV1 meta data.
+ */
+ meta.magiccode = NPUBIN_MAGICCODE | 0x1 | (extra_size << 8);
+ strncpy(meta.name, "get_npumodel_metadata", 128);
+ meta.model_id = 1;
+ meta.model_version = 1;
+ meta.buffer_size = buffer_size;
+ meta.size = NPUBIN_META_SIZE + program_size + weight_size;
+ meta.type = SMODEL_OPS_NPU;
+ meta.input_offset = input_offset;
+ meta.input_size = input_size;
+ meta.output_offset = output_offset;
+ meta.output_size = output_size;
+ meta.program_size = program_size;
+ meta.weight_size = weight_size;
+
+ dir = opendir (tmp_dir_path);
+
+ /** If /tmp does not exist, let's skip this test */
+ if (!dir)
+ return;
+ closedir (dir);
+
+ snprintf (bin_path, PATH_MAX, "%s/%s", tmp_dir_path, bin_name);
+ meta_only_bin_fp = fopen (bin_path, "wb");
+ if (!meta_only_bin_fp)
+ return;
+
+ cnt = fwrite (&meta, NPUBIN_META_SIZE, 1, meta_only_bin_fp);
+ if (cnt != 1) {
+ fclose (meta_only_bin_fp);
+ return;
+ }
+
+ /** Make it clear */
+ if (fseek (meta_only_bin_fp, NPUBIN_META_SIZE, SEEK_SET) != 0) {
+ fclose (meta_only_bin_fp);
+ return;
+ }
+
+ extra = (uint8_t *) malloc (extra_size * NPUBIN_META_SIZE);
+ memset (extra, 0, extra_size * NPUBIN_META_SIZE);
+
+ cnt = fwrite (extra, extra_size * NPUBIN_META_SIZE, 1, meta_only_bin_fp);
+ fclose (meta_only_bin_fp);
+ free (extra);
+ if (cnt != 1)
+ return;
+
+ loaded_meta = getNPUmodel_metadata(bin_path, true);
+ ASSERT_NE (loaded_meta, nullptr);
+ EXPECT_EQ (meta.magiccode, loaded_meta->magiccode);
+ EXPECT_EQ (meta.model_id, loaded_meta->model_id);
+ EXPECT_EQ (meta.model_version, loaded_meta->model_version);
+ EXPECT_EQ (meta.buffer_size, loaded_meta->buffer_size);
+ EXPECT_EQ (meta.size, loaded_meta->size);
+ EXPECT_EQ (meta.output_offset, loaded_meta->output_offset);
+ EXPECT_EQ (meta.output_size, loaded_meta->output_size);
+ EXPECT_EQ (meta.program_size, loaded_meta->program_size);
+ EXPECT_EQ (meta.weight_size, loaded_meta->weight_size);
+
+ free (loaded_meta);
+}
+
+/**
+ * @brief test getNPUmodel_metadata () with error handling #1
+ */
+TEST (ne_libnpuhost_test, get_npumodel_metadata_01_n)
+{
+ npubin_meta *loaded_meta;
+
+ /** The given path is nullptr */
+ loaded_meta = getNPUmodel_metadata(nullptr, false);
+ ASSERT_EQ (loaded_meta, nullptr);
+}
+
+/**
+ * @brief test getNPUmodel_metadata () with error handling #2
+ */
+TEST (ne_libnpuhost_test, get_npumodel_metadata_02_n)
+{
+ /* Constants */
+ const char wrong_bin_path[] = "nowhere/notfile.bin";
+ npubin_meta *loaded_meta;
+
+ /** The given path is nullptr */
+ loaded_meta = getNPUmodel_metadata(wrong_bin_path, false);
+ ASSERT_EQ (loaded_meta, nullptr);
+}
+
+/**
+ * @brief test getNPUmodel_metadata () with error handling #3
+ */
+TEST (ne_libnpuhost_test, get_npumodel_metadata_03_n)
+{
+ /* Constants */
+ const size_t program_size = 4096;
+ const size_t weight_size = 4096;
+ const size_t buffer_size = 4096;
+ const size_t input_offset = 0;
+ const size_t input_size = 1024;
+ const size_t output_offset = 512;
+ const size_t output_size = 2048;
+ const char tmp_dir_path[] = "/tmp";
+ const char bin_name[] = "npumodel_metaonly.bin";
+
+ npubin_meta *loaded_meta;
+ npubin_meta meta;
+ char bin_path[PATH_MAX];
+ FILE *meta_only_bin_fp;
+ DIR *dir;
+ size_t cnt;
+
+ memset (&meta, 0, sizeof(meta));
+ /**
+ * Since get_npumodel_metadata () is a common function regardless of the
+ * devices, this test uses a simple TRIV1 meta data.
+ */
+ /* Wrong magic code */
+ meta.magiccode = 0xFF;
+ strncpy(meta.name, "get_npumodel_metadata", 128);
+ meta.model_id = 1;
+ meta.model_version = 1;
+ meta.buffer_size = buffer_size;
+ meta.size = NPUBIN_META_SIZE + program_size + weight_size;
+ meta.type = SMODEL_OPS_NPU;
+ meta.input_offset = input_offset;
+ meta.input_size = input_size;
+ meta.output_offset = output_offset;
+ meta.output_size = output_size;
+ meta.program_size = program_size;
+ meta.weight_size = weight_size;
+
+ dir = opendir (tmp_dir_path);
+
+ /** If /tmp does not exist, let's skip this test */
+ if (!dir)
+ return;
+ closedir (dir);
+
+ snprintf (bin_path, PATH_MAX, "%s/%s", tmp_dir_path, bin_name);
+ meta_only_bin_fp = fopen (bin_path, "wb");
+ if (!meta_only_bin_fp)
+ return;
+
+ cnt = fwrite (&meta, NPUBIN_META_SIZE, 1, meta_only_bin_fp);
+ fclose (meta_only_bin_fp);
+ if (cnt != 1)
+ return;
+
+ loaded_meta = getNPUmodel_metadata(bin_path, false);
+ ASSERT_EQ (loaded_meta, nullptr);
+}
+
+/**
+ * @brief test HostHandler's getNPUmodel_metadata () with error handling #4
+ */
+TEST (ne_libnpuhost_test, get_npumodel_metadata_04_n)
+{
+ /* Constants */
+ const size_t program_size = 4096;
+ const size_t weight_size = 4096;
+ const size_t buffer_size = 4096;
+ const size_t input_offset = 0;
+ const size_t input_size = 1024;
+ const size_t output_offset = 512;
+ const size_t output_size = 2048;
+ const char tmp_dir_path[] = "/tmp";
+ const char bin_name[] = "npumodel_metaonly.bin";
+ constexpr size_t extra_size = 0x1;
+
+ npubin_meta *loaded_meta;
+ npubin_meta meta;
+ char bin_path[PATH_MAX];
+ uint8_t *extra;
+ FILE *meta_only_bin_fp;
+ DIR *dir;
+ size_t cnt;
+
+ memset (&meta, 0, sizeof(meta));
+ /**
+ * Since get_npumodel_metadata () is a common function regardless of the
+ * devices, this test uses a simple TRIV1 meta data.
+ */
+ meta.magiccode = NPUBIN_MAGICCODE | 0x1 | (extra_size << 8);
+ strncpy(meta.name, "get_npumodel_metadata", 128);
+ meta.model_id = 1;
+ meta.model_version = 1;
+ meta.buffer_size = buffer_size;
+ meta.size = NPUBIN_META_SIZE + program_size + weight_size;
+ meta.type = SMODEL_OPS_NPU;
+ meta.input_offset = input_offset;
+ meta.input_size = input_size;
+ meta.output_offset = output_offset;
+ meta.output_size = output_size;
+ meta.program_size = program_size;
+ meta.weight_size = weight_size;
+
+ dir = opendir (tmp_dir_path);
+
+ /** If /tmp does not exist, let's skip this test */
+ if (!dir)
+ return;
+ closedir (dir);
+
+ snprintf (bin_path, PATH_MAX, "%s/%s", tmp_dir_path, bin_name);
+ meta_only_bin_fp = fopen (bin_path, "wb");
+ if (!meta_only_bin_fp)
+ return;
+
+ cnt = fwrite (&meta, NPUBIN_META_SIZE, 1, meta_only_bin_fp);
+ if (cnt != 1) {
+ fclose (meta_only_bin_fp);
+ return;
+ }
+
+ /** Make it clear */
+ if (fseek (meta_only_bin_fp, NPUBIN_META_SIZE, SEEK_SET) != 0) {
+ fclose (meta_only_bin_fp);
+ return;
+ }
+ /** Wrong meta data is given */
+
+ extra = (uint8_t *) malloc (extra_size * NPUBIN_META_SIZE);
+ memset (extra, 0, extra_size * NPUBIN_META_SIZE);
+
+ cnt = fwrite (extra, extra_size * (NPUBIN_META_SIZE / 2), 1, meta_only_bin_fp);
+ fclose (meta_only_bin_fp);
+ free (extra);
+ if (cnt != 1)
+ return;
+
+ loaded_meta = getNPUmodel_metadata(bin_path, true);
+ ASSERT_EQ (loaded_meta, nullptr);
+}
+
+/**
+ * @brief test getNPU_deviceStatus()
+ */
+TEST (ne_libnpuhost_test, get_npu_device_status)
+{
+ dev_type type = NPUCOND_TRIV2_CONN_SOCIP;
+ npudev_h dev;
+ npu_status status;
+ uint32_t num_requests;
+ int num_devices;
+ int ret;
+
+ num_devices = getnumNPUdeviceByType (type);
+ EXPECT_GT (num_devices, 0);
+
+ ret = getNPUdeviceByType (&dev, type, 0);
+ EXPECT_EQ (ret, 0);
+
+ ret = getNPU_deviceStatus (dev, &status, &num_requests);
+ EXPECT_EQ (ret, 0);
+}
+
+/**
+ *@brief test getNPUdeviceByType with invalid dev_type
+ */
+TEST (ne_libnpuhost_test, get_npu_device_by_type_n)
+{
+ npudev_h dev;
+ int ret;
+
+ ret = getNPUdeviceByType (&dev, static_cast<dev_type> (0x1111), 0);
+ EXPECT_NE (ret, 0);
+}
+/**
+ * @brief test getNPU_deviceStatus() with error handling
+ */
+TEST (ne_libnpuhost_test, get_npu_device_status_n)
+{
+ npudev_h dev = nullptr;
+ npu_status status;
+ uint32_t num_requests;
+ int ret;
+
+ ret = getNPU_deviceStatus (dev, &status, &num_requests);
+ EXPECT_NE (ret, 0);
+}
+
+/**
* @brief main function for unit test
*/
int