注意(2021年5月12日追記)
この記事は XRT 2.6.0 を元に書いていて古い内容が含まれています。2021年5月現在、XRT のバージョンは 2.8.0 になっていて、これに対応した記事を新たに投稿しています。そちらを参照してください。
はじめに
筆者は 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 で動かすための手順を幾つかのパートに分けて説明します。
この記事では XRT を Ultra96/Ultra96-V2 向け Debian GNU/Linux 用にビルドする手順について説明します。
注意
この記事で紹介している Debian Package は Xilinx 社の公式なものではありません。
XRT のビルド
ビルド環境
XRT を ZynqMP-FPGA-Linux 向けにビルドするのは少し面倒です。XRT のビルドには Ubuntu や CentOS などの Linux ディストリビューションが必要です。ビルドには色々な開発ツールがインストールされていなければなりません。さらに Debian Package を作るためか、PC をホストにして ARM64 用にクロスコンパイルするのがとても面倒です。
そこで、 Ultra96-V2 に Ubuntu 18.04 を動かして、その上でセルフビルドします。Ultra96-V2 用の Ubuntu 18.04 は以下の URL で公開しています。
XRT のダウンロード
以下の URL より XRT のソースコードをダウンロードします。
fpga@ubuntu-fpga:~$ cd work
fpga@ubuntu-fpga:~/work$ git clone https://github.com/Xilinx/XRT
Cloning into 'XRT'...
remote: Enumerating objects: 30, done.
remote: Counting objects: 100% (30/30), done.
remote: Compressing objects: 100% (30/30), done.
remote: Total 43591 (delta 13), reused 7 (delta 0), pack-reused 43561
Receiving objects: 100% (43591/43591), 58.10 MiB | 2.57 MiB/s, done.
Resolving deltas: 100% (33849/33849), done.
Checking out files: 100% (1682/1682), done.
fpga@ubuntu-fpga:~/work$ cd XRT
fpga@ubuntu-fpga:~/work/XRT$
XRT を ZynqMP-FPGA-Linux 用にビルドするためにはいくつかファイルを修正します。ですので、https://github.com/Xilinx/XRT を直接 clone するよりも、fork したほうが良いでしょう。
ビルドに必要な Debian Package をインストール
ビルドに必要なパッケージをインストールします。幸い XRT には、ビルドに必要なパッケージをインストールするスクリプトが用意されています。
./src/runtime_src/tools/scripts/xrtdeps.sh を super user 権限で実行すると、apt プログラムによって足りない Debian Package がインストールされます。
fpga@ubuntu-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.
XRT の変更
XRT のビルド用ファイルにいくつかの修正をしますので、ブランチを作成します。現時点(2020年3月25日)でのmaster ブランチの最新のコミット(aac1e6871e95da47ccff4392d5849462bbd4ecad) をベースにします。
fpga@ubuntu-fpga:~/work/XRT$ git checkout aac1e6871e95da47ccff4392d5849462bbd4ecad
fpga@ubuntu-fpga:~/work/XRT$ git checkout -b 2019.2_Ultra96
Switched to a new branch '2019.2_Ultra96'
このブランチに対して変更を加えていきます。具体的な変更内容は次章の「XRTの変更内容」を参照してください。
ここでは変更点をパッチファイルにして用意していますので、それをあてていきます。パッチファイルは以下の URL に用意しています。
-
https://github.com/ikwzm/ZynqMP-FPGA-XRT
- files/00-xrt.patch
- files/01-xrt.patch
- files/02-xrt.patch
- files/03-xrt.patch
パッケージファイル名を変更
fpga@ubuntu-fpga:~/work/XRT$ patch -p1 < ../files/00-xrt.patch
patching file src/CMake/cpackLin.cmake
fpga@ubuntu-fpga:~/work/XRT$ git add --update
fpga@ubuntu-fpga:~/work/XRT$ git commit -m "[add] linux flavor name to built debian package name"
[2019.2_Ultra96 9ff0a408] [add] linux flavor name to built debian package name
1 file changed, 1 insertion(+), 1 deletion(-)
依存する Debian Package のバージョンの上限を撤廃
fpga@ubuntu-fpga:~/work/XRT$ patch -p1 < ../files/01-xrt.patch
patching file src/CMake/cpackLin.cmake
fpga@ubuntu-fpga:~/work/XRT$ git add --update
fpga@ubuntu-fpga:~/work/XRT$ git commit -m "[remove] upper limit of version of depend packages"
[2019.2_Ultra96 7e93ed34] [remove] upper limit of version of depend packages
1 file changed, 1 insertion(+), 1 deletion(-)
XRT_EDGE_BUILD を追加
fpga@ubuntu-fpga:~/work/XRT$ patch -p1 < ../files/02-xrt.patch
patching file build/build.sh
patching file src/CMake/config/dkms-zocl/dkms.conf.in
patching file src/CMake/config/edge/postinst.in
patching file src/CMake/config/edge/prerm.in
patching file src/CMake/cpackLin.cmake
patching file src/CMake/dkms-edge.cmake
patching file src/CMake/nativeLnx.cmake
patching file src/CMakeLists.txt
patching file src/runtime_src/CMakeLists.txt
patching file src/runtime_src/core/CMakeLists.txt
patching file src/CMake/cpackLin.cmake
fpga@ubuntu-fpga:~/work/XRT$ git add --update
fpga@ubuntu-fpga:~/work/XRT$ git add src/CMake/config/dkms-zocl
fpga@ubuntu-fpga:~/work/XRT$ git add src/CMake/config/edge
fpga@ubuntu-fpga:~/work/XRT$ git add src/CMake/dkms-edge.cmake
fpga@ubuntu-fpga:~/work/XRT$ git commit -m "[add] XRT_EDGE_BUILD for MPSoC Edge"
[2019.2_Ultra96 95287c93] [add] XRT_EDGE_BUILD for MPSoC Edge
10 files changed, 376 insertions(+), 10 deletions(-)
create mode 100644 src/CMake/config/dkms-zocl/dkms.conf.in
create mode 100644 src/CMake/config/edge/postinst.in
create mode 100644 src/CMake/config/edge/prerm.in
create mode 100644 src/CMake/dkms-edge.cmake
10-zocl.rules を追加
fpga@ubuntu-fpga:~/work/XRT$ patch -p1 < ../files/03-xrt.patch
patching file src/CMake/config/edge/postinst.in
patching file src/CMake/dkms-edge.cmake
patching file src/runtime_src/core/edge/drm/zocl/10-zocl.rules
fpga@ubuntu-fpga:~/work/XRT$ git add --update
fpga@ubuntu-fpga:~/work/XRT$ git add src/runtime_src/core/edge/drm/zocl/10-zocl.rules
fpga@ubuntu-fpga:~/work/XRT$ git commit -m "[add] 10-zocl.rules for udev"
[2019.2_Ultra96 04a8069d] [add] 10-zocl.rules for udev
3 files changed, 3 insertions(+)
create mode 100644 src/runtime_src/core/edge/drm/zocl/10-zocl.rules
ビルド
build ディレクトリに移動して、そこにある build.sh に "-edge" オプションをつけて実行することで、ビルドが開始されます。Ultra96/Ultra96-V2 だとけっこう時間がかかります。私の環境では1時間ほどかかりました。
fpga@ubuntu-fpga:~/work/XRT$ cd build/
fpga@ubuntu-fpga:~/work/XRT/build$ ./build.sh -edge
cmake -DRDI_CCACHE=0 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_TOOLCHAIN_FILE= ../../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/gcc-8
-- Check for working C compiler: /usr/bin/gcc-8 -- 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/g++-8
-- Check for working CXX compiler: /usr/bin/g++-8 -- 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
:
(後略)
:
fpga@ubuntu-fpga:~/work/XRT/build$
ビルドが終了すると、build/Edge ディレクトリの下に Debian Package が出来ています。
fpga@ubuntu-fpga:~/work/XRT$ cd build/
fpga@ubuntu-fpga:~/work/XRT/build$ ls -1 Edge/xrt_*
Edge/xrt_202010.2.6.0_Ubuntu_18.04-arm64-xbtest.deb
Edge/xrt_202010.2.6.0_Ubuntu_18.04-arm64-xbtest.tar.gz
Edge/xrt_202010.2.6.0_Ubuntu_18.04-arm64-xrt.deb
Edge/xrt_202010.2.6.0_Ubuntu_18.04-arm64-xrt.tar.gz
このうち Ultra96/Ultra96-V2 に必要な Debian Package は、Edge/xrt_202010.2.6.0_Ubuntu_18.04-arm64-xrt.deb です。
XRT の変更内容
この章では、オリジナルの XRT に対して、私が独自に変更した点について説明します。
パッケージファイル名を変更
オリジナルの XRT では、ビルドした Debian Package の名前は xrt_202010.2.6.0_18.04-arm64-xrt.deb になりますが、Ubuntu 用のパッケージであることを明示するためにxrt_202010.2.6.0_Ubuntu_18.04-arm64-xrt.deb にします。
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}")
+SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${XRT_VERSION_RELEASE}.${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}_${LINUX_FLAVOR}_${CPACK_REL_VER}-${CPACK_ARCH}")
message("-- ${CMAKE_BUILD_TYPE} ${PACKAGE_KIND} package")
依存する Debian Package のバージョンの上限を撤廃
オリジナルでは、ビルドした Debian Package が依存する Package のうち、libboost-dev、libboost-filesystem-dev、libc6 のバージョンに上限が設定されています。これだと、インストールするディストリビューションの制約が強すぎてインストールに失敗することがあります。例えば、この Debian Package を Debian10 にインストールを試みると失敗します。
そこで、後で問題になるかもしれませんが、次のように cpackLin.cmake を修正してバージョンの上限を撤廃します。
diff --git a/src/CMake/cpackLin.cmake b/src/CMake/cpackLin.cmake
index 9f6eebe4..5b056580 100644
--- a/src/CMake/cpackLin.cmake
+++ b/src/CMake/cpackLin.cmake
@@ -49,7 +49,7 @@ if (${LINUX_FLAVOR} MATCHES "^(Ubuntu|Debian)")
SET(CPACK_DEBIAN_PACKAGE_SHLIBDEPS "OFF")
SET(CPACK_DEBIAN_AWS_PACKAGE_DEPENDS "xrt (>= ${XRT_VERSION_MAJOR}.${XRT_VERSION_MINOR}.${XRT_VERSION_PATCH})")
SET(CPACK_DEBIAN_XBTEST_PACKAGE_DEPENDS "xrt (>= ${XRT_VERSION_MAJOR}.${XRT_VERSION_MINOR}.${XRT_VERSION_PATCH}), libjson-glib-dev")
- SET(CPACK_DEBIAN_XRT_PACKAGE_DEPENDS "ocl-icd-opencl-dev (>= 2.2.0), libboost-dev (>= ${Boost_VER_STR}), libboost-dev (<< ${Boost_VER_STR_ONEGREATER}), libboost-filesystem-dev (>=${Boost_VER_STR}), libboost-filesystem-dev (<<${Boost_VER_STR_ONEGREATER}), uuid-dev (>= 2.27.1), dkms (>= 2.2.0), libprotoc-dev (>=2.6.1), libssl-dev (>=1.0.2), protobuf-compiler (>=2.6.1), libncurses5-dev (>=6.0), lsb-release, libxml2-dev (>=2.9.1), libyaml-dev (>= 0.1.6), libc6 (>= ${GLIBC_VERSION}), libc6 (<< ${GLIBC_VERSION_ONEGREATER}), python (>= 2.7), python-pip, libudev-dev ")
+ SET(CPACK_DEBIAN_XRT_PACKAGE_DEPENDS "ocl-icd-opencl-dev (>= 2.2.0), libboost-dev (>= ${Boost_VER_STR}), libboost-filesystem-dev (>=${Boost_VER_STR}), uuid-dev (>= 2.27.1), dkms (>= 2.2.0), libprotoc-dev (>=2.6.1), libssl-dev (>=1.0.2), protobuf-compiler (>=2.6.1), libncurses5-dev (>=6.0), lsb-release, libxml2-dev (>=2.9.1), libyaml-dev (>= 0.1.6), libc6 (>= ${GLIBC_VERSION}), python (>= 2.7), python-pip, libudev-dev ")
elseif (${LINUX_FLAVOR} MATCHES "^(RedHat|CentOS|Amazon)")
execute_process(
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)
add_subdirectory(common)
if (${XRT_EDGE_BUILD} STREQUAL "yes")
add_subdirectory(edge)
else()
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()
:
(後略)
そして、edge 用のドライバ(zocl) を Debian パッケージに追加してインストール時に dkms を使ってビルドするように以下のファイルを追加します。
- src/CMake/dkms-edge.cmake
- src/CMake/config/dkms-zocl/dkms.conf.in
- src/CMake/config/edge/postinst.in
- src/CMake/config/edge/prerm.in
また、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" になるように修正します。
:
(前略)
:
f [[ $CPU == "aarch64" ]] && [[ $edge == 1 ]]; then
mkdir -p $edge_dir
cd $edge_dir
if [[ $nocmake == 0 ]]; then
echo "$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 [[ $docs == 1 ]]; then
echo "make xrt_docs"
make xrt_docs
else
echo "make -j $jcore $verbose DESTDIR=$PWD"
time make -j $jcore $verbose DESTDIR=$PWD
time ctest --output-on-failure
time make package
fi
cd $BUILDDIR
fi
:
(後略)
10-zocl.rules を追加
zocl がユーザーから書き込めるようにパーミッションを変更します。具体的には /etc/udev/rule.d に次のような 10-zocl.rules を追加します。
KERNEL=="renderD*",MODE="0666"
Debian Package をインストールした際に 10-zocl.rules が /etc/udev/rule.d にインストールされるようにします。
diff --git a/src/CMake/config/edge/postinst.in b/src/CMake/config/edge/postinst.in
index 22136c09..b85a1032 100644
--- a/src/CMake/config/edge/postinst.in
+++ b/src/CMake/config/edge/postinst.in
@@ -48,6 +48,7 @@ echo "Invoking DKMS common.postinst for xrt"
/usr/lib/dkms/common.postinst xrt @XRT_VERSION_STRING@ "" "" $2
if [ $? -eq 0 ]; then
echo "Finished DKMS common.postinst"
+ install -m 644 /usr/src/xrt-@XRT_VERSION_STRING@/driver/edge/drm/zocl/10-zocl.rules /etc/udev/rules.d
echo "Loading new XRT Linux kernel modules"
udevadm control --reload-rules
modprobe zocl
diff --git a/src/CMake/dkms-edge.cmake b/src/CMake/dkms-edge.cmake
index d1d39750..61664945 100644
--- a/src/CMake/dkms-edge.cmake
+++ b/src/CMake/dkms-edge.cmake
@@ -38,6 +38,7 @@ SET (XRT_DKMS_CORE_COMMON_DRV ${XRT_DKMS_CORE_DIR}/common/drv)
SET (XRT_DKMS_DRIVER_SRCS
edge/drm/zocl/LICENSE
edge/drm/zocl/Makefile
+ edge/drm/zocl/10-zocl.rules
edge/drm/zocl/sched_exec.c
edge/drm/zocl/sched_exec.h
edge/drm/zocl/zocl_bo.c
diff --git a/src/runtime_src/core/edge/drm/zocl/10-zocl.rules b/src/runtime_src/core/edge/drm/zocl/10-zocl.rules
new file mode 100644
index 00000000..11ed38e1
--- /dev/null
+++ b/src/runtime_src/core/edge/drm/zocl/10-zocl.rules
@@ -0,0 +1 @@
+KERNEL=="renderD*",MODE="0666"