FPGAの部屋 2020年09月23日
FC2ブログ

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

FPGAの部屋

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

Vivado HLS 2019.2 で合成した IP を Vivado で使ったが動作しなかった4(Vitis 編)

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

Vivado HLS 2019.2 でニューラルネットワークの IP を作成し、Vivado で IP を使用して回路を作成したが、動作しなかった。その顛末を書くことにしたということで、前回は Vivado 2019.2 を使用して、ブロックデザインを作成し、論理合成、インプリメンテーション、ビットストリームの生成を行い、XSA ファイルを作成した。今回は、その XSA ファイルを使用して Vitis 2019.2 のプラットフォームを作成し、アプリケーション・プロジェクトを作成して、実機で検証する。

もうすでに、プラットフォームとアプリケーション・プロジェクトを作成済みの Vitis 2019.2 を示す。前回作成した XSA ファイルを使用してプラットフォームを作成してある。
mnist_nn_17_200923.png

アプリケーション・ソフトウェアの mnist_nn_test.c を示す。

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

#include <stdio.h>
#include <stdint.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]);

#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;
    int mnist_nn_isdone = 0;
    int32_t res;

    printf("Hello World\n");

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

    // Initialize tht Device
    //printf("a"); fflush(stdout);
    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++){
        //printf("a"); fflush(stdout);
        u32 char_num = (u32)(&t_tran_uint8_t[i][0]);
        XMnist_nn_Set_in_V(&mnits_nn_ap, char_num);
        //printf("a"); fflush(stdout);
        XMnist_nn_Start(&mnits_nn_ap);

        while(mnist_nn_isdone == 0)
            mnist_nn_isdone = XMnist_nn_IsDone(&mnits_nn_ap);

        // minst nn result check
        for(int j=0; j<5; j++){
            XMnist_nn_Read_out_V_Words(&mnits_nn_ap, i, &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
        }

        mnist_nn_float(&t_tran_float[i][0], &result_soft[i][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);
}


ZYBO Z7-10 とパソコンを USB ケーブルで接続して、電源を ON にした。
Tera Term を起動した。
Vitis で mnist_nn_test.elf をデバックモードで起動した。
mnist_nn_18_200923.png

Step Over でプログラムを進めていく。
XMnist_nn_Initialize() を実行すると mnist_nn_ap 構造体に値が入った。アドレスの 0x43C00000 も入っている。
mnist_nn_19_200923.png

XMnist_nn_Set_in_V() を実行したところで、止まってしまっている。
mnist_nn_20_200923.png

今までデバッカーを Step Over で実行していたが、XMnist_nn_Set_in_V() を実行するところで、 Step Into に切り替える。
そうすると、ドライバの XMnist_nn_Set_in_V() 関数に来た。
mnist_nn_21_200923.png

XMnist_nn_Set_in_V() 関数の中の XMnist_nn_WriteReg() 関数に飛ぶ。
mnist_nn_22_200923.png

Xil_out32() 関数に飛んで、Value を LocalAddr に書き込む。
LocalAddr は 0x43C00018 で ” 0x18 : Data signal of in_r ”を指しているので、問題ない。
mnist_nn_23_200923.png

だが、これを実行すると DataAbortHandler に飛んでしまうのだ。
mnist_nn_24_200923.png

0x48C00018 番地に書けないようだ。これは困った。なぜだろうか?
  1. 2020年09月23日 04:31 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0