ウィンドウおよびストリーミング データ API

データフロー グラフのカーネルは、データ ストリーム (型付き値の無限長シーケンス) に対して処理を実行します。これらのデータ ストリームは個々のブロックに分割でき、これらのブロックをカーネルによって処理します。カーネルは、入力データ ブロックを消費し、出力データ ブロックを生成します。また、カーネルはサンプル単位でデータ ストリームにアクセスできます。この章では、これら 2 つの場合のデータ アクセス API について説明します。

注記: この章で説明するデータ移動 API は、ベクターとスカラーの符号付きおよび符号なしデータに適用されます。ただし、AI エンジン アーキテクチャでは、8 ビット データ型 v16uint8, v32uint8, v64uint8, v128uint8 には符号なし整数ベクター演算のみがサポートされます。スカラー演算には、すべての標準 C 符号なし整数型 unsigned char(uint8), unsigned short(uint16), unsigned int(uint32), unsigned long long(uint64) がサポートされます。

データ アクセスのメカニズム

ウィンドウ ベースのアクセス

カーネルの入力データ ブロック ビューは、入力ウィンドウと呼ばれます。入力ウィンドウは、タイプ (そのウィンドウ内に格納されるデータ型の定義) によって定義されます。この例は、実数部と虚数部がいずれも 16 ビット幅の複素整数を格納する入力ウィンドウの宣言を示しています。

input_window_cint16 myFirstWindow;

カーネルの出力データ ブロック ビューは、出力ウィンドウと呼ばれます。これらのウィンドウもタイプによって定義されます。この例は、32 ビット整数を格納する出力ウィンドウの宣言を示しています。

output_window_int32 myOtherWindow;

これらのウィンドウ データ構造は、AI エンジン コンパイラによってデータフロー グラフの接続から自動的に推論され、グラフ制御を実装するラッパー コード内で自動的に宣言されます。カーネル関数は、カーネル関数に引数として渡されるウィンドウ データ構造を指すポインターを処理します。データフロー グラフまたはカーネル プログラム内でこれらのウィンドウ データ構造を宣言する必要はありません。

同期ウィンドウ アクセス

カーネルは、入力ウィンドウからデータを読み出し、出力ウィンドウにデータを書き込みます。デフォルトでは、データの入力ウィンドウを待機するのに必要な同期または空の出力ウィンドウを準備するのに必要な同期は、カーネルに入る前に実行されます。カーネルの開始後は、データの個々の要素の読み出しまたは書き込みのためのカーネル内での同期は必要はありません。

ウィンドウのサイズ (バイト単位) は、次に示すように、プロデューサー ポートとコンシューマー ポート間の接続と共に宣言します (詳細は 接続 を参照)。これにより、ポート in とカーネルの最初の入力ポートの間に 128 バイトのウィンドウ接続が確立されます。

connect< window<128> > net0 (in, first.in[0]);

オプションの 2 番目のテンプレート パラメーターは、次に示すように、1 つのデータ ブロックから次のデータ ブロックへのオーバーラップ (マージンとも呼ばれる) をバイト単位で指定します。マージン パラメーターを指定した場合、割り当てられるメモリはウィンドウ サイズとマージン サイズの合計になります。

connect< window<128, 32> net1 (in, first.in[0]);

これらのウィンドウは、順次アクセスされるよう設計されています。カーネル プログラミングはウィンドウのタイプを読み出し、最初の位置から開始します。そのため、読み出しまたは書き込みの際に書き込み位置を前または後ろに移動させることができる現在位置を使用するモデルが便利です。カーネルの開始時に、現在位置は常に適切な位置になります。たとえば、フィルター用の入力ウィンドウの現在位置は、遅延ラインに復元される最初のサンプルになります。入力されるデータ サンプルのオーバーラップを必要とするフィルターの場合、現在位置が古いサンプルになることがあります。この場合、上記のオーバーラップまたはマージンを使用して接続を宣言する必要があります。同様に、出力ウィンドウの現在位置は、次のブロックが古いサンプルの重複を必要とするかどうかにかかわらず、次のブロックに送信される最初のサンプルになります。この現在位置はカーネルで自由に操作でき、カーネルの完了時にこの位置がブロックの最後になる必要はありません。ウィンドウ データ型は循環バッファーとしてインプリメントされます。

注記: ウィンドウ割り当ての最小サイズは 16 バイトです。ウィンドウ サイズの割り当ては、16 バイトの倍数に丸められます。マージン オーバーラップの最小サイズは 32 ビットで、32 ビットの倍数である必要があります。
注記: マルチキャスト通信では、すべてのレシーバーが同じサイズである必要があります。次に例を示します。
connect< window<128> > net0 (in, first.in[0]);
connect< window<128> > net1 (in, second.in[0]);

非同期ウィンドウ アクセス

カーネルを呼び出すたびに 1 つのウィンドウ分のデータを消費するわけではない場合や、カーネルを呼び出すたびに 1 つのウィンドウ分のデータを生成するわけではない場合、次に示すように、カーネル ポートが async になるように宣言することにより、バッファーの同期を制御できます。

 connect< window<128, 32> net1 (in, async(first.in[0])); 

この宣言は、カーネルの入口でウィンドウ バッファーの同期を省略するようにコンパイラに指示します。次に示すように、読み出し/書き込み API を使用してウィンドウにアクセスする前に、カーネル コード内 に示されるウィンドウ同期 API を使用する必要があります。

void super_kernel(input_window_int32 * data, output_window_int32 * result) {
  ...
  window_acquire(data);     // acquire input window unconditionally inside the kernel
  if (<somecondition>) {
    window_acquire(result); // acquire output window conditionally 
  }
  ...                       // do some computation with "data" and "result"
  window_release(data);     // release input window inside the kernel
  if (<somecondition>) {  
    window_release(result); // release output window conditionally
  }
  ...
};

