MENU

Kria KV260用のVitisプラットフォームの作成

Xilinxが公開しているVitisプラットフォームの作成チュートリアルの内容を試してみました。つまづいたポイントも含めてこのページにまとめています。

目次

動作確認環境

開発環境(ホストPC)

Ubuntu 22.04 LTS(Windows 10 PC上のWSL)

ツールバージョン

Vivado / Vitis 2022.1

Petalinux 2022.2

FPGAボード

Kria KV260 Vision AI Starter Kit

少なくともこちらの記事の内容については、KV260上で一通り確認できていることを前提としています。

実行手順

STEP
ハードウェアデザインの作成

Vivadoを使ってVitisアプリケーションの動作に必要なハードウェアを作成していきます。クロック、リセット、AXIインターフェース、割り込み信号等のハードウェア情報が含まれるXSA ファイルを生成します。

STEP
ソフトウェアコンポーネントの作成

PetaLinux を使用して、Linux カーネル、ルートファイルシステム、デバイス ツリー等のブートに必要なソフトウェアコンポーネントを作成していきます。

STEP
Vitisプラットフォームの作成

作成したハードウェアデザインとソフトウェアコンポーネントを組み合わせたVitisプラットフォーム(XPFM)を作成します。

STEP
テストアプリケーションの作成

Vitisプラットフォームを利用してテストアプリケーションを作成します。KV260上にアプリケーションを転送し、実行して動作確認を行います。

ハードウェアデザインの作成

プロジェクトの作成

必要な環境変数を設定し、Vivadoを起動します。

$ source <VIVADO_INSTALL_DIR>/settings64.sh
$ vivado &

Vivadoが起動したら、Create Project、Nextの順にクリックします。

Project nameにkv260_custom_platformと入力します。Project Locationは任意のディレクトリを指定して、Nextをクリックします。次の画面ではProject is an extensble Vitis platformにチェックを入れて、Nextをクリックします。

Boardsタブをクリックし、Search欄にKVと入力するとKria KV260 Vision AI Starter Kitが表示されます。これを選択してNextをクリックし、最後にSummaryが表示されるのでFinishをクリックします。

プロジェクトが作成されたら、Create Block Designをクリックします。

Design nameに今回はsystemと入力してOKをクリックします。

右側のDiagramで+のマーク(Add IP)をクリックし、Search欄にzynqと入力してZynq UltraScale+ MPSoCを選択します。

Run Block Automationをクリックします。

以下の3つの項目にチェックが入っていることを確認してOKをクリックします。

  • All Automation
  • Zynq_ultra_ps_e_0
  • Apply Boards Presets

クロック・リセットの作成

Clocking Wizardを追加して100MHz、200MHz、400MHzのCLKを新たに作成します。Add IPでClocking Wizardを追加し、Diagram上に配置されたclk_wiz_0をダブルクリックします。

Output Clocksタブを開き、デフォルトで設定されているclk_out1に加え、clk_out2を200MHz、clk_out3を400MHzに設定します。同じタブの下部にあるReset TypeについてActive Lowにチェックを入れて、OKをクリックします。

VitisフローではRTLやC/C++で記述されたハードウェアをKernelと呼び、Kernelはv++リンカでプラットフォームと接続されます。このKernelが使用するCLKは、PSが出力するpl_clkを利用することもできますが、最大4系統しかないことや各CLKの位相が揃っていないなどいくつかの制限があります。そのため、ここではClocking Wizardを追加し、Kernelが利用可能な100MHz、200MHz、400MHzのCLKを新たに作成しています。

同様の手順でProcessor System Resetを3つ追加します。Add IPで一つのProcessor System Resetを追加したら、Ctrl+Cでコピー、Ctrl+Vで貼り付けを繰り返すことで3つのIPを配置可能です。この状態でRun Connection Automationをクリックします。

All Automationにチェックを入れた後、clk_wiz_0のclk_in1を選択し、Clock Sourceを /zynq_ultra_ps_0/pl_clk0 (99MHz) に設定します。

