This patch adds the TRIV2 plugin prototype of npumgr.
Signed-off-by: Dongju Chae <dongju.chae@samsung.com>
# Note that VD NPU Manager is a gdbus-based thread application
glib_dep = dependency('glib-2.0', required: false)
+gmodule_dep = dependency('gmodule-2.0', required: false)
giounix_dep = dependency('gio-unix-2.0', required: false)
if glib_dep.found() and giounix_dep.found()
npumgr_deps = [
glib_dep,
+ gmodule_dep,
giounix_dep
]
install_dir : ne_libdir
)
+ npumgr_triv2_lib = shared_library ('npumgr_triv2',
+ ['npumgr_triv2.cc', 'npumgr_device.cc'],
+ include_directories : [ne_common_inc, ne_host_inc],
+ dependencies: npumgr_deps,
+ link_with : ne_library_shared,
+ build_rpath : ne_libdir,
+ install : true,
+ install_rpath : ne_libdir,
+ install_dir : ne_libdir
+ )
+
executable ('apptest_npumgr',
'npumgr_test.cc',
link_with : npumgr_lib,
)
executable ('dummy_npumgr',
- 'npumgr.cc',
+ ['npumgr.cc', 'npumgr_device.cc'],
dependencies: npumgr_deps,
install : true,
install_rpath : ne_libdir,
#include <stdlib.h>
#include <unistd.h>
#include <cstdint>
+#include <vector>
+#include <string>
+#include <gmodule.h>
#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
+
+#include <npumgr_api.h>
+#include <npumgr_device.h>
+
+#define NPUMGR_DEVICE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), NPUMGR_TYPE_DEVICE, NpumgrDeviceClass))
/**
- * @brief Class for NPU Manager Context
+ * @brief Internal data structure for NPU Manager Context
*/
-class npumgrContext {
- public:
- npumgrContext () : device_id_ (-1), priority_ (-1) {}
+typedef struct {
+ NpumgrDevice *device;
+ npumgr_context handle;
+} NpumgrContext;
- /** @brief set device id */
- void setDeviceID (int device_id) { device_id_ = device_id; }
- /** @brief set priority */
- void setPriority (int priority) { priority_ = priority; }
-
- private:
- int device_id_;
- int priority_;
-};
+G_LOCK_DEFINE_STATIC (mutex);
+static GHashTable *ctx_table;
static GDBusNodeInfo *introspection_data = NULL;
/* Introspection data for the npumgr service (NYI) */
static const gchar introspection_xml[] =
" <node>"
" <interface name='sr.odl.NPUManager.API'>"
+ " <method name='DeviceGetAvailableList'>"
+ " <arg type='u' name='num_devices' direction='out'/>"
+ " <arg type='ai' name='device_type' direction='out'/>"
+ " <arg type='au' name='device_id' direction='out'/>"
+ " </method>"
" <method name='ContextCreate'>"
" <arg type='i' name='device_id' direction='in'/>"
" <arg type='i' name='priority' direction='in'/>"
" </node>";
/**
+ * @brief Name of supported plugins
+ */
+static const char *supported_plugins[] = {
+ "triv2",
+};
+
+/**
+ * @brief Internal structure to hold plugin data
+ */
+typedef struct {
+ const char *name;
+ GModule *module;
+ NpumgrDevice *device;
+ uint32_t id;
+ uint32_t caps;
+ npumgr_device_type_t ptype;
+} plugin_pdata;
+
+/**
+ * @brief Registered plugins
+ */
+static GSList *registered_plugins;
+
+static void
+append_device (gpointer data, gpointer user_data) {
+ plugin_pdata *pdata = (plugin_pdata *) data;
+ npumgr_devices_id *devices = (npumgr_devices_id *) user_data;
+ NpumgrDevice *device = pdata->device;
+
+ NPUMGR_DEVICE_GET_CLASS (device)->device_get_capabilities (
+ device, &pdata->caps, &pdata->ptype);
+
+ devices->types[devices->n_devices] = pdata->ptype;
+ devices->id[devices->n_devices] = pdata->id;
+ devices->n_devices++;
+}
+
+/**
+ * @brief Insert npumgr context created
+ */
+static gboolean
+insert_context (npumgr_context handle, NpumgrContext *context) {
+ gboolean result;
+
+ G_LOCK (mutex);
+ result = g_hash_table_insert (ctx_table, GSIZE_TO_POINTER (handle), context);
+ G_UNLOCK (mutex);
+
+ return result;
+}
+
+/**
+ * @brief Remove the npumgr context
+ */
+static gboolean
+remove_context (npumgr_context handle) {
+ gboolean result;
+
+ G_LOCK (mutex);
+ result = g_hash_table_remove (ctx_table, GSIZE_TO_POINTER (handle));
+ G_UNLOCK (mutex);
+
+ return result;
+}
+
+/**
* @brief Method callback
*/
static void
const gchar *object_path, const gchar *interface_name,
const gchar *method_name, GVariant *parameters,
GDBusMethodInvocation *invocation, gpointer user_data) {
- if (g_strcmp0 (method_name, "ContextCreate") == 0) {
+ if (g_strcmp0 (method_name, "DeviceGetAvailableList") == 0) {
+ GVariantBuilder builder, builder_arr;
+ npumgr_devices_id devices = {.n_devices = 0};
+
+ g_slist_foreach (registered_plugins, append_device, &devices);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(uaiau)"));
+ g_variant_builder_add (&builder, "u", devices.n_devices);
+
+ g_variant_builder_init (&builder_arr, G_VARIANT_TYPE ("ai"));
+ for (int i = 0; i < devices.n_devices; i++)
+ g_variant_builder_add (&builder_arr, "i", ((int *) devices.types)[i]);
+ g_variant_builder_add_value (&builder,
+ g_variant_builder_end (&builder_arr));
+
+ g_variant_builder_init (&builder_arr, G_VARIANT_TYPE ("au"));
+ for (int i = 0; i < devices.n_devices; i++)
+ g_variant_builder_add (&builder_arr, "u", ((int *) devices.id)[i]);
+ g_variant_builder_add_value (&builder,
+ g_variant_builder_end (&builder_arr));
+
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_builder_end (&builder));
+ } else if (g_strcmp0 (method_name, "ContextCreate") == 0) {
int device_id = -1;
int priority = -1;
g_variant_get (parameters, "(ii)", &device_id, &priority);
- if (device_id >= 0 && priority >= 0) {
- npumgrContext *ctx = new npumgrContext;
-
- ctx->setDeviceID (device_id);
- ctx->setPriority (priority);
-
- g_dbus_method_invocation_return_value (
- invocation, g_variant_new ("(t)", reinterpret_cast<uintptr_t> (ctx)));
- } else {
+ if (device_id < 0 || priority < 0) {
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid arguments detected");
+ return;
+ }
+
+ plugin_pdata *pdata =
+ (plugin_pdata *) g_slist_nth_data (registered_plugins, device_id);
+ if (pdata == NULL) {
+ g_dbus_method_invocation_return_error (
+ invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Invalid device id");
+ return;
+ }
+
+ NpumgrDevice *device = pdata->device;
+ npumgr_context handle;
+ npumgr_status_e status;
+
+ status = NPUMGR_DEVICE_GET_CLASS (device)->context_create (
+ device, device_id, priority, &handle);
+ if (status == NPUMGR_STATUS_SUCCESS) {
+ NpumgrContext *ctx;
+
+ ctx = g_new0 (NpumgrContext, 1);
+ ctx->handle = handle;
+ ctx->device = device;
+
+ if (insert_context (handle, ctx)) {
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(t)", handle));
+ } else {
+ g_dbus_method_invocation_return_error (
+ invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "Unable to add context: same context handle detected");
+ NPUMGR_DEVICE_GET_CLASS (device)->context_destroy (device, handle);
+ g_free (ctx);
+ }
+ } else {
+ g_dbus_method_invocation_return_error (
+ invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "Unable to add context: internal errors");
}
} else if (g_strcmp0 (method_name, "ContextDestroy") == 0) {
- npumgrContext *ctx = NULL;
+ npumgr_context handle = 0;
- g_variant_get (parameters, "(t)", reinterpret_cast<uintptr_t *> (&ctx));
- if (ctx != NULL) {
- delete ctx;
- g_dbus_method_invocation_return_value (invocation, NULL);
+ g_variant_get (parameters, "(t)", &handle);
+ if (handle > 0) {
+ if (remove_context (handle))
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ else
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+ G_DBUS_ERROR_UNKNOWN_OBJECT,
+ "Unable to find the context");
} else {
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
}
/**
+ * @brief Destroy callback for freeing context instance
+ */
+static void
+ctx_destroy (gpointer data) {
+ NpumgrContext *ctx = static_cast<NpumgrContext *> (data);
+ NpumgrDevice *device;
+
+ g_return_if_fail (ctx != NULL);
+
+ device = ctx->device;
+ NPUMGR_DEVICE_GET_CLASS (device)->context_destroy (device, ctx->handle);
+
+ g_free (ctx);
+}
+
+static void
+plugin_pdata_free (gpointer *data) {
+ plugin_pdata *pdata = (plugin_pdata *) data;
+
+ g_module_close (pdata->module);
+ g_object_unref (pdata->device);
+ g_free (pdata);
+}
+
+/**
+ * @brief Initialize plugins
+ */
+static void
+init_plugins (void) {
+ typedef NpumgrDevice *(*NewFunc) (void);
+ GModule *module;
+ NewFunc func;
+
+ registered_plugins = NULL;
+
+ for (auto &name : supported_plugins) {
+ gchar *module_name = g_strdup_printf ("libnpumgr_%s", name);
+ module = g_module_open (module_name, G_MODULE_BIND_LAZY);
+ if (!module) {
+ g_critical ("Unable to open %s", module_name);
+ g_free (module_name);
+ continue;
+ }
+ g_free (module_name);
+
+ gchar *module_symbol = g_strdup_printf ("npumgr_device_%s_new", name);
+ if (!g_module_symbol (module, module_symbol, (gpointer *) &func)) {
+ g_critical ("Unable to find symbol %s", module_symbol);
+ g_free (module_symbol);
+ continue;
+ }
+ g_free (module_symbol);
+
+ plugin_pdata *pdata = g_new0 (plugin_pdata, 1);
+ registered_plugins = g_slist_append (registered_plugins, pdata);
+
+ pdata->name = name;
+ pdata->module = module;
+ pdata->device = func ();
+ pdata->id = g_slist_index (registered_plugins, pdata);
+ }
+}
+
+/**
* @brief Main function for gdbus-based server
*/
int
return -1;
}
+ init_plugins ();
+
+ ctx_table =
+ g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, ctx_destroy);
owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, "sr.odl.NPUManager.API",
G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired,
on_name_acquired, on_name_lost, NULL, NULL);
g_bus_unown_name (owner_id);
g_dbus_node_info_unref (introspection_data);
+ g_hash_table_destroy (ctx_table);
+ g_slist_free_full (registered_plugins, (GDestroyNotify) plugin_pdata_free);
+
return 0;
}
static GMutex _mutex;
static GCond _cond;
static const gchar *_name_owner;
+static gboolean _running;
/**
* @brief Wait until the gdbus session is connected
*/
npumgr_status_e
npumgr_device_get_available_list (npumgr_devices_id *pdev) {
- /* NYI */
- return NPUMGR_STATUS_SUCCESS;
+ GDBusMessage *method_call;
+ GDBusMessage *method_reply;
+ npumgr_status_e status = NPUMGR_STATUS_SUCCESS;
+ GError *error = NULL;
+
+ g_return_val_if_fail (pdev != NULL, NPUMGR_STATUS_ERR_PARAM_INVALID);
+ g_return_val_if_fail (wait_until_connected (), NPUMGR_STATUS_ERR_TIMEOUT);
+
+ method_call = g_dbus_message_new_method_call (
+ _name_owner, "/sr/odl/NPUManager/APIObject", "sr.odl.NPUManager.API",
+ "DeviceGetAvailableList");
+ g_dbus_message_set_body (method_call, NULL);
+
+ method_reply = g_dbus_connection_send_message_with_reply_sync (
+ _connection, method_call, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL,
+ &error);
+
+ if (method_reply == NULL) {
+ status = NPUMGR_STATUS_ERR_FAIL;
+ goto out;
+ }
+
+ if (g_dbus_message_get_message_type (method_reply) ==
+ G_DBUS_MESSAGE_TYPE_ERROR) {
+ g_dbus_message_to_gerror (method_reply, &error);
+ g_critical ("error: %s\n", error->message);
+ g_error_free (error);
+ status = NPUMGR_STATUS_ERR_FAIL;
+ goto out;
+ }
+
+ {
+ GVariantIter *iter_type;
+ GVariantIter *iter_id;
+ uint32_t idx;
+
+ g_variant_get (g_dbus_message_get_body (method_reply), "(uaiau)",
+ &pdev->n_devices, &iter_type, &iter_id);
+
+ if (pdev->n_devices > NPUMGR_MAX_DEVICES) {
+ g_critical ("Too many devices: %u", pdev->n_devices);
+ status = NPUMGR_STATUS_ERR_FAIL;
+ goto out_iter;
+ }
+
+ idx = 0;
+ while (idx < NPUMGR_MAX_DEVICES &&
+ g_variant_iter_loop (iter_type, "i", &pdev->types[idx++]))
+ ;
+
+ idx = 0;
+ while (idx < NPUMGR_MAX_DEVICES &&
+ g_variant_iter_loop (iter_id, "u", &pdev->id[idx++]))
+ ;
+
+ out_iter:
+ g_variant_iter_free (iter_type);
+ g_variant_iter_free (iter_id);
+ }
+
+out:
+ g_object_unref (method_call);
+ g_object_unref (method_reply);
+
+ return status;
}
/**
npumgr_network_create (npumgr_context ctx, int num_files,
npumgr_network_defn *input_files,
npumgr_buffer_t in_buffer_type, int in_tensor_cnt,
- const char *const *input_tensor_names,
+ const char *const *in_tensor_names,
npumgr_buffer_t out_buffer_type, int out_tensor_cnt,
- const char *const *output_tensor_names,
+ const char *const *out_tensor_names,
npumgr_network *out_nw_handle) {
/* NYI */
return NPUMGR_STATUS_SUCCESS;
on_name_vanished, NULL, NULL);
_loop = g_main_loop_new (NULL, FALSE);
+
+ g_mutex_lock (&_mutex);
+ _running = TRUE;
+ g_cond_broadcast (&_cond);
+ g_mutex_unlock (&_mutex);
+
g_main_loop_run (_loop);
g_bus_unwatch_name (watcher_id);
init_npumgr_api (void) {
_connection = NULL;
_loop = NULL;
+ _running = FALSE;
_thread = g_thread_new (NULL, npumgr_thread, NULL);
}
void
fini_npumgr_api (void) {
if (_thread) {
+ gint64 end_time = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND;
+
+ g_mutex_lock (&_mutex);
+ if (_running == FALSE)
+ g_cond_wait_until (&_cond, &_mutex, end_time);
g_main_loop_quit (_loop);
+ g_mutex_unlock (&_mutex);
+
g_thread_join (_thread);
}
}
NPUMGR_NETWORK_FILE_CAFFE_MODEL_FILE, /**< Network file of type caffe. */
NPUMGR_NETWORK_FILE_CAFFE_WEIGHTS_FILE, /**< Network file of type caffe weights. */
+ NPUMGR_NETWORK_FILE_TVN, /**< Trinity Vision NPU */
NPUMGR_NETWORK_TYPE_MAX
}npumgr_network_file_t;
NPUMGR_BUF_TYPE_DMABUF, /**< This type of buffer os imported by dmabuf fd or importable memory. */
NPUMGR_BUF_TYPE_CUSTOM_INDEX, /**< DPB Buffer (custom) index for memory. */
NPUMGR_BUF_TYPE_PATCH, /**< This type of buffer is not allocated but it is patched by npumgr with help from other drivers. */
- NPUMGR_BUT_TYPE_MAX
+ NPUMGR_BUF_TYPE_MAX
}npumgr_buffer_t;
/**
--- /dev/null
+/**
+ * Proprietary
+ * Copyright (C) 2021 Samsung Electronics
+ * Copyright (C) 2021 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file npumgr_device.cc
+ * @date 03 May 2021
+ * @brief a parent class (dummy) of VD NPU Manager device.
+ * @author Dongju Chae <dongju.chae@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+
+#include "npumgr_device.h"
+
+G_DEFINE_TYPE (NpumgrDevice, npumgr_device, G_TYPE_OBJECT);
+
+static void
+npumgr_device_class_init (NpumgrDeviceClass *klass) {
+ /* NYI */
+}
+
+static void
+npumgr_device_init (NpumgrDevice *self) {
+ /* NYI */
+}
*/
#include <iostream>
+
+#include <fcntl.h>
+#include <unistd.h>
+
#include "npumgr_api.h"
int
main (int argc, char **argv) {
npumgr_context ctx;
+ npumgr_devices_id list;
npumgr_status_e status;
+ int ret = -EINVAL;
+
+ status = npumgr_device_get_available_list (&list);
+ if (status != NPUMGR_STATUS_SUCCESS) {
+ std::cerr << "Unable to get available device list, " << status << "\n";
+ return ret;
+ }
+
+ /* TODO: find the first NPU device */
+ bool found = false;
+ uint32_t id;
+
+ for (int i = 0; i < list.n_devices; i++) {
+ if (list.types[i] == NPUMGR_DEVICE_TYPE_NPU) {
+ found = true;
+ id = list.id[i];
+ break;
+ }
+ }
+
+ if (!found) {
+ std::cerr << "No available device\n";
+ return ret;
+ }
- status = npumgr_context_create (0 /* device_id */, 0 /* priority */, &ctx);
+ status = npumgr_context_create (id, NPUMGR_FLAG_PRIORITY_DEFAULT, &ctx);
if (status != NPUMGR_STATUS_SUCCESS) {
std::cerr << "Unable to create a npumgr context, " << status << "\n";
- return status;
+ return ret;
}
status = npumgr_context_destroy (ctx);
if (status != NPUMGR_STATUS_SUCCESS) {
std::cerr << "Unable to destroy the npumgr context, " << status << "\n";
- return status;
+ return ret;
}
- return 0;
+ return ret;
}
--- /dev/null
+/**
+ * Proprietary
+ * Copyright (C) 2021 Samsung Electronics
+ * Copyright (C) 2021 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file npumgr_triv2.cc
+ * @date 03 May 2021
+ * @brief TRIV2 device plugin of VD NPU Manager
+ * @author Dongju Chae <dongju.chae@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+
+#include "npumgr_triv2.h"
+
+/* npu-engine API */
+#include <libnpuhost.h>
+
+#include <vector>
+#include <fcntl.h>
+#include <unistd.h>
+
+extern "C" {
+NpumgrDevice *npumgr_device_triv2_new (void);
+}
+
+/**
+ * @brief Class for triv2 npumgr context
+ */
+class NpumgrContextTriv2 {
+ public:
+ NpumgrContextTriv2 (npudev_h dev, int priority)
+ : dev_ (dev), priority_ (priority) {
+ handle_ = g_atomic_int_add (&g_ctx_handle, 1);
+ }
+
+ ~NpumgrContextTriv2 () {}
+
+ npumgr_context getHandle () { return handle_; }
+
+ private:
+ static volatile guint g_ctx_handle;
+
+ npumgr_context handle_;
+ npudev_h dev_;
+ int priority_;
+};
+
+static void
+ctx_destroy (gpointer data) {
+ NpumgrContextTriv2 *ctx = static_cast<NpumgrContextTriv2 *> (data);
+
+ delete ctx;
+}
+
+volatile guint NpumgrContextTriv2::g_ctx_handle = 1;
+
+/**
+ * @brief Private members in NpumgrDeviceTriv2
+ */
+struct _NpumgrDeviceTriv2Private {
+ npudev_h dev;
+ GMutex mutex;
+ GHashTable *ctx_table;
+};
+
+#define NPUMGR_DEVICE(obj) &((obj)->parent)
+#define NPUMGR_DEVICE_TRIV2_GET_PRIVATE(obj) \
+ ((NpumgrDeviceTriv2Private *) g_type_instance_get_private ( \
+ (GTypeInstance *) obj, NPUMGR_TYPE_DEVICE_TRIV2))
+
+G_DEFINE_TYPE_WITH_PRIVATE (NpumgrDeviceTriv2, npumgr_device_triv2,
+ NPUMGR_TYPE_DEVICE);
+
+/* GObject */
+static void triv2_finalize (GObject *object);
+/* NpumgrDevice */
+static npumgr_status_e triv2_device_get_capabilities (
+ NpumgrDevice *device, uint32_t *caps, npumgr_device_type_t *ptype);
+static npumgr_status_e triv2_context_create (NpumgrDevice *device,
+ int device_id, int priority,
+ npumgr_context *out_ctx);
+static npumgr_status_e triv2_context_destroy (NpumgrDevice *device,
+ npumgr_context ctx);
+
+extern NpumgrDevice *
+npumgr_device_triv2_new (void) {
+ gpointer instance = g_object_new (NPUMGR_TYPE_DEVICE_TRIV2, NULL);
+
+ return NPUMGR_DEVICE ((NpumgrDeviceTriv2 *) instance);
+}
+
+static void
+npumgr_device_triv2_class_init (NpumgrDeviceTriv2Class *klass) {
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ NpumgrDeviceClass *npumgr_device_class = &(klass->parent_class);
+
+ /* GObject */
+ gobject_class->finalize = triv2_finalize;
+ /* NpumgrDevice */
+ npumgr_device_class->device_get_capabilities = triv2_device_get_capabilities;
+ npumgr_device_class->context_create = triv2_context_create;
+ npumgr_device_class->context_destroy = triv2_context_destroy;
+ /* NYI */
+}
+
+static void
+npumgr_device_triv2_init (NpumgrDeviceTriv2 *self) {
+ NpumgrDeviceTriv2Private *priv = NPUMGR_DEVICE_TRIV2_GET_PRIVATE (self);
+ int status;
+
+ memset (priv, '\x00', sizeof (*priv));
+ g_mutex_init (&priv->mutex);
+ priv->ctx_table =
+ g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, ctx_destroy);
+
+ /** TODO: How npumgr supports multiple TRIV2 devices? */
+ status = getNPUdeviceByTypeAny (&priv->dev, NPUCOND_TRIV2_CONN_SOCIP, 2);
+ if (status != 0) {
+ g_critical ("Unable to find/open 2-TOPS TRIV2 device\n");
+ priv->dev = NULL;
+ return;
+ }
+ /* NYI */
+}
+
+static void
+triv2_finalize (GObject *object) {
+ NpumgrDeviceTriv2 *self = NPUMGR_DEVICE_TRIV2 (object);
+ NpumgrDeviceTriv2Private *priv = NPUMGR_DEVICE_TRIV2_GET_PRIVATE (self);
+
+ g_mutex_clear (&priv->mutex);
+ g_hash_table_destroy (priv->ctx_table);
+
+ if (priv->dev)
+ putNPUdevice (priv->dev);
+}
+
+/* Filling the virtual function table of TRIV2 */
+static npumgr_status_e
+triv2_device_get_capabilities (NpumgrDevice *device, uint32_t *caps,
+ npumgr_device_type_t *ptype) {
+ g_return_val_if_fail (device != NULL, NPUMGR_STATUS_ERR_PARAM_INVALID);
+ g_return_val_if_fail (caps != NULL, NPUMGR_STATUS_ERR_PARAM_INVALID);
+ g_return_val_if_fail (ptype != NULL, NPUMGR_STATUS_ERR_PARAM_INVALID);
+
+ NpumgrDeviceTriv2 *self = NPUMGR_DEVICE_TRIV2 (device);
+ NpumgrDeviceTriv2Private *priv = NPUMGR_DEVICE_TRIV2_GET_PRIVATE (self);
+
+ g_return_val_if_fail (priv->dev != NULL,
+ NPUMGR_STATUS_ERR_DEVICE_UNAVAILABLE);
+
+ *caps = NPUMGR_DEVICE_CAPABILITY_MMAP |
+ NPUMGR_DEVICE_CAPABILITY_MULTICONTEXT | NPUMGR_DEVICE_CAPABILITY_MMU |
+ NPUMGR_DEVICE_CAPABILITY_REALTIME;
+ *ptype = NPUMGR_DEVICE_TYPE_NPU;
+
+ return NPUMGR_STATUS_SUCCESS;
+}
+
+static gboolean
+insert_context (NpumgrDeviceTriv2Private *priv, npumgr_context handle,
+ NpumgrContextTriv2 *context) {
+ gboolean result;
+
+ g_mutex_lock (&priv->mutex);
+ result =
+ g_hash_table_insert (priv->ctx_table, GSIZE_TO_POINTER (handle), context);
+ g_mutex_unlock (&priv->mutex);
+
+ return result;
+}
+
+static gboolean
+remove_context (NpumgrDeviceTriv2Private *priv, npumgr_context handle) {
+ gboolean result;
+
+ g_mutex_lock (&priv->mutex);
+ result = g_hash_table_remove (priv->ctx_table, GSIZE_TO_POINTER (handle));
+ g_mutex_unlock (&priv->mutex);
+
+ return result;
+}
+
+static npumgr_status_e
+triv2_context_create (NpumgrDevice *device, int device_id, int priority,
+ npumgr_context *ctx_handle) {
+ g_return_val_if_fail (device != NULL, NPUMGR_STATUS_ERR_PARAM_INVALID);
+ g_return_val_if_fail (ctx_handle != NULL, NPUMGR_STATUS_ERR_PARAM_INVALID);
+
+ NpumgrDeviceTriv2 *self = NPUMGR_DEVICE_TRIV2 (device);
+ NpumgrDeviceTriv2Private *priv = NPUMGR_DEVICE_TRIV2_GET_PRIVATE (self);
+
+ g_return_val_if_fail (priv->dev != NULL,
+ NPUMGR_STATUS_ERR_DEVICE_UNAVAILABLE);
+
+ NpumgrContextTriv2 *context = new NpumgrContextTriv2 (priv->dev, priority);
+ *ctx_handle = context->getHandle ();
+
+ if (insert_context (priv, context->getHandle (), context)) {
+ return NPUMGR_STATUS_SUCCESS;
+ } else {
+ return NPUMGR_STATUS_ERR_FAIL;
+ }
+}
+
+static npumgr_status_e
+triv2_context_destroy (NpumgrDevice *device, npumgr_context ctx_handle) {
+ g_return_val_if_fail (device != NULL, NPUMGR_STATUS_ERR_PARAM_INVALID);
+ g_return_val_if_fail (ctx_handle != 0, NPUMGR_STATUS_ERR_PARAM_INVALID);
+
+ NpumgrDeviceTriv2 *self = NPUMGR_DEVICE_TRIV2 (device);
+ NpumgrDeviceTriv2Private *priv = NPUMGR_DEVICE_TRIV2_GET_PRIVATE (self);
+
+ if (remove_context (priv, ctx_handle))
+ return NPUMGR_STATUS_SUCCESS;
+ else
+ return NPUMGR_STATUS_ERR_CTX_INVALID;
+}
--- /dev/null
+/**
+ * Proprietary
+ * Copyright (C) 2021 Samsung Electronics
+ * Copyright (C) 2021 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file npumgr_triv2.h
+ * @date 03 May 2021
+ * @brief Internal header of TRIV2 device plugin
+ * @author Dongju Chae <dongju.chae@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+
+#ifndef __NPUMGR_TRIV2_H__
+#define __NPUMGR_TRIV2_H__
+
+/* npumgr device API */
+#include <npumgr_device.h>
+
+G_BEGIN_DECLS
+
+#define NPUMGR_TYPE_DEVICE_TRIV2 (npumgr_device_triv2_get_type ())
+#define NPUMGR_DEVICE_TRIV2(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NPUMGR_TYPE_DEVICE_TRIV2, \
+ NpumgrDeviceTriv2))
+
+typedef struct _NpumgrDeviceTriv2 NpumgrDeviceTriv2;
+typedef struct _NpumgrDeviceTriv2Class NpumgrDeviceTriv2Class;
+typedef struct _NpumgrDeviceTriv2Private NpumgrDeviceTriv2Private;
+
+/**
+ * @brief npumgr device class for TRIV2.
+ *
+ * NpumgrDeviceTriv2 inherits NpumgrDevice.
+ */
+struct _NpumgrDeviceTriv2 {
+ NpumgrDevice parent; /**< parent class object */
+};
+
+/**
+ * @brief NpumgrDeviceTriv2Class data structure.
+ *
+ * NpumgrDeviceTriv2Class inherits NpumgrDeviceClass.
+ */
+struct _NpumgrDeviceTriv2Class {
+ NpumgrDeviceClass parent_class; /**< inherits class object */
+};
+
+G_END_DECLS
+
+#endif