window_acquire API は、適切な同期と初期化を実行し、ウィンドウ オブジェクトを読み出しまたは書き込みに利用できるようにします。この API は、ウィンドウが複数の AI エンジン プロセッサ間で共有されており、ダブル バッファリングできる場合でも、内部で取得される適切なバッファー ポインターおよびロックを追跡します。この API は、動的制御下で無条件または条件付きで呼び出すことができ、ブロッキング動作になる可能性があります。この API に対応する window_release API が少し後に (おそらく次のカーネル呼び出し中に) 実行され、そのウィンドウ オブジェクトに関連するロックが解放されるようにするのは、ユーザーの役割です。同期が適切でない場合、コード内でデッドロックが発生することがあります。

ストリーム ベースのアクセス

ストリーム ベースのアクセス モデルでは、カーネルは型付きデータの入力ストリームまたは出力ストリームを引数として受け取ります。これらのストリームへの各アクセスは同期されます。すなわち、ストリーム内でデータが利用可能でない場合は読み出しはストールし、ストリームが新しいデータを受け入れることができない場合は書き込みはストールします。

AI エンジンは、id=0 または 1 の 2 つの 32 ビット入力ストリーム ポートをサポートし、id=0 または 1 の 2 つの 32 ビット出力ストリーム ポートをサポートします。この ID はストリーム オブジェクト コンストラクターに引数として与えられます。AI エンジン コンパイラは、入力および出力ストリーム ポートの ID をカーネルの引数リスト内で左から右に自動的に割り当てます。パケット交換ストリームの場合を除いて、同じ AI エンジンにマップされる複数のカーネルがストリーム ポートを共有することはできません (明示的パケット スイッチング 参照)。

1 つの AI エンジンのアキュムレータ レジスタと物理的に隣接するコアの間には、カスケードと呼ばれる直接ストリーム通信チャネルがあります。カスケード ストリームは、AI エンジン アレイ内で AI エンジン プロセッサからプロセッサへ蛇行して接続されます。

ストリーム データ構造は、AI エンジン コンパイラによってデータフロー グラフの接続から自動的に推論され、グラフ制御を実装するラッパー コード内で自動的に宣言されます。カーネル関数は、カーネル関数に引数として渡されるストリーム データ構造を指すポインターを処理します。データフロー グラフまたはカーネル プログラム内でこれらのストリーム データ構造を宣言する必要はありません。

カーネルのウィンドウ操作

ウィンドウのデータ型

表 1. サポートされるウィンドウのデータ型
入力ウィンドウのデータ型 出力ウィンドウのデータ型
input_window_int8 output_window_int8
input_window_int16 output_window_int16
input_window_int32 output_window_int32
input_window_int64 output_window_int64
input_window_uint8 output_window_uint8
input_window_uint16 output_window_uint16
input_window_uint32 output_window_uint32
input_window_uint64 output_window_uint64
input_window_cint16 output_window_cint16
input_window_cint32 output_window_cint32
input_window_float output_window_float
input_window_cfloat output_window_cfloat

現在の読み出し/書き込み位置の前進

次の説明では、<input_window_type> は許容される入力ウィンドウのデータ型を表します。同様に、<output_window_type> は許容される出力ウィンドウのデータ型を表します。

現在の読み出し/書き込み位置を、基になるウィンドウ データ型の count 値分増加するには、次のコードを使用します。

void window_incr(<input_window_type> *w, int count);
void window_incr(<output_window_type> *w, int count);

現在の読み出し/書き込み位置を、基になるウィンドウ データ型の count 値の 4 倍増加するには、次のコードを使用します。

void window_incr_v4(<input_window_type> *w, int count);
void window_incr_v4(<output_window_type> *w, int count);

現在の読み出し/書き込み位置を、基になるウィンドウ データ型の count 値の 8 倍増加するには、次のコードを使用します。

void window_incr_v8(<input_window_type> *w, int count);
void window_incr_v8(<output_window_type> *w, int count);

現在の読み出し/書き込み位置を、基になるウィンドウ データ型の count 値の 16 倍増加するには、次のコードを使用します。

void window_incr_v16(<input_window_type> *w, int count);
void window_incr_v16(<output_window_type> *w, int count);

現在の読み出し/書き込み位置を、基になるウィンドウ データ型の count 値の 32 倍増加するには、次のコードを使用します。

void window_incr_v32(<input_window_type> *w, int count);
void window_incr_v32(<output_window_type> *w, int count);

現在の読み出し/書き込み位置を、基になるウィンドウ データ型の count 値の 64 倍増加するには、次のコードを使用します。

void window_incr_v64(<input_window_type> *w, int count);
void window_incr_v64(<output_window_type> *w, int count);

現在の読み出し/書き込み位置の後進

次の説明では、<input_window_type> は許容される入力ウィンドウのデータ型を表します。同様に、<output_window_type> は許容される出力ウィンドウのデータ型を表します。

現在の読み出し/書き込み位置を、基になるウィンドウ データ型の count 値分減少するには、次のコードを使用します。

void window_decr(<input_window_type> *w, int count);
void window_decr(<output_window_type> *w, int count);

現在の読み出し/書き込み位置を、基になるウィンドウ データ型の count 値の 4 倍減少するには、次のコードを使用します。

void window_decr_v4(<input_window_type> *w, int count);
void window_decr_v4(<output_window_type> *w, int count);

現在の読み出し/書き込み位置を、基になるウィンドウ データ型の count 値の 8 倍減少するには、次のコードを使用します。

void window_decr_v8(<input_window_type> *w, int count);
void window_decr_v8(<output_window_type> *w, int count);

