SDS プラグマ

SDSoC での最適化

このセクションでは、システム最適化を支援するための SDSoC™ システム コンパイラ sdscc および sds++ のプラグマについて説明します。

SDSoC 環境システム コンパイラは、ベース プラットフォームをターゲットとし、Vivado® 高位合成 (HLS) ツールを起動して合成可能な C/C++ 関数をプログラマブル ロジックにコンパイルします。SDSoC IDE または sdscc/sds++ コマンド ライン オプションを使用して、ソース プログラムからハードウェアで実行する関数を選択し、アクセラレータおよびシステム クロックを指定して、データ転送のプロパティを設定します。

SDSoC 環境では、通信と計算のバランスが取られるようにハードウェア関数およびハードウェア関数への呼び出しを構成し、システム コンパイラに指示を与えるプラグマをソース コードに挿入することにより、システム生成プロセスを制御します。SDSoC コンパイラでは、データ転送に最適なシステム ポートが自動的に選択されますが、プラグマを使用してこの選択を変更することもできます。また、ハードウェア関数引数に異なるデータ ムーバーを選択するプラグマを指定したり、ハードウェア関数から転送またはハードウェア関数に転送されるデータ要素数をプラグマを使用して制御したりできます。

SDSoC 環境専用のすべてのプラグマには最初に #pragma SDS が付いており、C/C++ ソース コードの関数宣言の直前に挿入するか、特定の関数呼び出しを最適化するために関数呼び出しサイトに挿入する必要があります。

#pragma SDS data access_pattern(in_a:SEQENTIAL, out_b:SEQUENTIAL)
void f1(int in_a[20], int out_b[20]);

SDS プラグマには、次のタイプがあります。

表 1. SDS プラグマ (タイプ別)
タイプ プラグマ
データ アクセス パターン
データ転送サイズ
メモリの属性
データ ムーバーのタイプ
外部メモリへの SDSoC プラットフォーム インターフェイス
ハードウェア バッファーのワード数
関数の非同期実行
リソース バインドの指定
ハードウェア/ソフトウェアのトレース

pragma SDS async

説明

ASYNC プラグマは、ハードウェア関数の同期化の手動制御をサポートするため、WAIT プラグマと共に使用する必要があります。

ASYNC プラグマはハードウェア関数呼び出しの直前に指定し、データフロー解析に基づいて wait を自動的に生成しないようにコンパイラに指示します。WAIT プラグマは、プログラムの適切な位置に挿入し、関連付けられている同じ ID の ASYNC 関数呼び出しが完了するまで CPU が待機するよう指示します。

ASYNC プラグマを使用すると、SDSoC システム コンパイラで関連する呼び出しに対してスタブ関数内に sds_wait() は生成されません。プログラムには、CPU で実行されている制御スレッドとハードウェア関数スレッドを同期させるために sds_wait(ID) または #pragma SDS wait(ID) を適切な位置に含める必要があります。sds_wait(ID) 関数呼び出しの代わりに #pragma SDS wait(ID) を使用すると、gcc などの ASYNC または WAIT プラグマを解釈しない SDSoC コンパイラ以外のコンパイラでソース コードをコンパイルできるという利点があります。

構文

C ソースの関数呼び出しの直前に配置します。

#pragma SDS async(<ID>)
...
#pragma SDS wait(<ID>)
説明:
  • <ID>: ASYNC/WAIT ペアのユーザー定義 ID。コンパイル時の符号なし整数定数として指定します。

例 1

次の例では、このプラグマを異なる ID を使用して複数指定しています。

{
    #pragma SDS async(1)
    mmult(A, B, C);
    #pragma SDS async(2)
    mmult(D, E, F);
    ...
    #pragma SDS wait(1)
    #pragma SDS wait(2)
}

ハードウェアで実行されるプログラムは、まず AB を mmult ハードウェアに送信して、すぐに戻ります。次に DE を mmult ハードウェアに送信して、すぐに戻ります。#pragma SDS wait(1) まで実行されると、出力 C が準備できるまで待機します。#pragma SDS wait(2) まで実行されると、出力 F が準備できるまで待機します。

