20210512のLinuxに関する記事は2件です。

Visual Studio 2019 で linux コンソールアプリをデバッグする

.NET (Core) でのLinuxコンソールアプリのデバッグ 最近、Visual Studio 2019でWSL 2を用いてLinuxアプリのデバッグができるようになりました。 しかし、自分はつまづいた点がいくつかあったので、紹介したいと思います。 1. デバッグにWSL 2の選択がない Visual Studio の更新が終わったあと、試そうと思ったら こんな感じで選択肢に、WSL 2の選択肢がありませんでした。 これはすぐに解決しました。公式ホームページによると前提条件の一つに下の一文がありました。 .NET Core デバッグと WSL 2 オプション コンポーネントが含まれる Visual Studio 2019 v16.9 Preview 1 以降のバージョン。 [引用] はい「WSL 2 オプション コンポーネント」とやらが入っていなかっただけのようです。 というわけで、Visula Studio Installer から.NET Core Debugging with WSL 2コンポーネントをインストールします。 ただし、この時には「.NET Core クロスプラットホームの開発」のものを選択するようにしましょう。「ASP.NET と Web開発」にあるやつは関係ないです。 インストールが終わると、下のように普通に選択肢がでてきました。 2. デバッグ実行時のワーキングディレクトリどーすんの? 「Properties」ディレクトリにあるlaunchSettings.jsonのworkingDirectoryをいじることでできます。 たとえば、 launchSettings.json { "profiles": { "WSLDebug": { "commandName": "Project" }, "WSL 2": { "commandName": "WSL2", "workingDirectory": "/mnt/d" } } } Program.cs Console.WriteLine($"{Environment.CurrentDirectory}"); として実行することで、「出力」ウィンドウをみると実際に変更されていることがわかると思います。 3. 引数の指定はどーすんの? これも「Properties」ディレクトリにあるlaunchSettings.jsonのcommandLineArgsをいじることでできます。 たとえば、 launchSettings.json { "profiles": { "WSLDebug": { "commandName": "Project" }, "WSL 2": { "commandName": "WSL2", # 実際の環境では「WSLDebug.dll」のところは、自身のプログラムの「アセンブリ名.dll」とすること。 "commandLineArgs": "{OutDir}WSLDebug.dll arg1 arg2 arg3" } } } Program.cs Console.WriteLine($"{string.Join(" ", args)}"); として実行することで、「出力」ウィンドウをみると指定した引数が出力されていると思います。 最後に 以上の3点が自分がつまづいた点でした。 他にもディストリビューションごとにプロファイルを用意する方法や、詳しい起動プロファイルでの WSL の設定などは公式ホームページを参照してください。 環境 Windows 10 Pro 20H2 Visual Studio Community 2019 16.9.4 WSL 2 - Ubuntu 20.04.2 LTS dotnet 5.0.203 参照
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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

はじめに 筆者は 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 のビルド方法を以下の記事で紹介しました。 『Ultra96/Ultra96-V2 向け Debian GNU/Linux で XRT(Xilinx Runtime) を動かす(ビルド編)』@Qiita 上の記事は 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 で公開しています。 https://github.com/ikwzm/ZynqMP-FPGA-Linux https://github.com/ikwzm/ZynqMP-FPGA-Ubuntu20.04-Ultra96 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 が定義されています。 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}) 参考 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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む