現在の読み出し/書き込み位置を、基になるウィンドウ データ型の count 値の 16 倍減少するには、次のコードを使用します。

void window_decr_v16(<input_window_type> *w, int count);
void window_decr_v16(<output_window_type> *w, int count);

現在の読み出し/書き込み位置を、基になるウィンドウ データ型の count 値の 32 倍減少するには、次のコードを使用します。

void window_decr_v32(<input_window_type> *w, int count);
void window_decr_v32(<output_window_type> *w, int count);

現在の読み出し/書き込み位置を、基になるウィンドウ データ型の count 値の 64 倍減少するには、次のコードを使用します。

void window_decr_v64(<input_window_type> *w, int count);
void window_decr_v64(<output_window_type> *w, int count);

入力ウィンドウからのデータの読み出し

次のコードは、スカラー型の値を同じ型の入力ウィンドウから読み出します。現在位置は変更されません。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。

int8 window_read(input_window_int8 *w);
int16 window_read(input_window_int16 *w);
int32 window_read(input_window_int32 *w);
int64 window_read(input_window_int64 *w);
uint8 window_read(input_window_uint8 *w);
uint16 window_read(input_window_uint16 *w);
uint32 window_read(input_window_uint32 *w);
uint64 window_read(input_window_uint64 *w);
cint16 window_read(input_window_cint16 *w);
cint32 window_read(input_window_cint32 *w);
float window_read(input_window_float *w);
cfloat window_read(input_window_cfloat *w);

void window_read(input_window_int8 *w, int8 &v );
void window_read(input_window_int16 *w, int16 &v );
void window_read(input_window_int32 *w, int32 &v );
void window_read(input_window_int64 *w, int64 &v );
void window_read(input_window_uint8 *w, uint8 &v );
void window_read(input_window_uint16 *w, uint16 &v );
void window_read(input_window_uint32 *w, uint32 &v );
void window_read(input_window_uint64 *w, uint64 &v );
void window_read(input_window_cint16 *w, cint16 &v);
void window_read(input_window_cint32 *w, cint32 &v);
void window_read(input_window_float *w, float &v);
void window_read(input_window_cfloat *w, cfloat &v);

次のコードは、4 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出します。現在位置は変更されません。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v4cint16 window_read_v4(input_window_cint16 *w);
v4int32 window_read_v4(input_window_int32 *w);
v4cint32 window_read_v4(input_window_cint32 *w);
v4int64 window_read_v4(input_window_int64 *w);
v4float window_read_v4(input_window_float *w);
v4cfloat window_read_v4(input_window_cfloat *w);

void window_read(input_window_cint16 *w, v4cint16 &v);
void window_read(input_window_int32 *w, v4int32 &v);
void window_read(input_window_cint32 *w, v4cint32 &v);
void window_read(input_window_int64 *w, v4int64 &v);
void window_read(input_window_float *w, v4float &v);
void window_read(input_window_cfloat *w, v4cfloat &v);

次のコードは、8 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出します。現在位置は変更されません。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v8int16 window_read_v8(input_window_int16 *w);
v8cint16 window_read_v8(input_window_cint16 *w);
v8int32 window_read_v8(input_window_int32 *w);
v8float window_read_v8(input_window_float *w);

void window_read(input_window_int16 *w, v8int16 &v);
void window_read(input_window_cint16 *w, v8cint16 &v);
void window_read(input_window_int32 *w, v8int32 &v);
void window_read(input_window_float *w, v8float &v);

次のコードは、16 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出します。現在位置は変更されません。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v16int8 window_read_v16(input_window_int8 *w);
v16uint8 window_read_v16(input_window_uint8 *w);
v16int16 window_read_v16(input_window_int16 *w);
v16cint16 window_read_v16(input_window_cint16 *w);
v16int32 window_read_v16(input_window_int32 *w);
v16cint32 window_read_v16(input_window_cint32 *w);
v16float window_read_v16(input_window_float *w);
v16cfloat window_read_v16(input_window_cfloat *w);

void window_read(input_window_int8 *w, v16int8 &v);
void window_read(input_window_uint8 *w, v16uint8 &v);
void window_read(input_window_int16 *w, v16int16 &v);
void window_read(input_window_cint16 *w, v16cint16 &v);
void window_read(input_window_int32 *w, v16int32 &v);
void window_read(input_window_cint32 *w, v16cint32 &v);
void window_read(input_window_float *w, v16float &v);
void window_read(input_window_cfloat *w, v16cfloat &v);

次のコードは、32 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出します。現在位置は変更されません。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v32int8 window_read_v32(input_window_int8 *w);
v32uint8 window_read_v32(input_window_uint8 *w);
v32int16 window_read_v32(input_window_int16 *w);
v32cint16 window_read_v32(input_window_cint16 *w);
v32int32 window_read_v32(input_window_int32 *w);
v32float window_read_v32(input_window_float *w);

void window_read(input_window_int8 *w, v32int8 &v);
void window_read(input_window_uint8 *w, v32uint8 &v);
void window_read(input_window_int16 *w, v32int16 &v);
void window_read(input_window_cint16 *w, v32cint16 &v);
void window_read(input_window_int32 *w, v32int32 &v);
void window_read(input_window_float *w, v32float &v);

次のコードは、64 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出します。現在位置は変更されません。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v64int8 window_read_v64(input_window_int8 *w);
v64uint8 window_read_v64(input_window_uint8 *w);
v64int16 window_read_v64(input_window_int16 *w);

void window_read(input_window_int8 *w, v64int8 &v);
void window_read(input_window_uint8 *w, v64uint8 &v);
void window_read(input_window_int16 *w, v64int16 &v);

入力ウィンドウの読み出しおよび前進

次のコードは、スカラー型の値を同じ型の入力ウィンドウから読み出し、ウィンドウの現在位置を基になるデータ型のサイズの 1 倍前進させます。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。

