HLS 関数は、何よりもまず関数です。決まった数の入力と出力があり、関数が呼び出されると、入力を消費して決まった数の出力を生成します。xmcImportFunction
を使用してインポートした HLS 関数がハングした場合 (無限ループがあるなど)、Simulink もインポートされたブロックからの出力を恒久的に待つことになるためハングします。これは、xmcImportFunction
を使用してインポートされた HLS 関数は Simulink と同じスレッドで実行されるからです。インポートされた関数がハングすると、Simulink もハングします。
HLS Kernel は IP
HLS 関数をそれだけデザインにインポートしても、HLS 関数はストリーミング ポートを持つ IP としては機能しません。Vitis Model Composer では、HLS 関数を (ほかの HLS ブロックと共に) サブシステムに含め、Interface Spec ブロックを使用してデザインのストリーミング ポートを指定する必要があります。その後、HLS IP を生成できます。HLS Kernel は、インポートされた HLS 関数とは異なり、 Vitis™ HLS で使用可能な HLS IP であり、直接合成できます。次に、ストリーミング インターフェイスを含む HLS カーネル コードを示します。
hls_kernel.cc
void hls_kernel_blk(
hls::stream<ap_axis<64, 0, 0, 0> > & in_sample1,
hls::stream<ap_axis<64, 0, 0, 0> > & in_sample2,
hls::stream<ap_axis<64, 0, 0, 0> > & out0_itr1,
hls::stream<ap_axis<64, 0, 0, 0> > & out1_itr1
)
{
#pragma HLS PIPELINE II=1
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE axis register both port=out1_itr1
#pragma HLS INTERFACE axis register both port=out0_itr1
#pragma HLS INTERFACE axis register both port=in_sample1
#pragma HLS INTERFACE axis register both port=in_sample2
ap_int64 in_samp0 ; // Iteration-1: 2 complex samples concatenated to 64-bit
ap_int64 in_samp1 ; // Iteration-2: 2 complex samples concatenated to 64-bit
...
この例で、関数シグネチャとポートのインターフェイスを指定する HLS プラグマに注目してください。この関数には、HLS IP に必要なすべてのコンストラクトが含まれます。上記のコードは、HLS Kernel ブロックを使用して Model Composer に直接インポートしてシミュレーションできます。
HLS Kernel ブロックは、可変サイズの信号を受信でき、AI エンジン ブロックに接続して可変サイズの出力信号を生成できます。HLS カーネル ブロックは、xmcImportFunction
を使用してインポートしたブロックとは異なり、Simulink とは別のスレッドで実行されるので、HLS カーネル コードにブロッキング読み出し呼び出しがあっても、入力変数サイズ信号が空のときにも Simulink がハングすることはなく、空の変数サイズ出力信号を生成します。