アプリケーションおよびカーネルのデバッグ

Vitis™ 統合ソフトウェア プラットフォームは、ホスト コードとカーネル コード、およびそれらの通信をデバッグするための、アプリケーション レベルのデバッグ機能を提供します。これらの機能および手法は、ソフトウェア デバッグ フローとハードウェア デバッグ フローに分類できます。

ソフトウェア デバッグでは、標準デバッグ ツールとして GDB を使用して、ホスト コードおよびカーネル コードをデバッグできます。

ハードウェア デバッグでは、ハードウェアで実行中のカーネルを、Alveo™ データセンター アクセラレータ カードでは PCIe® バスを上で稼動するザイリンクス仮想ケーブル (XVC) を使用して、Alveo カードとエンベデッド プロセッサ プラットフォームでは USB-JTAG ケーブルを使用してデバッグできます。

デバッグ フロー

Vitis 統合ソフトウェア プラットフォームには、ホスト コードとカーネル コード、およびそれら 2 つのコード間の関係を効率的にデバッグするため、アプリケーション レベルのデバッグ機能があります。推奨されるデバッグ フローには、次の 3 つのレベルがあります。

この 3 段階により、ホスト コードとカーネル コード、およびその間の関係を、異なる抽象レベルでデバッグできます。それぞれデザインに関する特定の情報を提供するので、デバッグに役立ちます。すべてのフローは、統合 GUI フローおよびバッチ フローでサポートされ、基本的なコンパイル時間およびランタイム設定オプションを使用します。次のトピックでは、Vitis ソフトウェア プラットフォームでアプリケーションのデバッグに使用可能な機能の一部を説明します。

デバッグのための機能および手法

次の表に、異なるビルド コンフィギュレーションでのアプリケーションのデバッグに使用可能な機能と手法を示します。これらのデバッグ機能を使用することにより、機能的な問題、プロトコルの問題、ボード ハングなど、さまざまな問題を検出してデバッグできます。

  • GDB
  • 波形ビューアー
  • ChipScope™
  • printf
  • dmesg
  • xbutil
  • xclbininfo

ソフトウェア エミュレーションでのデバッグ

Vitis 統合ソフトウェア プラットフォームでは、一般的なホスト コードのソフトウェア デバッグが常にサポートされ、ソフトウェア エミュレーション モードの実行中およびハードウェア エミュレーション モードでカーネル コードのソフトウェア デバッグがサポートされます。これは、ブレークポイントを使用、コードをステップ実行、変数を解析、およびコードを特定のステートに強制するなどの操作を含む標準のソフトウェア デバッグ フローです。

次の図に、C/C++ または OpenCL™ で記述されたホストとカーネル コードをソフトウェア エミュレーションで GNU デバッグ (GDB) ツールを使用してデバッグするフローを示します。2 つの GDB インスタンスを使用してホスト プロセスとカーネル プロセスを個別にデバッグしており、デバッグ サーバー (xrt_server) を使用していることに注目してください。

1: ソフトウェア エミュレーション

ソフトウェア エミュレーションではコンパイルと実行が高速なので、ザイリンクスではデザインをできる限りソフトウェア エミュレーションで反復実行することをお勧めします。ソフトウェア エミュレーションの詳細は、ソフトウェア エミュレーション を参照してください。

GDB ベースのデバッグ

重要: デバッグには、-g オプションを使用してホストおよびカーネル コードの両方をコンパイルする必要があります。

GNU デバッグ (GDB) では、ブレークポイントを追加したり、変数を確認したりして、カーネルまたはホスト コードをデバッグできます。このソフトウェア デバッグ フローを使用すると、設計、コンパイル、デバッグをすばやく実行して、アプリケーションの機能を検証できます。Vitis デバッガーには、ホスト プログラムからザイリンクス ランタイム (XRT) ライブラリの内容を確認するための拡張機能が含まれます。これらの拡張機能を使用して、ホストとカーネル間のプロトコル同期化問題をデバッグできます。

Vitis コア開発キットでは、すべてのフローで GDB ホスト プログラムのデバッグがサポートされますが、カーネルのデバッグはソフトウェアおよびハードウェア エミュレーション モードでのみサポートされます。コンパイルおよびリンクを実行する際、-g オプションを使用してホストおよびカーネル コードでデバッグ機能を有効にする必要があります。

このセクションでは、GDB を使用してホストおよびカーネル デバッグを実行する方法を説明します。このフローはソフトウェア開発者には慣れたフローであるはずなので、このセクションでは、XRT ライブラリのホスト コード デバッグの拡張機能と、カーネル デバッグの要件について説明します。

ザイリンクス ランタイム ライブラリ GDB 拡張機能

Vitis デバッガー (xgdb) には、ホスト アプリケーションから XRT ライブラリを視覚化する新しい GDB コマンドが含まれます。
注記: Vitis デバッガー外で GDB を実行する場合は、ホストおよびカーネル デバッグの開始 で説明されているように、appdebug.py スクリプトを使用してコマンド拡張機能をイネーブルにする必要があります。

gdb コマンド ラインから、次の 2 種類のコマンドを呼び出すことができます。

  1. XRT ライブラリ データ構造 (cl_command_queuecl_event、および cl_mem) を可視化するための xprint コマンド。これらのコマンドは、下に説明されています。
  2. ハードウェア実行でのデバッグ時に Vitis ターゲット プラットフォームで実行されている IP を可視化するための xstatus コマンド。

xprint および xstatus コマンドの詳細を表示するには、gdb コマンド プロンプトで「help <command>」と入力します。

これらのコマンドは、ホスト アプリケーションがハングした場合に使用するのが一般的です。この場合、ホスト アプリケーションがコマンド キューが終了するのを待っているか、またはイベント リストで待機していると考えられます。xprint queue コマンドを使用してコマンド キューを表示すると、どのイベントが終了していないのかわかり、イベント間の依存性を解析できます。

これら両方のコマンドの出力は、Vitis IDE を使用してデバッグすると自動的に表示されます。[Debug] パースペクティブの左上の [Variables]、[Breakpoints]、[Registers] という 3 つのビューの横に、[Command Queue]、[Memory Buffers]、[Platform Debug] というビューが表示され、それぞれ xprint queuexprint mem、および xstatus の出力を表示します。Vitis IDE デバッグ フロー を参照してください。

xprint コマンド

xprint queue および xprint mem への引数はオプションです。アプリケーションのデバッグ環境では、すべての XRT ライブラリ オブジェクトが追跡され、引数が指定されていない場合は有効なすべてのキューおよび cl_mem オブジェクトが自動的に出力されます。さらに、これらのコマンドは、指定されているコマンドの queueeventcl_mem 引数を検証します。

xprint queue [<cl_command_queue>]
xprint event <cl_event>
xprint mem [<cl_mem>]
xprint kernel
xprint all
xstatus コマンド

この機能はシステム フロー (ハードウェア実行) でのみ使用でき、エミュレーション フローでは使用できません。

xstatus all
xstatus --<ipname>

GDB カーネル ベースのデバッグ

GDB カーネル デバッグは、ソフトウェア エミュレーション フローおよびハードウェア エミュレーション フローでサポートされます。通常のホスト コードのデバッグと同様、GDB 実行ファイルを IDE またはコマンド ライン フローでカーネルに接続し、ブレークポイントを設定して、カーネルの変数の内容をクエリします。カーネル GDB プロセスは生成されるソフトウェア プロセスに接続されるので、これはソフトウェア エミュレーションで完全にサポートされます。

ハードウェア エミュレーションでは、Vivado HLS でカーネル コードが RTL に変換されてから実行されます。RTL モデルのシミュレーションでは、パフォーマンスの最適化および同時ハードウェア実行のための変換がすべて適用されます。このため、すべての C/C++/OpenCL 行が独自に RTL コードにマップされるわけではないので、一部のブレークポイントのみがサポートされ、特定の変数のみをクエリ可能です。GDB ツールは、要求されたブレークポイント文に基づいて次の可能な行で停止し、RTL 変換のため変数をクエリできない場合はそれを明確に示します。

コマンド ライン デバッグ フロー

ヒント: ツールを実行する前に、Vitis 環境の設定 に説明されているように、コマンド シェルまたはウィンドウを設定します。

次に、コマンド ラインからソフトウェア エミュレーションのデバッグ フローを実行するのに必要な手順を示します。IDE でのデバッグについては、Vitis IDE の使用 を参照してください。Vitis コア開発キットでデバッグを実行する手順は、次のとおりです。

  1. g++ コマンド ラインに -g オプションを追加して、デバッグ用にホストをコンパイルおよびリンク (ホスト プログラムのビルド を参照)。
  2. v++ コマンド ラインに -g オプションを追加して、デバッグ用にカーネルをコンパイルおよびリンク (FPGA バイナリのビルド を参照)。
    注記: OpenCL カーネルをデバッグする際、OpenCL カーネルのデバッグ に説明されているように、コンパイルおよびリンク時に実行できる追加の段階があります。
  3. GDB を起動してアプリケーションをデバッグ。このプロセスには、ホストおよびカーネル デバッグの開始 に説明されているように、3 つのコマンド ターゲット プラットフォームが使用されます。