3つのproc_sys_resetのslowest_sync_clkをそれぞれ選択し、Clock Sourceを以下のように設定します。

  • proc_sys_reset_0のClock Sourceをclk_wiz_0/clk_out1 (100MHz) に
  • proc_sys_reset_1のClock Sourceをclk_wiz_0/clk_out2 (200MHz) に
  • proc_sys_reset_1のClock Sourceをclk_wiz_0/clk_out3 (400MHz) に

ここまで設定できたら、OKをクリックします。Diagram上でclk_wiz_0のlocked端子と3つのproc_sys_resetのdcm_locked端子を配線します。

Platform SetupタブでClockを選択し、clk_wiz_0のclk_out1~clk_out3のEnabledにチェックを入れます。また、それぞれのIDを0, 1, 2に割り当てます。clk_out2のIs Defaultにチェックを入れ、v++リンカが利用するデフォルトCLKを設定します。

割り込みコントローラの作成

再びDiagramに戻り、Zynq UltraScale+ MPSocのブロックをダブルクリックします。PS-PL Configuration、PS-PL Interfacesの順に選択し、AXI HPM0 FPDとAXI HPM1 FPDのチェックを外し、AXI HPM0 LPDにチェックを入れます。AXI HPM0 LPD Data Widthは32に設定し、OKをクリックします。

Kernelからの割り込みはv++リンカでプラットフォームと接続されます。KernelからPSの pl_ps_irqポートに割り込み信号を接続することもできますが、このままだと最大で16の割り込み信号しか扱えません。より多くの割り込み信号を供給できるよう、PSのAXI HPM0 LPDポートにAXI 割り込みコントローラーを接続します。

Zynq UltraScale+ MPSoCではPSからPLへのインターフェースとして、AXI HPM0 FPD、AXI HPM1 FPD、AXI HPM0 LPDの3つがあります。PS内には2種類のPower Domainが存在し、FPDはFull Power Domain、LPDはLow Power Domainのことを示しています。HPMはHigh Performance Masterの略です。今回はPSからAXI割り込みコントローラ等の32bitの制御レジスタを読み書きしたいだけなので、AXI HPM0 LPD を使用します。残りのポートは後でKernelを追加した際にVitisから利用できるよう、ここでは明示的に無効にしています。

Add IPでAXI Interrupt Controllerを追加し、Diagram上に配置されたaxi_intc_0をダブルクリックします。Interrupt Output ConnectionをSingleへと変更し、OKをクリックします。

Run Connection Automatinoをクリックし、そのままOKをクリックします。axi_intc_0のirq端子をzynq_ultra_ps_e_0のpl_ps_irq[0:0]へマウスで接続します。

Platform Setupタブ、Interruptの順に選択し、axi_intc_0のintrのEnabledにチェックを入れます。

AXIインターフェースの設定

Platform Setupタブ、AXI Portの順に選択し、zynq_ultra_ps_e_0のS_AXI_LPDを除く全てのポートのEnabledにチェックを入れ、MemportやSP Tagを以下のように設定します。これにより、Vitisで作成したKernelがこれらのAXI Portを介してPS側のDDRにアクセスすることができます。

以下はZynq UltraScale+ Device Technical Reference Manual(UG1085)内の図を引用しています。S_AXI_HPC0_FPDとS_AXI_HPC1_FPDのHPCはHigh Performance Coherentの略で、CCI(Cache-Coherent Interconnect)を介してAPU(Application Processing Unit)内のL1/L2キャッシュをスヌープすることにより、キャッシュコヒーレンシを維持しながらDDRにアクセス可能です。一方でS_AXI_HP0_FPD~S_AXI_HP3_FPDはキャッシュコヒーレンシは維持できないものの、HPCのポートよりもレイテンシが短いというメリットがあります。

参考URL: https://docs.xilinx.com/r/en-US/ug1085-zynq-ultrascale-trm

ここまでできたら、再びDiagramに戻ってValidate Designをクリックします。

Validate Designによりaxi_intc_0のintr端子が接続されていないとの警告が表示されますが、Vitisにより作成したKernelの割り込み信号がintrに接続されるため、この段階では警告は無視しても問題ありません。

ブロックデザインの最上位ラッパー作成します。Sourcesタブのsystem.bdを右クリックし、Create HDL Wrapperをクリックします。Let Vivado manage wrapper and auto-updateを選択してOKをクリックします。

XSAファイルの作成