int8 window_readincr(input_window_int8 *w);
int16 window_readincr(input_window_int16 *w);
int32 window_readincr(input_window_int32 *w);
int64 window_readincr(input_window_int64 *w);
uint8 window_readincr(input_window_uint8 *w);
uint16 window_readincr(input_window_uint16 *w);
uint32 window_readincr(input_window_uint32 *w);
uint64 window_readincr(input_window_uint64 *w);
cint16 window_readincr(input_window_cint16 *w);
cint32 window_readincr(input_window_cint32 *w);
float window_readincr(input_window_float *w);
cfloat window_readincr(input_window_cfloat *w);

void window_readincr(input_window_int8 *w, int8 &v );
void window_readincr(input_window_int16 *w, int16 &v );
void window_readincr(input_window_int32 *w, int32 &v );
void window_readincr(input_window_int64 *w, int64 &v );
void window_readincr(input_window_uint8 *w, uint8 &v );
void window_readincr(input_window_uint16 *w, uint16 &v );
void window_readincr(input_window_uint32 *w, uint32 &v );
void window_readincr(input_window_uint64 *w, uint64 &v );
void window_readincr(input_window_cint16 *w, cint16 &v);
void window_readincr(input_window_cint32 *w, cint32 &v);
void window_readincr(input_window_float *w, float &v );
void window_readincr(input_window_cfloat *w, cfloat &v);

次のコードは、4 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出し、ウィンドウの現在位置を基になるデータ型のサイズの 4 倍前進させます。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v4cint16 window_readincr_v4(input_window_cint16 *w);
v4int32 window_readincr_v4(input_window_int32 *w);
v4cint32 window_readincr_v4(input_window_cint32 *w);
v4int64 window_readincr_v4(input_window_int64 *w);
v4float window_readincr_v4(input_window_float *w);
v4cfloat window_readincr_v4(input_window_cfloat *w);

void window_readincr(input_window_cint16 *w, v4cint16 &v);
void window_readincr(input_window_int32 *w, v4int32 &v);
void window_readincr(input_window_cint32 *w, v4cint32 &v);
void window_readincr(input_window_int64 *w, v4int64 &v);
void window_readincr(input_window_float *w, v4float &v);
void window_readincr(input_window_cfloat *w, v4cfloat &v);

次のコードは、8 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出し、ウィンドウの現在位置を基になるデータ型のサイズの 8 倍前進させます。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v8int16 window_readincr_v8(input_window_int16 *w);
v8cint16 window_readincr_v8(input_window_cint16 *w);
v8int32 window_readincr_v8(input_window_int32 *w);
v8float window_readincr_v8(input_window_float *w);

void window_readincr(input_window_int16 *w, v8int16 &v);
void window_readincr(input_window_cint16 *w, v8cint16 &v);
void window_readincr(input_window_int32 *w, v8int32 &v);
void window_readincr(input_window_float *w, v8float &v);

次のコードは、16 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出し、ウィンドウの現在位置を基になるデータ型のサイズの 16 倍前進させます。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v16int8 window_readincr_v16(input_window_int8 *w);
v16uint8 window_readincr_v16(input_window_uint8 *w);
v16int16 window_readincr_v16(input_window_int16 *w);
v16cint16 window_readincr_v16(input_window_cint16 *w);
v16int32 window_readincr_v16(input_window_int32 *w);
v16cint32 window_readincr_v16(input_window_cint32 *w);
v16float window_readincr_v16(input_window_float *w);
v16cfloat window_readincr_v16(input_window_cfloat *w);

void window_readincr(input_window_int8 *w, v16int8 &v);
void window_readincr(input_window_uint8 *w, v16uint8 &v);
void window_readincr(input_window_int16 *w, v16int16 &v);
void window_readincr(input_window_cint16 *w, v16cint16 &v);
void window_readincr(input_window_int32 *w, v16int32 &v);
void window_readincr(input_window_cint32 *w, v16cint32 &v);
void window_readincr(input_window_float *w, v16float &v);
void window_readincr(input_window_cfloat *w, v16cfloat &v);

次のコードは、32 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出し、ウィンドウの現在位置を基になるデータ型のサイズの 32 倍前進させます。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v32int8 window_readincr_v32(input_window_int8 *w);
v32uint8 window_readincr_v32(input_window_uint8 *w);
v32int16 window_readincr_v32(input_window_int16 *w);
v32cint16 window_readincr_v32(input_window_cint16 *w);
v32int32 window_readincr_v32(input_window_int32 *w);
v32float window_readincr_v32(input_window_float *w);

void window_readincr(input_window_int8 *w, v32int8 &v);
void window_readincr(input_window_uint8 *w, v32uint8 &v);
void window_readincr(input_window_int16 *w, v32int16 &v);
void window_readincr(input_window_cint16 *w, v32cint16 &v);
void window_readincr(input_window_int32 *w, v32int32 &v);
void window_readincr(input_window_float *w, v32float &v);

次のコードは、64 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出し、ウィンドウの現在位置を基になるデータ型のサイズの 64 倍前進させます。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v64int8 window_readincr_v64(input_window_int8 *w);
v64uint8 window_readincr_v64(input_window_uint8 *w);
v64int16 window_readincr_v64(input_window_int16 *w);

void window_readincr(input_window_int8 *w, v64int8 &v);
void window_readincr(input_window_uint8 *w, v64uint8 &v);
void window_readincr(input_window_int16 *w, v64int16 &v);

入力ウィンドウの読み出しおよび後進

次のコードは、スカラー型の値を同じ型の入力ウィンドウから読み出し、ウィンドウの現在位置を基になるデータ型のサイズの 1 倍後進させます。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。

