VivadoとXilinx SDKとHLSのバックアップやバージョン管理

# 困りごと

Vivadoプロジェクトって気がつくと数100MBになっている事がしばしばありまして、
その大半が自動生成されるバイナリファイルだったりします。

いちいち大量の自動生成ファイルが書き換わるので、バージョン管理ツールに突っ込もうとすると困りますし、
プロジェクト容量があまりにもでかいので、ただ単にバックアップをとるのすらに困ります。

まあ所詮は数100MB程度なので丸ごとバックアップでもいいんですが、
配布や管理には困るので、Xilinx推奨の方法だったり先人の知恵を調べて確かめておきました。


# 方針

実のところVivadoのプロジェクトは自分で書いたHDLコードを除いてスクリプトによる自動生成が可能です。
なのでスクリプトさえ作って、なおかつプロジェクトフォルダ以下に管理対象になるものを入れ込まなければ、
一時ファイルだらけでやたらと嵩張るプロジェクトフォルダをいつでもゴミ箱に突っ込むことが出来ます。



## プロジェクト再構成Tclスクリプト

`Write Project to tcl`機能を使い、`Recreate Block Designs using Tcl`にチェックを入れてOKを押すと、それだけでプロジェクトとブロックデザイン生成用のスクリプトファイルが作れます。

これでプロジェクトとブロックデザインとそこで使うIPのカスタマイズ情報(`*.xci`)は再生成できるので、後は自分で書いたHDLと制約ファイル、自作IP定義を管理対象化に置けばそれで終わりです。

実際、作成したTCLファイルの冒頭に書かれたコメントを要約するとこんなことが書かれています:

> このスクリプトにはこのスクリプトが生成されたときのプロジェクトの状態を再生成するためのVivado Tcl コマンドが書かれているよ、
> 再生成するときはこのスクリプトをVivado Tcl シェルで読んでね。
> バージョン管理目的で使う場合は次のファイルを一緒に管理してね:
> 1. このスクリプト
> 2. ローカル(プロジェクトフォルダ内)のソースファイル
> 3. インポートされたソースファイル

### スクリプト生成時と再生成時でIP定義が異なる場合

* IPのRevが変わった場合

特に何もなく再生成できます。
TclスクリプトにRevは指定がないのでそもそもRevは見てないのでしょう。


* IPのバージョンが変わった場合/IPが見つからない場合

IPが見つからないと文句を言われてプロジェクトが中途半端に生成されて終わります。

自作IPは気をつけていればまだ大丈夫ですが、
XilinxのIPはVivadoのバージョンアップで一緒にバージョン変わったりするので
古いプロジェクトを再構成しようとしたり、他人に配布しようとしたときに困ります。

IPのバージョンが一致しない場合には、

* Tclスクリプトのバージョン表記を書き換えてしまうか、
* 何が何でもVivadoバージョンを合わせるか、
* Manage IP プロジェクトで使うIPを持っておくか、
* ブロックデザインもプロジェクトから出して、合成されたIPとブロックデザインを管理対象にまるごと含める
とこれが回避できます。

(ブロックデザイン再生成スクリプトというのも存在しますが、これはVivadoのバージョンが違うとエラーになるようになっています。)

