最適な水平たたみ込み
FPGA インプリメンテーションで効率的な方法で計算を実行するため、水平たたみ込みは次の図に示すように計算されます。

前の K 個のサンプルを使用してたたみ込み結果を計算する必要があるのでサンプルが一時キャッシュ hwin にコピーされます。このようにローカル ストレージを使用すると、PS から値を読み込み直す必要はなく、データのフローは途切れません。最初の計算では、hwin に結果を計算するのに十分な値が含まれていないので、条件により出力値は書き出されません。
アルゴリズムは入力サンプルを読み込み続け、hwin キャッシュに格納します。新しいサンプルが読み込まれるたびに、不要なサンプルが hwin から排出されます。出力値を初めて書き込むことができるのは、K 番目の入力が読み込まれてからです。これで、出力値を書き込むことができます。このように、最後のサンプルが読み込まれるまで行ごとに処理されます。この段階で hwin に格納されているのは最後の K 個のサンプルだけであり、そのすべてがたたみ込み計算に必要となります。
次に示すように、この操作を実行するコードでは、ローカル ストレージを使用することにより PL からの再読み込みを回避して最終インプリメンテーションでローカル ストレージからの読み出しを並列に実行できるようにし、さらに条件分岐を多用して各新しいデータ サンプルを異なる方法で処理できるようにしています。
// Horizontal convolution
phconv=hconv_buffer; // set / reset pointer to start of buffer
// These assertions let HLS know the upper bounds of loops
assert(height < MAX_IMG_ROWS);
assert(width < MAX_IMG_COLS);
assert(vconv_xlim < MAX_IMG_COLS - (K - 1));
HConvH:for(int col = 0; col < height; col++) {
HConvW:for(int row = 0; row < width; row++) {
#pragma HLS PIPELINE
T in_val = *src++;
// Reset pixel value on-the-fly - eliminates an O(height*width) loop
T out_val = 0;
HConv:for(int i = 0; i < K; i++) {
hwin[i] = i < K - 1 ? hwin[i + 1] : in_val;
out_val += hwin[i] * hcoeff[i];
}
if (row >= K - 1) {
*phconv++=out_val;
}
}
}
上記のコードでは、一時変数 out_val を使用してたたみ込み計算が実行されています。この変数は、計算の実行前に 0 に設定されるので、前の例で示したように、値をリセットするために 2 百万クロック サイクルを費やす必要はありません。
プロセス全体を通して、src 入力のサンプルはラスター ストリーミング方式で処理されます。すべてのサンプルが順番に読み込まれます。タスクからの出力は破棄または使用されますが、タスクは常に計算を実行し続けます。この点が、CPU で実行するために記述されたコードと異なります。