xcl_reqd_pipe_depth - 2021.1 Japanese

Vitis 統合ソフトウェア プラットフォームの資料: アプリケーション アクセラレーション開発 (UG1393)

Document ID
UG1393
Release Date
2022-03-29
Version
2021.1 Japanese

説明

重要: パイプの宣言には、小文字と数字を使用する必要があります。また、パイプで使用される変数では printf() はサポートされません。

OpenCL フレームワーク 2.0 仕様には、パイプと呼ばれる新しいメモリ オブジェクトが導入されています。パイプには、FIFO として構成されたデータが格納されます。パイプを使用すると、データを外部メモリなしで FPGA 内の 1 つのカーネルから別のカーネルにストリーミングでき、全体的なシステム レイテンシを大幅に向上できます。

Vitis コア開発キットでは、パイプはすべてのカーネル関数の外部でスタティックに定義する必要があります。パイプの深さは、パイプ宣言内で XCL_REQD_PIPE_DEPTH 属性を使用して指定する必要があります。
pipe int p0 __attribute__((xcl_reqd_pipe_depth(512)));

パイプには、ノンブロッキング モードの標準 OpenCL read_pipe() および write_pipe() ビルトイン関数、またはブロッキング モードのザイリンクス拡張 read_pipe_block() および write_pipe_block() 関数を使用してのみアクセス可能です。

重要: Vitis HLS では、パイプの読み出しおよび書き込みのためにブロッキング モードのみがサポートされます。ブロック以外の read_pipe/write_block 関数はサポートされません。
重要: 1 つのパイプは、異なるカーネル内に 1 つのプロデューサーおよびコンシューマーのみを持つことができます。

パイプ オブジェクトはホスト CPU からはアクセスできません。パイプのステータスは、OpenCL get_pipe_num_packets() および get_pipe_max_packets() ビルトイン関数を使用してクエリできます。ビルトイン関数の詳細は、Khronos OpenCL Working Group の 「The OpenCL C Specification」 を参照してください。

構文

パイプ オブジェクトの宣言で設定します。

pipe int <id> __attribute__((xcl_reqd_pipe_depth(<n>)));

説明:

<id>
パイプの ID を指定します。小文字と数字のみで指定する必要があります。たとえば、<infifo1> のように指定します (<inFifo1> は不可)。
<n>
パイプの深さを指定します。有効な値は 16、32、64、128、256、512、1024、2048、4096、8192、16384、32768 です。

次はザイリンクス GitHub からの dataflow_pipes_ocl 例で、パイプを使用してブロッキング read_pipe_block() および write_pipe_block() 関数によりデータを 1 つの処理段階から次の処理段階に渡しています。

pipe int p0 __attribute__((xcl_reqd_pipe_depth(32)));
pipe int p1 __attribute__((xcl_reqd_pipe_depth(32)));
// Input Stage Kernel : Read Data from Global Memory and write into Pipe P0
kernel __attribute__ ((reqd_work_group_size(1, 1, 1)))
void input_stage(__global int *input, int size)
{
__attribute__((xcl_pipeline_loop))
mem_rd: for (int i = 0 ; i < size ; i++)
{
//blocking Write command to pipe P0
write_pipe_block(p0, &input[i]);
}
}
// Adder Stage Kernel: Read Input data from Pipe P0 and write the result
// into Pipe P1
kernel __attribute__ ((reqd_work_group_size(1, 1, 1)))
void adder_stage(int inc, int size)
{
__attribute__((xcl_pipeline_loop))
execute: for(int i = 0 ; i < size ; i++)
{
int input_data, output_data;
//blocking read command to Pipe P0
read_pipe_block(p0, &input_data);
output_data = input_data + inc;
//blocking write command to Pipe P1
write_pipe_block(p1, &output_data);
}
}
// Output Stage Kernel: Read result from Pipe P1 and write the result to 
// Global Memory
kernel __attribute__ ((reqd_work_group_size(1, 1, 1)))
void output_stage(__global int *output, int size)
{
__attribute__((xcl_pipeline_loop))
mem_wr: for (int i = 0 ; i < size ; i++)
{
//blocking read command to Pipe P1
read_pipe_block(p1, &output[i]);
}
}