例 2

次のコード例では、同じ ID のプラグマを使用して、データ転送とアクセラレータの実行をパイプライン処理しています。

for (int i = 0; i < pipeline_depth; i++) {    
    #pragma SDS async(1)
    mmult_accel(A[i%NUM_MAT], B[i%NUM_MAT], C[i%NUM_MAT]);
}
for (int i = pipeline_depth; i < NUM_TESTS; i++) {
    #pragma SDS wait(1)
    #pragma SDS async(1)
    mmult_accel(A[i%NUM_MAT], B[i%NUM_MAT], C[i%NUM_MAT]);
}
for (int i = 0; i < pipeline_depth; i++) {
    #pragma SDS wait(1)
} 

上記の例では、最初のループにより深さ pipeline_depth でパイプラインを増加し、2 つ目のループでパイプラインを実行し、3 つ目のループでパイプラインを減少しています。ハードウェア バッファーの深さ (pragma SDS data buffer_depth を参照) は、pipeline_depth と同じ値に設定する必要があります。このパイプラインの目的は、現在の実行が進行中に、次の実行のためにデータをアクセラレータに転送することです。詳細は、SDSoC プロファイリングおよび最適化ガイド の「システムでの並列処理および同時処理の増加」を参照してください。

関連項目

pragma SDS data access_pattern

説明

このプラグマは、関数宣言の直前か、関数宣言に指定された別の #pragma SDS の直前に指定する必要があります。

このプラグマは、ハードウェア関数のデータ アクセス パターンを指定します。SDSoC コンパイラでこのプラグマの値が確認され、合成するハードウェア インターフェイスが決定されます。アクセス パターンに SEQUENTIAL が指定されている場合は、ap_fifo などのストリーミング インターフェイスが生成されます。RANDOM が指定されている場合は、RAM インターフェイスが生成されます。データ モーション ネットワーク生成におけるこのプラグマの使用に関する詳細は、『SDSoC 環境プロファイリングおよび最適化ガイド』 (UG1235) の「SDSoC でのデータ モーション ネットワークの生成」 を参照してください。

構文

このプラグマの構文は、次のとおりです。

#pragma SDS data access_pattern(ArrayName:<pattern>)

説明:

  • ArrayName: プラグマを設定する関数の仮引数のいずれかを指定します。
  • <pattern>: SEQUENTIAL または RANDOM のいずれかに指定できます。デフォルトは RANDOM です。

例 1

次のコード例では、配列引数 (A) に対してこのプラグマを使用しています。

#pragma SDS data access_pattern(A:SEQUENTIAL)
void foo(int A[1024], int B[1024]);

上記の例の場合、引数 A に対してストリーミング インターフェイスが、引数 B に対して RAM インターフェイスが生成されます。引数 A のアクセス パターンは A[0], A[1], A[2], ..., A[1023] のようにし、すべての要素が 1 回のみアクセスされるようにする必要があります。一方、引数 B はランダムにアクセスできるので、各要素は 0 回でも何回でもアクセスできます。

例 2

次のコード例では、ポインター引数に対してこのプラグマを使用しています。

#pragma SDS data access_pattern(A:SEQUENTIAL)
#pragma SDS data copy(A[0:1024])
void foo(int *A, int B[1024]);

上記の例では、引数 A がストリーミング ポートになる場合、これら 2 つのプラグマを適用する必要があります。これらのプラグマがないと、SDSoC ツールでは引数 A がレジスタ (関数 fooA がどのように使用されるかによって、IN、OUT、または INPUT) として合成されます。

例 3

次のコード例では、ZERO_COPY プラグマと ACCESS_PATTERN プラグマを組み合わせて使用しています。

#pragma SDS data zero_copy(A)
#pragma SDS data access_pattern(A:SEQUENTIAL)
void foo(int A[1024], int B[1024]);

上記の例では、ACCESS_PATTERN プラグマは無視されます。ZERO_COPY プラグマが引数に適用された後、AXI4 マスター インターフェイスがその引数に対して合成されます。詳細は、『SDSoC 環境プロファイリングおよび最適化ガイド』 (UG1235) の「zero_copy データ ムーバー」を参照してください。

