[ASR] Revise inference-related SW stack for NPU-ASR
authorDongju Chae <dongju.chae@samsung.com>
Tue, 17 Dec 2019 06:25:35 +0000 (15:25 +0900)
committer채동주/On-Device Lab(SR)/Staff Engineer/삼성전자 <dongju.chae@samsung.com>
Wed, 18 Dec 2019 09:17:40 +0000 (18:17 +0900)
This commit revises all inference-related SW stack for ASR.
It reuses exsiting codes using npu device type, using effective op.
Also, It adds new example apptest for NPU-ASR device.

Signed-off-by: Dongju Chae <dongju.chae@samsung.com>
include/common/typedef.h
src/core/ip/plugin-comm-ip.c
src/core/ne-host-input-service.c
src/core/ne-inf.c
src/core/ne-inputservice.h
src/core/npu/NPUdrvAPI.c
src/core/npu/NPUdrvAPI.h
src/core/npu/NPUemul.cpp
src/test/apptests/dummy_inference_asr.c [new file with mode: 0644]
src/test/apptests/meson.build
src/test/unittests/ne_core_npu_test.cpp

index cc9181d..b32295e 100644 (file)
@@ -21,6 +21,9 @@
 #define DEVICETYPE_ASR (0x20000) /** SR-ASR-IP 2019, Based on SRP */
 #define DEVICETYPE_MASK (0xFFFF0000)
 
+/* alias */
+#define DEVICETYPE_VISION DEVICETYPE_NPU
+
 /**
  * @brief Description of npu device types.
  */
index 77529f7..3af70ce 100644 (file)
@@ -57,8 +57,6 @@
 
 #define MAX_NUM_MODELS 1
 
-#define IS_ASR_DEVICE(npu_dev) ((npu_dev)->device_type & DEVICETYPE_ASR)
-
 /** @brief Locking macros */
 #define DEVICE_LOCK() pthread_mutex_lock(&npu_dev->mutex)
 #define DEVICE_UNLOCK() pthread_mutex_unlock(&npu_dev->mutex)