なお、[アナログ・デバイセズ社のGithubリポジトリ](https://github.com/analogdevicesinc/hdl)をみると、
プロジェクトで使われているIP名からインストールされているIPのバージョンを探して再構成するようなTclスクリプトを独自で書いているので
Vivadoのバージョンが違っていても問題なく再構成できるようになってます。Xilinxは見習ってほしいですね。

ちなみに`write_project_tcl`コマンドの実装はおそらく
`/Xilinx/Vivado/20XX.X/data/XilinxTclStore/tclapp/xilinx/projutils/write_project_tcl.tcl`
にあるので、これをカスタマイズすればこのあたりを解決したコマンドを自作できるはず





## 実際にやってみる

### Vivado本体

`File > Project > Write Tcl`でプロジェクト再構成用のTclスクリプトを作ります。
`Recreate Block Designs using Tcl`にチェックを入れましょう。

Tclスクリプトの保存先とプロジェクトの相対パスが保存されるので保存先には注意しましょう。
例えば
`/A/B/C/hoge.xpr`というプロジェクトで`/A/hoge.tcl`を保存した場合、
このスクリプトを実行すると
`hoge.tclの実行時のカレントディレクトリ/B/C/hoge.xpr`というふうにプロジェクトが生成されます。

なので実行前にディレクトリを`cd`コマンドで移るのを忘れると
自作IPやソースファイルとの相対パスが崩れたり、
全然意図しないところ(`.Appdata/local/xilinx/vivado`とか)にプロジェクトが作られたりします。しました。それで結構悩みました。

また、何かしらエラーがあった場合には、**黙って**空のTclスクリプトを生成することがあります。ありました。それで結構悩みました。
(例えばIPの参照が解決できなかったりした場合)

再構成する場合は作成したtclがあるところまで`cd`コマンドで移動して、
`Tool > Run Tcl Script`でスクリプトを起動します。



また、ブロックデザインのラッパーは`Create HDL Wrapper`で作ると
問答無用でプロジェクトフォルダ(の中に作られているであろうブロックデザインのフォルダ)に突っ込まれます
なので、扱いとしては

* `Create HDL Wrapper`はするが、ファイルを移動して管理する。
* ブロックデザインをプロジェクト外に出してラッパーを管理する。
* 特例としてラッパーファイルだけは管理する。
* `View instantiation Template`をコピーしてラッパーを自分で作る。

のどれかになります。

ファイルを移動する方法だと`Let Vivado manage wrapper and auto-update`が効かなくなりますし、
ブロックデザインをを外出しすると諸々をgitignoreにいろいろ追加することになります。

なるべく管理は簡単にしつつ、プロジェクトフォルダは何も考えずに削除できるようにしたいので、
`View instantiation Template`をコピーしてラッパーを自分で作るのが今の所おすすめです。


プロジェクトフォルダを何も考えずに削除できるようにするために、
とにかくプロジェクトフォルダに管理対象ファイルを含めないように注意します。

Tclファイルのヘッダーの項目2に書かれているローカル参照しているファイルが1つも無ければ、
とりあえずプロジェクトは再生成できます。さもなくば生成途中で止まります。

用心するならコミットの度に再生成が可能か確かめるといいです。


# HLS

HLSで管理が必要なのは、ソリューションフォルダ内に自動で作られる
`script.tcl`, `directive.tcl`
と自分で書いたソースファイル(*.c, *.cpp, *.h etc)です。

HLSプロジェクトを再構成するときは
`Vivado HLS 20XX.X Command Prompt`を起動して、
`niceHlsPrj`の1つ上の階層から`script.tcl`を走らせるとプロジェクトが再構成されます。

```
vivado_hls -f ./(プロジェクト名)/(solution名)/script.tcl
```
スクリプト生成時点で合成やシミュレーションをやっていればこれらも走ります。


# SDK

「Vivadoプロジェクト内に管理対象を入れない」という方針なので、
当たり前ですがSDKプロジェクトはVivadoプロジェクトの外に作ります。
気を抜くとVivadoはVivadoプロジェクト内になんでも作りやがるので注意してください。

さて、他に比べてSDKはGit管理で考えるべきことが少ないです。
というのもSDKはGitリポジトリ作成機能を持っています。

プロジェクトエクスプローラでプロジェクトを右クリックして
`Team > Share project`で作れます。
プロジェクト全体をGit管理下に置くので
`Use or create repository in parent folder of project`にチェックを入れます。

次にリポジトリの場所を指定します。ワークスペースフォルダ以下に置こうとすると難色を示してくるので、
ワークスペースの1つ上の階層を指定します。

なので、SDKプロジェクトを作るときは

```
プロジェクトルート
    .git
    SDKワークスペースフォルダ
```

という構成にすると良いです。

## 追記

と思ったらEclipse標準だと管理しづらさがマックスだったため
Vivadoプロジェクト同様にスクリプトとソースファイル管理になりそう。(ただしスクリプトは手打ち)

とはいえHDFはVivadoで生成、BSPも自動生成なので
プロジェクト設定をやり直すと割り切るならもはやソースコードだけでいい。

[ADIのベアメタルアプリケーション向けリポジトリ](https://github.com/analogdevicesinc/no-OS)
[XSCTコマンド](https://www.xilinx.com/html_docs/xilinx2019_1/SDK_Doc/xsct/intro/xsct_install_launch.html)
[フォーラム](https://forums.xilinx.com/t5/Embedded-Development-Tools/Which-files-and-folders-of-an-sdk-project-should-be-checked-into/td-p/1000467)

# まとめ

* Vivadoのプロジェクトフォルダは完全に一時ファイル置き場にして、ソースコードなど管理対象を入れない。
    * 気を抜くとプロジェクトフォルダ内にいろいろ作ろうとするので保存先には常に気をつける
* Vivadoプロジェクトとブロックデザインは`Write Project to Tcl`で作ったTclファイルで管理する。
* IPプロジェクトも同様にTclファイルで管理する。
* SDKはGitリポジトリ作成機能が統合されているので`Use or create repository in parent folder of project`にチェック入れて生成


普通のソフトウェア開発と比べると全然気軽さは無いですが、これで一応バージョン管理できます。


とりあえず考えたディレクトリ構成がこちらです:

```
HLx
    .git
    メインとなるプロジェクト(一時ファイル置き場)
    HDL(メインプロジェクトで使うHDLソース)
    ip_repo(自作IP用, HLS含む)
SDK
    .git
    SDKのワークスペース
```

この方法もいろいろ穴があると思うので、何かあれば都度塞いでください。


あと、私はこうやるよってだけなので、この方法で復元不可能になっても責任は負いません
必ずご自身の環境で復元ができるかどうかを確かめてください。

# 参考

[Vivado でのリビジョン管理の使用 (英語版)](https://japan.xilinx.com/video/hardware/vivado-design-suite-revision-control.html)
[Vivado Design Suite Tutorial - Revision Control Systems](https://www.xilinx.com/support/documentation/sw_manuals/xilinx2016_1/ug1198-vivado-revision-control-tutorial.pdf)
[Using Xilinx SDK - working with Git](https://www.xilinx.com/html_docs/xilinx2018_3/SDK_Doc/SDK_tasks/sdk_working_with_git.html)

# (追記)プロジェクト再構成スクリプトを生成しつつその中身を書き換えてさらに管理しやすくするスクリプト

[FPGA meets DevOps - Xilinx Vivado and Git ](https://github.com/starwaredesign/vivado-project-template/blob/master/scripts/create_project_tcl.tcl)

ブロックデザインも外出しするタイプ。
プロジェクトファイル生成スクリプトにブロックデザインのラッパー生成スクリプトを挿入してさらに手間を省いている