はじめに
筆者は 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 用
- リポジトリ: https://github.com/ikwzm/ZynqMP-FPGA-XRT
- ブランチ名: 2020.2_EDGE_1_Debian_10
- パッケージファイル名: xrt_202020.2.8.1_Edge_Debian_10-arm64.deb
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 用
- リポジトリ: https://github.com/ikwzm/ZynqMP-FPGA-XRT
- ブランチ名: 2020.2_EDGE_1_Ubuntu_20.04
- パッケージファイル名: xrt_202020.2.8.1_Edge_Ubuntu_20.04-arm64.deb
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 です。
- リポジトリ名: https://github.com/ikwzm/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 が定義されています。
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 には、次のようにホスト用のドライバをビルド&インストールするようになっています。
:
(前略)
:
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 変数を追加します。
:
(前略)
:
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 用のビルドを行うように、それぞれのファイルを変更します。
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()
:
(前略)
:
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 にあります。
:
(前略)
:
# 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 を修正します。
:
(前略)
:
# 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" になるように修正します。
:
(前略)
:
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 を定義します。
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 から該当するデバイスファイルをオープンするようにします。
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() を次のように修正します。
@@ -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に変更します。
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})
参考
- https://github.com/Xilinx/XRT
- https://github.com/ikwzm/ZynqMP-FPGA-XRT
- https://github.com/ikwzm/ZynqMP-FPGA-Linux
- https://github.com/ikwzm/ZynqMP-FPGA-Ubuntu20.04-Ultra96
- 『Ultra96/Ultra96-V2 向け Debian GNU/Linux で XRT(Xilinx Runtime) を動かす(概要編)』@Qiita
- 『Ultra96/Ultra96-V2 向け Debian GNU/Linux で XRT(Xilinx Runtime) を動かす(ビルド編)』@Qiita
- 『Ultra96/Ultra96-V2 向け Debian GNU/Linux で XRT(Xilinx Runtime) を動かす(インストール編)』@Qiita
- 『Ultra96/Ultra96-V2 向け Debian GNU/Linux で XRT(Xilinx Runtime) を動かす(実践編)』@Qiita
- 『Ultra96/Ultra96-V2 向け Debian GNU/Linux で XRT(Xilinx Runtime) を動かす(Vitis編)』@Qiita
- 『UltraZed/Ultra96/Ultra96-V2 向け Debian GNU/Linux (v2020.2版) ブートイメージの提供』@Qiita
- 『Ultra96/Ultra96-V2 向け Debian GNU/Linux で Lima Driverを動かす』@Qiita