FC2カウンター FPGAの部屋 Vivado HLS 2019.2 で合成した IP を Vivado で使ったが動作しなかった8(動作しました)
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

Vivado HLS 2019.2 で合成した IP を Vivado で使ったが動作しなかった8(動作しました)

Vivado HLS 2019.2 で合成した IP を Vivado で使ったが動作しなかった7(デバック編 3)”の続き。

Vivado HLS 2019.2 でニューラルネットワーク(NN)の IP を作成し、Vivado で IP を使用して回路を作成したが、動作しないという問題があった。これは、NN IP への AXI4-Lite インターフェースのトランザクションが出ていなかったが、”Vivado HLS 2019.2 で合成した IP を Vivado で使ったが動作しなかった7(デバック編 3)”で、main() 関数のソフトウェアによるニューラルネットワークを計算する部分を削除すると、NN IP への AXI4-Lite インターフェースのトランザクションが出るようになった。そこで、”Vitis のデフォルトの Stack size, Heap size は 8k バイトだった”で、スタックサイズを 128 k バイトに拡大すると、main() 関数のソフトウェアによるニューラルネットワークを計算する部分を削除しなくても AXI4-Lite インターフェースのトランザクションが出るようになった。Run すると正常な出力が出た。完成だ。結局 script.ld のスタック容量が足りないのが原因だったようだ。心配していたバイトレーンのエンディアンの影響も無かった。

まずは、Vitis の GUI 画面を示す。mnist_nn_test アプリケーション・プロジェクトを使用する。
mnist_nn_61_200929.png

、”Vitis のデフォルトの Stack size, Heap size は 8k バイトだった”で、スタックサイズを 128 k バイトに拡大した。
mnist_nn_60_200928.png

Vitis の Assistant ウインドウの mnist_nn_test_system -> mnist_nn_test -> Debug を右クリックし、右クリックメニューから Run -> Run Configuration を指定して Run する。
mnist_nn_62_200929.png

Tera Term に結果が表示された。これは正しい。
mnist_nn_68_200929.png

なお、実行時間も計測してみた。ハードウェアが約 2.39 ms 、ソフトウェアが約 2.59 ms で、ハードウェアの方がわずかに速いという結果になった。(なお、NN IP の動作周波数は 50 MHz で、当初の 100 MHz の 1/2 になっている。C コードの合成でのレイテンシは動作周波数 100 MHz で 1.18 ms だった。)

これで正常動作でめでたいのだが、この mnist_nn は Vivado HLS および Vitis HLS のバージョンによって IP の大きさにとっても差があるので、書いておきたい。なお、ソースコードは”Vivado HLS 2019.2 で合成した IP を Vivado で使ったが動作しなかった1(Vivado HLS 編 1)”に貼ってある。

まずは、今使用している Vivado HLS 2019.2 、Vivado HLS 2018.3、Vitis HLS 2020.1、Vivado HLS 2017.4 の Export RTL のレポートを示す。
mnist_nn_64_200929.pngmnist_nn_65_200929.pngmnist_nn_66_200929.pngmnist_nn_67_200929.png

Vivado HLS 2019.2 と 2018.3 の BRAM 使用量は 6 個だが、Vitis HLS 2020.1 の BRAM 使用量は 43 個、Vivado HLS 2017.4 の BRAM 使用量は 42 個だった。何でこんなに違うのだろうか?
Vivado HLS 2019.2 の IP は動作した。Vitis HLS 2020.1 で作った IP も Vivado 2019.2 のブロックデザインに入れてみたが動作した。Vitis HLS 2020.1 の IP のレイテンシは約 400 us なので、Vivado HLS 2019.2 よりも 2 倍以上速い。

最後に現在の mnist_nn_test.c を貼っておく。

// mnist_nn_test.c
// 2020/09/08 by marsee
//

#include <stdio.h>
#include <stdint.h>

#include "xtime_l.h"

#include "af1_weight_float.h"
#include "af1_bias_float.h"
#include "af2_weight_float.h"
#include "af2_bias_float.h"
#include "mnist_data_10.h"
#include "xmnist_nn.h"

int mnist_nn_float(float in[784], float out[10]);
int max_float(float out[10]);
int max_int32_t(int32_t out[10]);

void Xil_DCacheFlush(void);

#define NUM_ITERATIONS    10 // C Simulation
// #define NUM_ITERATIONS    2 // C/RTL CoSimulation