OpenCL カーネルのデバッグ

ソフトウェア エミュレーション フローでは、OpenCL カーネルに対して追加のランタイム チェックを実行できます。追加のチェックには、次のものがあります。

  • OpenCL カーネルがインターフェイス バッファーに対して範囲外アクセスを実行するか (fsanitize=address)。
  • カーネルが初期化されていないローカル メモリにアクセスするか (fsanitize=memory)。

--advanced オプション に説明されているように、--advanced コンパイラ オプションでイネーブルにする Vitis コンパイラ オプションがあり、次のコマンド構文を使用して指定できます。

--advanced.param compiler.fsanitize=address,memory

これらのオプションをイネーブルにすると、エミュレーションを実行したときにエミュレーション診断メッセージを含むデバッグ ログが <project_dir>/Emulation-SW/<proj_name>-Default>/emulation_debug.log に出力されます。

fsanitize 指示子も設定ファイルで次のように指定できます。

[advanced]
#param=<param_type>:<param_name>.<value>
param=compiler.fsanitize=address,memory

そして、この設定ファイルを v++ コマンド ラインで指定します。

v++ -l –t sw_emu --config ./advanced.txt -o bin_kernel.xclbin

--config オプションの詳細は、Vitis コンパイラの設定ファイル を参照してください。

ホストおよびカーネル デバッグの開始

ソフトウェア エミュレーションでは、ハードウェア アクセラレータをよりよくモデリングできるように、FPGA バイナリの実行は別のプロセスとして実行されます。ホスト コードのデバッグに GDB を使用している場合は、カーネル コードはホスト コード プロセス内で実行されるわけではないので、カーネル コードで設定されているブレークポイントは発生しません。ホスト コードおよびカーネル コードの同時デバッグをサポートするため、Vitis デバッガーには、デバッグ サーバー (xrt_server) を使用して実行されるカーネルに接続するシステムがメカニズムがあります。ホスト コードおよびカーネル コードをデバッグ サーバーに接続するには、次の手順を使用して 3 つのターミナル ウィンドウを開く必要があります。
ヒント: このフローは、GNU から入手可能な DDD (Data Display Debugger) などの GDB 用のグラフィカル フロントエンドを使用した場合でも使用できます。GDB を起動するには、次の手順に従います。
  1. 3 つのターミナル ウィンドウを開き、各ウィンドウを Vitis 環境の設定 で説明されているように設定します。3 つのウィンドウは、次のように使用します。
    • xrt_server を実行
    • ホスト コードで GDB (xgdb) を実行
    • カーネル コードで GDB (xgdb) を実行
  2. 最初のターミナルの環境を設定したら、次のコマンドを実行して Vitis デバッグ サーバーを起動します。
    xrt_server --sdx-url

    デバッグ サーバーは、ホストおよびカーネルからのデバッグ コマンドをリッスンし、2 つのプロセスを接続して 1 つのデバッグ環境を作成します。xrt_server から標準出力に listener port <num> と返されます。カーネル プロセスのデバッグに GDB でこのリスナー ポートが使用されるので、リスナー ポートの番号を継続的にチェックします。このプロセスを制御するには、新しい GDB インスタンスを開始し、xrt_server に接続する必要があります。これは、次の手順で実行します。

    重要: xrt_server の実行中は、実行されるすべての GDB プロセスはユーザーからの指示を待機します。GDB が xrt_server に接続されない場合、またはコマンドを供給しない場合は、カーネル コードがハングしているように見えます。
  3. 2 番目のターミナルの環境を設定したら、次の手順に従って、ホスト コード用に GDB を起動します。
    1. ENABLE_KERNEL_DEBUG 環境変数を設定します。たとえば、C シェルに次のように入力します。
      setenv ENABLE_KERNEL_DEBUG true
    2. アプリケーションの実行 の手順に従って、XCL_EMULATION_MODE 環境変数を sw_emu モードに設定します。たとえば、C シェルに次のように入力します。
      setenv XCL_EMULATION_MODE sw_emu
    3. xrt.ini ファイル に説明されているように、ランタイム デバッグ機能を xrt.ini ファイルのエントリを使用してイネーブルにする必要があります。ホスト実行ファイルと同じディレクトリに xrt.ini ファイルを作成し、次の行を含めます。
      [Debug]
      app_debug=true
      

      これにより、カーネルがデバッグ用にコンパイルされていることと、XRT ライブラリでデバッグ機能をイネーブルにする必要があることが、ランタイム ライブラリに通知されます。

    4. ザイリンクス ラッパーから gdb を起動します。
      xgdb --args <host> <xclbin>
      <host> はホスト実行ファイルの名前、<xclbin> は FPGA バイナリの名前です。次に例を示します。
      xgdb --args host.exe vadd.xclbin

      xgdb ラッパーから GDB を起動すると、Vitis デバッガーように次の手順が実行されます。

      • GDB に指定のホスト プログラムを読み込みます。
      • GDB コマンド プロンプトで source コマンドを使用して Python スクリプトを読み込み、Vitis デバッガー拡張機能をイネーブルにします。
        gdb> source ${XILINX_VITIS}/scripts/appdebug.py
  4. 3 番目のターミナルの環境を設定したら、xgdb コマンドを実行し、gdb プロンプトで次のコマンドを実行します。
    • ソフトウェア エミュレーションの場合:
      file <Vitis_path>/data/emulation/unified/cpu_em/generic_pcie/model/genericpciemodel

      <Vitis_path>Vitis コア開発キットのインストール パスです。$XILINX_VITIS 環境変数の使用は、GDB 内では機能しません。

    • ハードウェア エミュレーションの場合:
      1. xrt_server の一時ディレクトリ /tmp/sdx/$uid を検索します。
      2. このデバッグ セッションの DWARF ファイルを含む xrt_server プロセス ID (PID) を検索します。
      3. gdb コマンド ラインで file /tmp/sdx/$uid/$pid/NUM.DWARF を実行します。
    • どちらのエミュレーションでも、カーネル プロセスに接続します。
      target remote :<num>

      <num> は、xrt_server から返されるリスナー ポート番号です。

    ヒント: Vitis IDE でソフトウェア/ハードウェア エミュレーションのカーネルをデバッグする場合は、ホスト コードおよびカーネル コードを同時にデバッグするための環境が用意されていれば、これらの手順が自動的に処理され、カーネル プロセスも自動的にデバッグされます。

3 つのターミナル ウィンドウで xrt_server、ホスト用の GDB、カーネル用の GDB を実行すると、必要に応じてホストまたはカーネルにブレークポイントを設定し、continue コマンドを実行してアプリケーションをデバッグできます。すべてのカーネル実行が終了すると、ホスト コードは続行し、xrt_server 接続が解除されます。

重要: ソフトウェアおよびハードウェア エミュレーション フローでは、アクセラレーションされたカーネル コードのデバッグの操作に制限があります。このコードは、ソフトウェア エミュレーション フローでは前処理され、ハードウェア エミュレーション フローでは RTL に変換されるので、すべての位置にブレークポイントを設定できるとは限りません。特にハードウェア エミュレーションでは、保持されるループおよび関数など、限られた数のブレークポイントしかサポートされません。このような制限はありますが、この設定はホスト コードとカーネルの通信をデバッグするのに有益です。

カーネル デバッグでの printf() または cout の使用

アルゴリズムをデバッグする基本的な方法では、プログラムを実行して主なコード ステップとデータ値を検証します。アプリケーション開発では、チェックポイント文を表示し、コードの現在の値を出力するのが、プログラム実行における問題を特定するのにシンプルで効果的な方法です。これには、printf() 関数または cout を使用して標準出力に表示します。

C/C ++ カーネル

C/C++ カーネル モデルに対しては、printf() はソフトウェア エミュレーションでのみサポートされるので、Vivado® HLS 合成から除外されるようにする必要があります。この場合、printf() 文を次のコンパイラ マクロで囲みます。

#ifndef __SYNTHESIS__
    printf("Checkpoint 1 reached");
#endif

C++ カーネルでは、コードに cout を使用して、コードのデバッグに使用するチェックポイントまたはメッセージを追加できます。たとえば、次を追加できます。

std::cout << "TEST " << (match ? "PASSED" : "FAILED") << std::endl;

OpenCL カーネル

ザイリンクス ランタイム (XRT) ライブラリでは、すべてのビルド コンフィ (ソフトウェア エミュレーション、ハードウェア エミュレーション、およびハードウェア実行) で OpenCL™printf() ビルトイン関数がサポートされています。

