FC2カウンター FPGAの部屋 2017年08月

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

FPGAの部屋

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

白線追従走行用畳み込みニューラルネットワークの製作8(再度トレーニング、ラベル・ファイルの作成)

白線追従走行用畳み込みニューラルネットワークの製作7(学習2)”の続き。

白線追従走行用畳み込みニューラルネットワークの製作7(学習2)”で、精度が 71 % だったので、もう一度、白線追従直進走行用の画像データをもう一度取得して、再度トレーニング・ファイルとラベル・ファイルを作成することにした。(前回のトレーニング・ファイルとラベル・ファイルを作成は、”白線追従走行用畳み込みニューラルネットワークの製作3(トレーニング、ラベル・ファイルの作成)”を参照のこと)

画像データを取得したときの条件を示す。

ストレート(straight)
0: 角度 0 度、白線真ん中
1: 角度 0 度、左白線の内側エッジに左車輪の真ん中がくるように置いた
2: 角度 0 度、右白線の内側エッジにに右車輪の真ん中がくるように置いた
3: 角度 -5度、白線真ん中
4: 角度 +5 度、白線真ん中
5: 角度 -2 度、白線真ん中
6: 角度 +2 度、白線真ん中
7: 角度 -2 度、左白線の内側エッジにに左車輪の真ん中がくるように置いた
8: 角度 +2 度、右白線の内側エッジにに右車輪の真ん中がくるように置いた
9: 角度 0 度、左白線の真ん中に左車輪の真ん中を置いた
10: 角度 0 度、右白線の真ん中に右車輪の真ん中を置いた

左ターン(left_turn)
0: 角度 0 度、右白線外側のエッジに右車輪の真ん中がくるように置いた
1: 角度 0 度、右車輪逸脱車体1/4
2: 角度 +5 度、右車輪逸脱車体1/4
3: 角度 +10 度、右車輪逸脱車体1/4
4: 角度 0 度、右車輪逸脱車体1/2
5: 角度 +5 度、右車輪逸脱車体1/2
6: 角度 +10 度、白線真ん中
7: 角度 +15 度、白線真ん中
8: 角度 +20 度、白線真ん中
9: 角度 +5 度、右白線の内側エッジにに右車輪の真ん中がくるように置いた
10: 角度 +10 度、右白線の内側エッジにに右車輪の真ん中がくるように置いた

右ターン(right_turn)
0: 角度 0 度、左白線外側のエッジに左車輪の真ん中がくるように置いた
1: 角度 0 度、左車輪逸脱車体1/4
2: 角度 -5 度、左車輪逸脱車体1/4
3: 角度 -10 度、左車輪逸脱車体1/4
4: 角度 0 度、左車輪逸脱車体1/2
5: 角度 -5 度、左車輪逸脱車体1/2
6: 角度 -10 度、白線真ん中
7: 角度 -15 度、白線真ん中
8: 角度 -20 度、白線真ん中
9: 角度 -5 度、左白線の内側エッジにに左車輪の真ん中がくるように置いた
10: 角度 -10 度、左白線の内側エッジにに左車輪の真ん中がくるように置いた

これで取得した画像データを示す。
wlt_cnn_43_170820.png

VirtualBox 上のUbuntu 16.04 でVivado HLS 2016.4 を立ち上げて、~/Vivado_HLS/PYNQ/straigh_dataset_bmp2 に straigh_dataset_bmp2 プロジェクトを作成して、straight_dataset_bmp.cpp と straight_dataset_bmp.h をコピー&ペーストした。今回、撮影した白線の画像データもコピー&ペーストして、プロジェクトのテストベンチに入れた。
wlt_cnn_44_170820.png

C シミュレーションを行った。ファイルがいろいろと作成された。
wlt_cnn_45_170820.png

~/Vivado_HLS/PYNQ/straigh_dataset_bmp2/solution1/csim/build ディレクトリに train_straight_run_image と train_straight_run_label
が生成された。
wlt_cnn_46_170820.png

今回、トレーニング・ファイルとラベル・ファイルの画像データが増えたので、straight_dataset_bmp.cpp と straight_dataset_bmp.h を変更した。
straight_dataset_bmp.h を示す。

// straight_dataset_bmp.h
// 2017/07/24 by marsee
//

#ifndef __STRAIGHT_DATASET_BMP_H__
#define __STRAIGHT_DATASET_BMP_H__

#include "hls_video.h"

#define BMP_HEIGHT    600
#define BMP_WIDTH    800

#define REDUCTION_RATIO    0.075    // 1/13.3333... 60x45

#define DATASET_HEIGHT    10
#define DATASET_WIDTH    56

#define STRAIGHT_BMP_FILE_NAME        straight
#define LEFT_TRUN_BMP_FILE_NAME        left_turn
#define RIGHT_TRUN_BMP_FILE_NAME    right_turn
#define STRAIGHT_NUM_OF_IMAGE        11
#define LEFT_TRUN_NUM_OF_IMAGE        11
#define    RIGHT_TRUNNUM_OF_IMAGE        11

typedef hls::Scalar<3unsigned char> RGB_PIXEL;
typedef hls::Mat<BMP_HEIGHT, BMP_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Mat<BMP_HEIGHT, BMP_WIDTH, HLS_8UC1> GRAY_IMAGE;

#endif


straight_dataset_bmp.cpp を示す。

// straight_dataset_bmp.cpp
// 2017/07/24 by marsee
//

#include <iostream>
#include "hls_opencv.h"
#include "straight_dataset_bmp.h"
#include <arpa/inet.h>

