KV260にVitis AIを組み込む(AIEDGEコンテスト対応版）

# Vitis AIをKV260に組み込む

KV260は、AI ビジョンスターターキットと言われているくらい、AIにを動かすたの機能を十分満たしています。
ザイリンクス社から、リファレンスデザインは作られているのですが、カスタマイズがやりにくい状態になっています。
ここでは、FPGAボードにAIの機能を取り付けて、実際に動くまでの段取りを述べてみます。

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

# 事前準備
KV260で、AIを動かす上で、準備が必要になります。


Docker　仮想環境になります。Winodwsの方もWSL2で動かすことが出来ます。Dockerは参考記事が多いので、それらをみて、インストールしてください。

https://www.docker.com/

KV260用にVitis プラットフォームが必要です。次のブログで記述していますので、参考にしてください。

https://qiita.com/basaro_k/items/7295b214f80226b28e7a

SDカードイメージが必要になります。AIで動かすためのライブラリーの設定も行っています。

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

Vitis AI　本体のダウンロード

```gti.sh
cd ~/AIEDGE
git clone --recursive https://github.com/Xilinx/Vitis-AI.git
```

https://github.com/Xilinx/Vitis-AI.git

# 作業手順
1. AIのハードウェアブロック（DPU）を組み込みます。
2. Vitis AIで学習済みデータを変換します。
3. Vitisでソフトウェアを作ります。
4. KV260で実機動作します。
5. PaintPointingでの実装の仕方

###### AIのハードウェアブロックを組み込む
Vitis プラットフォームにハードウェアブロックを組み込みます。今回はRISCVとともに組み込むことを目指しています。手順としては、まず、コンパイラーにAIのライブラリーを組み込みます。そして、DPUのライブラリーをダウンロードして、Vitisのプラットフォームに組み込みます。


1.1 SYSROOT にAI用のライブラリーを追加します。すでにAIEDGEのフォルダーの下に共通イメージがあるという設定です。インストール場所によって、export install_pathのディレクトリを変更してください。

```
export install_path=~/AIEDGE/xilinx-zynqmp-common-v2022.1
wget https://www.xilinx.com/bin/public/openDownload?filename=vitis_ai_2022.1-r2.5.0.tar.gz -O vitis_ai_2022.1-r2.5.0.tar.gz
rm -r $install_path/sysroots/cortexa72-cortexa53-xilinx-linux/usr/share/cmake/XRT/
tar -xzvf vitis_ai_2022.1-r2.5.0.tar.gz -C $install_path/sysroots/cortexa72-cortexa53-xilinx-linux/
```

1.2 DPUの本体をダウンロードし、解凍します。これはVitisのライブラリーに組み込むことが出来ます。

```
wget https://www.xilinx.com/bin/public/openDownload?filename=DPUCZDX8G.tar.gz -O DPUCZDX8G.tar.gz
tar -xzvf DPUCZDX8G.tar.gz
```

1.3 Vitisを立ち上げます。適当なワークスペースを用意してください。

```
source /tools/Xilinx/Vitis/2022.1/settings64.sh
vitis
```

1.4 DPUのライブラリーを登録します。VitisのメニューからWindow→Preferencesを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/047c53aa-1026-371c-3b49-c7c01964c838.png)

1.5 Library Repositonを選択後、Addボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/3a6e5ab2-6c0a-2b75-c8bf-6ff0cef3a88a.png)

1.6 DPUの設置項目を入力します。Locationは解凍した場所になります。よろしければ、Apply and Closeをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/cb3d9c6a-a724-a53a-4c63-7c26a10e9bcd.png)

1.7 新しいアプリケーションを作成します。メニューからFIle　→　New　→　Application Project..を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/b5ddd268-6aef-a4ae-312b-db41992d2a3b.png)

1.8 新しいアプリケーションの説明が出てきます。そのまま NEXT を押します。

1.9 プラットフォームを選択します。ここでは、kv260_pfmを選択して、NEXTをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/7f17e26f-c5f0-55be-a04b-5cc1f07fe909.png)