Vitisにハードウェア情報を渡すためのXSAファイルを作成していきます。Generate Block Designをクリックし、Synthesis OptionsでGlobalを選択してGenerateをクリックします。これにより、Create Block Designで作成した各IPのネットリストが生成されます。

同様にFlow Navigatorの中のGenerate Bitstreamをクリックします。警告がいくつか出てくるケースがありますが、全て無視して進めます。ビットストリームが生成されると以下のようなポップアップが出てきますが、ここではView Reportsを選択してOKをクリックします。

Export Platformをクリックし、Nextをクリックします。Platform TypeではHardware and hardware emulationを選択し、Nextをクリックします。

Patform StateではPre-synthesisを選択し(デフォルトで既に選択されている状態)、Include bitstreamにチェックを入れてNextをクリックします。

Platform Propertiesでは作成したプラットフォームの説明を入力してNextをクリックします。以下はその一例です。

XSA file nameに出力するXSAファイルの名前を入力してNextをクリックします。最後に出力するプラットフォームの情報を確認してFinishをクリックすると、XSAファイルが出力されます。

ソフトウェアコンポーネントの作成

Petalinuxのビルド

Petalinux Tools 2022.2のインストーラをダウンロードし、インストーラを実行してPetalinux作成に必要なツール群をインストールしておきます。

https://www.xilinx.com/member/forms/download/xef.html?filename=petalinux-v2022.2-10141622-installer.run

KV260用のPetalinuxプロジェクトを作成していくためには、KV260用のBSP(Board Support Package)が必要になります。以下のURLから、KV260用のBSPをダウンロードしておきます。

https://www.xilinx.com/member/forms/download/xef.html?filename=xilinx-kv260-starterkit-v2022.2-10141622.bsp

Kria K26 SOM Wikiを見ると、Kria Starter Kit BSPの「2022.1」を利用する場合は、事前にPetaLinuxのアップグレードが必要と記載されています。「2022.2」の場合はアップグレードが必要か否か定かではありませんが、念のためPetalinux 2022.2のアップグレードを行っておきます。

$ source <PETALINUX_INSTALL_DIR>/settings.sh
$ petalinux-upgrade -u http://petalinux.xilinx.com/sswreleases/rel-v2022/sdkupdate/2022.2_update1/ -p "aarch64" --wget-args "--wait 1 -nH --cut-dirs=4"

ダウンロードしたBSPを指定してPetalinuxのプロジェクトを作成し、petalinux-configを実行してMenuconfigを開きます。Filesystem packages -> libx -> xrtの順にクリックし、xrtをONにします。これで、ルートファイルシステムにXRT(Xilinx Runtime Library)がインストールされるようになります。最後にpetalinux-buildでビルドを実行します。

$ petalinux-create --type project -s ./xilinx-kv260-starterkit-v2022.2-10141622.bsp
$ cd xilinx-kv260-starterkit-2022.2
$ petalinux-config -c rootfs # xrtをONに設定
$ petalinux-build

Webで検索すると、以下のようにVivadoで生成したXSAファイルを指定してコンフィグを行ってから、ビルドを実行している例が見つかります。

$ petalinux-config --get-hw-description=<path_to_xsa_file>
$ petalinux-config -c rootfs # xrtをONに設定
$ petalinux-build

私の環境では上記手順で生成したイメージファイルの場合、Linuxカーネルの起動時にハングしてしまう現象が見られています。よって、XSAファイルを指定したコンフィグはあえて省略しています。

ビルドエラーの解析

環境依存なのかもしれませんが、私の環境では途中で以下のようなErrorが発生しビルドが止まってしまいました。

FAILED: doc/zmq_atomic_counter_destroy.html <path_to_work>/xilinx-kv260-starterkit-2022.2/build/tmp/work/x86_64-linux/zeromq-native/4.3.4-r0/build/doc/zmq_atomic_counter_destroy.html 
cd <path_to_work>/xilinx-kv260-starterkit-2022.2/build/tmp/work/x86_64-linux/zeromq-native/4.3.4-r0/build && /usr/bin/asciidoc -d manpage -b xhtml11 -f <path_to_work>/xilinx-kv260-starterkit-2022.2/build/tmp/work/x86_64-linux/zeromq-native/4.3.4-r0/zeromq-4.3.4/doc/asciidoc.conf -azmq_version=4.3.4 -o doc/zmq_atomic_counter_destroy.html ../zeromq-4.3.4/doc/zmq_atomic_counter_destroy.txt
<path_to_work>/xilinx-kv260-starterkit-2022.2/build/tmp/hosttools/python3: No module named asciidoc

