Vitis2022.1版　KV260向け簡単なプラットフォームの作り方（AIエッジコンテスト対応版）

# FPGAの設計時間を短くしたい。
最近のFPGAは高性能になってきました。ハードウェアもできて、ソフトウェアもできます。AI もできるし画像処理もできます。独自のCPU まで入れることもできます。一方で、　設計ツールが多くなり覚えないといけないことが多くなりました。
しかもそのツール一つ一つが複雑でもあります。従って覚えるのも大変ですし、やらないといけない作業も増えてきています。

一方で、設計者のニーズとしては設計時間の短縮というのを望んでるところもあります。

そのそう反した想いはどうやって実現するのでしょうか。

FPGAメーカーである、ザイリンクスでは、FPGAの開発サイクルの短縮化も推し進めています。

今回はそのひとつで、Vitis（ヴイティス）プラットフォーム、いうものを簡単に作る方法をご紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/44878f89-a36e-152f-ca8f-dbb94f0ab490.png)

# Vitisプラットホームの簡単な作り方

VitisプラットホームはFPGAボードに対して、動作する必要最低限のFPGA設計を提供しています。
この部分は誰が作っても同じになりがちで、あまり時間をかけたくないところでもあります。
一方で、いろんなツールを使いながら、最初から作るには複雑になってますので初めての人には混乱するかもしれません。

今回はできるだけ簡単にと思いまして、通常使うツールの一つ（Petalinux)を使わないで作成したいと思います。

今回はVivado（ビバド）のTCLスクリプト機能、及びVitisのデバイスツリー作成機能を使いまして、できるだけ簡単なVitisプラットフォームの作成方法をご紹介いたします。

開発手順を知ってる人には、意外に思うかもしれませんが、今回はプラットフォームを作成するのにPetaLinux を使用しません。この部分は比較的誰が作っても同じようになる傾向が強いため時間を短縮できるメリットがあるために今回は他の方法でプラットフォームを実現したいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/2c514980-6cd1-5da7-33f6-f585f34917e3.png)

# 予め用意しておくもの

今回は Linux 上で開発を前提にしています。Linuxは、ubuntuを使用しています。ただしUbuntu パソコンを持っている人はまだ少数派です。なので Windows 上でWSL 2を使った Ubuntuでも試しています。Windows に開発ツールを入れる方法は別途ブログで紹介いたします。

###### 開発ツール Vitisが動くパソコン
　Vitisを動作させるためには Linuxパソコンの使用が推奨されています。Windows 版も用意されていますが、機能が制限されており全部の機能を使うためには Linux 版を推奨してるからです。元々の開発が Linux からスタートしているってのもあります。

 
　Vitisは高性能パソコンを好みます。できれば、メモリーを多く用意したほうがいいです。３２Gbyteくらいです。
　ただ、遅くはなりますが、１６Gバイトでも動かしている方は多いので、試すことはできます。今回は16 Gバイト のパソコンでも試しています。

　早いパソコンが欲しい方は、レンタルという手もあります。アマゾンのAWSや、Google Cloudを使うのもいいでしょう。
　日本では、ACRiルームと言うところが、FPGA開発ツールを無料で貸してくれます。KRIAも一台ありますので、お試しに使うのもいいでしょう。
　
https://gw.acri.c.titech.ac.jp/wp/

今回このブログでは、Linux専用パソコンで、Ubuntu 20.04、Windows11 上のWSL2で、Ubuntu 20.04を使用して、ともVitisは、2022.1のバージョンを使用しています。

###### ZYNQMPの共通イメージ
KV260上でLinuxを使うための、イメージファイルが入っています。
今回はこのイメージがあるため、Petalinuxのツールが不要になりました

https://japan.xilinx.com/support/download/index.html/content/xilinx/ja/downloadNav/embedded-platforms.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/1fb08886-1af5-f409-e959-ac0326ba61b1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/26b3e5fd-d7b1-d1b1-8149-983f34cc7cac.png)

###### デバイスツリージェネレータ

