LoginSignup
2

More than 1 year has passed since last update.

posted at

updated at

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

注意(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 に用意しています。

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

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 にします。

ZynqMP-FPGA-XRT/files/00-xrt.patch
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 を修正してバージョンの上限を撤廃します。

ZynqMP-FPGA-XRT/files/01-xrt.patch
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 が定義されています。

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)
add_subdirectory(common)
 if (${XRT_EDGE_BUILD} STREQUAL "yes")
   add_subdirectory(edge)
 else()
   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()
    :
    (後略)

そして、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 にあります。

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
    :
    (前略)
    :
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 を追加します。

/etc/udev/rule.d/10-zocl.rules
KERNEL=="renderD*",MODE="0666"

Debian Package をインストールした際に 10-zocl.rules が /etc/udev/rule.d にインストールされるようにします。

ZynqMP-FPGA-XRT/files/03-xrt.patch
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"

参考

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
What you can do with signing up
2