int main(){
    char straight_fn[256] = "straight";
    char left_turn_fn[256] = "left_turn";
    char right_turn_fn[256] = "right_turn";
    char bmp_file[256];
    FILE *ftin, *ftln;
    char train_image_name[256] = "train_straight_run_image";
    char train_label_name[256] = "train_straight_run_label";
    uint32_t buf[5];
    uint8_t bufchar[100];


    if ((ftin = fopen(train_image_name, "wb")) == NULL){
        fprintf(stderr, "Can't open %s\n", train_image_name);
        exit(1);
    }
    if ((ftln = fopen(train_label_name, "wb")) == NULL){
        fprintf(stderr, "Can't open %s\n", train_label_name);
        exit(1);
    }

    // Writed header
    buf[0] = htonl(0x803); // magic number
    buf[1] = htonl(5*5*(STRAIGHT_NUM_OF_IMAGE+LEFT_TRUN_NUM_OF_IMAGE+RIGHT_TRUNNUM_OF_IMAGE));
     // number of image
    buf[2] = htonl(10); // number of rows (10)
    buf[3] = htonl(56); // number of columns (56)
    fwrite(buf, sizeof(uint32_t), 4, ftin);

    buf[0] = htonl(0x801); // magic number
    buf[1] = htonl(5*5*(STRAIGHT_NUM_OF_IMAGE+LEFT_TRUN_NUM_OF_IMAGE+RIGHT_TRUNNUM_OF_IMAGE));
     // number of image
    fwrite(buf, sizeof(uint32_t), 2, ftln);

    // refereed to http://opencv.jp/cookbook/opencv_img.html
    // straight
    for(int i=0; i<STRAIGHT_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s%d.bmp", straight_fn, i);
        cv::Mat straight_img = cv::imread(bmp_file,1);
        if(straight_img.empty())
            return(-1);
        cv::Mat reduct_img(straight_img.rows*0.075, straight_img.cols*0.075, straight_img.type());
        cv::resize(straight_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        sprintf(bmp_file, "%s_RED%d.bmp", straight_fn, i);
        cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", straight_fn, i, y, x);
                cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x1;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    // left turn
    for(int i=0; i<LEFT_TRUN_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s%d.bmp", left_turn_fn, i);
        cv::Mat left_trun_img = cv::imread(bmp_file,1);
        if(left_trun_img.empty())
            return(-1);
        cv::Mat reduct_img(left_trun_img.rows*0.075, left_trun_img.cols*0.075, left_trun_img.type());
        cv::resize(left_trun_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        sprintf(bmp_file, "%s_RED%d.bmp", left_turn_fn, i);
        cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", left_turn_fn, i, y, x);
                cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x0;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    // right turn
    for(int i=0; i<STRAIGHT_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s%d.bmp", right_turn_fn, i);
        cv::Mat right_trun_img = cv::imread(bmp_file,1);
        if(right_trun_img.empty())
            return(-1);
        cv::Mat reduct_img(right_trun_img.rows*0.075, right_trun_img.cols*0.075, right_trun_img.type());
        cv::resize(right_trun_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        sprintf(bmp_file, "%s_RED%d.bmp", right_turn_fn, i);
        cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", right_turn_fn, i, y, x);
                cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x2;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    fclose(ftin);
    fclose(ftln);

    return(0);
}

  1. 2017年08月20日 06:51 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

ソニーのNeural Network Console をやってみた2

ソニーのNeural Network Console をやってみた1”の続き。

前回は、ソニーのNeural Network Console をインストールして、サンプルプロジェクトをやってみた。今回は更にサンプルプロジェクトをやってみることした。

まずは、binary_cnn。やはり、4 と 9 から 9 を選択する。
Neural_Network_Console_14_170818.png

ネットワークは、Input - 畳み込み - マックス・プーリング - Tanh - 畳み込み - マックス・プーリング - Tanh - 全結合 - Tanh - 全結合 - シグモイド - 交差エントロピー誤差だった。
Neural_Network_Console_15_170818.png

学習結果を示す。
Neural_Network_Console_16_170818.png

評価。
Neural_Network_Console_17_170818.png

Accuracy は 0.988 だった。”ソニーのNeural Network Console をやってみた1”のネットワークよりも精度が良い。
Neural_Network_Console_18_170818.png

次に、auto_encoder をやってみる。
Neural_Network_Console_19_170818.png

ネットワークは、Input - ドロップアウト - 全結合 - シグモイド - 全結合 - シグモイド - 2乗誤差 だった。
Neural_Network_Console_20_170818.png

学習の結果を示す。
Neural_Network_Console_21_170818.png

次は、deep_mlp を試してみた。
Neural_Network_Console_22_170818.png

ネットワークは Input - 全結合 - Tanh - 全結合 - Tanh - 全結合 - Tanh - 全結合 - Tanh - 全結合 - シグモイド - 交差エントロピー誤差だった。全結合が5層だ。
Neural_Network_Console_23_170818.png

学習結果を示す。
Neural_Network_Console_24_170818.png

精度は、0.966 だった。binary_cnn よりも精度が落ちている。
Neural_Network_Console_25_170818.png

residual_learning をやってみた。今回は、4 と 9 から 9 を推定ではなく、MNISTの 0 から 9 の手書き数字をすべて推定する。
Neural_Network_Console_26_170818.png

ネットワークはとっても長い。
Neural_Network_Console_27_170818.png
Neural_Network_Console_28_170818.png
Neural_Network_Console_29_170818.png
Neural_Network_Console_30_170818.png
Neural_Network_Console_31_170818.png

学習には、10時間程度かかった。
Neural_Network_Console_32_170819.png

さすがに精度は0.9913 で、今までで一番良い。というか、MNISTの数字の推定の結果だけれども。。。
Neural_Network_Console_33_170819.png
  1. 2017年08月19日 05:45 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

ソニーのNeural Network Console をやってみた1

Neural Network Console」という学習・評価だけでなく、ニューラルネットワークの設計までも可能なディープラーニング・ツールをソニーが無償提供したので、やってみることにした。

Neural Network Console」のページからNeural Network Console_V1.0.0 for Windows 8.1/10_64bit をダウンロードするリンクをメールアドレスを登録して送ってもらうことができる。
メールのリンクをクリックすると、neural_network_console_100.zip というファイルをダウンロードすることができた。中を見てみるとインストーラーは無いので、ファイルの中身をコピーした。
Neural_Network_Console_1_170818.png

Neural Network Console ドキュメントセットアップによると2バイト文字が含まれたパスにはインストールしないようにということだった。

フォルダを作成して、ZIP を解凍したファイルをコピーした。
Neural_Network_Console_2_170818.png

neural_network_console.exe をダブルクリックして、起動した。
すると、WindowsによってPC が保護されましたダイアログが出てきた。実行ボタンをクリックして、起動した。
Neural_Network_Console_3_170818.png

起動したところ、Microsoft Visual C++ 2015 Redistributable Package をインストールして、CUDAを最新にしろとのダイアログが出た。
Neural_Network_Console_4_170818.png

Microsoft Visual C++ 2015 Redistributable Update 3 RC のEnglish バージョンをダウンロード、インストールした。
NVIDIA のグラフィック・ドライバはバージョン: 385.28 があったので、インストールした。

もう一度、neural_network_console.exe を起動したが、やはり同じダイアログが出てきたので、Microsoft Visual C++ 2015 Redistributable Package をインストールして合ってもダイアログが出てしまうようだ。

チュートリアル:サンプルプロジェクトを用いた学習を参照して、最初のサンプル・プロジェクトの 01_logistic_regression.sdcproj をやってみた。

neural_network_console.exe の起動画面で 01_logistic_regression.sdcproj をクリックした。このプロジェクトはMNISTの4 と 9 の手書き数字から 9 を選ぶネットワークを学習するプロジェクトの様だ。
Neural_Network_Console_5_170818.png

MNISTデータをダウンロードしているようだ。
Neural_Network_Console_6_170818.png

入力 - 全結合ニューラルネットワーク - シグモイド関数 - バイナリ・交差エントロピー誤差 のネットワークのようだ。
Neural_Network_Console_7_170818.png

DATASET をクリックすると、データセットが見えた。4 が 0 で 9 が 1 という評価だ。
Neural_Network_Console_8_170818.png

EDIT をクリックすると、ネットワークの表示に戻る。Training のRun training ボタンをクリックして学習を始めた。
Neural_Network_Console_9_170818.png

すると、Learning Curveが表れて、どんどん学習が進んでいく様子が分かる。
Neural_Network_Console_10_170818.png

Evaluation の Run evaluation をクリックして、評価を行う。
Neural_Network_Console_11_170818.png

Evaluate ボタンが選択されて、評価結果が表示された。
Neural_Network_Console_12_170818.png

Confusion Matrix ラジオボタンをクリックした。
Accuracy が 0.,95 になっている。
Neural_Network_Console_13_170818.png
  1. 2017年08月18日 07:12 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Vivado シミュレータでDPI-C を使用してZynq VIPを使う3

Vivado シミュレータでDPI-C を使用してZynq VIPを使う2”の続き。

前回は、コンパイルとエラボレートを行った。今回はいよいよxsim を走らせて、シミュレーション波形を出してみよう。

最初に、simulate.sh を開いて編集する。xsim のコマンドラインに -g を追加した。GUI を上げるためのオプションだ。
DPI_examples_26_170813.png

tb.tcl を開いて編集した。 run 1000 ns を run all に変更した。
DPI_examples_27_170813.png

.simulate.sh を実行した。
DPI_examples_34_170813.png

xsim のGUI が上がって、波形が表示された。
DPI_examples_28_170813.png

拡大した波形を示す。うまく行っているようだ。
DPI_examples_32_170813.png

シミュレーションを実行中の ~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav ディレクトリの内容を示す。
DPI_examples_33_170813.png

シミュレーションのログを貼っておく。

start_gui
source xsim.dir/tb_behav/xsim_script.tcl
# load_feature core
# current_fileset
INFO: [IP_Flow 19-234] Refreshing IP repositories
INFO: [IP_Flow 19-1704] No user IP repositories specified
INFO: [IP_Flow 19-2313] Loaded Vivado IP repository '/opt/Xilinx/Vivado/2017.2/data/ip'.
# xsim {tb_behav} -autoloadwcfg -tclbatch {tb.tcl} -key {Behavioral:sim_1:Functional:tb}
Vivado Simulator 2017.2
Time resolution is 1 ps
open_wave_config /home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav/tb_behav.wcfg
source tb.tcl
## set curr_wave [current_wave_config]
## if { [string length $curr_wave] == 0 } {
## if { [llength [get_objects]] > 0} {
## add_wave /
## set_property needs_save false [current_wave_config]
## } else {
## send_msg_id Add_Wave-1 WARNING "No top level signals found. Simulator will start without a wave window. If you want to open a wave window go to 'File->New Waveform Configuration' or type 'create_wave_config' in the TCL console."
## }
## }
## run all
Block Memory Generator module tb.zynq_sys.base_zynq_i.blk_mem_gen_0.inst.native_mem_mapped_module.blk_mem_gen_v8_3_6_inst is using a behavioral model for simulation which will not precisely model memory collision behavior.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.M_AXI_GP0.master
[0] : *ZYNQ_BFM_INFO : M_AXI_GP0 : Port is ENABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.M_AXI_GP1.master
[0] : *ZYNQ_BFM_INFO : M_AXI_GP1 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_GP0.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_GP0 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_GP1.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_GP1 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_HP0.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_HP0 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_HP1.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_HP1 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_HP2.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_HP2 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_HP3.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_HP3 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_ACP.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_ACP : Port is DISABLED.
running the tb
[150] : *ZYNQ_BFM_INFO : FPGA Soft Reset called for 0x1
[150] : *ZYNQ_BFM_INFO : FPGA Soft Reset called for 0x0
[150] : M_AXI_GP0 : *ZYNQ_BFM_INFO : Starting Address(0x41200000) -> AXI Write -> 4 bytes
[1490] : M_AXI_GP0 : *ZYNQ_BFM_INFO : Done AXI Write for Starting Address(0x41200000) with Response 'OKAY'
LEDs are toggled, observe the waveform
[1490] : M_AXI_GP0 : *ZYNQ_BFM_INFO : Starting Address(0x40000000) -> AXI Write -> 4 bytes
[1790] : M_AXI_GP0 : *ZYNQ_BFM_INFO : Done AXI Write for Starting Address(0x40000000) with Response 'OKAY'
[1790] : M_AXI_GP0 : *ZYNQ_BFM_INFO : Starting Address(0x40000000) -> AXI Read -> 4 bytes
[1950] : M_AXI_GP0 : *ZYNQ_BFM_INFO : Done AXI Read for Starting Address(0x40000000) with Response 'OKAY'
1950000, running the testbench, data read from BRAM was 32'hdeadbeef
AXI VIP Test PASSED
Simulation completed


次に、2番目のWrite と Read のアドレスを 0x4000004 にしてみよう。更に、Write の delay を 500 にしてみる。
DPI_examples_39_170816.png

これで、compile.sh , elaborate.sh , simulate.sh を再実行した。波形を示す。
DPI_examples_37_170816.png

AWADDR を見ると 40000004 になっているのが分かる。更に、前のWrite のBVALID がアサートされ、ディアサートされた後から、今回のWrite のAWVALID がアサートされるまでの時間は、500.001 ns だった。正しく delay が効いているようだ。

Write の delay を 500 から 0 にしたときをもう一度、確かめてみよう。
DPI_examples_38_170816.png

前のWrite のBVALID がアサートされ、ディアサートされた後から、今回のWrite のAWVALID がアサートされるまでの時間は、20.001 ns だった。

Zynq VIP のレジスタWrite は完全にBVALID 、BRADY がアサートされたら終了なのかもしれない?複数のトランザクションを重ねることはできるのだろうか?
  1. 2017年08月16日 04:45 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

Vivado シミュレータでDPI-C を使用してZynq VIPを使う2

Vivado シミュレータでDPI-C を使用してZynq VIPを使う1”の続き。

前回は、Vivado 2017.2 で Base Zynq サンプル・プロジェクトを作成して、一度シミュレーションを実行し、テストベンチをSystemVerilog ファイルに変更し、シミュレーション用のディレクトリにDPI-C を実行するC ファイルを追加した。今回は、コンパイル、エラボレートを行う。

~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav には、compile.sh ができていた。
DPI_examples_14_170813.png

compile.sh を zynq_dpi.c をコンパイルするように変更する。
DPI_examples_17_170813.png

最後に xsc zynq_dpi.c を追加した。これで、zynq_dpi.c をコンパイルする。
次に、tb_vlog.prj にコンパイルするファイルやオプションが書いてあるので、zynq_tb.sv をコンパイルするように書き換えた。
DPI_examples_18_170813.png

./compile.sh を実行してコンパイルを行った。
DPI_examples_19_170813.png
DPI_examples_20_170813.png

コンパイルのログを貼っておく。

masaaki@masaaki-VirtualBox2:~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav$ ./compile.sh
xvlog -m64 --relax -L smartconnect_v1_0 -L axi_protocol_checker_v1_1_14 -L xil_common_vip_v1_0_0 -L axi_vip_v1_0_2 -L axi_vip_v1_0_1 -prj tb_vlog.prj
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_processing_system7_0_0/sim/base_zynq_processing_system7_0_0.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module base_zynq_processing_system7_0_0
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_blk_mem_gen_0_0/sim/base_zynq_blk_mem_gen_0_0.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module base_zynq_blk_mem_gen_0_0
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_xbar_0/sim/base_zynq_xbar_0.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module base_zynq_xbar_0
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_auto_pc_0/sim/base_zynq_auto_pc_0.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module base_zynq_auto_pc_0
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_auto_pc_1/sim/base_zynq_auto_pc_1.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module base_zynq_auto_pc_1
INFO: [VRFC 10-2263] Analyzing SystemVerilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.srcs/sim_1/imports/base_zynq/zynq_tb.sv" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module tb
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav/glbl.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module glbl
xvhdl -m64 --relax -prj tb_vhdl.prj
INFO: [VRFC 10-163] Analyzing VHDL file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_axi_gpio_0_0/sim/base_zynq_axi_gpio_0_0.vhd" into library xil_defaultlib
INFO: [VRFC 10-307] analyzing entity base_zynq_axi_gpio_0_0
INFO: [VRFC 10-163] Analyzing VHDL file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_axi_bram_ctrl_0_0/sim/base_zynq_axi_bram_ctrl_0_0.vhd" into library xil_defaultlib
INFO: [VRFC 10-307] analyzing entity base_zynq_axi_bram_ctrl_0_0
INFO: [VRFC 10-163] Analyzing VHDL file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_rst_ps7_0_50M_0/sim/base_zynq_rst_ps7_0_50M_0.vhd" into library xil_defaultlib
INFO: [VRFC 10-307] analyzing entity base_zynq_rst_ps7_0_50M_0
INFO: [VRFC 10-163] Analyzing VHDL file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/hdl/base_zynq.vhd" into library xil_defaultlib
INFO: [VRFC 10-307] analyzing entity m00_couplers_imp_QHT96L
INFO: [VRFC 10-307] analyzing entity m01_couplers_imp_11WP2HX
INFO: [VRFC 10-307] analyzing entity s00_couplers_imp_1JB4A1T
INFO: [VRFC 10-307] analyzing entity base_zynq_ps7_0_axi_periph_0
INFO: [VRFC 10-307] analyzing entity base_zynq
INFO: [VRFC 10-163] Analyzing VHDL file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.srcs/sources_1/bd/base_zynq/hdl/base_zynq_wrapper.vhd" into library xil_defaultlib
INFO: [VRFC 10-307] analyzing entity base_zynq_wrapper
Running compilation flow
Done compilation
Done linking: "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav/xsim.dir/xsc/dpi.so"
masaaki@masaaki-VirtualBox2:~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav$


~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav/xsim.dir/xsc にdpi.so と zynq_dpi.lnx64.o ができていた。
DPI_examples_21_170813.png

~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav ディレクトリを示す。
DPI_examples_22_170813.png

さて、次にエラボレートを行う。
elaborate.sh を開いて、-sv_lib dpi を追加した。
DPI_examples_23_170813.png

./elaborate.sh を実行した。
DPI_examples_24_170813.png
DPI_examples_25_170813.png

エラボレートのログを貼っておく。ただし、Xilinx 社のIPのワーニングは長すぎるので削除した。

masaaki@masaaki-VirtualBox2:~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav$ ./elaborate.sh
Vivado Simulator 2017.2
Copyright 1986-1999, 2001-2016 Xilinx, Inc. All Rights Reserved.
Running: /opt/Xilinx/Vivado/2017.2/bin/unwrapped/lnx64.o/xelab -wto 429c07435a554e888bf42dfaf10910cc --debug typical --relax --mt 8 -L axi_infrastructure_v1_1_0 -L xil_common_vip_v1_0_0 -L smartconnect_v1_0 -L axi_protocol_checker_v1_1_14 -L axi_vip_v1_0_2 -L axi_vip_v1_0_1 -L xil_defaultlib -L axi_lite_ipif_v3_0_4 -L lib_cdc_v1_0_2 -L interrupt_control_v3_1_4 -L axi_gpio_v2_0_15 -L blk_mem_gen_v8_3_6 -L axi_bram_ctrl_v4_0_11 -L proc_sys_reset_v5_0_11 -L generic_baseblocks_v2_1_0 -L axi_register_slice_v2_1_13 -L fifo_generator_v13_1_4 -L axi_data_fifo_v2_1_12 -L axi_crossbar_v2_1_14 -L axi_protocol_converter_v2_1_13 -L unisims_ver -L unimacro_ver -L secureip -L xpm --snapshot tb_behav xil_defaultlib.tb xil_defaultlib.glbl -log elaborate.log -cc gcc -sv_lib dpi
Using 8 slave threads.
Starting static elaboration

Starting simulation data flow analysis
Completed simulation data flow analysis
Time Resolution for simulation is 1ps
WARNING: [XSIM 43-3447] Restricting number of parallel compilation jobs to 4 to avoid system resource limitations.
Compiling package std.standard
Compiling package std.textio
Compiling package ieee.std_logic_1164
Compiling package unisim.vcomponents
Compiling package ieee.numeric_std
Compiling package ieee.std_logic_arith
Compiling package axi_bram_ctrl_v4_0_11.axi_bram_ctrl_funcs
Compiling package ieee.vital_timing
Compiling package ieee.vital_primitives
Compiling package unisim.vpkg
Compiling package ieee.std_logic_unsigned
Compiling package synopsys.attributes
Compiling package ieee.std_logic_misc
Compiling package axi_lite_ipif_v3_0_4.ipif_pkg
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.sng_port_arb [\sng_port_arb(c_s_axi_addr_width...]
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.wrap_brst [\wrap_brst(c_axi_addr_width=13,c...]
Compiling architecture muxcy_v of entity unisim.MUXCY [muxcy_default]
Compiling architecture muxcy_l_v of entity unisim.MUXCY_L [muxcy_l_default]
Compiling architecture xorcy_v of entity unisim.XORCY [xorcy_default]
Compiling architecture srl16e_v of entity unisim.SRL16E [\SRL16E(0,15)\]
Compiling architecture fdre_v of entity unisim.FDRE [fdre_default]
Compiling architecture fdr_v of entity unisim.FDR [fdr_default]
Compiling architecture imp of entity axi_bram_ctrl_v4_0_11.SRL_FIFO [\SRL_FIFO(c_data_bits=12,c_depth...]
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.wr_chnl [\wr_chnl(c_axi_addr_width=13,c_a...]
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.rd_chnl [\rd_chnl(c_axi_addr_width=13,c_a...]
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.full_axi [\full_axi(c_s_axi_addr_width=13,...]
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.axi_bram_ctrl_top [\axi_bram_ctrl_top(c_bram_addr_w...]
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.axi_bram_ctrl [\axi_bram_ctrl(c_memory_depth=20...]
Compiling architecture base_zynq_axi_bram_ctrl_0_0_arch of entity xil_defaultlib.base_zynq_axi_bram_ctrl_0_0 [base_zynq_axi_bram_ctrl_0_0_defa...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.pselect_f [\pselect_f(c_ab=2,c_aw=2,c_bar="...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.pselect_f [\pselect_f(c_ab=2,c_aw=2,c_bar="...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.pselect_f [\pselect_f(c_ab=2,c_aw=2,c_bar="...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.pselect_f [\pselect_f(c_ab=2,c_aw=2,c_bar="...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.address_decoder [\address_decoder(c_bus_awidth=9,...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.slave_attachment [\slave_attachment(c_ard_addr_ran...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.axi_lite_ipif [\axi_lite_ipif(c_s_axi_addr_widt...]
Compiling architecture implementation of entity lib_cdc_v1_0_2.cdc_sync [\cdc_sync(c_single_bit=0,c_vecto...]
Compiling architecture imp of entity axi_gpio_v2_0_15.GPIO_Core [\GPIO_Core(c_aw=9,c_gpio_width=4...]
Compiling architecture imp of entity axi_gpio_v2_0_15.axi_gpio [\axi_gpio(c_family="zynq",c_gpio...]
Compiling architecture base_zynq_axi_gpio_0_0_arch of entity xil_defaultlib.base_zynq_axi_gpio_0_0 [base_zynq_axi_gpio_0_0_default]
Compiling module blk_mem_gen_v8_3_6.blk_mem_gen_v8_3_6_output_stage(...
Compiling module blk_mem_gen_v8_3_6.blk_mem_gen_v8_3_6_output_stage(...
Compiling module blk_mem_gen_v8_3_6.blk_mem_gen_v8_3_6_softecc_outpu...
Compiling module blk_mem_gen_v8_3_6.blk_mem_gen_v8_3_6_mem_module(C_...
Compiling module blk_mem_gen_v8_3_6.blk_mem_gen_v8_3_6(C_FAMILY="zyn...
Compiling module xil_defaultlib.base_zynq_blk_mem_gen_0_0
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ge...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ge...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ar...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ar...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_fm...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ar...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ar...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ar...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ar...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ss...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_in...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_sp...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_dd...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_oc...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_oc...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_re...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_re...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_if(C_AXI_PROTOCOL...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_onehot_to_binary(...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_srl_rtl(C_A_WIDTH...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_axic_reg_srl_fifo...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_thr...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_syn...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_axi...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_syn...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_syn...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_cor...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_rep...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_top...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_top(C_AXI_PROTOCO...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ax...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ax...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_if(C_AXI_PROTOCOL...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_onehot_to_binary(...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_srl_rtl(C_A_WIDTH...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_axic_reg_srl_fifo...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_thr...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_axi...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_syn...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_cor...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_rep...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_top...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_top(C_AXI_PROTOCO...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ax...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ax...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_if(C_AXI_PROTOCOL...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_axi...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_syn...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_cor...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_rep...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_top...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_top(C_AXI_PROTOCO...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_in...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_in...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_af...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_in...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_af...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_in...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_af...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_in...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_af...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_if(C_AXI_PROTOCOL...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_onehot_to_binary(...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_srl_rtl(C_A_WIDTH...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_axic_reg_srl_fifo...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_thr...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_axi...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_cor...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_rep...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_top...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_top(C_AXI_PROTOCO...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ax...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1(C_...
Compiling module xil_defaultlib.base_zynq_processing_system7_0_0
Compiling module axi_infrastructure_v1_1_0.axi_infrastructure_v1_1_0_axi2ve...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_infrastructure_v1_1_0.axi_infrastructure_v1_1_0_vector...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axi_r...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_infrastructure_v1_1_0.axi_infrastructure_v1_1_0_axi2ve...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_infrastructure_v1_1_0.axi_infrastructure_v1_1_0_vector...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axi_r...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_a...
Compiling module xil_defaultlib.base_zynq_auto_pc_0
Compiling architecture structure of entity xil_defaultlib.m00_couplers_imp_QHT96L [m00_couplers_imp_qht96l_default]
Compiling architecture structure of entity xil_defaultlib.m01_couplers_imp_11WP2HX [m01_couplers_imp_11wp2hx_default]
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_a...
Compiling module xil_defaultlib.base_zynq_auto_pc_1
Compiling architecture structure of entity xil_defaultlib.s00_couplers_imp_1JB4A1T [s00_couplers_imp_1jb4a1t_default]
Compiling module generic_baseblocks_v2_1_0.generic_baseblocks_v2_1_0_carry_...
Compiling module generic_baseblocks_v2_1_0.generic_baseblocks_v2_1_0_compar...
Compiling module generic_baseblocks_v2_1_0.generic_baseblocks_v2_1_0_compar...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_addr_decode...
Compiling module generic_baseblocks_v2_1_0.generic_baseblocks_v2_1_0_mux_en...
Compiling module unisims_ver.SRLC32E_default_1
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_ndeep_srl(...
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_axic_srl_f...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_si_transact...
Compiling module generic_baseblocks_v2_1_0.generic_baseblocks_v2_1_0_mux_en...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_si_transact...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_splitter
Compiling module unisims_ver.SRLC32E_default
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_ndeep_srl(...
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_axic_reg_s...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_wdata_route...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_wdata_mux(C...
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_axic_srl_f...
Compiling module axi_infrastructure_v1_1_0.axi_infrastructure_v1_1_0_axi2ve...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_infrastructure_v1_1_0.axi_infrastructure_v1_1_0_vector...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axi_r...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_wdata_mux(C...
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_ndeep_srl(...
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_axic_srl_f...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_addr_arbite...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_decerr_slav...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_crossbar(C_...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_axi_crossba...
Compiling module xil_defaultlib.base_zynq_xbar_0
Compiling architecture structure of entity xil_defaultlib.base_zynq_ps7_0_axi_periph_0 [base_zynq_ps7_0_axi_periph_0_def...]
Compiling architecture implementation of entity lib_cdc_v1_0_2.cdc_sync [\cdc_sync(c_vector_width=2,c_mtb...]
Compiling architecture srl16e_v of entity unisim.SRL16E [\SRL16E(init="1111111111111111")...]
Compiling architecture srl16_v of entity unisim.SRL16 [\SRL16(init="1111111111111111")(...]
Compiling architecture imp of entity proc_sys_reset_v5_0_11.lpf [\lpf(c_ext_rst_width=4,c_aux_rst...]
Compiling architecture imp of entity proc_sys_reset_v5_0_11.upcnt_n [\upcnt_n(c_size=6)\]
Compiling architecture imp of entity proc_sys_reset_v5_0_11.sequence_psr [sequence_psr_default]
Compiling architecture imp of entity proc_sys_reset_v5_0_11.proc_sys_reset [\proc_sys_reset(c_family="zynq",...]
Compiling architecture base_zynq_rst_ps7_0_50m_0_arch of entity xil_defaultlib.base_zynq_rst_ps7_0_50M_0 [base_zynq_rst_ps7_0_50m_0_defaul...]
Compiling architecture structure of entity xil_defaultlib.base_zynq [base_zynq_default]
Compiling architecture structure of entity xil_defaultlib.base_zynq_wrapper [base_zynq_wrapper_default]
Compiling module xil_defaultlib.tb
Compiling module xil_defaultlib.glbl
Compiling package axi_vip_v1_0_2.axi_vip_v1_0_2_pkg
Compiling package xil_common_vip_v1_0_0.xil_common_vip_v1_0_0_pkg
Compiling package std.std
Compiling package smartconnect_v1_0.sc_util_v1_0_2_pkg
Waiting for 4 sub-compilation(s) to finish...
0 sub-compilation(s) remaining...
Built simulation snapshot tb_behav
masaaki@masaaki-VirtualBox2:~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav$


Vivado シミュレータでDPI-C を使用してZynq VIPを使う3”に続く。
  1. 2017年08月15日 06:00 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

Vivado シミュレータでDPI-C を使用してZynq VIPを使う1

Vivado シミュレータのDPI-C その1”と”Vivado シミュレータのDPI-C その2”でVivado シミュレータでDPI-C を実行する方法をXilinx者のサンプルで見てきた。
それでは、Zynq VIP を使用するときにDPI-C を使用することができるかどうか?をやってみた。

今回使用するのは、”Vivado 2017.1 の新機能8(Zynq-7000 VIP)”で使用したBase Zynq サンプル・プロジェクトだ。

最初に使用したのはVirtualBox 上のUbuntu 16.04 にインストールしたVivado 2017.2 だ。
さて、Vivado 2017.2 でサンプル・プロジェクトをオープンして、Templates からBase Zynq を選択して、プロジェクトを生成する。
DPI_examples_12_170813.png

一度、Flow Navigator からSIMULATION -> Run Simulation -> Run Behavioral Simulation を選択して、論理シミュレーションを行っておく。
DPI_examples_13_170813.png

その時に、Scope の tb -> zynq_sys -> base_zynq_i を右クリックし、Add to Wave Window を選択して、wave window にAXI バスの信号線を追加しておこう。そして、wave window の tb_behav.wcfg をセーブしておく。

~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav を見た。
DPI_examples_14_170813.png

シミュレーション用のファイルがいろいろと生成されていた。
ここに zynq_dpi.c を追加した。
DPI_examples_15_170813.png

zynq_dpi.c を示す。

// zynq_dpi.c
// 2017/08/12 by marsee
//

#include "svdpi.h"

#define AXI_TRANS_CS_LIMIT 10
#define READ_STATE    1

const struct axi_trans_scenario {
    int r_w;
    int delay;
    int addr;
    int trans_bytes;
    int    data;
} axi_trans_sc[AXI_TRANS_CS_LIMIT] =
    {{000x4120000040xFFFFFFFF},
    {000x4000000040xDEADBEEF},
    {100x4000000040}, {00000}, {00000}, {00000}, 
    {00000}, {00000}, {00000}, {00000}};

static int i=0;
                
int write_axit(int * const delay, int * const addr, 
    int * const trans_bytes, int * const data){
    int r_w;
    
    r_w = axi_trans_sc[i].r_w;
    *delay = axi_trans_sc[i].delay;
    *addr = axi_trans_sc[i].addr;
    *trans_bytes = axi_trans_sc[i].trans_bytes;
    *data = axi_trans_sc[i].data;
    
    if(axi_trans_sc[i].trans_bytes != 0 && i<AXI_TRANS_CS_LIMIT){
        if(r_w == 0){
            i++;
            return(0);
        }else
            return(1);
    }else
        return(2);
}

int read_axit(int * const delay, int * const addr, 
    int * const trans_bytes){
    int r_w;
    
    r_w = axi_trans_sc[i].r_w;
    *delay = axi_trans_sc[i].delay;
    *addr = axi_trans_sc[i].addr;
    *trans_bytes = axi_trans_sc[i].trans_bytes;
    
    if(axi_trans_sc[i].trans_bytes != 0 && i<AXI_TRANS_CS_LIMIT){
        if(r_w == 1){
            i++;
            return(0);
        }else
            return(1);
    }else
        return(2);
}


ソースコードを見てお分かりの様に、zynq_dpi.c はアドレスや書き込みデータをSV テストベンチに渡す。

次に、~/Vivado/zynq_base_ex_172/zynq_base_ex_172.srcs/sim_1/imports/base_zynq ディレクトリに行くと、zynq_tb.v がある。それをコピー&ペーストして、zynq_tb_sv に名前を変更した。
zynq_tb_sv にコードを追加した。なお、zynq_tb_v はXilinx 社のコードなので、一部を貼っておくだけとする。
まずはwire や reg の宣言部分にDPI-C の宣言を記述して、DPI-C で使用する変数を宣言した。
DPI_examples_35_170813.png

    integer delay, trans_bytes, addr;
    integer    data;
    
    integer i;
    
    import "DPI-C" function int write_axit(
        output int delay,
        output int addr,
        output int trans_bytes,
        output int data);

    import "DPI-C" function int read_axit(
        output int delay,
        output int addr,
        output int trans_bytes);


write_axit() と read_axit() を使用するようにSystemVerilog ファイルを変更した。task も使用していないが実証コードということで。。。
DPI_examples_36_170813.png

        //This drives the LEDs on the GPIO output
        if(write_axit(delay, addr, trans_bytes, data) == 0) begin
            for(i=0; i<delay; i++) begin
                #1;
            end
            tb.zynq_sys.base_zynq_i.processing_system7_0.inst.write_data(addr,trans_bytes, data, resp);
        end
        $display ("LEDs are toggled, observe the waveform");
        
        //Write into the BRAM through GP0 and read back
        if(write_axit(delay, addr, trans_bytes, data) == 0) begin
            for(i=0; i<delay; i++) begin
                #1;
            end
            tb.zynq_sys.base_zynq_i.processing_system7_0.inst.write_data(addr,trans_bytes, data, resp);
        end

        if(read_axit(delay, addr, trans_bytes) == 0) begin
            for(i=0; i<delay; i++) begin
                #1;
            end
            tb.zynq_sys.base_zynq_i.processing_system7_0.inst.read_data(addr, trans_bytes, read_data, resp);
        end


Vivado シミュレータでDPI-C を使用してZynq VIPを使う2”に続く。
  1. 2017年08月14日 04:48 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

Vivado シミュレータのDPI-C その2

Vivado シミュレータのDPI-C その1”の続き。

前回は、DPI のexample の simple_import をやってみた。今回は、simple_export をやってみよう。

今回も、aster_ismの工作室さんの”Vivado SimulatorによるDPI-Cシミュレーション”を参考にさせて頂く。

VirtualBox 上のUbuntu 16.04 の /opt/Xilinx/Vivado/2016.4/examples/xsim/systemverilog/dpi/simple_export ディレクトリがある。
DPI_examples_1_170809.png

やはり、README と file.sv, function.c, run.csh があった。
README を引用する。

Steps
-----
1. Run the setup for Xilinx executables.
2. Check if the executables "xsc" and "xelab" are in your PATH.
3. Invoke run.csh

This example shows a simple DPI-C export usage. The System Verilog code (file.sv)
calls a function "cFunc" defined in function.c that in turn calls a function "svFunc" which is
defined on the SV side in the file file.sv.
1. First the xvlog/xelab combination is run to generate the header dpi.h that is included
in the function.c
2. Then the C code is compiled using xsc to create a dll in directory xsim.dir/xsc/dpi.so.
3. This dll is then linked into when using "xelab" to compile the file.sv

The return value is checked by the System Verilog code triggering a "PASSED" output for a valid run.


function.c を引用する。


#include "dpi.h"

int cFunc(int x)
{
  return svFunc(x) ;
}

// XSIP watermark, do not delete 67d7842dbbe25473c3c32b93c0da8047785f30d78e8a024de1b57352245f9689


file.sv を引用する。


module TOP();

  export "DPI-C" function svFunc ; 

  int svValue ;

  function int svFunc(input int x) ;
    svValue = x + 1 ;
    return svValue + 3 ;
  endfunction

  import "DPI-C" function int cFunc(input int x) ;

  int result ;
  
  initial
  begin
    svValue = 15 ;
    result = cFunc(3) ;
    if (svValue != 4)
    begin
      $display("FAILED") ;
      $finish ;
    end
    if (result == 7)
      $display("PASSED") ;
    else
      $display("FAILED") ;
  end

endmodule


前回の simple_import では、C の関数を呼び出して、その値を使用するだけだったのだが、simple_export では、呼び出したC の関数からSystemVerilog の関数を呼び出している。

run.csh を引用する。

#!/bin/csh -xvf
xvlog -sv file.sv
xelab TOP -dpiheader dpi.h
xsc function.c
xelab TOP -sv_lib dpi -R


Ubuntu 16.04 上で、/opt/Xilinx/Vivado/2016.4/examples/xsim/systemverilog/dpi/simple_export ディレクトリを ~/DPI_examples ディレクトリにコピー&ペーストして、そのディレクトリの中の./run.csh を起動した。
DPI_examples_3_170809.png
DPI_examples_4_170809.png
DPI_examples_5_170809.png

PASSED が表示されたので成功だ。

~/DPI_examples/simple_export ディレクトリには、やはり、いろいろなファイルが生成されている。
DPI_examples_2_170809.png
  1. 2017年08月11日 05:21 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

Vivado シミュレータのDPI-C その1

Vivado シミュレータでDPI (Direct Programming Interface)をやってみることにした。

参考にするのは、aster_ismの工作室さんの”Vivado SimulatorによるDPI-Cシミュレーション”だ。
Vivado SimulatorによるDPI-Cシミュレーション”によるとVivado シミュレータのDPI のサンプルが /opt/Xilinx/Vivado/バージョン番号/examples/xsim/systemverilog/dpi/ にあるそうだ。

VirtualBox 上のUbuntu 16.04 の /opt/Xilinx/Vivado/2016.4/examples/xsim/systemverilog/dpi/ に行ってみると、simple_import と simple_export の2つのディレクトリがあった。
DPI_examples_11_170809.png

そのうちの simple_import ディレクトリの中に入ってみた。
DPI_examples_6_170809.png

README と file.sv, function.c, run.csh があった。
README を引用する。

Steps
-----
1. Run the setup for Xilinx executables.
2. Check if the executables "xsc" and "xelab" are in your PATH.
3. Invoke run.csh

This example shows a simple DPI-C import usage. The System Verilog code (file.sv)
calls a function "myFunction" that is defined on the C side in the file function.c.
The C code is compiled using xsc to create a dll in directory xsim.dir/xsc/dpi.so.
This dll is then linked into when using "xelab" to compile the file.sv
You could use your own compiler (gcc) for compiling and creating a dll.
myFunction() call into the C code returns an C integer value of 5 which is then checked
by the System Verilog code triggering a "PASSED" output for a valid run.


function.c を引用する。


#include "svdpi.h"

DPI_DLLESPEC
int myFunction()
{
    return 5;
}


// XSIP watermark, do not delete 67d7842dbbe25473c3c32b93c0da8047785f30d78e8a024de1b57352245f9689


file.sv を引用する。


module m();

import "DPI-C" pure function int myFunction ();

int i;

initial
begin
#1;
  i = myFunction();
  if( i == 5)
    $display("PASSED");
  else
    $display("FAILED");
  $finish();
end


endmodule


最後に run.csh を引用する。

#!/bin/csh -xvf
xsc function.c
xvlog -svlog file.sv
xelab work.m -sv_lib dpi -R


run.csh のコマンドについては、”Vivado Design Suite ユーザー ガイド ロジック シ ミ ュレーシ ョ ン UG900 (v2017.1) 2017 年 4 月 5 日”の 171 ページの”付録 D Vivado シミュレータのダイレクト プログラミング インターフェイス (DPI)”に書いてある。
そこから引用する。

xsc コ ンパイ ラ を使用する と、 1 つまたは複数の C フ ァ イルから共有ラ イブラ リ (Windows の場合は .a、 Linux の場合は .so) を作成でき ます。


xvlog はSystemVerilog を解析するパーサーのようだ。
xelab はシミュレータ・コンパイラで、HDL モデルがスナップショットにコンパイルされるそうだ。

さて、Ubuntu 16.04 上で、/opt/Xilinx/Vivado/2016.4/examples/xsim/systemverilog/dpi/simple_import ディレクトリを ~/DPI_examples ディレクトリにコピー&ペーストして、そのディレクトリの中の./run.csh を起動してみた。
最初に csh がインストールされていなかったので、sudo apt-get install csh でインストールした。
DPI_examples_8_170809.png
DPI_examples_9_170809.png
DPI_examples_10_170809.png

PASSED が表示された。成功だ。

なお、 ~/DPI_examples/simple_import ディレクトリはいろいろなファイルが生成されている。
DPI_examples_7_170809.png
  1. 2017年08月10日 04:33 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

映画『ジョジョの奇妙な冒険 ダイヤモンドは砕けない 第一章』を見てました

今日は8月11日に大学説明会で出勤するので、振替休日だった。なので、映画『ジョジョの奇妙な冒険 ダイヤモンドは砕けない 第一章』(音注意)を見てきた。
少し怖かったが(ジョジョの奇妙な冒険は漫画でも怖かったので、よく読んでいない)面白かった。
  1. 2017年08月09日 17:18 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作7(学習2)

白線追従走行用畳み込みニューラルネットワークの製作6(学習1)”の続き。

前回は、白線追従走行の直線走行用のトレーニング・データとテスト・データを用意し、それらのデータセットを使用するためのPython コードのstraight_dataset.py を用意した。今回は、浮動小数点数を使用して畳み込みニューラルネットワーク(CNN)をトレーニングするためにPython コードを修正する。
今回使用するフォルダは前回コピー&ペーストした ch07_straight フォルダだ。その内容を示す。
wlt_cnn_40_170808.png

このうちの、simple_convnet.py を変更した。このCNNを記述するPython コードはn x n の画像に対応しているコードだった。今回は 10 x 56 で行と列の数が違っているので、対応することができないのだ。そこで、input_size の代わりにinput_size_x とinput_size_y をconv_output_size の代わりにconv_output_size_x とconv_output_size_y を作った。

        input_size_y = input_dim[1]
        input_size_x = input_dim[2]
        conv_output_size_y = (input_size_y - filter_size + 2*filter_pad) / filter_stride + 1
        conv_output_size_x = (input_size_x - filter_size + 2*filter_pad) / filter_stride + 1
        pool_output_size = int(filter_num * (conv_output_size_y/2) * (conv_output_size_x/2))


simple_convnet.py の全文を貼っておく。

# simple_convnet.py
# 2017/08/08 白線追従走行用CNNに変更 by marsee
# 元になったコードは、https://github.com/oreilly-japan/deep-learning-from-scratch にあります。
# 改変したコードもMITライセンスとします。 2017/08/08 by marsee

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
import pickle
import numpy as np
from collections import OrderedDict
from common.layers import *
from common.gradient import numerical_gradient


class SimpleConvNet:
    """単純なConvNet

    conv - relu - pool - affine - relu - affine - softmax
    
    Parameters
    ----------
    input_size : 入力サイズ(MNISTの場合は784)
    hidden_size_list : 隠れ層のニューロンの数のリスト(e.g. [100, 100, 100])
    output_size : 出力サイズ(MNISTの場合は10)
    activation : 'relu' or 'sigmoid'
    weight_init_std : 重みの標準偏差を指定(e.g. 0.01)
        'relu'または'he'を指定した場合は「Heの初期値」を設定
        'sigmoid'または'xavier'を指定した場合は「Xavierの初期値」を設定
    """
    def __init__(self, input_dim=(1, 10, 56), 
                 conv_param={'filter_num':30, 'filter_size':5, 'pad':0, 'stride':1},
                 hidden_size=100, output_size=10, weight_init_std=0.01):
        filter_num = conv_param['filter_num']
        filter_size = conv_param['filter_size']
        filter_pad = conv_param['pad']
        filter_stride = conv_param['stride']
        input_size_y = input_dim[1]
        input_size_x = input_dim[2]
        conv_output_size_y = (input_size_y - filter_size + 2*filter_pad) / filter_stride + 1
        conv_output_size_x = (input_size_x - filter_size + 2*filter_pad) / filter_stride + 1
        pool_output_size = int(filter_num * (conv_output_size_y/2) * (conv_output_size_x/2))
        print("pool_output_size ={0}".format(pool_output_size))

        # 重みの初期化
        self.params = {}
        self.params['W1'] = weight_init_std * \
                            np.random.randn(filter_num, input_dim[0], filter_size, filter_size)
        self.params['b1'] = np.zeros(filter_num)
        self.params['W2'] = weight_init_std * \
                            np.random.randn(pool_output_size, hidden_size)
        self.params['b2'] = np.zeros(hidden_size)
        self.params['W3'] = weight_init_std * \
                            np.random.randn(hidden_size, output_size)
        self.params['b3'] = np.zeros(output_size)

        # レイヤの生成
        self.layers = OrderedDict()
        self.layers['Conv1'] = Convolution(self.params['W1'], self.params['b1'],
                                           conv_param['stride'], conv_param['pad'])
        self.layers['Relu1'] = Relu()
        self.layers['Pool1'] = Pooling(pool_h=2, pool_w=2, stride=2)
        self.layers['Affine1'] = Affine(self.params['W2'], self.params['b2'])
        self.layers['Relu2'] = Relu()
        self.layers['Affine2'] = Affine(self.params['W3'], self.params['b3'])

        self.last_layer = SoftmaxWithLoss()

    def predict(self, x):
        for layer in self.layers.values():
            x = layer.forward(x)

        return x

    def loss(self, x, t):
        """損失関数を求める
        引数のxは入力データ、tは教師ラベル
        """
        y = self.predict(x)
        return self.last_layer.forward(y, t)

    def accuracy(self, x, t, batch_size=100):
        if t.ndim != 1 : t = np.argmax(t, axis=1)
        
        acc = 0.0
        
        for i in range(int(x.shape[0] / batch_size)):
            tx = x[i*batch_size:(i+1)*batch_size]
            tt = t[i*batch_size:(i+1)*batch_size]
            y = self.predict(tx)
            y = np.argmax(y, axis=1)
            acc += np.sum(y == tt) 
        
        return acc / x.shape[0]

    def numerical_gradient(self, x, t):
        """勾配を求める(数値微分)

        Parameters
        ----------
        x : 入力データ
        t : 教師ラベル

        Returns
        -------
        各層の勾配を持ったディクショナリ変数
            grads['W1']、grads['W2']、...は各層の重み
            grads['b1']、grads['b2']、...は各層のバイアス
        """
        loss_w = lambda w: self.loss(x, t)

        grads = {}
        for idx in (1, 2, 3):
            grads['W' + str(idx)] = numerical_gradient(loss_w, self.params['W' + str(idx)])
            grads['b' + str(idx)] = numerical_gradient(loss_w, self.params['b' + str(idx)])

        return grads

    def gradient(self, x, t):
        """勾配を求める(誤差逆伝搬法)

        Parameters
        ----------
        x : 入力データ
        t : 教師ラベル

        Returns
        -------
        各層の勾配を持ったディクショナリ変数
            grads['W1']、grads['W2']、...は各層の重み
            grads['b1']、grads['b2']、...は各層のバイアス
        """
        # forward
        self.loss(x, t)

        # backward
        dout = 1
        dout = self.last_layer.backward(dout)

        layers = list(self.layers.values())
        layers.reverse()
        for layer in layers:
            dout = layer.backward(dout)

        # 設定
        grads = {}
        grads['W1'], grads['b1'] = self.layers['Conv1'].dW, self.layers['Conv1'].db
        grads['W2'], grads['b2'] = self.layers['Affine1'].dW, self.layers['Affine1'].db
        grads['W3'], grads['b3'] = self.layers['Affine2'].dW, self.layers['Affine2'].db

        return grads
        
    def save_params(self, file_name="params.pkl"):
        params = {}
        for key, val in self.params.items():
            params[key] = val
        with open(file_name, 'wb') as f:
            pickle.dump(params, f)

    def load_params(self, file_name="params.pkl"):
        with open(file_name, 'rb') as f:
            params = pickle.load(f)
        for key, val in params.items():
            self.params[key] = val

        for i, key in enumerate(['Conv1', 'Affine1', 'Affine2']):
            self.layers[key].W = self.params['W' + str(i+1)]
            self.layers[key].b = self.params['b' + str(i+1)]


次に、Jupyter Notebook を立ち上げて、DLFS_Chap7.ipynb を起動した。
wlt_cnn_41_170808.png

train_convnet.py のdataset_straight.straight_dataset を読むように変更し、また、input_dim=(1,10,56) に変更した。
wlt_cnn_42_170808.png

train_convnet.py を貼っておく。

# train_convnet.py
# 2017/08/08 白線追従走行用CNNに変更 by marsee
# 元になったコードは、https://github.com/oreilly-japan/deep-learning-from-scratch にあります。
# 改変したコードもMITライセンスとします。 2017/08/08 by marsee

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
import numpy as np
import matplotlib.pyplot as plt
from dataset_straight.straight_dataset import load_mnist
from simple_convnet import SimpleConvNet
from common.trainer import Trainer

# データの読み込み
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)

# 処理に時間のかかる場合はデータを削減 
#x_train, t_train = x_train[:5000], t_train[:5000]
#x_test, t_test = x_test[:1000], t_test[:1000]

max_epochs = 20

network = SimpleConvNet(input_dim=(1,10,56), 
                        conv_param = {'filter_num': 30, 'filter_size': 5, 'pad': 0, 'stride': 1},
                        hidden_size=100, output_size=3, weight_init_std=0.01)
                        
trainer = Trainer(network, x_train, t_train, x_test, t_test,
                  epochs=max_epochs, mini_batch_size=100,
                  optimizer='Adam', optimizer_param={'lr': 0.001},
                  evaluate_sample_num_per_epoch=100)
trainer.train()

# パラメータの保存
network.save_params("params.pkl")
print("Saved Network Parameters!")

# グラフの描画
markers = {'train': 'o', 'test': 's'}
x = np.arange(max_epochs)
plt.plot(x, trainer.train_acc_list, marker='o', label='train', markevery=2)
plt.plot(x, trainer.test_acc_list, marker='s', label='test', markevery=2)
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()


train_convnet.py を実行した結果を貼っておく。

pool_output_size =2340
train loss:1.09740103666
=== epoch:1, train acc:0.0, test acc:0.0 ===
train loss:1.09619339353
train loss:1.09805550027
train loss:1.09687513729
train loss:1.0943589982
train loss:1.09043641309
train loss:1.08765370932
train loss:1.08988835762
train loss:1.08589893222
train loss:1.08082757519
train loss:1.07091805021
train loss:1.06677488283
train loss:1.07590794106
train loss:1.07036316486
train loss:1.0564093902
train loss:1.04913884878
=== epoch:2, train acc:1.0, test acc:1.0 ===
train loss:1.05282141475
train loss:1.02463171511
train loss:1.03238803274
train loss:1.01808300652
train loss:1.00418097479
train loss:0.994927691467
train loss:0.971943720127
train loss:0.938959564805
train loss:0.959999566898
train loss:0.964902849483
train loss:0.930027599907
train loss:0.910958350671
train loss:0.912115741252
train loss:0.877372771453
train loss:0.881933637438
=== epoch:3, train acc:1.0, test acc:1.0 ===
train loss:0.82203361721
train loss:0.875176827014
train loss:0.799964071175
train loss:0.801881639351
train loss:0.815978625085
train loss:0.779677387859
train loss:0.808213315743
train loss:0.779122522377
train loss:0.67732259731
train loss:0.664630569144
train loss:0.696595385714
train loss:0.804241795734
train loss:0.665426441902
train loss:0.672940861823
train loss:0.65431805427
=== epoch:4, train acc:1.0, test acc:1.0 ===
train loss:0.733642727716
train loss:0.724044016753
train loss:0.728747015891
train loss:0.645574644162
train loss:0.563772565951
train loss:0.650969893624
train loss:0.71471792151
train loss:0.562708504548
train loss:0.603808048409
train loss:0.599713674484
train loss:0.627750549668
train loss:0.554349357064
train loss:0.615028866599
train loss:0.581826815111
train loss:0.614025507529
=== epoch:5, train acc:0.98, test acc:0.98 ===
train loss:0.536548177427
train loss:0.616438072707
train loss:0.545175491413
train loss:0.59173160996
train loss:0.593612159015
train loss:0.599846111758
train loss:0.602536956687
train loss:0.526653021569
train loss:0.493542164942
train loss:0.652987814042
train loss:0.593193099959
train loss:0.651098995425
train loss:0.583797795175
train loss:0.497425254547
train loss:0.50022478405
=== epoch:6, train acc:1.0, test acc:0.99 ===
train loss:0.546986740154
train loss:0.632857452048
train loss:0.596720193602
train loss:0.628242539831
train loss:0.516102642255
train loss:0.584049938495
train loss:0.643520590658
train loss:0.433788079879
train loss:0.464739965862
train loss:0.517770447956
train loss:0.565927389082
train loss:0.574423786278
train loss:0.487440270503
train loss:0.460763808238
train loss:0.50437176485
=== epoch:7, train acc:0.91, test acc:0.8 ===
train loss:0.539680492517
train loss:0.43184783555
train loss:0.463142994517
train loss:0.40834945717
train loss:0.502730258745
train loss:0.530335381027
train loss:0.483509730618
train loss:0.419754214749
train loss:0.542743643599
train loss:0.545018581985
train loss:0.527738479101
train loss:0.552609220918
train loss:0.511188282627
train loss:0.439410114208
train loss:0.547204230479
=== epoch:8, train acc:0.87, test acc:0.74 ===
train loss:0.42177291798
train loss:0.37878361722
train loss:0.553163684557
train loss:0.573063758222
train loss:0.39186244896
train loss:0.445078706415
train loss:0.462594294123
train loss:0.438555772242
train loss:0.385638041553
train loss:0.415701287503
train loss:0.391015150038
train loss:0.468615281475
train loss:0.504983134551
train loss:0.377033870421
train loss:0.39501268333
=== epoch:9, train acc:0.95, test acc:0.89 ===
train loss:0.387747127634
train loss:0.385348791912
train loss:0.482271444765
train loss:0.397431981912
train loss:0.38837660175
train loss:0.456368766821
train loss:0.381980621014
train loss:0.320979196606
train loss:0.374925172354
train loss:0.424100142739
train loss:0.339776275437
train loss:0.379021958425
train loss:0.415783734932
train loss:0.312515924983
train loss:0.493949450648
=== epoch:10, train acc:0.99, test acc:0.9 ===
train loss:0.443524574076
train loss:0.357979512064
train loss:0.415673465881
train loss:0.362790259715
train loss:0.25231192493
train loss:0.405671943517
train loss:0.35069212333
train loss:0.372544883284
train loss:0.409110864872
train loss:0.343560294381
train loss:0.31804787133
train loss:0.403356537286
train loss:0.268652788357
train loss:0.394903753068
=============== Final Test Accuracy ===============
test acc:0.714666666667
Saved Network Parameters!
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-d6e09c53f736> in <module>()
     36 markers = {'train': 'o', 'test': 's'}
     37 x = np.arange(max_epochs)
---> 38 plt.plot(x, trainer.train_acc_list, marker='o', label='train', markevery=2)
     39 plt.plot(x, trainer.test_acc_list, marker='s', label='test', markevery=2)
     40 plt.xlabel("epochs")

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\pyplot.py in plot(*args, **kwargs)
   3316                       mplDeprecation)
   3317     try:
-> 3318         ret = ax.plot(*args, **kwargs)
   3319     finally:
   3320         ax._hold = washold

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\__init__.py in inner(ax, *args, **kwargs)
   1889                     warnings.warn(msg % (label_namer, func.__name__),
   1890                                   RuntimeWarning, stacklevel=2)
-> 1891             return func(ax, *args, **kwargs)
   1892         pre_doc = inner.__doc__
   1893         if pre_doc is None:

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_axes.py in plot(self, *args, **kwargs)
   1404         kwargs = cbook.normalize_kwargs(kwargs, _alias_map)
   1405 
-> 1406         for line in self._get_lines(*args, **kwargs):
   1407             self.add_line(line)
   1408             lines.append(line)

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _grab_next_args(self, *args, **kwargs)
    405                 return
    406             if len(remaining) <= 3:
--> 407                 for seg in self._plot_args(remaining, kwargs):
    408                     yield seg
    409                 return

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _plot_args(self, tup, kwargs)
    383             x, y = index_of(tup[-1])
    384 
--> 385         x, y = self._xy_from_xy(x, y)
    386 
    387         if self.command == 'plot':

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _xy_from_xy(self, x, y)
    242         if x.shape[0] != y.shape[0]:
    243             raise ValueError("x and y must have same first dimension, but "
--> 244                              "have shapes {} and {}".format(x.shape, y.shape))
    245         if x.ndim > 2 or y.ndim > 2:
    246             raise ValueError("x and y can be no greater than 2-D, but have "

ValueError: x and y must have same first dimension, but have shapes (20,) and (10,)

In [21]:

print(network.params['W1'].shape)


plot がなぜか?エラーになってしまう。

テストデータの正解率が 71 % になってしまうのは低すぎないだろうか?
もう一度、トレーニング・データを取り直してみようか?
  1. 2017年08月09日 03:34 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作6(学習1)

白線追従走行用畳み込みニューラルネットワークの製作5(テストデータの作成)”の続き。

前回はテストデータを測定しファイルにまとめた。今回はトレーニング・ファイルとテスト・ファイルがそろったので、Pythonコードを使用したのCNNの学習を行う。

「ゼロから作るDeep Learning」の畳み込みニューラルネットワークのハードウェア化1”からのブログ記事を参考にMNISTから白線追従データセット用に変更する。

まずは、dataset_straight フォルダを作成し、ch07 フォルダをコピー&ペーストして ch07_straight フォルダを作成した。
wlt_cnn_39_170808.png

dataset_straight フォルダに”白線追従走行用畳み込みニューラルネットワークの製作3(トレーニング、ラベル・ファイルの作成)”で作成したトレーニングの画像ファイルの train_straight_run_image とラベル・ファイル train_straight_run_label をコピー&ペーストした。更に、”白線追従走行用畳み込みニューラルネットワークの製作5(テストデータの作成)”で作成したテスト用の画像ファイルtest_straight_run_image とテスト用のラベル・ファイル test_straight_run_label をコピー&ペーストした。
次に、mnist.py をベースに straight_dataset.py を作成した。なお、多くのPython コードで load_mnist() が使用されているので、それは変更していない。straight_dataset.py を示す。

# straight_dataset.py
# 2017/08/08 白線追従走行用CNNに変更 by marsee
# 元になったコードは、https://github.com/oreilly-japan/deep-learning-from-scratch の mnist.py です
# 改変したコードもMITライセンスとします。 2017/08/08 by marsee

# coding: utf-8
try:
    import urllib.request
except ImportError:
    raise ImportError('You should use Python 3.x')
import os.path
import gzip
import pickle
import os
import numpy as np


key_file = {
    'train_img':'train_straight_run_image',
    'train_label':'train_straight_run_label',
    'test_img':'test_straight_run_image',
    'test_label':'test_straight_run_label'
}

dataset_dir = os.path.dirname(os.path.abspath(__file__))
save_file = dataset_dir + "/mnist.pkl"

train_num = 750
test_num = 375
img_dim = (1, 10, 56)
img_size = 560


def _load_label(file_name):
    file_path = dataset_dir + "/" + file_name
    
    print("Converting " + file_name + " to NumPy Array ...")
    with open(file_path, 'rb') as f:
            labels = np.frombuffer(f.read(), np.uint8, offset=8)
    print("Done")
    
    return labels

def _load_img(file_name):
    file_path = dataset_dir + "/" + file_name
    
    print("Converting " + file_name + " to NumPy Array ...")    
    with open(file_path, 'rb') as f:
            data = np.frombuffer(f.read(), np.uint8, offset=16)
    data = data.reshape(-1, img_size)
    print("Done")
    
    return data
    
def _convert_numpy():
    dataset = {}
    dataset['train_img'] =  _load_img(key_file['train_img'])
    dataset['train_label'] = _load_label(key_file['train_label'])    
    dataset['test_img'] = _load_img(key_file['test_img'])
    dataset['test_label'] = _load_label(key_file['test_label'])
    
    return dataset

def init_mnist():
    dataset = _convert_numpy()
    print("Creating pickle file ...")
    with open(save_file, 'wb') as f:
        pickle.dump(dataset, f, -1)
    print("Done!")

def _change_one_hot_label(X):
    T = np.zeros((X.size, 3))
    for idx, row in enumerate(T):
        row[X[idx]] = 1
        
    return T
    

def load_mnist(normalize=True, flatten=True, one_hot_label=False):
    """MNISTデータセットの読み込み
    
    Parameters
    ----------
    normalize : 画像のピクセル値を0.0~1.0に正規化する
    one_hot_label : 
        one_hot_labelがTrueの場合、ラベルはone-hot配列として返す
        one-hot配列とは、たとえば[0,0,1,0,0,0,0,0,0,0]のような配列
    flatten : 画像を一次元配列に平にするかどうか 
    
    Returns
    -------
    (訓練画像, 訓練ラベル), (テスト画像, テストラベル)
    """
    if not os.path.exists(save_file):
        init_mnist()
        
    with open(save_file, 'rb') as f:
        dataset = pickle.load(f)
    
    if normalize:
        for key in ('train_img', 'test_img'):
            dataset[key] = dataset[key].astype(np.float32)
            dataset[key] /= 255.0
            
    if one_hot_label:
        dataset['train_label'] = _change_one_hot_label(dataset['train_label'])
        dataset['test_label'] = _change_one_hot_label(dataset['test_label'])
    
    if not flatten:
         for key in ('train_img', 'test_img'):
            dataset[key] = dataset[key].reshape(-1, 1, 10, 56)

    return (dataset['train_img'], dataset['train_label']), (dataset['test_img'], dataset['test_label']) 


if __name__ == '__main__':
    init_mnist()


いろいろと元の mnist.py そのままだが、とりあえず、これで動くようだ。

dataset_straight フォルダを示す。
wlt_cnn_38_170808.png

今日は寝坊してしまったので、ここまで。明日に続きます。
  1. 2017年08月08日 07:34 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

MFT2017 に行って来ました

近頃久しく出展してないですが、昨日MFT2017 に見学に行ってきました。
MFT2017_1_170807.jpg

会場の様子です。
MFT2017_2_170807.jpg

朝から、にぎわっていました。

筑波大学の学生さんのSigboost もありました。ケースの中にZYBO が入っていました。

FabLab Kannai の作品です。木をレーザー加工機で加工した板を組み合わせて丸い形にしていました。とっても良い感じでしたね。
MFT2017_3_170807.jpg

MFT2017_4_170807.jpg

Make Network の方のワークベンチです。作りは荒かったですが、どこでも移動して広げて作業するというコンセプトが良かったです。
MFT2017_5_170807.jpg

千葉大学平沢研究室の木工用5軸加工機で加工した木材の数々。でもこの加工機では完全な加工はできないような?ノミも使っているのかもしれません?
MFT2017_6_170807.jpg

MFT2017_7_170807.jpg

木工用5軸加工機。
MFT2017_8_170807.jpg

加工の様子。音がうるさいので注意です。


HotDog というIchgoJam 向けのロボットカーが走っていました。私の作っているミニ・ロボットカーの土台にいいかな?と思って資料もらってきました。

MachiKania というPIC32 が搭載されたカラーテレビゲームシステムがありました。ビデオ信号をPIC32 のソフトウェアで作っているそうです。同期の時にゲームの処理をしているそうです。凄いです。大変そう。。。お値段はPIC32 だけで済むので、安いそうです。

そうそう、R2D2たちもいました。著作権は大丈夫なのかな?ピンぼけ写真ですみません。。。
MFT2017_9_170807.jpg

MFT2017_10_170807.jpg

スイッチサイエンスやRS コンポーネンツなども来ていました。

私も持っているHAKKO のはんだごてのFX-600 に数量限定ではありますが、ピンクとゴールド、シルバーの新色が登場したそうです。凄いです。女性が喜ぶからなんですかね?

29,800円の 3D プリンタ BS CUBE がありました。でも、スライスソフトは自分で用意するとのことです。大丈夫かな?
アマゾンでも売っています。なかなか良かったです。

マンホールのふたの写真を集めているアプリの宣伝がありました。面白いです。ご当地マンホール蓋。つくば市にもスペースシャトルのマンホール蓋があります。見ました。

ラズベリーパイカメラに取り付けて魚眼レンズにするというのがありました。Entaniya ラズベリーパイ VR 220 改造キット

4096個だったかな?を使用したLED の3次元ディスプレイです。LEDの数に圧倒されました。
MFT2017_11_170807.jpg

面白そうなものとしては、空飛ぶスーパーカブがありました。ターボプロップ・エンジンしょって飛ぶのは大丈夫でしょうか?飛べれば面白いですが。。。ネタにしかならない気もします。

写真はホバークラフトです。飛んでいるところはなかったです。残念。。。
MFT2017_12_170807.jpg

最後につくば科学株式会社のテスラコイルです。放電で音楽を流していましたが、凄い音量です。イベントで使えそうですね。。。
MFT2017_13_170807.jpg

あと、DNNを使ったものがちらほらと。。。きゅうりの選別は有名ですが、鳥箱に入った鳥をYOROを使ったDNNで判別というのもありました。Jetson 使っているそうです。ディスプレイに写した鳥を判別していました。

以上独断と偏見のMFT2017 レポートでした。
  1. 2017年08月07日 05:21 |
  2. Make出展
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作5(テストデータの作成)

白線追従走行用畳み込みニューラルネットワークの製作4(トレーニング・ファイルのチェック)”の続き。

前回は、トレーニング・ファイルをチェックして、画像が取り出せることが分かった。今回は、テストデータを作成してみよう。

トレーニング・ファイルは結構いい加減にデータを取ってしまったが、テストデータはデータのとり方を記録に残しておくことにする。

白線追従テストデータ測定方法

<直進>
ミニロボットカーが真っ直ぐの時の角度 111度
左、右 ±7度
左右車輪が白線の真ん中、姿勢は真っ直ぐ

<左ターン>
白線内 +15度
白線内 +20度
右車輪白線逸脱車体1/4
右車輪白線逸脱車体1/4 + +10度
右車輪白線逸脱車体1/2

<右ターン>
白線内 -15度
白線内 -20度
左車輪白線逸脱車体1/4
左車輪白線逸脱車体1/4 + -10度
左車輪白線逸脱車体1/2


なお、角度はデジタルコンパスで測定した。まずはまっすぐで、白線のちょうど真ん中の時。(直進)
wlt_cnn_33_170805.jpg

左車輪が白線の真ん中、姿勢は真っ直ぐ(直進)。
wlt_cnn_34_170805.jpg

白線内 +15度(左ターン)。
wlt_cnn_35_170805.jpg

右車輪白線逸脱車体1/4(左ターン)。
wlt_cnn_36_170805.jpg

右車輪白線逸脱車体1/4 + +10度(左ターン)。
wlt_cnn_37_170805.jpg

なお、撮影したBMPファイルは直進(straight_test?.bmp)と左ターン(left_turn_test?.bmp)と右ターン(right_turn_test?.bmp)がそれぞれ5枚ずつとなった。よって、3 x 5 x 25 = 375 枚となった。

Vivado HLS 2016.4 で straight_test_dataset を作成した。
straight_test_dataset ディレクトリにBMPファイルと straight_dataset_bmp.cpp と straight_dataset_bmp.h をコピー&ペーストした。
straight_dataset_bmp.h をテストデータ用に記述を変更した。
wlt_cnn_26_170805.png

straight_dataset_bmp.cpp をテストデータ用に記述を変更した。
wlt_cnn_27_170805.png

C シミュレーションを行った。
wlt_cnn_28_170805.png

test_straight_run_image と test_straight_run_label ができた。
wlt_cnn_28_170805.png

solution1/csim/build ディレクトリを示す。
wlt_cnn_29_170805.png

wlt_cnn_30_170805.png

test_straight_run_image の内容を示す。
wlt_cnn_31_170805.png

test_straight_run_label の内容を示す。
wlt_cnn_32_170805.png

これでテストデータもできたので、いよいよ学習を始められるかな?
  1. 2017年08月05日 05:27 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作4(トレーニング・ファイルのチェック)

白線追従走行用畳み込みニューラルネットワークの製作3(トレーニング、ラベル・ファイルの作成)”の続き。

前回は、straight_dataset_bmp.cpp を作成して、直進学習用の白線の画像のMNISTフォーマットのトレーニング・ファイルとラベル・ファイルを作成した。今回は、トレーニング・ファイルを本当に画像が格納されているかどうか?をチェックする。

トレーニング・ファイルは、train_straight_run_image という名前だ。
Vivado HLS 2016.4 の straight_dataset_check プロジェクトを作成し、train_straight_run_image と、新たに作成したstraight_dataset_check.cpp とstraight_dataset_bmp.h を straight_dataset_check プロジェクトのディレクトリにコピーした。
wlt_cnn_20_170804.png

straight_dataset_check.cpp を貼っておく。なお、このアプリケーションソフトは、train_straight_run_image からIMAGE_NUMBER 番目の画像を output.bmp に変換する。現在のIMAGE_NUMBER は 0 だ。つまり最初の画像を output.bmp に変換する。

// straight_dataset_check.cpp
// 2017/08/02 by marsee
//

#include <iostream>
#include "hls_opencv.h"
#include "straight_dataset_bmp.h"

#define IMAGE_NUMBER 4

int main(){
    FILE *ftin, *ftln;
    char train_image_name[256] = "train_straight_run_image";
    uint8_t buf[600];

    if ((ftin = fopen(train_image_name, "rb")) == NULL){
        fprintf(stderr, "Can't open %s\n", train_image_name);
        exit(1);
    }

    fread(buf, sizeof(uint32_t), 4, ftin); // header read

    for(int i=0; i<=IMAGE_NUMBER; i++){
        fread(buf, sizeof(uint8_t), DATASET_HEIGHT*DATASET_WIDTH, ftin);
    }

    cv::Mat wlt_img(cv::Size(5610), CV_8UC1);

    for (int y = 0; y < wlt_img.rows; y++) {
        for (int x = 0; x < wlt_img.cols; x++) {
            wlt_img.at<uchar>(y, x) = buf[y*DATASET_WIDTH+x];
        }
    }

    cv::imwrite("output.bmp", wlt_img);

    fclose(ftin);

    return(0);
}


straight_dataset_bmp.h は前回と同じファイルを使用している。

C シミュレーションを行った。
wlt_cnn_21_170804.png

output.bmp が生成されているのが分かる。
output.bmp を見てみよう。
wlt_cnn_22_170804.png

最初の画像が抽出されたのが分かった。

それでは、IMAGE_NUMBER を 4 に変更して、もう一度、C シミュレーションを行った。なお、5 番目の画像は、一番右側の画像になる。1つの白線の画像から 5 x 5 = 25 個のトレーニング用画像を生成している。最初に1ピクセルずつ段々と右にシフトしていくので
5 個目の画像が一番右側の画像となる。
wlt_cnn_23_170804.png

生成された output.bmp を示す。
wlt_cnn_24_170804.png

IMAGE_NUMBER が 0 の画像よりも右側の白線の画像だということが分かると思う。

これで、トレーニング・ファイルも問題なさそうだということが分かった。

OpenCV を使うとソースコードが短くなって書くのが楽でよい。
  1. 2017年08月04日 04:19 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作3(トレーニング、ラベル・ファイルの作成)

白線追従走行用畳み込みニューラルネットワークの製作2(画像縮小、切り出し)”の続き。

前回は、800 x 600 ピクセルの元画像を 60 x 45 に縮小してから、白黒変換し、56 x 10 ピクセルの白線の画像を切り出した。今回は、本格的に56 x 10 ピクセルの白線の画像を切り出すとともに、MNISTデータセットと同じフォーマットでトレーニング・ファイルとラベル・ファイルを生成しよう。
なお、ソフトを作成する際に参考にしたサイトは、”OpenCV入門 2.画像の簡単操作”だ。このサイトには、Matからピクセル値を取り出す方法が書いてある。

まずは、straight_dataset_bmp.cpp を変更した。ここに貼っておく。なお、3つ続けて、同じコードを使用して、みっともないことをお詫びしておく。
buf[0] = htonl(0x803); の htonl() だが、uint32_t を fwrite() するとリトルエンディアンでファイルに書き込まれてしまう。つまり、0x00000803 だと 03 08 00 00 と書き込まれてしまう。これではまずいので、ビックエンディアンに変更した。リトルエンディアンをビックエンディアンに変更する関数が htonl() である。

// straight_dataset_bmp.cpp
// 2017/07/24 by marsee
//

#include <iostream>
#include "hls_opencv.h"
#include "straight_dataset_bmp.h"
#include <arpa/inet.h>

int main(){
    char straight_fn[256] = "straight";
    char left_turn_fn[256] = "left_turn";
    char right_turn_fn[256] = "right_turn";
    char bmp_file[256];
    FILE *ftin, *ftln;
    char train_image_name[256] = "train_straight_run_image";
    char train_label_name[256] = "train_straight_run_label";
    uint32_t buf[5];
    uint8_t bufchar[100];


    if ((ftin = fopen(train_image_name, "wb")) == NULL){
        fprintf(stderr, "Can't open %s\n", train_image_name);
        exit(1);
    }
    if ((ftln = fopen(train_label_name, "wb")) == NULL){
        fprintf(stderr, "Can't open %s\n", train_label_name);
        exit(1);
    }

    // Writed header
    buf[0] = htonl(0x803); // magic number
    buf[1] = htonl(750); // number of image (750)
    buf[2] = htonl(10); // number of rows (10)
    buf[3] = htonl(56); // number of columns (56)
    fwrite(buf, sizeof(uint32_t), 4, ftin);

    buf[0] = htonl(0x801); // magic number
    buf[1] = htonl(750); // number of image (750)
    fwrite(buf, sizeof(uint32_t), 2, ftln);

    // refereed to http://opencv.jp/cookbook/opencv_img.html
    // straight
    for(int i=0; i<STRAIGHT_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s%d.bmp", straight_fn, i);
        cv::Mat straight_img = cv::imread(bmp_file,1);
        if(straight_img.empty())
            return(-1);
        cv::Mat reduct_img(straight_img.rows*0.075, straight_img.cols*0.075, straight_img.type());
        cv::resize(straight_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        sprintf(bmp_file, "%s_RED%d.bmp", straight_fn, i);
        cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", straight_fn, i, y, x);
                cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x1;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    // left turn
    for(int i=0; i<LEFT_TRUN_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s%d.bmp", left_turn_fn, i);
        cv::Mat left_trun_img = cv::imread(bmp_file,1);
        if(left_trun_img.empty())
            return(-1);
        cv::Mat reduct_img(left_trun_img.rows*0.075, left_trun_img.cols*0.075, left_trun_img.type());
        cv::resize(left_trun_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        sprintf(bmp_file, "%s_RED%d.bmp", left_turn_fn, i);
        cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", left_turn_fn, i, y, x);
                cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x0;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    // right turn
    for(int i=0; i<STRAIGHT_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s%d.bmp", right_turn_fn, i);
        cv::Mat right_trun_img = cv::imread(bmp_file,1);
        if(right_trun_img.empty())
            return(-1);
        cv::Mat reduct_img(right_trun_img.rows*0.075, right_trun_img.cols*0.075, right_trun_img.type());
        cv::resize(right_trun_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        sprintf(bmp_file, "%s_RED%d.bmp", right_turn_fn, i);
        cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", right_turn_fn, i, y, x);
                cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x2;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    fclose(ftin);
    fclose(ftln);

    return(0);
}


次に、straight_dataset_bmp.h を貼っておく。これはバグをフィックスした。

// straight_dataset_bmp.h
// 2017/07/24 by marsee
//

#ifndef __STRAIGHT_DATASET_BMP_H__
#define __STRAIGHT_DATASET_BMP_H__

#include "hls_video.h"

#define BMP_HEIGHT    600
#define BMP_WIDTH    800

#define REDUCTION_RATIO    0.075    // 1/13.3333... 60x45

#define DATASET_HEIGHT    10
#define DATASET_WIDTH    56

#define STRAIGHT_BMP_FILE_NAME        straight
#define LEFT_TRUN_BMP_FILE_NAME        left_turn
#define RIGHT_TRUN_BMP_FILE_NAME    right_turn
#define STRAIGHT_NUM_OF_IMAGE        10
#define LEFT_TRUN_NUM_OF_IMAGE        10
#define RIGHT_TRUNNUM_OF_IMAGE        10

typedef hls::Scalar<3unsigned char> RGB_PIXEL;
typedef hls::Mat<BMP_HEIGHT, BMP_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Mat<BMP_HEIGHT, BMP_WIDTH, HLS_8UC1> GRAY_IMAGE;

#endif


straight_dataset_bmp のVivado HLS プロジェクトを示す。
wlt_cnn_11_170803.png

C シミュレーションを行った。
wlt_cnn_12_170803.png

Straight_dataset_bmp/solution1/csim/build ディレクトリの内容を示す。ここにC シミュレーションの結果のファイルがある。
wlt_cnn_13_170803.png

wlt_cnn_19_170803.png

ピンクの四角枠で示した train_straight_run_image がトレーニング・ファイルで 56 x 10 ピクセルの 750 枚分の白線の画像が入っている。411KB だ。MNISTデータのフォーマットについては、”MNIST手書き数字のデータフォーマット”を参照のこと。
train_straight_run_label がラベル・ファイルだ。左旋回が 0 、直進が 1 、右旋回が 2 のラベルが入っている。1KB だ。

train_straight_run_label の内容を示す。
wlt_cnn_18_170803.png

train_straight_run_image の最初の部分を示す。
wlt_cnn_17_170803.png

ヘッダの次の値が 0x61, 0x5F なのに注目してほしい。
この値は、left_turn_RED_rect0_00.bmp ファイルの最初の行の最初の列からの2つのピクセル値のはずだ。
GIMP2 で見てみよう。スポイトを使用して、最初の行の最初の列(0, 0)の値を抜き出してみよう。
wlt_cnn_14_170803.png

(0, 0)のピクセル値は0x61 だった。
wlt_cnn_15_170803.png

(0, 1)のピクセル値は0x5F だった。
wlt_cnn_16_170803.png

これは、 train_straight_run_image の最初の 2 つのピクセル値と一致している。
これでトレーニング・ファイルとラベル・ファイルは大丈夫の様だが、一応、トレーニング・ファイルの値を読み込んで画像を復元するアプリケーションソフトを作成してみよう。
  1. 2017年08月03日 04:52 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

MNIST手書き数字のデータフォーマット

MNIST手書き数字のデータフォーマットを解析してみた。MNIST手書き数字のデータフォーマットに、今回、白線追従走行用のデータフォーマットを合わせた方が都合が良いのでやってみた。

日本語で参照したのは、”MNIST 手書き数字データを画像ファイルに変換する”。ここには、画像ファイルのフォーマットしか掲載されていなかったため、ラベルファイルのフォーマットも併せて、”MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges”を参照した。

MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges”から画像ファイルとラベルファイルのフォーマットを引用する。

TRAINING SET LABEL FILE (train-labels-idx1-ubyte):

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000801(2049) magic number (MSB first) 
0004     32 bit integer  60000            number of items 
0008     unsigned byte   ??               label 
0009     unsigned byte   ??               label 
........ 
xxxx     unsigned byte   ??               label
The labels values are 0 to 9.

TRAINING SET IMAGE FILE (train-images-idx3-ubyte):

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000803(2051) magic number 
0004     32 bit integer  60000            number of images 
0008     32 bit integer  28               number of rows 
0012     32 bit integer  28               number of columns 
0016     unsigned byte   ??               pixel 
0017     unsigned byte   ??               pixel 
........ 
xxxx     unsigned byte   ??               pixel
Pixels are organized row-wise. Pixel values are 0 to 255. 0 means background (white), 255 means foreground (black).

TEST SET LABEL FILE (t10k-labels-idx1-ubyte):

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000801(2049) magic number (MSB first) 
0004     32 bit integer  10000            number of items 
0008     unsigned byte   ??               label 
0009     unsigned byte   ??               label 
........ 
xxxx     unsigned byte   ??               label
The labels values are 0 to 9.

TEST SET IMAGE FILE (t10k-images-idx3-ubyte):

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000803(2051) magic number 
0004     32 bit integer  10000            number of images 
0008     32 bit integer  28               number of rows 
0012     32 bit integer  28               number of columns 
0016     unsigned byte   ??               pixel 
0017     unsigned byte   ??               pixel 
........ 
xxxx     unsigned byte   ??               pixel
Pixels are organized row-wise. Pixel values are 0 to 255. 0 means background (white), 255 means foreground (black). 


画像ファイルは 0 が白で 255 が黒だそうだ。そうか手書き数字は白地に黒だったのか。。。知らなかった。

実際のデータを見てみよう。トレーニングデータは大きいので、テストデータを見ていこう。
最初に画像ファイルの t10k-images-idx3-ubyte をバイナリエディタで見た。
MNIST_dataset_1_170801.png

最初の 0x0000 0803 が画像ファイルのマジック・ナンバーだ。その次の 0x0000 2710 は16進数なので、10進数に直すと10,000 となってデータの数を表す。0x0000 001c は10 進数にすると 28 だ。その次も同様。その後からは1バイトずつ、つまり、0 ~ 255 までのピクセル値を表す。

次にラベル・ファイルの t10k-labels-idx1-ubyte を見てみよう。
MNIST_dataset_2_170801.png

最初の 0x0000 0801 はラベル・ファイルのマジック・ナンバーだ。その次の 0x0000 2710 は16進数なので、10進数に直すと10,000 となってデータの数を表す。その次からはラベルが続いている。最初のラベルは0x07 で、つまり最初の数字は 7 であるということを表す。その次の数字は 2 だ。
  1. 2017年08月01日 12:37 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作2(画像縮小、切り出し)

白線追従走行用畳み込みニューラルネットワークの製作1(概要)”の続き。

前回から間が空いてしまったが、前回集めた直線の白線画像をデータセットにする第1段階として、画像縮小と切り出しを行うソフトウェアを作成してみよう。
Vivado HLSでハードウェア化しやすく、短いコードで書けるようにOpenCVを使用することにする。もちろんVivado HLSを使用して、Vivado HLSのテストベンチとして、C++ ソースファイルを用意する。環境はネイティブUbuntu16.04 でVivado HLS 2017.2 を使用している。

これからの白線追従のためのニューラルネット学習のためのデータ・セット作成手順を書いておく。

1. 800x600の白線画像を1/13.333...(0.075)の60x45に縮める。
2. 60x45のうちの下から60x14を中間BMPファイルとしてセーブ
3. 60x14のうちの56x10を切り出してBMPファイルに。1つにつき5x5の25個できる。
4. 左右直進をやる。
直進10枚x25+左旋回10x25+右旋回10x25=750このデータセットをとりあえず、作ってみようか?
56x10=560なのでMNISTデータセットよりも小さくなる。


現在のソースコードを貼っておく。まずは、ヘッダファイルの straight_dataset_bmp.h から。
(2017/08/03 :修正 バグフィックス)


// straight_dataset_bmp.h
// 2017/07/24 by marsee
//

#ifndef __STRAIGHT_DATASET_BMP_H__
#define __STRAIGHT_DATASET_BMP_H__

#include "hls_video.h"

#define BMP_HEIGHT 600
#define BMP_WIDTH 800

#define REDUCTION_RATIO 0.075 // 1/13.3333... 60x45

#define DATASET_HEIGHT 10
#define DATASET_WIDTH 56

#define STRAIGHT_BMP_FILE_NAME straight
#define LEFT_TRUN_BMP_FILE_NAME left_turn
#define RIGHT_TRUN_BMP_FILE_NAME right_turn
#define STRAIGHT_NUM_OF_IMAGE 10
#define LEFT_TRUN_NUM_OF_IMAGE 10
#define RIGHT_TRUNNUM_OF_IMAGE 10

typedef hls::Scalar<3, unsigned char> RGB_PIXEL;
typedef hls::Mat<BMP_HEIGHT, BMP_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Mat<BMP_HEIGHT, BMP_WIDTH, HLS_8UC1> GRAY_IMAGE;

#endif


次に、straight_dataset_bmp.cpp を貼っておく。まだ、直進の画像だけをしょりするコードだ。


// 2017/07/24 by marsee
//

#include <iostream>
#include "hls_opencv.h"
#include "straight_dataset_bmp.h"

int main(){
char straight_fn[256] = "straight";
char left_turn_fn[256] = "left_turn";
char right_turn_fn[256] = "right_turn";
char bmp_file[256];
cv::Rect rect_center(2, 33, 56, 10);

// refereed to http://opencv.jp/cookbook/opencv_img.html
// straight
for(int i=0; i<STRAIGHT_NUM_OF_IMAGE; i++){
sprintf(bmp_file, "%s%d.bmp", straight_fn, i);
cv::Mat straight_img = cv::imread(bmp_file,1);
if(straight_img.empty())
return(-1);
cv::Mat reduct_img(straight_img.rows*0.075, straight_img.cols*0.075, straight_img.type());
cv::resize(straight_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
cv::Mat gray_img;
cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

sprintf(bmp_file, "%s_RED%d.bmp", straight_fn, i);
cv::imwrite(bmp_file, gray_img);

cv::Rect rect_center(2, 33, 56, 10);
cv::Mat img_rect(gray_img, rect_center);
sprintf(bmp_file, "%s_RED_rect%d.bmp", straight_fn, i);
cv::imwrite(bmp_file, img_rect);
}

return(0);
}


Vivado HLS 2017.2 の画面を示す。C シミュレーションが終了したところだ。
wlt_cnn_6_170801.png

60x45 に縮小した 0 番目の直進の画像を示す。
wlt_cnn_7_170801.png

60x45 に縮小した 9 番目の直進の画像を示す。
wlt_cnn_8_170801.png

60x45 の画像から白線の 60x14 の画像を切り出して、その真ん中の56x10 の画像を更に切り出した。これは 0 番目の画像から切り出した。
wlt_cnn_9_170801.png

60x45 の画像から白線の 60x14 の画像を切り出して、その真ん中の56x10 の画像を更に切り出した。これは 9 番目の画像から切り出した。
wlt_cnn_10_170801.png

大体うまく行っているかな?1 つの白線画像から 5x5 = 25 個のトレーニング用画像ができるはずだ。
  1. 2017年08月01日 05:09 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0