KV260を動かすのには、デバイスツリーが必要になります。これを作るプログラムがオープンソースで公開されてます。これをあらかじめダウンロードします。バージョンが決まってますので注意してください。Linux上で、実現しています。
``` device-tree.git
git clone https://github.com/Xilinx/device-tree-xlnx.git
cd device-tree-xlnx/
git checkout xlnx_rel_v2022.1
```



# Vitisプラットホームの作成手順
１：Vivadoのツールで、ハードウェアブロックを生成します。
２：Vitisのツールで、デバイスツリーを作成します。
３：Vitisプラットフォームを作成します。そのために必要なファイルも集めます。
４：きちんと動くかどうかテストプログラムを作成しKV260で動作させます。


# ステップ１　Vivadoでハードウェア作り。
プラットフォームを作るには、プラットフォーム対応の元になるハードウェアが必要になります。
ここでカスタマイズすることも出来るのですが、今回は基本的な機能を入れるのみに致します。

また、今回の目的は簡単に作るっていうのがひとつの目的です。
ハードウェアブロックを作るための、作成手順は基本的に誰が作っても同じになります。
そのためここはスクリプト化しまして、それを実行するだけでハードウェアブロックを作成します。

なお、Vivadoをスクリプトを使わず、GUIで作成したい人向けにKV260向けに作成手順をブログ化しています。興味がある方は参照してください。

https://qiita.com/basaro_k/items/e83128c265ae86801bbc

1.1 作業ディレクトリを作成します。今回は AIEDGEにしました。ディレクトリーを作成しそこに移動します。Linux 上のターミナルで操作します。

``` sh:mkdir.AIEDGE
mkdir AIEDGE
cd AIEDGE
```

1.2 Vivadoを動かす環境設定を行います。後ほどVitisを動かすので、Vitisのセッティングを行います。

```sh:vivado_setting.sh
source /tools/Xilinx/Vitis/2022.1/settings64.sh
```

1.3 今回はスクリプトファイルを作りましたので、それを実行することでVivado作業を終わりにしたいと思います。そのために必要なファイルを作成してください。下記の所からコピーできます。make_vivado.sh と make_vivado.tclを作成します。エディターは geditなどが使えます。

```sh:make_vivado.sh
vivado -mode tcl -source make_vivado.tcl 
```

make_vidado.tclは、長いので、折りたたんでいます。三角印をクリックして、展開して確認してください。Vivadoという、ツールはメモリーを消費します。今回は16GBメモリー搭載パソコンでも動作するように動作CPUの数を２に制限しています。32GBメモリーを積んでいましたら、CPUが６～８くらいはいけますので、TCLファイルのjobs の後の数字を大きくしてお試しください。２箇所あります。

<details><summary>make_vivado.tcl</summary>

