Vivadoでハードウェア情報をエクスポートするTclスクリプト

# はじめに

Vivado SDK で Vivado で作ったFPGAのプログラムを開発するためには、Vivado から Vivado SDK にハードウェア情報をエクスポートする必要があります。
Vivado の GUI では
 
```
File > Export > Export Hardware
```

でハードウェア情報をエクスポート出来ますが、いちいち GUI でマウスボタンをポチポチするのは面倒です。
Vivado は Tcl スクリプトでバッチ処理が出来るので、決まり切った仕事なら Tcl スクリプトを書いて処理させたほうが楽です。
この記事では、Vivadoでハードウェア情報をエクスポートするTclスクリプトを解説します。

# 環境

 - Xilinx Vivado 2015.4
 - Xilinx Vivado 2016.4
 - Xilinx Vivado 2017.1
 - Xilinx Vivado 2017.2
 - Xilinx Vivado 2018.3
 - Xilinx Vivado 2019.1
 - Xilinx Vivado 2019.2 (Vitis)

# Tclスクリプトの説明

## 1 プロジェクトを開く

このスクリプトではすでにプロジェクトが作られていて、配置配線まで完了していることを前提にしています。
変数 project_name にプロジェクト名を、変数 project_directory にプロジェクトのあるディレクトリを設定しておきます。
この例では、project_name に "project" を、project_directory にTclスクリプトのあるディレクトリを指定しています。
project_directory をカレントディレクトリにしておいた方が、間違いがなくて良いでしょう。

````Tcl:export_hardware.tcl
set project_directory   [file dirname [info script]]
set project_name        "project"

cd $project_directory
open_project [file join $project_directory $project_name]
````

## 2 ハードウェア情報を出力するディレクトリを作る(もし無ければ)

変数 sdk_workspace に ハードウェア情報を出力するディレクトリを設定します。
通常、Vivado から Vivado SDK を実行する場合はプロジェクト名.sdk と言う名前のワークスペースが使われるので、ここではそのワークスペースにハードウェア情報を出力しています。

````Tcl:export_hardware.tcl
set     sdk_workspace       [file join $project_directory $project_name.sdk]

if { [file exists $sdk_workspace] == 0 } {
    file mkdir $sdk_workspace
}
````

## 3 ハードウェア情報をエクスポートする

### 3.1 Vivado 2019.1 以前

変数 design_top_name に Vivado のプロジェクトで設定したトップ階層のモジュール名を設定します。Design Runs impl_1 で生成したハードウェア情報を 2で指定したワークスペースに名前を変えてコピーします。Vivado 2019.1 以前の場合、Design Runs impl_1 で生成したハードウェア情報のファイル名は ```$design_top_name.sysdef``` です。ワークスペースにコピーするときに拡張子を .hdf に変更します。

````Tcl:export_hardware.tcl
set design_top_name [get_property "top" [current_fileset]]

file copy -force [file join $project_directory $project_name.runs "impl_1" $design_top_name.sysdef] [file join $sdk_workspace $design_top_name.hdf]
````

### 3.2 Vivado 2019.2 (Vitis) 以降

変数 design_top_name に Vivado のプロジェクトで設定したトップ階層のモジュール名を設定します。Vivado 2019.2 の write_hw_platform コマンドを使ってワークスペースにハードウェア情報ファイル ```$design_top_name.xsa``` をエクスポートします。下の例では、BitStream ファイルを含めるために write_hw_platform コマンドに -include_bit オプションをつけています。

````Tcl:export_hardware.tcl
set design_top_name [get_property "top" [current_fileset]]

write_hw_platform -fixed -force -include_bit -file [file join $sdk_workspace $design_top_name.xsa]
````

## 6 プロジェクトを閉じる

````Tcl:export_hardware.tcl
close_project
````

# Tclスクリプトの実行

## Vivado のバッチモードで実行する

Tclスクリプトを Vivado のバッチモードで実行する場合は次のようにします。

````
shell% vivado -mode batch -source implementation.tcl
````

## Vivado の GUIモードから実行する

Tclスクリプトを Vivado のGUIモードから動かす場合は次のようにします。

````
Vivado > Tools > Run Tcl Script... > implementation.tcl
````

# Tclスクリプトサンプル

### Vivado 2019.1 以前

````Tcl:export_hardware.tcl
set project_directory   [file dirname [info script]]
set project_name        "project"
set sdk_workspace       [file join $project_directory $project_name.sdk]

cd $project_directory
open_project [file join $project_directory $project_name]

if { [file exists $sdk_workspace] == 0 } {
    file mkdir $sdk_workspace
}

set design_top_name     [get_property "top" [current_fileset]]

file copy -force [file join $project_directory $project_name.runs "impl_1" $design_top_name.sysdef] [file join $sdk_workspace $design_top_name.hdf]

close_project
````

### Vivado 2019.2 (Vitis) 以降

````Tcl:export_hardware.tcl
set project_directory   [file dirname [info script]]
set project_name        "project"
set sdk_workspace       [file join $project_directory $project_name.sdk]

cd $project_directory
open_project [file join $project_directory $project_name]

if { [file exists $sdk_workspace] == 0 } {
    file mkdir $sdk_workspace
}

set design_top_name     [get_property "top" [current_fileset]]

write_hw_platform -fixed -force -include_bit -file [file join $sdk_workspace $design_top_name.xsa]

close_project
````

# 参考

- [「VivadoをGUIを使わずに実行するためのTclスクリプト達」@Qiita](http://qiita.com/ikwzm/items/a0120079d2f7f86a5904)