テンプレートは、C++ の強力なツールです。データ型をパラメーターとして渡すことにより、異なるデータ型をサポートするためにコードを記述し直す必要がなくなります。テンプレートは、マクロと同様にコンパイル時に展開されます。違いは、コンパイラがテンプレートを展開する前に型チェックを実行することです。ソース コードにはテンプレート関数とクラス定義が含まれていますが、コンパイルされたコードには同じ関数またはクラスの複数のコピーを含めることができます。型パラメーター、型パラメーター以外のパラメーター、デフォルト引数、スカラー パラメーター、およびテンプレート パラメーターをテンプレートに渡すことができます。それに応じて、コンパイラによりテンプレートに関数またはクラスがインスタンシエートされます。
- 汎用 C++ テンプレート機能をサポート。
- サポートされているデータ型 (T) とカーネル間の接続の種類:
- データ型 (T):
int8
、uint8
、int16
、uint16
、cint16
、int32
、uint32
、cint32
、int64
、uint64
、float
、int4
、uint4
、bfloat16
。重要:acc48
およびcacc48
データ型は、テンプレート ストリーム接続ではサポートされません。
- データ型 (T):
- コンパイラでは、テンプレート カーネルのコンパイル済みヘッダーはサポートされません。
関数テンプレート
関数テンプレートのソース コードは、異なるデータ型に使用可能な汎用関数を定義します。次に、関数テンプレートの例を示します。
// add.h
using namespace adf;
template<typename ELEMENT_TYPE, int FACTOR, size_t NUM_SAMPLES> void add(input_buffer<ELEMENT_TYPE> &in, output_buffer<ELEMENT_TYPE> &out);
// add.cpp
#include <aie_api/aie.hpp>
#include <aie_api/aie_adf.hpp>
using namespace adf;
template<typename ELEMENT_TYPE, int FACTOR, size_t NUM_SAMPLES> void add(input_buffer<ELEMENT_TYPE> &in, output_buffer<ELEMENT_TYPE> &out){
auto inIter=aie::begin(in);
auto outIter=aie::begin(out);
for (int i=0; i<NUM_SAMPLES; i++){
ELEMENT_TYPE value = *inIter++;
value += FACTOR;
*outIter++=value;
}
}
// graph.h
mygraph()
{
k[0] = kernel::create(add<int32, 6, 8>);
k[1] = kernel::create(add<int16, 3, 8>);
for (int i=0; i<NUM_KERNELS; i++)
{
runtime<ratio>(k[i]) = 0.3;
source(k[i]) = "src/add.cpp";
}
connect(in[0], k[0].in[0]);
connect(k[0].out[0], out[0]);
connect(in[1], k[1].in[0]);
connect(k[1].out[0], out[1]);
dimensions(k[0].in[0])={8};
dimensions(k[0].out[0])={8};
dimensions(k[1].in[0])={8};
dimensions(k[1].out[0])={8};
}
説明:
-
add.h: テンプレート
add()
関数を定義します。 -
add.cpp: テンプレート
add()
関数のコードを定義します。 -
graph.h:
mygraph
クラス内のテンプレートadd()
関数を使用します。
クラス テンプレート
クラス テンプレートは、関数テンプレートと同様、特定のデータ型とは独立したオブジェクトをクラスで定義する場合に便利です。次に、クラス テンプレートの例を示します。
// fir.h
...
template<size_t NUM_COEFFS, typename ELEMENT_TYPE> class FIR
{
private:
ELEMENT_TYPE (&coeffs)[NUM_COEFFS];
ELEMENT_TYPE tapDelayLine[NUM_COEFFS];
uint32 numSamples;
public:
FIR(ELEMENT_TYPE(&coefficients)[NUM_COEFFS], uint32 samples);
void filter(input_buffer<ELEMENT_TYPE> &in, output_buffer<ELEMENT_TYPE> &out);
//user needs to write this function to register necessary info
static void registerKernelClass()
{
REGISTER_FUNCTION(FIR::filter);
REGISTER_PARAMETER(coeffs);
}
}
// fir.cpp
...
template<size_t NUM_COEFFS, typename ELEMENT_TYPE> FIR<NUM_COEFFS, ELEMENT_TYPE>::FIR(ELEMENT_TYPE(&coefficients)[NUM_COEFFS], uint32 samples):coeffs(coefficients)
{
...
}
template<size_t NUM_COEFFS, typename ELEMENT_TYPE> void FIR<NUM_COEFFS,ELEMENT_TYPE>::filter(input_buffer<ELEMENT_TYPE> &in, output_buffer<ELEMENT_TYPE> &out)
{
...
}
// graph.h
...
mygraph()
{
k1 = kernel::create_object<FIR<12, int32>>(std::vector<int>({ 180, 89, -80, -391, -720, -834, -478, 505, 2063, 3896, 5535, 6504 }), 8);
runtime<ratio>(k1) = 0.1;
source(k1) = "src/fir.cpp";
headers(k1) = { "src/fir.h" };
k2 = kernel::create_object<FIR<15, int32>>(std::vector<int>({ -21, -249, 319, -78, -511, 977, -610, -844, 2574, -2754, -1066, 18539, 0, 0, 0 }), 8);
runtime<ratio>(k2) = 0.1;
source(k2) = "src/fir.cpp";
headers(k2) = { "src/fir.h" };
...
}
説明:
-
fir.h: クラス
FIR
が宣言されているクラス テンプレートを定義します。 -
fir.cpp: クラス
FIR
のインプリメンテーションとクラスFIR
メンバー関数のfilter
インプリメンテーションを含みます。 -
graph.h:
mygraph
クラス内のテンプレート クラスFIR
インスタンシエーションを示します。