int8 window_readdecr(input_window_int8 *w);
int16 window_readdecr(input_window_int16 *w);
int32 window_readdecr(input_window_int32 *w);
int64 window_readdecr(input_window_int64 *w);
uint8 window_readdecr(input_window_uint8 *w);
uint16 window_readdecr(input_window_uint16 *w);
uint32 window_readdecr(input_window_uint32 *w);
uint64 window_readdecr(input_window_uint64 *w);
cint16 window_readdecr(input_window_cint16 *w);
cint32 window_readdecr(input_window_cint32 *w);
float window_readdecr(input_window_float *w);
cfloat window_readdecr(input_window_cfloat *w);

void window_readdecr(input_window_int8 *w, int8 &v );
void window_readdecr(input_window_int16 *w, int16 &v );
void window_readdecr(input_window_int32 *w, int32 &v );
void window_readdecr(input_window_int64 *w, int64 &v );
void window_readdecr(input_window_uint8 *w, uint8 &v );
void window_readdecr(input_window_uint16 *w, uint16 &v );
void window_readdecr(input_window_uint32 *w, uint32 &v );
void window_readdecr(input_window_uint64 *w, uint64 &v );
void window_readdecr(input_window_cint16 *w, cint16 &v);
void window_readdecr(input_window_cint32 *w, cint32 &v);
void window_readdecr(input_window_float *w, float &v );
void window_readdecr(input_window_cfloat *w, cfloat &v);

次のコードは、4 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出し、ウィンドウの現在位置を基になるデータ型のサイズの 4 倍後進させます。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v4cint16 window_readdecr_v4(input_window_cint16 *w);
v4int32 window_readdecr_v4(input_window_int32 *w);
v4cint32 window_readdecr_v4(input_window_cint32 *w);
v4int64 window_readdecr_v4(input_window_int64 *w);
v4float window_readdecr_v4(input_window_float *w);
v4cfloat window_readdecr_v4(input_window_cfloat *w);

void window_readdecr(input_window_cint16 *w, v4cint16 &v);
void window_readdecr(input_window_int32 *w, v4int32 &v);
void window_readdecr(input_window_cint32 *w, v4cint32 &v);
void window_readdecr(input_window_int64 *w, v4int64 &v);void window_readdecr(input_window_float *w, v4float &v);
void window_readdecr(input_window_cfloat *w, v4cfloat &v);

次のコードは、8 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出し、ウィンドウの現在位置を基になるデータ型のサイズの 8 倍後進させます。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v8int16 window_readdecr_v8(input_window_int16 *w);
v8cint16 window_readdecr_v8(input_window_cint16 *w);
v8int32 window_readdecr_v8(input_window_int32 *w);
v8float window_readdecr_v8(input_window_float *w);

void window_readdecr(input_window_int16 *w, v8int16 &v);
void window_readdecr(input_window_cint16 *w, v8cint16 &v);
void window_readdecr(input_window_int32 *w, v8int32 &v);
void window_readdecr(input_window_float *w, v8float &v);

次のコードは、16 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出し、ウィンドウの現在位置を基になるデータ型のサイズの 16 倍後進させます。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v16int8 window_readdecr_v16(input_window_int8 *w);
v16uint8 window_readdecr_v16(input_window_uint8 *w);
v16int16 window_readdecr_v16(input_window_int16 *w);
v16cint16 window_readdecr_v16(input_window_cint16 *w);
v16int32 window_readdecr_v16(input_window_int32 *w);
v16cint32 window_readdecr_v16(input_window_cint32 *w);
v16float window_readdecr_v16(input_window_float *w);
v16cfloat window_readdecr_v16(input_window_cfloat *w);

void window_readdecr(input_window_int8 *w, v16int8 &v);
void window_readdecr(input_window_uint8 *w, v16uint8 &v);
void window_readdecr(input_window_int16 *w, v16int16 &v);
void window_readdecr(input_window_cint16 *w, v16cint16 &v);
void window_readdecr(input_window_int32 *w, v16int32 &v);
void window_readdecr(input_window_cint32 *w, v16cint32 &v);
void window_readdecr(input_window_float *w, v16float &v);
void window_readdecr(input_window_cfloat *w, v16cfloat &v);

次のコードは、32 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出し、ウィンドウの現在位置を基になるデータ型のサイズの 32 倍後進させます。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v32int8 window_readdecr_v32(input_window_int8 *w);
v32uint8 window_readdecr_v32(input_window_uint8 *w);
v32int16 window_readdecr_v32(input_window_int16 *w);
v32cint16 window_readdecr_v32(input_window_cint16 *w);
v32int32 window_readdecr_v32(input_window_int32 *w);
v32float window_readdecr_v32(input_window_float *w);

void window_readdecr(input_window_int8 *w, v32int8 &v);
void window_readdecr(input_window_uint8 *w, v32uint8 &v);
void window_readdecr(input_window_int16 *w, v32int16 &v);
void window_readdecr(input_window_cint16 *w, v32cint16 &v);
void window_readdecr(input_window_int32 *w, v32int32 &v);
void window_readdecr(input_window_float *w, v32float &v);

次のコードは、64 ウェイ ベクター型の値を同じ型の入力ウィンドウから読み出し、ウィンドウの現在位置を基になるデータ型のサイズの 64 倍後進させます。関数形式 (値を返す) とプロシージャ形式 (参照引数を変更する) の両方が提供されています。ベクター操作では、メモリ データパスは 128 ビットまたは 256 ビット幅です。

v64int8 window_readdecr_v64(input_window_int8 *w);
v64uint8 window_readdecr_v64(input_window_uint8 *w);
v64int16 window_readdecr_v64(input_window_int16 *w);