```tcl:make_vivado.tcl
#-----------------------------------------------------------
# Vivado v2022.1 (64-bit)
# SW Build 3526262 on Mon Apr 18 15:47:01 MDT 2022
# IP Build 3524634 on Mon Apr 18 20:55:01 MDT 2022
# Start of session at: Wed Aug 31 19:00:01 2022
# Process ID: 8206
# Current directory: .
# Command line: vivado
# Log file: ./vivado.log
# Journal file: ./vivado.jou
# Running On: tadaaki-AERO-15-YB, OS: Linux, CPU Frequency: 3100.000 MHz, CPU Physical cores: 8, Host memory: 67296 MB
#-----------------------------------------------------------
start_gui
create_project vivado ./vivado -part xck26-sfvc784-2LV-c
set_property board_part xilinx.com:kv260_som:part0:1.3 [current_project]
set_property platform.extensible true [current_project]
create_bd_design "system"
update_compile_order -fileset sources_1
startgroup
create_bd_cell -type ip -vlnv xilinx.com:ip:zynq_ultra_ps_e:3.4 zynq_ultra_ps_e_0
endgroup
apply_bd_automation -rule xilinx.com:bd_rule:zynq_ultra_ps_e -config {apply_board_preset "1" }  [get_bd_cells zynq_ultra_ps_e_0]
set_property -dict [list CONFIG.PSU__FPGA_PL1_ENABLE {0} CONFIG.PSU__USE__M_AXI_GP0 {0} CONFIG.PSU__USE__M_AXI_GP1 {0} CONFIG.PSU__USE__M_AXI_GP2 {1}] [get_bd_cells zynq_ultra_ps_e_0]
startgroup
create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0
endgroup
set_property -dict [list CONFIG.CLKOUT2_USED {true} CONFIG.CLKOUT3_USED {true} CONFIG.CLKOUT4_USED {true} CONFIG.CLKOUT5_USED {true} CONFIG.CLKOUT6_USED {true} CONFIG.CLK_OUT1_PORT {clk_100} CONFIG.CLK_OUT2_PORT {clk_150} CONFIG.CLK_OUT3_PORT {clk_200} CONFIG.CLK_OUT4_PORT {clk_300} CONFIG.CLK_OUT5_PORT {clk_400} CONFIG.CLK_OUT6_PORT {clk_600} CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {150.000} CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {200.000} CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {300.000} CONFIG.CLKOUT5_REQUESTED_OUT_FREQ {400.000} CONFIG.CLKOUT6_REQUESTED_OUT_FREQ {600.000} CONFIG.RESET_TYPE {ACTIVE_LOW} CONFIG.MMCM_CLKOUT1_DIVIDE {8} CONFIG.MMCM_CLKOUT2_DIVIDE {6} CONFIG.MMCM_CLKOUT3_DIVIDE {4} CONFIG.MMCM_CLKOUT4_DIVIDE {3} CONFIG.MMCM_CLKOUT5_DIVIDE {2} CONFIG.NUM_OUT_CLKS {6} CONFIG.RESET_PORT {resetn} CONFIG.CLKOUT2_JITTER {107.567} CONFIG.CLKOUT2_PHASE_ERROR {87.180} CONFIG.CLKOUT3_JITTER {102.086} CONFIG.CLKOUT3_PHASE_ERROR {87.180} CONFIG.CLKOUT4_JITTER {94.862} CONFIG.CLKOUT4_PHASE_ERROR {87.180} CONFIG.CLKOUT5_JITTER {90.074} CONFIG.CLKOUT5_PHASE_ERROR {87.180} CONFIG.CLKOUT6_JITTER {83.768} CONFIG.CLKOUT6_PHASE_ERROR {87.180}] [get_bd_cells clk_wiz_0]
startgroup
create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 proc_sys_reset_0
endgroup
copy_bd_objs /  [get_bd_cells {proc_sys_reset_0}]
copy_bd_objs /  [get_bd_cells {proc_sys_reset_0}]
copy_bd_objs /  [get_bd_cells {proc_sys_reset_0}]
copy_bd_objs /  [get_bd_cells {proc_sys_reset_0}]
copy_bd_objs /  [get_bd_cells {proc_sys_reset_0}]
startgroup
apply_bd_automation -rule xilinx.com:bd_rule:board -config { Clk {/zynq_ultra_ps_e_0/pl_clk0 (99 MHz)} Manual_Source {Auto}}  [get_bd_pins clk_wiz_0/clk_in1]
apply_bd_automation -rule xilinx.com:bd_rule:board -config { Manual_Source {/zynq_ultra_ps_e_0/pl_resetn0 (ACTIVE_LOW)}}  [get_bd_pins clk_wiz_0/resetn]
apply_bd_automation -rule xilinx.com:bd_rule:board -config { Manual_Source {/zynq_ultra_ps_e_0/pl_resetn0 (ACTIVE_LOW)}}  [get_bd_pins proc_sys_reset_0/ext_reset_in]
apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/clk_wiz_0/clk_100 (100 MHz)} Freq {100} Ref_Clk0 {None} Ref_Clk1 {None} Ref_Clk2 {None}}  [get_bd_pins proc_sys_reset_0/slowest_sync_clk]
apply_bd_automation -rule xilinx.com:bd_rule:board -config { Manual_Source {/zynq_ultra_ps_e_0/pl_resetn0 (ACTIVE_LOW)}}  [get_bd_pins proc_sys_reset_1/ext_reset_in]
apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/clk_wiz_0/clk_150 (150 MHz)} Freq {150} Ref_Clk0 {None} Ref_Clk1 {None} Ref_Clk2 {None}}  [get_bd_pins proc_sys_reset_1/slowest_sync_clk]
apply_bd_automation -rule xilinx.com:bd_rule:board -config { Manual_Source {/zynq_ultra_ps_e_0/pl_resetn0 (ACTIVE_LOW)}}  [get_bd_pins proc_sys_reset_2/ext_reset_in]
apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/clk_wiz_0/clk_200 (200 MHz)} Freq {200} Ref_Clk0 {None} Ref_Clk1 {None} Ref_Clk2 {None}}  [get_bd_pins proc_sys_reset_2/slowest_sync_clk]
apply_bd_automation -rule xilinx.com:bd_rule:board -config { Manual_Source {/zynq_ultra_ps_e_0/pl_resetn0 (ACTIVE_LOW)}}  [get_bd_pins proc_sys_reset_3/ext_reset_in]
apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/clk_wiz_0/clk_300 (300 MHz)} Freq {300} Ref_Clk0 {None} Ref_Clk1 {None} Ref_Clk2 {None}}  [get_bd_pins proc_sys_reset_3/slowest_sync_clk]
apply_bd_automation -rule xilinx.com:bd_rule:board -config { Manual_Source {/zynq_ultra_ps_e_0/pl_resetn0 (ACTIVE_LOW)}}  [get_bd_pins proc_sys_reset_4/ext_reset_in]
apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/clk_wiz_0/clk_400 (400 MHz)} Freq {400} Ref_Clk0 {None} Ref_Clk1 {None} Ref_Clk2 {None}}  [get_bd_pins proc_sys_reset_4/slowest_sync_clk]
apply_bd_automation -rule xilinx.com:bd_rule:board -config { Manual_Source {/zynq_ultra_ps_e_0/pl_resetn0 (ACTIVE_LOW)}}  [get_bd_pins proc_sys_reset_5/ext_reset_in]
apply_bd_automation -rule xilinx.com:bd_rule:clkrst -config { Clk {/clk_wiz_0/clk_600 (600 MHz)} Freq {600} Ref_Clk0 {None} Ref_Clk1 {None} Ref_Clk2 {None}}  [get_bd_pins proc_sys_reset_5/slowest_sync_clk]
endgroup
startgroup
connect_bd_net [get_bd_pins clk_wiz_0/locked] [get_bd_pins proc_sys_reset_0/dcm_locked]
connect_bd_net [get_bd_pins clk_wiz_0/locked] [get_bd_pins proc_sys_reset_1/dcm_locked]
connect_bd_net [get_bd_pins clk_wiz_0/locked] [get_bd_pins proc_sys_reset_2/dcm_locked]
connect_bd_net [get_bd_pins clk_wiz_0/locked] [get_bd_pins proc_sys_reset_3/dcm_locked]
connect_bd_net [get_bd_pins clk_wiz_0/locked] [get_bd_pins proc_sys_reset_4/dcm_locked]
connect_bd_net [get_bd_pins clk_wiz_0/locked] [get_bd_pins proc_sys_reset_5/dcm_locked]
endgroup
startgroup
create_bd_cell -type ip -vlnv xilinx.com:ip:axi_intc:4.1 axi_intc_0
endgroup
set_property -dict [list CONFIG.C_IRQ_CONNECTION {1}] [get_bd_cells axi_intc_0]
apply_bd_automation -rule xilinx.com:bd_rule:axi4 -config { Clk_master {Auto} Clk_slave {Auto} Clk_xbar {Auto} Master {/zynq_ultra_ps_e_0/M_AXI_HPM0_LPD} Slave {/axi_intc_0/s_axi} ddr_seg {Auto} intc_ip {New AXI Interconnect} master_apm {0}}  [get_bd_intf_pins axi_intc_0/s_axi]
connect_bd_net [get_bd_pins axi_intc_0/irq] [get_bd_pins zynq_ultra_ps_e_0/pl_ps_irq0]
regenerate_bd_layout
set_property PFM.AXI_PORT {M_AXI_HPM0_FPD {memport "M_AXI_GP" sptag "" memory "" is_range "false"} M_AXI_HPM1_FPD {memport "M_AXI_GP" sptag "" memory "" is_range "false"} S_AXI_HPC0_FPD {memport "S_AXI_HP" sptag "HPC0" memory "" is_range "false"} S_AXI_HPC1_FPD {memport "S_AXI_HP" sptag "HPC1" memory "" is_range "false"} S_AXI_HP0_FPD {memport "S_AXI_HP" sptag "HP0" memory "" is_range "false"} S_AXI_HP1_FPD {memport "S_AXI_HP" sptag "HP1" memory "" is_range "false"} S_AXI_HP2_FPD {memport "S_AXI_HP" sptag "HP2" memory "" is_range "false"} S_AXI_HP3_FPD {memport "S_AXI_HP" sptag "HP3" memory "" is_range "false"}} [get_bd_cells /zynq_ultra_ps_e_0]
set_property PFM.CLOCK {clk_100 {id "0" is_default "false" proc_sys_reset "/proc_sys_reset_0" status "fixed" freq_hz "100000000"} clk_150 {id "1" is_default "true" proc_sys_reset "/proc_sys_reset_1" status "fixed" freq_hz "150000000"} clk_200 {id "2" is_default "false" proc_sys_reset "/proc_sys_reset_2" status "fixed" freq_hz "200000000"} clk_300 {id "3" is_default "false" proc_sys_reset "/proc_sys_reset_3" status "fixed" freq_hz "300000000"} clk_400 {id "4" is_default "false" proc_sys_reset "/proc_sys_reset_4" status "fixed" freq_hz "400000000"} clk_600 {id "5" is_default "false" proc_sys_reset "/proc_sys_reset_5" status "fixed" freq_hz "600000000"}} [get_bd_cells /clk_wiz_0]
set_property PFM.IRQ {intr { id 0 range 32 }} [get_bd_cells /axi_intc_0]
set_property platform.version {1.0} [current_project]
set_property platform.vendor {fpgainfo} [current_project]
set_property platform.board_id {kv260} [current_project]
set_property platform.name {kv260_custom} [current_project]
set_property pfm_name {fpgainfo:kv260:kv260_custom:1.0} [get_files -all {system.bd}]
validate_bd_design
make_wrapper -files [get_files ./vivado/vivado.srcs/sources_1/bd/system/system.bd] -top
add_files -norecurse ./vivado/vivado.gen/sources_1/bd/system/hdl/system_wrapper.v
launch_runs impl_1 -to_step write_bitstream -jobs 2
wait_on_run impl_1
set_property pfm_name {fpgainfo:kv260:kv260_custom:1.0} [get_files -all {./vivado/vivado.srcs/sources_1/bd/system/system.bd}]
set_property platform.extensible {true} [current_project]
set_property platform.description {kv260 platform for AIEdge Contest} [current_project]
set_property platform.design_intent.embedded {true} [current_project]
set_property platform.design_intent.datacenter {false} [current_project]
set_property platform.design_intent.server_managed {false} [current_project]
set_property platform.design_intent.external_host {false} [current_project]
set_property platform.default_output_type {sd_card} [current_project]
set_property platform.uses_pr {false} [current_project]
write_hw_platform -hw -include_bit -force -file ./vivado/system_wrapper.xsa
exit 
```

