Model Composer への C/C++ のインポート - 2023.2 日本語

Vitis Model Composer ユーザー ガイド (UG1483)

Document ID
UG1483
Release Date
2023-11-15
Version
2023.2 日本語

Vitis Model Composer では、C または C++ 関数をインポートしてブロックのライブラリを作成できますが、コードが正しく認識および処理されるようにするため、特別な要件に従う必要があります。関数ソースは、ヘッダー ファイル (.h)、C または C++ ソース ファイル (.c.cpp) のいずれかで定義できますが、ヘッダー ファイルには関数シグネチャを含める必要があります。

関数引数が実数または複素型のスカラー、ベクター、または行列の関数をインポートできるほか、固定小数点型を含む Model Composer HLS ライブラリでサポートされるすべてのデータ型を使用できます。Model Composer では、テンプレートとして関数を定義することも可能です。テンプレート変数は入力信号で定義するか、ブロックをモデルに追加したときまたはシミュレーション前に指定する必要のあるカスタマイズ パラメーターとして定義します。コードで関数テンプレートを使用すると、異なるアプリケーションをサポートする Model Composer ブロックを作成でき、ブロック ライブラリの再利用性が高まります。詳細は、関数テンプレートを使用したブロックの定義 を参照してください。

重要: 関数シグネチャはヘッダー ファイルで定義する必要があり、Model Composer (XMC) プラグマはヘッダー ファイルの関数シグネチャの一部として指定する必要があります。

xmcImportFunction コマンドでは、std::complex<T> または hls::x_complex<T> 型を使用する C++ 関数がサポートされます。詳細は、複素型の使用 を参照してください。

インポートした関数の入力が 1-D 配列の場合は、ツールで入力信号と関数引数を一部自動的にマップできます。たとえば、関数引数が a[10] の場合、Model Composer で接続される信号には、サイズ 10 のベクター、あるいは 1x10 または 10x1 サイズの行行列または列行列を使用できます。

ただし、インポートした関数の入力および出力すべてがスカラー引数である場合は、ベクター信号または行列信号を入力に接続できます。この場合、インポートした関数が入力信号のベクターの各値を処理するか、行列を別々の値として処理することで、これらの値を出力信号のベクターまたは行列にまとめます。たとえば、スカラー入力に接続されるサイズが 10 のベクターには、処理されるベクターの各要素が含まれ、出力信号にはサイズ 10 のベクターが返されます。

入力がなく、出力を生成するのみの関数をインポートできます。これはソース ブロックとして知られており、出力のデータ型にはスカラー、ベクター、複素、または行列を使用できます。複数の出力を持つソース ブロックもインポートできます。次の関数例には入力ポートはなく、出力ポートは y です。
#include <stdint.h>
#include <ap_fixed.h>

#pragma XMC OUTPORT y
#pragma XMC PARAMETER Limit
template <typename T>
void counter(T &y, int16_t Limit)
{
    static T count = 0;
    
    count++;
    
    if (count > Limit)
            count =0;    
    y = count;
}
ヒント: ソース ブロックには入力がないので、xmcImportFunction コマンドを使用してブロックを作成すると、次の図の [Function declaration] に示すように、SampleTime パラメーターが自動的に追加されます。デフォルト値は -1 で、サンプル時間はモデルから継承されます。モデルに追加するときにブロックをカスタマイズすることにより、サンプル時間を明示的に指定することもできます。
図 1. ソース ブロックのサンプル時間の設定

関数引数のポートの方向は、xmcImportFunction コマンドで自動的に決定されるか、ヘッダー ファイルの関数シグネチャでプラグマを使用して手動で指定できます。

  • 入力および出力ポートの自動決定:
    • 関数の return 値は、戻り値が void の場合を除き、常に出力として定義されます。
    • const 修飾子で宣言される仮関数引数は、入力として定義されます。
    • 参照、ポインター型、または const 修飾子のない配列型で宣言された引数は、出力として定義されます。
    • その他の引数 (値で読み込まれるスカラーなど) は、デフォルトで入力として定義されます。
  • 入力および出力ポートの手動定義:
    • ヘッダー ファイルの関数宣言の直前に INPORT および OUTPORT プラグマを追加すると、入力および出力として定義する関数引数を指定できます。
    • #pragma XMC INPORT <parameter_name> [, <parameter_name>...]
    • #pragma XMC OUTPORT <parameter_name> [, <parameter_name>...]

次の例では、const 修飾子があるので、in は自動的に入力として定義され、out は出力として定義されます。インポートされたブロックには、関数の return 整数値があるので、2 つ目の出力も含まれます。

int func(const int in, int &out);

次の関数では、in は自動的に入力として定義され、out は出力になりますが、return 値はありません。

void func(const in[512], int out[512]);

次の例では、ソース コードの関数宣言の直前にプラグマを追加することで、ポートが手動で指定されています。関数を Model Composer にインポートする必要のある元の C++ コードに加えた変更はこれだけです。この例の場合、どのパラメーターをブロックの入力にするか、どのパラメーターをブロックの出力にするかをプラグマで指定しています。

#pragma XMC INPORT din
#pragma XMC OUTPORT dout
void fir_sym (ap_fixed<17,3,AP_TRN,AP_WRAP> din[100],
              ap_fixed<17,3,AP_TRN,AP_WRAP> dout[100]);
ヒント: ap_fixedVitis HLS と互換性のある固定小数点を指定しています。

ヘッダー ファイルの関数シグネチャにプラグマを手動で追加して関数の入力および出力パラメーターを定義する方法は、コードに const 修飾子が使用されておらず、関数に階層があり、const 修飾子を追加するためにソース コードを大幅に変更する必要のある場合に便利です。また、入力および出力をコード内で明示的に指定できるので、インポート ブロックとの関連をより明確にできます。

Model Composer にインポートする C または C++ コードを記述する際は、次の点にも注意する必要があります。

  • ソース コードは 32 ビットおよび 64 ビット アーキテクチャ間で移植できるように開発する必要があります。
  • ソース コードには、リソースおよびパフォーマンス最適化に Vitis HLS のプラグマを使用できます。これらのプラグマは Model Composer でも使用されますが、Model Composer により変更されたり追加されたりすることはありません。
  • コードにスタティック変数がある場合、その関数をインポートするブロックのインスタンスすべてで共有されます。この変数をすべてのインスタンスで共有しない場合は、スタティック変数を含む関数をコピーして名前を変更し、xmcImportFunction コマンドを使用して新しいライブラリ ブロックをインポートします。
  • C++ (.cpp) ソース ファイルではなく C (.c) ソース ファイルを使用してライブラリ関数をモデリングする場合は、Vitis HLS などのダウンストリーム ツールのために、.h ヘッダー ファイルに extern "C" 宣言を含める必要があります。次に、ヘッダー ファイルでの extern "C" の宣言例を示します。

    // c_function.h:
    #ifdef __cplusplus
    extern 'C' {
    #endif
    void c_function(int in, int &out);
    #ifdef __cplusplus
    }
    #endif