void window_readdecr(input_window_int8 *w, v64int8 &v);
void window_readdecr(input_window_uint8 *w, v64uint8 &v);
void window_readdecr(input_window_int16 *w, v64int16 &v);

出力ウィンドウへのデータの書き込み

次のコードは、スカラー型の値を同じ型の出力ウィンドウに書き込みます。現在位置は変更されません。

void window_write(output_window_int8 *w, int8 v);
void window_write(output_window_uint8 *w, uint8 v);
void window_write(output_window_int16 *w, int16 v);
void window_write(output_window_uint16 *w, uint16 v);
void window_write(output_window_cint16 *w, cint16 v);
void window_write(output_window_int32 *w, int32 v );
void window_write(output_window_uint32 *w, uint32 v );
void window_write(output_window_cint32 *w, cint32 v);
void window_write(output_window_int64 *w, int64 v );
void window_write(output_window_uint64 *w, uint64 v );
void window_write(output_window_float *w, float v );
void window_write(output_window_cfloat *w, cfloat v);

次のコードは、4 ウェイ ベクター型の値を同じ型の出力ウィンドウに書き込みます。現在位置は変更されません。

void window_write(output_window_cint16 *w, v4cint16 v);
void window_write(output_window_int32 *w, v4int32 v );
void window_write(output_window_cint32 *w, v4cint32 v);
void window_write(output_window_int64 *w, v4int64 v );
void window_write(output_window_float *w, v4float v );
void window_write(output_window_cfloat *w, v4cfloat v);

次のコードは、8 ウェイ ベクター型の値を同じ型の出力ウィンドウに書き込みます。現在位置は変更されません。

void window_write(output_window_int16 *w, v8int16 v);
void window_write(output_window_cint16 *w, v8cint16 v);
void window_write(output_window_int32 *w, v8int32 v );
void window_write(output_window_float *w, v8float v );

次のコードは、16 ウェイ ベクター型の値を同じ型の出力ウィンドウに書き込みます。現在位置は変更されません。

void window_write(output_window_int8 *w, v16int8 v);
void window_write(output_window_uint8 *w, v16uint8 v);
void window_write(output_window_int16 *w, v16int16 v);
void window_write(output_window_cint16 *w, v16cint16 v);
void window_write(output_window_int32 *w, v16int32 v );
void window_write(output_window_cint32 *w, v16cint32 v);
void window_write(output_window_float *w, v16float v );
void window_write(output_window_cfloat *w, v16cfloat v);

次のコードは、32 ウェイ ベクター型の値を同じ型の出力ウィンドウに書き込みます。現在位置は変更されません。

void window_write(output_window_int8 *w, v32int8 v);
void window_write(output_window_uint8 *w, v32uint8 v);
void window_write(output_window_int16 *w, v32int16 v);
void window_write(output_window_cint16 *w, v32cint16 v);
void window_write(output_window_int32 *w, v32int32 v );
void window_write(output_window_float *w, v32float v );

次のコードは、64 ウェイ ベクター型の値を同じ型の出力ウィンドウに書き込みます。現在位置は変更されません。

void window_write(output_window_int8 *w, v64int8 v);
void window_write(output_window_uint8 *w, v64uint8 v);
void window_write(output_window_int16 *w, v64int16 v);

出力ウィンドウの書き込みおよび前進

次のコードは、スカラー型の値を同じ型の出力ウィンドウに書き込み、ウィンドウの現在位置をそのデータ型に基づいて前進させます。

void window_writeincr (output_window_int8 *w, int8 v);
void window_writeincr (output_window_uint8 *w, uint8 v);
void window_writeincr (output_window_int16 *w, int16 v);
void window_writeincr (output_window_uint16 *w, uint16 v);
void window_writeincr (output_window_cint16 *w, cint16 v);
void window_writeincr (output_window_int32 *w, int32 v );
void window_writeincr (output_window_uint32 *w, uint32 v );
void window_writeincr (output_window_cint32 *w, cint32 v);
void window_writeincr (output_window_int64 *w, int64 v);
void window_writeincr (output_window_uint64 *w, uint64 v);void window_writeincr (output_window_float *w, float v );
void window_writeincr (output_window_cfloat *w, cfloat v);

次のコードは、4 ウェイ ベクター型の値を同じ型の出力ウィンドウに書き込み、現在位置を基になるデータ型のサイズの 4 倍前進させます。

void window_writeincr(output_window_cint16 *w, v4cint16 v);
void window_writeincr(output_window_int32 *w, v4int32 v );
void window_writeincr(output_window_cint32 *w, v4cint32 v);
void window_writeincr(output_window_int64 *w, v4int64 v );
void window_writeincr(output_window_float *w, v4float v );
void window_writeincr(output_window_cfloat *w, v4cfloat v);

次のコードは、8 ウェイ ベクター型の値を同じ型の出力ウィンドウに書き込み、現在位置を基になるデータ型のサイズの 8 倍前進させます。

void window_writeincr(output_window_int16 *w, v8int16 v);
void window_writeincr(output_window_cint16 *w, v8cint16 v);
void window_writeincr(output_window_int32 *w, v8int32 v );
void window_writeincr(output_window_float *w, v8float v );

次のコードは、16 ウェイ ベクター型の値を同じ型の出力ウィンドウに書き込み、現在位置を基になるデータ型のサイズの 16 倍前進させます。

void window_writeincr(output_window_int8 *w, v16int8 v);
void window_writeincr(output_window_uint8 *w, v16uint8 v);
void window_writeincr(output_window_int16 *w, v16int16 v);
void window_writeincr(output_window_cint16 *w, v16cint16 v);
void window_writeincr(output_window_int32 *w, v16int32 v );
void window_writeincr(output_window_cint32 *w, v16cint32 v);
void window_writeincr(output_window_float *w, v16float v );
void window_writeincr(output_window_cfloat *w, v16cfloat v);

