FC2カウンター FPGAの部屋 2018年10月02日
FC2ブログ

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

FPGAの部屋

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

ZYBOt の白線間走行用CNNをVivado HLS 2018.2 で試しに実装した

ZYBOt のコースをKeras で学習した”の続き。

(2018/10/03:変更)
(2018/10/06 : 修正)画像を増やすスクリプトが間違っていたので、間違いを修正してやり直しました。


前回は、今まで作ってきたトレーニング・ファイルやラベル・ファイル、テスト・ファイルやラベル・ファイルを使用して、Keras で学習させ、重みやバイアスをC ヘッダ・ファイルに出力した。今回は、その重みやバイアスのC ヘッダ・ファイルを使用してVivado HLS 2018.2 でプロジェクトを作成して、量子化ビット長を設定し、C シミュレーションとC コードの合成を行う。

まずは、Vivado HLS 2018.2 の course_conv_nn2 プロジェクトを示す。
ZYBOt_Keras_28_180930

course_conv_nn2.cpp を貼っておく。

// course_conv_nn2.cpp
// 2018/09/30 by marsee
// 畳み込み層のカーネル数 2
//

#include <ap_fixed.h>

#include "conv1_weight.h"
#include "conv1_bias.h"
#include "af1_weight.h"
#include "af1_bias.h"
#include "af2_weight.h"
#include "af2_bias.h"

#define NUM_OF_KERNELS 2
#define COULMN_PIXELS 56
#define ROW_PIXELS 10
#define ALL_PIXELS 560
#define NUM_OF_OUTPUT 3