関連項目

pragma SDS data buffer_depth

説明

このプラグマは、関数宣言の直前か、関数宣言に指定された別の #pragma SDS の直前に指定する必要があり、その関数の呼び出し元すべてに適用されます。

ブロック RAM または FIFO インターフェイスにマップされている配列にのみ適用されます。ブロック RAM にマップされている配列では、<BufferDepth> 値はハードウェア マルチバッファーの深さを指定します。FIFO にマップされている配列では、<BufferDepth> 値は配列に割り当てられているハードウェア FIFO の深さを指定します。このプラグマでは、次が満たされている必要があります。

  • ブロック RAM: 1 ≤ <BufferDepth> ≤ 4、および 2 ≤ ArraySize ≤ 16384。
  • FIFO: <BufferDepth> = 2n (4 ≤ n ≤ 20)。
ヒント: このプラグマを指定しない場合、デフォルトの <buffer_depth> は 1 です。

構文

このプラグマの構文は、次のとおりです。

#pragma SDS data buffer_depth(ArrayName:<BufferDepth>)

説明:

  • ArrayName: プラグマを設定する関数の仮引数のいずれかを指定します。
  • <BufferDepth>: コンパイル時定数値を指定する必要があります。
  • 1 つのプラグマで複数の配列をカンマで区切って指定できます。次に例を示します。
    #pragma SDS data buffer_depth(ArrayName1:BufferDepth1, ArrayName2:BufferDepth2)

例 1

次の例では、引数 a の RAM インターフェイスに使用されるサイズ 4 のマルチバッファーを指定しています。