</details>

1.4　スクリプトファイルを実行します。これによりVivadoで必要な作業が全て終わります。最終的に必要なファイルは XSAファイルです。実行が終了するまでに、数分から数10分かかります。

``` source:make_vivado.sh
source make_vivado.sh
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/700199e0-afbc-00ca-0f89-af8c5be32425.png)

1.5 実行が終わると自動的にVivadoが終了します。

1.6 vivadoというディレクトリが作成され、その中のsystem_wapper.xsaというファイルが必要なファイルになります。

FPGAのツールになれている方は、ここでカスタマイズすることができます。より良い結果を出したい方はカスタマイズして構いません。

# SETP2　デバイスツリーを作る。
デバイスツリーとは 組み込み Linuxに対してハードウェアの情報を持っているファイル群です。今回のkv260のように、FPGAの場合はハードウェアの状態が異なることが多々あります。ハードウェアの情報を Linux のシステムに使うために使用しています。段階としては、Vitisで、デバイスツリーのソースファイルを作り、その後コマンドで、デバイスツリーのコンパイルをいたします。ここでの目的のファイルは、デバイスツリーのバイナリーファイルになります。

2.1 Vitisを立ち上げます。

```
vitis
```

2.2 Vitisのワークスペースを決めます。今回は、AIEDGEの下にVitisとしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/be73d108-03c2-2f8b-0873-56d6638b6c50.png)


2.3 Vitisで使うための準備をします。事前準備したデバイスツリーのダウンロード先を指定します。Vitisのメニューから、Xilinx → Software Repositoriesを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/288b7857-c2ec-52ff-b1ac-cd71ce479690.png)

2.4 Local Repositories の Newをクリックして、デバイスツリーのフォルダの登録です。ダウンロードしたデバイスツリーのフォルダを指定します。device-tree-xlnx になります。決まりましたら、Apply and Closeをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/bea56be2-9b97-89bf-4d0c-09a4b283e38b.png)

2.5 実際にデバイスツリーを作成します。VitisのメニューからXilinx→Generate Device Treeを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/30ac16ba-a411-1382-1b85-ab68502a1c91.png)

2.6 デバイスツリーを作るために必要なことになるファイルと、出力ディレクトリを指定します。Hardwre Specification File には、ステップ１のVivadoで作りました、system_wrapper.xsaファイルを指定します。出力先はOutput Directoryで指定します。今回はdtというディレクトリは新たに作りまして、そこに入れました。オプションの設定をしたいので、Modeify DeviceTree Settingをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/00c8419d-9b07-3fe3-e4b4-d1bc2094433d.png)

2.7 デバイスツリーのオプションを設定します。今回はkv260でアクセラレータを作るために、overlayの設定と zoclと言うドライバーをあらかじめ組み込んでおきます。device_treeをクリック後、dt_overlayの隣の欄をtrueに変更、dt_zoclの隣の欄も trueに変更してください。その後 OK です。
元のダイアログに戻りましたら、Gerareteをクリックします。数秒後、デバイスツリーが作成されたとダイアログボックスが出ますので、OKをクリックします。ターミナルで出来ているファイルを確認します。今回はtreeコマンドを使いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/659cedbf-dfba-8d59-845f-8a268b8c175d.png)


```
tadaaki@tadaaki-AERO-15-YB:~/AIEDGE$ tree ./dt -L 2
./dt
├── include
│   └── dt-bindings
├── Makefile
├── pcw.dtsi
├── pl.dtsi
├── system_2.mss
├── system.mss
├── system-top.dts
├── zynqmp-clk-ccf.dtsi
└── zynqmp.dtsi
```

2.8 デバイスツリーをコンパイルします。直接、コマンドで入力してください。最初にプリプロセッサを動かして、include ファイルを解消し、その後デバイスツリーコンパイラーでデバイスツリーのバイナリーファイルを作成します。目的のファイルは./dt/pl.dtbo になります。これは、kv260でアプリケーションを動かすときに使用します。

```sh:dtc
dtc -@ -O dtb -o ./dt/pl.dtbo ./dt/pl.dtsi
```



# STEP3 必要なファイルを集め、Vitisプラットホームを作成する。
今回の目的である Vitisプラットフォームをここで作成します。kv260では、プラットフォームを作るためのファイルが少なくてすみます。

3.1 事前ダウンロードしたZynqMP共通イメージを解凍します。またこの中にsysrootの元になる、sdk.shも入っていますので、それも解凍します。sdkの解凍中に、ディレクトリーの再確認を行いますので、yを入れてあげます。

``` sh:xilinx-zynqmp-common
tar xzvf xilinx-zynqmp-common-v2022.1_04191534.tar.gz
cd xilinx-zynqmp-common-v2022.1
./sdk.sh -d .
```

3.2 必要なディレクトリーを作成します。pfmフォルダを作り、その中、boot,sd_dirを作成します。

```sh:mdkir pfm
cd ~/AIEDGE
mkdir pfm
mkdir pfm/boot
mkdir pfm/sd_dir
```


3.3 新しくプラットフォームを作ります。Vitisを立ち上げてない場合はVitisを起動させてください。2.1で立ち上げています。Create Platform Projectを選択します。メニューから File→Platfrom Project からでも作成できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/4f567778-4476-7d9c-1d93-fefcb32bb8aa.png)

3.4 新しいプラットフォーム名を決めます。今回はkv260_pfmにしました。Linux 向けのプラットフォームになります。Nextをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/4bcf03ef-3cdb-7dfc-92ab-668c13024a7d.png)

3.5 ハードウェア情報を入力します。ステップ１で作成した、XSAファイルを指定します。Operating system はlinuxを選択、Generate boot componentsは、使用しないのでチェックを外します。終わりましたらFinishをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/65f38e5f-ec1e-9c04-c7b7-bb5893733512.png)

3.6 BIFファイルを作成します。このファイルは BOOT.BINファイルを作るために必要になります。BOOT.BINはSD カードに入れてultra96を起動させるためのファイルになります。BIF Fileの右側のGenarete BIF のBroseの右側の三角しるしをクリックするとメニューが出てきますので、Generate BIFを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/fa8bfa17-8779-660a-e195-7068cce8a744.png)

3.7 準備したファイルを指定します。Boot Components Directoryには、pfm/bootを 、FAT32 Parition Directoryには、pfm/sd_dirを指定します。Linux RootfsとSysroot Directoryは指定してもいいのですが、作成されるファイルが大きくなるので、アプリケーションを作るときに指定することにします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/9c15788a-a652-3de1-201b-3ef374b6c459.png)

3.8 ビルドをします。左上メニューの下にハンマーのアイコンがあります。これをクリックします。ビルドが始まります。数十秒で終わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/6188869c-2148-4bb0-4de7-3b9bc623a608.png)


3.9 作成したファイルの確認を行います。export以下のフォルダーがVitisプラットフォームとして作成されました。配布する時はこの部分を配布します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/7d33cb05-cbfb-53c3-23c6-3e6a7f2d7805.png)


# SETP4 テストアプリケーションでkv260を動かす。
実際に作成したVitisプラットホームが、きちんと動作するかの確認を行います。ここではVaddというアプリケーションを作成、動作を確認します。Vaddは、ハードウェアブロックを使って、大量の演算を行うアプリケーションです。ソフトではなくて、ハードウェアで実行します。

4.1 メニューから　File→New→Application Projectを選択します。作り方の説明が出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/d78699e6-5f8d-d902-aa5e-d5fcefdfb750.png)

4.2 プラットホームの選択をします。ステップ３で作成したkv260_pfmを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/3de05066-ee9b-04e1-f5cf-010ac9ce9649.png)

4.3 アプリケーションの名前を決めます。今回はvaddとしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/fc0ca0d9-f36e-d9a5-8600-33648fdfd690.png)

4.4 アプリケーションのセッティングを進めます。sysroot pathを指定します。sysrootはzynqMP共通イメージを解凍したフォルダーから指定します。指定が終わりましたが Next をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/00bb966f-d303-6993-b9aa-32f6bce0305e.png)


4.5 サンプルアプリケーションを選択します。今回はsimple Vector Additionを選択します。今は数が少ないですが、下のボタンの、Vitis IDE ExamplesやVitis IDE Libraryesのボタンから、ファイルをダウンロードするとたくさんのサンプルが用意できます。
時間のあるときに試してみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/da2ebbaf-80fa-e795-6d98-294a2c798704.png)

4.6 ソフトのビルドを行います。まず、TargetをHardwareにします。今回のkv260のプラットフォームでは、ハードウェアしか動作しません。その後左側のvaddを選択します。その後、ハンマーをクリックして、ビルドを行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/328a9c80-4ec4-91ed-432a-7f47a5a7a6f4.png)

4.7
ハードウェアカーネルをビルドします。Vadd_system_hw_link の下の Vadd_system_hw_link.prjを選択してから、上のアイコンのハンマー（ビルド）をクリックします。終了まで、数分から、数十分かかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/ad1af6da-0c6f-6a59-4dc9-a04f57626422.png)

<details><summary>エラーが起きる方へ</summary>


4.7a この部分で、エラーが多く発生しています。ほとんどの原因はメモリー不足によるエラーになります。次のような対策方法がありますので使ってみてください。論理合成の時に CPU の数が多いとメモリも多く使う傾向があります。16 GB や32 GB も平気で使用してきます。その時は 動作するCPU の数を減らしてあげると、使用メモリーが少なくなりうまくいくことがあります。そのぶん処理時間が長くなりますので遅くなる傾向はあります。Krnl_vaddを右クリックして、メニューを出し、Settingsをクリックします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/315e6b11-7650-0d50-ac5c-363998cbf3a4.png)


4.7b binary_container を選択して、V++ command optionに次のオプションを入れます。数字は動かすCPUの数です。Apply and closeでオプションを反映させます。

`--vivado.synth.jobs 2`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/a712cfc7-b12f-4ecd-a4e7-0b7ccf1f4e3d.png)



</details>




##### KRIAにコピーするファイルを集める

4-8 KRIAで動作させるために、次のファイルが必要となります。その内、pl.dtboはSTEP 2で作成されています。binary_container_1.binは、4-7 で作成された、binary_container_1.xclbinをリネームしたものです。shell.jsonはテキストファイルで作る必要があります。

```
# On target board
ls /lib/firmware/xilinx/vadd
pl.dtbo                       #DTB overlay file
binary_container_1.bin        #Acceleration binary container for XRT configuration. Also includes system.bit and metadata that describes the kernels. 
shell.json                    #Description file
```

4-9 shell.json をテキストエディターで作成します。

```shell.json
{
  "shell_type" : "XRT_FLAT",
  "num_slots": "1"
}
```

3-17 KRIAボードにシリアルポート、イーサーネットを接続します。イーサーネットはファイルをコピーするために必要となります。KRIAに電源を入れます。イーサーネットで、パソコンと接続するため、必要に応じて、IPアドレスを設定します。

```
sudo ifconfig eth0 192.168.0.14
```

3-18 送るためのファイルを準備します。
```
mkdir scpfolder
cd scpfolder/
cp ../dt/pl.dtbo .
cp ../vitis/vadd_system_hw_link/Hardware/binary_container_1.xclbin .
mv binary_container_1.xclbin binary_container_1.bin
cp ../kv260_vitis_application/vadd/Hardware/vadd .
```
```
cat shell.json 

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

