C++ クラスは、Vitis HLS での合成で完全にサポートされています。合成の最上位は、関数である必要があります。クラスは、合成では最上位にできません。クラスのメンバー関数を合成するには、クラス自体を関数にインスタンシエートする必要があります。最上位クラスは、単にテストベンチにインスタンシエートしないようにしてください。次のコード例は、CFir
クラス (次で説明するヘッダー ファイルで定義) がどのように最上位関数 cpp_FIR
にインスタンシエートされ、FIR
フィルターのインプリメントに使用されるかを示しています。
#include "cpp_FIR.h"
// Top-level function with class instantiated
data_t cpp_FIR(data_t x)
{
static CFir<coef_t, data_t, acc_t> fir1;
cout << fir1;
return fir1(x);
}
上記の C++ FIR フィルターの例で、デザインをインプリメントするために使用されるクラスを調べる前に、Vitis HLS では合成中に標準出力ストリームの cout
が無視されることに注意してください。Vitis HLS で合成されると、次のような警告メッセージが表示されます。
INFO [SYNCHK-101] Discarding unsynthesizable system call:
'std::ostream::operator<<' (cpp_FIR.h:108)
INFO [SYNCHK-101] Discarding unsynthesizable system call:
'std::ostream::operator<<' (cpp_FIR.h:108)
INFO [SYNCHK-101] Discarding unsynthesizable system call: 'std::operator<<
<std::char_traits<char> >' (cpp_FIR.h:110)
次のコード例に示す cpp_FIR.h ヘッダー ファイルには、CFir
クラスの定義およびそれに関連するメンバー関数が含まれています。この例では、演算子のメンバー関数 ()
および <<
はオーバーロードされる演算子です。どちらも main アルゴリズムを実行するために使用され、cout
と共に使用すると C/C++ シミュレーション中に表示されるデータをフォーマットできます。
#include <fstream>
#include <iostream>
#include <iomanip>
#include <cstdlib>
using namespace std;
#define N 85
typedef int coef_t;
typedef int data_t;
typedef int acc_t;
// Class CFir definition
template<class coef_T, class data_T, class acc_T>
class CFir {
protected:
static const coef_T c[N];
data_T shift_reg[N-1];
private:
public:
data_T operator()(data_T x);
template<class coef_TT, class data_TT, class acc_TT>
friend ostream&
operator<<(ostream& o, const CFir<coef_TT, data_TT, acc_TT> &f);
};
// Load FIR coefficients
template<class coef_T, class data_T, class acc_T>
const coef_T CFir<coef_T, data_T, acc_T>::c[N] = {
#include "cpp_FIR.h"
};
// FIR main algorithm
template<class coef_T, class data_T, class acc_T>
data_T CFir<coef_T, data_T, acc_T>::operator()(data_T x) {
int i;
acc_t acc = 0;
data_t m;
loop: for (i = N-1; i >= 0; i--) {
if (i == 0) {
m = x;
shift_reg[0] = x;
} else {
m = shift_reg[i-1];
if (i != (N-1))
shift_reg[i] = shift_reg[i - 1];
}
acc += m * c[i];
}
return acc;
}
// Operator for displaying results
template<class coef_T, class data_T, class acc_T>
ostream& operator<<(ostream& o, const CFir<coef_T, data_T, acc_T> &f) {
for (int i = 0; i < (sizeof(f.shift_reg)/sizeof(data_T)); i++) {
o << shift_reg[ << i << ]= << f.shift_reg[i] << endl;
}
o << ______________ << endl;
return o;
}
data_t cpp_FIR(data_t x);
次のコード例に示される C++ FIR フィルターのテストベンチは、最上位関数 cpp_FIR
がどのように呼び出されて検証されるか示しています。この例には、Vitis HLS 合成用にテストベンチの重要な属性が含まれます。
- 出力結果は、既知の良い値に対して比較されます。
- 結果が正しいと確認されれば、テストベンチは 0 を返します。
#include "cpp_FIR.h"
int main() {
ofstream result;
data_t output;
int retval=0;
// Open a file to saves the results
result.open(result.dat);
// Apply stimuli, call the top-level function and saves the results
for (int i = 0; i <= 250; i++)
{
output = cpp_FIR(i);
result << setw(10) << i;
result << setw(20) << output;
result << endl;
}
result.close();
// Compare the results file with the golden results
retval = system(diff --brief -w result.dat result.golden.dat);
if (retval != 0) {
printf(Test failed !!!\n);
retval=1;
} else {
printf(Test passed !\n);
}
// Return 0 if the test
return retval;
}
cpp_FIR
の C++ テストベンチ
指示子をクラスで定義したオブジェクトに適用するには、次の手順に従ってください。
- クラスが定義されているファイル (通常はヘッダー ファイル) を開きます。
- Directives タブを使用して指示子を適用します。
関数と同様、1 つのクラスのインスタンスはすべて同じ最適化が適用されます。