1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Ultra96/Ultra96-V2 向け Debian GNU/Linux で XRT(Xilinx Runtime)を動かす(2.8ビルド編)

Last updated at Posted at 2021-05-11

はじめに

筆者は Ultra96/Ultra96-V2(ZynqMP) 向けに Debian GNU/Linux を提供しています1。また、XRT(Xilinx Runtime) はXilinx社が提供する開発環境(Vitis)で開発したプログラムをプラットフォームで動かすための環境です2

本来なら MPSoC Edge Device 用の XRT は Xilinx が提供する Linux 環境(Petalinux) でしか動きませんが、XRT を Ultra96/Ultra96-V2 向け Debian GNU/Linux で動かすための Debian Package のビルド方法を以下の記事で紹介しました。

上の記事は XRT のバージョンは2.6.0でした。 この記事はその続編で、 XRTの 2.8.0 を Ultra96/Ultra96-V2 向け Debian GNU/Linux または Ubuntu 20.04 用にビルドする手順について説明します。

注意

この記事で紹介している Debian Package は Xilinx 社の公式なものではありません。

XRT Debian Package の提供

XRT の Debian Package をビルドするためにはビルド環境を整えなければならず、とても面倒です。そこでビルド済みの Debian Package を用意しています。自分でビルドするのが面倒なかたはこちらをお使いください。

Debian 10 用

fpga@ubuntu-fpga:~/work$ git clone --depth 1 --branch 2020.2_EDGE_1_Debian_10 https://github.com/ikwzm/ZynqMP-FPGA-XRT.git
fpga@ubuntu-fpga:~/work$ sudo apt install ./ZynqMP-FPGA-XRT/xrt_202020.2.8.1_Edge_Debian_10-arm64.deb

Ubuntu 20.04 用

fpga@ubuntu-fpga:~/work$ git clone --depth 1 --branch 2020.2_EDGE_1_Ubuntu_20.04 https://github.com/ikwzm/ZynqMP-FPGA-XRT.git
fpga@ubuntu-fpga:~/work$ sudo apt install ./ZynqMP-FPGA-XRT/xrt_202020.2.8.1_Edge_Ubuntu_20.04-arm64.deb

XRT のビルド

ビルド環境

XRT を ZynqMP-FPGA-Linux 向けにビルドするのは少し面倒です。XRT のビルドには Ubuntu や CentOS などの Linux ディストリビューションが必要です。ビルドには色々な開発ツールがインストールされていなければなりません。さらに Debian Package を作るためか、PC をホストにして ARM64 用にクロスコンパイルするのがとても面倒です。

そこで、 Ultra96-V2 に Debian 10 または Ubuntu 18.04 を動かして、その上でセルフビルドします。Ultra96-V2 用の Debian 10 および Ubuntu 18.04 は以下の URL で公開しています。

XRT のダウンロード

以下の URL より XRT のソースコードをダウンロードします。ブランチは 2020.2_EDGE です。

このリポジトリは、 Xilinx 社が github に公開している https://github.com/Xilinx/XRT を fork して各種修正を加えたものです。修正内容は次章で説明します。

fpga@debian-fpga:~/work$ git clone --depth 1 --branch 2020.2_EDGE https://github.com/Xilinx/XRT
Cloning into 'XRT'...
remote: Enumerating objects: 2142, done.
remote: Counting objects: 100% (2142/2142), done.
remote: Compressing objects: 100% (1885/1885), done.
remote: Total 2142 (delta 653), reused 626 (delta 220), pack-reused 0
Receiving objects: 100% (2142/2142), 20.80 MiB | 1.22 MiB/s, done.
Resolving deltas: 100% (653/653), done.
Checking out files: 100% (1958/1958), done.

ビルドに必要な Debian Package をインストール

ビルドに必要なパッケージをインストールします。幸い XRT には、ビルドに必要なパッケージをインストールするスクリプトが用意されています。

./src/runtime_src/tools/scripts/xrtdeps.sh を super user 権限で実行すると、apt プログラムによって足りない Debian Package がインストールされます。