@@ -148,19 +146,21 @@ exitNEcomm (void)
 static int model_dev_validity_check (npudev_h dev, uint32_t modelid)
 {
   npu_device *npu_dev;
+  dev_type type;
 
   if (dev == NULL) {
     return -EINVAL;
   }
 
   npu_dev = dev;
-  if (IS_ASR_DEVICE(npu_dev)) {
+  type = npu_dev->device_type & DEVICETYPE_MASK;
+  if (type == DEVICETYPE_ASR) {
      if (npu_dev != libnpupriv.asr_dev)
       return -EINVAL;
 
     if (npu_dev->device_type != NPUCOND_ASR_CONN_SOCIP)
       return -EINVAL;
-  } else {
+  } else if (type == DEVICETYPE_NPU) {
     if (modelid >= libnpupriv.npu_dev->num_models)
       return -EINVAL;
 
@@ -169,6 +169,9 @@ static int model_dev_validity_check (npudev_h dev, uint32_t modelid)
 
     if (npu_dev->device_type != NPUCOND_CONN_SOCIP)
       return -EINVAL;
+  } else {
+    /* no support for other types */
+    return -EINVAL;
   }
 
   return 0;
@@ -412,7 +415,10 @@ int getASRdevice(npudev_h *dev, uint32_t id)
     /** assume that model[0] is always registered */
     if ((err = registerNPUmodelmem((npudev_h) asr_dev, NULL, &modelid)) < 0) {
       logerr (TAG, "Failed to register NPU model, errno: %d\n", err);
+
       free (asr_dev);
+      libnpupriv.asr_dev = NULL;
+
       return err;
     }
 
@@ -531,9 +537,15 @@ int registerNPUmodel(npudev_h dev, generic_buffer *model, uint32_t *modelid)
   long data_size;
   int err;
   hwmem *hwmem_ptr;
+  dev_type type;
 
-  if (IS_ASR_DEVICE((npu_device*) dev)) {
+  type = ((npu_device*) dev)->device_type & DEVICETYPE_MASK;
+  if (type == DEVICETYPE_ASR) {
+    /** asr does not require model */
     return 0;
+  } else if (type != DEVICETYPE_NPU) {
+    /** other types are not supported */
+    return -EINVAL;
   }
 
   /** check the file */
@@ -600,6 +612,7 @@ out_free:
 int unregisterNPUmodel(npudev_h dev, uint32_t modelid)
 {
   npu_device *npu_dev;
+  dev_type type;
   int err = 0;
 
   if ((err = model_dev_validity_check (dev, modelid)) < 0) {
@@ -608,8 +621,11 @@ int unregisterNPUmodel(npudev_h dev, uint32_t modelid)
   /** first stop the model, and then unregister */
 
   npu_dev = dev;
-  if (IS_ASR_DEVICE(npu_dev)) {
+  type = npu_dev->device_type & DEVICETYPE_MASK;
+  if (type == DEVICETYPE_ASR) {
     return 0;
+  } else if (type != DEVICETYPE_NPU) {
+    return -EINVAL;
   }
 
   DEVICE_LOCK();
@@ -841,6 +857,7 @@ static int activateNPUmodel(npudev_h dev, uint32_t modelid, npuOutputNotify cb,
     void *data)
 {
   npu_device *npu_dev;
+  dev_type type;
   int err;
   void *cb_data;
 
@@ -849,8 +866,9 @@ static int activateNPUmodel(npudev_h dev, uint32_t modelid, npuOutputNotify cb,
   }
 
   npu_dev = dev;
-  if (IS_ASR_DEVICE(npu_dev)) {
-    /** ASR doesn't have explit models; always set modelid to zero */
+  type = npu_dev->device_type & DEVICETYPE_MASK;
+  if (type == DEVICETYPE_ASR) {
+    /** ASR doesn't have explicit models; always set modelid to zero */
     modelid = 0;
   }
   if (npu_dev->activated_model_id == modelid) {
@@ -894,6 +912,7 @@ static int runNPU_async_util(npudev_h dev, uint32_t modelid, const input_buffers
 {
   int err = 0;
   npu_device *npu_dev = NULL;
+  dev_type type;
   buffer *buffer_ptr = NULL;
   const generic_buffer *in_buf;
   hwmem *hwmem_ptr;
@@ -906,7 +925,8 @@ static int runNPU_async_util(npudev_h dev, uint32_t modelid, const input_buffers
   in_buf = &input->bufs[0];
 
   npu_dev = dev;
-  if (IS_ASR_DEVICE(npu_dev)) {
+  type = npu_dev->device_type & DEVICETYPE_MASK;
+  if (type == DEVICETYPE_ASR) {
     /** @todo we don't have a specific decision for buffer sizes. fix this later. */
     err = libnpupriv.host_handle->resizeBuffers (in_buf->size);
     if (err < 0) {
index 40a3142..9beae19 100644 (file)
@@ -81,9 +81,13 @@ typedef struct {
   int tlb_fd;                 /**< file descriptor of TLB driver */
 
   /** private data structure per opened device */
-  int device_id;                         /**< npu device number */
+  int device_npu_id;          /**< npu device number */
+  int device_asr_id;          /**< npu-asr device number */
+
+  int fd;                     /**< configured file descriptor */
+  int npu_fd;                 /**< file descriptor for NPU device */
+  int asr_fd;                 /**< file descriptor for ASR device */
 
-  int fd;                                      /**< file descriptor for the device */
   npu_input_opmode opmode;    /**< opmode for the device */
   n40_data *data;             /**< data shared from N40 */
 
@@ -353,10 +357,18 @@ static int configureHost (inputservice *me, const model *m, n40_data *data)
   npriv->meta = npriv->model->meta;
 
   /** set the mode for the device */
-  if (me->internalInput) {
-    npriv->opmode = NPUINPUT_INTERNAL_CAM;
-  } else {
+  if (npriv->meta->type == SMODEL_OPS_NPU) {
+    if (me->internalInput) {
+      npriv->opmode = NPUINPUT_INTERNAL_CAM;
+    } else {
+      npriv->opmode = NPUINPUT_HOST;
+    }
+    npriv->fd = npriv->npu_fd;
+  } else if (npriv->meta->type == SMODEL_OPS_NPU_ASR) {
     npriv->opmode = NPUINPUT_HOST;
+    npriv->fd = npriv->asr_fd;
+  } else {
+    return -EINVAL;
   }
   npu_set_mode (npriv->fd, npriv->opmode);
 
@@ -367,30 +379,32 @@ static int configureHost (inputservice *me, const model *m, n40_data *data)
     return status;
   }
 
-  /** get base address for the model */
-  status = hwmem_get_offset (npriv->model->memblock, &model_base_offset);
-  if (status < 0) {
-    logerr(TAG, "Failed to get data from hwmem\n");
-    return status;
-  }
+  if (npriv->model->memblock) {
+    /** get base address for the model */
+    status = hwmem_get_offset (npriv->model->memblock, &model_base_offset);
+    if (status < 0) {
+      logerr(TAG, "Failed to get data from hwmem\n");
+      return status;
+    }
 
-  /** Host input service passes dmabuf id as dmabuf_id */
-  model_config.dmabuf_id = get_dmabuf_id (npriv, npriv->model->memblock);
-  if (model_config.dmabuf_id < 0) {
-    logerr(TAG, "Invalid dmabuf id for the provided model, errno: %d\n",
-        model_config.dmabuf_id);
-    return -EINVAL;
-  }
+    /** Host input service passes dmabuf id as dmabuf_id */
+    model_config.dmabuf_id = get_dmabuf_id (npriv, npriv->model->memblock);
+    if (model_config.dmabuf_id < 0) {
+      logerr(TAG, "Invalid dmabuf id for the provided model, errno: %d\n",
+          model_config.dmabuf_id);
+      return -EINVAL;
+    }
 
-  /** setup model */
-  model_config.program_size = npriv->meta->program_size;
-  model_config.program_offset_addr = model_base_offset + NPUBIN_META_SIZE;
-  model_config.weight_offset_addr = model_base_offset + NPUBIN_META_SIZE +
-    model_config.program_size;
-  status = npu_set_model(npriv->fd, &model_config);
-  if (status < 0) {
-    logerr(TAG, "Unable to set the model on the NPU\n");
-    return status;
+    /** setup model */
+    model_config.program_size = npriv->meta->program_size;
+    model_config.program_offset_addr = model_base_offset + NPUBIN_META_SIZE;
+    model_config.weight_offset_addr = model_base_offset + NPUBIN_META_SIZE +
+      model_config.program_size;
+    status = npu_set_model(npriv->fd, &model_config);
+    if (status < 0) {
+      logerr(TAG, "Unable to set the model on the NPU\n");
+      return status;
+    }
   }
 
   return 0;
@@ -437,40 +451,59 @@ static int haltHost (inputservice *me, n40_haltmode mode)
 /**
  * @brief get the status for the service
  */
-static n40_status getStatusHost (inputservice *me)
+static n40_status getStatusHost (inputservice *me, model_opmode opmode)
 {
   int status;
   n40_status nstatus;
 #if DEBUG == 1
   struct srnpu_status_arg * npu_status;
+  struct srnpu_status_arg * asr_status;
 #endif
   host_inservice_priv *npriv;
 
+  if (opmode != SMODEL_OPS_NPU && opmode != SMODEL_OPS_NPU_ASR)
+    return N40_ERROR;
+
   npriv = HOST_PRIV (me);
   assert (npriv);
 
 #if DEBUG == 1
-  npu_status = npu_get_status (npriv->fd);
-  if (npu_status != NULL) {
-    loginfo(TAG, "CP_INFO: %x\n", npu_status->cp_info);
-
-    loginfo(TAG, "CP_PROC_STAT: %x\n", npu_status->cp_proc_stat);
-    loginfo(TAG, "NPU_STAT: %x\n", npu_status->npu_stat);
-
-    loginfo(TAG, "CP_DMAI_CTRL: %x\n", npu_status->cp_dmai_ctrl);
-
-    loginfo(TAG, "CP_CNT_CFG: %x\n", npu_status->cp_cnt_cfg);
-    loginfo(TAG, "CP_CNT_FRL: %x\n", npu_status->cp_cnt_frl);
-    loginfo(TAG, "CP_CNT_FRH: %x\n", npu_status->cp_cnt_frh);
-    loginfo(TAG, "CP_CNT_STL: %x\n", npu_status->cp_cnt_stl);
-    loginfo(TAG, "CP_CNT_STH: %x\n", npu_status->cp_cnt_sth);
-    free (npu_status);
-  } else {
-    logerr (TAG, "NPU status returns NULL\n");
+  if (opmode == SMODEL_OPS_NPU) {
+    npu_status = npu_get_status (npriv->npu_fd);
+    if (npu_status != NULL) {
+      loginfo(TAG, "CP_INFO: %x\n", npu_status->cp_info);
+
+      loginfo(TAG, "CP_PROC_STAT: %x\n", npu_status->cp_proc_stat);
+      loginfo(TAG, "NPU_STAT: %x\n", npu_status->npu_stat);
+
+      loginfo(TAG, "CP_DMAI_CTRL: %x\n", npu_status->cp_dmai_ctrl);
+
+      loginfo(TAG, "CP_CNT_CFG: %x\n", npu_status->cp_cnt_cfg);
+      loginfo(TAG, "CP_CNT_FRL: %x\n", npu_status->cp_cnt_frl);
+      loginfo(TAG, "CP_CNT_FRH: %x\n", npu_status->cp_cnt_frh);
+      loginfo(TAG, "CP_CNT_STL: %x\n", npu_status->cp_cnt_stl);
+      loginfo(TAG, "CP_CNT_STH: %x\n", npu_status->cp_cnt_sth);
+      free (npu_status);
+    } else {
+      logerr (TAG, "NPU status returns NULL\n");
+    }
+  } else { /* opmode == SMODEL_OPS_NPU_ASR */
+    asr_status = npu_get_status (npriv->asr_fd);
+    if (asr_status != NULL) {
+      /** @todo add some debug info if necessary */
+      free (asr_status);
+    } else {
+      logerr (TAG, "NPU-ASR status returns NULL\n");
+    }
   }
 #endif
 
-  status = npu_check_compute_ready (npriv->fd);
+  if (opmode == SMODEL_OPS_NPU) {
+    status = npu_check_compute_ready (npriv->npu_fd);
+  } else { /* opmode == SMODEL_OPS_NPU_ASR */
+    status = npu_check_compute_ready (npriv->asr_fd);
+  }
+
   if (status < 0 && status != -EBUSY) {
     logerr(TAG, "Bad device status = %d\n", status);
     nstatus = N40_ERROR;
@@ -596,17 +629,24 @@ static int nextHost (inputservice *me, buffer *buffer)
  * @param[in] device_id device number of npu for the input service
  * @param[in] npriv host service private obj
  * @return 0 on success, errno on failure
+ * @note at least one NPU device should be opened
  */
 static int open_host_inputservice (int device_id, host_inservice_priv *npriv)
 {
-  npriv->device_id = device_id;
-  npriv->fd = npu_open(device_id);
-  if (npriv->fd < 0) {
-    logerr(TAG, "Failed to open the device, errno = %d\n", npriv->fd);
-    return npriv->fd;
+  npriv->npu_fd = npu_open(device_id, NPUCOND_CONN_SOCIP);
+  if (npriv->npu_fd < 0) {
+    logerr(TAG, "Failed to open the NPU device, errno = %d\n", npriv->npu_fd);
+  } else {
+    npriv->device_npu_id = device_id;
   }
 
-  return 0;
+  npriv->asr_fd = npu_open(device_id+1, NPUCOND_ASR_CONN_SOCIP);
+  if (npriv->asr_fd < 0) {
+    logerr(TAG, "Failed to open the ASR device, errno = %d\n", npriv->asr_fd);
+  } else {
+    npriv->device_asr_id = device_id+1;
+  }
+  return (npriv->npu_fd >= 0 || npriv->asr_fd >= 0);
 }
 
 /**
@@ -617,10 +657,17 @@ static void close_host_inputservice (host_inservice_priv *npriv)
 {
   int status;
 
-  if (npriv->fd < 0) {
-    logwarn(TAG, "Closing unopened device\n");
-  } if ((status = npu_close (npriv->fd)) < 0) {
-    logwarn(TAG, "Failed to closet the device, errno = %d\n", status);
+  if (npriv->npu_fd >= 0) {
+    status = npu_close (npriv->npu_fd);
+    if (status < 0)
+      logwarn(TAG, "Fail to close npu device, (fd:%d, err: %d)\n",
+          npriv->npu_fd, status);
+  }
+  if (npriv->asr_fd >= 0) {
+    status = npu_close (npriv->asr_fd);
+    if (status < 0)
+      logwarn(TAG, "Fail to close asr device, (fd:%d, err: %d)\n",
+          npriv->asr_fd, status);
   }
 }
 
index b0a0657..436404a 100644 (file)
@@ -21,6 +21,9 @@
 #include "ne-inf.h"
 #include "ne-inputservice.h"
 
+/** NPU devices are handled in the same input service */
+#define TO_EFFECTIVE_OP(op) \
+  (((op) == SMODEL_OPS_NPU_ASR) ? SMODEL_OPS_NPU : (op))
 #define TAG _N4
 
 /** @brief private data structure for n4 */
@@ -74,12 +77,12 @@ static void n4_callback (buffer *buf, uint64_t offset, uint64_t size,
 
   n40_data_ptr = (n40_data *) data;
   n4x = n40_data_ptr->n;
+  op = n40_data_ptr->op;
 
   /** return buffer and change state to output_ready */
   GET_MEM()->return_buffer (buf);
 
-  op = ((intptr_t) n4_priv.inputservices - (intptr_t) n4x) / sizeof (inputservice);
-  status = n4x->getStatus(n4x);
+  status = n4x->getStatus(n4x, op);
   if (status == N40_ERROR) {
     logerr (TAG, "Opmode %d in error state\n", op);
     goto exit;
@@ -94,7 +97,7 @@ exit:
   pthread_mutex_lock(&n4x->mutex);
   if (n4_priv.stopped == 1) {
     /** condition the halt that a callback is complete */
-    while ((status = n4x->getStatus(n4x)) == N40_BUSY) {
+    while ((status = n4x->getStatus(n4x, op)) == N40_BUSY) {
       pthread_cond_wait (&n4x->cond, &n4x->mutex);
     }
     pthread_cond_broadcast(&n4x->cond);
@@ -108,22 +111,19 @@ int n4_start(model_opmode op)
   int err = 0;
   n40_status status;
   inputservice *n4x;
+  model_opmode eff_op = TO_EFFECTIVE_OP(op);
 
-  if (op != SMODEL_OPS_NPU) {
-    return -EINVAL;
-  }
-
-  if (n4_priv.state[op] != CONFIGURED) {
+  if (n4_priv.state[eff_op] != CONFIGURED) {
     return -EPERM;
   }
 
-  n4x = getN4x(op);
+  n4x = getN4x(eff_op);
   if (n4x == NULL)
     return -EINVAL;
 
   pthread_mutex_lock(&n4x->mutex);
 
-  status = n4x->getStatus(n4x);
+  status = n4x->getStatus(n4x, op);
   if (status != N40_IDLE) {
     err = -EINVAL;
     goto out;
@@ -135,7 +135,7 @@ int n4_start(model_opmode op)
 out:
   pthread_mutex_unlock(&n4x->mutex);
   if (err == 0)
-    n4_priv.state[op] = STARTED;
+    n4_priv.state[eff_op] = STARTED;
 
   return err;
 }
@@ -151,22 +151,19 @@ int n4_stop(model_opmode op, stop_condition syncmode)
   inputservice *n4x;
   int err = 0;
   n40_status status;
+  model_opmode eff_op = TO_EFFECTIVE_OP(op);
 
-  if (op != SMODEL_OPS_NPU) {
-    return -EINVAL;
-  }
-
-  if (n4_priv.state[op] != STARTED) {
+  if (n4_priv.state[eff_op] != STARTED) {
     return -EPERM;
   }
 
-  n4x = getN4x(op);
+  n4x = getN4x(eff_op);
   if (n4x == NULL)
     return -EINVAL;
 
   pthread_mutex_lock(&n4x->mutex);
   n4_priv.stopped = 1;
-  status = n4x->getStatus(n4x);
+  status = n4x->getStatus(n4x, op);
 
   if (status == N40_IDLE)
     goto out;
@@ -181,7 +178,7 @@ int n4_stop(model_opmode op, stop_condition syncmode)
       if (err < 0)
         goto out;
 
-      while ((status = n4x->getStatus(n4x)) != N40_IDLE) {
+      while ((status = n4x->getStatus(n4x, op)) != N40_IDLE) {
         if (status != N40_BUSY) {
           err = -EINVAL;
           goto out;
@@ -206,7 +203,7 @@ int n4_stop(model_opmode op, stop_condition syncmode)
 out:
   pthread_mutex_unlock(&n4x->mutex);
   if (err == 0)
-    n4_priv.state[op] = CONFIGURED;
+    n4_priv.state[eff_op] = CONFIGURED;
 
   return err;
 }
@@ -214,43 +211,40 @@ out:
 /** @brief Start the configured N4 instance. For more detail, refer to the header */
 int n4_configure(model_opmode op, model *m, output_ready cb, void *cb_data)
 {
-  inputservice *n4x = getN4x(op);
+  inputservice *n4x;
   int err = 0;
   n40_data *n40_data_ptr;
   n40_status status;
+  model_opmode eff_op = TO_EFFECTIVE_OP(op);
 
-  if (op != SMODEL_OPS_NPU || m == NULL) {
+  if (m == NULL || m->meta->type != op) {
     return -EINVAL;
   }
 
-  if (n4_priv.state[op] == STARTED) {
+  if (n4_priv.state[eff_op] == STARTED) {
     return -EPERM;
   }
 
-  n4x = getN4x(op);
+  n4x = getN4x(eff_op);
   if (n4x == NULL)
     return -EINVAL;
 
   pthread_mutex_lock(&n4x->mutex);
 
-  status = n4x->getStatus(n4x);
+  status = n4x->getStatus(n4x, op);
   if (status != N40_IDLE) {
     err = -EINVAL;
     goto out;
   }
 
-  if (op != SMODEL_OPS_NPU || m->meta->type != SMODEL_OPS_NPU) {
-    err = -EINVAL;
-    goto out;
-  }
-
   /** TODO: how to know/set internalInput, waitingHalt? */
 
   /** make the n40_data */
-  n40_data_ptr = &n4_priv.n40_data_all[op];
+  n40_data_ptr = &n4_priv.n40_data_all[eff_op];
   n40_data_ptr->cb_data = n40_data_ptr;
   n40_data_ptr->cb = n4_callback;
   n40_data_ptr->n = n4x;
+  n40_data_ptr->op = op;
 
   n4_priv.cb = cb;
   n4_priv.cb_data = cb_data;
@@ -261,7 +255,7 @@ int n4_configure(model_opmode op, model *m, output_ready cb, void *cb_data)
 out:
   pthread_mutex_unlock(&n4x->mutex);
   if (err == 0)
-    n4_priv.state[op] = CONFIGURED;
+    n4_priv.state[eff_op] = CONFIGURED;
 
   return err;
 }
@@ -269,16 +263,18 @@ out:
 /** @brief Allows to enter host input data. For more detail, refer to the header */
 int n4_dataReady(void)
 {
-  inputservice *n4x = n4_priv.inputservices[n4_priv.opmode];
+  inputservice *n4x;
   n40_status status;
   int err = 0;
   buffer *buffer;
   model_opmode op = n4_priv.opmode;
+  model_opmode eff_op = TO_EFFECTIVE_OP(op);
 
-  if (n4_priv.state[op] != STARTED) {
+  if (n4_priv.state[eff_op] != STARTED) {
     return -EPERM;
   }
 
+  n4x = getN4x(eff_op);
   if (n4x == NULL)
     return -EINVAL;
 
@@ -290,9 +286,8 @@ int n4_dataReady(void)
     goto exit;
   }
 
-
   pthread_mutex_lock(&n4x->mutex);
-  status = n4x->getStatus(n4x);
+  status = n4x->getStatus(n4x, op);
   if (status == N40_ERROR) {
     logerr (TAG, "Opmode %d in error state\n", op);
     err = -EBADFD;
index 2616299..8d4d834 100644 (file)
@@ -65,7 +65,7 @@ struct _inputservice {
   int (*configure) (inputservice *me, const model *m, n40_data *data);
   int (*halt) (inputservice *me, n40_haltmode mode);
     /**< halt right now, or halt after processing this instance */
-  n40_status (*getStatus) (inputservice *me);
+  n40_status (*getStatus) (inputservice *me, model_opmode opmode);
 
   int (*start) (inputservice *me);
   int (*next) (inputservice *me, buffer *buffer);
@@ -80,6 +80,7 @@ struct _n40_data {
   void *cb_data; /**< N3's private data for the callback */
   output_ready cb; /**< N3's callback */
   inputservice *n; /**< The N4x plugin, "inputservice" */
+  model_opmode op; /**< The current operation mode of the inputservice */
 };
 
 /**
index 2e92446..be603e6 100644 (file)
@@ -38,7 +38,8 @@
 /** Base location for the device */
 #define DEV_BASE_PATH "/dev"
 /** Name for the device */
-#define DEV_NAME "srnpu"
+#define DEV_NAME_VISION "srnpu"
+#define DEV_NAME_ASR    "srasr"
 
 /**
  * Maximum number of allowed devices
@@ -60,7 +61,7 @@ typedef struct _npu_dev_priv
 {
   int internal_fd;        /**< the actual fd for the opened device */
   npu_input_opmode mode;  /**< operating for the npu */
-
+  dev_type type;          /**< npu device type (masked) */
   /**< npu configuration variables, stored for debugging purposes */
   int model_dmabuf_id;              /**< dmabuf id for the model memory */
   uint64_t program_offset_addr;     /**< offset for program instruction list */
@@ -121,11 +122,12 @@ static npu_dev_priv* fd_to_obj (int fd)
  * @brief add an entry to the fd table
  * @param[in] fd abstracted file descriptor for the device
  * @param[in] internal_fd actual non-abstracted file descriptor for the device
+ * @param[in] type npu device type
  *
  * @note actual file descriptor is referred as internal_fd, and abstracted
  *       fd is referred directly as fd
  */
-static int fd_table_add_new_entry (int fd, int internal_fd)
+static int fd_table_add_new_entry (int fd, int internal_fd, dev_type type)
 {
   if (fd >= MAX_NUM_DEVICE) {
     return -ENOMEM;
@@ -144,6 +146,7 @@ static int fd_table_add_new_entry (int fd, int internal_fd)
   napi_priv.npu_fd_table[fd]->enable = 0;
   napi_priv.npu_fd_table[fd]->model_dmabuf_id = -1;
   napi_priv.npu_fd_table[fd]->input_dmabuf_id = -1;
+  napi_priv.npu_fd_table[fd]->type = type;
 
   pthread_mutex_unlock(&napi_priv.mutex);
   return 0;
@@ -230,14 +233,21 @@ static int _npu_open (const unsigned int dev_id, const char *prefix)
  * @param[in] dev_id index of the device to be opened
  * @return file descriptor is not error. otherwise errno
  */
-int npu_open (unsigned int dev_id)
+int npu_open (unsigned int dev_id, dev_type type)
 {
   int fd;
   char prefix[64];
   int status;
   errno = 0;
 
-  snprintf(prefix, sizeof(prefix), "%s/%s", DEV_BASE_PATH, DEV_NAME);
+  /* device type is masked */
+  type &= DEVICETYPE_MASK;
+  if (type == DEVICETYPE_NPU)
+    snprintf(prefix, sizeof(prefix), "%s/%s", DEV_BASE_PATH, DEV_NAME_VISION);
+  else if (type == DEVICETYPE_ASR)
+    snprintf(prefix, sizeof(prefix), "%s/%s", DEV_BASE_PATH, DEV_NAME_ASR);
+  else
+    return -EINVAL;
 
 #if defined(ENABLE_EMUL)
   fd = dev_id;
@@ -249,7 +259,7 @@ int npu_open (unsigned int dev_id)
     return -errno;
   }
 
-  status = fd_table_add_new_entry (dev_id, fd);
+  status = fd_table_add_new_entry (dev_id, fd, type);
   if (status < 0) {
 #if !defined(ENABLE_EMUL)
     close (fd);
@@ -387,31 +397,40 @@ int npu_run_input (int fd, npu_input_config * input_config)
   if (npu_dev_priv_t == NULL)
     return -ENXIO;
 
-  if (verify_size32(input_config->activation_offset_addr0) != 0 ||
-      verify_size32(input_config->activation_offset_addr1) != 0) {
-    return -ERANGE;
-  }
-
   if (npu_dev_priv_t->mode == NPUINPUT_STOP) {
     return -EPERM;
   } else if (npu_dev_priv_t->mode != NPUINPUT_HOST) {
     return -EBADFD;
   }
 
-  /** Model should be set before running the npu with an input */
-  if (npu_dev_priv_t->model_dmabuf_id == -1) {
-    return -EPERM;
-  }
+  if (npu_dev_priv_t->type == DEVICETYPE_NPU) {
+    if (verify_size32(input_config->activation_offset_addr0) != 0 ||
+        verify_size32(input_config->activation_offset_addr1) != 0) {
+      return -ERANGE;
+    }
+
 
-  npu_dev_priv_t->input_dmabuf_id = input_config->dmabuf_id;
-  npu_dev_priv_t->activation_offset_addr0 =
-    input_config->activation_offset_addr0;
-  npu_dev_priv_t->activation_offset_addr1 =
-    input_config->activation_offset_addr1;
-  npu_dev_priv_t->enable = input_config->enable;
+    /** Model should be set before running the npu with an input */
+    if (npu_dev_priv_t->model_dmabuf_id == -1) {
+      return -EPERM;
+    }
 
-  return npu_ioctl(npu_dev_priv_t->internal_fd, SRNPU_IOCTL_RUN_INPUT,
-      input_config);
+    npu_dev_priv_t->input_dmabuf_id = input_config->dmabuf_id;
+    npu_dev_priv_t->activation_offset_addr0 =
+      input_config->activation_offset_addr0;
+    npu_dev_priv_t->activation_offset_addr1 =
+      input_config->activation_offset_addr1;
+    npu_dev_priv_t->enable = input_config->enable;
+
+    return npu_ioctl(npu_dev_priv_t->internal_fd, SRNPU_IOCTL_RUN_INPUT,
+        input_config);
+  } else if (npu_dev_priv_t->type == DEVICETYPE_ASR) {
+    /** @todo add input parameters */
+    return npu_ioctl(npu_dev_priv_t->internal_fd, SRNPU_IOCTL_RUN_ASR,
+        input_config);
+  } else {
+    return -EBADFD;
+  }
 }
 
 
index c7748a5..c4becff 100644 (file)
@@ -50,6 +50,7 @@ void fini_npu_api (void);
 /**
  * @brief open the npu device
  * @param[in] dev_id index of the device to be opened
+ * @param[in] type npu device type
  * @return file descriptor is not error. otherwise negative
  *
  * @details This will open the device using the driver (exposed via /dev).
@@ -57,7 +58,7 @@ void fini_npu_api (void);
  * @note dev_id is used to indicate device in case of multiple devices
  */
 int
-npu_open (unsigned int dev_id);
+npu_open (unsigned int dev_id, dev_type type);
 
 
 /**
@@ -180,5 +181,8 @@ npu_check_compute_ready (int fd);
 int
 npu_wait_compute_ready (int fd);
 
+/** @todo remove this after ioctl macros for ASR are defined */
+#define SRNPU_IOCTL_RUN_ASR 0x2020
+
 #endif /** __NPU_CORE_NPUdrvAPI_H__ */
 
index 218f9f2..3c83831 100644 (file)
@@ -538,6 +538,11 @@ int npu_ioctl_emul (int fd, unsigned long cmd, void *arg)
         emul.set_input(input_config);
         return emul.run();
       }
+    case SRNPU_IOCTL_RUN_ASR:
+      {
+        /** @todo */
+        return 0;
+      }
     default:
       return -EINVAL;
   }
diff --git a/src/test/apptests/dummy_inference_asr.c b/src/test/apptests/dummy_inference_asr.c
new file mode 100644 (file)
index 0000000..214bacd
--- /dev/null
@@ -0,0 +1,95 @@
+/**
+ * Proprietary
+ * Copyright (C) 2019 Samsung Electronics
+ * Copyright (C) 2019 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file dummy_inference_asr.c
+ * @date 9 Aug 2019
+ * @brief AppTest to test ASR inference capability with dummy input/output.
+ * @author Dongju Chae <dongju.chae@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libnpuhost.h>
+#include <npubinfmt.h>
+
+#include "../ne_test_utils.h"
+
+/** @brief compare output result with the golden data */
+static int
+compare_result (const void *data, uint32_t size)
+{
+  return 0;
+}
+
+/** @brief inference entry */
+static int
+run_inference (npudev_h dev)
+{
+  uint64_t buffer_size = 4096;
+  int err = -1;
+
+  input_buffers input;
+  output_buffer output;
+
+#if !defined(ENABLE_EMUL)
+  /** @todo currently, FastModel doesn't support this application
+   *  because the ASR SRP is not prepared yet. */
+  return 0;
+#endif
+
+  /** allocate I/O buffers */
+  input.num_buffers = 1;
+  if ((err = allocNPUBuffer (buffer_size, BUFFER_MAPPED, NULL, &input.bufs[0])) != 0)
+    goto out;
+  if ((err = allocNPUBuffer (buffer_size, BUFFER_MAPPED, NULL, &output)) != 0) {
+    cleanNPUBuffer (&input.bufs[0]);
+    goto out;
+  }
+
+  /** run NPU-ASR inference */
+  fill_input_data (&input.bufs[0], 0, buffer_size);
+
+  if ((err = runNPU_sync (dev, 0 /* ignored */, &input, &output)) != 0)
+    goto out;
+
+  /** compare the output result */
+  err = compare_result (output.addr, output.size);
+
+  cleanNPUBuffer (&input.bufs[0]);
+  cleanNPUBuffer (&output);
+
+out:
+  return err;
+}
+
+/** @brief apptest main  */
+int
+main (int argc, char **argv)
+{
+  npudev_h dev;
+  int num_devices = getnumASRdevice();
+  int result = -1;
+
+  if (num_devices > 0) {
+    if (getASRdevice (&dev, num_devices - 1) == 0) {
+      result = run_inference (dev);
+      if (result == 0) {
+        fprintf(stderr, "[APPTEST] %s: PASSED\n", argv[0]);
+      } else {
+        fprintf(stderr, "[APPTEST] %s: FAILED (%d)\n", argv[0], result);
+      }
+      free (dev);
+    }
+  }
+
+  return result;
+}
+
index 73e73af..d7c0754 100644 (file)
@@ -1,5 +1,6 @@
 ## For app tests, make build executables which links with 'ne_library_shared'
 
+## SRNPU VISION
 executable ('apptest_dummy_inference',
   'dummy_inference.c',
   include_directories : [ne_common_inc, ne_host_inc],
@@ -44,3 +45,13 @@ executable ('apptest_example_visa',
   install : true,
   install_dir : join_paths(ne_bindir, 'apptests')
 )
+
+## SRNPU ASR
+executable ('apptest_dummy_inference_asr',
+  'dummy_inference_asr.c',
+  include_directories : [ne_common_inc, ne_host_inc],
+  dependencies : ne_test_utils_dep,
+  link_with : ne_library_shared,
+  install : true,
+  install_dir : join_paths(ne_bindir, 'apptests')
+)
index 560bf4f..540cd86 100644 (file)
@@ -32,6 +32,8 @@ extern "C"
 #define TLB_NAME "srtlb"
 #define GEM_NAME "cgem"
 
+#define NPU_OPEN_VISION(dev_id) npu_open(dev_id, NPUCOND_CONN_SOCIP)
+
 /**
  * @brief base open and close a device
  */
@@ -41,27 +43,27 @@ TEST (ne_core_npu_test, dev_open_close)
   int ret;
 
   /** basic open and close */
-  fd = npu_open (DEV_ID);
+  fd = NPU_OPEN_VISION (DEV_ID);
   EXPECT_EQ (fd, DEV_ID);
   ret = npu_close (fd);
   EXPECT_EQ (ret, RET_SUCCESS);
 
   /** open/close multiple devices at once */
-  fd = npu_open (DEV_ID);
+  fd = NPU_OPEN_VISION (DEV_ID);
   EXPECT_EQ (fd, DEV_ID);
 #if defined(ENABLE_EMUL)
   /**
    * Opening non-existing devices only passes in test mode to test
    * functionality of NPUdrvAPI
    */
-  fd = npu_open (1);
+  fd = NPU_OPEN_VISION (1);
   EXPECT_EQ (fd, 1);
-  fd = npu_open (2);
+  fd = NPU_OPEN_VISION (2);
   EXPECT_EQ (fd, 2);
-  fd = npu_open (3);
+  fd = NPU_OPEN_VISION (3);
   EXPECT_EQ (fd, 3);
   /** open more than allowed devices */
-  fd = npu_open (16);
+  fd = NPU_OPEN_VISION (16);
   EXPECT_LT (fd, RET_SUCCESS);
   /** close unopened devices */
   ret = npu_close (17);
@@ -81,16 +83,16 @@ TEST (ne_core_npu_test, dev_open_close)
   EXPECT_EQ (ret, RET_SUCCESS);
 
   /** reopen closed device */
-  fd = npu_open (1);
+  fd = NPU_OPEN_VISION (1);
   EXPECT_EQ (fd, 1);
   ret = npu_close (fd);
 #else
   ret = npu_close (fd);
   EXPECT_EQ (ret, RET_SUCCESS);
-  fd = npu_open (1);
+  fd = NPU_OPEN_VISION (1);
   EXPECT_LT (fd, RET_SUCCESS);
   /** open more than allowed devices */
-  fd = npu_open (16);
+  fd = NPU_OPEN_VISION (16);
   EXPECT_LT (fd, RET_SUCCESS);
 #endif
   EXPECT_EQ (ret, RET_SUCCESS);
@@ -154,7 +156,7 @@ TEST (ne_core_npu_test, set_dev_data)
   EXPECT_LT (npu_set_model (fd, &model_config), RET_SUCCESS);
 
   /** basic open and close */
-  fd = npu_open (DEV_ID);
+  fd = NPU_OPEN_VISION (DEV_ID);
   EXPECT_EQ (fd, DEV_ID);
 
   /**
@@ -229,7 +231,7 @@ TEST (ne_core_npu_test, check_dev_status)
   EXPECT_EQ (npu_get_status (fd), nullptr);
 
   /** basic open and close */
-  fd = npu_open (DEV_ID);
+  fd = NPU_OPEN_VISION (DEV_ID);
   EXPECT_EQ (fd, DEV_ID);
 
   /** status on opened device */