次のコードは、32 ウェイ ベクター型の値を同じ型の出力ウィンドウに書き込み、現在位置を基になるデータ型のサイズの 32 倍前進させます。

void window_writeincr(output_window_int8 *w, v32int8 v);
void window_writeincr(output_window_uint8 *w, v32uint8 v);
void window_writeincr(output_window_int16 *w, v32int16 v);
void window_writeincr(output_window_cint16 *w, v32cint16 v);
void window_writeincr(output_window_int32 *w, v32int32 v );
void window_writeincr(output_window_float *w, v32float v );

次のコードは、64 ウェイ ベクター型の値を同じ型の出力ウィンドウに書き込み、現在位置を基になるデータ型のサイズの 64 倍前進させます。

void window_writeincr(output_window_int8 *w, v64int8 v);
void window_writeincr(output_window_uint8 *w, v64uint8 v);
void window_writeincr(output_window_int16 *w, v64int16 v);

カーネルのストリーム操作

ストリームのデータ型

表 2. サポートされるストリームのデータ型
入力ストリームのデータ型 出力ストリームのデータ型
input_stream_int8 output_stream_int8
input_stream_int16 output_stream_int16
input_stream_int32 output_stream_int32
input_stream_int64 output_stream_int64
input_stream_uint8 output_stream_uint8
input_stream_uint16 output_stream_uint16
input_stream_uint32 output_stream_uint32
input_stream_uint64 output_stream_uint64
input_stream_cint16 output_stream_cint16
input_stream_cint32 output_stream_cint32
input_stream_acc48 output_stream_acc48
input_stream_cacc48 output_stream_cacc48
input_stream_acc80 output_stream_acc80
input_stream_cacc80 output_stream_cacc80
input_stream_accfloat output_stream_accfloat
input_stream_caccfloat output_stream_caccfloat
input_stream_float output_stream_float
input_stream_cfloat output_stream_cfloat

この表の各データ型は、AI エンジンからスカラーまたはベクター グループとして読み出しまたは書き込みできます。ただし、AI エンジンからプログラマブル ロジック インターフェイス ポートまたはストリーム スイッチ ネットワークでサポートされるバス データ幅に基づき、グループ化に特定の制限があります。AI エンジン カーネルに有効な組み合わせは、合計 32 ビットまたは 128 ビットまでのベクター バンドルです。アキュムレータのデータ型は、隣接する AI エンジン間のカスケード ストリーム接続を指定するためのみに使用されます。有効なグループ化は、2 つのプロセッサ間の 384 ビット幅のカスケード チャネルに基づきます。

注記: これらのデータ型を使用するには、カーネルのソース ファイルに #include <adf.h> を使用する必要があります。

入力ストリームの実行および前進

AI エンジン操作

次の操作は、指定の入力ストリームからデータを読み出し、そのストリームを AI エンジン上で前進させます。AI エンジンには 2 つの入力ストリーム ポートがあるので、物理的なポートの割り当ては AI エンジン コンパイラにより自動的に実行され、ストリーム データ構造の一部として指定されます。ストリームからのデータ値は、1 つずつまたはベクターとして読み出されます。ベクターとして読み出す場合、すべての値が読み出されるまで、ストリーム操作は停止します。データのグループ化は、基になる 1 サイクルの 32 ビット ストリーム操作または 4 サイクルの 128 ビット幅ストリーム操作に基づきます。カスケード接続では、すべてのアキュムレータ値が並列に読み出されます。

int32 readincr(input_stream_int32 *w);
uint32 readincr(input_stream_uint32 *w);
cint16 readincr(input_stream_cint16 *w);
float readincr(input_stream_float *w);
cfloat readincr(input_stream_cfloat *w);

v16int8 readincr_v16(input_stream_int8 *w);
v16uint8 readincr_v16(input_stream_uint8 *w);
v8int16 readincr_v8(input_stream_int16 *w);
v4cint16 readincr_v4(input_stream_cint16 *w);
v4int32 readincr_v4(input_stream_int32 *w);
v2cint32 readincr_v2(input_stream_cint32 *w);
v4float readincr_v4(input_stream_float *w);

v8acc48 readincr_v8(input_stream_acc48 *w);
v4cacc48 readincr_v4(input_stream_cacc48 *w);
v4acc80 readincr_v4(input_stream_acc80 * str);
v2cacc80 readincr_v2(input_stream_cacc80 * str);
v8float readincr_v8(input_stream_accfloat * str);
v4cfloat readincr_v4(input_stream_caccfloat * str);

出力ストリームの書き込みおよび前進

AI エンジン操作

次の操作は、データを指定の出力ストリームに書き込み、そのストリームを AI エンジン上で前進させます。AI エンジンには 2 つの出力ストリーム ポートがあるので、物理的なポートの割り当ては AI エンジン コンパイラにより自動的に実行され、ストリーム データ構造の一部として指定されます。データ値は、1 つずつまたはベクターとして出力ストリームに書き込むことができます。ベクターとして書き込む場合、すべての値が書き込まれるまで、ストリーム操作は停止します。データのグループ化は、基になる 1 サイクルの 32 ビット ストリーム操作または 4 サイクルの 128 ビット幅ストリーム操作に基づきます。カスケード接続では、すべての値が並列に書き込まれます。

void writeincr(output_stream_int32 *w, int32 v);
void writeincr(output_stream_uint32 *w, uint32 v);
void writeincr(output_stream_cint16 *w, cint16 v);
void writeincr(output_stream_float *w, float v);
void writeincr(output_stream_cfloat *w, cfloat v);