fpga@debian-fpga:~/work/XRT$ sudo ./src/runtime_src/tools/scripts/xrtdeps.sh
Installing packages...
Reading package lists... Done
Building dependency tree
Reading state information... Done
	:
(中略)
	:
The following packages were automatically installed and are no longer required:
  libgl2ps1.4 libibverbs1 liblept5 libnetcdf-c++4 libnl-route-3-200
  libopencv-flann-dev libopencv-flann3.2 libopencv-ml-dev libopencv-ml3.2
  libopencv-photo-dev libopencv-photo3.2 libopencv-shape-dev
  libopencv-shape3.2 libopencv-ts-dev libopencv-video-dev libopencv-video3.2
  libtcl8.6 libtesseract4 libtk8.6 libxss1
Use 'sudo apt autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 26 not upgraded.

ビルド

build ディレクトリに移動して、そこにある build.sh に "-edge" オプションをつけて実行することで、ビルドが開始されます。Ultra96/Ultra96-V2 だとけっこう時間がかかります。私の環境では1時間30分ほどかかりました。

fpga@debian-fpga:~/work/XRT$ cd build/
fpga@ubuntu-fpga:~/work/XRT/build$ ./build.sh -edge
env XRT_EDGE_BUILD=yes cmake -DRDI_CCACHE=0 -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ../../src
-- The C compiler identification is GNU 8.3.0
-- The CXX compiler identification is GNU 8.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Host system processor is aarch64
-- Target system processor is aarch64
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29")
-- Checking for module 'libdrm'
--   Found libdrm, version 2.4.97
-- Looking for DRM - found at /usr 2.4.97
-- Checking for module 'OpenCL'
--   Found OpenCL, version 2.2
-- Looking for OPENCL - found at /usr 2.2 /usr/include
	:
(後略)
	:
real    1m28.030s
user    1m8.790s
sys     0m15.279s
fpga@debian-fpga:~/work/XRT/build$ 

ビルドが終了すると、build/Edge ディレクトリの下に Debian Package が出来ています。

fpga@debian-fpga:~/work/XRT/build$ ls -1 Edge/xrt_*
Edge/xrt_202020.2.8.1_Edge_Debian_10-arm64.deb
Edge/xrt_202020.2.8.1_Edge_Debian_10-arm64.tar.gz

このうち Ultra96/Ultra96-V2 に必要な Debian Package は、Edge/xrt_202020.2.8.1_Edge_Debian_10-arm64.deb です。

XRT の変更内容