1.10 アプリケーションプロジェクト名を入力します。今回はaiedgeにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/25080a7a-5964-1fea-8d66-240433de2f78.png)

1.11 sysrootを設定します。共通イメージのsysrootの場所を指定します。NEXTをクリックします。
`
/home/******/AIEDGE/xilinx-zynqmp-common-v2022.1/sysroots/cortexa72-cortexa53-xilinx-linux
`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/547870c5-9c08-e1ee-e564-dc666fc4c192.png)

1.12 DPUを選択します。これでカスタマイズできる IP コアを登録することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/bd39c425-3e15-aa0d-6493-0f0c1848067a.png)

1.13 ハードウェア設定を行います。右上の Active build Configration を Hardwarenに変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/1dbc88c2-6b2a-9251-e988-713887163409.png)

1.14 （RISCV追加オプション）AIEDGE参加の方は、RISCVを組み込む必要があると思います。ここで、RISCVを組み込んでしまいます。すでにブログ記事 KV260プラットフォームにRISC-Vを組み込む(AI EDGEコンテスト対応版）で、5のところまで行っていると、RISCVのIPが出来ています。これを組み込みます。まずは、Exploererのaiedge_kernels のSrcを右クリックして、メニューを出し、import Sources をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/a6f1efb7-4690-ff63-4e15-da62db7232a6.png)

1.15 （RISCV追加オプション）From Directoryで、riscvのフォルダーを選択します。その後出てきた、選択のうちriscv.xoを選択します。入力しましたら、Finishです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/e149f4c2-4374-363c-92a7-f1750f0a503d.png)

1.16 （RISCV追加オプション）RISCVをハードウェアアクセラレータとして、登録します。ペンのアイコンをクリック後、ハードウェアファンクションにriscvを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/c1d1c622-58cc-ef4a-ab89-6574b9884f33.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/a8d35602-630e-ab18-b17a-055348330fa2.png)

1.17 IPのカスタマイズをします。デバイスの大きさに合わせて適切な対応をするためです。他のIPの設定もできます。Explorerで、aiedge_system_hw_linkをクリックします。名前を使いやすくすため、aiedgeに変更しました。デバイスの大きさの関係から、DPUCZDX8Gの数を１にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/9820666e-99bf-18a6-96e8-1e93daa34a55.png)

1.18 DPUのカスタマイズをします。dpu_conf.vhを編集します。AIの性能に左右します。必要に応じて、値を変更します。今回は、次のような設定にしました。コメントを除いて、記述しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/9213037f-19be-3327-c4ba-c9e9e69dd397.png)

```dpu_conf.vh
`define B3136 
`define URAM_ENABLE 
//config URAM
`ifdef URAM_ENABLE
    `define def_UBANK_IMG_N          6
    `define def_UBANK_WGT_N          17
    `define def_UBANK_BIAS           1
`elsif URAM_DISABLE
    `define def_UBANK_IMG_N          0
    `define def_UBANK_WGT_N          0
    `define def_UBANK_BIAS           0
`endif
`define DRAM_DISABLE 
//config DRAM
`ifdef DRAM_ENABLE
    `define def_DBANK_IMG_N          1 
    `define def_DBANK_WGT_N          1
    `define def_DBANK_BIAS           1
`elsif DRAM_DISABLE
    `define def_DBANK_IMG_N          0
    `define def_DBANK_WGT_N          0
    `define def_DBANK_BIAS           0
`endif
`define RAM_USAGE_LOW
`define CHANNEL_AUGMENTATION_ENABLE
`define DWCV_ENABLE
`define ALU_PARALLEL_DEFAULT 
`define CONV_RELU_LEAKYRELU_RELU6
`define ALU_RELU_RELU6
`define DSP48_USAGE_HIGH 
`define LOWPOWER_DISABLE
`define MPSOC
```  
1.19　接続部の設定を行います。画面左下の Assitantのなかから、 aiedge_system → aiedge_system_hw_link → Hardware → aiedge を右クリックします。出てきたメニューから Settings..をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/68201229-0e1b-f801-7e07-ad8800daf48d.png)