int course_conv_nn(ap_ufixed<8, 0, AP_TRN_ZERO, AP_SAT> in[ALL_PIXELS], ap_fixed<12, 7, AP_TRN_ZERO, AP_SAT> out[NUM_OF_OUTPUT]){
    ap_ufixed<8, 0, AP_TRN_ZERO, AP_SAT> buf[ROW_PIXELS][COULMN_PIXELS];
    ap_fixed<13, 3, AP_TRN_ZERO, AP_SAT> conv_out[NUM_OF_KERNELS][ROW_PIXELS-4][COULMN_PIXELS-4];
    ap_fixed<13, 3, AP_TRN_ZERO, AP_SAT> pool_out[NUM_OF_KERNELS][(ROW_PIXELS-4)/2][(COULMN_PIXELS-4)/2];
    ap_fixed<16, 5, AP_TRN_ZERO, AP_SAT> dot1[100];
    ap_fixed<16, 7, AP_TRN_ZERO, AP_SAT> dot2[NUM_OF_OUTPUT];

    buf_copy1: for(int i=0; i<ROW_PIXELS; i++)
        buf_copy2: for(int j=0; j<COULMN_PIXELS; j++)
            buf[i][j] = in[i*COULMN_PIXELS+j];

    // Convolutional Neural Network 5x5 kernel, Stride = 1, Padding = 0
    // + ReLU
    CONV1: for(int i=0; i<NUM_OF_KERNELS; i++){ // カーネルの個数
        CONV2: for(int j=0; j<ROW_PIXELS-4; j++){
            CONV3: for(int k=0; k<COULMN_PIXELS-4; k++){
                conv_out[i][j][k] = 0;
                CONV4: for(int m=0; m<5; m++){
                    CONV5: for(int n=0; n<5; n++){
                        conv_out[i][j][k] += buf[j+m][k+n] * conv1_weight[i][0][m][n];
                    }
                }
                conv_out[i][j][k] += conv1_bias[i];

                if(conv_out[i][j][k]<0) // ReLU
                    conv_out[i][j][k] = 0;
            }
        }
    }

    // Pooling Kernel = 2 x 2, Stride = 2
    POOL1: for(int i=0; i<NUM_OF_KERNELS; i++){
        POOL2: for(int j=0; j<ROW_PIXELS-4; j += 2){
            POOL3: for(int k=0; k<COULMN_PIXELS-4; k += 2){
                POOL4: for(int m=0; m<2; m++){
                    POOL5: for(int n=0; n<2; n++){
                        if(m==0 && n==0){
                            pool_out[i][j/2][k/2] = conv_out[i][j][k];
                        } else if(pool_out[i][j/2][k/2] < conv_out[i][j+m][k+n]){
                            pool_out[i][j/2][k/2] = conv_out[i][j+m][k+n];
                        }
                    }
                }
            }
        }
    }

    af1_dot1: for(int col=0; col<100; col++){
        dot1[col] = 0;
        af1_dot2: for(int i=0; i<NUM_OF_KERNELS; i++){
            af1_dot3: for(int j=0; j<(ROW_PIXELS-4)/2; j++){
                af1_dot4: for(int k=0; k<(COULMN_PIXELS-4)/2; k++){
                    dot1[col] += pool_out[i][j][k]*af1_weight[i*((ROW_PIXELS-4)/2)*((COULMN_PIXELS-4)/2)+j*((COULMN_PIXELS-4)/2)+k][col];
                }
            }
        }
        dot1[col] += af1_bias[col];

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

    af2_dot1: for(int col=0; col<NUM_OF_OUTPUT; col++){
        dot2[col] = 0;
        af2_dot2: for(int row=0; row<100; row++){
            dot2[col] += dot1[row]*af2_weight[row][col];
        }
        dot2[col] += af2_bias[col];

        out[col] = dot2[col];
    }

    return(0);
}


C シミュレーションを行った。
ZYBOt_Keras_45_181006

ハードウェアのエラーは 98.9 % 、ソフトウェアのエラーは 99.0 % だった。これは 1000 個のデータでの精度なので、他の部分ではもっと精度が悪いことが考えられる。というのも、”ZYBOt のコースをKeras で学習した”では、テスト・データでの精度は、約 92.4 % だからだ。
すべてのログを示す。

INFO: [SIM 2] *************** CSIM start ***************
INFO: [SIM 4] CSIM will launch GCC as the compiler.
   Compiling ../../../course_conv_nn2_tb.cpp in debug mode
   Compiling ../../../course_conv_nn2.cpp in debug mode
   Generating csim.exe
id = 38, max_id_ref = 0, max_id_hw = 2
id = 38, max_id_ref = 0, max_id_sw = 2
id = 45, max_id_ref = 2, max_id_hw = 1
id = 45, max_id_ref = 2, max_id_sw = 1
id = 47, max_id_ref = 0, max_id_hw = 1
id = 47, max_id_ref = 0, max_id_sw = 1
id = 74, max_id_ref = 0, max_id_hw = 1
id = 74, max_id_ref = 0, max_id_sw = 1
id = 114, max_id_ref = 2, max_id_hw = 1
id = 114, max_id_ref = 2, max_id_sw = 1
id = 117, max_id_ref = 0, max_id_hw = 1
id = 117, max_id_ref = 0, max_id_sw = 1
id = 124, max_id_ref = 0, max_id_hw = 2
id = 124, max_id_ref = 0, max_id_sw = 2
id = 133, max_id_ref = 2, max_id_hw = 1
id = 133, max_id_ref = 2, max_id_sw = 1
id = 137, max_id_ref = 2, max_id_hw = 1
id = 137, max_id_ref = 2, max_id_sw = 1
id = 139, max_id_ref = 1, max_id_hw = 2
id = 142, max_id_ref = 2, max_id_hw = 1
id = 142, max_id_ref = 2, max_id_sw = 1

hw_err_cnt = 11, sw_err_cnt = 10
hw accuracy = 98.900002%, sw accuracy = 99.000001%

INFO: [SIM 1] CSim done with 0 errors.
INFO: [SIM 3] *************** CSIM finish ***************



次に C コードの合成を行った。ここでは、あくまで目安の値を確認することを目的としている。実際に使用するIP はDMA を付ける必要があるので、後で実装する。
ZYBOt_Keras_46_181006
ZYBOt_Keras_47_181006

Estimated は 8.25 ns だった。Latency は 171774 クロックで、100 MHz クロックでは、約 1.72 ms となる。
リソース使用量は、BRAM_18K が 13 個、DSP48E が 8 個、FF が 726 個、LUT が 2531 個だった。
  1. 2018年10月02日 05:01 |
  2. Zybot
  3. | トラックバック:0
  4. | コメント:0