##はじめに
Synthesijerで作ったモジュールをMessagePack-RPCで制御する(アーキテクチャ編)の続きです。
今回は、前回作った Accumulator と MessagePack-RPC サーバーを IP にパッケージする手順を説明します。
##開発ツール
- Xilinx社 Vivado 2015.3
##手順1
リポジトリと各submodule をダウンロードします。
shell% git clone git://github.com/ikwzm/msgpack-vhdl-examples.git
shell% cd msgpack-vhdl-examples
shell% git submodule init
shell% git submodule update
shell% cd examples/accumulator/fpga/xilinx/ip
##手順2
最初の難関は、あちこちに分散された VHDL のソースコードをどのようにかき集めるかです。特に、MessagePack for VHDL のソースコードは結構ファイル数が多く、アナライズする順番に制約があります。
msgpack-vhdl-examples.git には、あらかじめ examples/accumulator/fpga/xilinx/ip に MessagePack for VHDL の必要なソースコードのみをアーカイブした msgpack.vhd と、それ以外のファイルを Vivado のプロジェクトに読み込むためのスクリプトファイル add_sources.tcl が用意してあります。これらのファイルを使う場合は、手順3に飛んでください。
ここでは msgpack.vhd と add_souces.tcl を生成する方法を説明します。
まず、次のような yaml ファイルを用意します。
- Library:
Name : msgpack
Archive : msgpack.vhd
PathList :
- "../../../../../msgpack-vhdl/src/msgpack/"
- Library:
Name : work
Print : true
Format : "add_vhdl_file sources_1 #{library_name} #{file_name}"
PathList :
- "../../../src/main/vhdl/"
- "../../../src/main/synthesijer/Accumulator.vhd"
Top : ["Accumulator_Server"]
次に ../../../../../PipeWork/tools/vhdl-archiver.rb を使って、msgpack.vhd と add_sources.tcl を作ります。
shell% ../../../../../PipeWork/tools/vhdl-archiver.rb --config add_sources.yml > add_sources.tcl
このスクリプトにより、../../../../../mstpack-vhdl/src/msgpack から必要なファイルのみを一つのファイル msgpack.vhd にまとめます。
add_sources.tcl は次のような Tcl スクリプトが生成されます。
add_vhdl_file sources_1 WORK ../../../src/main/synthesijer/Accumulator.vhd
add_vhdl_file sources_1 WORK ../../../src/main/vhdl/add_interface.vhd
add_vhdl_file sources_1 WORK ../../../src/main/vhdl/get_interface.vhd
add_vhdl_file sources_1 WORK ../../../src/main/vhdl/set_interface.vhd
add_vhdl_file sources_1 WORK ../../../src/main/vhdl/accumulator_server.vhd
これで、IP に必要なソースファイルが揃いました。
##手順3
Vivado の IP-Packager を起動して IP を作ります。
いちいち GUI でボタンをペチペチやるのは非効率なので、Tclスクリプトを用意しました。
#
# create_ip.tcl Tcl script for create project and generate IP
#
set ip_name "accumulator_server"
set ip_vendor_name "ikwzm"
set ip_library_name "msgpack"
set ip_root_directory [file join [file dirname [info script]] $ip_name]
set project_name "accumulator_server"
set project_directory [file join [file dirname [info script]] "work"]
set device_parts "xc7z010clg400-1"
#
# Create project
#
create_project -force $project_name $project_directory
#
# Set project properties
#
set_property "part" $device_parts [get_projects $project_name]
set_property "default_lib" "xil_defaultlib" [get_projects $project_name]
set_property "simulator_language" "Mixed" [get_projects $project_name]
set_property "target_language" "VHDL" [get_projects $project_name]
#
# Create fileset "sources_1"
#
if {[string equal [get_filesets -quiet sources_1] ""]} {
create_fileset -srcset sources_1
}
#
# Create fileset "constrs_1"
#
if {[string equal [get_filesets -quiet constrs_1] ""]} {
create_fileset -constrset constrs_1
}
#
# Create fileset "sim_1"
#
if {[string equal [get_filesets -quiet sim_1] ""]} {
create_fileset -simset sim_1
}
#
# Create run "synth_1" and set property
#
if {[string equal [get_runs -quiet synth_1] ""]} {
create_run -name synth_1 -part $device_parts -flow "Vivado Synthesis 2014" -strategy "Vivado Synthesis Defaults" -constrset constrs_1
} else {
set_property strategy "Vivado Synthesis Defaults" [get_runs synth_1]
set_property strategy "Flow_PerfOptimized_High" [get_runs synth_1]
}
current_run -synthesis [get_runs synth_1]
#
# Create run "impl_1" and set property
#
if {[string equal [get_runs -quiet impl_1] ""]} {
create_run -name impl_1 -part $device_parts -flow "Vivado Implementation 2014" -strategy "Vivado Implementation Defaults" -constrset constrs_1 -parent_run synth_1
} else {
set_property strategy "Vivado Implementation Defaults" [get_runs impl_1]
set_property strategy "Performance_Explore" [get_runs impl_1]
}
current_run -implementation [get_runs impl_1]
#
# Add files
#
proc add_vhdl_file {fileset library_name file_name} {
set file [file normalize $file_name]
set fileset [get_filesets $fileset ]
set file_obj [import_files -norecurse -fileset $fileset $file]
set_property "file_type" "VHDL" $file_obj
set_property "library" $library_name $file_obj
}
add_vhdl_file sources_1 MsgPack msgpack.vhd
source "add_sources.tcl"
#
# Create IP-Package project
#
ipx::package_project -root_dir $ip_root_directory -vendor $ip_vendor_name -library $ip_library_name -taxonomy /UserIP -generated_files -import_files -force
#
# Infer Bus Interfaces
#
ipx::infer_bus_interfaces xilinx.com:interface:aximm_rtl:1.0 [ipx::current_core]
ipx::infer_bus_interfaces xilinx.com:interface:axis_rtl:1.0 [ipx::current_core]
#
# Set Supported Families
#
set_property supported_families {zynq Production virtex7 Production qvirtex7 Production kintex7 Production kintex7l Production qkintex7 Production qkintex7l Production artix7 Production artix7l Production aartix7 Production qartix7 Production zynq Production qzynq Production azynq Production} [ipx::current_core]
#
# Set Core Version
#
set_property core_revision 1 [ipx::current_core]
#
# Generate files
#
ipx::create_xgui_files [ipx::current_core]
ipx::update_checksums [ipx::current_core]
ipx::save_core [ipx::current_core]
#
# Close and Done.
#
close_project
このスクリプトの肝は
- add_vhdl_file プロシージャで VHDLファイルをライブラリを設定しつつimportしている
- ipx::package_project で IP-Package用のプロジェクトを作成している
- ipx::infer_bus_interfaces で Interface を推定させている
ことです。特に今回の IP では MessagePack の入出力に AXI4-Stream を使っているので Vivado が自動的に Interface を推定して定義してくれるので大変楽です。
この create_ip.tcl を次のように Vivado で実行します。
shell% vivado -mode batch -source create_ip.tcl
または Vivado GUI を起動して、Tools > Run Tcl Script... から create_ip.tcl を選択。
これで ./examples/accumulator/fpga/xilinx/ip/accumulator_server が生成されます。
##参照
MessagePack for VHDL (https://github.com/ikwzm/msgpack-vhdl)
MessagePack for VHDL Examples (https://github.com/ikwzm/msgpack-vhdl-examples)
MessagePack-RPCを使ってFPGAを制御
Synthesijerで作ったモジュールをMessagePack-RPCで制御する(アーキテクチャ編)
Synthesijerで作ったモジュールをMessagePack-RPCで制御する(ZYNQ論理合成編)
Synthesijerで作ったモジュールをMessagePack-RPCで制御する(TTYドライバ編)
Synthesijerで作ったモジュールをMessagePack-RPCで制御する(MessagePack-Ruby編)
Synthesijerで作ったモジュールをMessagePack-RPCで制御する(リモートサーバー編)