1.20 コンフィグレーションのセッティングを行います。V++ configuration settings の ...のアイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/0d52f8c2-989b-9f4b-1a74-741fea8c56bb.png)

1.21 DPUのIPは一つしかないので、一個分の設定を行います。なお、ここも性能を左右するところで、他のIPの接続情報も入力することが出来ます。OKを押して、その後Apply and closeをクリックします。

```V++congigurathon.setting
[clock]
freqHz=300000000:DPUCZDX8G_1.aclk
freqHz=600000000:DPUCZDX8G_1.ap_clk_2
[connectivity]
sp=DPUCZDX8G_1.M_AXI_GP0:HPC0
sp=DPUCZDX8G_1.M_AXI_HP0:HP0
sp=DPUCZDX8G_1.M_AXI_HP2:HP1
```

1.22　ビルドを行います。現段階ではハードウェアだけビルドをします。aiedge_system_linkを選択して、上のハンバーアイコンをクリックして、ビルドをします。数十分かかります。なお、パソコンのメモリーが少ない方はエラーになりやすいので、1.20で行った、setting で、V++ command line optionsでCPUの動作数を少なくしたほうが望ましいです。メモリーが１６ギガバイトで、CPU2個くらいです（WSL2の場合）

`--vivado.synth.jobs 2`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/168e202a-047c-15fa-645a-23be7582c474.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/6fac0d9f-3381-56dd-b9bd-51ab6b5ca8b0.png)

1.23 結果を確認します。AssistantのなかにLink Summaryが出てきますので、そこをダブルクリックをします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/983908bf-f84a-5bd0-1596-af24706924d7.png)

1.24 Vitis Analyzerが立ち上がり、各種結果を見ることが出来ます。使用率、バスの接続方法、タイミングなどが見れます。次回改善の情報に割り当てください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/586df7d5-5454-99c9-0248-6a6da5fc33c8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/b8a75d5c-11c0-bd3d-dfa9-46b3a88cb587.png)

1.25 AIエッジコンテストの方は、ここで、結果をエクスポートして、参加の意思を表示することが出来ます。aiedge_system を右クリック後、メニューを出して、Export as Archiveを選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/9c234036-1e29-597b-6670-dabd10def92a.png)


1.26 アーカイブファイルが作成されます。これをVitisのプロジェクトとして、利用可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299213/6b6b1eff-0fa1-0f49-b554-3ee02d551aed.png)



###### Vitis AIでMNISTをコンパイルする。
DPUが動いているかどうかは、簡単なプログラムを使用することで、実行することが出来ます。AIのハローワールドと言われるMNIST（手書き数字の認識）を使って、実際に学習から、KV260で動くAIモデル作成を行っていきます。

2.1 Dockerは、OSごとに使用が異なりますので、必要に応じて利用してください。Dockerが入っているかはコマンドで確認できます。GPUを使える方はGPUのドライバーを入れたあと、Dockerを入れると、GPUが使えるようになります。なお、比較的新しいGPUをお使いの方は、Dockerのホームページにかかれている方法より、GPUメーカなどの提供しているDockerの方が安定して動作します。nvidia-docker2などがそれにあたります。
`docker --version`

2.2 Vitis AI をGithubからダウンロードします。２０２２年９月で、バージョンは２．５になります。

```
 git clone --recursive https://github.com/Xilinx/Vitis-AI.git
```

2.3 Vitis-AIのDockerイメージを用意します。用意する方法は2種類あります。
　　まずCPUで動作させる方は次のコマンドで、ダウンロードします。量が多いので時間がかかります。
　　GPUで動かす方は事前にビルドをする必要があります。スクリプトファイルが用意されています。
　　

CPUの方
```
docker pull xilinx/vitis-ai-cpu:latest  
```

GPUの方
```
cd Vitis-AI
cd docker
./docker_build_gpu.sh
```

2.3 演習データを用意します。メーカーの方で用意されているのを使います。以前のバージョンのデータを使うので、ダウンロードするときにバージョン指定を行います。

```
cd ~/AIEDGE
git clone -b 1.4 https://github.com/Xilinx/Vitis-AI-Tutorials.git
```