int main(){
    float t_tran_float[NUM_ITERATIONS][784];
    uint8_t t_tran_uint8_t[NUM_ITERATIONS][784];
    int32_t result_hard[NUM_ITERATIONS][10];
    float result_soft[NUM_ITERATIONS][10];
    int max_id_hw, max_id_sw, max_id_ref;
    XMnist_nn mnits_nn_ap;
    int32_t res;
    XTime hw_start_time, hw_end_time;
    XTime sw_start_time, sw_end_time;

    for(int i=0; i<NUM_ITERATIONS; i++){
        for(int j=0; j<784; j++){
            t_tran_float[i][j] = (float)(t_train_256[i][j])/256.0;
            t_tran_uint8_t[i][j] = (uint32_t)(t_train_256[i][j]);
        }
    }
    Xil_DCacheFlush();

    // Initialize tht Device
    int XMinst_status = XMnist_nn_Initialize(&mnits_nn_ap, 0);
    if (XMinst_status != XST_SUCCESS){
        fprintf(stderr, "Could not Initialize XMnist_nn\n");
        return(-1);
    }

    for(int i=0; i<NUM_ITERATIONS; i++){
        u32 char_num = (u32)(&t_tran_uint8_t[i][0]);
        XMnist_nn_Set_in_V(&mnits_nn_ap, char_num);

        XTime_GetTime(&hw_start_time);
        XMnist_nn_Start(&mnits_nn_ap);

        while(!XMnist_nn_IsDone(&mnits_nn_ap));
        XTime_GetTime(&hw_end_time);

        // minst nn result check
        for(int j=0; j<5; j++){
            XMnist_nn_Read_out_V_Words(&mnits_nn_ap, j, &res, 1);
            result_hard[i][j*2] = res & 0x1fff; // 13 bit
            if(result_hard[i][j*2] & 0x1000) // minus
                result_hard[i][j*2] = 0xffffe000 | result_hard[i][j*2]; // Sign extension

            result_hard[i][j*2+1] = (res & 0x1fff0000) >> 16;
            if(result_hard[i][j*2+1] & 0x1000) // minus
                result_hard[i][j*2+1] = 0xffffe000 | result_hard[i][j*2+1]; // Sign extension
        }
        XTime_GetTime(&sw_start_time);
        mnist_nn_float(&t_tran_float[i][0], &result_soft[i][0]);
        XTime_GetTime(&sw_end_time);
        printf("i = %d, HW Execution time = %lf ms, SW Execution time = %lf ms\n", i,
                (double)((long long int)hw_end_time-(long long int)hw_start_time)/333333.0,
                (double)((long long int)sw_end_time-(long long int)sw_start_time)/333333.0);
    }

    int errflag=0;
    for(int i=0; i<NUM_ITERATIONS; i++){
        max_id_hw = max_int32_t(&result_hard[i][0]);
        max_id_sw = max_float(&result_soft[i][0]);
        max_id_ref = max_float(&t_test[i][0]);

        if(max_id_ref != max_id_hw){
            printf("id = %d, max_id_ref = %d, max_id_hw = %d\n", i, max_id_ref, max_id_hw);
            errflag = 1;
        }
        if(max_id_ref != max_id_sw){
            printf("id = %d, max_id_ref = %d, max_id_sw = %d\n", i, max_id_ref, max_id_sw);
            errflag = 1;
        }
    }
    if(errflag == 0)
        printf("No Error\n");

    return(0);
}

int mnist_nn_float(float in[784], float out[10]){
    float dot1[50];
    float dot2[10];

    for(int col=0; col<50; col++){
        dot1[col] = 0;
        for(int row=0; row<784; row++){
            dot1[col] += in[row]*af1_fweight[row][col];
        }
        dot1[col] += af1_fbias[col];

        if(dot1[col] < 0)    // ReLU
            dot1[col] = 0;
    }

    for(int col=0; col<10; col++){
        dot2[col] = 0;
        for(int row=0; row<50; row++){
            dot2[col] += dot1[row]*af2_fweight[row][col];
        }
        dot2[col] += af2_fbias[col];

        if(dot2[col] < 0)    // ReLU
            dot2[col] = 0;
        out[col] = dot2[col];
    }

    return(0);
}

int max_float(float out[10]){
    int max_id;
    float max;

    for(int i=0; i<10; i++){
        if(i == 0){
            max = out[0];
            max_id = 0;
        }else if(out[i]>max){
            max = out[i];
            max_id = i;
        }
    }
    return(max_id);
}

int max_int32_t(int32_t out[10]){
    int max_id;
    int32_t max;

    for(int i=0; i<10; i++){
        if(i == 0){
            max = out[0];
            max_id = 0;
        }else if(out[i]>max){
            max = out[i];
            max_id = i;
        }
    }
    return(max_id);
}

  1. 2020年09月29日 05:09 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/5013-7313287b
この記事にトラックバックする(FC2ブログユーザー)