ヒント: printf() 関数は、OpenCL カーネルのすべてのビルド コンフィギュレーションでのみサポートされます。C/C ++ カーネルでは、printf() はソフトウェア エミュレーションでのみサポートされます。

次に、カーネルで printf() を使用する例と、カーネルを global サイズ 8 で実行した場合の出力を示します。

__kernel __attribute__ ((reqd_work_group_size(1, 1, 1)))
void hello_world(__global int *a)
{
    int idx = get_global_id(0);

     printf("Hello world from work item %d\n", idx);
     a[idx] = idx;
}

出力は次のようになります。

Hello world from work item 0
Hello world from work item 1
Hello world from work item 2
Hello world from work item 3
Hello world from work item 4
Hello world from work item 5
Hello world from work item 6
Hello world from work item 7
重要: printf() メッセージはグローバル メモリに格納され、カーネル実行が終了するとアップロードされます。printf() を複数のカーネルで使用した場合、各カーネルからのメッセージがどの順でホスト ターミナルに表示されるかはわかりません。特にハードウェア エミュレーションおよびハードウェアで実行している場合、ハードウェアのバッファー サイズによってキャプチャされる printf 出力の量は制限されます。

ハードウェア エミュレーションでのデバッグ

ハードウェア エミュレーションでは、カーネル コードは RTL コードにコンパイルされるので、ザイリンクス デバイスにインプリメンテーションする前にカーネルの RTL ロジックを評価できます。ホスト コードはカーネルの RTL モデルのビヘイビアー シミュレーションと同時に実行でき、直接インポートされるか、Vivado HLS を使用して C/C++/OpenCL カーネル コードから作成されます。詳細は、ハードウェア エミュレーション を参照してください。

次の図に、ホスト コードの検証、ホストおよびカーネルのパフォーマンスのプロファイリング、FPGA リソース使用量の見積もり、ハードウェア (RTL) の正確なモデルを使用したカーネルの検証を実行するために Vitis デバッガーで使用可能なハードウェア エミュレーション フローを示します。GDB も、ホストおよびカーネル コードのソフトウェア スタイル デバッグに使用できます。

2: ハードウェア エミュレーション

ハードウェア エミュレーションを実行して、ホストおよびカーネルのハードウェア インプリメンテーションが正しいことを検証します。ハードウェア エミュレーション フローでは、FPGA ファブリックで実行されるカーネル ロジックをテストするため、Vitis コア開発キットから Vivado ロジック シミュレータが起動します。インターフェイス モデルの全体的な実行時間に対する影響を制限するため、モデル間のインターフェイスはトランザクション レベル モデル (TLM) で記述されます。ハードウェア エミュレーションの実行時間は、ソフトウェア エミュレーションよりも長くなります。

ヒント: ザイリンクスでは、デバッグおよび検証に小さなデータ セットを使用することをお勧めします。

ハードウェア エミュレーションでは、パフォーマンスを改善するためカーネル コードを変更することも可能です。機能が正しく、カーネルのパフォーマンス見積もりが十分なものになるまで、ハードウェア エミュレーションでホストおよびカーネル コード デザインを繰り返し実行します。

ハードウェア エミュレーションでの GDB ベースのデバッグ

ソフトウェア ベースの GDB フローを使用したデバッグは、ハードウェア エミュレーションで完全にサポートされています。Vitis デバッガーでは RTL コードが元の C/C++ ソース コードにマップされるので、ハードウェア エミュレーションでのデバッグにおける GDB の使用にも違いはありません。ただし、Vivado HLS での RTL 生成でカーネル ソースの変数およびループが削除されることがあるので、このコードのマップではブレークポイントの設定および変数の内容の確認が制限される場合があります。

ハードウェア エミュレーションでホスト コードおよびカーネル コードのデバッグに GDB を使用する場合、ソフトウェア エミュレーションと同じ 3 つのターミナル プロセスが使用されます。このフローの実行方法は、コマンド ライン デバッグ フロー の手順を参照してください。

波形ベースのカーネル デバッグ

ハードウェア エミュレーション ビルド コンフィギュレーションでは、C/C++ および OpenCL カーネル コードは Vivado HLS を使用して RTL コードに合成されるので、RTL ビヘイビアー シミュレーションを使用してカーネル ロジックを解析することもできます。ハードウェア設計者は、この方法に慣れています。この波形ベースの HDL デバッグは Vitis コア開発キットでサポートされており、ハードウェア エミュレーションにおいて、コマンド ライン フローまたは IDE フローで使用できます。

ヒント: 波形ベースのデバッグは、アドバンス機能です。ほとんどの場合、RTL ロジックを解析する必要はありません。

Vitis コンパイラ コマンドを使用した波形デバッグのイネーブル

波形デバッグ プロセスは、v++ コマンドで次の手順を使用してイネーブルにできます。
  1. FPGA バイナリのビルド に説明されているように、コンパイルおよびリンクの実行時にカーネル コードのデバッグ機能をイネーブルにします。
    v++ -g ...
  2. ホスト実行ファイルと同じディレクトリに次の内容の xrt.ini ファイル (xrt.ini ファイル を参照) を作成します。
    [Emulation]
    launch_waveform=batch
    
    [Debug]
    profile=true
    timeline_trace=true
    data_transfer_trace=fine
  3. アプリケーション、ホスト、およびカーネルをハードウェア エミュレーション モードで実行します。ハードウェア トランザクション データを含む波形データベースは、<hardware_platform>-<device_id>-<xclbin_name>.wdb ファイルに収集されます。このファイルは、Vitis アナライザーの使用 に説明されているように、Vitis アナライザーで直接開くことができます。
    ヒント: [Waveform] ビューおよびライブ波形ビューアー に説明されているように、launch_waveform=guixrt.ini に含まれていると、アプリケーションを実行したときにライブ波形ビューアーが起動します。ライブ波形ビューアーでは、シミュレータでのシミュレーション プロセスを停止してその時点までの波形を確認できるので、hw_emu のハング問題をデバッグする場合に特に有益です。

波形ベースのカーネル デバッグ フローの実行

Vitis IDE では、ハードウェア エミュレーション モードで波形ベースの HDL デバッグがサポートされています。波形は、Vivado ロジック シミュレーション ユーザーが使い慣れた Vivado 波形ビューアーに開きます。Vitis IDE では、カーネル インターフェイスおよび内部信号を表示でき、再開、HDL ブレークポイントなどのデバッグ制御や、HDL コード ルックアップ、波形マーカーもサポートされます。また、最上位 DDR データ転送 (バンクごと) と、計算ユニットの停止、ループ パイプラインのアクティビティ、カーネル特定の詳細も示されます。

詳細は、[Waveform] ビューおよびライブ波形ビューアーを参照してください。

ライブ波形ビューアーが生成されるように設定した場合は、実行ファイルを実行したときに波形ビューアーが自動的に開きます。デフォルトでは、波形ビューアーにすべてのインターフェイス信号と次のデバッグ階層が表示されます。

3: 波形ビューアー
Memory Data Transfers
すべての計算ユニットからのこれらのインターフェイスを介したデータ転送を表示します。
ヒント: これらのインターフェイスのビット幅は、計算ユニットとは異なることがあります。その場合、バースト長が異なります。たとえば、計算ユニットでの 16 個の 32 ビット ワードのバーストは、OCL マスターでは 1 つの 512 ビット ワードのバーストになります。
Kernel <kernel name><workgroup size> Compute Unit<CU name>
カーネル名、ワークグループ サイズ、および計算ユニット名。
CU Stalls (%)
CU 全体のストールのサマリを表示します。すべての最下位ストール信号のバスが 1 つ作成されます。このバスは、各時点においてアクティブな信号の割合 (%) として波形に表示されます。
Data Transfers
CU のすべての AXI マスターのデータ転送を表示します。
User Functions
CU の階層内の関数すべてをリストします。
Function: <function name>
これは関数名です。
Dataflow/Pipeline Activity
CU の関数レベルのループのデータフロー/パイプライン信号を表示します。
Function Stalls
この関数内の 3 つのストール信号をリストします。
Function I/O
関数の I/O をリストします。これらの I/O は、-m_axiap_fifoap_memory、または ap_none プロトコルのものです。
ヒント: 波形デバッガーと同様、[Scope] メニューから該当するインスタンスを選択し、[Object] メニューから信号を選択すると、内部信号の追加のデバッグ データを表示できます。また、HDL ブレークポイントなどのデバッグ制御、HDL コード ルックアップ、および波形マーカーもサポートされます。波形ビューアーの詳細は、『Vivado Design Suite ユーザー ガイド: ロジック シミュレーション』 (UG900) を参照してください。

ハードウェア実行中のデバッグ

