[AppTest] add AppTest to test dma-buf sharing for model data
authorDongju Chae <dongju.chae@samsung.com>
Mon, 16 Sep 2019 04:35:56 +0000 (13:35 +0900)
committer임근식/On-Device Lab(SR)/Principal Engineer/삼성전자 <geunsik.lim@samsung.com>
Mon, 16 Sep 2019 08:30:37 +0000 (17:30 +0900)
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>
src/test/apptests/async_callbacks.c
src/test/apptests/dmabuf_model.c [new file with mode: 0644]
src/test/apptests/dummy_inference.c
src/test/apptests/meson.build
src/test/meson.build
src/test/ne_test_utils.c
src/test/ne_test_utils.h
src/test/unittests/ne_core_comm_ip_test.cpp

index cfb1adb..5f8acc0 100644 (file)
@@ -101,7 +101,7 @@ run_inference (npudev_h dev)
   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;
 
diff --git a/src/test/apptests/dmabuf_model.c b/src/test/apptests/dmabuf_model.c
new file mode 100644 (file)
index 0000000..591a06d
--- /dev/null
@@ -0,0 +1,168 @@
+/**
+ * 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;
+}
index 0287b5f..f530b53 100644 (file)
@@ -65,7 +65,7 @@ run_inference (npudev_h dev)
     .weight_size = weight_size,
   };
 
-  model = make_model (&meta, BUFFER_MAPPED);
+  model = make_model (&meta, BUFFER_MAPPED, 0);
   if (model) {
     uint32_t model_id;
 
index be20ae7..e6992cc 100644 (file)
@@ -17,3 +17,12 @@ executable ('apptest_async_callbacks',
   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')
+)
index 23ca644..39630e7 100644 (file)
@@ -3,7 +3,6 @@ ne_test_utils_src = ['ne_test_utils.c']
 
 ne_test_utils_dep = declare_dependency(
   sources : ne_test_utils_src,
-  dependencies: ne_dependencies
 )
 
 subdir('unittests')
index 8819dad..52f4d06 100644 (file)
 #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)
 {
@@ -55,38 +60,58 @@ void fill_input_data (generic_buffer *buffer, size_t offset, 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;
 }
 
 /**
index ea312cb..75b03c2 100644 (file)
@@ -32,9 +32,10 @@ void fill_input_data (generic_buffer *buffer, size_t offset, 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);
 
 /**
  * @brief Allocate a generic buffer using malloc
index f338d49..816056a 100644 (file)
@@ -139,7 +139,7 @@ TEST (ne_core_ip_test_default_conf, registerNPUmodel_normal_case)
 
   /* 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);
@@ -171,7 +171,7 @@ TEST (ne_core_ip_test_default_conf, registerNPUmodel_fail_undefined_buf)
    * 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]);
@@ -203,14 +203,14 @@ TEST (ne_core_ip_test_default_conf, registerNPUmodel_fail_models_more_than_max)
     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);
@@ -226,7 +226,7 @@ TEST (ne_core_ip_test_default_conf, registerNPUmodel_fail_models_more_than_max)
 
   /* 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]);
@@ -253,7 +253,7 @@ TEST (ne_core_ip_test_default_conf, registerNPUmodel_large_size)
   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);
@@ -262,7 +262,7 @@ TEST (ne_core_ip_test_default_conf, registerNPUmodel_large_size)
    /* 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);