目次
デザインのビルド
デザインのビルド
デザインのビルド
このセクションでは、Versal デバイスの DSP58 エンジンを使用した行列乗算デザインのビルドと実行について説明します。デザインをコンパイルしたら大きいシステム デザインに統合します (PS ホスト アプリケーションを含む)。
デザインのビルドに使用される makefile は、コマンド ラインからユーザー入力を 2 つ使用します。これらは、TARGET (hw/hw_emu) と GEMM_SIZE (32、64、128、256、512 または 1024) の 2 つです。
これらの入力に基づいて、デザイン フローでは新しいディレクトリ (build/
) が生成されます。その下に gemm_GEMM_SIZExGEMM_SIZExGEMM_SIZE というサブディレクトリができます。 たとえば、GEMM_SIZE に 64 を指定すると、build ディレクトリの下に gemm_64x64x64 というサブディレクトリが作成されます。その下に、hw_emu/
および hw/
サブフォルダーのいずれか、または両方が作成されます。各フォルダーには、hw
または hw_emu
をそれぞれターゲットとするホスト アプリ実行ファイルおよびビルドが含まれます。hw_emu/
サブフォルダーには、ハードウェア エミュレーション用のビルドが含まれます。hw/
サブフォルダーには、VCK190 ボードで実行するハードウェア用のビルドが含まれます。
make ステップ
make ステップ
次の make
ステップ (たとえば、make kernels
、make xsa
、make application
および make package
) は、gemm_dsp58/
フォルダーから実行する必要があります。make
ステップで指定できるオプションは、次のとおりです。オプションを適用する方法については、このセクションで後述します。
TARGET:
このオプションは hw
または hw_emu
に設定し、それぞれハードウェアまたはハードウェア エミュレーション フローでデザインをビルドできます。デフォルトは hw_emu
です。
GEMM_SIZE:
このオプションは 32、64、128、256、512、または 1024 に設定できます。
Makefile では、次のディレクトリ参照が使用されます。
## Relative directory
RELATIVE_PROJECT_DIR := ./
PROJECT_REPO := $(shell readlink -f $(RELATIVE_PROJECT_DIR))
DESIGN_REPO := $(PROJECT_REPO)/design
PL_SRC_REPO := $(DESIGN_REPO)/pl_src
CONSTRAINTS_REPO := $(PL_SRC_REPO)/constraints
HOST_APP_SRC := $(DESIGN_REPO)/host_app_src
SYSTEM_CONFIGS_REPO := $(DESIGN_REPO)/system_configs
VIVADO_METRICS_SCRIPTS_REPO := $(DESIGN_REPO)/vivado_metrics_scripts
BASE_BLD_DIR := $(PROJECT_REPO)/build_$(PL_FREQ)
GEMM_BLD_DIR := $(BASE_BLD_DIR)/gemm_$(MAT_DIMS)
BUILD_TARGET_DIR := $(GEMM_BLD_DIR)/$(TARGET)
VIVADO_REPORTS_REPO := $(PROJECT_REPO)/vivado_reports_dir
BLD_VIVADO_REPORTS_DIR := $(VIVADO_REPORTS_REPO)/gemm_$(MAT_DIMS)
EMBEDDED_PACKAGE_OUT := $(BUILD_TARGET_DIR)/package
EMBEDDED_EXEC_SCRIPT := run_script.sh
1 つのコマンドを使用したデザイン全体のビルド
1 つのコマンドを使用したデザイン全体のビルド
Vitis カーネル コンパイル フローを理解している場合は、1 つのコマンドでデザイン全体をビルドできます。
make run (default TARGET=hw_emu, GEMM_SIZE=64)
または
make run TARGET=hw (Target is hardware, GEMM_SIZE=64)
このコマンドは、指定した TARGET
に基づいてハードウェア エミュレーション用またはハードウェア (VCK190 ボード) での実行用に、make kernels
、make xsa
、make application
、make package
、および make run_emu
を実行します。設定は、次にリストする個々の make ステップにも適用されます。
生成されたファイルは、個々のディレクトリ $(BUILD_TARGET_DIR)/
の下に配置されます。デザインを構築する各 make
ステップについては、以降のセクションで説明します。また、使用するオプションと、入力および出力ファイルのディレクトリについても説明します。
すべての Vitis コンパイラ オプションの詳細は、こちらのページを参照してください。次の表に、使用するオプションをまとめます。
オプション | 説明 |
---|---|
--target | -t [hw|hw_emu] | ビルド ターゲットを指定します。 |
--platform | -f | サポートされるアクセラレーション プラットフォームの名前を $PLATFORM_REPO_PATHS 環境変数で指定されているように指定するか、XPFM プラットフォーム ファイルへの完全パスを指定します。 |
--save-temps | -s | Vitis コンパイラ コマンドでコンパイルおよびリンク プロセス中に作成された中間ファイル/ディレクトリを保存します。--temp_dir オプションを使用すると、中間ファイルを保存するディレクトリを指定できます。 |
--temp_dir |
ビルド プロセス中に作成された一時ファイルを保存するディレクトリを指定します。--save-temps オプションを指定しておかない場合、一時的な結果は Vitis コンパイラで書き出された後削除されます。 |
--verbose | 詳細/デバッグ情報を表示します。 |
--compile | -c | コンパイルしてカーネル ソース ファイルから XO ファイルを生成するのに必要です。 |
--kernel \<arg>|-k \<arg> | 入力ファイルから指定したカーネルのみをコンパイルします。Vitis コンパイラ コマンドごとに使用できる -k オプションは 1 つだけです。 |
-D | --define \<Macro Name>=\<value> | コンパイラのマクロを定義します。 |
--output | -o | V++ コマンドで生成された出力ファイルの名前を指定します。カーネル出力は XO にする必要があります。 |
このデザインでは、次の RTL ファイルが使用されます。
${PL_SRC_REPO}/rtl/BDELAY.vhd
${PL_SRC_REPO}/rtl/FIXGEMM.vhd
${PL_SRC_REPO}/rtl/SDELAY.vhd
${PL_SRC_REPO}/rtl/sfixed_pkg.vhd
${PL_SRC_REPO}/rtl/cfixed_pkg.vhd
${PL_SRC_REPO}/rtl/DSP_GW.vhd
${PL_SRC_REPO}/rtl/FIXGEMM_WRAPPER.vhd
${PL_SRC_REPO}/rtl/control_logic.sv
${PL_SRC_REPO}/rtl/gemm_top.sv
${PL_SRC_REPO}/rtl/ps_slave.sv
${PL_SRC_REPO}/rtl/DSP_data_controller.sv
${PL_SRC_REPO}/rtl/op_uram.sv
${PL_SRC_REPO}/rtl/row_uram.sv
${PL_SRC_REPO}/rtl/col_uram.sv
${PL_SRC_REPO}/rtl/gemm_large_ocm.sv
${PL_SRC_REPO}/rtl/partial_sum_bram.sv
${PL_SRC_REPO}/rtl/synchronizer.sv
$(CONSTRAINTS_REPO)/gemm_dsp58.tcl は、合成とインプリメンテーション用の制約を提供します。
次の XO ファイルが出力されます。
$(PROJECT_REPO)/build/gemm_GEMM_SIZExGEMM_SIZExGEMM_SIZE/gemm_large_ocm.xo
make kernels: PL カーネルの生成
make kernels: PL カーネルの生成
このステップでは、上記で指定した RTL と mem_init_files を使用して PL カーネル (gemm_large_ocm.xo) が生成されます。
make xsa: Vitis ツールを使用した PL カーネルとプラットフォームとのリンク
make xsa: Vitis ツールを使用した HLS カーネルとプラットフォームとのリンク
カーネルが生成されたら、Vitis コンパイラを使用してプラットフォームとリンクし、XSA ファイルを生成できます。
Vitis ツールを使用すると、カーネルを既存のエクステンシブル プラットフォームに統合できます。これは、ソフトウェア開発者の観点からすると自動化されたステップで、選択したプラットフォームはハードウェア設計者から提供されます。または、AMD が提供している多数のエクステンシブル ベース プラットフォームの中から 1 つを使用することを選択し、Vitis ツールを使用してハードウェア デザインをビルドし、カーネルをそのデザインに統合することもできます。
このステップを実行するコマンドは、次のとおりです。
make xsa TARGET=<hw/hw_emu> GEMM_SIZE=<64,128,256,512,1024>
拡張コマンドは次のとおりです。
cd $(BUILD_TARGET_DIR); \
v++ -l --platform xilinx_vck190_base_202410_1 --save-temps --temp_dir $(BUILD_TARGET_DIR)/_x \
--verbose -g --clock.freqHz 500000000:gemm_large_ocm_0 --clock.defaultTolerance 0.001 \
--config $(SYSTEM_CONFIGS_REPO)/gemm.cfg --vivado.prop fileset.sim_1.xsim.simulate.log_all_signals=true \
--vivado.prop run.synth_1.{STEPS.SYNTH_DESIGN.ARGS.CONTROL_SET_OPT_THRESHOLD}={16} \
--vivado.prop run.synth_1.{STEPS.SYNTH_DESIGN.ARGS.KEEP_EQUIVALENT_REGISTERS}={true} \
--xp vivado_prop:run.impl_1.STEPS.PLACE_DESIGN.TCL.PRE=$(CONSTRAINTS_REPO)/gemm_dsp58.tcl
-t hw_emu -o $(BUILD_TARGET_DIR)/gemm.hw_emu.xclbin $(PROJECT_REPO)/build/gemm_GEMM_SIZExGEMM_SIZExGEMM_SIZE/gemm_large_ocm.xo
Vitis リンク オプションの詳細は、こちらのページを参照してください。次の表に、使用するオプションをまとめます。
オプション | 説明 |
---|---|
--platform | -f | サポートされるアクセラレーション プラットフォームの名前を $PLATFORM_REPO_PATHS 環境変数で指定されているように指定するか、XPFM プラットフォーム ファイルへの完全パスを指定します。 |
--save-temps | -s | V++ コマンドでコンパイルおよびリンク プロセス中に作成された中間ファイル/ディレクトリを保存します。--temp_dir オプションを使用すると、中間ファイルを保存するディレクトリを指定できます。 |
--temp_dir |
ビルド プロセス中に作成された一時ファイルを保存するディレクトリを指定します。--save-temps オプションを指定しておかない場合、一時的な結果は Vitis コンパイラで書き出された後削除されます。 |
--verbose | 詳細/デバッグ情報を表示します。 |
--output | -o | V++ コマンドで生成された出力ファイルの名前を指定します。このデザインでは、XO ファイルに、PL カーネルとインターフェイスする HLS/DSP カーネルの出力が含まれます。 |
--vivado.prop \<arg> | FPGA のバイナリ (xclbin) の合成およびインプリメンテーションに使用する Vivado Design Suite のプロパティを指定します。Vivado オプションの詳細は、こちらのページを参照してください。 |
--profile.data [ |
モニター IP を介してデータ ポートを監視します。このオプションは、リンク時には指定する必要があります。プロファイリング オプションの詳細は、こちらのページを参照してください。 |
--profile.trace_memory \<FIFO>:\<size>|\<MEMORY>[\<n>] | ハードウェア ターゲット (-t=hw) を構築する際に、トレース データを取り込むのに使用するメモリのタイプおよび量を指定できます。プロファイリング オプションの詳細は、こちらのページを参照してください。 |
--config |
V++ オプションを含むコンフィギュレーション ファイルを指定します。 |
PL カーネルを一緒に接続する方法をリンカーに指示するための情報は、コンフィギュレーション ファイル system_configs/gemm.cfg
に記述されます。これは、システムの接続方法全体が記述されたファイルです。
[connectivity]
nk=gemm_large_ocm:1:gemm_large_ocm_0
[clock]
id=0:gemm_large_ocm_0.S_AXI_ACLK
[advanced]
## Disable Profiling in hw_emu so that it is faster...
param=hw_emu.enableProfiling=false
## Export the xsa of the design..
param=compiler.addOutputTypes=hw_export
param=compiler.worstNegativeSlack=-1.0
[vivado]
prop=run.synth_1.STRATEGY=Flow_PerfOptimized_high
prop=run.impl_1.STEPS.OPT_DESIGN.is_enabled=true
prop=run.impl_1.STEPS.OPT_DESIGN.ARGS.DIRECTIVE=Explore
prop=run.impl_1.STEPS.PLACE_DESIGN.ARGS.DIRECTIVE=ExtraTimingOpt
prop=run.impl_1.STEPS.PHYS_OPT_DESIGN.is_enabled=true
prop=run.impl_1.STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE=AggressiveExplore
#prop=run.impl_1.STEPS.ROUTE_DESIGN.ARGS.MORE OPTIONS=-tns_cleanup
prop=run.impl_1.STEPS.ROUTE_DESIGN.ARGS.DIRECTIVE=AggressiveExplore
Vitis コンパイラ コンフィギュレーション ファイルの詳細は、こちらのページを参照してください。次の表に、使用されるコンフィギュレーション オプションを示します。
オプション | 備考 |
---|---|
--connectivity.nk | カーネル数。gemm_large_ocm:1:gemm_large_ocm_0 の場合、Vitis コンパイラは 1 つの gemm_large_ocm カーネルをインスタンシエートして、インスタンス名を gemm_large_ocm_0 に設定する必要があることを意味します。 |
param=hw_emu.enableProfiling=false - hw_emu の実行時にプロファイルを無効にし、実行時間を短縮します。 | |
param=compiler.addOutputTypes=hw_export | このオプションは Vitis コンパイラに、XCLBIN ファイルの作成だけでなく、Vitis ソフトウェア開発用のポスト Vivado 固定プラットフォームを作成するのに必要な XSA ファイルを出力するよう指示します。 |
param=compiler.worstNegativeSlack=-1.0 - WNS のトレランスを 210 ps に設定します。 | |
prop=run.synth_1.STRATEGY=Flow_PerfOptimized_high - 合成ストラテジを設定します。 | |
prop=run.impl_1.STEPS.OPT_DESIGN.is_enabled=true - 最適化デザイン指示子を有効にします。 | |
prop=run.impl_1.STEPS.OPT_DESIGN.ARGS.DIRECTIVE=Explore - 最適化デザイン段階指示子の値を設定します。 | |
prop=run.impl_1.STEPS.PLACE_DESIGN.ARGS.DIRECTIVE=ExtraTimingOpt - 配置デザイン指示子の値を設定します。 | |
prop=run.impl_1.STEPS.PHYS_OPT_DESIGN.is_enabled=true - 物理最適化指示子を有効にします。 | |
prop=run.impl_1.STEPS.PHYS_OPT_DESIGN.ARGS.DIRECTIVE=AggressiveExplore - 物理最適化指示子の値を設定します。 | |
prop=run.impl_1.STEPS.ROUTE_DESIGN.ARGS.DIRECTIVE=AggressiveExplore - 配線デザイン指示子の値を設定します。 |
Vitis™ コンパイラは、内部で Vivado™ IP インテグレーターを呼び出してデザインを構築します。プラットフォームおよびカーネルは、Vivado Design Suite への入力で、デザインの配置配線を実行した後にシミュレーション XSA または XSA を生成します。Vivado から XSA が生成される時点は、Vitis コンパイラ コマンド ラインで設定した -target
オプションによって異なります。
これで、$(BUILD_TARGET_DIR)/_x/link/vivado/vpl/prj
ディレクトリにある Vivado プロジェクトを表示できます。プラットフォームでデザインを実行するのに使用される XCLBIN ファイル $(BUILD_TARGET_DIR)/gemm.hw_emu.xclbin
を生成しました。
make application: ホスト アプリケーションのコンパイル
make application: ホスト アプリケーションのコンパイル
Cortex A72 プロセッサ用の次の一般的なクロス コンパイル フローに従って、ホスト アプリケーションをコンパイルできます。アプリケーションをビルドするには、次のコマンドを実行します。
make application
または
cd $(BUILD_TARGET_DIR); \
aarch64-xilinx-linux-g++ -mcpu=cortex-a72.cortex-a53 -march=armv8-a+crc -fstack-protector-strong \
-D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=$(SDKTARGETSYSROOT) -O -c \
-std=c++14 -D__linux__ \
-DM_LARGE=$(GEMM_SIZE) -DN_LARGE=$(GEMM_SIZE) -DL_LARGE=$(GEMM_SIZE) \
-I$(SDKTARGETSYSROOT)/usr/include/xrt -I$(SDKTARGETSYSROOT)/usr/include -I$(SDKTARGETSYSROOT)/usr/lib -I$(HOST_APP_SRC)/$(MAT_DIMS) \
$(HOST_APP_SRC)/main.cpp -o $(BUILD_TARGET_DIR)/gemm_top_app.o \
-L$(SDKTARGETSYSROOT)/lib -lxrt_coreutil
aarch64-xilinx-linux-g++ -mcpu=cortex-a72.cortex-a53 -march=armv8-a+crc -fstack-protector-strong \
-D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security --sysroot=$(SDKTARGETSYSROOT) \
$(BUILD_TARGET_DIR)/gemm_top_app.o -L$(SDKTARGETSYSROOT)/usr/lib -lxrt_coreutil \
-o $(BUILD_TARGET_DIR)/gemm_dsp_xrt.elf
XRT の資料は、こちらのページを参照してください。ホスト アプリケーション プログラミングの詳細は、こちらのページを参照してください。
オプション | 説明 |
---|---|
-O | Optimize. | コンパイルを最適化するには比較的時間がかかり、大型ファンクションではメモリも多く必要です。-O を使用すると、コンパイラは、かなりのコンパイル時間がかかる可能性のある最適化を実行せずに、コード サイズおよび実行時間の削減を試みます。 |
-D__linux__ | |
-DXAIE_DEBUG | 特定のコア ステータス、イベント ステータス、またはスタック トレースを出力できるデバッグ インターフェイス機能をイネーブルにします。 |
-D\<Pre-processor Macro String>=\<value> | クロス コンパイラにプリプロセッサ マクロ定義を渡します。 |
-I \<dir> | ヘッダー ファイルを検索するディレクトリのリストにディレクトリ dir を追加します。 |
-o \<file> | ファイル <file> に出力を配置します。これは、生成される出力が実行ファイル、オブジェクト ファイル、アセンブラー ファイル、または前処理された C コードであるかどうかにかかわらず適用されます。 |
--sysroot=\<dir> | ヘッダーおよびライブラリの論理ルート ディレクトリとして dir を使用します。たとえば、コンパイラが /usr/include でヘッダー、/usr/lib でライブラリを通常は検索する場合、代わりに dir/usr/include および dir/usr/lib で検索します。これは、env_setup.sh スクリプトにより自動的に設定されます。 |
-l\<library> | リンク中に library というライブラリを検索します。2D-FFT チュートリアルでは、adf_api_xrt および xrt_coreutil ライブラリが必要です。 |
-L \<dir> | -l を検索するディレクトリのリストにディレクトリ <dir> を追加します。 |
次は、クロス コンパイラ コマンドでコンパイルされる入力ソースの説明です。
入力ソース | 説明 |
---|---|
$(HOST_APP_SRC)/main.cpp | A72 プロセッサで実行する gemm_dsp_xrt.elf のソース アプリケーション ファイル。 |
$(HOST_APP_SRC)/matrix_A_data.h, matrix_B_data.h | 行列 A と B の行列乗算に使用するデータ。 |
$(HOST_APP_SRC)/output_data.h | DUT 出力を比較するためのゴールデン データ。 |
次は、上記の入力およびオプションを使用してクロス コンパイラ コマンドを実行した結果の出力オブジェクトの説明です。
出力オブジェクト | 説明 |
---|---|
$(BUILD_TARGET_DIR)/gemm_dsp_xrt.elf | A72 プロセッサで実行する実行ファイル。 |
make package: デザインのパッケージ
make package: デザインのパッケージ
カーネル出力および新しいプラットフォームが作成されたら、プログラマブル デバイス イメージ (PDI) と、SD カードで使用されるパッケージを生成できます。PDI には、デバイスの実行ファイル、ビットストリーム、およびコンフィギュレーションがすべて含まれます。パッケージされた SD カード ディレクトリには、Linux のブートに必要なすべてのもの、生成されたアプリケーション、および XCLBIN が含まれます。
このステップを実行するコマンドを、次に示します (デフォルト: TARGET=hw_emu
)。
make package
または
cp $(PROJECT_REPO)/run_script.sh $(BUILD_TARGET_DIR)/
cd $(BUILD_TARGET_DIR); \
v++ -p -t hw --save-temps --temp_dir $(BUILD_TARGET_DIR)/_x -f xilinx_vck190_base_202410_1 \
--package.rootfs $(XLNX_VERSAL)/rootfs.ext4 --package.kernel_image $(XLNX_VERSAL)/Image --package.boot_mode=sd \
--package.out_dir $(BUILD_TARGET_DIR)/package --package.image_format=ext4 --package.sd_file $(BUILD_TARGET_DIR)/gemm_dsp_xrt.elf \
$(BUILD_TARGET_DIR)/gemm.hw.xclbin
XRT_ROOT
が設定されていると、次の Vitis コンパイラ フラグも設定されます。
--package.sd_dir $(XRT_ROOT)
システムのパッケージの詳細は、こちらのページを参照してください。
オプション | 説明 |
---|---|
--target | -t [hw|hw_emu] | ビルド ターゲットを指定します。 |
--package | -p | Vitis コンパイルおよびリンク ビルド プロセスの終わりで最終的な出力をパッケージします。 |
--package.rootfs \<arg> | \<arg>: 処理された Linux ルート ファイル システム ファイルへの絶対パスまたは相対パスを指定します。プラットフォーム RootFS ファイルは、xilinx.com からダウンロードできます。詳細は、Vitis ソフトウェア プラットフォームのインストールを参照してください。 |
--package.kernel_image \<arg> | \<arg>: Linux カーネル イメージ ファイルへの絶対パスまたは相対パスを指定します。プラットフォームで使用可能な既存のイメージを上書きします。プラットフォーム イメージ ファイルは、xilinx.com からダウンロードできます。詳細は、Vitis ソフトウェア プラットフォームのインストールを参照してください。 |
--package.boot_mode \<arg> | \<arg>: |
--package.image_format | \<arg>: \<ext4|fat32> で出力イメージ ファイル形式を指定します。ext4 は Linux ファイル システム、fat32 は Windows ファイル システムです。 |
--package.sd_file | \<arg>: sd_card ディレクトリ/イメージにパッケージする ELF またはその他のデータ ファイルを指定します。このオプションを繰り返し使用すると、複数のファイルを sd_card に追加できます。 |
入力ソース | 説明 |
---|---|
$(XRT_ROOT) | PS ホスト アプリケーションを実行するには、このフォルダーに XRT ヘッダーが必要です。env_setup.sh で設定します。 |
$(XLNX_VERSAL)/rootfs.ext4 | PetaLinux のルート ファイル システム ファイル。 |
$(XLNX_VERSAL)/Image | プロセッサがブートされるビルド済みの PetaLinux イメージ。 |
$(BUILD_TARGET_DIR)/gemm_dsp_xrt.elf | make application ステップで作成された PS ホスト アプリケーション実行ファイル。 |
$(BUILD_TARGET_DIR)/gemm.hw_emu.xclbin | make xclbin ステップで作成された XCLBIN ファイル。 |
V++ パッケージ ステップの出力は、ハードウェア エミュレーションを実行するためのコンテンツを含むパッケージ ディレクトリです。
出力オブジェクト | 説明 |
---|---|
$(BUILD_TARGET_DIR)/package | ブート ファイル、ハードウェア エミュレーション起動スクリプト、PLM および PMC ブート ファイル、PMC および QEMU コマンド引数仕様ファイル、Vivado シミュレーション フォルダーを含むハードウェア エミュレーション パッケージ。 |
make run_emu: ハードウェア エミュレーションの実行
make run_emu: ハードウェア エミュレーションの実行
パッケージ後、ハードウェア エミュレーションの実行に必要なものがすべて設定されます。エミュレーションを実行するには、次のコマンドを実行します (デフォルト TARGET=hw_emu
)。
make run_emu
または
###########################################################################
Hardware Emulation Goto:
$(BUILD_TARGET_DIR)/package
and do:
./launch_hw_emu.sh or ./launch_hw_emu.sh -g (for waveform viewer)...
ハードウェア エミュレーションが起動すると、QEMU シミュレータ ロードが表示されます。自動ブート カウントダウンがゼロになるまで待ちます。数分後、root Linux プロンプトが表示されます。
root@versal-rootfs-common-2024.1:~#
root プロンプトが表示されたら、次のコマンドを入力してデザインを実行します。
cd /mnt
export XILINX_XRT=/usr
./gemm_dsp_xrt.elf a.xclbin
gemm_dsp_xrt.elf
が実行されます。数分後、TEST PASSED
という出力がコンソールに表示されるはずです。これが表示されたら、次のキーワード コマンドを入力して QEMU インスタンスを終了します。
#To exit QEMU Simulation
Press CtrlA, let go of the keyboard, and then press x
波形を使用して実行する手順は、次のとおりです。
cd $(BUILD_TARGET_DIR)/package
./launch_hw_emu.sh -g
XSIM 波形ビューアーが起動します。ビューアーに信号をドラッグ アンド ドロップし、[Play] をクリックしてエミュレーションを開始します。ターミナルに戻り、Linux プロンプトが表示されるまで待ちます。XSIM 波形ビューアーでは、波形に追加した信号が表示され、デザインの実行が調整されます。これが完了したら、一時停止ボタンを押してウィンドウを閉じ、エミュレーションを終了します。ハードウェア エミュレーションではソフトウェアの問題が原因でデータ整合性の不一致が生じますが、ハードウェア実行ではデザインは機能します。
TARGET=hw: ハードウェアでの実行
ハードウェアでの実行
ハードウェアでデザインを実行するには、次の make
ステップを、TARGET=hw
およびその他の該当オプション (上記に示した make
ステップを参照) を使用して再実行します。
make kernels TARGET=hw
make xsa TARGET=hw
make application TARGET=hw
make package TARGET=hw
これらのコマンドは、ハードウェアでの実行用にカーネル、XSA、および package
を含む $(BUILD_TARGET_DIR)
フォルダーを作成します。
次のステップを実行し、実行ファイル、生成されたイメージ、およびベース イメージ ($(BUILD_TARGET_DIR)/package/sd_card
および $(BUILD_TARGET_DIR)/package/sd_card.img
) を設定します。
make run_emu TARGET=hw
これらのコマンドは、ハードウェアでの実行用にカーネル、XCLBIN、および package
を含む build/hw
フォルダーを作成します。手順 1 ~ 9 に従い、VCK190 ボードで gemm_dsp_xrt.elf
実行ファイルを実行します。
手順 1: ボードの電源がオフになっていることを確認します。
手順 2: SD カード ライター (balenaEtcher など) を使用して sd_card.img
ファイルを SD カードのフラッシュ メモリに書き込みます。
手順 3: フラッシュ メモリに書き込んだ SD カードを VCK190 ボードの一番上のスロットに挿入します。
手順 4: スイッチを設定します (SW1 Mode\[3:0\]=1110 = OFF OFF OFF ON
)。
手順 5: ボードに同梱されている USB ケーブルを使用して、VCK190 ボードにコンピューターを接続します。
手順 6: TeraTerm ターミナルを開き、正しい COM ポートを選択します。ポート設定を次のように指定します。
Port: <COMMXX>
Speed: 115200
Data: 8 bit
Parity: none
Stop Bits: 1 bit
Flow control: none
Transmit delay: 0 msec/char 0 msec/line
手順 7: ボードに電源を投入します。
手順 8: root@versal-rootfs-common-2024_1
Linux コマンド プロンプトが表示されるまで待ちます。xinit
エラーが表示されなくなるまで Enter キーを数回押します。
手順 9: TeraTerm ターミナルで次のコマンド実行します。
mount /dev/mmcblk0p1 /mnt
cd /mnt
export XILINX_XRT=/usr
./gemm_dsp_xrt.elf a.xclbin
ハードウェア デザインの詳細
DSP58 インプリメンテーション アーキテクチャを使用した行列乗算
DSP58 インプリメンテーション アーキテクチャを使用した行列乗算
このデザインの場合、行列乗算が 32x32 サイズの DSP58 シストリック配列を使用してインプリメントされているので、32 個の DSP58 カスケード チェーンがあり、各チェーンに 32 個の DSP58 があります。このため、32x32 の行列が基本的な行列乗算サイズとなります。これより大きな行列は、32x32 の部分行列に分割されます。
基本的な 32x32 の乗算は次のように実行されます。
行列 A の行データは、DSP A ポートのカスケード チェーン沿いに上方向に移動します。最初の 32 クロック間は、データは DSP チェーンにシフトされるだけです。この 32 クロック後に、次の図のように、行列 A の行 0 が最初の DSP カスケード チェーンに、行 1 が次のカスケード チェーンに入力されます。
出力行列の最初の行の計算
行列 A のエレメントがカスケード チェーンにシフトされると、行列 B の最終行は、次の図に示すように、クロックごとに最初のカスケード チェーンの一番下の DSP に駆動されます。
出力行列の最初の行は次のように計算されます。
最下位の DSP は A[0,31] B[31,0] を計算し、PCOUT カスケード ポートを介して上位の DSP に出力を送信します。2 クロック目に上位の DSP が B[30,0]、B[30,1]、...B[30,31] (つまり行列 B の行 30) の受信を開始します。 つまり、2 クロック目で 2 つ目の DSP は A[0,30] B[30,0] + PCOUT = A[0,30] B[30,0] + A[0,31] B[31,0] を計算し、それを 3 つ目の DSP に送信します。3 つ目の DSP は 3 クロック目で行列 B の列 29 の受信を開始し、3 つ目の MAC 演算を計算し、4 つ目の DSP に送信します。この結果、32 クロック後に、最上位の DSP が出力行列の行 0 列 0 エレメントを生成しました。
2 クロック目で、最下位の DSP が B[31,1] を受信し、A[0,31] * B[31,1] を計算します。これが出力行列の行 0 列 0 エレメントの MAC 演算はここから開始されます。行 0、列 1 の計算も同様に上方向に移動し、33 クロック目に最上位 DSP が出力行列の行 0 列 1 のエレメントを生成します。
次の 30 クロック (クロック 34 ~ 63) 間についても同様に、最初のカスケード チェーンの最上位 DSP は、出力行列の行 0 のほかの 30 エレメントを生成します。
出力行列のその他の行は次のように計算されます。
B[31,0]、B[31,1]、...B[31,31] エレメント、つまり行列 B の行 31 は 1 クロックごとに次の DSP チェーンにシフトされます。この結果、行列 A の後続の DSP チェーンへの駆動も 1 クロック遅れで開始されます。 2 つ目のカスケード チェーンの一番下の DSP は 2 つ目のクロックで開始し、A[1,31] * B[31,0] を計算します。出力行列の行 1 列 0 エレメントの MAC 演算はここから開始されます。このため、2 つ目のカスケード チェーンは 1 つ目のカスケード チェーンより 1 クロック遅れ、クロック 33 から 64 までの 32 の出力を生成します。これらの出力が、出力行列の行 1 になります。後続の各カスケード チェーンは前のチェーンより 1 クロック遅れているため、最後のカスケード チェーンはクロック 63 から 94 で行 31 出力を生成します。
32x32 行列乗算のレイテンシ
最初の 32 クロックでは、行列 A 行 0 が最初のカスケード チェーンにロードされます。次の 32 クロックで、最初のカスケード チェーンが出力行列の最初の行を計算し、次の 32 クロックで出力行列のほかの行が生成されます。ただし、64 クロック後には、最初の DSP カスケード チェーンが次の 32x32 行列の最初の行データを受信できます。
これより大きな行列は、より小さな 32x32 行列に分割されます。たとえば、1Kx1Kx1K 行列は次のように、各ボックスが 32x32 行列になります。
出力行列は、次のようになります。
大きな行列のデータフロー
行列 A00 はまず行列 B00 と乗算されます。これは基本的な 32x32 行列乗算です。最初の 96 クロックで、各 DSP チェーンが 32 の出力を生成するため、合計 1K の出力が生成され、これが最終出力の部分和となります。これらの部分和は 64 の部分和 BRAM に書き込まれます。 64 クロック後、最初のカスケード チェーンが A00 B00 部分行列で実行され、A00 B01 を実行し始めて、出力行列の次の列の部分和を計算します。同様に、次の 32 クロックの間に、ほかの DSP カスケード チェーンも A00 B00 行列乗算を終了し、A00 B01 部分行列乗算に移行します。このように、行列 A00 が行列 B00、B01、B02...B0,31 と乗算されていきます。
これで A00 の部分行列の乗算が完了します。次に、行列 A の部分行列 A01 を読み込み、行列 B の部分行列と乗算させます。部分和は前に生成された部分和に加算され、再び格納されます。この結果、行列 A の最初の行に沿って移動し続け、その部分行列と行列 B の部分行列を乗算します。これを 32 回繰り返し、32 回目の繰り返しでは、部分和 BRAM の代わりに出力 BRAM にデータが書き込まれます。これで出力行列の 1 行目の計算が完了します。
この後、行列 A の次の行に移動して、これらすべてのステップを繰り返します。このような繰り返しを 32 回実行したら、1K×1K×1K の行列乗算が完了します。
大きな行列の行列計算レイテンシ
32x32 の行列計算には 96 クロックが必要です。ただし、DSP58 配列の最初のカスケード チェーンは 64 クロック後に計算を終了して、次の部分行列用のデータの受信を開始できるようになります。この結果、32 クロック間は、前の部分行列の計算と新しい部分行列の計算がオーバーラップします。このため、大きな行列の乗算に必要なクロック数は、64 * 部分行列の数 + 32 となります。
このデザインの場合、DSP クロックは 750 MHz (1.33 ns) で動作しています。
次の図は、このデザインのブロック図です。