2.4 今回はAIの部分をカスタマイズしたので、その情報が必要になります。すでにVitisで作られています。Dockerでも使えるようにコピーをしておきます。

```
cd ~/AIEDGE
cp ./vitis/aiedge_system_hw_link/Hardware/aiedge.build/link/vivado/vpl/prj/prj.gen/sources_1/bd/system/ip/system_DPUCZDX8G_1_0/arch.json .
```

2.5　Vitis AIを起動します。動作できるディレクトリーの影響を考えて、起動するディレクトリーを変更しています。起動したら、エンターキーを６回押して、最後にｙとエンターキーを押せば、Vitis-AIが起動します。GPUの方はvitis-ai-cpuのところをvitis-ai-gpuに変更してください。

```
cd ~/AIEDGE
Vitis-AI/docker_run.sh xilinx/vitis-ai-cpu:latest
```

2.6　今回はAIEDGEコンテストの課題で、PointPainingを使うので、Pytorchで演習を行います。pytorchの演習に移動します。

```
cd Vitis-AI-Tutorials/Design_Tutorials/09-mnist_pyt/files
```

2.7 演習のデータは用意されているので、run_all.shを実行すれば、通常は動作するのですが、今回はAIをカスタマイズしていますので、ひとつひとつコマンドを入力していきます。まずはpytorchの環境に移動します。

```
conda activate vitis-ai-pytorch
```

2.8 環境の設定を行います。
```
export BUILD=./build
export LOG=${BUILD}/logs
mkdir -p ${LOG}
```

2.9　ダウンロード後1回だけですが、次の学習を行う前にトレーニングデータのバグの修正を行います。MNISTデータをダウンロードするのですが、アドレスにミスがあるので、それを取り除きます。また、kv260を追加するために、ターゲットを作成するファイルを変更します。

``` edit.sh
sed -i 40,45d train.py
sed -i "s/'vck190'/'vck190','kv260'/g" target.py
```

2.10 学習を行います。画像データもダウンロードされます。
```
python -u train.py -d ${BUILD} 2>&1 | tee ${LOG}/train.log
```
2.11 FPGAでの計算量を少なくするために量子化を行います。また、続けて、そのテストを行います。

```
python -u quantize.py -d ${BUILD} --quant_mode calib 2>&1 | tee ${LOG}/quant_calib.log
python -u quantize.py -d ${BUILD} --quant_mode test  2>&1 | tee ${LOG}/quant_test.log
```

2.12 KV260で動くモデルを作成します。ここは、カスタマイズした情報が必要なので、arch.jsonを指定して実行します。

```
export ARCH=/workspace/arch.json
export TARGET=kv260
vai_c_xir --xmodel ${BUILD}/quant_model/CNN_int.xmodel --arch $ARCH --net_name CNN_${TARGET} --output_dir  ${BUILD}/compiled_model
```


2.13 kv260で動かすための、ファイルを揃えます。スクリプトが出来ていますので、それを実行します。build/target_kv260に生成されたファイルが出来上がります。後ほど、kv260にコピーして使用します。

```
python -u target.py --target kv260 -d ${BUILD} 2>&1 | tee ${LOG}/target_kv260.log
```

2.14 VItis-AI 終了させます。作成したファイルは残っています。
```
exit
```

###### Vitisでソフトウェアを作ります。
kv260で動かすために、アプリケーションを作成します。
pythonで作成するか、Vitis等を使って、C言語で作成するのですが、今回はすでにPython作られています。
内容を確認したい方は、次のファイルを確認してください。

```
gedit ~/AIEDGE/Vitis-AI-Tutorials/Design_Tutorials/09-mnist_pyt/files/build/target_kv260/app_mt.py &
```

###### KV260で実機動作します。
作成したファイルをkv260にコピーして、実機で動作させます。作成したのは、DPUを動かすためのハードウェアの部分と、Vitis-AIで動作させた部分になります。

3.1 kv260を動作させます。イーサーネットをパソコンとつながるようにしておきます。
    IPアドレスをifcofng　等で確認しておいてください。もしIPアドレスが設定されてない場合はkv260上で、IPアドレスを設定してください。

