C++ の特徴の 1 つに、再帰テンプレートがあります。グラフは再帰テンプレートを利用することで再帰的に作成できます。
template<int Level>
class RecursiveGraph: public adf::graph {
private:
adf::kernel k;
RecursiveGraph<Level-1> RG;
public:
adf::port<input> din;
adf::port<output> dout;
RecursiveGraph() {
k = adf::kernel::create(passthrough);
adf::source(k) = "kernels.cpp";
adf::runtime<ratio>(k) = 0.9;
adf::connect(din, k.in[0]);
adf::connect(k.out[0], RG.din);
adf::connect(RG.dout, dout);
};
};
template<>
class RecursiveGraph<1>: public adf::graph {
private:
adf::kernel k;
public:
adf::port<input> din;
adf::port<output> dout;
RecursiveGraph() {
k = adf::kernel::create(passthrough);
adf::source(k) = "kernels.cpp";
adf::runtime<ratio>(k) = 0.9;
adf::connect(din, k.in[0]);
adf::connect(k.out[0], dout);
};
};
クラス RecursiveGraph
は、再帰関数の深さを表すテンプレート パラメーター Level
でパラメーター指定されます。RecursiveGraph
クラス内で、テンプレート パラメター Level-1
を使用して RecursiveGraph<Level-1> RG;
と同じクラスのインプリメンテーションが実行されます。これにより、RecursiveGraph
が Level-1
回繰り返しインスタンシエートされます。RecursiveGraph<1>
クラスの特殊化は、再帰のストップ コンディションとして動作します。
class TestRecursiveGraph: public adf::graph {
public:
adf::input_plio plin;
adf::output_plio plout;
RecursiveGraph<5> Recursive;
TestRecursiveGraph()
{
plin = adf::input_plio::create("input",adf::plio_64_bits,"data/Input_64.txt",500);
adf::connect(plin.out[0],Recursive.din);
plout = adf::output_plio::create("output",adf::plio_64_bits,"data/Output.txt",500);
adf::connect(Recursive.dout,plout.in[0]);
};
};
この例では、RecursiveGraph
のインスタンスが 5 つ、TestRecursiveGraph
グラフにインスタンシエートされます。
TestRecursiveGraph RecursiveUnitTest;
int main(int argc, char ** argv) {
RecursiveUnitTest.init();
RecursiveUnitTest.run(NFRAMES*NITERATIONS);
RecursiveUnitTest.end();
return 0;
}
次に、Vitis アナライザーで得られる再帰グラフをシーケンシャル グラフと対比させて示します。
図 1. 再帰グラフとシーケンシャル グラフによる複数カーネルの表示
グラフ表示で、再帰性によって得られた階層が確認できます。