テストベンチ例 - 2023.2 日本語

Vitis 高位合成ユーザー ガイド (UG1399)

Document ID
UG1399
Release Date
2023-12-18
Version
2023.2 日本語

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;
}