ハードウェア実行では、実際のハードウェア プラットフォームを使用してカーネルを実行しますが、ホスト プログラムとアクセラレーション カーネルのパフォーマンスはアプリケーションを実行することにより評価できます。ただし、ハードウェア ビルドをデバッグするには、アプリケーションに追加のロジックを組み込む必要があります。これは、カーネルにより使用される FPGA リソースと、ハードウェアで実行されるカーネルのパフォーマンスに影響します。ハードウェア ビルドのデバッグ コンフィには、Integrated Logic Analyzer (ILA)Virtual Input/Output (VIO) コア、AXI パフォーマンス モニターなどの特別な ChipScope デバッグ ロジックが含まれます。

ヒント: ハードウェアのデバッグに必要な追加ロジックは、最終的な製品ビルドからは削除する必要があります。

次の図に、ハードウェア ビルドのデバッグ プロセスを示します。GDB を使用したホスト コードのデバッグ、Vivado ハードウェア マネージャーを使用した波形解析、カーネル アクティビティ レポート、およびメモリ アクセス解析を実行して、ハードウェアの問題を特定します。

4: ハードウェア実行

デバッグ用に設定されたシステム ハードウェア ビルドを使用すると、CPU で実行されるホスト プログラムとザイリンクス デバイスで実行される Vitis アクセラレーション カーネルがターゲット プラットフォームの実際のハードウェアで正しく実行されるかどうかを確認できます。特定または解析する必要のある問題には、次のものがあります。

  • プロトコル違反によるシステム ハング:
    • これらの違反により、システム全体が停止することがあります。
    • これらの違反により、カーネルが無効なデータを取得したり、停止することがあります。
    • これらの違反がどこでいつ発生しているかを検出するのは困難です。
    • このような状況をデバッグするには、AXI プロトコル チェッカーから ILA をトリガーする必要がある場合があります。これは、Vitis ターゲット プラットフォームで設定する必要があります。
  • ハードウェア カーネルの問題:
    • タイミング問題、レース コンディション、無効なデザイン制約など、インプリメンテーションにより問題が発生することがあります。
    • ハードウェア エミュレーションでは検出されない論理的な問題。
  • パフォーマンス問題:
    • 1 秒ごとに処理されるフレーム数が予測と異なるなど。
    • データ ビートとパイプライン処理を確認できます。
    • トリガー シーケンサー付きの ILA を使用して、バースト サイズ、パイプライン処理、およびデータ幅を確認し、ボトルネックを特定します。

ChipScope を使用したデバッグでのカーネルのイネーブル

ハードウェア デバッグで重要なのは、カーネルに必要なデバッグ ロジックを挿入することです。次のトピックでは、使用可能なカーネル ポートをリストし、選択したポートで ILA コアを有効にする v++ リンカー オプションを示します。

ILA コアを使用すると、ハードウェアで実行される計算ユニット (CU) のインスタンスのアクティビティをトランザクション レベルで表示できます。ILA コアを使用すると、特定の AXI トラフィックをキャプチャして表示することもできます。ILA コアは、既存の RTL カーネルに追加してデザイン内でデバッグ機能をイネーブルにするか、v++ コンパイラでリンク時に自動的に挿入されるようにできます。v++ コマンドには、デバッグおよびパフォーマンス監視用にカーネルへのインターフェイスに System ILA コアを接続する --dk オプションがあります。

-–dk オプションを使用して ILA IP コアの挿入をイネーブルにするには、次の構文を使用します。

 --dk <[chipscope|list_ports]:<cu_name>:<interface_name>>

通常、<interface_name> の使用はオプションです。指定しない場合、すべてのポートが解析されます。<compute_unit_name> および <interface_name> に対して chipscope オプションを使用する場合、計算ユニットに名前を指定する必要があります。list_ports オプションは、現在のデザインの有効な計算ユニットとポートの組み合わせのリストを生成します。カーネルをコンパイルした後に使用する必要があります。

  1. まず、カーネル ソース ファイルを .xo ファイルにコンパイルします。
    v++ -c -g -k <kernel_name> --platform <platform> -o <kernel_xo_file>.xo <kernel_source_files> 
  2. カーネルを .xo ファイルにコンパイルしたら、v++ リンク プロセスに使用するコマンド ライン オプションに--dk list_ports を追加できます。これにより、v++ コンパイラでカーネルに対して有効な計算ユニットとポート組み合わせのリストが表示されます。次に例を示します。
    v++ -l -g --platform <platform> --connectivity.nk <kernel_name>:<compute_units>:<kernel_nameN> 
    --dk list_ports <kernel_xo_file>.xo 
  3. 最後に、list_ports を適切な --dk chipscope コマンドに置き換えて、必要なポートで ChipScope デバッグを有効にします。
    v++ -l -g --platform <platform> --connectivity.nk <kernel_name>:<compute_units>:<kernel_nameN> 
    --dk chipscope:<compute_unit_name>:<interface_name> <kernel_xo_file>.xo 
ヒント: --dk オプションは、1 つの v++ コマンド ラインで複数回指定して、複数の CU およびインターフェイスを指定できます。

デザインがビルドされたら、ChipScope を使用したデバッグ に示すように、Vivado ハードウェア マネージャーを使用してデザインをデバッグできます。

System ILA

Vitis コア開発キットでは、デザインに Integrated Logic Analyzer (ILA) を挿入し、カーネル インターフェイスとグローバル メモリ間の信号をプローブすることにより、AXI トランザクション レベルのアクティビティを取り込んで表示できます。ILA を使用すると、1 つまたは複数の信号をトリガーするカスタム イベントを指定し、システム速度で波形をキャプチャすることが可能です。波形は、ビューアーで表示して解析することにより、プロトコル違反やパフォーマンスの問題などをデバッグするために使用でき、アプリケーションのハングなどの困難な状況をデバッグする際には不可欠です。

キャプチャされたデータは、Vivado ツールを使用してザイリンクス仮想ケーブル (XVC) を介してアクセスできます。詳細は、『Vivado Design Suite ユーザー ガイド: プログラムおよびデバッグ』 (UG908) を参照してください。

注記: ILA デバッグ コアには、信号データをキャプチャして格納するためのロジックおよびローカル メモリなど、システム リソースが必要です。つまり、カーネルの機能を視覚的に確認できるという点は優れていますが、パフォーマンスとリソース使用率に影響します。

デザインに System ILA を挿入するには、次に示すように v++ --dk オプションを使用します。

$ v++ --dk chipscope:<compute_unit_name>:<interface_name>

詳細は、Vitis コンパイラ コマンド を参照してください。

RTL カーネルへのデバッグ IP の追加

重要: このデバッグ手法を使用するには、Vivado Design Suite および RTL デザインに関する知識が必要です。

ILA や VIO などの ChipScope デバッグ コアを RTL カーネル コードに手動で追加することにより、RTL カーネルでデバッグをイネーブルにすることもできます。Vivado Design Suite で、RTL カーネル コードを編集して手動で ILA デバッグ コアをインスタンシエートするか、Vivado IDE でほかの IP を使用する場合と同様にザイリンクス IP カタログから VIO IP を挿入します。デザインにデバッグ コアを追加する方法の詳細は、『Vivado Design Suite ユーザー ガイド: プログラムおよびデバッグ』 (UG908) で HDL インスタンシエーション フローを参照してください。

デバッグ コアは、RTL カーネルを作成したときに追加するのがベストです。詳細は、『UltraFast 設計手法ガイド (Vivado Design Suite 用)』 (UG949) の「デバッグ」を参照してください。次に、ILA デバッグ コアを GitHub の RTL カーネルのデバッグ デザイン例の RTL カーネル ソース ファイルにインスタンシエートした例を示します。ILA は src/hdl/krnl_vadd_rtl_int.sv ファイルで指定した組み合わせ加算器の出力を監視します。

	// ILA monitoring combinatorial adder
	ila_0 i_ila_0 (
		.clk(ap_clk),              // input wire        clk
		.probe0(areset),           // input wire [0:0]  probe0  
		.probe1(rd_fifo_tvalid_n), // input wire [0:0]  probe1 
		.probe2(rd_fifo_tready),   // input wire [0:0]  probe2 
		.probe3(rd_fifo_tdata),    // input wire [63:0] probe3 
		.probe4(adder_tvalid),     // input wire [0:0]  probe4 
		.probe5(adder_tready_n),   // input wire [0:0]  probe5 
		.probe6(adder_tdata)       // input wire [31:0] probe6
	);

または、次の Tcl スクリプト例に示すように 『Vivado Design Suite ユーザー ガイド: プログラムおよびデバッグ』 (UG908) に説明されているネットリスト挿入フローを使用して、開いている Vivado プロジェクトで Tcl スクリプトを実行して ILA デバッグ コアを追加することもできます。

