AXI4 メモリ マップド (m_axi
) インターフェイスを使用すると、カーネルがグローバルメモリ (DDR、HBM、PLRAM) 内のデータを読み出しおよび書き込みできます。メモリ マップド インターフェイスは、ホストとカーネル間、またはアクセラレータ カード上のカーネル間など、アクセラレーション アプリケーションのさまざまな要素間でデータを共有する便利な方法です。これらのコンセプトのいくつかの例については、GitHub の Vitis-HLS-Introductory-Examples/Interface/Memory を参照してください。
m_axi
インターフェイスの主な利点は、次のとおりです。
- 独立した個別の読み出しチャネルおよび書き込みチャネルを持ちます。
- バースト ベースのアクセスをサポートし、最大約 ~17 GB/s のパフォーマンスを実現します。
- 未処理のトランザクションをサポートします。
- CACHE プラグマや指示子で説明したように、キャッシュを含めると、パフォーマンスを向上できます。
Vitis カーネル フローでは、m_axi
インターフェイスはデフォルトでポインターおよび配列引数に割り当てられます。このフローでは、次のデフォルト機能がサポートされます。
- ポインターおよび配列引数は、自動的に
m_axi
インターフェイスにマップされます。 -
Vitis フローでは、デフォルトの動作モードは
offset=slave
offset=slave であり、変更すべきではありません。 - すべてのポインターおよび配列引数は、デバイス リソースを節約するため 1 つのインターフェイス バンドルにマップされ、ポートがアクティブな間、読み出しおよび書き込みアクセスを共有します。
- Vitis フローのデフォルト アライメントは、64 バイトに設定されます。
- 最大読み出し/書き込みバースト長は、デフォルトで 16 に設定されます。
Vivado IP フローではデフォルトでは使用されませんが、m_axi
インターフェイスを指定した場合、次のデフォルト機能があります。
- デフォルトの動作モードは offset=off ですが、オフセットと動作モード に説明されているように変更できます。
- 割り当てられたポインターおよび配列引数は、デバイス リソースを節約するため 1 つのインターフェイス バンドルにマップされ、アクティブな間、インターフェイスが共有されます。
- Vivado IP フローのデフォルト アライメントは、1 バイトに設定されます。
- 最大読み出し/書き込みバースト長は、デフォルトで 16 に設定されます。
Vivado IP フローと Vitis カーネルフ ローの両方で、m_axi
インターフェイスのグローバル デフォルト値は syn.interface.xxx
コマンドで定義されます (インターフェイス コンフィギュレーション を参照)。INTERFACE プラグマや指示子を使用すると、特定のインターフェイスのデフォルト値を必要に応じて変更できます。AXI システム パフォーマンスの最適化 で説明するように、カスタマイズによっては、デザイン パフォーマンスを向上できます。pragma HLS cache で説明されるように CACHE プラグマまたは指示子を追加して、m_axi
インターフェイスのパフォーマンスを向上させることもできます。
AXI4 マスター インターフェイスは配列またはポインター/リファレンス引数で使用でき、Vitis HLS では次のいずれかのモードでインプリメントされます。
- 個別のデータ転送
- バースト モードのデータ転送
個別のデータ転送では、Vitis HLS で各アドレスのデータの 1 つの要素が読み出されるか書き込まれます。次の例に、1 つの読み出しおよび 1 つの書き込み操作を示します。Vitis HLS で AXI インターフェイスにアドレスが生成され、1 つのデータ値とアドレスが読み出され、1 つのデータ値が書き込まれます。インターフェイスは、アドレスごとに 1 つのデータ値を転送します。
void bus (int *d) {
static int acc = 0;
acc += *d;
*d = acc;
}
バースト モード転送では、Vitis HLS で 1 つのベース アドレスを使用してデータが読み出しまたは書き込みされ、その後に複数のシーケンシャル データ サンプルが続くので、より高いデータ スループットを達成できます。バースト モードでの動作は、パイプライン処理された for
ループを使用すると可能になります。詳細は、AXI バースト転送 を参照してください。
memcpy
の使用はお勧めしません。引数の型が char
に変更されることで、array_partition
、array_reshape
、または構造体 disaggregate
が使用される場合にエラーが発生するという問題が発生することもあるからです。このため、明示的な配列とループを使って独自のバージョンの memcpy
を記述して、より制御ができるようにします。前の例が合成されると、次の図のようなインターフェイスになります。
バースト読み出しまたは書き込みをインプリメントするのに for
ループを使用する場合は、次の要件に従ってさい。
- ループをパイプライン処理する
- 昇順でアドレスにアクセスする
- 条件文内にアクセスを記述しない
- 入れ子状態のループの場合、バースト動作が抑制されてしまわないよう、LOOP_FLATTEN プラグマまたは指示子を使用して手動でループを平坦にしないようにしてください。
for
ループ内で使用できるのは読み出し 1 つと書き込み 1 つのみです。