重要: コードで
hls::task
オブジェクトを使用するには、次のようにヘッダー ファイル hls_task.h を含めます。
hls::task
ライブラリは、データ駆動型プロセスをモデリングするシンプルな方法を提供し、ストリーミング I/O (hls::stream
または hls::stream_of_blocks
) のみでタスクのスタティック インスタンシエーションを可能にし、C++ で並行プロセスをモデリングするのに必要な空のストリームをチェックする必要がなくなります。
ヒント:
データ駆動型 TLP の非同期 I/O で説明されるように、
hls::task
は s_axilite
インターフェイスのスカラー値への安定した入力、または m_axi
インターフェイスの配列へのポインターをサポートしています。次は、GitHub からの simple_data_driven という単純な例です。
void odds_and_evens(hls::stream<int> &in, hls::stream<int> &out1, hls::stream<int> &out2) {
hls_thread_local hls::stream<int> s1; // channel connecting t1 and t2
hls_thread_local hls::stream<int> s2; // channel connecting t1 and t3
// t1 infinitely runs splitter, with input in and outputs s1 and s2
hls_thread_local hls::task t1(splitter, in, s1, s2);
// t2 infinitely runs function odds, with input s1 and output out1
hls_thread_local hls::task t2(odds, s1, out1);
// t3 infinitely runs function evens, with input s2 and output
hls_thread_local hls::task t3(evens, s2, out2);
}
最上位関数の odds_and_evens
では、ストリーミング入力/出力インターフェイスが使用されることに留意が必要です。これは、純粋なストリーミング カーネルです。最上位関数には、次が含まれています。
- s1 および s2 は、スレッドのローカル ストリーム (
hls_thread_local
) で、タスク チャネル タスク t1 と t2 を接続するために使用されます。これらのストリームは、複数の最上位呼び出しにわたってアクティブとなるように、スレッドのローカル ストリームである必要があります。 - t1、t2、および t3 は、それぞれ関数 (
splitter
、odds
、evens
) を実行するスレッドのローカルhls::task
です。タスクは無限に実行され、入力ストリームのデータを処理します。同期は不要です。
ただし、このタイプのストリームのみのモデルには、次のような制限があります。
- ローカル メモリ以外のメモリにはアクセスできない
- これらのポートが STABLE プラグマによって安定であると宣言されていれば、スカラー、配列、ポインターなどのストリーム以外のデータを引数として渡すことができます。現在のところ、
m_axi
インターフェイスを使用する最上位ポインターは、offset=off
オプションでのみ渡すことができます。重要: スカラー、配列、ポインターは、hls::task
との同期がないため、不明な間隔で読み出されます。そのため、これらのポートがいつ読み出されるかに依存しないようにコードを書く必要があります。 - 並列タスクの指定により、デザインの並列処理を明示的に記述する必要がある
-
hls::task
は、常に並列コンテキストでインスタンシエートされる必要があり、逐次コンテキストで入れ子にはできません。- 最上位関数で
hls::task
を使用すると、その最上位関数が並列コンテキストになります。 -
hls::task
は、並列コンテキストなので、データフロー領域内にインスタンシエートできます。 - 逐次コンテキストでタスクをインスタンシエートする関数を呼び出す場合は、次に従ってください。
- 関数は、データフロー領域などの並列コンテキストである必要があります。
- タスクの入力と出力ストリームは、並列コンテキスト内の通常のデータフロー プロセスによって生成されて、消費される必要があります。
- 制御駆動型 TLP は、最上位、ほかの制御起動型内、または逐次領域内に含めることができます。
- データ駆動型の場合は、最上位、別のデータ駆動型内、または制御駆動型タスクの間に入れ子にできます。
- 制御駆動型 TLP は、パイプライン内にも、データ駆動型内に直接含めることはできません。後者の場合、データ駆動型タスクによって実行される逐次領域内に含める必要があります。
- データ駆動型は、逐次、パイプライン、制御駆動型内に直接含めることはできません。
- 逐次領域またはパイプラインは、制御またはデータ駆動型タスクの本体内にのみ含めることができ、制御またはデータ駆動型の領域には含めることはできません。
- 最上位関数で
hls::task
オブジェクトは、標準的なデータフロー形式の関数呼び出しと自由に混在させることができ、メモリ (DRAM および BRAM) に対してデータを入出力できます。また、タスクは、データ ストリームを処理するワーカー プールを構築するために 1 対多のデータ配布をサポートするチャネルの分割 (hls::split
)、および多対 1 のデータ集約をサポートするチャネルのマージ (hls::merge
) をサポートします。