void writeincr_v16(output_stream_int8 *w, v16int8 v);
void writeincr_v16(output_stream_uint8 *w, v16uint8 v);
void writeincr_v8(output_stream_int16 *w, v8int16 v);
void writeincr_v4(output_stream_cint16 *w, v4cint16 v);
void writeincr_v4(output_stream_int32 *w, v4int32 v);
void writeincr_v2(output_stream_cint32 *w, v2cint32 v);
void writeincr_v4(output_stream_float *w, v4float v);

void writeincr_v8(output_stream_acc48 *w, v8acc48 v);
void writeincr_v4(output_stream_cacc48 *w, v4cacc48 v);
void writeincr_v4(output_stream_acc80* str, v4acc80 value);
void writeincr_v2(output_stream_cacc80* str, v2cacc80 value);
void writeincr_v8(output_stream_accfloat* str, v8float value);
void writeincr_v4(output_stream_caccfloat* str, v4cfloat value);

ストリームの並列使用

ストリーミング入力および出力インターフェイスでパフォーマンスがストリーム数によって制限される場合は、2 つのストリーミング入力または 2 つのストリーミング出力を並列に使用できます。2 つのストリームを並列に使用するには、次の 2 つのマクロをペアで使用することをお勧めします。ここで、idx1 および idx2 は 2 つのストリームです。ストリーム ポートに restrict キーワードを追加して、ポートを並列処理用に最適化します。このマクロは、1 サイクルごとに 32 ビット、または 4 サイクルごとに 128 ビットを処理します。

READINCR(SS_rsrc1, idx1) and READINCR(SS_rsrc2, idx2)
READINCRW(WSS_rsrc1, idx1) and READINCRW(WSS_rsrc2, idx2)
WRITEINCR(MS_rsrc1, idx1, val) and WRITEINCR(MS_rsrc2, idx2, val)
WRITEINCRW(WMS_rsrc1, idx1, val) and WRITEINCRW(WMS_rsrc2, idx2, val)

次に、間隔 1 でパイプライン処理を使用する 2 つの並列入力ストリームのサンプル コードを示します。

void simple( input_stream_int32 * restrict data0, input_stream_int32 * restrict data1, 
    output_stream_int32 * restrict out) {
   for(int i=0; i<1024; i++)
   chess_prepare_for_pipelining
 {
     int32_t d = READINCR(SS_rsrc1, data0) ;
     int32_t e = READINCR(SS_rsrc2, data1) ;
     WRITEINCR(MS_rsrc1,out,d+e);
 }
}

パケット ストリームの操作

表 3. サポートされるパケット ストリームのデータ型
入力ストリームのデータ型 出力ストリームのデータ型
input_pktstream output_pktstream

パケット化された複数の異なるストリームがインターリーブされたストリーミング データの特性を指定するため、さらに 2 つのストリーム データ型があります。これらのデータ型は、プログラム内の独立したデータ ストリームの数が、使用可能なハードウェア ストリーム チャネルまたはポートの数を超える場合に便利です。このメカニズムの詳細は、明示的パケット スイッチング を参照してください。

パケット ストリームの読み出しと書き込み

1 つのデータ パケットには、1 つのワード (32 ビット) パケット ヘッダーの後に複数のデータ ワードが含まれ、最後のデータ ワードにはパケットの最後を示す TLAST フィールドが含まれます。入力パケット ストリームを読み込んで前進させ、出力パケット ストリームを書き込んで前進させるには、次の操作を使用します。

int32 readincr(input_pktstream *w);
int32 readincr(input_pktstream *w, bool &tlast);

void writeincr(output_pktstream *w, int32 value);
void writeincr(output_pktstream *w, int32 value, bool tlast);

パケット サイズが固定されていない場合は、API に TLAST 引数を使用すると、パケットの終了条件の読み出しまたは書き込みを実行できます。

パケット処理

パケットの最初の 32 ビット ワードはパケット ヘッダーで、次の表に示すビット フィールドで構成されています。

表 4. パケットのビット フィールド
ビット フィールド
4 ~ 0 パケット ID
11 ~ 5 7'b0000000
14 ~ 12 パケット タイプ
15 1'b0
20 ~ 16 ソース行
27 ~ 21 ソース列
30 ~ 28 3'b000
31 ビット [30:0] の奇数パリティ

パケット ID は、配線要件に基づいてコンパイラにより割り当てられます。パケット タイプには、任意の 3 ビット パターンを使用でき、パケットのタイプを特定するために挿入できます。ソース行および列は、パケットの送信元の AI エンジン タイル座標です。プログラマブル ロジック (PL) から送信されるパケットのソース行および列は、-1、-1 です。

各パケットの先頭に適切なパケット ヘッダーを作成して送信するのは、ユーザーの責任です。受信側では、データを読み出す前に、パケット ヘッダーを受信してデコードする必要があります。

AI エンジン カーネルのパケット ヘッダーをアセンブルまたは逆アセンブルするには、次の操作を使用できます。

void writeHeader(output_pktstream *str, unsigned int pcktType, unsigned int ID);
void writeHeader(output_pktstream *str, unsigned int pcktType, unsigned int ID, bool tlast);


uint32 getPacketid(input_pktstream *w, int index);
uint32 getPacketid(output_pktstream *w, int index);

writeHeader API は、パケット ヘッダーを指定のパケット ID およびパケット タイプと共にアセンブルします。ソース行および列は、この API が実行される AI エンジン タイルの座標を使用して自動的に挿入されます。

getPacketid API は、コンパイラで割り当てられたパケット ID を、入力または出力パケット ストリーム データ構造でクエリします。index 引数は、グラフ仕様の分割または結合分岐エッジを示します。

重要: writeHeader() および getPacketid() API は、PL カーネルではサポートされません。
重要: generateHeader API は廃止予定で、writeHeader に置き換えられています。

詳細は、明示的パケット スイッチング を参照してください。