asciidocによるHTMLドキュメント生成過程でのエラーのようですが、生成するソフトウェアの中身には直接関係ないように思えます。そこで、以下の手順でasciidocによるドキュメント生成自体を省略します(修正方法として正しいのかわかりません)。

xilinx-kv260-starterkit-2022.2/build/tmp/work/x86_64-linux/zeromq-native/4.3.4-r0/以下を探していると、CMakeLists.txtに以下のような記述を見つけました。

option(WITH_DOCS "Build html docs" ON)
if(WITH_DOCS)
    ...
    if(WITH_DOC)
      add_custom_command(
        OUTPUT ${dst}
        COMMAND ${ASCIIDOC_EXECUTABLE} -d manpage -b xhtml11 -f ${CMAKE_CURRENT_SOURCE_DIR}/doc/asciidoc.conf
                -azmq_version=${ZMQ_VERSION} -o ${dst} ${src}
    ...
endif()

CMakeのオプション「WITH_DOCS」をOFFにすることで、asciidocを使ったドキュメント生成処理をOFFにできそうです。run.do_configureスクリプト内にcmakeの実行コマンドが記述されているので、ここにオプションを追記します。

cmake_do_configure() {
  ...

	cmake \
    -G 'Ninja' -DCMAKE_MAKE_PROGRAM=ninja \
    ...
    -Wno-dev \
    -DWITH_DOCS=OFF # これを追記
}

この状態でrun.do_configureスクリプトを手動で実行し、再びpetalinux-buildを実行します。無事にビルド処理が進み、images/linux以下にPetalinuxのイメージファイルが生成されました。

$ pushd <path_to_work>/xilinx-kv260-starterkit-2022.2/build/tmp/work/x86_64-linux/zeromq-native/4.3.4-r0/temp
$ ./run.do_configure
$ popd
$ petalinux-build

Petalinux SDKもここで作成しておきます。images/linux以下にsdk.shという名前のスクリプトが生成されます。

$ petalinux-build --sdk

ビルドしたPetalinuxが正常に起動するか確認するため、SDカードイメージを作成します。

$ petalinux-package --boot --u-boot --force
$ petalinux-package --wic --images-dir images/linux/ --bootfiles "ramdisk.cpio.gz.u-boot,boot.scr,Image,system.dtb,system-zynqmp-sck-kv-g-revB.dtb" --disk-name "mmcblk1"

images/linux以下に生成されるpetalinux-sdimage.wicがSDカードイメージになります。このファイルをbalenaEtcher等でSDカードに書き込み、KV260を起動します。しばらくすると以下のようなログインプロンプトが現れ、無事にビルドしたPetalinux で起動することを確認できました。

PetaLinux 2022.2_update1_04022314 xilinx-kv260-starterkit-20222 ttyPS1

xilinx-kv260-starterkit-20222 login:

デバイスツリーの作成

Linuxは起動時にデバイスツリーを読み込むことでハードウェア情報を認識します。KV260ではLinuxの起動後にPLをロードするため、Linuxが起動後に動的にPLを認識できるよう、デバイスツリーオーバーレイという仕組みを利用します。ここでは、オーバーレイに必要なデバイスツリーを作成していきます。

必要な環境変数を設定し、XSCT(Xilinx Software Command-Line Tool)を起動します。XSCTはVitisの機能をコマンドラインで実行可能なツールです。私の環境では、以下のようにxsctを実行するとSegmentation faultが発生してしまいました。

$ source <VITIS_INSTALL_DIR>/settings64.sh
$ mkdir kv260_vitis_platform
$ cd kv260_vitis_platform
$ xsct
<VITIS_INSTALL_DIR>/bin/xsct: line 241:  3305 Segmentation fault      "$RDI_BINROOT"/unwrapped/"$RDI_PLATFORM$RDI_OPT_EXT"/rlwrap -rc -b "(){}[],+= & ^%$#@"";|\\" -f "$HDI_APPROOT"/scripts/xsct/xsdb/cmdlist -H "$LOG_FILE" "$RDI_BINROOT"/loader -exec rdi_xsct "${RDI_ARGS[@]}"

以下のように-norlwrapオプションをつけることにより、XSCTが起動するようになりました。

$ xsct -norlwrap

createdtsコマンドでXSAファイルからデバイスツリーを作成します。

xsct% createdts -hw <path_to_xsa_file> -zocl -platform-name mydevice -git-branch xlnx_rel_v2022.2 -overlay -compile -out mydevice

各オプションは以下のような意味となっています。

  • -hw: Vivadoで出力したXSAファイルへのパスを指定
  • -zocl: zoclドライバーの有効化
  • -platform-name: 生成するソフトウェアプラットフォームの名前
  • -git-branch: Linux device tree generator for the Xilinx SDK のブランチを指定(デフォルトではMasterブランチ)
  • -overlay: デバイスツリーオーバーレイのサポートを有効化
  • -compile: デバイスツリーソース(dts)をコンパイルしてバイナリのデバイスツリーブロブ(dtb)を生成する
  • -out : ソフトウェアプラットフォームの生成ディレクトリを指定

オーバーレイ用のデバイスツリーをコンパイルし、生成されたバイナリをdtg_outputという名前のディレクトリに保存します。

$ dtc -@ -O dtb -o mydevice/mydevice/mydevice/psu_cortexa53_0/device_tree_domain/bsp/pl.dtbo mydevice/mydevice/mydevice/psu_cortexa53_0/device_tree_domain/bsp/pl.dtsi
$ mkdir dtg_output
$ cp mydevice/psu_cortexa53_0/device_tree_domain/bsp/pl.dtbo dtg_output

各オプションの意味は以下のようになっています。

  • -@: シンボルを生成する
  • -O: 出力フォーマットの指定
  • -o: 出力ファイル名

Vitisプラットフォームの作成

Vitisプラットフォーム作成に必要なファイルを、既に作成済みのkv260_vitis_platformディレクトリに準備していきます。

sdk.shを実行しsysrootを生成します。このとき、環境変数LD_LIBRARY_PATHには何も設定しないでおきます。

$ cd kv260_vitis_platform
$ pushd <path_to_work>/xilinx-kv260-starterkit-2022.2/images/linux
$ ./sdk.sh -d <path_to_kv260_vitis_platform_dir>
$ popd

pfmという名前のディレクトリを作成し、その下にboot、sd_dirという名前のディレクトリをそれぞれ作成しておきます。

$ mkdir pfm
$ mkdir pfm/boot
$ mkdir pfm/sd_dir

KV260に電源が投入されると、PMU(Platform Management Unit)が起動し内部ROMに書き込まれているファームによって動作します。PMUはプライマリブートデバイス(KV260の場合はKria SOM上に配置されたQSPI Flash)上のBOOT.binというファイルを読みに行きます。pfm/bootには、BOOT.binを作成するのに必要なファイルを置いておきます。

  • FSBL(fsbl.elf): 内部ROMファームにより内部RAM上に展開され、Cortex-A53により実行される
  • PMUファームウェア(pmufw.elf): FSBLの中で内部RAM上に展開され、PMUにより実行される
  • Arm Trusted Firmware(bl31.elf): FSBLの中でDRAM上に展開され、Cortex-A53により実行される
  • U-boot(u-boot.elf): FSBLの中でDRAM上に展開され、Cortex-A53により実行される

pfm/sd_dirにはSDカードのFAT32パーティションに格納すべきファイル(boot.scrやsystem.dtb)を置いておきます。KV260の場合、BOOT.binはデフォルトでQSPI Flashに書き込まれているため、pfm/bootにファイルを格納しBOOT.binを新たに作成する必要はありません。また、今回は上述した手順で既に起動確認済みのSDカードをそのまま利用するため、pfm/sd_dirにもファイルを格納する必要はありません。

Vitisを起動し、Workspaceに任意のディレクトリを指定してLaunchをクリックします。Windowが現れたら、Create Platform Projectをクリックします。

私の環境では、Create Platform Projectをクリックしてもなぜか何も反応しませんでした。gnome-icon-themeをインストールすることで、Windowが起動するようになりました。

$ sudo apt install gnome-icon-theme

Platform project nameにkv260_customと入力し、Nextをクリックします。

XSA FileにVivadoで生成したXSAファイルを指定し、Operating systemにlinuxを選択します。ここでは、Generate boot componentsにチェックを入れていますが、特にチェックを入れなくても(ブート用のファイルを生成しなくても)手順は進められます。

linux on psu_cortexa53を選択し、Bif FileのドロップダウンアイコンをクリックしてGenerate Bifをクリックします。Boot Components DirectoryとFAT32 Partation Directoryにそれぞれpfm/bootとpfm/sd_dirのディレクトリを指定し、左上のBuildボタンをクリックすると、kv260_custom/export以下にVitisプラットフォームが生成されます。

以下のコマンドで生成したプラットフォームの内容を確認可能です。

$ platforminfo kv260_custom/export/kv260_custom/kv260_custom.xpfm

テストアプリケーションの作成

Vitisを起動し、Workspaceに任意のディレクトリを指定してLauchをクリックします。Windowが現れたら、Create Application Projectをクリックします。次の画面ではそのままNextをクリックします。

作成したVitisプラットフォームを追加するため、右上のAddをクリックします。

作成したVitisプラットフォームを指定してOpenをクリックします。kv260_customという名前のプラットフォームが追加されたら、それを選択してNextをクリックします。

Application project nameにvaddと入力し、Nextをクリックします。Sysroot pathにsdk.shを使って生成したsysrootへのパスを指定し、Nextをクリックします。

サンプルアプリケーションとしてSimple Vector Additionを選択し、Finishをクリックします。

Active build configurationでHardwareを選択します。Explorerタブのvadd_system_hw_link.prjを選択してBuildボタンをクリックすると、ハードウェアカーネルの合成が始まります。処理が完了したら、vadd.prjを選択してBuildボタンをクリックし、ホストアプリケーションをビルドします。

vaddprjという名前のディレクトリを作成し、この中にKV260上に転送が必要なファイルを集めていきます。このとき、binary_container_1.xclbinの拡張子を「xclbin」から「bin」に変更しておきます。

$ mkdir vaddprj
$ cd vaddprj
$ cp <path_to_work>/kv260_vitis_platform/dtg_output/pl.dtbo . # オーバーレイ用のデバイスツリー
$ cp <path_to_work>/kv260_vitis_application/vadd_system_hw_link/Hardware/binary_container_1.xclbin binary_container_1.bin # カーネルのビットファイルを含むバイナリ
$ cp <path_to_work>/kv260_vitis_application/vadd/Hardware/vadd . # カーネルを動作させるためのソフトウェア

また、shell.jsonという名前のファイルを新たに作成し、以下のように記述してvaddprjの中にファイルを置いておきます。

{
    "shell_type" : "XRT_FLAT",
    "num_slots": "1"
}

ホストPCからKV260上に集めたファイルを転送します。

$ scp -r vaddprj petalinux@192.168.0.14:~/

転送したファイルはKV260上の/lib/firmware/xilinx/以下に置いておく必要があります。xmutilコマンドを使ってハードウェア情報を登録します。

xilinx-k260-starterkit-20222:~$ sudo cp -R vaddprj /lib/firmware/xilinx/
xilinx-k260-starterkit-20222:~$ sudo xmutil listapps
xilinx-k260-starterkit-20222:~$ sudo xmutil unloadapp
xilinx-k260-starterkit-20222:~$ sudo xmutil loadapp vaddprj

カーネルを実行します。以下のように表示すれば成功です。

xilinx-k260-starterkit-20222:~$ cd vaddprj
xilinx-k260-starterkit-20222:~$ ./vadd binary_container_1.bin
Loading: 'binary_container_1.bin'
Trying to program device[0]: edge
Device[0]: program successful!
TEST PASSED
  • URLをコピーしました!

この記事を書いた人

映像処理ハードウェアの研究開発をしています。ASIC, FPGA, 機械学習などの話題に興味があります。このブログでは、自分が最近勉強したことなどを中心にマイペースに発信していきます。

目次