This PR adds new AppTest to test dma-buf sharing for model data.
Also, there are minor changes in other unittests due to the updated common API.
Signed-off-by: Dongju Chae <dongju.chae@samsung.com>
pthread_mutex_init (&priv.mutex, NULL);
pthread_cond_init (&priv.cond, NULL);
- model = make_model (&meta, BUFFER_MAPPED);
+ model = make_model (&meta, BUFFER_MAPPED, 0);
if (!model)
goto out;
--- /dev/null
+/**
+ * Proprietary
+ * Copyright (C) 2019 Samsung Electronics
+ * Copyright (C) 2019 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file dmabuf_model.c
+ * @date 19 Aug 2019
+ * @brief AppTest to test dmabuf sharing for model data
+ * @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"
+#include "../../core/ne-conf.h"
+#include "../../core/gem/GEMdrvAPI.h"
+
+/** @brief compare output result with the golden data */
+static int
+compare_result (const void *data, uint32_t size)
+{
+ /* @todo */
+ return 0;
+}
+
+/** @brief inference entry */
+static int
+run_inference (npudev_h dev)
+{
+ /* Constants */
+ const size_t program_size = 4096;
+ const size_t weight_size = 4096;
+ const size_t buffer_size = 4096;
+ const size_t input_offset = 0;
+ const size_t input_size = 1024;
+ const size_t output_offset = 512;
+ const size_t output_size = 2048;
+
+ generic_buffer * model;
+ uint32_t model_id;
+ int result = -1;
+
+ /* make dummy model data */
+ npubin_meta meta = {
+ /* below are compiler stuff */
+ .name = "dummy model",
+ .model_id = 1,
+ .model_version = 1,
+ .buffer_size = buffer_size,
+ .size = NPUBIN_META_SIZE + program_size + weight_size,
+ .type = SMODEL_OPS_NPU,
+ .input_offset = input_offset,
+ .input_size = input_size,
+ .output_offset = output_offset,
+ .output_size = output_size,
+ .program_size = program_size,
+ .weight_size = weight_size,
+ };
+
+ input_buffers input;
+ output_buffer output;
+
+ /**
+ * in this example, let's reuse the existing cgem driver for testing.
+ * users can use any way to obtain dmabuf fd.
+ */
+ uint32_t handle;
+ uint32_t size_out;
+ int dmabuf_fd;
+ int fd;
+
+ /* this test works only when test_mode is off */
+ if (conf->test_mode == 1) {
+ result = 0;
+ goto out;
+ }
+
+ if (meta.size > UINT32_MAX)
+ goto out;
+
+ fd = gem_open ("cgem");
+ if (fd < 0)
+ goto out;
+
+ /* get cgem object handle to represent CMA buffer */
+ handle = gem_create (fd, (uint32_t) meta.size, &size_out);
+ if (handle == 0)
+ goto out_close;
+
+ /* export object handle to dmabuf fd */
+ dmabuf_fd = gem_prime_export (fd, handle);
+ if (dmabuf_fd < 0)
+ goto out_destroy;
+
+ model = make_model (&meta, BUFFER_DMABUF, dmabuf_fd);
+ if (!model)
+ goto out_destroy;
+
+ if (registerNPUmodel (dev, model, &model_id) != 0)
+ goto out_free_model;
+
+ input.num_buffers = 1;
+ if (alloc_generic_buffer (&input.bufs[0], buffer_size, BUFFER_MAPPED) != 0)
+ goto out_unregister;
+
+ if (alloc_generic_buffer (&output, buffer_size, BUFFER_MAPPED) != 0) {
+ free_generic_buffer (&input.bufs[0]);
+ goto out_unregister;
+ }
+
+ /* fill input data and run NPU */
+ fill_input_data (&input.bufs[0], meta.input_offset, meta.input_size);
+
+ if (runNPU_sync (dev, model_id, &input, &output) == 0)
+ result = compare_result (output.buf, output.size);
+
+ /* free all resources */
+ free_generic_buffer (&input.bufs[0]);
+ free_generic_buffer (&output);
+
+out_unregister:
+ unregisterNPUmodel(dev, model_id);
+
+out_free_model:
+ free_generic_buffer (model);
+ free (model);
+
+out_destroy:
+ gem_destroy (fd, handle);
+
+out_close:
+ gem_close (fd);
+
+out:
+ return result;
+}
+
+/** @brief apptest main */
+int
+main (int argc, char **argv)
+{
+ npudev_h dev;
+ int num_devices = getnumNPUdevice();
+ int result = -1;
+
+ if (num_devices) {
+ if (getNPUdevice (&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;
+}
.weight_size = weight_size,
};
- model = make_model (&meta, BUFFER_MAPPED);
+ model = make_model (&meta, BUFFER_MAPPED, 0);
if (model) {
uint32_t model_id;
install : true,
install_dir : join_paths(ne_bindir, 'apptests')
)
+
+executable ('apptest_dmabuf_model',
+ 'dmabuf_model.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')
+)
ne_test_utils_dep = declare_dependency(
sources : ne_test_utils_src,
- dependencies: ne_dependencies
)
subdir('unittests')
#include <stdlib.h>
#include <string.h>
+#include <sys/mman.h>
+
#include "ne_test_utils.h"
+#define ALIGN_SIZE 4096
+#define TO_ALIGN_SIZE(size) (((size - 1) / ALIGN_SIZE + 1) * ALIGN_SIZE)
+
/** @brief fill program data for testing */
static void fill_program (void *buf, size_t size)
{
* @brief Make a model based on the parameter of the npubin_meta type, meta
* @param[in] meta Meta data required to make a model
* @param[in] buf_type The memory type of the buffer included in the model
+ * @param[in] opt optional argument for each buffer type
* @return A generic buffer including dummy model data, NULL if error
*/
-generic_buffer* make_model (npubin_meta *meta, buffer_types buf_type)
+generic_buffer* make_model (npubin_meta *meta, buffer_types buf_type, int opt)
{
size_t size = NPUBIN_META_SIZE + meta->program_size + meta->weight_size;
generic_buffer *buffer;
- void *buf;
+ void *buf = NULL;
buffer = (generic_buffer *) malloc (sizeof (*buffer));
if (!buffer) {
return NULL;
}
- /* let's use malloc() for testing */
- buf = malloc (size);
- if (!buf) {
- free (buffer);
+ switch (buf_type) {
+ case BUFFER_MAPPED:
+ /* let's use malloc() for testing */
+ buf = malloc (size);
+ if (!buf)
+ goto out_err;
- return NULL;
+ buffer->buf = buf;
+ break;
+ case BUFFER_DMABUF:
+ buf = mmap (0, TO_ALIGN_SIZE(size), PROT_WRITE | PROT_READ, MAP_SHARED, opt, 0);
+ if (buf == MAP_FAILED)
+ goto out_err;
+ break;
+ default:
+ /* not supported for other types yet */
+ break;
}
- buffer->buf = buf;
buffer->size = size;
buffer->type = buf_type;
- memcpy (buffer->buf, meta, NPUBIN_META_SIZE);
+ if (buf) {
+ memcpy (buf, meta, NPUBIN_META_SIZE);
+
+ fill_program (buf + NPUBIN_META_SIZE, meta->program_size);
+ fill_weight (buf + NPUBIN_META_SIZE + meta->program_size, meta->weight_size);
- fill_program (buffer->buf + NPUBIN_META_SIZE, meta->program_size);
- fill_weight (buffer->buf + NPUBIN_META_SIZE + meta->program_size,
- meta->weight_size);
+ if (buf_type == BUFFER_DMABUF)
+ munmap (buf, TO_ALIGN_SIZE(size));
+ }
return buffer;
+
+out_err:
+ free (buffer);
+
+ return NULL;
}
/**
* @brief Make a model based on the parameter of the npubin_meta type, meta
* @param[in] meta Meta data required to make a model
* @param[in] buf_type The memory type of the buffer included in the model
+ * @param[in] opt optional argument for each buffer type
* @return A generic buffer including dummy model data, NULL if error
*/
-generic_buffer* make_model (npubin_meta *meta, buffer_types buf_type);
+generic_buffer* make_model (npubin_meta *meta, buffer_types buf_type, int opt);
/**
* @brief Allocate a generic buffer using malloc
/* Normal case */
set_default_val_to_meta (&meta, model_name);
- model = make_model(&meta, BUFFER_MAPPED);
+ model = make_model(&meta, BUFFER_MAPPED, 0);
ret = registerNPUmodel (dev, model, &model_id);
ASSERT_EQ (ret, RET_SUCCESS);
ret = unregisterNPUmodel (dev, model_id);
* whose type is BUFFER_UNDEFINED (ret = -EINVAL).
*/
set_default_val_to_meta (&meta, model_name);
- model[0] = make_model(&meta, BUFFER_UNDEFINED);
+ model[0] = make_model(&meta, BUFFER_UNDEFINED, 0);
ret = registerNPUmodel (dev, model[0], &model_id);
ASSERT_NE (ret, RET_SUCCESS);
free_generic_buffer (model[0]);
snprintf (model_name, max_len_model_name, "DummyModel_%d", i);
memcpy (meta.name, model_name, max_len_model_name);
meta.model_id = i;
- model[i] = make_model(&meta, BUFFER_MAPPED);
+ model[i] = make_model(&meta, BUFFER_MAPPED, 0);
ret = registerNPUmodel (dev, model[i], &model_id);
ASSERT_EQ (ret, RET_SUCCESS);
}
/* Try to register a model above the limt of the maximum number of models */
meta.model_id = i;
- model[i] = make_model(&meta, BUFFER_MAPPED);
+ model[i] = make_model(&meta, BUFFER_MAPPED, 0);
ret = registerNPUmodel (dev, model[i], &model_id);
/* Should be failed */
ASSERT_NE (ret, RET_SUCCESS);
/* Try a huge size of memory (buffer_size) */
meta.buffer_size = SIZE_MAX;
- model[0] = make_model(&meta, BUFFER_UNDEFINED);
+ model[0] = make_model(&meta, BUFFER_UNDEFINED, 0);
ret = registerNPUmodel (dev, model[0], &model_id);
ASSERT_NE (ret, RET_SUCCESS);
free_generic_buffer (model[0]);
set_default_val_to_meta (&meta, "DummyModel");
/* Try a huge size of memory (buffer_size) */
meta.buffer_size = SIZE_MAX;
- model = make_model(&meta, BUFFER_UNDEFINED);
+ model = make_model(&meta, BUFFER_UNDEFINED, 0);
ret = registerNPUmodel (dev, model, &model_id);
ASSERT_NE (ret, RET_SUCCESS);
free_generic_buffer (model);
/* Try a huge size of memory (size) */
set_default_val_to_meta (&meta, "DummyModel");
meta.size = SIZE_MAX;
- model = make_model(&meta, BUFFER_UNDEFINED);
+ model = make_model(&meta, BUFFER_UNDEFINED, 0);
ret = registerNPUmodel (dev, model, &model_id);
ASSERT_NE (ret, RET_SUCCESS);
free_generic_buffer (model);