IPアドレスの確認
```
ifconfig
```
IPアドレスを設定する場合
```
sudo ifconfig eth0 192.168.0.11
```

3.2 次はパソコン上での作業です。まずはVitisで作成したファイルをひとまとめにします。
sd_aiedgeというフォルダーを作成して、その中に必要なファイルを集めます。必要なファイルは３つです。
aiedge.xclbin pl.dtbo shell.jsonです。
aiedge.xclbinは、ここの１番で作成しました。pl.dtboはプラットフォーム作りのときに作成しています。
shell.jsonは自分で作る必要があります。今回はechoコマンドを使って作成しました。また、同じ内容なのですが、aiedge.xclbinはaiedge.binにコピーして、２重にします。
kv260のOS側では、binファイルを、AIエンジンではXCLBINを使うためです。

``` make_sd_aiedge.sh
mkdir sd_aiedge
cp ./vitis/aiedge_system_hw_link/Hardware/aiedge.xclbin sd_aiedge
cp ./dt/pl.dtbo sd_aiedge
echo '{' > sd_aiedge/shell.json
echo '  "shell_type" : "XRT_FLAT",' >>  sd_aiedge/shell.json
echo '  "num_slots": "1"' >>  sd_aiedge/shell.json
echo '}' >> sd_aiedge/shell.json
cp sd_aiedge/aiedge.xclbin sd_aiedge/aiedge.bin
```

3.3 kv260 にファイルをコピーします。scpコマンドが使えます。IPアドレスはkv260のに合わせておいてください。

``` scp.sh
cd ~/AIEDGE
 scp -r sd_aiedge Vitis-AI-Tutorials/Design_Tutorials/09-mnist_pyt/files/build/target_kv260 petalinux@192.168.0.11:~
```

3.4 kv260上での作業に移ります。まずはハードウェアを動かせるようにkv260に登録をします。
登録はファイルのコピーをすればいいので、それを実行してください。
kv260上での作業です。

```
cd ~/sd_aiedge
sudo mkdir /lib/firmware/xilinx/aiedge
sudo cp * /lib/firmware/xilinx/aiedge
```

3.5 kv260でAIを使えるように、ファイルの書き換えを行います。/etc/vart.conf にその内容が書いてありますので、それを変更します。

```
echo 'firmware: /lib/firmware/xilinx/aiedge/aiedge.xclbin' > vart.conf
sudo cp -f vart.conf /etc/
```

3.6 aiedge のDPUが動くように、FPGA部分を切り替えます。

```
sudo xmutil listapps
sudo xmutil unloadapp
sudo xmutil loadapp aiedge
```

3.7 MNISTを動かします。Pythonですでにアプリは用意されていますので、

```
cd ~/target_kv260
python3 app_mt.py --model=CNN_kv260.xmodel
```
実行結果です。
```
xilinx-k26-starterkit-20221:~/target_kv260$ python3 app_mt.py --model=CNN_kv260.xmodel
Command line options:
 --image_dir :  images
 --threads   :  1
 --model     :  CNN_kv260.xmodel
-------------------------------
Pre-processing 10000 images...
-------------------------------
Starting 1 threads...
Sep 25 05:23:54 xilinx-k26-starterkit-20221 kernel: [drm] ERT_EXEC_WRITE is obsoleted, use ERT_START_KEY_VAL
-------------------------------
Throughput=4022.37 fps, total frames = 10000, time=2.4861 seconds
Correct:9882, Wrong:118, Accuracy:0.9882
-------------------------------
```

ここまで動作すれば、FPGA部分には問題がありません。あとは学習モデルとアプリケーション次第で、どのようなAIも動作することが出来ます。

###### PaintPointingでの実装の仕方
今回のAIEDGEコンテストでは、PaintPointgを使用します。ザイリンクス社では、すでに学習済みのモデルを用意していますので、それを利用して、実装することも可能です。

https://github.com/Xilinx/Vitis-AI/tree/master/model_zoo


# 参考資料

https://github.com/Xilinx/Vitis-AI.git

https://github.com/Xilinx/Vitis-AI-Tutorials