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

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

FPGAの部屋

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

Vivado HLS 2017.4 で片方が定数の場合の乗算の検討6(畳み込み演算3)

Vivado HLS 2017.4 で片方が定数の場合の乗算の検討5(畳み込み演算2)”の続き。

前回は、乗算記号の * を使用して、畳み込みニューラルネットワークの畳み込み演算の重みを定数と置いたときの乗算で途中の演算の小数点以下の精度を下げてやってみた。今回は、従来通りの畳み込み演算の重みの配列を使用して、LUT にマップした演算ができないかどうか?を確かめてみた。

さて、Vivado HLS 2017.4 で multi_test3 プロジェクトを作成した。
multi_test_48_180203.png

multi_test3.cpp を貼っておく。

// multi_test3.cpp
// 2018/01/30 by marsee
//

#include <ap_fixed.h>
#include "multi_test3.h"
#include "conv1_weight.h"

int multi_test3(ap_ufixed_in in[25], ap_fixed_add &out){
#pragma HLS ARRAY_PARTITION variable=in complete dim=1
#pragma HLS PIPELINE II=1

    ap_fixed_madd out_temp = 0.0;
#pragma HLS RESOURCE variable=out_temp core=AddSub

    conv1: for(int m=0; m<5; m++){
#pragma HLS UNROLL
        conv2: for(int n=0; n<5; n++){
            out_temp += in[m*5+n] * conv1_weight[0][0][m][n];
        }
    }

    out = out_temp;

    return(0);
}


ご覧の様に、今までやってたように for ループを使用しているが、unroll 指示子でループを展開して、RESOURCE 指示子で AddSub を指定すれば、LUT を使用してくれるようだ。

次に、multi_test3.h を示す。

// multi_test3.h
// 2018/01/30 by marsee
//

#ifndef __multi_test_H__
#define __multi_test_H__
#include <ap_fixed.h>

typedef ap_ufixed<80, AP_TRN, AP_WRAP> ap_ufixed_in;
typedef ap_fixed<91, AP_TRN, AP_WRAP> ap_fixed_weight;
typedef ap_fixed<226, AP_TRN, AP_WRAP> ap_fixed_madd;
typedef ap_fixed<166, AP_TRN_ZERO, AP_SAT> ap_fixed_add;

#endif


conv_weight.h を示す。

// conv1_weight.h
// 2017/12/06 10:54:11 by marsee

const float conv1_fweight[2][1][5][5] = 
{
    {
        {
            {0.764403421227,0.658424746889,0.595604201652,0.554044871161,0.367767232883},
            {0.582414155838,0.413274869036,0.31659268154,0.3508390519,0.331194144626},
            {0.589182274309,0.462105790282,-0.241299390378,-0.10093021104,0.233291757594},
            {0.792411286764,0.315893121865,0.0397628864727,0.356726636694,0.426826537165},
            {0.634481192118,0.651475977113,0.688949928547,0.707285991358,0.681420943406}
        }
    }
    ,
    {
        {
            {0.00564732125401,-0.012955272371,-0.0231571581103,-0.00289983746176,0.0281080593816},
            {-0.0115360072012,0.00253310449813,-0.00860163957467,0.00112793810127,-0.01455040341},
            {-0.00881717612899,-0.00902248113722,0.0004194288468,0.00110240651437,-0.0140454059394},
            {0.00271556513713,-0.00307791921855,0.000117170379207,-0.00891721414879,0.0173026634286},
            {0.000808453898046,0.000116327205532,-0.00275343050716,-0.00683461392689,-0.0169130858704}
        }
    }
};

const ap_fixed<91, AP_TRN, AP_WRAP> conv1_weight[2][1][5][5] =
{
    {
        {
            {0.765625,0.66015625,0.59375,0.5546875,0.3671875},
            {0.58203125,0.4140625,0.31640625,0.3515625,0.33203125},
            {0.58984375,0.4609375,-0.23828125,-0.09765625,0.234375},
            {0.79296875,0.31640625,0.0390625,0.35546875,0.42578125},
            {0.6328125,0.65234375,0.6875,0.70703125,0.6796875}
        }
    }
    ,
    {
        {
            {0.00390625,-0.0078125,-0.01953125,0.0,0.02734375},
            {-0.0078125,0.00390625,-0.00390625,0.0,-0.01171875},
            {-0.00390625,-0.00390625,0.0,0.0,-0.01171875},
            {0.00390625,0.0,0.0,-0.00390625,0.015625},
            {0.0,0.0,0.0,-0.00390625,-0.01171875}
        }
    }
};


multi_test3_tb.cpp を示す。

// multi_test3_tb.h
// 2018/01/30 by marsee
//

#include "multi_test3.h"

int multi_test3(ap_ufixed_in in[25], ap_fixed_add &out);

int main(void){
    ap_ufixed_in in[25];
    ap_fixed_add out;
    ap_ufixed_in v = 0.5;

    for(int i=0; i<25; i=i++){
        in[i] = (ap_ufixed_in)v;
        v += (ap_ufixed_in)0.00390625;
        printf("in[%d] = %f\n", i, (float)v);
    }

    multi_test3(in, out);

    printf("out = %f\n", (float)out);

    return(0);
}


C シミュレーションを行った。結果を示す。
multi_test_49_180203.png

C コードの合成を行った。結果を示す。
multi_test_50_180203.png

Latency は 7 クロックだった。Interval は 1 で 1 クロックごとに次のデータを入れることができる。
リソース使用量は、BRAM_18K が 0 個、DSP48E も 0 個で、演算を LUT にマップできていることが分かった。FF は 1,286 個、LUT は 2,106 個使用している。うまく行っている。

C/RTL 協調シミュレーションを行った。
multi_test_51_180203.png

Latency は 7 クロックだった。

C/RTL 協調シミュレーションの波形を示す。
multi_test_52_180203.png

畳み込み演算器がデータを受け取ってから、演算を行い、出力の値をその先の回路が受け取るまでに 7 クロックだった。

Export RTL を行った。結果を示す。
なお、Vivado synthesis, place and route にチェックを入れてある。
multi_test_53_180203.png

LUT 使用数は 852 個だった。でもSRL の 36 もLUTとしての数に含めるべきかもしれない?
そうすると、852 + 36 = 888 個だった。
  1. 2018年02月03日 05:44 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0