Vitis では、ソース コードに VPP_ACC
クラスから派生したクラスが含まれる場合、ハードウェアおよびホスト コードのコンパイル用に VSC がイネーブルになります。VPP_ACC
から派生したクラスは、アクセラレータとしてコンパイルされます。
シングル ソースの C++ モデルでは、VSC アクセラレータ インターフェイスは、C++ ヘッダー ファイルで必要なクラス定義として定義されます。複数のアクセラレータ クラス定義は、1 つのコンパイル ユニット内で (1 つの v++ --compile
コマンドとして) 見つけることができます。これらはすべて同じ PL ハードウェアにインプリメントされます。また、複数のコンパイル ユニットで複数のアクセラレータを提供することもできます。ただし、各コンパイル ユニットがそのユニット用の完全なカーネル (または HLS) コードを定義する必要があります。
すべてのユーザー定義のアクセラレータ クラスは、次の条件に従っている必要があります。
-
Vitis の定義済みの
VPP_ACC
クラスから派生する必要があります。 -
compute()
というスタティック メソッドが必要です。 -
compute()
の引数と機能は、ユーザーが定義できます。 - クラステ ンプレートには、次の 2 つの引数があります。
- 1 つ目の引数は、ユーザー定義のクラス名と同じである必要があります。
- 2 つ目の引数は、ハードウェアで複製される計算ユニット数です。
次に、アクセラレータ クラス定義 (xmmult
) の例を示します。
#include "vpp_acc.hpp"
class xmmult : VPP_ACC<xmmult, /*NCU=*/4>
{
public:
// Platform port connections
SYS_PORT(A, DDR[0]);
SYS_PORT(B, DDR[1]);
SYS_PORT(C, DDR[2]);
SYS_PORT_PFM(u50, A, (HBM[0]:HBM[4]:HBM[8]:HBM[12]));
SYS_PORT_PFM(u50, B, (HBM[1]:HBM[5]:HBM[9]:HBM[13]));
SYS_PORT_PFM(u50, C, (HBM[2]:HBM[6]:HBM[10]:HBM[14]));
// Data interfaces
ACCESS_PATTERN(A, SEQUENTIAL);
ACCESS_PATTERN(B, RANDOM);
DATA_COPY(A, A[SZ]); // move to local memory
DATA_COPY(B, B[SZ]);
ZERO_COPY(C); // direct AXI-mm
// define the SW entry point of the accelerator
static void compute(data_t* A, data_t* B, data_t* C);
// define the HW top-level of the accelerator (HLS top)
static void mmult(data_t* A, data_t* B, data_t* C);
};
このクラス インターフェイス モデルは、単一の統合ソースでハードウェア システム関連のすべての考慮事項を組み込んでいるので、compute()
関数を使用してアプリケーション層と簡単に統合できるようになっています (compute() API を参照)。compute()
関数は、ハードウェア アクセラレータへのホスト アプリケーションのエントリ ポイントです。
このクラス定義には、compute()
引数を参照するガイダンス マクロも含まれます。これらを使用することで、インプリメンテーション時に VSC で特定のハードウェアを選択できるようになります。詳細は、ガイダンス マクロ を参照してください。
上記の例では、VSC でハードウェアに 4 つの CU (/*NCU=*/4
) が含まれるようにコンパイルされる xmmult
というアクセラレータ クラスを示しています。アクセラレータには、mmult()
関数内で定義される PE (またはカーネル) コードがあります。このコードは、3 つの引数 A、B、および C を取り込む compute()
内で呼び出されます。これらの引数ごとに、メモリ ポート接続とデータ アクセスの 2 種類のガイダンス マクロが指定されています。
-
SYS_PORT()
とSYS_PORT_PFM()
マクロを使用したプラットフォーム ポート接続。- これらは通常、Vitis でコンパイル時に使用されるハードウェア プラットフォームで使用可能なグローバル メモリ I/O 接続またはその他の AXI4 インターフェイス接続です。この例では、最初の 3 つの
SYS_PORT()
マクロが、compute()
の 3 つの引数 (A、B、C) を異なる DDR バンク (0、1、2) に接続します。ヒント: 各引数のSYS_PORT()
ガイダンス マクロ接続は、1 つのメモリ バンクしか指定しないため、xmmult
アクセラレータ内のすべての CU インスタンス (NCU=4) に適用されます。 - この 3 つの
SYS_PORT_PFM()
マクロは、グローバル メモリ接続を次の 2 つの方法で適用します。- U50 Alveo カードのように、ターゲット プラットフォーム名に u50 が含まれている場合にのみ適用されます。
- 4 つの各 CU ごとに、各引数が異なる HBM バンクに接続されます。これは、各引数の
SYS_PORT_PFM()
に使用される構文で接続が 4 回指定されるためです。SYS_PORT_PFM(u50, A, (HBM[0]:HBM[4]:HBM[8]:HBM[12]));
- これらは通常、Vitis でコンパイル時に使用されるハードウェア プラットフォームで使用可能なグローバル メモリ I/O 接続またはその他の AXI4 インターフェイス接続です。この例では、最初の 3 つの
- データ アクセスは、
ACCESS_PATTERN()
、DATA_COPY()
、ZERO_COPY()
マクロを使用して指定します。-
ACCESS_PATTERN()
マクロは、VSC にデータ転送のためのシーケンシャル アクセスまたはランダム アクセスを推論するよう指示します。この例では、引数 A はシーケンシャル アクセスとして定義されているため、ストリーム接続を使用してインプリメントできます。引数 B はランダムにアクセスされるため、PEmmult()
からのランダム データ アクセスをサポートするローカル (オンチップ) メモリ バッファーが必要です。 - 引数 A および B の場合、
DATA_COPY()
マクロが VSC にアクセラレータの横にローカル メモリ (RAM) を推論するように指示します。 -
ZERO_COPY()
マクロは、VSC に引数 C のメモリ マップド AXI (M_AXI) 接続を作成するよう指示します。
-