create_ip -name ila -vendor xilinx.com -library ip -version 6.2 -module_name ila_0
set_property -dict [list CONFIG.C_PROBE6_WIDTH {32} CONFIG.C_PROBE3_WIDTH {64} \
CONFIG.C_NUM_OF_PROBES {7} CONFIG.C_EN_STRG_QUAL {1} CONFIG.C_INPUT_PIPE_STAGES {2} \
CONFIG.C_ADV_TRIGGER {true} CONFIG.ALL_PROBE_SAME_MU_CNT {4} CONFIG.C_PROBE6_MU_CNT {4} \
CONFIG.C_PROBE5_MU_CNT {4} CONFIG.C_PROBE4_MU_CNT {4} CONFIG.C_PROBE3_MU_CNT {4} \
CONFIG.C_PROBE2_MU_CNT {4} CONFIG.C_PROBE1_MU_CNT {4} CONFIG.C_PROBE0_MU_CNT {4}] [get_ips ila_0]

RTL カーネルにデバッグ用に適切なデバッグ コアを挿入したら、ChipScope を使用したデバッグ に説明するように、ハードウェアを Vivado ハードウェア マネージャーで解析できます。

ハードウェア デバッグでの ILA トリガーのイネーブル

ホスト プログラムとターゲット プラットフォームで実行されるカーネル コードの両方のハードウェア デバッグを実行するには、カーネルがデバイスにプログラムされた、カーネルを開始に ILA トリガー条件を設定できるようにアプリケーション ホスト コードを変更する必要があります。

カーネル開始前に ILA トリガーを追加

ホスト プログラムを一時停止するには、GitHub の RTL カーネル例で使用されている wait_for_enter 関数など、コードに一時停止または待機ステップを追加します。この関数は、src/host.cpp コードで次のように定義します。