3-19 scpコマンドを入力して、ファイルをKRIAにコピーします。パソコン側で操作します。途中で、KRIA側のパスワードを聞いてきますので、入力してください。
```

scp pl.dtbo vadd shell.json binary_container_1.bin petalinux@192.168.0.14:/home/petalinux
```

##### KRIA側でのアプリケーション登録

3－20 KRIA側で、ハードウェアを登録します。この時に FPGA のハードウェア情報が動的にロードされます。
```
sudo mkdir /lib/firmware/xilinx/vadd
cd /home/petalinux
sudo cp pl.dtbo binary_container_1.bin shell.json　/lib/firmware/xilinx/vadd/
sudo xmutil listapps
sudo xmutil unloadapp
sudo xmutil loadapp vadd
```

##### KRIA上でアプリケーションを動作させる

3-21 実行ファイルを動かします。./vadd vinary_container_1.binと入力します。実際にテストはうまくいきました。

```
xilinx-kv260-starterkit-20221:~$ chmod +x ./vadd
xilinx-kv260-starterkit-20221:~$ ./vadd binary_container_1.bin 
INFO: Reading binary_container_1.bin
Loading: 'binary_container_1.bin'
Trying to program device[0]: edge
Device[0]: program successful!
TEST PASSED
```
これで、KRIAでハードウェアの確認を行うことができました。


# 参考文献

https://github.com/Xilinx/kria-vitis-platforms

https://github.com/Xilinx/Vitis-Tutorials/tree/2022.1/Vitis_Platform_Creation/Design_Tutorials/02-Edge-AI-ZCU104