#pragma SDS data buffer_depth(a:4)
void foo(int a[1024], b[1024);

関連項目

pragma SDS data copy

説明

pragma SDS data copy | zero_copy は、関数宣言の直前か、関数宣言に指定された別の #pragma SDS の直前に指定する必要があります。

重要: COPY プラグマおよび ZERO_COPY プラグマは、同じオブジェクトに同時に指定することはできません。

COPY プラグマを使用すると、データがホスト プロセッサ メモリからハードウェア関数にコピーされます。最適なデータ ムーバーによりデータ転送が実行されます。詳細は、SDSoC プロファイリングおよび最適化ガイド の「システム パフォーマンスの向上」を参照してください。

ZERO_COPY を使用すると、ハードウェア関数が AXI4 マスター バス インターフェイスを介して共有メモリからデータに直接アクセスします。

重要: SDSoC コンパイラでは、デフォルトでは配列引数に COPY プラグマが想定され、データがプロセッサからデータ ムーバーを介してアクセラレータにコピーされます。

構文

このプラグマの構文は、次のとおりです。

#pragma SDS data copy|zero_copy(ArrayName[<offset>:<length>])

説明:

  • ArrayName[<offset>:<length>]: プラグマを割り当てる関数パラメーターまたは引数と、配列の次元およびデータ転送サイズを指定します。
  • ArrayName: パラメーター名がオプションであるプロトタイプからではなく、関数定義からの仮引数のいずれかを指定する必要があります。
  • <offset>: 配列の最初の要素からの要素数を指定します (オプション)。コンパイル時定数として指定する必要があります。
    重要: <offset> 値は現在のところ無視されますが、0 に指定する必要があります。
  • <length>: 指定した次元に対して配列から転送する要素数を指定します。演算式が関数内で実行時に解決可能であれば、任意の演算式にできます。
    ヒント: 下の例に示すように、<length> は同じ関数のほかのスカラー引数を含む C 演算式にできます。
  • 多次元配列では、各次元を個別に指定する必要があります。たとえば、2 次元配列の場合は次を使用します。
    pragma SDS data copy(ArrayName[offset_dim1:length1][offset_dim2:length2])
  • 同じプラグマで複数の配列をカンマ (,) で区切って指定できます。次に例を示します。
    pragma SDS data copy(ArrayName1[offset1:length1], ArrayName2[offset2:length2])
  • [<offset>:<length>] はオプションで、配列のデータ転送サイズをコンパイル時に決定できない場合にのみ必要です。これを指定しない場合、COPY または ZERO_COPY プラグマは、データ ムーバーを介したメモリとアクセラレータ間のコピーか、アクセラレータからプロセッサ メモリへの直接アクセスかを選択するためにのみ使用されます。配列サイズを判断するため、SDSoC コンパイラでアクセラレータ関数の呼び出しコードが解析され、配列のメモリ割り当て API (malloc または sds_alloc など) に基づいて転送サイズが決定されます。この解析で判断できない場合、引数タイプがチェックされ、引数タイプにコンパイル時配列サイズが指定されていて、そのサイズがデータ転送サイズとして使用されているかどうかが確認されます。データ転送サイズを判断できない場合、コンパイラでエラー メッセージが表示され、[<offset_dim>:<length>] を使用してデータ サイズを指定できます。データ サイズが呼び出し元と呼び出し先で異なる場合や、複数の呼び出し元間で異なる場合にもコンパイラからエラー メッセージが表示されるので、ソース コードを修正するか、このプラグマを使用してコンパイラによる解析を無効にできます。

例 1

次の例では、関数宣言の直前に、COPY プラグマをアクセラレータ関数 foo の引数 A および B に適用しています。<length> オプションは size*size という式で指定されます。

#pragma SDS data copy(A[0:size*size], B[0:size*size])
void foo(int *A, int *B, int size);

SDSoC システム コンパイラにより、関数 foo の本体がアクセラレータ制御、データ転送、およびデータ同期コードに置き換えられます。次のコードに、データ転送部分を示します。

void _p0_foo_0(int *A, int *B, int size)
{
    ...
    cf_send_i(&(_p0_swinst_foo_0.A), A, (size*size) * 4, &_p0_request_0);
    cf_receive_i(&(_p0_swinst_foo_0.B), B, (size*size) * 4, &_p0_request_1);
    ...
}

オフセット値 size*size は、SDSoC に配列 A および B のランタイム時の要素数を通知するために使用されます。

ヒント: cf_send_i および cf_receive_i 関数には転送するバイト数を指定する必要があるので、コンパイラにより <length> で指定された要素数と各要素のバイト数 (この場合は 4) が乗算されます。

例 2

次のコード例では、上記の COPY プラグマの、代わりに ZERO_COPY プラグマを適用しています。

#pragma SDS data zero_copy(A[0:size*size], B[0:size*size])
void foo(int *A, int *B, int size);

関数 foo の本体は次のようになります。

void _p0_foo_0(int *A, int *B, int size)
{
    ...
    cf_send_ref_i(&(_p0_swinst_foo_0.A), A, (size*size) * 4, &_p0_request_0);
    cf_receive_ref_i(&(_p0_swinst_foo_0.B), B, (size*size) * 4, &_p0_request_1);
    ...
}

cf_send_ref_i および cf_receive_ref_i 関数は配列の参照またはポインターのみをアクセラレータに転送し、アクセラレータは直接メモリにアクセスします。

例 3

次の例では、複数の配列に ZERO_COPY プラグマを指定し、DDR を使用した直接メモリ インターフェイスとハードウェア関数を生成しています。

#pragma SDS data zero_copy(in1[0:mat_dim*mat_dim], in2[0:mat_dim*mat_dim], out[0:mat_dim*mat_dim])
void matmul_partition_accel(int *in1,  // Read-Only Matrix 1
                            int *in2,  // Read-Only Matrix 2
                            int *out,  // Output Result
                            int mat_dim); //  Matrix Dim (assumed only square matrix)

例 4

次の例では、DATA COPY プラグマにより、スタブ関数本体内の対応する送信/受信呼び出しに転送サイズ式が挿入されます。そのため、関数宣言で使用する引数名と関数定義で使用する引数名を一致させる要があります。次のコード例では、関数宣言に関数定義で使用されたのとは異なる引数名を使用するよくあるミスを示しています。

"foo.h"
#pragma SDS data copy(in_A[0:1024])
void foo(int *in_A, int *out_B);

"foo.cpp"
#include "foo.h"
void foo(int *A, int *B)
{
...
}

C/C++ 規格では関数宣言の引数名はオプションなので、C/C++ コンパイラで関数宣言の引数名が無視され、関数定義の引数名のみが使用されます。プラグマを適用しようとしたときに、SDSoC コンパイラにより警告メッセージが表示されます。

WARNING: [SDSoC 0-0] Cannot find argument in_A in accelerator function foo(int *A, int *B)

関連項目

pragma SDS data data_mover

説明

重要: このプラグマは、通常の使用にはお勧めしません。コンパイラで生成されるデータ ムーバーでデザイン要件が満たされない場合のみに使用してください。

このプラグマは、関数宣言の直前か、関数宣言に指定された別の #pragma SDS の直前に指定する必要があります。その関数の呼び出し元すべてに適用されます。

デフォルトでは、SDSoC コンパイラによりコードが解析され、データ型が自動的に選択されます。DATA_MOVER プラグマは、コンパイラでのデフォルトを無効にするために使用できます。このプラグマは、配列引数を転送するのに使用されるハードウェア IP タイプ (DataMover) を指定します。

FASTDMA データ ムーバーでは、データ転送に広帯域幅がサポートされます。Zynq® UltraScale+™ MPSoC では、データ幅は 64 ~ 256 ビットです。Zynq-7000 では、データ幅は 64 ビットです。

SDSoC™ コンパイラにより、対応する配列の転送に使用されるデータ ムーバー ハードウェア IP のインスタンスが自動的に割り当てられます。:id を指定すると、関連の仮引数に特定のデータ ムーバー インスタンスを割り当てることができます。3 つ以上の仮引数の DataMover および id が同じ場合、これらの仮関数で同じデータ ムーバー ハードウェア IP インスタンスが共有されます。

重要: AXIDMA_SIMPLE データ ムーバーを使用するには、対応する配列を sds_alloc() を使用して割り当てる必要があるという追加要件があります。

構文

このプラグマの構文は、次のとおりです。

#pragma SDS data data_mover(ArrayName:DataMover[:id])

説明:

  • ArrayName: プラグマを設定する関数の仮引数のいずれかを指定します。
  • DataMover: 次のいずれかです。
    • AXIFIFO: 300 バイト未満の非連続メモリに使用されます。
    • AXIDMA_SIMPLE: 32 MB 未満の連続メモリに使用されます。
    • AXIDMA_SG: 300 バイトを超える連続または非連続メモリに使用されます。
    • FASTDMA: 連続メモリのみ。FASTDMA を使用する場合はプラグマが必要です。
  • :id: オプション。正の整数値を指定します。
  • 1 つのプラグマで複数の配列をカンマ (,) で区切って指定できます。次に例を示します。
    #pragma SDS data data_mover(ArrayName1:DataMover[:id], ArrayName2:DataMover[:id])

例 1

次のコード例では、プラグマにデータ ムーバー ID を指定しています。

#pragma SDS data data_mover(A:AXIDMA_SG:1, B:AXIDMA_SG:1)
void foo(int A[1024], int B[1024]);

上記の例では、同じデータ ムーバー ID が指定されているため、同じ AXIDMA_SG IP インスタンスが共有されて、引数 A および B のデータが転送されます。

例 2

次の例では、FASTDMA データ ムーバーを使用しています。
#pragma SDS data data_mover(A:FASTDMA,B:FASTDMA,C:FASTDMA,D:AXIDMA_SIMPLE,E:AXIDMA_SIMPLE)
void foo(float A[1024], float B[1024], float C[1024], int D[1024], int E[1024]);
 

配列 A、B、および C は個別の FASTDMA データ ムーバーを使用して転送され、配列 D、E は個別の AXIDMA_SIMPLE データ ムーバーを使用して転送されます。

関連項目

pragma SDS data mem_attribute

説明

このプラグマは、関数宣言の直前か、関数宣言に指定された別の #pragma SDS の直前に指定する必要があります。その関数の呼び出し元すべてに適用されます。

仮想メモリをサポートする Linux のようなオペレーティング システムの場合、ユーザー空間の割り当てられたメモリがページ化されるために、システム パフォーマンスに影響が出ることがあります。SDSoC ランタイムには、物理的に隣接したメモリを割り当てるための API も含まれます。このセクションのプラグマを使用すると、コンパイラにその引数が物理的に隣接したメモリに割り当てらているかどうかを伝えることができます。

構文

このプラグマの構文は、次のとおりです。

#pragma SDS data mem_attribute(ArrayName:contiguity)

説明:

  • ArrayName: プラグマを設定する関数の仮引数のいずれかを指定します。
  • Contiguity: PHYSICAL_CONTIGUOUS または NON_PHYSICAL_CONTIGUOUS のいずれかを指定します。デフォルト値は NON_PHYSICAL_CONTIGUOUS です。
    • PHYSICAL_CONTIGUOUS: 関連付けられている ArrayName に対応するすべてのメモリが sds_alloc を使用して割り当てられています。
    • NON_PHYSICAL_CONTIGUOUS: 関連付けられている ArrayName に対応するすべてのメモリが malloc を使用して、またはスタックの自由変数として割り当てられています。これは、SDSoC コンパイラでの最適なデータ ムーバーの選択に有益です。
  • 1 つのプラグマで複数の配列をカンマ (,) で区切って指定できます。次に例を示します。
    #pragma SDS data mem_attribute(ArrayName:contiguity, ArrayName:contiguity)

例 1

次のコード例では、contiguity 属性を指定しています。

#pragma SDS data mem_attribute(A:PHYSICAL_CONTIGUOUS)
void foo(int A[1024], int B[1024]);

上記の例では、物理的に隣接したメモリ ブロックに配列 A を割り当てることを SDSoC コンパイラに伝える必要があります。AXI_DMA_Simple の方が小型で物理的に隣接したメモリを高速に転送できるので、SDSoC コンパイラで AXIDMA_SG の代わりに AXIDMA_SIMPLE が選択されます。

関連項目

pragma SDS data sys_port

説明

このプラグマは、関数宣言の直前か、関数宣言に指定された別の #pragma SDS の直前に指定する必要があり、その関数の呼び出し元すべてに適用されます。

このプラグマを使用すると、SDSoC コンパイラによるデフォルトのメモリ ポートとは異なるメモリ ポートを指定できます。配列引数に対して SYS_PORT プラグマを指定しない場合、配列のメモリ属性 (キャッシュ可能か不可能か)、配列サイズ、使用されるデータ ムーバーなどに基づいて、SDSoC システム コンパイラ (sdscc/sds++) により外部メモリへのインターフェイスが自動的に選択されます。

Zynq®-7000 デバイスでは、プログラマブル ロジックと外部メモリの間にキャッシュ コヒーレント インターフェイス (S_AXI_ACP)、非キャッシュ コヒーレント アクセス用にハイ パフォーマンス ポート (S_AXI_HP) を使用できます。Zynq® UltraScale+™ MPSoC では、キャッシュ コヒーレント インターフェイス (S_AXI_HPCn_FPD) と非キャッシュ コヒーレント インターフェイス (S_AXI_HPn_FPD) を使用できます。

構文

このプラグマの構文は、次のとおりです。
#pragma SDS data sys_port(<param_name>:<port>)

説明:

  • <param_name>: プラグマを設定する関数の仮引数のいずれかを指定します。
  • <port>: SDSoC コンパイラでは、定義済みメモリ ポート タイプである ACP (キャッシュ コヒーレント アクセス、Zynq-7000 デバイスのみ)、HPC (キャッシュ コヒーレント アクセス)、HP (高速非コヒーレント アクセス)、および MIG (PL ロジックにインプリメントされるソフト メモリ コントローラーを介してアクセス可能なメモリ) が認識されます。<port> に特定のプラットフォーム ポート名を使用することもできますが、コンパイラで正しいポートが認識されない場合以外はお勧めしません。この状況は、プラットフォームのストリーム ポートで発生することがあります。プラットフォーム ポートのリストを取得するには、ターミナル シェルで sds++ -sds-pf-info <platform> を実行します。

    たとえば、sds++ -sds-pfm-info zcu102 コマンドを実行すると、「System Ports」の下に次が返されます。

    System Ports
    
    Use the system port name in a sysport pragma, for example 
    #pragma SDS data sys_port(parameter_name:system_port_name)
     
    System Port Name (Vivado BD instance name, Vivado BD port name)
    ps_e_S_AXI_HPC0_FPD (ps_e, S_AXI_HPC0_FPD)
    ps_e_S_AXI_HPC1_FPD (ps_e, S_AXI_HPC1_FPD)
    ps_e_S_AXI_HP0_FPD (ps_e, S_AXI_HP0_FPD)
    ps_e_S_AXI_HP1_FPD (ps_e, S_AXI_HP1_FPD)
    ps_e_S_AXI_HP2_FPD (ps_e, S_AXI_HP2_FPD)
    ps_e_S_AXI_HP3_FPD (ps_e, S_AXI_HP3_FPD)
    
    
    この場合、SYS_PORT プラグマは次のように定義できます。
    #pragma SDS data sys_port(Array1:ps_e_S_AXI_HPC0_FPD)

    <port> が HPC の略称を使用して定義されている場合、SDSoC コンパイラにより引数 Array1 は HPC0 または HPC1 に設定されます。

    プラットフォームを作成する際、特定のプラットフォーム ポートの略称は PFM.AXI_PORT プロパティを使用して指定できます。PFM プロパティの詳細は、SDSoC 環境プラットフォーム開発ガイド を参照してください。次に例を示します。
    set_property PFM.AXI_PORT {M_AXIS {type "M_AXIS" sptag "Counter"}} \
    [get_bd_cells /stream_fifo]
    この例では SYS_PORT タグを「Counter」と定義しており、これはプラグマで次のように指定できます。
    #pragma SDS data sys_port(Array1:Counter)
    
    これは、次のように宣言するのと同じです。
    #pragma SDS data sys_port(Array1:stream_fifo_M_AXIS)
    
  • 1 つのプラグマで複数の引数をカンマ (,) で区切って指定できます。
    #pragma SDS data sys_port(param1:port, param2:port)

例 1

次に、このプラグマの使用例を示します。

#pragma SDS data sys_port(A:HP)
void foo(int A[1024], int B[1024]);

上記の例では、呼び出し元が malloc または sds_alloc などのキャッシュ コヒーレント呼び出しで割り当てられた配列 (A) を渡すと、SDSoC コンパイラではそれが最適でなくても HP プラットフォーム インターフェイスが使用されます。

関連項目

pragma SDS resource

説明

このプラグマは、手動でリソース バインドを指定するために関数呼び出しサイトに使用できます。

RESOURCE プラグマはハードウェア関数呼び出しの直前に指定し、呼び出し元を指定したアクセラレータ インスタンスにバインドするようにコンパイラに指示します。SDSoC コンパイラは、関数に複数のリソース ID が指定されている状況を特定し、プログラマブル ロジックにハードウェア関数を実現するハードウェア アクセラレータとデータ モーション ネットワークを自動的に生成します。

構文

このプラグマの構文は、次のとおりです。
#pragma SDS resource(<ID>)

説明:

  • <ID>: コンパイル時符号なし整数定数を指定する必要があります。同じ関数の場合は、独自の ID それぞれでハードウェア アクセラレータの各インスタンスを示します。

例 1

次のコードは、異なる ID を使用したこのプラグマの例です。

{
    #pragma SDS resource(1)
    mmult(A, B, C);
    #pragma SDS resource(2)
    mmult(D, E, F);
    ...
}

上記の例の場合、関数 mmult への最初の呼び出しが ID 1 のアクセラレータにバインドされ、mmult への 2 つ目の呼び出しが ID 2 のアクセラレータにバインドされます。

関連項目

pragma SDS trace

説明

SDSoC 環境のトレース機能は、ハードウェア/ソフトウェア イベントのトレースを使用して、アプリケーションの実行中にシステムで何が発生しているのかを詳細に表示します。詳細は、SDSoC 環境ユーザー ガイド を参照してください。

このプラグマは、アクセラレータのトレース挿入を関数レベルまたは引数レベルで指定し、デバッグの目的でアクセラレータのアクティビティを監視できるようにします。トレースがイネーブルの場合、ソフトウェア コードにトレース インストルメンテーションが自動的に挿入され、ハードウェア ロジックのインプリメンテーション中にハードウェア システムにハードウェア モニターが挿入されます。アクセラレータ関数または関数の個々のパラメーターを監視できます。

トレースのタイプは、SWHW、またはその両方に指定できます。HWトレースは、ハードウェア アクセラレータの開始と停止、指定した引数のデータ転送の開始および停止など、該当するハードウェア コンポーネントの開始と停止を意味します。これにより、ハードウェアに入るアクティビティおよびハードウェアから出るアクティビティを監視できます。SW トレースは、ハードウェア アクセラレーションされる関数のソフトウェア スタブを監視し、トランザクションのソフトウェア側の関数および引数を監視できるようにします。ハードウェアおよびソフトウェア トランザクションの両方を監視することも可能です。

構文

このプラグマは、関数宣言の直前か、関数宣言に指定された別の #pragma SDS の直前に指定する必要があります。

#pragma SDS trace(<var1>[:SW|:HW][,<var2>[:SW|:HW]])

説明:

  • <var>: 関数名または関数のパラメーターの 1 つを指定します。
  • [:SW|:HW]: HW トレースまたは SW トレースのいずれかを指定します。このオプションを指定しない場合、HW および SW トレースの両方が挿入されます。

例 1

次の例では、関数 foo をトレースしています。

#pragma SDS monitor trace(foo)
void foo(int a, int b);
ヒント: :HW または :SW が指定されていないので、アクセラレータに両方のトレースが挿入されます。

例 2

次の例では、このプラグマを使用して関数の複数の引数をトレースしています。

#pragma SDS monitor trace(a, b:SW, c:HW)
void foo(int a, int b, int *c);

上記の例では、引数 a に対して HW トレースと SW トレースの両方が挿入されます。引数 bSW トレースのみが挿入されます。引数 c の場合は HW トレースのみが挿入されます。

関連項目

pragma SDS wait

説明

ヒント: 詳細は、ASYNC プラグマを参照してください。

WAIT プラグマは、ハードウェア関数の同期化の手動制御をサポートするため、ASYNC プラグマと共に使用する必要があります。

ASYNC プラグマはハードウェア関数呼び出しの直前に指定し、データフロー解析に基づいて wait を自動的に生成しないようにコンパイラに指示します。WAIT プラグマは、プログラムの適切な位置に挿入し、関連付けられている同じ ID の ASYNC 関数呼び出しが完了するまで CPU が待機するよう指示します。

関連項目

pragma SDS data zero_copy

説明

ヒント: ZERO_COPY プラグマの詳細は、pragma SDS data copy を参照してください。

COPY プラグマを使用すると、ホスト プロセッサ メモリとハードウェア関数の間で転送に適切なデータ ムーバーを使用してデータが明示的にコピーされます。ZERO_COPY を使用すると、ハードウェア関数が AXI4 マスター バス インターフェイスを介して共有メモリからデータに直接アクセスします。

重要: COPY プラグマおよび ZERO_COPY プラグマは、同じオブジェクトに同時に指定することはできません。

例 1

次の例では、複数の配列に ZERO_COPY プラグマを指定し、DDR を使用した直接メモリ インターフェイスとハードウェア関数を生成しています。

#pragma SDS data zero_copy(in1[0:mat_dim*mat_dim], in2[0:mat_dim*mat_dim], out[0:mat_dim*mat_dim])
void matmul_partition_accel(int *in1,  // Read-Only Matrix 1
                            int *in2,  // Read-Only Matrix 2
                            int *out,  // Output Result
                            int mat_dim); //  Matrix Dim (assumed only square matrix) 
重要: ZERO_COPY データ ムーバーに渡す配列引数は、物理的に連続している必要があります。malloc で割り当てられたバッファーを ZERO_COPY データ ムーバーに渡すと、動作が未定義になります。

関連項目

  • 『SDSoC 環境プロファイリングおよび最適化ガイド』 (UG1235)