From 3917b2f58184dcbb7cd9acd8e93c7edb3a233672 Mon Sep 17 00:00:00 2001 From: Dongju Chae Date: Fri, 3 Apr 2020 13:48:04 +0900 Subject: [PATCH] [Refactor/Comm] Revise Comm. Plugin interface and IP plugin impl. This patch revises comm. plugin interface and IP plugin implementation. It now handles only data transfer between npu-engine and outside. Signed-off-by: Dongju Chae --- src/core/comm/CommPlugin.h | 40 ++ src/core/{ip => comm}/README.md | 0 src/core/comm/meson.build | 5 + src/core/comm/plugin-comm-ip.cc | 113 ++++ src/core/ip/meson.build | 5 - src/core/ip/plugin-comm-ip.c | 1321 --------------------------------------- src/core/ne-comm.h | 177 ------ 7 files changed, 158 insertions(+), 1503 deletions(-) create mode 100644 src/core/comm/CommPlugin.h rename src/core/{ip => comm}/README.md (100%) create mode 100644 src/core/comm/meson.build create mode 100644 src/core/comm/plugin-comm-ip.cc delete mode 100644 src/core/ip/meson.build delete mode 100644 src/core/ip/plugin-comm-ip.c delete mode 100644 src/core/ne-comm.h diff --git a/src/core/comm/CommPlugin.h b/src/core/comm/CommPlugin.h new file mode 100644 index 0000000..9dc8866 --- /dev/null +++ b/src/core/comm/CommPlugin.h @@ -0,0 +1,40 @@ +/** + * Proprietary + * Copyright (C) 2020 Samsung Electronics + * Copyright (C) 2020 Dongju Chae + */ +/** + * @file CommPlugin.h + * @date 03 Apr 2020 + * @brief Interface to access communication plugin from NPU Engine (ne) + * @author Dongju Chae + * @bug No known bugs except for NYI items + */ + +#ifndef NE_COMM_H__ +#define NE_COMM_H__ + +#include +#include + +/** @brief the binded data manipulation function */ +typedef std::function dataManipFunc; + +/** @brief communication plugin: singleton */ +class CommPlugin { + public: + static CommPlugin& getCommPlugin(); + + /** host -> npu-engine */ + virtual int extractGenericBuffer (const generic_buffer *buf, void *data, + dataManipFunc func = nullptr) = 0; + /** npu-engine -> host */ + virtual int insertGenericBuffer (void *data, generic_buffer *buf, + dataManipFunc func = nullptr) = 0; + + protected: + CommPlugin () {} + virtual ~CommPlugin() {}; +}; + +#endif /* NE_COMM_H__ */ diff --git a/src/core/ip/README.md b/src/core/comm/README.md similarity index 100% rename from src/core/ip/README.md rename to src/core/comm/README.md diff --git a/src/core/comm/meson.build b/src/core/comm/meson.build new file mode 100644 index 0000000..7371890 --- /dev/null +++ b/src/core/comm/meson.build @@ -0,0 +1,5 @@ +ne_plugin_comm_inc = include_directories ('.') +ne_plugin_comm_src = ['plugin-comm-' + get_option('comm_opt') + '.cc'] +ne_plugin_comm_dep = declare_dependency( + sources : ne_plugin_comm_src, + include_directories : ne_plugin_comm_inc) diff --git a/src/core/comm/plugin-comm-ip.cc b/src/core/comm/plugin-comm-ip.cc new file mode 100644 index 0000000..ee18b10 --- /dev/null +++ b/src/core/comm/plugin-comm-ip.cc @@ -0,0 +1,113 @@ +/** + * Proprietary + * Copyright (C) 2020 Samsung Electronics + * Copyright (C) 2020 Dongju Chae + */ +/** + * @file plugin-comm-ip.cc + * @date 03 Apr 2020 + * @brief Source of IP communication plugin + * @author Dongju Chae + * @bug No known bugs except for NYI items + */ + +#include + +#include "CommPlugin.h" + +#include +#include +#include +#include + +#define TAG _N11 + +/** + * Because it's IP communication plugin, it can directly transfer data between + * npu-engine and outside, without via an event handler (e.g., USB event handler). + * Note that we don't support different types of plugins at the same time. + */ + +/** @brief IP communication plugin */ +class CommPluginIP : public CommPlugin { +public: + /** @brief get singleton instance */ + static CommPluginIP & getInstance () { + call_once (once_flag_, []() { + instance_.reset (new CommPluginIP); + }); + return *(instance_.get ()); + }; + + /** + * @brief extract data from generic buffer + * @param[in] buf generic buffer + * @param[in] data data to be written + * @param[in] func data manipulation function + * @return 0 if no error. otherwise a negative errno + */ + int extractGenericBuffer (const generic_buffer *buf, void *data, + dataManipFunc func = nullptr) { + /** Note that npu-engine supports data manipulation only for the BUFFER_MAPPED. + * Thus, for other types, user need to ensure that the data format in the dmabuf + * is compatible with the device. */ + if (buf->type == BUFFER_FILE) { + std::ifstream ifs (buf->filepath, std::ios::binary); + if (ifs.good()) { + ifs.read(static_cast(data), buf->size); + size_t count = ifs.gcount(); + ifs.close(); + + if (count != buf->size) + return -EINVAL; + } + } else if (buf->type == BUFFER_MAPPED) { + if (func != nullptr) + func (data, buf->addr, buf->size); + else + memcpy (data, buf->addr, buf->size); + } else { + return -EINVAL; + } + + return 0; + } + + /** + * @brief insert data to generic buffer + * @param[in] data data to be read + * @param[in] buf generic buffer + * @param[in] func data manipulation function + * @return 0 if no error. otherwise a negative errno + */ + int insertGenericBuffer (void *data, generic_buffer *buf, + dataManipFunc func = nullptr) { + /** This support only BUFFER_MAPPED for now */ + if (buf->type != BUFFER_MAPPED) + return -EINVAL; + + if (func != nullptr) + func (buf->addr, data, buf->size); + else + memcpy (buf->addr, data, buf->size); + + return 0; + } + +private: + CommPluginIP () {}; + + static std::unique_ptr instance_; + static std::once_flag once_flag_; +}; + +std::unique_ptr CommPluginIP::instance_; +std::once_flag CommPluginIP::once_flag_; + +/** + * @brief get communication plugin instance + * @note only one plugin can implement CommPlugin::createCommPlugin() + */ +CommPlugin& CommPlugin::getCommPlugin () { + return CommPluginIP::getInstance(); +} diff --git a/src/core/ip/meson.build b/src/core/ip/meson.build deleted file mode 100644 index cc04f8c..0000000 --- a/src/core/ip/meson.build +++ /dev/null @@ -1,5 +0,0 @@ -ne_plugin_comm_ip_src = ['plugin-comm-ip.c'] -ne_plugin_comm_dep = declare_dependency( - sources : ne_plugin_comm_ip_src, - dependencies : [ne_core_utils_dep], - include_directories : [ne_common_inc, ne_host_inc, ne_core_inc]) diff --git a/src/core/ip/plugin-comm-ip.c b/src/core/ip/plugin-comm-ip.c deleted file mode 100644 index 93af914..0000000 --- a/src/core/ip/plugin-comm-ip.c +++ /dev/null @@ -1,1321 +0,0 @@ -/** - * Proprietary - * Copyright (C) 2019 Samsung Electronics - * Copyright (C) 2019 MyungJoo Ham - * Copyright (C) 2019 Parichay Kapoor - * Copyright (C) 2019 Dongju Chae - */ -/** - * @file plugin-comm-ip.c - * @date 26 Jul 2019 - * @brief Implement API to access NPU from Host - * @see http://suprem.sec.samsung.net/confluence/display/ODLC/Software+Stack - * @author MyungJoo Ham - * @author Parichay Kapoor - * @author Dongju Chae - * @bug No known bugs except for NYI items - * - * @note This version does not support multi-model. - * Therefore registerNPUModel always returns "FULL" if there is a model - * registered. - * @note This version does not support multi-device. - * Therefor getnumNPUdevice returns 1, 0 or -1. - * - * @note This program is not thread safe - * - * @todo This does not support the case where NPU-IP not available while ASR-IP available. - * @todo The ASR-NPU common part should be separated. - * - * To packagers: this is exported to HOST PROGRAMMERS as a devel package. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define TAG _N11 - -#define DEV_BASE_PATH "/dev" -#define DEV_NAME_NPU "triv" -#define DEV_NAME_ASR "srasr" -#define DEV_NAME_SIZE 128 -#define DEV_MAX_OFFSET 16 -#define DEFAULT_FORCE_STOP true - -#define MAX_NUM_MODELS 1 - -/** @brief Locking macros */ -#define DEVICE_LOCK() pthread_mutex_lock(&npu_dev->mutex) -#define DEVICE_UNLOCK() pthread_mutex_unlock(&npu_dev->mutex) -#define DEVICE_WAKEUP() pthread_cond_broadcast (&npu_dev->cond) -#define DEVICE_WAIT() pthread_cond_wait (&npu_dev->cond, &npu_dev->mutex); - -/** @brief Private data structure oer model */ -typedef struct { - uint64_t model_id; /**< model id returned from registration */ - uint64_t model_version; /**< model version returned from registration */ - tensors_data_info info_in; /**< layout/type info of input tensors */ - tensors_data_info info_out; /**< layout/type info of output tensors */ - npuConstraint constraint; /**< constraints for inferences */ - npuOutputNotify cb; /**< callback after finish running this model */ - void *cb_data; /**< callback data */ -} model_private; - -/** @brief Private data structure per device */ -typedef struct { - dev_type device_type; /**< NPU or ASR / Connection Type - The first word MUST be this. */ - int device_id; /**< id of the device */ - int num_models; /**< num of models loaded */ - model_private *models[MAX_NUM_MODELS]; /**< private for each model */ - int activated_model_id; /**< currently activated model */ - uint64_t sequence_in; /**< increasing number for running input */ - pthread_mutex_t mutex; /**< mutex for locking */ - pthread_cond_t cond; /**< for syncing running the device */ -} npu_device; - -/** @brief private data structure for the lib npu host */ -struct lib_npu_private { - npu_device *npu_dev; /**< npu device handle */ - npu_device *asr_dev; /**< asr device handle */ - int init_status; /**< status of init ne handler */ - const hostHandlerInfo *host_handle; /**< host handler */ -}; - -/** @brief private data for the libnpu */ -static struct lib_npu_private libnpupriv; - -/** @brief declare as constructor and destructor */ -void init_lib_npu (void) __attribute__ ((constructor(PLUGIN_PRIORITY))); -void fini_lib_npu (void) __attribute__ ((destructor(PLUGIN_PRIORITY))); - -/** @brief constructor for the lib npu */ -void init_lib_npu (void) -{ - libnpupriv.npu_dev = NULL; - libnpupriv.asr_dev = NULL; - /** TODO: set conf path of npu-engine.ini file?? */ - libnpupriv.init_status = load_conf (NULL); - if (libnpupriv.init_status == 0) { - libnpupriv.init_status = init_ne_handler (); - } -} - -/** @brief destructor for the lib npu */ -void fini_lib_npu (void) -{ - if (libnpupriv.init_status == 0) { - exit_ne_handler (); - } -} - -/** @brief init comm for ip */ -int -initNEcomm (const hostHandlerInfo *hh, dev_type type) -{ - if (type != NPUCOND_CONN_SOCIP) { - return -EINVAL; - } - libnpupriv.host_handle = hh; - return 0; -} - -/** @brief exit comm for ip */ -int -exitNEcomm (void) -{ - return 0; -} - -/** - * @brief Check the validity of the device handle and id - * @param[in] dev Device handle - * @param[in] modelid ID of the model to run - */ -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; - 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 if (type == DEVICETYPE_NPU) { - if (modelid >= libnpupriv.npu_dev->num_models) - return -EINVAL; - - if (npu_dev != libnpupriv.npu_dev) - return -EINVAL; - - if (npu_dev->device_type != NPUCOND_CONN_SOCIP) - return -EINVAL; - } else { - /* no support for other types */ - return -EINVAL; - } - - return 0; -} - -/** - * @brief return the number of devices with the requested device name - * @param[in] base the base path of device - * @param[in] name the device name - * @return @c the number of devices - */ -static int getnumdevice(const char *base, const char *name) -{ - char filename[DEV_NAME_SIZE + 1]; - int offset, ret; - int num_devices = 0; - - /** assume that device has a suffix offset if there are multiple devices */ - for (offset = 0; offset < DEV_MAX_OFFSET; offset++) { - ret = snprintf (filename, DEV_NAME_SIZE, "%s/%s-%d", base, name, offset); - if (ret < 0) - return ret; - - filename[ret] = '\x00'; - if (access(filename, F_OK) == 0) - num_devices++; - else - break; - } - - /** check a device wiht no-suffix name as well */ - ret = snprintf (filename, DEV_NAME_SIZE, "%s/%s", base, name); - if (ret < 0) - return ret; - - filename[ret] = '\x00'; - if (access(filename, F_OK) == 0) - num_devices++; - - return num_devices; -} - - -/** - * @brief Returns the list of 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. - */ -int getnumNPUdevice(void) -{ -#if defined(ENABLE_EMUL) - /** test mode deos not need device */ - return 1; -#endif - - return getnumdevice(DEV_BASE_PATH, DEV_NAME_NPU); -} - -/** - * @brief Returns the list of ASR devices. - * @return @c The number of ASR devices. - * @retval 0 if no ASR devices available. if positive (number of ASRs) if NPU devices available. otherwise, a negative error value. - */ -int getnumASRdevice(void) -{ -#if defined(ENABLE_EMUL) - /** test mode deos not need device */ - return 1; -#endif - - return getnumdevice(DEV_BASE_PATH, DEV_NAME_ASR); -} - -/** - * @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 < getNumNPUDevices(). - * @return @c 0 if no error. otherwise a negative error value - */ -int getNPUdevice(npudev_h *dev, uint32_t id) -{ - int num_devices; - int idx; - npu_device *npu_dev; - - num_devices = getnumNPUdevice(); - if (num_devices < 0) { - return num_devices; - } - - if (id >= num_devices) { - return -ERANGE; - } - - /** Current implementation only supports one NPU device at once */ - if (libnpupriv.npu_dev != NULL) { - if (libnpupriv.npu_dev->device_id == id) { - *dev = (npudev_h) libnpupriv.npu_dev; - return 0; - } else { - return -EINVAL; - } - } else { - npu_dev = (npu_device *) malloc (sizeof (npu_device)); - if (npu_dev == NULL) { - return -errno; - } - npu_dev->device_id = id; - npu_dev->num_models = 0; - npu_dev->sequence_in = 0; - npu_dev->activated_model_id = -1; - npu_dev->device_type = NPUCOND_CONN_SOCIP; - /** @todo This should be determined after communicating with device driver */ - for (idx = 0; idx < MAX_NUM_MODELS; idx ++) { - npu_dev->models[idx] = NULL; - } - - libnpupriv.npu_dev = npu_dev; - *dev = (npudev_h) libnpupriv.npu_dev; - } - - return 0; -} - -/** - * @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 @c 0 if no error. otherwise a negative error value - */ -int getASRdevice(npudev_h *dev, uint32_t id) -{ - npu_device *asr_dev; - int num_devices; - - num_devices = getnumASRdevice(); - if (num_devices < 0) { - return num_devices; - } - - if (id >= num_devices) { - return -ERANGE; - } - - /** Current implementation only supports one ASR device at once */ - if (libnpupriv.asr_dev != NULL) { - if (libnpupriv.asr_dev->device_id == id) { - *dev = (npudev_h) libnpupriv.asr_dev; - return 0; - } else { - 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->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 = registerNPUmodel((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; - } - - *dev = (npudev_h) libnpupriv.asr_dev; - } - - return 0; -} - -/** - * @brief Returns the handle of an NPU device meeting the condition - * @param[out] dev The NPU device handle - * @param[in] cond The condition for device search. - * @return @c 0 if no error. otherwise a negative error value - * - * @todo THIS IS NPU-ASR COMMON PART. Needs Refactoring! - */ -int getNPUdeviceByCondition(npudev_h *dev, const npucondition *cond) -{ - if (cond->connection == NPUCOND_CONN_SOCIP || - cond->connection == NPUCOND_CONN_UNKNOWN) { - /** Sort and loads are unused for now - only 1 NPU device supported for now */ - return getNPUdevice (dev, 0); - } - - if (cond->connection == NPUCOND_ASR_CONN_UNKNOWN || - cond->connection == NPUCOND_ASR_CONN_SOCIP) { - return getASRdevice (dev, 0); - } - - return -EINVAL; -} - -/** - * @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 NULL - * - * @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. - * - * @todo need refactoring - */ -npubin_meta * getNPUmodel_metadata(const char *model, bool need_extra) -{ - npubin_meta *meta; - FILE *fp; - int ret; - - if (!model) - return NULL; - - fp = fopen (model, "rb"); - if (!fp) { - logerr (TAG, "Failed to open the model binary: %d\n", -errno); - return NULL; - } - - 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 *) realloc (meta, NPUBIN_META_TOTAL_SIZE(meta->magiccode)); - if (!new_meta) { - logerr (TAG, "Failed to allocate extra metadata\n"); - goto exit_free; - } - - ret = fread (new_meta->reserved_extra, 1, NPUBIN_META_EXTRA_SIZE (meta->magiccode), fp); - if (ret != NPUBIN_META_EXTRA_SIZE (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 NULL; -} - -/** - * @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 - * - * @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. - */ - -int registerNPUmodel(npudev_h dev, generic_buffer *model, uint32_t *modelid) -{ - npu_device *npu_dev = (npu_device *) dev; - model_private *priv_model = NULL; - dev_type type; - uint32_t id; - int err; - - if (!npu_dev || !modelid) - return -EINVAL; - - type = npu_dev->device_type & DEVICETYPE_MASK; - if (type != DEVICETYPE_NPU && type != DEVICETYPE_ASR) { - /** other types are not supported */ - 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; - } - - /** call a handler's registerModel() */ - err = libnpupriv.host_handle->registerModel (model, - &(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; - } - - /** set default values for the model */ - priv_model->constraint.timeout_ms = DEFAULT_TIMEOUT; - priv_model->constraint.priority = DEFAULT_PRIORITY; - - priv_model->info_in.num_info = 1; - priv_model->info_in.info[0].layout = DATA_LAYOUT_SRNPU; - priv_model->info_in.info[0].type = DATA_TYPE_SRNPU; - priv_model->info_out.num_info = 1; - priv_model->info_out.info[0].layout = DATA_LAYOUT_SRNPU; - priv_model->info_out.info[0].type = DATA_TYPE_SRNPU; - - /** 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 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) -{ - npu_device *npu_dev; - dev_type type; - int err = 0; - - if ((err = model_dev_validity_check (dev, modelid)) < 0) { - return err; - } - /** first stop the model, and then unregister */ - - npu_dev = dev; - type = npu_dev->device_type & DEVICETYPE_MASK; - if (type == DEVICETYPE_ASR) { - return 0; - } else if (type != DEVICETYPE_NPU) { - return -EINVAL; - } - - DEVICE_LOCK(); - - if (npu_dev->activated_model_id == modelid) { - err = libnpupriv.host_handle->setOpMode (NPUINPUT_STOP, DEFAULT_FORCE_STOP, - npu_dev->models[modelid]->model_id, - npu_dev->models[modelid]->model_version, NULL, NULL); - if (err < 0) { - goto out; - } - } - - err = libnpupriv.host_handle->unregisterModel( - npu_dev->models[modelid]->model_id, - npu_dev->models[modelid]->model_version); - if (err < 0) { - goto out; - } - - npu_dev->num_models -= 1; - free (npu_dev->models[modelid]); - npu_dev->models[modelid] = NULL; - if (npu_dev->activated_model_id == modelid) { - npu_dev->activated_model_id = -1; - } - - if (npu_dev->num_models == 0) { - pthread_mutex_destroy (&npu_dev->mutex); - pthread_cond_destroy (&npu_dev->cond); - } - -out: - DEVICE_UNLOCK(); - return err; -} - -/** - * @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) -{ - int idx, err; - int ret = 0; - - for (idx = 0; idx < MAX_NUM_MODELS; idx += 1) { - if ((err = unregisterNPUmodel (dev, idx)) < 0) { - ret = err; - } - } - - return ret; -} - -/** - * @brief Set the target model's 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 - */ -int setNPU_dataInfo(npudev_h dev, uint32_t modelid, - tensors_data_info *info_in, tensors_data_info *info_out) -{ - npu_device *npu_dev; - int err; - - if ((err = model_dev_validity_check (dev, modelid)) < 0) { - return err; - } - - if (!info_in || !info_out) { - logerr (TAG, "Invalid info arguments\n"); - return -EINVAL; - } - - npu_dev = dev; - - DEVICE_LOCK(); - - memcpy(&npu_dev->models[modelid]->info_in, info_in, - sizeof (tensors_data_info)); - memcpy(&npu_dev->models[modelid]->info_out, info_out, - sizeof (tensors_data_info)); - - DEVICE_UNLOCK(); - - return 0; -} - -/** - * @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) -{ - npu_device *npu_dev; - - int err; - - if ((err = model_dev_validity_check (dev, modelid)) < 0) { - return err; - } - - npu_dev = dev; - - DEVICE_LOCK(); - - memcpy (&npu_dev->models[modelid]->constraint, - &constraint, sizeof (npuConstraint)); - - DEVICE_UNLOCK(); - - return 0; -} - -/** - * @brief Receives NPU results. - * @param[in] buffer_ptr NPU results. - * @param[in] data Callback data. - */ -static void npu_callback (buffer *buffer_ptr, void *data) -{ - model_private *priv_model; - npuOutputNotify output_callback; - void *cb_data; - npu_device *npu_dev; - int modelid; - int err; - -#ifdef ENABLE_BUFFERING - buffer *buffer_ptr_verify; - /** it's just a double-check */ - buffer_ptr_verify = libnpupriv.host_handle->getCurrentOutputBuffer(&err); - if (buffer_ptr_verify == NULL) { - logerr (TAG, "Error getting current output buffer, errno: %d", err); - } - assert (buffer_ptr_verify == buffer_ptr); -#endif - - npu_dev = data; - - DEVICE_LOCK(); - - modelid = npu_dev->activated_model_id; - priv_model = npu_dev->models[modelid]; - - output_callback = priv_model->cb; - cb_data = priv_model->cb_data; - - DEVICE_UNLOCK(); - - if (output_callback != NULL) { - output_buffers *output_buf; - npubin_meta meta; - - err = libnpupriv.host_handle->getModelMeta ( - priv_model->model_id, priv_model->model_version, &meta); - if (err < 0) { - logerr (TAG, "Failed getting model metadata, errno: %d\n", err); - goto out_wake; - } - - output_buf = malloc (sizeof (output_buffers)); - if (output_buf == NULL) { - logerr (TAG, "Failed allocating output buffer\n"); - goto out_wake; - } - - err = libnpupriv.host_handle->extractOutputBuffer (&meta, - &npu_dev->models[modelid]->info_out, buffer_ptr, output_buf); - if (err < 0) { - free (output_buf); - logerr (TAG, "Failed extracting output buffer, errno: %d\n", err); - goto out_wake; - } - - /** - * After this callback, the NPU Engine loses the ownership of the output buffer. - * So, the callback should free the output buffer. - */ - output_callback (output_buf, buffer_ptr->sequence, cb_data); - -#ifdef ENABLE_BUFFERING - GET_MEM()->return_buffer (buffer_ptr); -#else - GET_MEM()->reset_buffer (buffer_ptr); -#endif - } - - return; - -out_wake: - DEVICE_LOCK(); - -#ifdef ENABLE_BUFFERING - GET_MEM()->return_buffer (buffer_ptr); -#else - GET_MEM()->reset_buffer (buffer_ptr); -#endif - DEVICE_WAKEUP(); - - DEVICE_UNLOCK(); - - return; -} - -/** - * @brief Tell NPU that you are going to use this model for next inferences. - * @param[in] dev The NPU device handle - * @param[in] modelid The model to be inferred. - * @param[in] cb The output buffer handler. - * @param[in] data The data given as a parameter to the runNPU_async call. - * @return @c 0 if no error. otherwise a negative error value - * - * @detail This cleans up buffers and stops the current inferences if - * a different model has been operating in this NPU. - * If you have only one model registered, you do not need this. - * - * This is required to clean up double-buffering. You do not want - * the previous model to process the new buffer with next model. - * - * Called automatically with runNPU_* internally. - * - * @todo Are we going to support blocking call of activate-model that will wait for the current on-going inference? - */ -static int activateNPUmodel(npudev_h dev, uint32_t modelid, npu_input_opmode opmode, - npuOutputNotify cb, void *data) -{ - npu_device *npu_dev; - dev_type type; - int err; - void *cb_data; - - npu_dev = dev; - 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) { - /** already activated */ - return 0; - } - - npu_dev->models[modelid]->cb = cb; - npu_dev->models[modelid]->cb_data = data; - - /** TODO: properly setup force */ - cb_data = npu_dev; - err = libnpupriv.host_handle->setOpMode (opmode, DEFAULT_FORCE_STOP, - npu_dev->models[modelid]->model_id, - npu_dev->models[modelid]->model_version, npu_callback, cb_data); - if (err < 0) { - return err; - } - - npu_dev->activated_model_id = modelid; - return 0; -} - -/** - * Details for how the NPU Engine handles multiple tensors - * - * The NPU engine (NE) relies on a single physically-contiguous buffer to interact NPU HW. - * So, if there are multiple tensors, they should be properly located in that buffer, - * depending on how users provide tensors' buffers. - * - * 1) BUFFER_MAPPED: common case for most user apps - * - User apps access NE APIs using their own memory buffers (e.g., via malloc()). - * But, memcpy is unavoidable because tensor data should be relocated to the internal buffer. - * - * 2) BUFFER_DMABUF: performance-aware case for advanced user apps - * - User apps have a pre-allocated physically-contiguous buffer (i.e., dmabuf fd). - * In most cases, it can avoid uncessary memcpy for performance. But, it may still perform - * mempy if data manipulation is required (due to zero padding and interleaving). - */ - -/** - * @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 - * - * @todo THIS IS NPU-ASR COMMON PART. Needs Refactoring! - */ -static int runNPU_async_util(npudev_h dev, uint32_t modelid, const input_buffers *input, - npuOutputNotify cb, uint64_t *sequence, void *data, - npu_async_mode mode) -{ - buffer *buffer_ptr = NULL; - npu_device *npu_dev = dev; - npu_priority priority; - npubin_meta meta; - dev_type type; - int err = 0; - uint64_t timestamp; - - if ((err = model_dev_validity_check (dev, modelid)) < 0) { - return err; - } - - /** at least one input buffer should be provided */ - if (input->num_buffers == 0) - return -EINVAL; - - timestamp = get_timestamp(npu_dev->models[modelid]->constraint.timeout_ms); - priority = npu_dev->models[modelid]->constraint.priority; - - type = npu_dev->device_type & DEVICETYPE_MASK; - if (type == DEVICETYPE_ASR) { - /** assume that ASR requires only a single pair of input/output data (or tensor) */ - if (input->num_buffers != 1) - return -EINVAL; - -#ifdef ENABLE_BUFFERING - /** @todo we don't have a specific decision for buffer sizes. fix this later. */ - if ((err = libnpupriv.host_handle->resizeBuffers (input->bufs[0].size)) < 0) { - logerr (TAG, "Fail to resize buffers\n"); - return err; - } -#endif - } - - DEVICE_LOCK(); - - if ((err = activateNPUmodel (dev, modelid, NPUINPUT_HOST, cb, data)) < 0) { - logerr (TAG, "Error activating NPU model\n"); - goto out_unlock; - } - - if ((err = libnpupriv.host_handle->getModelMeta ( - npu_dev->models[modelid]->model_id, - npu_dev->models[modelid]->model_version, - &meta)) < 0) { - logerr (TAG, "Error getting the model's metadata\n"); - goto out_unlock; - } - - DEVICE_UNLOCK(); - -#ifdef ENABLE_BUFFERING - /** This has to be get a new/existing buf, depending on buffering type */ - buffer_ptr = libnpupriv.host_handle->getCurrentInputBuffer(mode, &err); -#else - buffer_ptr = GET_MEM()->create_buffer(meta.buffer_size, &err); -#endif - if (err < 0) { - if (mode == NPUASYNC_DROP_NEW && err == -EBUSY) - logwarn (TAG, "New buffer dropped by QoS\n"); - else - logerr (TAG, "Error getting buffer, errno: %d\n", err); - return err; - } - assert (buffer_ptr != NULL); - - DEVICE_LOCK(); - - if ((err = libnpupriv.host_handle->feedInputBuffer (&meta, - &npu_dev->models[modelid]->info_in, input, buffer_ptr) < 0)) { - logerr (TAG, "Error feeding input data for inference\n"); - goto out_unlock; - } - - buffer_ptr->sequence = npu_dev->sequence_in + 1; - - DEVICE_UNLOCK(); - - if ((err = libnpupriv.host_handle->validateBuffer (buffer_ptr, - priority, timestamp)) < 0) { - logerr (TAG, "Error validating buffer, errno: %d\n", err); - return err; - } - - DEVICE_LOCK(); - - *sequence = ++npu_dev->sequence_in; - -out_unlock: - DEVICE_UNLOCK(); - return err; -} - -/** - * @brief internal callback data for runNPU_sync() - */ -typedef struct { - npu_device *npu_dev; - output_buffers *user_output; - bool handled; -} sync_cb_data; - -/** - * @brief internal callback for runNPU_sync() - * @param[in] output output buffer - * @param[in] sequence sequence number - * @param[in] data callback data - */ -static void sync_callback (output_buffers *output, uint64_t sequence, - void *data) -{ - sync_cb_data *cb_data; - npu_device *npu_dev; - - assert (output && data); - - cb_data = data; - npu_dev = cb_data->npu_dev; - - DEVICE_LOCK(); - - /** just copy output_buffers */ - memcpy (cb_data->user_output, output, sizeof (output_buffers)); - cb_data->handled = true; - free (output); - - /** wake the sync process up, if any */ - DEVICE_WAKEUP(); - DEVICE_UNLOCK(); -} - -/** - * @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. - * - * @todo THIS IS NPU-ASR COMMON PART. Needs Refactoring! - */ -int runNPU_sync(npudev_h dev, uint32_t modelid, const input_buffers *input, - output_buffers *output) -{ - int err; - uint64_t sequence; - npu_device *npu_dev; - sync_cb_data cb_data = { - .npu_dev = dev, - .user_output = output, - .handled = false, - }; - - npu_dev = dev; - - if (output == NULL || input == NULL || input->num_buffers == 0) { - return -EINVAL; - } - - err = runNPU_async_util(dev, modelid, input, sync_callback, &sequence, &cb_data, - NPUASYNC_DROP_OLD); - if (err < 0) { - return err; - } - - loginfo (TAG, "Running input with sequence %" PRIu64 " synchronously\n", sequence); - - /** wait until the internal callback is finished */ - DEVICE_LOCK(); - if (!cb_data.handled) - DEVICE_WAIT(); - DEVICE_UNLOCK(); - - return 0; -} - -/** - * @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. - * - * @todo THIS IS NPU-ASR COMMON PART. Needs Refactoring! - * @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) -{ - int err; - - if (sequence == NULL || input == NULL || input->num_buffers == 0) { - return -EINVAL; - } - - if (cb == NULL) { - return -EINVAL; - } - - err = runNPU_async_util (dev, modelid, input, cb, sequence, data, mode); - if (err < 0) { - return err; - } - - loginfo (TAG, "Running input with sequence %" PRIu64 " asynchronously\n", *sequence); - - return 0; -} - -/** - * @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] cb The output buffer handler. - * @param[in] data Internal data to be given to the callback, cb. - * @return @c 0 if no error. otherwise a negative error value - */ -int runNPU_internalInput(npudev_h dev, uint32_t modelid, - npu_input_opmode opmode, npuOutputNotify cb, - void *data) -{ - npu_device *npu_dev; - npu_priority priority; - uint64_t timestamp; - uint64_t sequence; - int err; - - if ((err = model_dev_validity_check (dev, modelid)) < 0) { - return err; - } - - npu_dev = dev; - timestamp = get_timestamp(npu_dev->models[modelid]->constraint.timeout_ms); - priority = npu_dev->models[modelid]->constraint.priority; - - DEVICE_LOCK(); - if ((err = activateNPUmodel (dev, modelid, opmode, cb, data)) < 0) { - logerr (TAG, "Error activating NPU model\n"); - DEVICE_UNLOCK(); - return err; - } - DEVICE_UNLOCK(); - - if ((err = libnpupriv.host_handle->validateBuffer (NULL, - priority, timestamp)) < 0) { - logerr (TAG, "Error validating buffer, errno: %d\n", err); - return err; - } - - DEVICE_LOCK(); - sequence = ++npu_dev->sequence_in; - DEVICE_UNLOCK(); - - loginfo (TAG, "Running input with sequence %" PRIu64 " synchronously\n", sequence); - - return 0; -} - -/** - * @brief Allocate a buffer for NPU model with the requested buffer type. - * @param[in/out] Buffer the buffer pointer where memory is allocated. - * @return 0 if no error, otherwise a negative errno. - */ -int allocModelBuffer (generic_buffer *buffer) -{ - return GET_MEM()->alloc_npu_buffer (buffer); -} - -/** - * @brief Free the buffer and remove the address mapping. - * @return 0 if no error, otherwise a negative errno. - */ -int cleanModelBuffer (generic_buffer *buffer) -{ - return GET_MEM()->clean_npu_buffer (buffer); -} - -/** - * @brief Allocate a buffer for NPU input with the requested buffer type. - * @param[in/out] Buffer the buffer pointer where memory is allocated. - * @return 0 if no error, otherwise a negative errno. - * @note please utilize allocInputBuffers() for multiple input tensors because subsequent - * calls of allocInputBuffer() don't gurantee contiguous allocations between them. - */ -int allocInputBuffer (generic_buffer *buffer) -{ - return GET_MEM()->alloc_npu_buffer (buffer); -} - -/** - * @brief Free the buffer and remove the address mapping. - * @return 0 if no error, otherwise a negative errno. -*/ -int cleanInputBuffer (generic_buffer *buffer) -{ - return GET_MEM()->clean_npu_buffer (buffer); -} - -/** - * @brief Allocate input buffers (multiple instances of generic_buffers) - * @param[in/out] input input buffers. - * @return 0 if no error, otherwise a negative errno. - * @note it reuses allocInputbuffer(). - * @details This function is used to gurantee physically-contiguous memory for multiple tensors - * (for BUFFER_DMABUF). So, it should be used for multiple input tensors in a single - * inference (not batch size). - */ -int allocInputBuffers (input_buffers * input) -{ - generic_buffer *buf; - buffer_types type; - int idx, err = 0; - - if (!input || input->num_buffers < 1) - return -EINVAL; - - /* assume that the first buffer type decides that of the whole buffer (in case of DMABUF) */ - type = input->bufs[0].type; - if (type == BUFFER_DMABUF) { - uint64_t total_size = 0; - uint64_t first_size = input->bufs[0].size; - uint64_t offset; - - for (idx = 0; idx < input->num_buffers; ++idx) { - buf = &input->bufs[idx]; - total_size += buf->size; - } - - input->bufs[0].type = type; - input->bufs[0].size = total_size; - err = allocInputBuffer (&input->bufs[0]); - if (err != 0) - return err; - - input->bufs[0].size = first_size; - offset = first_size; - for (idx = 1; idx < input->num_buffers; ++idx) { - /* copy dmabuf info to other tensors but set different offsets */ - input->bufs[idx].dmabuf = input->bufs[0].dmabuf; - input->bufs[idx].offset = input->bufs[0].offset + offset; - input->bufs[idx].priv = input->bufs[0].priv; - - offset += input->bufs[idx].size; - } - } else { - for (idx = 0; idx < input->num_buffers; ++idx) { - buf = &input->bufs[idx]; - err = allocInputBuffer (buf); - if (err != 0) - goto err_alloc; - } - } - - return 0; - -err_alloc: - /* rollback the previous allocations */ - if (type == BUFFER_DMABUF) { - buf = &input->bufs[0]; - assert (cleanInputBuffer (&input->bufs[0]) == 0); - } else { - for (idx = idx - 1; idx >= 0; --idx) - assert (cleanInputBuffer (&input->bufs[idx]) == 0); - } - - return err; -} - -/** - * @brief Free input buffers allocated by allocInputBuffers(). - * @param[in/out] input input buffers. - * @note it reuses cleanInputbuffer(). - * @return 0 if no error, otherwise a negative errno. - */ -int cleanInputBuffers (input_buffers * input) -{ - int idx, err = 0; - buffer_types type; - - if (!input || input->num_buffers < 1) - return -EINVAL; - - type = input->bufs[0].type; - if (type == BUFFER_DMABUF) { - err = cleanInputBuffer (&input->bufs[0]); - if (err != 0) - goto clean_fail; - } else { - for (idx = 0; idx < input->num_buffers; ++idx) { - err = cleanInputBuffer (&input->bufs[idx]); - if (err != 0) - goto clean_fail; - } - } - - return 0; - -clean_fail: - logerr (TAG, "Fail to clean some input buffers: %d\n", err); - - return err; -} - -/** deprecated buffer APIs; please use the above APIs */ - -/** - * @deprecated - * @brief Allocate a buffer for NPU with the requested buffer type. - * @param[in] size the requested size of memory. - * @param[in] type the requested buffer type. - * @param[in] [OPTIONAL] filepath the path of file wrapped in the buffer (only for BUFFER_FILE). - * NULL will be provided for other buffer types. - * @param[out] buffer fill its contents if no error (it should be allocated before) - * @return 0 if no error, otherwise a negative errno. - */ -int allocNPUBuffer (uint64_t size, buffer_types type, - const char * filepath, generic_buffer *buffer) -{ - logwarn (TAG, "allocNPUBuffer() is deprecated. " - "Please use allocInputBuffer() / allocModelBuffer()\n"); - - if (buffer) { - buffer->size = size; - buffer->type = type; - buffer->filepath = filepath; - } - - return GET_MEM()->alloc_npu_buffer (buffer); -} - -/** - * @deprecated - * @brief Free the buffer and remove the address mapping. - * @param[in] buffer the generic buffer instance. - * @return @c 0 if no error. otherwise a negative error value. - * @note it does not free generic_buffer itself - */ -int cleanNPUBuffer (generic_buffer * buffer) -{ - logwarn (TAG, "cleanNPUBuffer() is deprecated. " - "Please use cleanInputBuffer() / cleanModelBuffer()\n"); - - return GET_MEM()->clean_npu_buffer (buffer); -} diff --git a/src/core/ne-comm.h b/src/core/ne-comm.h deleted file mode 100644 index 33f710e..0000000 --- a/src/core/ne-comm.h +++ /dev/null @@ -1,177 +0,0 @@ -/** - * Proprietary - * Copyright (C) 2019 Samsung Electronics - * Copyright (C) 2019 MyungJoo Ham - */ -/** - * @file ne-comm.h - * @date 15 May 2019 - * @brief Interface to access communication plugin from NPU Engine (ne) - * @see http://suprem.sec.samsung.net/confluence/display/ODLC/Software+Stack - * @see http://suprem.sec.samsung.net/confluence/pages/viewpage.action?pageId=128465352 - * @author MyungJoo Ham - * @bug No known bugs except for NYI items - * - * To packagers: this is NOT exported. - * - * @note This version does not support multi-model. - * Therefore registerNPUModel always returns "FULL" if there is a model - * registered. - */ - -#ifndef NE_COMM_H__ -#define NE_COMM_H__ - -#include -#include -#include "ne-mem.h" -#include "ne-common.h" - -/** - * @brief N2. Host Handler registers its callbacks with this struct - */ -typedef struct { -/* Queries on the status */ - /** - * @brief get the allocated memory size of models - * @return the memory size of models - */ - uint64_t (*getSizeModels) (); -#ifdef ENABLE_BUFFERING - /** - * @brief get the allocated memory size of buffers - * @return the memory size of buffers - */ - uint64_t (*getSizeBuffers) (); -#endif - /** - * @brief get a number of registered models - * @return a number of registered models - */ - uint32_t (*getNumRegisteredModels) (); - /** - * @brief get a model metadata with the target id and version - * @param[in] id model id - * @param[in] version model version - * @param[out] meta model metadata - * @return 0 if no error, otherwise a negative error - */ - int (*getModelMeta) (uint64_t id, uint64_t version, npubin_meta *meta); - -/* Operators: N1 calls N2 with these callbacks registred. */ - /** - * @brief Host tells us to start an operation. - * @param[in] op The operation mode - * @param[in] force if non-zero, try to stop/start with preemption - * @param[in] id the model id to be activated - * @param[in] version the model version to be activated - * @param[in] cb The callback to be called when the output is ready - * @param[in] cb_data The private data to be given to the callback. - * @return 0 if ok. errno if error. - */ - int (*setOpMode) (npu_input_opmode op, bool force, uint64_t id, - uint64_t version, output_ready cb, void *cb_data); - -#ifdef ENABLE_BUFFERING - /** - * 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. - */ - int (*resizeBuffers) (uint64_t size); -#endif - - /** - * @brief Host tells us to register a model - * @param[in] model_buf The generic_buffer for the compiled NPU NN model. - * @param[in] mem The hwmem block/chunk with the model from the host. - * @param[in] id the model id to be activated - * @param[in] version the model version to be activated - * @return 0 if ok. errno if error - * - * @detail ADDR-M in the Activity Sequence is the retval->mem_model; - */ - int (*registerModel) (generic_buffer *model_buf, uint64_t *id, uint64_t *version); - - /** - * @brief Host tells us to unregister a model - * @param[in] id The id of model to be unregistered. - * @param[in] version The version of model to be unregistered. - * @return 0 if ok. errno if error. - */ - int (*unregisterModel) (uint64_t id, uint64_t version); - -#ifdef ENABLE_BUFFERING - /** - * @brief get the next input buffer - * @param[in] mode How this operation when input buffers are full - * @param[out] err Set with error-number if there is an error - * @return the buffer for input data writing. NULL if error. - * @detail Depending on the parameters from libNPUHost, the caller (N1) - * may wait and retry or return error. - * The return value is "ADDR-I1" in Activity Sequence. - */ - buffer *(*getCurrentInputBuffer) (npu_async_mode mode, int *err); -#endif - - /** - * @brief feed input data to the obtained buffer - * @param[in] meta metadata for the target model - * @param[in] info the input tensors info - * @param[in] input the input data from users - * @param[out] buffer_ptr the buffer pointer to be filled - * @return 0 if ok. errno if error. - */ - int (*feedInputBuffer) (const npubin_meta *meta, const tensors_data_info *info, - const input_buffers *input, buffer *buffer_ptr); - - /** - * @brief The buffer is filled and valid for inference. Start when ready. - * @param[in] buffer The buffer with input data filled. - * @param[in] priority The priority of this inference - * @param[in] timestamp The timeout timestamp - * @return 0 if ok. errno if error. - * - * @note after validation, it's no longer accessible because it was returned. - */ - int (*validateBuffer)(buffer *buffer, npu_priority priority, uint64_t timestamp); - -#ifdef ENABLE_BUFFERING - /** - * @brief get the next output buffer - * @param[out] err Set with error-number if there is an error - * @return the buffer for output data to be transferred. NULL if error. - * @detail Depending on the parameters from libNPUHost, the caller (N1) - * may wait and retry or return error. - */ - buffer *(*getCurrentOutputBuffer) (int *err); -#endif - - /** - * @brief extract output data from the buffer - * @param[in] meta metadata for the target model - * @param[in] info the output tensors info - * @param[in] buffer_ptr the buffer pointer that contains the result data - * @param[out] output the output data to store data - * @return 0 if ok. errno if error. - */ - int (*extractOutputBuffer) (const npubin_meta *meta, const tensors_data_info *info, - const buffer *buffer_ptr, output_buffers *output); -} hostHandlerInfo; - - -/** - * @brief Register NE-comm's own functions to libUSB so that it can - * receive messages from the host. - * - * @detail There is only one instance in a system. - */ -int initNEcomm (const hostHandlerInfo *hh, dev_type type); - -/** - * @brief Stop receiving messages from the transmission medium. - */ -int exitNEcomm (void); - -#endif /* NE_COMM_H__ */ -- 2.7.4