KV260向けにVitisプラットフォームを作成してDPUを動かす その1 (Vitis 2022.1 + Vitis-AI v2.5)

ようやくKV260ボードを手に入れました。
KV260向けには`kv260-smartcam`などのスタートキットのSDイメージを使用することで既にDPUが搭載されたアプリケーションを試すことができます。しかしながら、DPUのコンフィグレーションを変更したり、DPU以外に自作の回路を足すなど色々としたいので、自分でプラットフォームを作ってDPUを搭載することにしました。

# 参考
今回の作業を行うにあたって、たくさんの記事を参考にさせていただきました。ありがとうございます。Vitis2022.1 + KV260向けの記事はいくつか存在し、それぞれ微妙に手順は異なりますが、概ね手順は同じです。本記事の手順も参考記事をベースにしています。
- [KRIA XILINXのSOMボードのVitisプラットフォームの作り方(2022.1 版）](https://qiita.com/basaro_k/items/e83128c265ae86801bbc)
  * こちらの記事では[XILINX　KIRA K26（KV260)　Petalinux2022.1用起動用SDカードイメージの作り方](https://qiita.com/basaro_k/items/15bf24e9c4d631e53add)でBSPから作成したSDイメージを使用しています。
  * こちらの記事では`KRIA向け起動用ブートファイルを作成するには、ハードウェア情報のない状態でファイルを作成する必要があります。`と書かれています。
  * この記事の通りに作業を行うとvaddの動作確認までできましたが、プラットフォームのベースとなるVivadoプロジェクトから生成するプラットフォーム名と、Vitis IDEでプラットフォームをビルドするときに指定するプラットフォーム名（プロジェクト名）を一致させる必要があるので注意です。
- [Kria KV260 and PetaLinux 2022.1: Part 02- Vitis Platform](https://highlevel-synthesis.com/2022/06/13/kria-kv260-and-petalinux-2022-1-part-02-vitis-platform/)
  * こちらの方法ではBSPを使用したpetalinuxプロジェクトから`sdk.sh`生成時に`--get-hw-description`を実行しています。
  * 手順を間違えたのか、この方法で作成したSDイメージはLinux起動中に`Starting Create System Users`で止まってしまいました。
- [KV260 の ブートファームウェアを更新](https://qiita.com/ikwzm/items/4e5e954eabc988bd78d5)

# 環境
- Ubuntu 18.04
- Vitis/Vivado/Petalinux 2022.1
- Vitis-AI v2.5
  * v2.5 tagは[GPU向けDockerイメージのビルドに失敗する](https://github.com/Xilinx/Vitis-AI/issues/914)ため、v2.5より少し進んだコミットID(`469a4`を使用します）
 
各環境のインストール手順は省略します。

# Vitis-AIのClone
色々なところでファイルを使用するので先にCloneしておきます。
```sh
cd <YOUR_WORKING_DIRECTORY>
git clone https://github.com/Xilinx/Vitis-AI
cd Vitis-AI
git checkout 469a4b7bc7b7213d76507c34eeb258580322befd
```

CPUイメージは[dockerhub上にあります](https://hub.docker.com/r/xilinx/vitis-ai/tags)が、GPUイメージはビルドする必要があります。
```
cd docker
./docker_build_gpu.sh #1時間以上はかかります
```

# プラットフォームの作成
## Vivadoベースデザインの作成
[KRIA XILINXのSOMボードのVitisプラットフォームの作り方(2022.1 版）](https://qiita.com/basaro_k/items/e83128c265ae86801bbc#%E3%82%B9%E3%83%86%E3%83%83%E3%83%971-vivado%E3%81%A7%E3%81%AE%E9%96%8B%E7%99%BA)を参考にして作ります。プロジェクト名は`kv260_platform_clk5`としました。
参考記事とはクロックの数が異なりますが、それ以外は同じように作成します。色々な周波数のクロックを使用したいため5種類(100/150/200/300/400)の周波数を`Clocking Wizard`に設定しました。
![Screenshot from 2022-09-20 23-57-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/b5cee486-9c6d-954b-8e66-0672397e450c.png)
- 完成したブロックデザイン
![Screenshot from 2022-09-20 23-56-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/b1bde571-b0df-e3a0-25bc-6905b90d86f4.png)
- プラットフォームのクロック設定
![Screenshot from 2022-09-20 23-57-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/8e69a37d-4ad3-2cdc-7174-c8b039308906.png)
- プラットフォームのAXIポート設定
![Screenshot from 2022-09-20 23-57-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/5638e7ea-5668-2087-e6a4-9fc39cdce0ed.png)

参考記事同様にビットストリームを生成し、`Export Platform`からxsaファイルを生成します。プラットフォーム名をVivadoプロジェクト名と同じく`kv260_platform_clk5`として`kv260_platform_clk5.xsa`ファイルを生成します。

## オーバレイ用pl.dtboファイルの生成

先程の参考記事の[オーバーレイ用デバイスツリーを作成する。](https://qiita.com/basaro_k/items/e83128c265ae86801bbc#%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%AC%E3%82%A4%E7%94%A8%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%83%84%E3%83%AA%E3%83%BC%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)と同じ手順でデバイスツリーオーバレイ用のデバイスツリーを生成します。

```sh
source /tools/Xilinx/Vitis/2022.1/settings64.sh
xsct
createdts -hw <YOUR_VIVADO_PROJECT>/kv260_platform_clk5.xsa -zocl -platform-name mydevice -git-branch xlnx_rel_v2022.1 -overlay -compile -out mydevice
exit
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/mydevice/mydevice/psu_cortexa53_0/device_tree_domain/bsp/pl.dtbo dtg_output
```
生成した`pl.dtbo`は後でKV260に転送します。

## Petalinuxプロジェクトの作成
PetalinuxプロジェクトをBSP(Board support package)から作成します。
（Ultra96のときはBSPなしで1からプロジェクトを作ってもMACHINE_NAMEさえ設定すればなんとかなったのですが今回はうまくいかなかったので大人しくBSPを使うことにしました）

今回は`xilinx-kv260-starterkit-v2022.1-05140151.bsp`を使用します。[xilinx-wiki](
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/1641152513/Kria+K26+SOM#KV260-Starter-Kit)からダウンロードリンクを取得します。

### Petalinuxの更新
アップデートしないと生成したSDイメージはKV260で起動しません。[PetaLinux 2022.1 Kria Update 2](https://support.xilinx.com/s/article/000034197?language=en_US)

```sh
source <YOUR_PETALINUX_INSTALL_PATH>/settings.sh
petalinux-upgrade -u http://petalinux.xilinx.com/sswreleases/rel-v2022/sdkupdate/2022.1_update2/ -p "aarch64" --wget-args "--wait 1 -nH --cut-dirs=4"
```
### プロジェクトの作成

```sh
petalinux-create -t project xilinx-kv260-starterkit-v2022.1-05140151.bsp
cd xilinx-kv260-starterkit-2022.1
```

### XRTの有効化
`petalinux-config -c rootfs`からMenuconfigを起動して設定することもできますがコマンドで作業しました
```
sed -i 's/# CONFIG_xrt is not set/CONFIG_xrt=y/g' project-spec/configs/rootfs_config
```

### プロジェクトへのVitis-AI-Libraryの追加
KV260で動作するPetalinuxシステムではパッケージ管理のdnfが使用可能です。Petalinuxをビルドするときにrootfsのconfigを変更してパッケージを追加しなくても、後からボード上で`dnf install`によってパッケージの追加が可能です。

Vitis-AIを動作させるに当たって必要なライブラリは`packagegroup-petalinux-vitisai`という名前で公開されているのですが、記事執筆現時点で2022.1向けにはパッケージが公開されておらず利用できません：[[Petalinux 2021.1]packagegroup-petalinux-vitisai problem](https://support.xilinx.com/s/question/0D52E00006iHjbZSAS/petalinux-20211packagegrouppetalinuxvitisai-problem?language=ja) 
[Githubではrpmパッケージが公開されている](https://github.com/Xilinx/Vitis-AI/tree/v2.5/setup/mpsoc/2022.1)のですが、パッケージの依存が解決できずボード上でインストールすることはできませんでした。

ということで、Petalinuxビルド時に予めVitis-AI-Libraryを含めることにしました。この手順はVitis-AIのGithubでも公開されています：[To rebuild the system by configuring PetaLinux](https://github.com/Xilinx/Vitis-AI/tree/v2.5/setup/petalinux)

- Vitis-AIレシピファイルのコピー
```sh
cp -r <Vitis-AI Directory>/setup/petalinux/recipes-vitis-ai ./project-spec/meta-user/
```
- rootfsコンフィグの修正
`./project-spec/meta-user/conf/user-rootfsconfig`に下記を追記
```
CONFIG_vitis-ai-library
CONFIG_vitis-ai-library-dev
CONFIG_vitis-ai-library-dbg
```
- vitis-ai-libraryの有効化
`petalinux-config -c rootfs`でmenuconfigを起動して`user packages --->`からvitis-ai-libraryを有効化
![Screenshot from 2022-09-21 00-35-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/e0ccca34-6474-038c-cb03-1191ee29d728.png)
今回はdbgもdevも全部選択しました。（全部は要らなさそう）

### ビルド+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"
```
`petalinux-build`をしていると、`Fetcher failure: Unable to find file`のエラーが出てビルドが失敗することがあります。私の環境では`unset HTTP_PROXY`を実行してからもう一度ビルドするとビルドに成功しました。
参考:[Error when trying to build a PetaLinux project](https://support.xilinx.com/s/question/0D52E00006hphoPSAQ/error-when-trying-to-build-a-petalinux-project?language=ja)

生成された`./images/linux/petalinux-sdimage.wic`がブート可能なSDイメージです。これをetcher等でSDカードに書き込んでKV260の電源を接続し起動します。USBケーブルでPCと接続し、`sudo screen /dev/ttyUSB1 115200`でシリアルコンソールに接続できます。ユーザ名`petalinux`でログインして初回はパスワードを設定します。
有線LANを接続し今後はssh接続でアクセスすることにします。

※KV260のファームウェアを更新しないと私の環境ではブートに失敗しました。下記記事を参考にしてKV260のファームウェアを更新してください。
- [KV260 の ブートファームウェアを更新](https://qiita.com/ikwzm/items/4e5e954eabc988bd78d5)
  * BSPでrecommendになっている`BOOT_xilinx-k26-starterkit-v2022.1-07250622_update2.BIN`に更新しました:[Boot-Firmware-Updates](https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/1641152513/Kria+K26+SOM#Boot-Firmware-Updates)

### sysrootの作成
Vitisでアプリケーションを作成する際はsysrootが必要になるので生成します。先程の工程で追加したVitis-AI-Library込みのsysrootが生成されます。

```sh
petalinux-build --sdk
cd images/linux
./sdk.sh #展開する任意のディレクトリを入力
```


## Vitisプラットフォームの生成
```sh
mkdir <VITIS_PLATFORM_PRJ_DIR>
cd <VITIS_PLATFORM_PRJ_DIR>
vitis -workspace ./
```
参考記事の[Vitisでプラットフォームの作成。](https://qiita.com/basaro_k/items/e83128c265ae86801bbc#vitis%E3%81%A7%E3%83%97%E3%83%A9%E3%83%83%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%81%AE%E4%BD%9C%E6%88%90)と同じ手順で作成します。
ワークスペースの場所は何でも良いですが、プラットフォーム名はベースデザインと同じ名前（今回は`kv260_platform_clk5`）にしてください。（同じにしないと筆者環境では後のDPUを載せる工程で失敗しました）

参考記事同様、`Boot Components Directory, FAT32 Partition Directory`は空のディレクトリを設定、`Sysroot Directory`は空欄のままにしました。
![Screenshot from 2022-09-21 01-00-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/9b2dcf7a-9a86-7592-be25-7957c713c12f.png)
ビルドはすぐに終わります。

`<VITIS_PLATFORM_PRJ_DIR>/<PLATFORM_NAME>/export`にプラットフォームが生成されます。
プラットフォーム情報を確認しておきます。
```sh
platforminfo ./export/kv260_platform_clk5/kv260_platform_clk5.xpfm
```
Vitisインストールディレクトリにコピーしておくと使い勝手がいいのでコピーしておきました。
```sh
cd export
cp -r kv260_platform_clk5 /tools/Xilinx/Vitis/2022.1/platforms/
```

やっとプラットフォームができました。。

# VitisでDPUを搭載したデザインの作成
DPUを搭載したデザインを作成するにはVivadoフローとVitisフローの2種類のフローがXilinxから公開されています。今回はVitisフローを使用します。

Vitis-AI v1.4まではGithubリポジトリ上にIPやフローが公開されていたのですが、なぜかv2.5ではリポジトリ外で公開されています。[Vitis-AI/reference_design](https://github.com/Xilinx/Vitis-AI/tree/v2.5/reference_design)からKV260やUltra96などのMPSoCで使用できるDPU IP`DPUCZDX8G`のIPおよびプロジェクトのテンプレート`DPUCZDX8G.tar.gz`を
ダウンロードして解凍します。
```sh
cp ~/Downloads/DPUCZDX8G.tar.gz <YOUR_WORKING_DIRECTORY>
cd <YOUR_WORKING_DIRECTORY>
tar xvf DPUCZDX8G.tar.gz
```
ここからは[DPU + vadd on Ultra96v2 (Vitis 2020.2)](https://qiita.com/lp6m/items/7bd393c6177a88290b97#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90)とほぼ同じ手順です。

## プロジェクトの作成
Vitisを起動し、`Window->Preferences->Library Repositories`の設定を開き、先程ダウンロードしたDPUCZDX8Gディレクトリを追加します。

```sh
cd <YOUR_DPUPRJ_DIR>
vitis
```

![Screenshot from 2022-09-21 01-28-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/a50c46f5-d128-17a8-ac12-18048c14d5a5.png)

`File->New->Application Project`からプロジェクトを作成します。プロジェクト名は今回は`dpuprj`としました。ベースとなるプラットフォームは先程作成したプラットフォームを選択します。

sysrootに先程`sdk.sh`を実行して展開したsysrootディレクトリの中の`cortexa72-cortexa53-xilinx-linux`ディレクトリを設定します。
![Screenshot from 2022-09-21 01-32-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/30897b3e-1bec-d284-9d32-e0188d7f22ba.png)
テンプレートから`DPU Kernel`を選択して、プロジェクトを作成します。
![Screenshot from 2022-09-21 01-33-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/568a3b9a-9b74-98a9-3338-90227130007f.png)

## dpuコンフィグレーションの変更
Explorerウインドウのdpu_trd_kernelsからsrc->prj->Vitis->dpu_conf.vhを開いてDPUのコンフィグレーションを変更します。

![Screenshot from 2022-09-21 01-35-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/01f6b313-5d7f-d796-38fd-c35c8e175e64.png)

KV260にはB3136を載せることができます。使用するモデルに応じて機能の有効化/無効化を設定することができます。今回は以下のような設定にしました。
<details><summary>dpu_conf.vh</summary>

<div>

```
/*
* Copyright 2019 Xilinx Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

//Setting the arch of DPU, For more details, Please read the PG338 


/*====== Architecture Options ======*/
// |------------------------------------------------------|
// | Support 8 DPU size
// | It relates to model. if change, must update model
// +------------------------------------------------------+
// | `define B512               
// +------------------------------------------------------+
// | `define B800                 
// +------------------------------------------------------+
// | `define B1024                 
// +------------------------------------------------------+
// | `define B1152                 
// +------------------------------------------------------+
// | `define B1600                 
// +------------------------------------------------------+
// | `define B2304                 
// +------------------------------------------------------+
// | `define B3136                 
// +------------------------------------------------------+
// | `define B4096                 
// |------------------------------------------------------|

`define B3136 

// |------------------------------------------------------|
// | If the FPGA has Uram. You can define URAM_EN parameter               
// | if change, Don't need update model
// +------------------------------------------------------+
// | for zcu104 : `define URAM_ENABLE               
// +------------------------------------------------------+
// | for zcu102 : `define URAM_DISABLE                 
// |------------------------------------------------------|

`define URAM_ENABLE 

//config URAM
`ifdef URAM_ENABLE
    `define def_UBANK_IMG_N          5
    `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

// |------------------------------------------------------|
// | You can use DRAM if FPGA has extra LUTs               
// | if change, Don't need update model
// +------------------------------------------------------+
// | Enable DRAM  : `define DRAM_ENABLE               
// +------------------------------------------------------+
// | Disable DRAM : `define DRAM_DISABLE                 
// |------------------------------------------------------|

`define DRAM_ENABLE 

//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

// |------------------------------------------------------|
// | RAM Usage Configuration              
// | It relates to model. if change, must update model
// +------------------------------------------------------+
// | RAM Usage High : `define RAM_USAGE_HIGH               
// +------------------------------------------------------+
// | RAM Usage Low  : `define RAM_USAGE_LOW                 
// |------------------------------------------------------|

`define RAM_USAGE_HIGH

// |------------------------------------------------------|
// | Channel Augmentation Configuration
// | It relates to model. if change, must update model
// +------------------------------------------------------+
// | Enable  : `define CHANNEL_AUGMENTATION_ENABLE              
// +------------------------------------------------------+
// | Disable : `define CHANNEL_AUGMENTATION_DISABLE                
// |------------------------------------------------------|

`define CHANNEL_AUGMENTATION_ENABLE

// |------------------------------------------------------|
// | ALU parallel Configuration
// | It relates to model. if change, must update model
// +------------------------------------------------------+
// | setting 0  : `define ALU_PARALLEL_DEFAULT              
// +------------------------------------------------------+
// | setting 1  : `define ALU_PARALLEL_1                
// |------------------------------------------------------|
// | setting 2  : `define ALU_PARALLEL_2                
// |------------------------------------------------------|
// | setting 3  : `define ALU_PARALLEL_4                
// |------------------------------------------------------|
// | setting 4  : `define ALU_PARALLEL_8                
// |------------------------------------------------------|

`define ALU_PARALLEL_DEFAULT 

// +------------------------------------------------------+
// | CONV RELU Type Configuration
// | It relates to model. if change, must update model
// +------------------------------------------------------+
// | `define CONV_RELU_RELU6
// +------------------------------------------------------+
// | `define CONV_RELU_LEAKYRELU_RELU6
// |------------------------------------------------------|

`define CONV_RELU_LEAKYRELU_RELU6

// +------------------------------------------------------+
// | ALU RELU Type Configuration
// | It relates to model. if change, must update model
// +------------------------------------------------------+
// | `define ALU_RELU_RELU6
// +------------------------------------------------------+
// | `define ALU_RELU_LEAKYRELU_RELU6
// |------------------------------------------------------|

`define ALU_RELU_RELU6

// |------------------------------------------------------|
// | DSP48 Usage Configuration  
// | Use dsp replace of lut in conv operate 
// | if change, Don't need update model
// +------------------------------------------------------+
// | `define DSP48_USAGE_HIGH              
// +------------------------------------------------------+
// | `define DSP48_USAGE_LOW                
// |------------------------------------------------------|

`define DSP48_USAGE_HIGH 

// |------------------------------------------------------|
// | Power Configuration
// | if change, Don't need update model
// +------------------------------------------------------+
// | `define LOWPOWER_ENABLE              
// +------------------------------------------------------+
// | `define LOWPOWER_DISABLE               
// |------------------------------------------------------|

`define LOWPOWER_DISABLE

// |------------------------------------------------------|
// | DEVICE Configuration
// | if change, Don't need update model
// +------------------------------------------------------+
// | `define MPSOC              
// +------------------------------------------------------+
// | `define ZYNQ7000               
// |------------------------------------------------------|

`define MPSOC
```
</div>
</details>

## Hardware Link Configの変更
Explorerから`dpuprj_system_hw_link.prj`を開いてカーネルの個数の設定を変更します。
今回はsoftmaxコアは不要なのでsfm_xrt_topは削除し、DPUCZDX8Gの個数を2個から1個に変更しました。

![Screenshot from 2022-09-21 01-38-58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/2168f546-05fe-367b-27c4-39fe8b383dad.png)

## makefileの生成
この時点でExplorerから`dpuprj_system`を選択し、トンカチアイコンから`Hardware`を選択してHardwareビルドします。
恐らくサブプロジェクトの`dpuprj_kernels`のみビルドに成功し、他は失敗するはずです。（後述するdpu-link.cfgのテンプレートに不要な文字が含まれているため）
ビルド試行によって、makefileが生成されればこの段階では十分です。
以降はVitis IDEは使用しないので閉じても問題ありません。

## クロックとポート設定の変更

`dpuprj_system_hw_link/Hardware/dpu-link.cfg`をテキストエディタで開いて修正します。このファイルはVitis IDEで修正したとしても、ビルド開始をすると自動的にテンプレートからコピーされて上書きされてしまいます。このためこれ以降の作業でVitis IDEからビルドを走らせることはありません。Vitis-AI公式のフローにも
> The gui flow only support default configuration. if want to other configuration, please use commandline flow.

と書かれています。

私の環境ではテンプレートから作成された`dpu-link.cfg`に
```
[# *    http://www]
apache.org/licenses/LICENSE-2.0

[# * Licensed under the Apache License, Version 2]
0 (the "License");
```
という部分が含まれており、cfgの形式として正しくないのでエラーになるのでこの部分を削除しました。

そのうえで、`[clock], [connectivity]`を以下のように設定しました。

```
[clock]
#100, 150, 200, 300, 400
id=2:DPUCZDX8G_1.aclk
id=4:DPUCZDX8G_1.ap_clk_2

[connectivity]
nk=DPUCZDX8G:1:DPUCZDX8G_1
sp=DPUCZDX8G_1.M_AXI_GP0:HPC0
sp=DPUCZDX8G_1.M_AXI_HP0:HP0
sp=DPUCZDX8G_1.M_AXI_HP2:HP1
```
今回使用しているプラットフォームにはid=0から順に`100, 150, 200, 300, 400[MHz]`のクロックが存在するので、上記の設定では`id=2,4`を指定しているのでDPUには200MHzと400MHzのクロックが設定されることになります。

`dpu-link.cfg`の修正後、コマンドラインからmakeを実行します。DPUの搭載されたブロックデザインが自動的に生成され、合成が始まります。
```sh
cd <YOUR_DPUPRJ_DIR>/dpuprj_system_hw_link/Hardware
make
```

自動生成されたブロックデザインをVivadoで確認することもできます。
```
vivado ./dpu.build/link/vivado/vpl/prj/prj.xpr
```
指定したとおりのクロックとポートが設定されていました。
![Screenshot from 2022-09-21 01-54-58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/8c09f466-0f41-5ef2-b25a-7bc502e83025.png)

ビルドにより生成された`dpuprj_system_hw_link/Hardware/dpu.xclbin`ファイルがKV260で使用するファイルになります。
xclbinにはビットストリームだけでなくIPのメモリアドレスの情報なども含まれています。
参考:[FPGAカーネル超入門 (2)](https://valinux.hatenablog.com/entry/20210225#3-xclbin%E3%81%AE%E5%86%85%E5%AE%B9)

これでVitisでDPUを搭載したデザインの作成は完了です。

`dpuprj`にはresnet50を使用したサンプルアプリケーションが含まれています。Vitis-AI Libraryを含んだsysrootも設定しているのでビルドには成功しますが、使用されているxmodelファイル（DPU向けのモデルファイル）は今回使用したDPUのコンフィグレーションと異なるためそのままではアプリは動かないのでアプリケーション自体が不要です。

最後に、DPUのコンフィグレーション情報を表すJSONファイルを使い勝手の良い場所にコピーしておきます。
`vai_c_tensorflow`や`vai_c_pytorch`などのVitis-AIのツールを使ってDNNモデルをDPU向けにコンパイルする際にこのファイルが必要になります。

```
cp ./dpuprj_system_hw_link/Hardware/dpu.build/link/vivado/vpl/prj/prj.gen/sources_1/bd/design_1/ip/design_1_DPUCZDX8G_1_0/arch.json <VITIS_AI_REPO_DIR>/kv260_myarch.json
```

# DPUを含んだデザインのロード確認
KV260上でDPUを含んだFPGAビットストリームの読み込みに成功するかを確認します。

[ビルド+SDイメージの作成、ブート確認](###ビルド+SDイメージの作成、ブート確認)で作成したSDカードを使用してKV260を起動しておきます。

ビットストリームを含むDPUデザインを、KV260上で「アプリケーション」として登録するのに必要なファイルを集めてきます。
```sh
mkdir sd
cp dtg_output/pl.dtbo ./sd/
cp dpuprj/dpuprj_system_hw_link/Hardware/dpu.xclbin ./sd/
touch ./sd/shell.json
```
`shell.json`は以下の内容で作成します。
```
{
    "shell_type" : "XRT_FLAT",
    "num_slots": "1"
}
```
用意したファイルをKV260に転送します。
```
scp -r ./sd petalinux@192.168.xxx.xxx:~/
```

以降はKV260で作業を行います。`/lib/firmware/xilinx/`以下にファイルを格納することでアプリケーションユーティリティ`xmutil`にアプリケーションが認識されます。
```
cd ~/sd
sudo mkdir /lib/firmware/xilinx/dpuprj
sudo cp pl.dtbo shell.json /lib/firmware/xilinx/dpuprj/
sudo cp dpu.xclbin /lib/firmware/xilinx/dpuprj/binary_container_1.bin
```
xclbinに関しては拡張子を`.bin`に変更する必要があるようです。
```
sudo xmutil listapps
sudo xmutil unloadapp #デフォルトのk26-starter-kitsをアンロード
sudo xmutil loadapp dpuprj
```

`Loaded to slot 0`と表示されればビットストリームが書き込めています！

記事が長くなってしまったので、次の記事ではDPUでYOLOv4を動作させてみたいと思います。