[FIX/FPGA] Add driver-assisted memcpy for workaround solution
authorDongju Chae <dongju.chae@samsung.com>
Fri, 7 Aug 2020 08:05:55 +0000 (17:05 +0900)
committer송욱/On-Device Lab(SR)/Staff Engineer/삼성전자 <wook16.song@samsung.com>
Tue, 18 Aug 2020 01:26:11 +0000 (10:26 +0900)
This patch adds driver-assisted memcpy for workaround solution.

In the current FPGA env, memcpy() between FPGAs makes bit-flip
for a certain memory regions. This workaround codes can avoid
this issue by driver-assisted codes.

Signed-off-by: Dongju Chae <dongju.chae@samsung.com>
meson.build
meson_options.txt
src/core/ne-handler.cc
src/core/npu/NPUdrvAPI.h
src/core/npu/NPUdrvAPI_triv2.cc

index e4ea57f..767275c 100644 (file)
@@ -86,6 +86,10 @@ if not get_option('enable_npu_emul')
   endif
 endif
 
+if get_option('enable_fpga_workaround')
+  add_project_arguments('-DENABLE_FPGA_WORKAROUND', language: ['c', 'cpp'])
+endif
+
 if sysroot.startswith('/')
   sysroot_inc_cflags_template = '-I@0@/usr/include@1@'
   sysroot_inc = sysroot_inc_cflags_template.format(sysroot, '')
index c671f18..e36a846 100644 (file)
@@ -6,4 +6,5 @@ option('log_verbose', type : 'boolean', value : false)
 option('enable_npu_emul', type : 'boolean', value : false)
 option('enable_data_manip', type : 'boolean', value : false)
 option('enable_buffering', type : 'boolean', value : false)
+option('enable_fpga_workaround', type : 'boolean', value : false)
 option('kernel_hdr_dir', type : 'string', value : '')
index 0c9053e..6b83a8b 100644 (file)
@@ -1603,6 +1603,13 @@ TrinityVision2::callback (Request *req, npuOutputNotify cb, void *cb_data)
     /** user needs to free this */
     output.bufs[idx].addr = calloc (1, output_tensor_size);
 
+#if defined(ENABLE_FPGA_WORKAROUND)
+    api_->fpga_memcpy (
+        segt->getOutputSegment(idx)->getDmabuf(),
+        segt->getOutputSegmentOffset(idx),
+        output.bufs[idx].addr,
+        output.bufs[idx].size);
+#else
     auto func = std::bind (TrinityVision2::manipulateData, model, idx, false,
         std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
     int status = comm_.insertGenericBuffer (
@@ -1612,6 +1619,7 @@ TrinityVision2::callback (Request *req, npuOutputNotify cb, void *cb_data)
     if (status != 0) {
       logerr (TAG, "Failed to return output buffer: %d\n", status);
     }
+#endif
   }
 
   cb (&output, req->getID(), cb_data);
index cf5defa..2332cb0 100644 (file)
@@ -99,6 +99,11 @@ class DriverAPI {
     virtual int registerModel (model_config_t *model) const { return -EPERM; }
     virtual int deregisterModel (unsigned long long id) const { return -EPERM; }
 
+#if defined(ENABLE_FPGA_WORKAROUND)
+    virtual int fpga_memcpy (int dmabuf, uint32_t offset,
+        void *addr, size_t size) const { return -EPERM; }
+#endif
+
   protected:
     int dev_id_;  /**< device id. assume that 0 <= id < getNUmDevices() */
     int dev_fd_;  /**< devide fd. opened in constructor and closed in destructor */
@@ -170,6 +175,11 @@ class TrinityVision2API : public DriverAPI {
     int registerModel (model_config_t *model) const;
     int deregisterModel (unsigned long long id) const;
 
+#if defined(ENABLE_FPGA_WORKAROUND)
+    int fpga_memcpy (int dmabuf, uint32_t offset,
+        void *addr, size_t size) const;
+#endif
+
   private:
     int getDrvVersion () const;
     static const std::string dev_node_base;
index 5670d5a..fd7aec8 100644 (file)
@@ -378,3 +378,26 @@ TrinityVision2API::getDrvVersion () const
 
   return ver;
 }
+
+#if defined(ENABLE_FPGA_WORKAROUND)
+int
+TrinityVision2API::fpga_memcpy (int dmabuf, uint32_t offset, void *addr, size_t size) const
+{
+  struct trinity_fpga_memcpy fpga;
+  int ret;
+
+  if (!this->initialized())
+    return -EPERM;
+
+  fpga.dbuf_fd = dmabuf;
+  fpga.dbuf_off = offset;
+  fpga.user_addr = addr;
+  fpga.user_size = size;
+
+  ret = ioctl (this->getDeviceFD (), TRINITY_IOCTL_FPGA_MEMCPY, &fpga);
+  if (ret != 0)
+    return -errno;
+
+  return 0;
+}
+#endif