VSC モードでは、ハードウェアの構築 で説明するように、ユーザー定義のハードウェア パイプラインを含む CU を使用してアクセラレータをコンパイルできます。このようなパイプラインは、AXI4-Stream を介して相互接続される PE で構成され、グローバル メモリやイーサネット QSFP ポートなどの IO インターフェイスなど、AXI4 接続のプラットフォーム ポートにも接続できます。プラットフォームでは、このようなインターフェイスをユーザー定義パイプラインの PE に接続できる AXI4-Stream ポートに変換する IP が提供されます。
VSC を使用すると、このようなハードウェア パイプラインが、ホスト CPU で実行されているアプリケーションから実行時の処理動作をダイナミックに変更できるように簡単に設定できます。このようなアクセラレータを作成する方法は、次のとおりです。システム構成の例を次の図に示します。
Eth_Rx
および Eth_Tx
モジュールは、通常、AXI4-Stream ワードをイーサネット パケットに変換するプラットフォーム IP です。これらは、ユーザー定義の AXI4 インターフェイスを使用したカスタム IP にすることもできます。
白いボックスに示されている残りのアクセラレータ パイプラインは、AXI4-Stream 接続を使用して VSC で作成されます。パイプライン内の PE は、インターネット プロトコル パケット フィルターのようなパケット プロセッシングなどの、ユーザー定義の機能です。この例には、2 つのタスク (mod
と smp
という PE) を使用して作成されたパイプラインがあります。また、このシステムは、これらのパイプライン PE への AXI4-Stream 接続を持つ別の制御 PE で構成されます。次は、アクセラレータ コードの例です。左側は .hpp ファイル、右側は .cpp ファイルです。
|
|
この例では、eth_tx
および eth_rx
などを含む 5 つの PE が定義されており、プラットフォーム IP が AXI4-Stream でワードを送受信する動作が模倣されます。compute()
スコープは、これらの PE 間の AXI4-Stream 接続を使用してアクセラレータ パイプラインをインプリメントします。control
PE はこれらのストリームでコマンド ワードを送信でき、タスク PE (fsk_mod
および fsk_smp
) はこれらのコマンドを AXI4-Stream を介して監視し、ビヘイビアーを変更することで反応します。fsk_smp
PE は、要求された数のパケットを control
PE にサンプリングして戻すことで反応します。fsk_mod
PE は、パケット データに値を追加するか、Eth_Rx
から Eth_Tx
に渡されるパケットをドロップすることによって反応します。
パイプライン PE (fsk_mod
および fsk_smp
) は、入力ストリーム内のワードによって動作に駆動される終了しない PE なので、FREE_RUNNING
です (ガイダンス マクロ を参照)。
control
PE は、入力 (dIn
) および出力 (dOut
) のインターフェイス引数データ ポインターの 2 つの SYS_PORT
接続、およびスカラー コマンド引数 (cmd
) を介してホスト CPU と通信します。control
PE はフリーランニングではなく、ホスト CPU からの compute()
呼び出しに反応します。このシステム構成は、コマンドの性質および対応する PE 機能を含め、すべてユーザーが定義します。
次は、ホスト コードのスナップショットです。例全体は、GitHub を参照してください。
// -- file: host.cpp --
#include "vpp_acc_core.hpp" // required
#include "ETH.hpp"
int config_sample(int sz)
{
printf("main: sample %d\n", sz);
Pkt* sample = (Pkt*)ETH::alloc_buf(sz * sizeof(Pkt), vpp::output);
Pkt* config = (Pkt*)ETH::alloc_buf(sizeof(Pkt), vpp::input);
config[0].dt = sz;
auto fut = ETH::compute_async(cmd_sample, config, sample);
fut.get();
print_sample(sample, sz);
int pkt_nr = sample[0].nr;
ETH::free_buf(config);
ETH::free_buf(sample);
return pkt_nr;
}
VSC ホスト コードによって発行されるジョブ コマンドは、特に compute_async()
API を使用した場合、制御 PE をイネーブルにしてコマンドを変換し、コマンド ストリームを介してコンフィギュレーション ワードをパイプライン PE に渡すことができます。このスナップショットには、パケット サンプリング コマンドを発行するユーザー定義の API が表示されます。必要な sz
の sample
バッファーが実行時に割り当てられ、compute_async()
呼び出しがパケットの sz
数を取り込むように制御 PE をトリガーし、ワードをホストに戻します。compute()
によって返された fut
は、結果が使用可能になるまでホスト コードでブロックされます。ただし、compute_async()
は名前の示すとおり非同期呼び出しで、アクセラレータをトリガーします。サンプル ワードが返され、ホストによって処理されると、対応するバッファーがフリーになります。
この場合、ホスト制御は計算ジョブの連続パイプラインではありませんが、不定期でタイミングが重要ではないジョブだけなので、send_while/receive_all
スレッドはこれを管理しません。代わりに、vpp_acc_core.hpp で定義された compute_async()
API を使用して同期がアプリケーションで管理されます。
vpp_acc.hpp
が含まれる前に含める必要があります。VSC では、このようなハードウェア パイプラインを構成し、ホスト CPU から非同期に制御できます。このようなアクセラレータのアプリケーションの 1 つは、NIC カード上のパケット プロセッシング アクセラレータです。たとえば、X3 ハイブリッド プラットフォームでは、MAC インターフェイスを介して、QSFP ポートに到着するイーサネット パケットを AXI4-Stream に変換するイーサネット伝送および受信 IP が提供されます。さらに、NIC インターフェイスを使用すると、アクセラレータが PCIe を介して接続されたホスト CPU にデータを提供できます。または、PCIe を介してホスト CPU メモリへの直接アクセスにホスト メモリ アクセスを使用できます 。VSC を使用すると、アクセラレータ パケット プロセッシング パイプラインを PL 上で構成し、PCIe を介して CPU によって非同期的に制御できます。