関数のインスタンシエーションとは、関数の階層を保持しながら関数の特定のインスタンスに対してローカル最適化を実行する最適化手法です。これにより関数呼び出し周辺の制御ロジックが単純になり、レイテンシおよびスループットが向上することがあります。
FUNCTION_INSTATIATE プラグマまたは指示子を使用すると、関数が呼び出されたときに関数の一部の入力が定数値であることがあるという事実を利用して、周辺の制御構造が簡略化され、より最適化されたより小さい関数ブロックが作成されます。これは、次のコード例で示されています。
char func(char inval, char incr) {
#pragma HLS INLINE OFF
#pragma HLS FUNCTION_INSTANTIATE variable=incr
return inval + incr;
}
void top(char inval1, char inval2, char inval3,
char *outval1, char *outval2, char *outval3)
{
*outval1 = func(inval1, 0);
*outval2 = func(inval2, 1);
*outval3 = func(inval3, 100);
}
OFF
オプションを使用すると、この自動インライン展開が実行されないようにできます。
func
関数は、排他的に 3 回 (incr
の値による) 実行されるように記述されています。func
関数の各インスタンスはまったく同じようにインプリメントされます。これは、関数の再利用とエリア最適化に向いていますが、関数内の制御ロジックは、その 2 回の排他的な演算をできるほど複雑である必要があります。このコード例のフル バージョンは、
Vitis-HLS-Introductory-Examples/Pipelining/Functions/function_instantiate
を参照してください。
FUNCTION_INSTATIATE 最適化を使用すると、各インスタンスを個別に最適化できるので、機能およびエリアを削減できます。FUNCTION_INSTATIATE 最適化を実行すると、上記のコードは 2 つの個別の関数に変換され、それぞれを次に示すように異なるモード値用に最適化できます。
void func1() {
// code segment 1
}
void func2() {
// code segment 2
}
関数が異なる階層レベルで使用されていて、インライン展開またはコード変更を広範囲で実行しないと関数の共有が困難な場合、FUNCTION_INSTATIATE を使用するのがエリアを削減する最適な方法となり得ます。ローカルで最適化された小さなコピーが多数ある方が、共有できない大きなコピーが多数あるよりも効率的です。