Vitis HLS 2021.1 で Vitis Vision Library 2021.1 をセットアップする方法

# このページの目的
Vitis HLS に [Vitis Vision Library](https://xilinx.github.io/Vitis_Libraries/vision/) を導入し、サンプルデザインを実行するまでのセットアップについて解説していきます。

実は、セットアップ方法については以下の公式ページ

* [Vitis Vision Libraryのgithub](https://github.com/Xilinx/Vitis_Libraries/blob/master/vision/docs/getting-started-with-hls.rst)
* [Vitis Vision Libraryの公式ページ](https://xilinx.github.io/Vitis_Libraries/vision/2021.1/overview.html)

で説明がなされています・・・が、この説明の通りに作業をしてもほとんどの場合何らかのエラーが発生し、まともに動かないはずです。
そこで、本ページでは導入の流れと起こりうるエラーと解決法について特に力を入れて解説していきたいと思います。

> なお、この記事は大学の研究室内wikiに投稿したドキュメントを移植したものです。
> したがって、Xilinx Vitis HLS のライセンス取得等についてはこの記事の対象外です。

## 使用バージョン
各アプリケーションのバージョンは以下の表の通りになっているものとします。なお、「*」の付いているものについては、この後詳しく解説します。

| アプリケーション |     バージョン     |
|:----------------|------------------:|
| Operating system | Ubuntu 20.04.3 LTS |
| gcc/g++-9      |              9.3.0 |
| gcc/g++-7* | 7.5.0 |
| cmake* | 3.21.2 |
| Vitis HLS | 2021.1 |
| Vitis Vision Library | 2021.1 |
| OpenCV | 4.4.0 |

## Vitis Vision Libraryとは?
Vitis Vision Library という言葉は、Xilinx 社が提供してる [Vitis Libraries](https://github.com/Xilinx/Vitis_Libraries) の vision フォルダを指しています。

私は画像処理系を研究している学生なので Vitis Vision Library のみを取り上げますが、 Vitis Libraries では数学・統計・線形代数・画像処理などの複雑な処理を伴うIPを作るためのライブラリが提供されており、FPGAで何かしたいと思う方の役に立つはずです。

なお、 Vitis Vision Library はデバッグ環境に OpenCV を用いる関係上、 Vitis HLS と OpenCV 間でいろいろな不具合が起こる可能性があり、導入が難しい理由となっています。

# インストール編
## 0. 知っておいてほしい "which" コマンドの話
whichコマンドとは、「コマンドのフルパス」を調べるためのコマンドです。

実は、Vivado / Vitis / VitisHLS のインストール時に `<installation path>/Xilinx/Vitis/2021.1/settings64.sh` を実行したことによって環境変数が書き換わっており、 cmake コマンドなどは実行時のパスが変更されている可能性があります。

したがって、"which" コマンドを利用して、「自分は /usr/local/bin/cmake と /Xilinx/Vitis/2021.1/tps/lnx64/cmake-3.3.2/bin/cmake のどちらのcmakeを使っているのか」を意識して作業してください！

なお、PATHを変更することでコマンドの探索順番を変更し、cmakeコマンドが /usr/local/bin/cmake を指すようにできるはずです。

## 1. 複数バージョンのgcc/g++を使い分けられるようにする
**理由**
Vitis HLS は Ubuntu に標準搭載されているgcc/g++-9でビルドしたOpenCVを使うことができないから[^1]

[^1]: Vitis HLS 2021.1は内部でgcc4.6.3とgcc6.2.0を使用しています

**方法**
[How to switch between multiple GCC and G++ compiler versions on Ubuntu 20.04 LTS Focal Fossa](https://linuxconfig.org/how-to-switch-between-multiple-gcc-and-g-compiler-versions-on-ubuntu-20-04-lts-focal-fossa) を参考に、update-alternatives コマンドで gcc/g++-7 と gcc/g++-9 を使い分けられるようにしてください。

## 2. cmakeのバージョンを上げる
**理由**
Ubuntu に標準搭載されている cmake-3.1? では OpenCV をビルドすることができないから

**方法**
[How to upgrade cmake in Ubuntu](https://askubuntu.com/questions/829310/how-to-upgrade-cmake-in-ubuntu) を参考に、cmake のバージョンを上げてください。

なお、apt remove する際は [0. 知っておいてほしいwhichコマンドの話](https://qiita.com/PastaSoba/items/f2a58b42e9d14a914845#0-%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%8A%E3%81%84%E3%81%A6%E3%81%BB%E3%81%97%E3%81%84-which-%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AE%E8%A9%B1) に注意して、**/usr/bin (もしくは /usr/local/bin)の cmake** を消すようにしてください。

## 3. OpenCVをインストールする
**方法**
[docs.opencv.org](https://docs.opencv.org/master/d7/d9f/tutorial_linux_install.html) の *Build core modules* と *Install* セクションを実行して OpenCV をビルド・インストールします。

**注意点**

- Vitis Vision Library 2021.1 では動作確認が Opencv 4.4.0 までされています。したがって、'''Build core modules''' 中のコマンド列を以下の様に変更してください。

```bash:インストールのためのコマンド列
## Install minimal prerequisites (Ubuntu 18.04 as reference)
sudo apt update && sudo apt install -y cmake g++ wget unzip

## Download and unpack sources
# wget -O opencv.zip https://github.com/opencv/opencv/archive/master.zip
wget -O opencv.zip https://github.com/opencv/opencv/archive/refs/tags/4.4.0.zip
unzip opencv.zip

## Create build directory
mkdir -p build && cd build

## Configure
cmake  ../opencv-master

## Build
cmake --build .

```

- ビルド・インストールの際は、[1. 複数バージョンのgcc/g++を使い分けられるようにする](https://qiita.com/PastaSoba/items/f2a58b42e9d14a914845#1-%E8%A4%87%E6%95%B0%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%AEgccg%E3%82%92%E4%BD%BF%E3%81%84%E5%88%86%E3%81%91%E3%82%89%E3%82%8C%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B) を参考にして、**gcc-7を使って** ビルドしてください。また、cmake は [2. cmakeのバージョンを上げる](https://qiita.com/PastaSoba/items/f2a58b42e9d14a914845#2-cmake%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%92%E4%B8%8A%E3%81%92%E3%82%8B) でインストールした **/usr/local/bin/cmake の方の cmake** を使ってください。

:::note warn
Vitis Vision Library のインストールに失敗する原因の大部分は、OpenCVをビルドする gcc のバージョン違いによるものです。
:::

:::note warn
sudo apt install libopencv-dev などの方法でOpenCVをインストールすることは非推奨です。後に使う /lib フォルダや /include フォルダが生成されない恐れがあります。
:::

## 4. Vitis Vision Libraryを導入する
**方法**
[Vitis Vision Library の github リポジトリ](https://github.com/Xilinx/Vitis_Libraries) からお好みの場所に clone もしくはダウンロードしてくれば大丈夫です。

**補足**
シンボリックリンクを張ってしまうと、
> リンク元の /vision/L1 を読み込む → リンク先の /vision/L1 を読み込む → 多重定義されてるよ！

というエラーが発生してしまうのでご注意ください。（1敗）

## 5. libOpenCL.so をインストールする
[Vitis Vision Libraryの公式ページ](https://xilinx.github.io/Vitis_Libraries/vision/2021.1/overview.html#prerequisites) で
> libOpenCL.so must be installed if not present along with the platform.

と書いてあるので、[How to install libOpenCL.so on ubuntu](https://askubuntu.com/questions/796770/how-to-install-libopencl-so-on-ubuntu) を参考にしてインストールしてください。

## 6. 環境変数（LD_LIBRARY_PATH）を設定する
[Vitis Vision Libraryのgithub](https://github.com/Xilinx/Vitis_Libraries/blob/master/vision/docs/getting-started-with-hls.rst) で

> Open a terminal and update the LD_LIBRARY_PATH to point to OpenCV lib folder.

と書いてあるので、~/.bashrc で 環境変数 LD_LIBRARY_PATH を登録してください。

## 7. 後片付け
以上でインストールは完了です。

cmake のパスを Vitis のインストール時に戻したり、update-alternatives コマンドで gcc/g++ のバージョンを gcc/g++-9 に戻したりして後片付けを行いましょう。

# 利用編
とりあえず、[getting-started-with-hls](https://xilinx.github.io/Vitis_Libraries/vision/2020.2/overview.html#getting-started-with-hls) の ***Use the following steps to operate the HLS Standalone Mode using GUI:*** セクションをやってみましょう。

**補足**

- 上記の例では dilation プロジェクトを動かしています。
dilation プロジェクトの accel.cpp ファイルは [4. Vitis Vision Libraryを導入する](https://qiita.com/PastaSoba/items/f2a58b42e9d14a914845#4-vitis-vision-library%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B) で導入した Vitis Libraries の vision/L1/examples/dilation フォルダ内にある xf_dilation_accel.cpp ファイルのことです。

- 途中で `-std=c++0x` と設定する場所がありますが、これではエラーが出ます。`-std=c++14` としてください。
- ここまでのインストールが成功していれば、上記ページで設定すべきパスの場所はこのようになっているはずです。

| パスの名前 | 場所 |
|:-|:-|
| \<path-to-L1-include-directory> | Vitis Libraries の vision/L1/include |
| \<path-to-opencv-include-folder> | /usr/local/include/opencv4 |
| \<path-to-opencv-lib-folder> | /usr/local/lib |

- Vitis HLS のファイル探査機能 [^2] の動作原理は非常に謎です。
具体的にはソースコード編集時はinclude先のファイルにジャンプできている（つまりinclude先が分かっている）のに、ビルド時に「include元のファイルに到達できません」というエラーがしばしば発生します。
これは Vitis HLS のファイル探索と Vitis HLS がビルド時に用いる gcc のファイル探索が別々になっていることが理由だと思います。きちんと -L, -I オプションを設定したり、最悪 Vitis HLS を起動しているディレクトリにファイルを置いたりして、gcc のご機嫌を損ねないようにしましょう。

[^2]: インクルード機能とかリンク機能と言ったほうがいいのかもしれません

# トラブルシューティング編
## ERROR: [HLS 207-812] 'asm/errno.h' file not found: /usr/include/linux/errno.h:1:10
**原因**
/usr/include/asm が存在していない。

**解決策**
やや強引ですが、/usr/include/asm -> /usr/include/asm-generic のシンボリックリンクを張ることで解決できます。

## /usr/local/lib/libopencv_core.so: undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()@GLIBCXX_3.4.26
**原因**
おそらく、[3. OpenCVをインストールする](https://qiita.com/PastaSoba/items/f2a58b42e9d14a914845#3-opencv%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B) の際にgcc/g++-7 を使っていなかったことが原因です。[^3]

[^3]: Vitis HLS が使っているバージョンの gcc にとって未知の命令が現れてしまったという感じなのでしょうか

これは、/usr/local/lib/libopencv_core.so のシンボリックリンクを辿っていくと、OpenCV のビルド・インストール時に作成された /usr/local/lib/libopencv_core.so.4.4.0 等のファイルに行きつくことから分かります。

**解決策**
gcc-7 を使って OpenCV を再ビルド・インストールし、libopencv_core.so のシンボリックリンクを再インストールして作成された libopencv_core.so.4.#.## に張りなおせば解決できます。

## /usr/local/lib/libopencv_imgcodecs.so: undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()@GLIBCXX_3.4.26
**原因と解決策**
上と同じです。gcc-7を使って OpenCV をビルド・インストールし、シンボリックリンクを張りなおせば解決します。