グラフには、カーネルとサブグラフを混在させることができます。複数のカーネルをインスタンシエートする場合は、配列として、または特定の名前を付けて宣言できます。次の例では、テンプレート パラメーターで、配列として宣言されるカーネルの数を指定しています。
template <int NK>
class MultiKernelGraph: public adf::graph {
private:
adf::kernel k[NK];
public:
adf::port<input> din;
adf::port<output> dout;
MultiKernelGraph() {
for(int i=0;i<NK;i++)
{
k[i] = adf::kernel::create(passthrough);
adf::source(k[i]) = "kernels.cpp";
adf::runtime<ratio>(k[i]) = 0.9;
}
adf::connect(din, k[0].in[0]);
for(int i=0;i<NK-1;i++)
adf::connect(k[i].out[0], k[i+1].in[0]);
adf::connect(k[NK-1].out[0], dout);
};
};
class TestGraphMulti: public adf::graph {
public:
adf::input_plio plin;
adf::output_plio plout;
MultiKernelGraph<3> Multi;
TestGraphMulti()
{
plin = adf::input_plio::create("input2",adf::plio_64_bits,"data/Input_64.txt",500);
adf::connect(plin.out[0],Multi.din);
plout = adf::output_plio::create("output2",adf::plio_64_bits,"data/Output2.txt",500);
adf::connect(Multi.dout,plout.in[0]);
};
};
図 1. グラフ ビュー
前述のとおり、グラフはカーネルとサブグラフを含むことができます。テストベンチ .cpp のコードは、複数のグラフをインスタンシエートし、個別に実行できます。
TestGraphSimple Simple_UnitTest;
TestGraphMulti Multi_UnitTest;
int main(int argc, char ** argv) {
Simple_UnitTest.init();
Multi_UnitTest.init();
Simple_UnitTest.run(NFRAMES*NITERATIONS);
Multi_UnitTest.run(NFRAMES*NITERATIONS);
Simple_UnitTest.end();
Multi_UnitTest.end();
return 0;
}
Vitis IDE では、グラフ ビューに 2 つの独立したグラフが表示されます。
図 2. 複数のグラフ
これら 2 つのグラフは、テストベンチにインスタンシエートされる 3 つ目のグラフに含めることも可能です。
class TestGraph: public adf::graph {
public:
adf::input_plio plin1,plin2;
adf::output_plio plout1,plout2;
SimplestGraph Simple;
MultiKernelGraph Multi;
TestGraph()
{
plin1 = adf::input_plio::create("input1",adf::plio_64_bits,"data/Input_64.txt",500);
adf::connect(plin1.out[0],Simple.din);
plout1 = adf::output_plio::create("output1",adf::plio_64_bits,"data/Output1.txt",500);
adf::connect(Simple.dout,plout1.in[0]);
plin2 = adf::input_plio::create("input2",adf::plio_64_bits,"data/Input_64.txt",500);
adf::connect(plin2.out[0],Multi.din);
plout2 = adf::output_plio::create("output2",adf::plio_64_bits,"data/Output2.txt",500);
adf::connect(Multi.dout,plout2.in[0]);
};
};
TestGraph UnitTest;
int main(int argc, char ** argv) {
UnitTest.init();
UnitTest.run(NFRAMES*NITERATIONS);
UnitTest.end();
return 0;
}
図 3. 複合グラフ ビュー
シーケンシャル カーネルやパラレル カーネルを含むより複雑なグラフを作成できます。この複雑なグラフでは、データフローがグラフ全体で複数回分割および統合され、AI エンジン アレイを介してバッファーやストリームを使用してデータが転送されます。
VeryComplexGraph() {
// Declare Kernels
for(int i=0;i<2;i++)
{
simple[i] = adf::kernel::create(passthrough);
adf::source(simple[i]) = "kernels.cpp";
adf::runtime<ratio>(simple[i]) = 0.9;
}
// Connections
// Inputs
connect(din[0],split[0].din);
connect(din[1],split[1].din);
// Outputs
connect(merge[2].dout,dout[0]);
connect(split[3].dout[0],dout[1]);
connect(split[3].dout[1],dout[2]);
// Internal connections
connect(split[0].dout[0],multi3.din);
connect(multi3.dout,merge[2].din[0]);
connect(split[0].dout[1],merge[0].din[0]);
connect(split[1].dout[0],merge[0].din[1]);
connect(merge[0].dout,simple[0].in[0]);
connect(simple[0].out[0],split[2].din);
connect(split[2].dout[0],multi2[1].din);
connect(multi2[1].dout,merge[2].din[1]);
connect(split[2].dout[1],simple[1].in[0]);
connect(simple[1].out[0],merge[1].din[0]);
connect(split[1].dout[1],multi2[0].din);
connect(multi2[0].dout,merge[1].din[1]);
connect(merge[1].dout,split[3].din);
};
図 4. 複雑なグラフ ビュー
このグラフ ビューでは、複雑なデータフローが複数のポイントで分割および統合されていることがわかります。データフローの一部が PL に出入りする必要がある場合、リンク フェーズで PL カーネルに接続する、対応する出力ポートと入力ポートが表示されます。