AMDでは、合成用の最上位関数はテストベンチとは分けて記述し、ヘッダー ファイルを使用する方法をお勧めします。次に、HLS プロジェクトの最上位関数 hier_func
が次の 2 つのサブ関数を呼び出すデザインのコード例を示します。
-
sumsub_func
: 加算および減算を実行。 -
shift_func
: シフトを実行。
データ型はヘッダー ファイル ファイル (hier_func.h) で定義されています。関数のコードは次のとおりです。
#include "hier_func.h"
int sumsub_func(din_t *in1, din_t *in2, dint_t *outSum, dint_t *outSub)
{
*outSum = *in1 + *in2;
*outSub = *in1 - *in2;
}
int shift_func(dint_t *in1, dint_t *in2, dout_t *outA, dout_t *outB)
{
*outA = *in1 >> 1;
*outB = *in2 >> 2;
}
void hier_func(din_t A, din_t B, dout_t *C, dout_t *D)
{
dint_t apb, amb;
sumsub_func(&A,&B,&apb,&amb);
shift_func(&apb,&amb,C,D);
}
最上位関数には複数のサブ関数を含めることができますが、合成できるのは 1 つの最上位関数のみです。複数の関数を合成するには、それらをサブ関数として 1 つの最上位関数にまとめます。
次に示すヘッダー ファイル (hier_func.h
) に、マクロの使用方法と、typedef
文を使用することでコードの移植性および読みやすさを向上できることを示します。
ヒント:
任意精度 (AP) 型 には、
typedef
文で任意精度型を使用できること、それにより最終的な FPGA インプリメンテーションでエリアとパフォーマンスの両方を向上するために変数のビット幅を調整できることが説明されています。#ifndef _HIER_FUNC_H_
#define _HIER_FUNC_H_
#include <stdio.h>
#define NUM_TRANS 40
typedef int din_t;
typedef int dint_t;
typedef int dout_t;
void hier_func(din_t A, din_t B, dout_t *C, dout_t *D);
#endif
上記のヘッダー ファイルには、NUM_TRANS
などの #define
文が含まれています。これは hier_func
関数には必要ありませんが、同じヘッダー ファイルを含むテストベンチ用に含まれています。
次に、hier_func
デザインのテストベンチを定義するコードを示します。
#include "hier_func.h"
int main() {
// Data storage
int a[NUM_TRANS], b[NUM_TRANS];
int c_expected[NUM_TRANS], d_expected[NUM_TRANS];
int c[NUM_TRANS], d[NUM_TRANS];
//Function data (to/from function)
int a_actual, b_actual;
int c_actual, d_actual;
// Misc
int retval=0, i, i_trans, tmp;
FILE *fp;
// Load input data from files
fp=fopen(tb_data/inA.dat,r);
for (i=0; i<NUM_TRANS; i++){
fscanf(fp, %d, &tmp);
a[i] = tmp;
}
fclose(fp);
fp=fopen(tb_data/inB.dat,r);
for (i=0; i<NUM_TRANS; i++){
fscanf(fp, %d, &tmp);
b[i] = tmp;
}
fclose(fp);
// Execute the function multiple times (multiple transactions)
for(i_trans=0; i_trans<NUM_TRANS-1; i_trans++){
//Apply next data values
a_actual = a[i_trans];
b_actual = b[i_trans];
hier_func(a_actual, b_actual, &c_actual, &d_actual);
//Store outputs
c[i_trans] = c_actual;
d[i_trans] = d_actual;
}
// Load expected output data from files
fp=fopen(tb_data/outC.golden.dat,r);
for (i=0; i<NUM_TRANS; i++){
fscanf(fp, %d, &tmp);
c_expected[i] = tmp;
}
fclose(fp);
fp=fopen(tb_data/outD.golden.dat,r);
for (i=0; i<NUM_TRANS; i++){
fscanf(fp, %d, &tmp);
d_expected[i] = tmp;
}
fclose(fp);
// Check outputs against expected
for (i = 0; i < NUM_TRANS-1; ++i) {
if(c[i] != c_expected[i]){
retval = 1;
}
if(d[i] != d_expected[i]){
retval = 1;
}
}
// Print Results
if(retval == 0){
printf( *** *** *** *** \n);
printf( Results are good \n);
printf( *** *** *** *** \n);
} else {
printf( *** *** *** *** \n);
printf( Mismatch: retval=%d \n, retval);
printf( *** *** *** *** \n);
}
// Return 0 if outputs are corre
return retval;
}