void wait_for_enter(const std::string &msg) {
    std::cout << msg << std::endl;
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

wait_for_enter 関数は、main 関数内で次のように使用します。

....
    std::string binaryFile = xcl::find_binary_file(device_name,"vadd");
	
    cl::Program::Binaries bins = xcl::import_binary_file(binaryFile);
    devices.resize(1);
    cl::Program program(context, devices, bins);
    cl::Kernel krnl_vadd(program,"krnl_vadd_rtl");


     wait_for_enter("\nPress ENTER to continue after setting up ILA trigger...");

    //Allocate Buffer in Global Memory
    std::vector<cl::Memory> inBufVec, outBufVec;
    cl::Buffer buffer_r1(context,CL_MEM_USE_HOST_PTR | CL_MEM_READ_ONLY, 
            vector_size_bytes, source_input1.data());
    ...

    //Copy input data to device global memory
    q.enqueueMigrateMemObjects(inBufVec,0/* 0 means from host*/);

    //Set the Kernel Arguments
    ...

    //Launch the Kernel
    q.enqueueTask(krnl_vadd);

wait_for_enter 関数を使用すると、ホスト プログラムが一時停止し、必要な ILA トリガーを設定して、カーネルからのデータを収集する準備をするための時間が与えられます。Vivado ハードウェア マネージャーを設定したら、Enter キーを押してホスト アプリケーションの実行を続行します。

  • C ホスト コードでは、上記の例に示すように、cl::Kernel オブジェクトの作成後に一時停止を追加します。
  • C ホスト コードでは、clCreateKernel() 関数呼び出しの後に一時停止を追加します。

GDB を使用したホスト アプリケーションの一時停止

GDB を実行してカーネルでハードウェア デバッグを実行するのと同時にホスト プログラムをデバッグする場合、必要に応じてコードにブレークポイントを挿入してホスト プログラムを一時停止できます。ホスト アプリケーションを変更してカーネル実行の前に一時停止するようにする代わりに、ホスト コードのカーネル実行の前にブレークポイントを設定できます。ブレークポイントに到達したら、Vivado ハードウェア マネージャーでデバッグ ILA トリガーを設定してトリガー待機状態にし、GDB でホスト プログラムの実行を再開します。

ChipScope を使用したデバッグ

ChipScope デバッグ環境と Vivado ハードウェア マネージャーを使用すると、ホスト アプリケーションとカーネルをすばやく効率的にデバッグできます。これらのツールでは、カーネルがハードウェアで実行されている状態で、ロジック レベルからシステム レベルのデバッグまで幅広い機能を使用できます。これには、次のいずれかの条件が満たされている必要があります。

ハードウェア デバッグ サポートのための FPGA ボードのチェック

ハードウェア デバッグをサポートするには、プラットフォームで複数の IP コンポーネント (Debug Bridge など) がサポートされている必要があります。プラットフォーム設計者に、これらのコンポーネントがターゲット プラットフォームに含まれるかどうかを確認してください。ザイリンクス プラットフォームを使用する場合、デバッグが可能かどうかを確認するには、platforminfo ユーティリティを使用してプラットフォームをクエリします。デバッグ機能は、chipscope_debug オブジェクトの下にリストされます。

たとえば、プラットフォームでハードウェア デバッグがサポートされているかどうかをクエリするには、次の platforminfo コマンドを使用します。

$ platforminfo --json="hardwarePlatform.extensions.chipscope_debug" xilinx_u200_xdma_201830_2
{
    "debug_networks": {
        "user": {
            "name": "User Debug Network",
            "pcie_pf": "1",
            "bar_number": "0",
            "axi_baseaddr": "0x000C0000",
            "supports_jtag_fallback": "false",
            "supports_microblaze_debug": "true",
            "is_user_visible": "true"
        },
        "mgmt": {
            "name": "Management Debug Network",
            "pcie_pf": "0",
            "bar_number": "0",
            "axi_baseaddr": "0x001C0000",
            "supports_jtag_fallback": "true",
            "supports_microblaze_debug": "true",
            "is_user_visible": "false"
        }
    }
}

出力には user および mgmt デバッグ ネットワークを含むターゲット プラットフォームが含まれ、MicroBlaze™ プロセッサのデバッグがサポートされ、管理デバッグ ネットワークの JTAG フォールバックもサポートされます。

XVC およびハードウェア サーバーの実行

ザイリンクス仮想ケーブル (XVC) およびハードウェア サーバーを実行し、ホスト アプリケーションを実行して、Vivado ハードウェア マネージャーでデバッグ コアをトリガー待機状態にしてトリガーするには、次の手順を実行します。
  1. ChipScope を使用したデバッグでのカーネルのイネーブル の手順に従って、カーネルにデバッグ IP を追加します。
  2. ハードウェア デバッグでの ILA トリガーのイネーブルの手順に従って、ホスト プログラムを適切な位置で一時停止するよう変更します。
  3. ハードウェア デバッグ用の自動設定 に説明されている自動スクリプトを使用するか、ハードウェア デバッグの手動設定 に説明されている手動の方法を使用して、ハードウェア デバッグの環境を設定します。
  4. 次の手順を実行してハードウェア デバッグを実行します。
    1. 必要な XVC および Vivado ハードウェア マネージャーの hw_server を起動します。
    2. ホスト プログラムを実行し、適切な位置で一時停止して、ILA トリガーのセットアップをイネーブルにします。
    3. Vivado ハードウェア マネージャーを開き、XVC サーバーに接続します。
    4. デザインの ILA トリガー条件を設定します。
    5. ホスト プログラムの実行を続行します。
    6. Vivado ハードウェア マネージャーでカーネルのアクティビティを確認します。
    7. 必要に応じて、上記の手順 b から繰り返します。
ハードウェア デバッグ用の自動設定
  1. Vitis 環境の設定 に説明されているように、Vitis コア開発キットを設定します。
  2. 次のコマンドに示すように、debug_hw スクリプトを使用して xvc_pcie および hw_server を起動します。
    debug_hw --xvc_pcie /dev/xvc_pub.<driver_id> --hw_server
    debug_hw スクリプトにより次のようなメッセージが表示されます。
    launching xvc_pcie...
    xvc_pcie -d /dev/xvc_pub.<driver_id> -s TCP::10200
    launching hw_server...
    hw_server -sTCP::3121
    ヒント: /dev/xvc_pub.<driver_id> ドライバー キャラクター パスはユーザーのマシンで定義されており、/dev フォルダーで確認できます。
  3. ハードウェア デバッグでの ILA トリガーのイネーブル で説明されているように、ホスト コードのカーネルが作成/ダウンロードされた、カーネル実行が開始するに一時停止文を追加します。
  4. 変更したホスト プログラムを実行します。
  5. debug_hw スクリプトを使用して Vivado Design Suite を起動します。
    debug_hw --vivado --host <host_name> --ltx_file ./_x/link/vivado/vpl/prj/prj.runs/impl_1/debug_nets.ltx
    ヒント: <host_name> はシステム名です。

    次に、コマンド ウィンドウに表示される結果の例を示します。

    launching vivado... ['vivado', '-source', 'vitis_hw_debug.tcl', '-tclargs', 
    '/tmp/project_1/project_1.xpr', 'workspace/vadd_test/System/pfm_top_wrapper.ltx', 
    'host_name', '10200', '3121']
     
    ****** Vivado v2019.2 (64-bit)
      **** SW Build 2245749 on Date Time
      **** IP Build 2245576 on Date Time
        ** Copyright 1986-2019 Xilinx, Inc. All Rights Reserved.
     
    start_gui
  6. Vivado Design Suite で ILA トリガーを実行します。

  7. Enter キーを押してホスト プログラムの実行を続行します。
  8. Vivado ハードウェア マネージャーの [Waveform] ウィンドウで、カーネル計算ユニットのスレーブ制御インターフェイス上のインターフェイス トランザクションを確認します。

ハードウェア デバッグの手動設定
ヒント: 次の手順は、Nimbix などのクラウド プラットフォームを設定する際に使用できます。

Vivado ハードウェア マネージャーでデザインをデバッグする前に、次の手順を実行してデバッグ サーバーを起動する必要があります。

  1. Vitis 環境の設定 に説明されているように、Vitis コア開発キットを設定します。
  2. xvc_pcie サーバーを起動します。xvc_pcie に渡すファイル名は、カーネル デバイス ドライバーにインストールされているキャラクター型ドライバー ファイルと同じである必要があります。<driver_id> は、/dev フォルダーで確認できます。
    >xvc_pcie -d /dev/xvc_pub.<device_id>
    ヒント: xvc_pcie サーバーには、多数の有益なコマンド ライン オプションがあります。xvc_pcie -help を実行すると、使用可能なオプションのリストが表示されます。
  3. 次のコマンドを使用して、ポート 3121hw_server を起動し、ポート 10201 の XVC サーバーに接続します。
    >hw_server -e "set auto-open-servers xilinx-xvc:localhost:10201" -e "set always-open-jtag 1"
  4. Vivado Design Suite を起動してハードウェア マネージャーを開きます。
    vivado

Vivado ハードウェア マネージャーを使用したデザインのデバッグ

Vivado ハードウェア マネージャーを使用したザイリンクス デバイスのデバッグには、従来物理的な JTAG 接続が使用されてきました。Vitis 統合ソフトウェア プラットフォームでは、リモート アクセラレータ カードのハードウェア デバッグにザイリンクス仮想ケーブル (XVC) が利用されます。この機能を活用するため、Vitis デバッガーでは XVC サーバーが使用されます。この XVC サーバーは XVC プロトコルのインプリメンテーションで、Vivado ハードウェア マネージャーをローカルまたはリモート ターゲット デバイスに接続し、ILA や VIO IP などの標準ザイリンクス デバッグ コアを使用してデバッグできるようにします。

Vivado Design Suite または Vivado デバッグ機能に含まれる Vivado ハードウェア マネージャーは、ターゲット インスタンス上で実行するか、異なるホスト上でリモートで実行できます。XVC サーバーがリッスンしている TCP ポートが、Vivado ハードウェア マネージャーを実行するホストにアクセスできることが必要です。Vivado ハードウェア マネージャーをターゲット上の XVC サーバーに接続するには、Vivado ツールをホストするマシンで次の手順を実行します。

  1. Vivado デバッグ機能またはフル Vivado Design Suite を起動します。
  2. [Tasks] セクションで Open Hardware Manager をクリックします。

  3. 次の図に示すように、ローカルまたはリモート接続 ([Connected to])、ホスト名 (Host name)、およびポート (Port) を指定して、Vivado ツールの hw_server に接続します。

  4. ターゲット インスタンスである仮想 JTAG XVC サーバーに接続します。

  5. Vivado ハードウェア マネージャーの [Hardware] ウィンドウで debug_bridge インスタンスを選択します。
    デザインのプローブ ファイル (.ltx) を指定し、[Hardware Device Properties] ウィンドウの Probes > File に追加します。プローブ ファイルを追加するとハードウェア デバイスが更新され、[Hardware] ウィンドウにデザインのデバッグ コアが表示されます。
    ヒント: カーネルに ChipScope を使用したデバッグでのカーネルのイネーブル で指定したデバッグ コアが含まれる場合、Vivado ツールによりカーネルのインプリメンテーション中にプローブ ファイル (.ltx) が生成されます。
  6. これで、Vivado ハードウェア マネージャーを使用して Vitis ソフトウェア プラットフォーム上で実行中のカーネルをデバッグできます。カーネルの ILA コアをトリガー待機状態にして、ホスト アプリケーションを実行します。

ヒント: Vivado ハードウェア マネージャーでのデザインのデバッグに関する詳細は、『Vivado Design Suite ユーザー ガイド: プログラムおよびデバッグ』 (UG908) を参照してください。

プライベート デバッグ ネットワーク用の JTAG フォールバック

Alveo データセンター アクセラレータ カードのハードウェア デバッグでは、物理的なカードおよびカード上の JTAG コネクタにはアクセスできないので、XVC-over-PCIe 接続を使用するのが一般的です。XVC-over-PCIe を使用すると、ターゲット プラットフォーム上で実行されているアプリケーションをリモートでデバッグできますが、AXI インターコネクトのシステム ハングアップなどの状況が発生すると、これらの PCIe/AXI 機能を使用するハードウェア デバッグ機能は使用できません。これらの状況をデバッグするのは、プラットフォーム設計では特に重要です。

JTAG フォールバックは、これまで XVC-over-PCIe でのみアクセス可能であったデバッグ ネットワークにアクセスするために設計された機能です。JTAG フォールバック機能は、プラットフォーム デザインの XVC-over-PCIe ベースのデバッグ ネットワークを変更せずにイネーブルにできます。

ホスト側では、Vivado ハードウェア マネージャー ユーザーが hw_server を介してアクセラレータ カード (テスト対象デバイス (DUT)) の JTAG ピンに接続されている JTAG ケーブルに接続すると、hw_server が XVC-over-PCIe のハードウェアへのパスをディスエーブルにします。これにより、XVC-over-PCIe ケーブルをプライマリ デバッグ パスとして使用できるようになりますが、特定の状況で必要な場合は JTAG ケーブルを介したデバッグがイネーブルになります。JTAG ケーブルへの接続を解除すると、hw_server は XVC-over-PCIe のハードウェアへのパスを再びイネーブルにします。

JTAG フォールバック手順
JTAG フォールバックをイネーブルにするには、次の手順に従います。
  1. JTAG アクセスが必要なデバッグ ネットワークのデバッグ ブリッジ (AXI-to-BSCAN モード) マスターの JTAG フォールバック機能をイネーブルにします。これにより、このデバッグ ブリッジ インスタンスの BSCAN スレーブ インターフェイスがイネーブルになります。
  2. プラットフォーム デザインのスタティック ロジック パーティションに別のデバッグ ブリッジ (BSCAN プリミティブ モード) をインスタンシエートします。
  3. 手順 2 のデバッグ ブリッジ (BSCAN プリミティブ モード) の BSCAN マスター ポートを手順 1 のデバッグ ブリッジ (AXI-to-BSCAN モード) の BSCAN スレーブ インターフェイスに接続します。

ハードウェア デバッグのユーティリティ

場合によっては、通常の Vitis IDE およびコマンド ライン デバッグ機能では問題を見つけられないことがあります。これは特に、ソフトウェアまたはハードウェアがハングしていて、何も進捗していないように見える場合です。このようなシステム問題は、このセクションで説明するユーティリティを使用して解析することをお勧めします。

Linux dmesg ユーティリティの使用

カーネルおよびモジュールが適切に設計されていれば、カーネル リング バッファーを介して問題がレポートされます。これは Vitis テクノロジ モジュールの場合も同様で、アクセラレータ ボードと通信する最下位 Linux レベルでのデバッグが可能になります。

dmesg ユーティリティは、カーネル リング バッファーを読み出すための Linux ツールです。カーネル リング バッファーでは、循環バッファーにカーネル情報メッセージが格納されます。リソース要件を制限するため固定サイズの循環バッファーが使用されており、1 番古いエントリが次に入ってくるメッセージで上書きされます。

ヒント: ほとんどの場合、詳細度の低い xbutil 機能でも問題を検出するのには十分です。このツールをデバッグに使用する場合の詳細は、ザイリンクス xbutil ユーティリティの使用 を参照してください。

Vitis テクノロジでは、情報メッセージは xocl モジュールおよび xclmgmt ドライバー モジュールによりリング バッファーに書き込まれます。このため、アプリケーションのハングやクラッシュが発生したり、予期しない動作 (ビットストリームをプログラムできないなど) が見られる場合は、dmesg ツールを使用してリング バッファーを確認する必要があります。

次の図に、ターゲット プラットフォームに関連付けられたソフトウェア プラットフォームのレイヤーを示します。

5: ソフトウェア プラットフォーム レイヤー

Linux ツールからのメッセージを確認するには、まずリング バッファーをクリアする必要があります。

sudo dmesg -c

これにより、すべてのメッセージがリング バッファーから消去されるので、xocl および xclmgmt からのメッセージを見つけやすくなります。その後、アプリケーションを開始して dmesg を別のターミナルで実行します。

sudo dmesg

dmesg ユーティリティで、次の例のような情報が表示されます。

6: dmesg ユーティリティの例

上記の例の場合、AXI Firewall 2 が作動しているので、xbutil ユーティリティを使用して検証することをお勧めします。

ザイリンクス xbutil ユーティリティの使用

ザイリンクス ボード ユーティリティ (xbutil) は、下位レベルのハードウェア/ソフトウェア間の相互関係の問題をデバッグするのに使用可能なスタンドアロンのコマンド ライン ユーティリティです。このユーティリティの詳細は、xbutil ユーティリティ を参照してください。

デバッグには、次の xbutil オプションを使用できます。
query
カード メモリのカーネル上の情報も含め、カードの全体的なステータスを示します。
program
バイナリ (xclbin) をザイリンクス デバイスのプログラマブル領域にダウンロードします。
status
パフォーマンス モニター (spm) および軽量 AXI プロトコル チェッカー (lapc) のステータスを示します。

アプリケーションのハングをデバッグするための手法

このセクションでは、ホスト コードとアクセラレーション カーネルの間での通信に関連する問題のデバッグについて説明します。これらの問題が発生すると、マシンまたはアプリケーションがハングします。GDB デバッグ環境を使用すると (xprint を使用)、ハングが特定のカーネルに関連するなど、エラーを特定するのに役立つことはありますが、このセクションに示すように、dmesg および xbutil コマンドを使用してデバッグするのが最適です。

このハードウェア デバッグ プロセスで問題を解決できない場合は、ChipScope を使用してハードウェア デバッグを実行する必要があります。

AXI Firewall が作動する

AXI Firewall は、ホストがハングしないようにします。このため、ザイリンクスでは Vitis ターゲット プラットフォームに AXI Protocol Firewall IP を含めることをお勧めしています。ファイアウォールが作動した場合、最初に確認することの 1 つは、ホスト コードとカーネルが同じメモリ バンクを使用しているかということです。このチェックを実行するには、次の手順に従います。
  1. xbutil を使用して FPGA をプログラムします。
    xbutil program -p <xclbin>
    ヒント: xbutil の詳細は、xbutil ユーティリティ を参照してください。
  2. xbutil クエリ オプションを実行してメモリ トポロジを確認します。
    xbutil query

    次の例では、メモリ バンクに関連付けられているカーネルはありません。

  3. ホスト コードが DDR バンク/PLRAM が使用されることを想定している場合は、このレポートに問題があることが示されます。この場合、カーネルとホスト コードで何が想定されているかを確認する必要があります。ホスト コードがザイリンクス OpenCL 拡張機能を使用している場合、カーネルでどの DDR バンクを使用するべきかを確認する必要があります。これらは、カーネル ポートのグローバル メモリへのマップ に説明されているように、指定した connectivity.sp オプションと同じである必要があります。

AXI 違反のためカーネルがハングする

カーネルとメモリ コントローラー間の AXI トランザクションが無効であるため、カーネルがハングする可能性があります。これらの問題をデバッグするには、カーネルをインストルメント化する必要があります。
  1. Vitis コア開発キットには、v++ リンク (-l) 時に適用可能なインストルメンテーション オプションが 2 つあります。これらのオプションは両方ともインプリメンテーションにハードウェアが追加されるので、リソース使用率に基づいてインストルメンテーションを制限する必要があることがあります。
    1. 軽量 AXI プロトコル チェッカー (lapc) を追加します。これらのプロトコル チェッカーは、-–dk オプションを使用して追加します。次の構文を使用します。
      --dk [protocol|list_ports]:<compute_unit_name>:<interface_name>
      通常、<interface_name> の使用はオプションです。指定しない場合、すべてのポートが解析されます。プロトコル チェッカーが挿入されるように定義するには、protocol オプションを使用します。このオプションでは、<compute_unit_name> および <interface_name> のいずれかまたは両方に、キーワード all を使用できます。list_ports オプションは、現在のデザインの有効な計算ユニットとポート組み合わせのリストを生成します。
      注記: コマンド ライン 1 行に複数の --dk オプションを含めて、インターフェイス モニター機能を追加できます。
    2. パフォーマンス モニター (am, aim, asm) を追加すると、詳細な通信統計 (カウンター) のリストがイネーブルになります。これはパフォーマンス解析に最も役立ち、未処理のポート アクティビティのデバッグにおいて有益な情報を得ることができます。パフォーマンス モニターを追加するには、profile_kernel オプションを使用します。profile_kernel オプションの基本的な構文は、次のとおりです。
      --profile_kernel data:<krnl_name>|all:<cu_name>|all:<intrfc_name>|all:<counters>|all
      パフォーマンス モニターを追加する正確なインターフェイスを指定するには、3 つのフィールドが必要ですが、リソース使用量が問題ではない場合は、all キーワードを使用すると、1 つのオプションで既存のカーネル、計算ユニット、インターフェイスすべてを監視できるよう設定できます。または、kernel_namecu_name、および interface_name を明示的に指定してインストルメンテーションを制限します。
      最後のオプション <counters>|all は、大型デザインで情報の収集を counters に制限するか、all (デフォルト) を指定して実際のトレース情報が収集されるようにします。
      注記: コマンド ライン 1 行に複数の --profile_kernel オプションを含めて、パフォーマンス機能を追加できます。
      --profile_kernel data:kernel1:cu1:m_axi_gmem0 
      --profile_kernel data:kernel1:cu1:m_axi_gmem1 
      --profile_kernel data:kernel2:cu2:m_axi_gmem
  2. アプリケーションをビルドし直したら、追加した AIM IP および LAPC IP を含め、xclbin を使用してホスト アプリケーションを実行し直します。
  3. アプリケーションがハングしたら、xbutil status を使用してエラーや異常を確認します。
  4. 次のように AIM 出力を確認します。
    • xbutil status --aim を数回実行して、動いているカウンターがあるかを確認します。カウンターが動いている場合、カーネルはアクティブです。
      ヒント: AIM 出力のテストは、GDB デバッグでも xstatus spm コマンドを使用してサポートされます。
    • カウンターが止まっている場合、未処理のカウントが 0 より大きいということは、AXI トランザクションにハングしているものがある可能性があります。
  5. 次のように LAPC 出力を確認します。
    • xbutil status --lapc を実行して、AXI 違反がないかどうかを確認します。
      ヒント: LAPC 出力のテストは、GDB デバッグでも xstatus lapc コマンドを使用してサポートされます。
    • AXI 違反がある場合は、カーネル インプリメンテーションに問題があることを意味します。

ホスト アプリケーションがメモリにアクセス中にハングする

アプリケーションのハングは、ホスト コードからの不完全な DMA 転送により発生することもあります。これは、必ずしもホスト コードが間違っているということではなく、カーネルが無効なトランザクションを発行したために AXI がロックアップすることもあります。
  1. プラットフォームに Vitis ターゲット プラットフォームと同様の AXI ファイアウォールがある場合、ファイアウォールが作動します。ドライバーにより SIGBUS が発行され、アプリケーションが強制終了されて、デバイスがリセットされます。これは xbutil query を実行するとチェックできます。次の図に、このようなファイアウォール ステータスのエラーを示します。

    ヒント: ファイアウォールが作動しなかった場合、Linux ツール dmesg で追加の情報が示される場合があります。
  2. ファイアウォールが作動した場合は、DMA タイムアウトの原因を特定することが重要です。原因には、無効な DMA 転送、カーネルの誤動作などが考えられます。AXI ファイアウォールが作動すると、アプリケーションの強制終了後にドライバーのヘルス チェック機能によりボードがリセットされ、デバイス上にある根本的な原因を特定する役立つ情報はすべて失われます。この問題をデバッグするには、xclmgmt カーネル モジュールでヘルス チェック スレッドをディスエーブルにして、エラーがキャプチャされるようにします。これには、一般的な Unix カーネル ツールを次の順で使用します。
    1. sudo modinfo xclmgmt: モジュールの現在の設定をリストし、health_check パラメーターがオンかオフかを示します。xclmgmt モジュールへのパスも返します。
    2. sudo rmmod xclmgmt: xclmgmt カーネル モジュールを削除してディスエーブルにします。
    3. sudo insmod <path to module>/xclmgmt.ko health_check=0: ヘルス チェックをディスエーブルにした状態で xclmgmt カーネル モジュールを再インストールします。
      ヒント: このモジュールへのパスは、modinfo への呼び出しの出力にレポートされます。
  3. ヘルス チェックをディスエーブルにしたら、アプリケーションを再実行します。前述のように、カーネル インストルメンテーションを使用して問題を特定できます。

アプリケーションのハングを引き起こす典型的なエラー

次に、アプリケーションのハングを引き起こす典型的なユーザー エラーを示します。

  • 5.0+ シェルで書き込み前に読み出しを使用すると、Memory Interface Generator エラー訂正コード (MIG ECC) エラーが発生します。これは、典型的なユーザー エラーです。たとえば、カーネルで DDR に 4 KB のデータを書き込む際に、1 KB のデータしか生成されず、4 KB のデータをホストに転送しようとすると、このエラーが発生することがあります。また、1 KB バッファーをカーネルに供給していて、カーネルが 4 KB のデータを読み出そうとした場合にも発生する可能性があります。
  • ECC の書き込み前に読み出しエラーは、最後にビットストリームがダウンロードされて初期化されたためにメモリ ロケーションにデータが何も書き込まれていないと、そのメモリ ロケーションに対して読み出し要求が発行された場合にも発生することがあります。カーネルではこの ECC エラーを処理できないので、影響を受けた MIG がストールします。これは、次のいずれかの形で現れます。
    1. CU が影響を受けた MIG に対して読み出しまたは書き込みを実行するときに、このエラーを処理できないため、CU がハングまたはストールします。xbutil クエリには、CU が BUSY ステートに停滞し、進行していないことが示されます。
    2. 影響を受けた MIG に対して PCIe® DMA 要求が発行されると、DMA エンジンで要求を完了できないため、AXI Firewall が作動します。AXI Firewall が作動すると Linux カーネル ドライバーが SIGBUS 信号でデバイス ノードを開いたすべてのプロセスを強制終了します。xbutil クエリには、AXI Firewall が差動したかどうかとタイムスタンプが示されます。
    上記のハングが発生しない場合、ホスト コードで正しいデータがリードバックされない可能性があります。この正しくないデータは通常 0 で、データの最後の部分に配置されます。ホスト コードを注意して確認することが重要です。よくある例の 1 つは圧縮で、圧縮後のデータのサイズがわかっておらず、アプリケーションがカーネルで生成されたデータよりも多くのデータをホストに転送しようとする場合です。

防御的プログラミング

Vitis コンパイラでは、非常に効率的なインプリメンテーションを作成できますが、場合によってはインプリメンテーションの問題が発生することがあります。たとえば、プロセスに書き込みトランザクションを完了するのに十分なデータがないときに書き込み要求が発行される場合などです。複数の同時カーネルがこの問題の影響を受け、カーネルの読み出し要求を実行するのに入力読み出しが完了することが必要な場合、デッドロック状態が発生する可能性があります。

このような状況を回避するため、アダプターに保守モードがあります。このモードでは、原則として、書き込みを完了するのに必要なデータが揃うまで、書き込み要求を遅らせます。このモードを有効にするには、コンパイル時に v++ コンパイラに次の --advanced.param オプションを指定します。

--advanced.param:compiler.axiDeadLockFree=yes

このモードを有効にするとパフォーマンスに影響することがあるので、防御的プログラミング手法として使用し、開発およびテスト時にこのオプションを挿入して最適化時には削除することもできます。アクセラレータが繰り返しハングする場合にも、このオプションを追加してみることをお勧めします。

コマンド ライン デバッグの例

コマンド ライン フローを使用したデバッグ方法の理解を助けるため、この例ではザイリンクス GitHub の IDCT 例をビルドしてデバッグします。
  1. ターミナルで、Vitis 環境の設定 で説明されているように環境を設定します。
  2. Vitis Examples GitHub リポジトリ全体をクローンして、すべての Vitis 例を入手します。
    git clone https://github.com/Xilinx/Vitis_Accel_Examples.git

    これにより、IDCT 例を含む Vitis_Examples ディレクトリが作成されます。

  3. cd コマンドを使用して IDCT 例のディレクトリに移動します。
    cd Vitis_Examples/vision/idct/

    ホスト コードは src/idct.cpp に含まれており、カーネル コードは src/krnl_idct.cpp の一部です。

  4. FPGA バイナリのビルド の手順に従って、ソフトウェア エミュレーション用にカーネル ソフトウェアをビルドします。
    1. -g を使用して v++ コンパイラを実行し、カーネル オブジェクト ファイルをデバッグ用にコンパイルします。
      v++ -t sw_emu --platform <DEVICE> -g -c -k krnl_idct \
      -o krnl_idct.xo src/krnl_idct.cpp
    2. -g を指定してカーネル オブジェクト ファイルをリンクします。
      v++ -g -l -t sw_emu --platform <DEVICE> -config config.txt \
      -o krnl_idct.xclbin krnl_idct.xo
      --config オプションは、Vitis コンパイラの設定ファイル で説明されているように、ビルド プロセスの指示子を含む設定ファイル config.txt を指定します。設定ファイルの内容は次のとおりです。
      kernel_frequency=250
      
      [connectivity]
      nk=krnl_idct:1:krnl_idct_1
      
      sp=krnl_idct_1.m_axi_gmem0:DDR[0]
      sp=krnl_idct_1.m_axi_gmem1:DDR[0]
      sp=krnl_idct_1.m_axi_gmem2:DDR[1]
      
      [advanced]
      prop=solution.hls_pre_tcl='src/hls_config.tcl"
  5. ホスト プログラムのビルド の手順に従って、GNU コンパイラ チェーン g++ を使用してホスト コードをデバッグ用にコンパイルします。
    注記: エンベデッド プロセッサ ターゲット プラットフォームでは、Arm 用のコンパイルおよびリンク で説明するように、GNU Arm クロス コンパイラを使用します。
    1. -g オプションを使用してホスト コード C++ ファイルをデバッグ用にコンパイルします。
      g++ -c -I${XILINX_XRT}/include -g -o idct.o src/idct.cpp 
    2. -g を使用してオブジェクト ファイルをデバッグ用にリンクします。
      g++ -g -lOpenCL -lpthread -lrt -lstdc++ -L${XILINX_XRT}/lib/ -o idct idct.o
  6. emconfigutil ユーティリティ に説明されているように、次のコマンドを使用してエミュレーション環境を設定します。
    emconfigutil --platform <device>
    エミュレーション モード (sw_emu または hw_emu) は、XCL_EMULATION_MODE 環境変数で設定します。これは、C シェルでは次のように指定します。
    setenv XCL_EMULATION_MODE sw_emu
  7. xrt.ini ファイル に説明されているように、ランタイムをデバッグ用に設定する必要があります。ホスト アプリケーションをコンパイルしたディレクトリで、次のないようの xrt.ini ファイルを作成します。
    [Debug]
    app_debug=true
    
  8. ホストおよびカーネルで GDB を実行します。次の手順に従うと、コマンド ラインでのデバッグ プロセスを実行できます。これには、Vitis 環境の設定 に説明されているように、3 つのコマンド ターミナルが必要です。
    1. 最初のターミナルでは、XRT デバッグ サーバーを開始します。XRT デバッグ サーバーは、ホスト コードとカーネル コードの間のトランザクションを処理します。
      ${XILINX_VITIS}/bin/xrt_server --sdx-url
    2. 2 つ目のターミナルで、エミュレーション モードを設定します。
      setenv XCL_EMULATION_MODE sw_emu
      次のコマンドを使用して GDB を実行します。
      xgdb –-args idct krnl_idct.xclbin
      gdb プロンプトに次のコマンドを入力します。
      run
    3. 3 つ目のターミナルで、ソフトウェア エミュレーションまたはハードウェア エミュレーション モデルを GDB に接続し、デザインをステップ実行できるようにします。ここでは、ソフトウェア エミュレーションとハードウェア エミュレーションの実行に違いがあります。どちらのフローでも、別の xgdb を起動します。
      xgdb
      • ソフトウェア エミュレーションでのデバッグの場合:
        • gdb プロンプトに次のコマンドを入力します。
          file <XILINX_VITIS>/data/emulation/unified/cpu_em/generic_pcie/model/genericpciemodel
          注記: GDB では環境変数は展開されないので、<XILINX_VITIS>Vitis ソフトウェア プラットフォームのインストールへのパスに置き換える必要があります。
      • ハードウェア エミュレーションでのデバッグの場合:
        1. xrt_server の一時ディレクトリ /tmp/sdx/$uid を見つけます。
        2. このデバッグ セッションの DWARF ファイルを含む xrt_server プロセス ID (PID) を検索します。
        3. gdb プロンプトで次のコマンドを実行します。
          file /tmp/sdx/$uid/$pid/NUM.DWARF
      • どちらのエミュレーションでも、カーネル プロセスに接続します。
        target remote :NUM

        NUM は、GDB リスナー ポートとして xrt_server から返される値です。

      この時点で、ホスト コードとカーネル コードが 2 つの異なる GDB セッションで実行され、GDB でデバッグを通常どおり実行できるようになります。これは、異なるプロセスを処理する場合は一般的です。

      重要: 1 つのプロセスが次のブレークポイントに達する前に、もう 1 つのプロセスがブレークポイントに達することがあるということに注意してください。この場合、2 つ目のターミナルで入力を待つ間、1 つ目のターミナルでのデバッグ セッションがハングしているように見えます。