FC2カウンター FPGAの部屋

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

FPGAの部屋

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

MNISTのCNN 用DMA IP 2(C コードの合成、C/RTL 協調シミュレーション、Export RTL)

MNISTのCNN 用DMA IP 1(C シミュレーション)”の続き。

前回は、MNISTのCNN 用のDMA IP を作成し、C シミュレーションを行った。今回は、C コードの合成、C/RTL 協調シミュレーション、Export RTLを行った。

まずは、Vivado HLS 2018.2 の新機能の Schedule Viewer の機能を見るために、PIPELINE指示子をコメントアウトして、C コードの合成を行った。
mnist_square_dma_7_180621.png

C コードの合成結果を示す。
mnist_square_dma_8_180621.png

Latency は 3389 クロックだった。column_count ループの Iteration Latency が 4 クロックだったので、それでクロック数が増えているようだ。
リソース使用量は、BRAM_18K が 2 個、DSP48E が 2 個、FF が 830 個、LUT が 1270 個だった。

Analysis ボタンをクリックして、Schedule Viewer を表示させた。
mnist_square_dma_9_180621.png

row_count と column_count があるのが分かる。
Operation\Control Step の数は 12 だった。

次に、PIPELINE指示子を戻した。
mnist_square_dma_10_180621.png

これで C コードの合成を行った。結果を示す。
mnist_square_dma_11_180621.png

Latency は 3389 クロックから 809 クロックに下がった。
リソース使用量は、BRAM_18K が 2 個、DSP48E が 3 個、FF が 1378 個、LUT が 1583 個だった。PIPELINE指示子が無い時よりも大分増えている。

Analysis ボタンをクリックして、Schedule Viewer を表示させた。
mnist_square_dma_12_180621.png

row_count と column_count が合わさって、row_count_column_count になっていた。
Operation\Control Step の数は 25 だった。

C/RTL 協調シミュレーションを行った。結果を示す。
mnist_square_dma_13_180621.png

Latency は 1014 クロックだった。

C/RTL 協調シミュレーションの波形を示す。
まずは波形全体から。
mnist_square_dma_14_180621.png

AXI4-Stream の TLAST をアサートしている辺りで、TVALID が 0 にディアサートされているのが気になるが、スループットは出ているようだ。

次に最初の部分を拡大してみよう。
mnist_square_dma_15_180621.png

28 個のピクセルの DMA を行う。ARLENを見ると最初は 0x0f なので 16 バーストで、次は 0x0B なので 12 バーストの計 28 個バーストしている。
アドレス転送とデータ転送がもう少しオーバーラップしている方が良いと思う。

Export RTLを行った。
Vivado HLS 2018.2 では、Wave Debug 項目が増えている。これは、Verilog/VHDL Simulator Selection が AUTO だとハイドされている。これが有効になるのは、Vivado Simulator の時だけのようだ。このオプションにチェックすると、C/RTL 協調シミュレーションが終了する前にVivado が起動して、波形を表示する。
mnist_square_dma_16_180621.png

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

LUT が 575 個、FF が 807 個、DSP が 4 個、BRAM が 1 個、SRLが 39 個使用していた。
  1. 2018年06月22日 04:51 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

MNISTのCNN 用DMA IP 1(C シミュレーション)

MNISTのCNN 用のDMA IP を作成した。
MNISTのCNN は、ap_uint<8> のHLS ストリーム・データを入力する。よって、MNISTのCNN に手書き数字データを供給するために画像を切り取り 28 x 28 ピクセルのHLSストリーム・データを供給する mnist_square_dma IP を作成する。

Vivado HLS 2018.2 の mnist_square_dma プロジェクトを示す。
mnist_square_dma_1_180621.png

mnist_square_dma.cpp を示す。

// mnist_square_dma.cpp
// 2018/06/19 by marsee
//

#include <ap_fixed.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>

int conv_rgb2y(int rgb);

int mnist_square_dma(int in[22400], int addr_offset, hls::stream<ap_axiu<8,1,1,1> >&outs){
#pragma HLS INTERFACE axis register both port=outs
#pragma HLS INTERFACE m_axi depth=22400 port=in offset=slave
#pragma HLS INTERFACE s_axilite port=return

    ap_axiu<8,1,1,1> pixel;

    row_count: for(int i=0; i<28; i++){
        column_count: for(int j=0; j<28; j++){
#pragma HLS PIPELINE II=1
            pixel.data = 255 - conv_rgb2y(in[addr_offset+i*800+j]);
            // 白地に黒数字から黒地に白数字に変換

            if(i==0 && j==0)
                pixel.user = 1;
            else
                pixel.user = 0;
            if(j == 27)
                pixel.last = 1;
            else
                pixel.last = 0;

            outs << pixel;
        }
    }
    return(0);
}

// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y =  0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
    int r, g, b, y_f;
    int y;

    b = rgb & 0xff;
    g = (rgb>>8) & 0xff;
    r = (rgb>>16) & 0xff;

    y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
    y = y_f >> 8// 256で割る

    if (y >= 256)
        y = 255;

    return(y);
}


mnist_square_dma_tb.cpp を示す。

// mnist_square_dma_tb.cpp
// 2018/06/21 by marsee
//

#include <stdio.h>
#include <ap_fixed.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>

#include "bmp_header.h"

#define READ_BMP_FILE_NAME    "bmp_file0.bmp"

// 8
#define X_POS    560
#define Y_POS    183
// 7
//#define X_POS    504
//#define Y_POS    184
// 5
//#define X_POS    390
//#define Y_POS    138
// 0
//#define X_POS    390
//#define Y_POS    70
#define WIDTH    28
#define HEIGHT    28

int mnist_square_dma(int in[22400], int addr_offset, hls::stream<ap_axiu<8,1,1,1> >&outs);

int main(){
    int *in;
    BITMAPFILEHEADER bmpfhr; // BMPファイルのファイルヘッダ(for Read)
    BITMAPINFOHEADER bmpihr; // BMPファイルのINFOヘッダ(for Read)
    FILE *fbmpr;
    int *rd_bmp;
    int blue, green, red;
    hls::stream<ap_axiu<8,1,1,1> > outs;
    ap_axiu<8,1,1,1> pixel;

    if ((fbmpr = fopen(READ_BMP_FILE_NAME, "rb")) == NULL){ // test.bmp をオープン
        fprintf(stderr, "Can't open ");
        fprintf(stderr, READ_BMP_FILE_NAME);
        fprintf(stderr, " by binary read mode\n");
        exit(1);
    }
    // bmpヘッダの読み出し
    fread(&bmpfhr.bfType, sizeof(uint16_t), 1, fbmpr);
    fread(&bmpfhr.bfSize, sizeof(uint32_t), 1, fbmpr);
    fread(&bmpfhr.bfReserved1, sizeof(uint16_t), 1, fbmpr);
    fread(&bmpfhr.bfReserved2, sizeof(uint16_t), 1, fbmpr);
    fread(&bmpfhr.bfOffBits, sizeof(uint32_t), 1, fbmpr);
    fread(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpr);

    // ピクセルを入れるメモリをアロケートする
    if ((rd_bmp =(int *)malloc(sizeof(int) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
        fprintf(stderr, "Can't allocate rd_bmp memory\n");
        exit(1);
    }

    if ((in =(int *)malloc(sizeof(int) * (800 * 28))) == NULL){
        fprintf(stderr, "Can't allocate (ap_ufixed<8, 0, AP_TRN_ZERO, AP_SAT>)in memory\n");
        exit(1);
    }

    // rd_bmp にBMPのピクセルを代入。その際に、行を逆転する必要がある
    for (int y=0; y<bmpihr.biHeight; y++){
        for (int x=0; x<bmpihr.biWidth; x++){
            blue = fgetc(fbmpr);
            green = fgetc(fbmpr);
            red = fgetc(fbmpr);
            rd_bmp[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] = (blue & 0xff) | ((green & 0xff)<<8) | ((red & 0xff)<<16);
        }
    }
    fclose(fbmpr);

    // rd_bmp を in に入力
    for (int y=Y_POS; y<Y_POS+HEIGHT; y++){
        for (int x=0; x<bmpihr.biWidth; x++){
            in[(y-Y_POS)*bmpihr.biWidth+x] = rd_bmp[y*bmpihr.biWidth+x];
        }
    }

    mnist_square_dma(in, X_POS, outs);

    for (int y=0; y<HEIGHT; y++){
        for (int x=0; x<WIDTH; x++){
            outs >> pixel;
            if(pixel.data >= 0x80)
                printf("*");
            else
                printf(" ");
        }
        printf("\n");
    }

    free(rd_bmp);
    free(in);

    return(0);
}


mnist_square_dma_tb.cpp で 下の画像の手書き数字を切り取る。
mnist_square_dma_3_180621.jpg

現在の mnist_square_dma_tb.cpp は 8 を切り取るようになっている。C シミュレーションをしてみよう。
mnist_square_dma_2_180621.png

ご覧の通りに 8 が切り取られている。

7 の切り取り。
mnist_square_dma_4_180621.png

5 の切り取り。
mnist_square_dma_5_180621.png

0 の切り取り。
mnist_square_dma_6_180621.png
  1. 2018年06月21日 05:29 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado 2018.2 が出た

昨日、Vivado 2018.2 が出ていた。

Vivado HLS のAnalysis にSchedule Viewer が追加されたということでやってみることにした。

MNISTのCNNの特徴マップが 3 個の場合で確かめてみた。
Vivado 2018.2 で mnist_conv_nn3_hlss_k_org82 フォルダのVivado HLS プロジェクトをC コードの合成を行った。結果を示す。
下に 2018.1 の結果も示す。
vivado_2018_1_1_180620.pngtensorflow_keras_111_180618.png

同じ結果だった。

Analysis モードにすると、Schedule Viewer が起動した。新しいモードだ。
vivado_2018_1_2_180620.png

conv_layer1 > conv_layer_template を選択した。
赤い部分があるが、これはタイミング違反のブロックということだ。
どこからデータが来て、どこに行くのかが矢印で示されているのだと思う。
vivado_2018_1_3_180620.png

affine_layer1 > affine_layer_templat_1 を示す。
vivado_2018_1_4_180620.png

見やすくなった気がするが、どこの演算をしているのかがいまいち分からない?

Export RTLの結果を示す。2018.1 の結果も示す。
vivado_2018_1_5_180620.pngtensorflow_keras_112_180618.png

特に FF と SLICE の使用量が 2018.2 の方が少なくなっている。
CP achieved post-implementation が 9.525 ns から 8.846 ns に改善されているが、これはVivado の改善のようだ。


次に、Vivado 2018.2 を”Kerasを使用したMNIST CNNで手書き文字認識1(以前のVivado プロジェクトをVivado 2017.4に変換)”のVivado 2017.4 と比較してみよう。

Vivado 2018.2 の PYNQ ボードのMNIST のCNN プロジェクトを示す。
vivado_2018_1_6_180620.png

Vivado 2018.2 の結果を示す。 2017.4 の結果も示す。
vivado_2018_1_7_180620.pngvivado_2018_1_8_180620.png

LUT は少し 2018.2 の方が少なく、LUT RAM と FF がやはり、2018.2 の方が少なくなった。
今度から 2018.2 を使ってみようか?
  1. 2018年06月20日 04:50 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

Kerasを使用したMNIST CNNで手書き文字認識1(以前のVivado プロジェクトをVivado 2017.4に変換)

TensorFlow + Kerasを使ってみた22(Linux版とWindows版のVivado HLSでの違い)”までで作ってきたMNISTのCNNをVivado に組み込んで実機で動作させてみようと思う。とりあえずは、従来のフレームワークに入れて、HLSストリーム版のCNN が実際にうまく行くかを確認したい。

以前の「手書き数字認識用畳み込みニューラルネットワーク回路」のVivado プロジェクトは、”手書き数字認識用畳み込みニューラルネットワーク回路の製作4(Vivadoプロジェクト)”のVivado 2017.2 のプロジェクトだった。
これをVivado 2017.4 に変換した。
keras_minst_cnn_1_180619.png

次に、論理合成、インプリメンテーション、ビットストリームの生成を行った。
結果を示す。
keras_minst_cnn_2_180619.png

タイミングも満たされてうまく行っている。
次は、HLSストリームを使用したMNISTのCNNは、ストリーム入力になっているので、ストリームを作成するDMA をVivado HLS で作っていこう。
  1. 2018年06月19日 05:24 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

TensorFlow + Kerasを使ってみた22(Linux版とWindows版のVivado HLSでの違い)

TensorFlow + Kerasを使ってみた21(特徴マップ数が3個、5個、10個のMNIST用CNNをC/RTLコシムとIP化)”の続き。

前回は、特徴マップ数が 3 個、 5 個、10 個のMNIST用CNNをC/RTL 強調シミュレーションと、Export RTL を行って、結果を比較した。今回は、前回はLinux 版のVivado HLS 2017.4 の結果だったが、Windows版のVivado HLS 2017.4 の結果も比較した。また、Vivado HLS 2018.1 で特徴マップが 3 個の場合をやってみたので比較した。

Windows版のVivado HLS 2017.4 の特徴マップ 3 個、5 個、10 個のC コードの合成とExport RTLを行った。結果は下表に示す。

特徴マップが 3 個の場合のWindows版Vivado HLS 2018.1 の C コードの合成の結果を示す。
tensorflow_keras_111_180618.png

特徴マップが 3 個の場合のWindows版Vivado HLS 2018.1 の Export RTLの結果を示す。
tensorflow_keras_112_180618.png

Vivado HLSの特徴マップ 3 個、5 個、10 個のC コードの合成とExport RTLの結果を下表に示す。
tensorflow_keras_113_180618.png

Vivado HLS 2017.4 のLinux 版とWindows版のC コードの合成結果は同じだったが、Export RTLの結果は異なっている。これは、Vivado 2017.4 が Linux 版とWindows版で異なっているのかもしれない?
Vivado HLS 2018.1 のC コードの合成結果は、2017.4 の結果よりも FF と LUT のリソース使用量が少なった。Export RTLの結果は、FF は Vivado HLS 2018.1 の方がリソース使用量が少なかったが、LUT は Vivado HLS 2017.4 の方がリソース使用量が少なかった。
  1. 2018年06月18日 05:30 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

TensorFlow + Kerasを使ってみた21(特徴マップ数が3個、5個、10個のMNIST用CNNをC/RTLコシムとIP化)

TensorFlow + Kerasを使ってみた20(特徴マップ3個のMNIST用CNNをVivado HLSで実装)”の続き。

前回は、MNIST 用のCNN で特徴マップ数が 3 個の場合をVivado HLS で実装した。今回は、特徴マップ数が 3 個、 5 個、10 個のMNIST用CNNをC/RTL 強調シミュレーションと、Export RTL を行う。

まずは、特徴マップ数が 3 個の時のMNIST 用CNN をC/RTL 強調シミュレーションと、Export RTL を行ってみよう。
最初に、テストベンチの mnist_conv_nn_hlss_tb.cpp の 「#define NUM_ITERATIONS 1000」をコメントアウトして、「#define NUM_ITERATIONS 2」のコメントアウトを削除した。これは、C/RTL 強調シミュレーションを行うにあたって、1000 個推論を実行するのは時間がかかりすぎると思ったからだ。波形を見るだけなので、少ない推論数でも十分なわけだ。
tensorflow_keras_104_180616.png

これで、C/RTL 強調シミュレーションを行ったところ、エラーだった。
tensorflow_keras_105_180616.png

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

LUT は 2794 個、FF は 3195 個、DSP は 62 個、BRAM 34 個、SRL 73 個使用している。
合成時のリソース使用量はBRAM_18K が 34 個、DSP48E が 62 個、FF が 5284 個、LUT が 9137 個だった。DSP と BRAM の個数は同じで、FF は約 60.5 % 、LUT は約 31.4 % になった(LUT はLUT とSRL をLUT として計算した)。


次に、特徴マップ数が 5 個の時のMNIST 用CNN をC/RTL 強調シミュレーションと、Export RTL を行ってみよう。
同様に、テストベンチの mnist_conv_nn_hlss_tb.cpp の 「#define NUM_ITERATIONS 1000」をコメントアウトして、「#define NUM_ITERATIONS 2」のコメントアウトを削除した。
C/RTL 強調シミュレーションを実行したところ、同様にエラーだった。
tensorflow_keras_106_180616.png

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

LUT は 3605 個、FF は 3811 個、DSP は 93 個、BRAM 66 個、SRL 63 個使用している。
合成時のリソース使用量はBRAM_18K が 66 個、DSP48E が 93 個、FF が 6215 個、LUT が 11144 個だった。DSP と BRAM の個数は同じで、FF は約 61.3 % 、LUT は約 32.9 % になった(LUT はLUT とSRL をLUT として計算した)。


最後に、特徴マップ数が 5 個の時のMNIST 用CNN をC/RTL 強調シミュレーションと、Export RTL を行ってみよう。
同様に、テストベンチの mnist_conv_nn_hlss_tb.cpp の 「#define NUM_ITERATIONS 1000」をコメントアウトして、「#define NUM_ITERATIONS 2」のコメントアウトを削除した。
C/RTL 強調シミュレーションを実行したところ、同様にエラーだった。
tensorflow_keras_109_180617.png

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

LUT は 5708 個、FF は 5681 個、DSP は 175 個、BRAM 130 個、SRL 73 個使用している。
合成時のリソース使用量はBRAM_18K が 130 個、DSP48E が 175 個、FF が 9005 個、LUT が 16391 個だった。DSP と BRAM の個数は同じで、FF は約 63.1 % 、LUT は約 35.3 % になった(LUT はLUT とSRL をLUT として計算した)。

Export RTL 時の特徴マップ数によるリソース使用量の違いを表に追加した。
tensorflow_keras_110_180617.png
  1. 2018年06月17日 05:36 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

「空飛ぶタイヤ」(映画)を見てきました

「空飛ぶタイヤ」(映画)(音注意)を見てきました。
池井戸潤の原作は3回読んだんですが、やはり映画は、時間が足りないですね。「64」の様に前後編に分けたほうが良かったのでは?と思いました。はるな銀行に銀行を変えたのか?の経緯が全く飛んでましたね。。。
ちょうど、ハリーポッターの最後から2、3作前のような感じです。本のボリュームは多くなっても、映画の時間はそれほど増えないので、映画が良く分からなくなった感じがしました。。。
  1. 2018年06月16日 19:37 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0
»