この章では、オリジナルの XRT(https://github.com/Xilinx/XRT ブランチ2020.2) に対して、私が独自に変更した点について説明します。

XRT_EDGE_BUILD を追加

オリジナルではホストプロセッサとターゲットプロセッサが同じ場合に XRT_NATIVE_BUILD という変数が "yes" にセットされます。 そして、XRT_NATIVE_BUILD が "yes" の時(ホストプロセッサとターゲットプロセッサが同じ時)に src/runtime_src/core/pcie が、"no" の時(ホストプロセッサとターゲットプロセッサが異なる時)に src/runtime_src/core/edge がビルドされるように src/runtime_src/core/CMakeLists.txt が定義されています。

src/runtime_src/core/CMakeLists.txt
include_directories(
  ${CMAKE_CURRENT_SOURCE_DIR}
  )
add_subdirectory(include)
add_subdirectory(common)
 if (${XRT_NATIVE_BUILD} STREQUAL "yes")
   add_subdirectory(pcie)
   add_subdirectory(tools)
 else()
   add_subdirectory(edge)
 endif()

また、XRT_NATIVE_BUILD が "yes" の時(ホストプロセッサとターゲットプロセッサが同じ時)にインクルードされる src/CMake/nativeLnx.cmake には、次のようにホスト用のドライバをビルド&インストールするようになっています。

src/CMake/nativeLnx.cmakext
	:
	(前略)
	:
include (CMake/dkms.cmake)
include (CMake/dkms-aws.cmake)
include (CMake/dkms-azure.cmake)
include (CMake/dkms-container.cmake)
	:
	(後略)

Ultra96-V2 に Ubuntu 18.04 を動かしてその上でセルフビルドする場合は、ホストプロセッサとターゲットプロセッサが同じ arm64 になります。このままだと、edge 用のではなく pcie 用にビルドされてしまいます。

そこで、次のように src/CMakfile.txt に XRT_EDGE_BUILD 変数を追加します。

src/CMakeLists.txt
	:
	(前略)
	:	
set(XRT_EDGE_BUILD "no")
if (XRT_NATIVE_BUILD STREQUAL "no")
  set(XRT_EDGE_BUILD "no")
endif()
if (DEFINED ENV{XRT_EDGE_BUILD})
  set(XRT_EDGE_BUILD $ENV{XRT_EDGE_BUILD})
endif():
	:
	(後略)

そして XRT_EDGE_BUILD が "yes" の場合は edge 用のビルドを行うように、それぞれのファイルを変更します。

src/runtime_src/core/CMakeLists.txt
include_directories(
  ${CMAKE_CURRENT_SOURCE_DIR}
  )
add_subdirectory(include)
 if (${XRT_EDGE_BUILD} STREQUAL "yes")
   add_subdirectory(common)
   add_subdirectory(edge)
   add_subdirectory(tools)
 else()
   add_subdirectory(common)
   add_subdirectory(pcie)
   add_subdirectory(tools)
 endif()

src/CMake/nativeLnx.cmakext
	:
	(前略)
	:
if (${XRT_EDGE_BUILD} STREQUAL "yes")
  include (CMake/dkms-edge.cmake)
else()
  include (CMake/dkms.cmake)
  include (CMake/dkms-aws.cmake)
  include (CMake/dkms-azure.cmake)
  include (CMake/dkms-container.cmake)
endif()
	:
	(後略)

また、XRT_NATIVE_BUILD が "yes" の時(ホストプロセッサとターゲットプロセッサが同じ時)、コンパイルのオプションに "-Wall" と -"Werror" が追加されるような設定が src/runtime_src/CMakeLists.txt にあります。

src/runtime_src/CMakeLists.txt
	:
	(前略)
	:
# TODO CL_TARGET_OPENCL_VERSION is not defined..
if (${XRT_NATIVE_BUILD} STREQUAL "yes")
  add_compile_options("-Wall" "-Werror")
endif()
	:
	(後略)

"-Werror" オプションがあると src/runtime_src/core/edge 以下のビルド時にエラーが出てコンパイルに失敗します。そこで XRT_EDGE_BUILD が "yes" の時はコンパイルオプションに "-Wall" と "-Werror" が追加されないように src/runtime_src/CMakeLists.txt を修正します。

src/runtime_src/CMakeLists.txt
	:
	(前略)
	:
# TODO CL_TARGET_OPENCL_VERSION is not defined..
if (${XRT_EDGE_BUILD} STREQUAL "no")
  add_compile_options("-Wall" "-Werror")
endif()	:
	(後略)

最後に build/build.sh を修正して、ホストプロセッサが arm64 かつ "-edge" オプションが追加された場合は XRT_EDGE_BUILD が "yes" になるように修正します。

build/build.sh
	:
	(前略)
	:
if [[ $CPU == "aarch64" ]] && [[ $edge == 1 ]]; then
  mkdir -p $edge_dir
  cd $edge_dir
  if [[ $nocmake == 0 ]]; then
    echo "env XRT_EDGE_BUILD=yes $CMAKE -DRDI_CCACHE=$ccache -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ../../src"
    time  env XRT_EDGE_BUILD=yes $CMAKE -DRDI_CCACHE=$ccache -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ../../src
  fi
  if [[ $nobuild == 0 ]]; then
      echo "make -j $jcore $verbose DESTDIR=$PWD install"
      time make -j $jcore $verbose DESTDIR=$PWD install
      if [[ $noctest == 0 ]]; then
          time ctest --output-on-failure
      fi
      time make package
  fi
  if [[ $docs == 1 ]]; then
      echo "make xrt_docs"
      make xrt_docs
  fi
fi
	:
	(後略)

パッケージファイル名を変更

オリジナルの XRT では、ビルドした Debian Package の名前は xrt_202010.2.8.0_18.04-arm64-xrt.deb になりますが、Debian 10 用またはUbuntu 用のパッケージであることを明示するために、次のようにEdge というキーワードとともに Linux のフレーバー名を追加しておきます。

diff --git a/src/CMake/cpackLin.cmake b/src/CMake/cpackLin.cmake
index 4f45f97a..9f6eebe4 100644
--- a/src/CMake/cpackLin.cmake
+++ b/src/CMake/cpackLin.cmake
@@ -79,7 +79,7 @@ else ()
   SET (CPACK_GENERATOR "TGZ")
 endif()
 
-SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${XRT_VERSION_RELEASE}.${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}_${CPACK_REL_VER}-${CPACK_ARCH}")
+if (${XRT_EDGE_BUILD} STREQUAL "yes")
+   SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${XRT_VERSION_RELEASE}.${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}_Edge_${LINUX_FLAVOR}_${CPACK_REL_VER}-${CPACK_ARCH}")
+else()
+   SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${XRT_VERSION_RELEASE}.${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}_${CPACK_REL_VER}-${CPACK_ARCH}")
+endif()
 
 message("-- ${CMAKE_BUILD_TYPE} ${PACKAGE_KIND} package")
 

dkms-edge 関連の修正

ビルドした Debian パッケージを Debian 10 または Ubuntu 20.04 にインストールした時、dkms(Dynamic Kernel Module Support) というメカニズムによって、XRT の Edge 用の Linux Kernel Module である zocl を、自動的にコンパイルします。しかし、残念ながら、Xilinx オリジナルのままでは上手くいきませんでした。そのためいくつかの修正を加えます。

postinst と prerm の追加

Xilinx オリジナルのままでは Debian パッケージをインストールする時に自動的に実行されるスクリプト postinst と、アンインストールする時に自動的に実行されるスクリプト prerm が Debian パッケージに含まれません。これらのスクリプトが Debian パッケージに含まれるようにするために、src/CMake/cpackLin.cmake を次のように修正します。

diff --git a/src/CMake/cpackLin.cmake b/src/CMake/cpackLin.cmake
index 0f38c922..3d32674f 100644
--- a/src/CMake/cpackLin.cmake
+++ b/src/CMake/cpackLin.cmake
@@ -84,6 +84,11 @@ if (${LINUX_FLAVOR} MATCHES "^(Ubuntu|Debian)")
     SET(CPACK_DEBIAN_PACKAGE_DEPENDS ${CPACK_DEBIAN_XRT_PACKAGE_DEPENDS})
   endif()
 
+  if (${XRT_EDGE_BUILD} STREQUAL "yes")
+    SET(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_BINARY_DIR}/postinst;${CMAKE_CURRENT_BINARY_DIR}/prerm")
+    SET(CPACK_DEBIAN_PACKAGE_DEPENDS ${CPACK_DEBIAN_XRT_PACKAGE_DEPENDS})
+  endif()
+
 elseif (${LINUX_FLAVOR} MATCHES "^(RedHat|CentOS|Amazon|Fedora)")
   execute_process(
     COMMAND uname -m
@@ -140,7 +145,11 @@ else ()
   SET (CPACK_GENERATOR "TGZ")
 endif()

足りないファイルを追加

さらに Xilinx オリジナルのままでは、dkms に必要なファイルが幾つか含まれません。そこで、src/CMake/dkms-edge.cmake と次のように修正して足りないファイルを追加します。

diff --git a/src/CMake/dkms-edge.cmake b/src/CMake/dkms-edge.cmake
index 48e4ad1e..83d9d8ec 100644
--- a/src/CMake/dkms-edge.cmake
+++ b/src/CMake/dkms-edge.cmake
@@ -35,6 +35,7 @@ SET (XRT_DKMS_CORE_COMMON_DRV ${XRT_DKMS_CORE_DIR}/common/drv)
 
 SET (XRT_DKMS_DRIVER_SRCS
   zocl/include/sched_exec.h
+  zocl/include/zocl_aie.h
   zocl/include/zocl_bo.h
   zocl/include/zocl_cu.h
   zocl/include/zocl_dma.h
@@ -53,6 +54,7 @@ SET (XRT_DKMS_DRIVER_SRCS
   zocl/LICENSE
   zocl/Makefile
   zocl/sched_exec.c
+  zocl/zocl_aie.c
   zocl/zocl_bo.c
   zocl/zocl_cu.c
   zocl/zocl_dma.c
@@ -86,6 +88,7 @@ SET (XRT_DKMS_COMMON_XRT_DRV
   common/drv/xrt_cu.c
   common/drv/cu_hls.c
   common/drv/cu_plram.c
+  common/drv/fast_adapter.c
   common/drv/xrt_xclbin.c
   common/drv/Makefile
   )

-D__NONE_PETALINUX__ の追加

PetaLinux 環境以外で zocl をコンパイルするためには -D__NONE_PETALINUX__ という C のオプションが必要なようです。このオプションをつけてビルドするように src/CMake/config/dkms-zocl/dkms.conf.in を次のように修正します。

diff --git a/src/CMake/config/dkms-zocl/dkms.conf.in b/src/CMake/config/dkms-zocl/dkms.conf.in
index c79c23c2..78fd5a90 100644
--- a/src/CMake/config/dkms-zocl/dkms.conf.in
+++ b/src/CMake/config/dkms-zocl/dkms.conf.in
@@ -1,7 +1,7 @@
 PACKAGE_NAME="xrt-zocl"
 PACKAGE_VERSION="@XRT_VERSION_STRING@"
-MAKE[0]="cd driver/zocl; make -j KERNEL_SRC=${kernel_source_dir}; cd ../.."
-CLEAN="cd driver/zocl; make clean KERNEL_SRC=${kernel_source_dir}; cd ../.."
+MAKE[0]="cd driver/zocl; make -j KERNEL_SRC=${kernel_source_dir} cflags_zocl=-D__NONE_PETALINUX__; cd ../.."
+CLEAN="cd driver/zocl; make clean KERNEL_SRC=${kernel_source_dir} cflags_zocl=-D__NONE_PETALINUX__; cd ../.."
 BUILT_MODULE_NAME[0]="zocl"
 BUILT_MODULE_LOCATION[0]="driver/zocl"
 DEST_MODULE_LOCATION[0]="/kernel/extras"

不要なテストの削除

Debian Package のビルド時に、ビルドしたツールが正常に動作するかテストが行われます。しかし、Xilinx オリジナルのままでは、Edge 用の Debian Package にもかかわらず、PCI-Express 用のツールである xbmgmt と xbutil のテストを試みようとして失敗します。どこで、src/CMake/NativeTests.cmake を次のように修正して不要なテストを行わないようにします。

diff --git a/src/CMake/nativeTests.cmake b/src/CMake/nativeTests.cmake
index 9f53ad61..25e0d19d 100644
--- a/src/CMake/nativeTests.cmake
+++ b/src/CMake/nativeTests.cmake
@@ -3,13 +3,17 @@
 # XRT_INSTALL_BIN_DIR
 
 enable_testing()
+if (${XRT_EDGE_BUILD} STREQUAL "no")
 add_test(NAME xbmgmt
   COMMAND ${CMAKE_BINARY_DIR}/runtime_src/core/pcie/tools/xbmgmt/xbmgmt scan
   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+endif()
 
+if (${XRT_EDGE_BUILD} STREQUAL "no")
 add_test(NAME xbutil
   COMMAND ${CMAKE_BINARY_DIR}/runtime_src/core/pcie/tools/xbutil/xbutil scan
   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+endif()
 
 add_test(NAME xbutil2
   COMMAND ${CMAKE_BINARY_DIR}/runtime_src/core/tools/xbutil2/xbutil2 --new scan
@@ -19,4 +23,6 @@ add_test(NAME xbmgmt2
   COMMAND ${CMAKE_BINARY_DIR}/runtime_src/core/tools/xbmgmt2/xbmgmt2 --new scan
   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
 
-set_tests_properties(xbutil xbmgmt PROPERTIES ENVIRONMENT INTERNAL_BUILD=1)
+if (${XRT_EDGE_BUILD} STREQUAL "no")
+  set_tests_properties(xbutil xbmgmt PROPERTIES ENVIRONMENT INTERNAL_BUILD=1)
+endif()

zocl ドライバオープン時の修正

Xilinx オリジナルでは、XRT が zocl(XRT Edge 用の Linux Kernel Module) をオープンする際に指定するファイル名を "/dev/dri/renderD128" に固定しています。このままでは、例えば[『Ultra96/Ultra96-V2 向け Debian GNU/Linux で Lima Driverを動かす』]で紹介したように、他の DRM ドライバと共存するのが難しくなります。そこで、zocl をオープンする際、/dev/dri をサーチして "zocl" を探すようにします。

具体的には、src/runtime_src_core/edge/user/shim.cpp に /dev/dri から zocl を探すためのクラス ZYNQ::scanner を定義します。

files/2020.2-01-xrt.patch
diff --git a/src/runtime_src/core/edge/user/shim.cpp b/src/runtime_src/core/edge/user/shim.cpp
index df0ff366..143e3264 100644
--- a/src/runtime_src/core/edge/user/shim.cpp
+++ b/src/runtime_src/core/edge/user/shim.cpp
@@ -38,6 +38,7 @@
 #include <cassert>
 #include <cstdarg>
 
+#include <dirent.h>
 #include <fcntl.h>
 #include <poll.h>
 #include <unistd.h>
@@ -90,6 +91,98 @@ namespace ZYNQ {
 //initializing static member
 std::map<uint64_t, uint32_t *> shim::mKernelControl;
 
+class scanner {
+private:
+  std::mutex lock;
+  std::vector<std::string> dev_name_list;

+  void rescan_nolock(void)
+  {
+    const std::string dri_path      = "/dev/dri";
+    const std::string render_prefix = "renderD";
+    const std::string drm_name      = "zocl";
+
+    DIR* dp = opendir(dri_path.c_str());
+    if (dp) {
+      struct dirent* entry;
+      drm_version    version;
+      const std::unique_ptr<char[]> path(new char[512]);
+      const std::unique_ptr<char[]> name(new char[128]);
+      const std::unique_ptr<char[]> desc(new char[512]);
+      const std::unique_ptr<char[]> date(new char[128]);
+      std::memset(&version, 0, sizeof(version));
+      version.name     = name.get();
+      version.name_len = 128;
+      version.desc     = desc.get();
+      version.desc_len = 512;
+      version.date     = date.get();
+      version.date_len = 128;
+        
+      while ((entry = readdir(dp))) {
+        int fd;
+        if (std::strncmp(entry->d_name, render_prefix.c_str(), render_prefix.length()) != 0)
+          continue;
+        sprintf(path.get(), "%s/%s", dri_path.c_str(), entry->d_name);
+        if ((fd = open(path.get(), O_RDWR, 0)) < 0)
+          continue;
+        if (ioctl(fd, DRM_IOCTL_VERSION, &version) == 0) {
+          if (std::strncmp(version.name, drm_name.c_str(), drm_name.length()) == 0) {
+            std::string dev_name(path.get());
+            dev_name_list.insert(dev_name_list.begin(), dev_name);
+          }
+        }
+        close(fd);
+      }
+      std::sort(dev_name_list.begin(), dev_name_list.end());
+      closedir(dp);
+    }
+  }
+
+public:
+  static scanner *get()
+  {
+    static scanner scanner;
+    return &scanner;
+  }
+  void rescan(void)
+  {
+    std::lock_guard<std::mutex> l(lock);
+    rescan_nolock();
+  }
+
+  size_t dev_num_total(void)
+  {
+    std::lock_guard<std::mutex> l(lock);
+    return dev_name_list.size();
+  }
+
+  const std::string& dev_name(int index)
+  {
+    static const std::string null;
+    std::lock_guard<std::mutex> l(lock);
+    if (index >= dev_name_list.size())
+      return null;
+    else
+      return dev_name_list[index];
+  }
+
+private:
+  scanner(void) { rescan_nolock();}
+  scanner(const scanner&  s);
+  scanner& operator=(const scanner& s);
+};
+void rescan(void)
+{
+  scanner::get()->rescan();
+}
+size_t dev_num_total(void)
+{
+  return scanner::get()->dev_num_total();
+}
+const std::string& dev_name(int index)
+{
+  return scanner::get()->dev_name(index);
+}
+

次に src/runtime_src_core/edge/user/shim.cpp にあるクラス shim のコンストラクタを次のように修正して /dev/dri から該当するデバイスファイルをオープンするようにします。

files/2020.2-01-xrt.patch
 shim::
 shim(unsigned index, const char *logfileName, xclVerbosityLevel verbosity)
   : mCoreDevice(xrt_core::edge_linux::get_userpf_device(this, index))
@@ -103,9 +196,13 @@ shim(unsigned index, const char *logfileName, xclVerbosityLevel verbosity)
 
   xclLog(XRT_INFO, "XRT", "%s", __func__);
 
-  mKernelFD = open("/dev/dri/renderD128", O_RDWR);
+  const std::string device_name = dev_name(index);
+  if (device_name.empty()) {
+    xclLog(XRT_ERROR, "XRT", "%s: Card [%d] not found", __func__, index);
+  }
+  mKernelFD = open(device_name.c_str(), O_RDWR, 0);
   if (!mKernelFD) {
-    xclLog(XRT_ERROR, "XRT", "%s: Cannot open /dev/dri/renderD128", __func__);
+    xclLog(XRT_ERROR, "XRT", "%s: Cannot open device %s", __func__, device_name.c_str());
   }
   mCmdBOCache = std::make_unique<xrt_core::bo_cache>(this, xrt_core::config::get_cmdbo_cache());
   mDev = zynq_device::get_dev();

さらに、src/runtime_src_core/edge/user/shim.cpp にある xclProbe() を次のように修正します。

files/2020.2-01-xrt.patch
 @@ -1536,28 +1633,7 @@ unsigned
 xclProbe()
 {
   PROBE_CB;
-
-  int fd = open("/dev/dri/renderD128", O_RDWR);
-  if (fd < 0) {
-    return 0;
-  }
-  drm_version version;
-  std::memset(&version, 0, sizeof(version));
-  version.name = new char[128];
-  version.name_len = 128;
-  version.desc = new char[512];
-  version.desc_len = 512;
-  version.date = new char[128];
-  version.date_len = 128;
-
-  int result = ioctl(fd, DRM_IOCTL_VERSION, &version);
-  if (result)
-    return 0;
-
-  result = std::strncmp(version.name, "zocl", 4);
-  close(fd);
-
-  return (result == 0) ? 1 : 0;
+  return (ZYNQ::dev_num_total() > 0);
 }
 #endif

最後にソースコード自体に修正を加えたことを示すために、src/CMakeList.txt で丁未されているDebian Package のパッチレベルを0から1に変更します。

files/2020.2-01-xrt.patch
 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8cb46a32..dca721a9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -70,7 +70,7 @@ SET(XRT_VERSION_MINOR 8)
 if (DEFINED ENV{XRT_VERSION_PATCH})
   SET(XRT_VERSION_PATCH $ENV{XRT_VERSION_PATCH})
 else(DEFINED $ENV{XRT_VERSION_PATCH})
-  SET(XRT_VERSION_PATCH 0)
+  SET(XRT_VERSION_PATCH 1)
 endif(DEFINED ENV{XRT_VERSION_PATCH})
 
 #set(XRT_SOVERSION ${XRT_VERSION_MAJOR}.${XRT_VERSION_MINOR})

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?