[Host/Refactor] Move libnpuhost codes to ./src/host/
authorDongju Chae <dongju.chae@samsung.com>
Mon, 23 Nov 2020 05:42:58 +0000 (14:42 +0900)
committer송욱/On-Device Lab(SR)/Staff Engineer/삼성전자 <wook16.song@samsung.com>
Thu, 26 Nov 2020 04:32:23 +0000 (13:32 +0900)
This patch makes refactoring for libnpuhost codes by
moving the codes to host/ne-host.cc from core/ne-handler.cc

In short, the patch includes
- Seperate host APIs from handler
- Move definitions from libnpuhost.h to typedef.h
- Remove inclusion of libnpuhost.h in core sources
- Remove unused variables

Signed-off-by: Dongju Chae <dongju.chae@samsung.com>
21 files changed:
README.md
include/common/typedef.h
include/host/libnpuhost.h
src/core/comm/CommPlugin.h
src/core/comm/plugin-comm-ip.cc
src/core/ne-handler.cc
src/core/ne-handler.h
src/core/ne-inf.h
src/core/ne-mem.h
src/core/ne-model.h
src/core/ne-scheduler.h
src/core/utils/ne-utils.cc
src/core/utils/ne-utils.h
src/host/libnpuhost/README.md [deleted file]
src/host/libnpuhost/meson.build [deleted file]
src/host/meson.build
src/host/ne-host.cc [new file with mode: 0644]
src/meson.build
tests/unittests/meson.build
tests/unittests/ne_core_handler_test.cc
tests/unittests/ne_libnpuhost_test.cc

index 4791df7..f656b90 100644 (file)
--- a/README.md
+++ b/README.md
@@ -11,8 +11,8 @@
 ```
 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
index 9acdbfc..a4383b6 100644 (file)
@@ -17,6 +17,8 @@
 #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 {
@@ -89,6 +96,100 @@ 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.
@@ -112,6 +213,19 @@ typedef enum {
 } 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 {
@@ -151,6 +265,8 @@ typedef enum {
   SMODEL_OPS_END,
 } model_opmode;
 
+/** NPU Statistics (only for real-device envionment) */
+
 /**
  * @brief Description of npu app (per device open) status
  */
@@ -207,4 +323,24 @@ typedef struct {
   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__ */
index 5a6e54d..f64e0bd 100644 (file)
 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
@@ -213,19 +145,6 @@ int setNPU_dataInfo(npudev_h dev, uint32_t modelid,
     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
@@ -250,28 +169,6 @@ int runNPU_sync(npudev_h dev, uint32_t modelid, const input_buffers *input,
     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.
@@ -291,15 +188,6 @@ int runNPU_internalInput(npudev_h dev, uint32_t modelid, npu_input_opmode opmode
  */
 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
@@ -460,26 +348,6 @@ int allocNPU_genericBuffers (npudev_h dev, generic_buffers * buffers);
  */
 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
index a4fd178..c24993f 100644 (file)
@@ -14,7 +14,7 @@
 #ifndef NE_COMM_H__
 #define NE_COMM_H__
 
-#include <libnpuhost.h>
+#include <typedef.h>
 #include <functional>
 
 /** @brief the binded data manipulation function */
index 4b42301..d603679 100644 (file)
@@ -11,8 +11,6 @@
  * @bug No known bugs except for NYI items
  */
 
-#include <libnpuhost.h>
-
 #include "CommPlugin.h"
 
 #include <cstring>
index 1537a4a..094a7bf 100644 (file)
@@ -4,9 +4,9 @@
  * 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
@@ -15,7 +15,6 @@
 #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),
@@ -988,8 +431,6 @@ HostHandler::getDevice (npudev_h *dev, dev_type type, uint32_t id)
   }
 
   *dev = device;
-  /** This is just for backward-compatility; we don't guarantee its corresness */
-  latest_dev_ = *dev;
 
   return 0;
 }
index 115983e..9bd7210 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef __NPU_ENGINE_HANDLER_H__
 #define __NPU_ENGINE_HANDLER_H__
 
-#include <libnpuhost.h>
 #include <typedef.h>
 #include <CommPlugin.h>
 
@@ -68,8 +67,6 @@ class HostHandler {
     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);
index 2f61d15..88ad252 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <stdint.h>
 #include <typedef.h>
-#include <libnpuhost.h>
 #include <NPUdrvAPI.h>
 
 #include "ne-common.h"
index eab5904..876eee2 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <stdint.h>
 #include <stdbool.h>
-#include <libnpuhost.h>
 #include <npubinfmt.h>
 
 #include "ne-common.h"
index 0f72d88..4a2117d 100644 (file)
@@ -17,7 +17,6 @@
 #define __NE_MODEL_HH__
 
 #include <npubinfmt.h>
-#include <libnpuhost.h>
 
 #include "ne-hwmem.h"
 
index 9dae9e5..8ec8d83 100644 (file)
@@ -16,7 +16,7 @@
 #ifndef NE_SCHEDULER_H__
 #define NE_SCHEDULER_H__
 
-#include <libnpuhost.h>
+#include <typedef.h>
 #include <NPUdrvAPI.h>
 
 #include "ne-model.h"
index d4b4f40..0d9cba8 100644 (file)
@@ -39,7 +39,8 @@ static const char *loglevelstr[LOG_END] = {
 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",
index aae405c..92a5ddf 100644 (file)
@@ -43,6 +43,7 @@ typedef enum {
   _N1 = 0,
   _N11,
   _N2,
+  _N21,
   _N3,
   _N4,
   _N41,
diff --git a/src/host/libnpuhost/README.md b/src/host/libnpuhost/README.md
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/host/libnpuhost/meson.build b/src/host/libnpuhost/meson.build
deleted file mode 100644 (file)
index 8cf91da..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-## 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)
index ee5139f..d86084b 100644 (file)
@@ -1,3 +1,9 @@
-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]
+)
diff --git a/src/host/ne-host.cc b/src/host/ne-host.cc
new file mode 100644 (file)
index 0000000..4be7716
--- /dev/null
@@ -0,0 +1,568 @@
+/**
+ * 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;
+}
index 09467aa..9c6915b 100644 (file)
@@ -4,7 +4,7 @@ subdir('host')
 # Final dependencies
 ne_dependencies = [
   ne_core_dep,
-  ne_host_dep    # not used yet
+  ne_host_dep
 ]
 
 # Build library
index fe1b8a2..ac2085a 100644 (file)
@@ -128,7 +128,7 @@ if gtest_dep.found()
   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')
index 0664398..6a65b89 100644 (file)
@@ -1709,391 +1709,6 @@ TEST (ne_core_handler_test, handler_triv_stop_internal_n)
 }
 
 /**
- * @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
index 91dc104..23d8229 100644 (file)
@@ -440,6 +440,391 @@ TEST (ne_libnpuhost_test, run_internal_triv2_binfmt_v3_n)
 }
 
 /**
+ * @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