#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)
}
npu_dev = dev;
- if (npu_dev->device_type & DEVICETYPE_ASR) {
+ if (IS_ASR_DEVICE(npu_dev)) {
if (npu_dev != libnpupriv.asr_dev)
return -EINVAL;
}
/**
+ * @brief Send the NN model to NPU.
+ * @param[in] dev The NPU device handle
+ * @param[in] model_mem The NPU NN model loaded into hwmem
+ * @param[out] modelid The modelid allocated for this instance of NN model.
+ * @return @c 0 if no error. otherwise a negative error value
+ *
+ * @detail This version does not support multimodel. Thus, dev should be
+ * emptied with unregister function before registering another.
+ * This may incur some latency with memory compatcion.
+ * @todo Add a variation: in-memory model register.
+ */
+static int registerNPUmodelmem(npudev_h dev, hwmem *model_mem, uint32_t *modelid)
+{
+ npu_device *npu_dev = (npu_device *) dev;
+ model_private *priv_model = NULL;
+ uint32_t id;
+ int err;
+
+ if (npu_dev == NULL || modelid == NULL) {
+ return -EINVAL;
+ }
+
+ if (!((npu_dev == libnpupriv.npu_dev && model_mem) ||
+ (npu_dev == libnpupriv.asr_dev && !model_mem))) {
+ return -EINVAL;
+ }
+
+ if (npu_dev->num_models == 0) {
+ pthread_mutex_init (&npu_dev->mutex, NULL);
+ pthread_cond_init (&npu_dev->cond, NULL);
+ } else if (npu_dev->num_models == MAX_NUM_MODELS) {
+ return -ENOMEM;
+ }
+
+ /** assign temporary number (but one of candidates) to id */
+ id = npu_dev->num_models;
+
+ priv_model = (model_private *) malloc (sizeof (*priv_model));
+ if (!priv_model) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ /** copy model to a created hwmem */
+ err = libnpupriv.host_handle->registerModel (model_mem,
+ &(priv_model->model_id), &(priv_model->model_version));
+ if (err < 0) {
+ logerr (TAG, "Registering model has failed, errno: %d\n", err);
+ free (priv_model);
+ goto error;
+ }
+
+ /* update variables to be set */
+ npu_dev->models[id] = priv_model;
+ npu_dev->num_models += 1;
+ *modelid = id;
+
+ return 0;
+
+error:
+ if (npu_dev->num_models == 0) {
+ pthread_cond_destroy (&npu_dev->cond);
+ pthread_mutex_destroy (&npu_dev->mutex);
+ }
+
+ return err;
+}
+
+/**
* @brief Returns the handle of the chosen ASR devices.
* @param[out] dev The ASR device handle
* @param[in] id The ASR id to get the handle. 0 <= id < getnumASRdevice().
return -EINVAL;
}
} else {
+ uint32_t modelid;
+ int err;
+
asr_dev = (npu_device *) malloc (sizeof (npu_device));
if (asr_dev == NULL) {
return -errno;
}
+
asr_dev->device_id = id;
+ asr_dev->num_models = 0;
asr_dev->sequence_in = 0;
asr_dev->sequence_out = 0;
+ asr_dev->activated_model_id = -1;
asr_dev->device_type = NPUCOND_ASR_CONN_SOCIP;
libnpupriv.asr_dev = asr_dev;
+
+ /** 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);
+ return err;
+ }
+
*dev = (npudev_h) libnpupriv.asr_dev;
}
/**
* @brief Send the NN model to NPU.
* @param[in] dev The NPU device handle
- * @param[in] model_mem The NPU NN model loaded into hwmem
- * @param[out] modelid The modelid allocated for this instance of NN model.
- * @return @c 0 if no error. otherwise a negative error value
- *
- * @detail This version does not support multimodel. Thus, dev should be
- * emptied with unregister function before registering another.
- * This may incur some latency with memory compatcion.
- * @todo Add a variation: in-memory model register.
- */
-static int registerNPUmodelmem(npudev_h dev, hwmem *model_mem, uint32_t *modelid)
-{
- npu_device *npu_dev = (npu_device *) dev;
- model_private *priv_model = NULL;
- uint32_t id;
- int err;
-
- if (npu_dev == NULL || model_mem == NULL || modelid == NULL ||
- npu_dev != libnpupriv.npu_dev) {
- return -EINVAL;
- }
-
- if (npu_dev->num_models == 0) {
- pthread_mutex_init (&npu_dev->mutex, NULL);
- pthread_cond_init (&npu_dev->cond, NULL);
- } else if (npu_dev->num_models == MAX_NUM_MODELS) {
- return -ENOMEM;
- }
-
- /** assign temporary number (but one of candidates) to id */
- id = npu_dev->num_models;
-
- priv_model = (model_private *) malloc (sizeof (*priv_model));
- if (!priv_model) {
- err = -ENOMEM;
- goto error;
- }
-
- /** copy model to a created hwmem */
- err = libnpupriv.host_handle->registerModel (model_mem,
- &(priv_model->model_id), &(priv_model->model_version));
- if (err < 0) {
- logerr (TAG, "Registering model has failed, errno: %d\n", err);
- free (priv_model);
- goto error;
- }
-
- /* update variables to be set */
- npu_dev->models[id] = priv_model;
- npu_dev->num_models += 1;
- *modelid = id;
-
- return 0;
-
-error:
- if (npu_dev->num_models == 0) {
- pthread_cond_destroy (&npu_dev->cond);
- pthread_mutex_destroy (&npu_dev->mutex);
- }
-
- return err;
-}
-
-/**
- * @brief Send the NN model to NPU.
- * @param[in] dev The NPU device handle
* @param[in] model The generic buffer for the compiled NPU NN model.
* @param[out] modelid The modelid allocated for this instance of NN model.
* @return @c 0 if no error. otherwise a negative error value
int err;
hwmem *hwmem_ptr;
+ if (IS_ASR_DEVICE((npu_device*) dev)) {
+ return 0;
+ }
+
/** check the file */
if (model == NULL) {
return -EINVAL;
/** first stop the model, and then unregister */
npu_dev = dev;
+ if (IS_ASR_DEVICE(npu_dev)) {
+ return 0;
+ }
+
DEVICE_LOCK();
if (npu_dev->activated_model_id == modelid) {
}
npu_dev = dev;
+ if (IS_ASR_DEVICE(npu_dev)) {
+ /** ASR doesn't have explit models; always set modelid to zero */
+ modelid = 0;
+ }
if (npu_dev->activated_model_id == modelid) {
/** already activated */
return 0;
return err;
}
+ /** TODO: handle more than 1 input buffer at once */
+ in_buf = &input->bufs[0];
+
npu_dev = dev;
+ if (IS_ASR_DEVICE(npu_dev)) {
+ /** @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) {
+ logerr (TAG, "Fail to resize buffers\n");
+ goto out;
+ }
+ }
/** This has to be get a new/existing buf, depending on buffering type */
buffer_ptr = libnpupriv.host_handle->getCurrentInputBuffer(mode, &err);
logwarn (TAG, "New buffer dropped by QoS\n");
goto out;
} else if (err < 0 || buffer_ptr == NULL) {
- logerr (TAG, "Error getting bufferm, errno: %d\n", err);
+ logerr (TAG, "Error getting buffer, errno: %d\n", err);
goto out;
}
goto out_unlock;
}
- /** TODO: handle more than 1 input buffer at once */
- in_buf = &input->bufs[0];
-
if (in_buf->type != BUFFER_DMABUF) {
if ((err = buffer_set_dmabuf (buffer_ptr, 0)) < 0) {
logerr (TAG, "Error disabling dmabuf sharing\n");
return err;
}
- loginfo (TAG, "Running input with sequence %d synchronously\n", sequence);
+ loginfo (TAG, "Running input with sequence %ld synchronously\n", sequence);
/** wait until the internal callback is finished */
DEVICE_LOCK();
return err;
}
- loginfo (TAG, "Running input with sequence %d asynchronously\n", sequence);
+ loginfo (TAG, "Running input with sequence %ld asynchronously\n", *sequence);
return 0;
}
}
/**
+ * @brief resize I/O buffers by force
+ * @param[in] size the buffer size; a zero size means free
+ * @return 0 if no error, otherwise a negative errno
+ * @note this should be called only for ASR inferences.
+ */
+static int
+handler_resize_buffers (uint64_t size)
+{
+ int err = 0;
+
+ HANDLER_LOCK ();
+
+ if (hpriv.buffer_size < size || hpriv.num_models == 0) {
+ err = GET_MEM()->resize_buffers (size);
+ hpriv.buffer_size = size;
+ }
+
+ HANDLER_UNLOCK ();
+
+ return err;
+}
+
+/**
* @brief create and register model with hwmem
* @param[in] mem The hwmem block/chunk with the model from the host.
* @param[in] id ID of the model registered
/** TODO: add a check that the same model has not been registered before */
- /* activate hwmem; it means that it's not compacted until unregistration */
- if ((err = hwmem_activate (hwmem)) < 0)
- goto err_free;
+ new_model = &mpriv->model;
+ new_model->inputSequence = 0;
+ new_model->meta = &mpriv->meta;
- if ((err = hwmem_get_data (hwmem, &ptr)) < 0)
- goto err_deactivate;
+ if (hwmem) {
+ /* activate hwmem; it means that it's not compacted until unregistration */
+ if ((err = hwmem_activate (hwmem)) < 0)
+ goto err_free;
- if ((err = parse_model_meta (mpriv, ptr)) < 0)
- goto err_deactivate;
+ if ((err = hwmem_get_data (hwmem, &ptr)) < 0)
+ goto err_deactivate;
- if (hpriv.buffer_size < mpriv->meta.buffer_size) {
- /* need to increase buffer size! */
- if (GET_MEM()->resize_buffers (mpriv->meta.buffer_size) != 0) {
- /* fail to resize... */
- err = -ENOMEM;
- goto err_free;
+ if ((err = parse_model_meta (mpriv, ptr)) < 0)
+ goto err_deactivate;
+
+ if (hpriv.buffer_size < mpriv->meta.buffer_size) {
+ /* need to increase buffer size! */
+ if (GET_MEM()->resize_buffers (mpriv->meta.buffer_size) != 0) {
+ /* fail to resize... */
+ err = -ENOMEM;
+ goto err_free;
+ }
+ hpriv.buffer_size = mpriv->meta.buffer_size;
}
- }
- new_model = &mpriv->model;
- new_model->meta = &mpriv->meta;
- new_model->memblock = hwmem;
- new_model->model_size = hwmem->size;
- new_model->inputSequence = 0;
+ new_model->memblock = hwmem;
+ new_model->model_size = hwmem->size;
+
+ hpriv.model_size += hwmem->size;
+ } else {
+ /* set dummy metadata */
+ mpriv->meta.type = SMODEL_OPS_NPU_ASR;
+ mpriv->meta.size = 0;
+ mpriv->meta.buffer_size = 4096;
+ mpriv->meta.input_offset = 0;
+ mpriv->meta.input_size = 4096;
+ mpriv->meta.output_offset = 0;
+ mpriv->meta.output_size = 4096;
+ mpriv->meta.model_id = 0;
+ mpriv->meta.model_version = 0;
+
+ new_model->memblock = NULL;
+ new_model->model_size = 0;
+ }
- hpriv.model_size += hwmem->size;
hpriv.num_models++;
list_add (&hpriv.model_priv_list, &mpriv->list);
model *model;
model_priv *mpriv;
int err = 0;
- uint64_t size;
+ uint64_t model_size, buffer_size;
HANDLER_LOCK ();
mpriv = GET_MODEL_PRIVATE (model);
- if ((err = hwmem_deactivate (mpriv->hwmem)) < 0)
- goto err_unlock;
+ if (mpriv->hwmem) {
+ if ((err = hwmem_deactivate (mpriv->hwmem)) < 0)
+ goto err_unlock;
- size = mpriv->hwmem->size;
- if ((err = GET_MEM()->dealloc (mpriv->hwmem)) < 0)
- goto err_activate;
+ model_size = mpriv->hwmem->size;
+ if ((err = GET_MEM()->dealloc (mpriv->hwmem)) < 0)
+ goto err_activate;
+ } else {
+ model_size = 0;
+ }
list_del (&hpriv.model_priv_list, &mpriv->list);
/* resizing should be successful because buffer is resized to equal or smaller size */
- assert (GET_MEM()->resize_buffers (get_maximum_buffer_size ()) == 0);
+ buffer_size = get_maximum_buffer_size ();
+ assert (GET_MEM()->resize_buffers (buffer_size) == 0);
free (mpriv);
assert (hpriv.num_models > 0);
hpriv.num_models--;
- hpriv.model_size -= size;
+ hpriv.model_size -= model_size;
+ hpriv.buffer_size = buffer_size;
HANDLER_UNLOCK ();
* @brief the instance of host handler. Its callbacks are called in N1.
*/
static hostHandlerInfo handler = {
+ .resizeBuffers = handler_resize_buffers,
.getSizeModels = handler_get_size_models,
.getSizeBuffers = handler_get_size_buffers,
.getNumRegisteredModels = handler_get_num_registered_models,