FC2カウンター FPGAの部屋 DNN

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

FPGAの部屋

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

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

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

ソニーのNeural Network Console がVer. 1.1.0 になったので、やってみた。
zip ファイルを展開してからNeural Network Console を起動した。
Neural_Network_Console_38_171124.png

ENGINEはGPU に設定した。CPU よりも断然速い。GPU はNVidia のGTX1060 を搭載している。

LeNet.sdcproj をやってみた。
Neural_Network_Console_39_171124.png

TRAINING を実行した。
Neural_Network_Console_40_171124.png

EVALUATION を実行した。
Neural_Network_Console_41_171124.png

重みやバイアスの値を見たいので、ACTION をクリックして、Open Result Location をクリックした。
Neural_Network_Console_42_171124.png

F:\NN_console\samples\sample_project\image_recognition\MNIST\LeNet.files\20170804_140639 フォルダが開いた。
Neural_Network_Console_45_171124.png

どうやら parameters.h5 に重みやバイアスが書いてあるらしい?

見るためには、hdfview が必要のようだが、Windows 用はダウンロードできなかった。
そこで、簡単に手に入るUbuntu 用の hdfview を使うことにした。
Fall Creaters Update をWindows 10 にインストールすると、ストアからUbuntu をWindows 10 にインストールすることができる。
Ubuntu をインストールして、

sudo apt update
sudo apt upgrade

を行った。
sudo apt install hdfview
でhdfview をインストールした。
Neural_Network_Console_43_171124.png
Neural_Network_Console_44_171124.png

時間がかかったが、インストールできた。
Neural_Network_Console_46_171124.png

GUI が起動するので、設定を行う必要がある。
Windows 10 fall creators update のWindows Subsystem for Linuxを試してみた
Windows 10 fall creators update のWindows Subsystem for Linuxを試してみた3
を参考にしながらやっていく。

sudo apt-get install x11-apps
を実行した。
Neural_Network_Console_47_171124.png

vi .bashrc
で .bashrc を編集して、

export DISPLAY=:0.0

を追加した。
Neural_Network_Console_48_171124.png

source .bashrc
を実行して、.bashrc の内容を反映させた。
Neural_Network_Console_49_171124.png

日本語表示ができるように、次のコマンドを実行した。
sudo ln -s /mnt/c/Windows/Fonts /usr/share/fonts/WindowsFonts
sudo fc-cache -fv

Neural_Network_Console_50_171124.png

Xming を立ち上げてから、
hdfview
を実行した。
Neural_Network_Console_51_171124.png

GUI で hdfview が立ち上がった。
Neural_Network_Console_52_171124.png

File メニューから open を選んで、F:\NN_console\samples\sample_project\image_recognition\MNIST\LeNet.files\20170804_140639 フォルダの prameters.h5 を選択した。
Neural_Network_Console_53_171124.png

ネットワークの重みやバイアスを見ることができた。
Neural_Network_Console_54_171124.png

表示しているConvolution_2 のW をすべて選択して、Ctrl+C を押して、コピーし、LibreOffice のCalc を起動してCtrl+V をクリックするとコピーすることができた。
Neural_Network_Console_55_171124.png

これで、重みやバイアスをいろいろ加工することができそうだ。
  1. 2017年11月24日 05:31 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

カーブ、直線用白線間走行用畳み込みニューラルネットワーク1(データ)

白線追従走行用畳み込みニューラルネットワーク・システムの製作7(白線間を走行)”で、ミニ・ロボットカーが直線の白線を走行することができた。

次はカーブを曲がれるようにしたい。そこで、曲がってい角度が 23 度のカーブと 48 度のカーブを用意して、曲がれるかどうかを試してみた。(注:カーブを曲がる学習はまだしていません。直線を走る学習のみです)
23 度のカーブは曲がれる時もあるようだ。


カーブの種類によって、カーブの位置のよるミニ・ロボットカーのカメラから見た画像とその位置を示しておくことにする。

48 度のカーブ
ミニ・ロボットカーの位置、ミニ・ロボットカーから見た画像
curve_tracing_cnn_0_171122.jpgbmp_file0_171122.jpg

curve_tracing_cnn_1_171122.jpgbmp_file1_171122.jpg

curve_tracing_cnn_2_171122.jpgbmp_file2_171122.jpg

curve_tracing_cnn_3_171122.jpgbmp_file3_171122.jpg

curve_tracing_cnn_4_171122.jpgbmp_file4_171122.jpg

curve_tracing_cnn_5_171122.jpgbmp_file5_171122.jpg

curve_tracing_cnn_6_171122.jpgbmp_file6_171122.jpg

curve_tracing_cnn_7_171122.jpgbmp_file7_171122.jpg


23 度のカーブ
ミニ・ロボットカーの位置、ミニ・ロボットカーから見た画像
curve_tracing_cnn_8_171122.jpgbmp_file8_171122.jpg

curve_tracing_cnn_9_171122.jpgbmp_file9_171122.jpg

curve_tracing_cnn_10_171122.jpgbmp_file10_171122.jpg

curve_tracing_cnn_11_171122.jpgbmp_file11_171122.jpg

curve_tracing_cnn_12_171122.jpgbmp_file12_171122.jpg

curve_tracing_cnn_13_171122.jpgbmp_file13_171122.jpg

curve_tracing_cnn_14_171122.jpgbmp_file14_171122.jpg

curve_tracing_cnn_15_171122.jpgbmp_file15_171122.jpg

  1. 2017年11月22日 05:36 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

「RTLを語る会(14) ~FPGAの現実~」で発表してきました

RTLを語る会(14) ~FPGAの現実~」で「「ゼロから作るDeep Learning」の畳み込みニューラルネットワークのハードウェア化」という題で1時間発表してきました。

SlideShare でも「「ゼロから作るDeep learning」の畳み込みニューラルネットワークのハードウェア化」のスライドを公開しました。
「ゼロから作るDeep learning」という本を読んで、MNIST の手書き数字の認識用の畳み込みニューラルネットワークをVivado HLSを使ってFPGA に実装したよ。。。というお話です。そういえばMNIST の手書き数字とはどこにも書いてなかったかも?修正します。
修正しました。MNIST の手書き数字認識用畳み込みニューラルネットワークと書いておきました。

いろいろとオフレコの話が聞けて面白かったです。オフレコなので、ブログに書けませんけどね。。。
  1. 2017年09月25日 04:32 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワーク・システムの製作7(白線間を走行)

白線追従走行用畳み込みニューラルネットワーク・システムの製作6(実機で確認2)”の続き。

前回は、SDKで進む方向を表示するアプリケーションソフトを製作して、問題がないことを確かめた。今回は、ZYBO のUbuntu 14.04 上でアプリケーションソフトを作り、白線間を走行させる。

Zybot/wl_tracing_cnn ディレクトリを作成し、wl_tracing_cnn.cpp アプリケーションソフトを作成した。
wl_tracing_cnn ディレクトリには、dmar4resize_gray, resize_gray, straight_conv_nn2_axis2 のドライバを入れて、画像フレーム用のバッファ領域を確保するためにikwzm さんの udmabuf もコンパイル済みの状態で入っている。後、コンパイルするためのMakefile も作成した。
wlt_cnn_208_170922.png

make でコンパイルして wl_tracing_cnn を生成した。

ミニ・ロボットカーを白線間にセットして、udmabuf_insmod を実行してから、 wl_tracing_cnn を起動した。
白線間は走行したのだが、左右に振れてしまって真っ直ぐ走らない感じだ。例えば、左旋回して戻るときに白線間の真ん中あたりに車体がまっすぐになるように右に舵を切る必要がある。それを考えていなかったので左右に振れてしまっているのだと思う。
例えば、右旋回して戻るときに直進が無くて、すぐに左旋回になっているイメージだろうか?
動画を貼っておく。




現在の wl_tracing_cnn.cpp を貼っておく。

// wl_traceing_cnn.cpp
// 2017/09/18 by marsee
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

#include "xpwm.h"
#include "xdmar4resize_gray.h"
#include "xresize_gray.h"
#include "xstraight_conv_nn2_axis2.h"

#define CMA_START_ADDRESS 0x17800000
#define VIDEO_BUFFER_START_ADDRESS  0x18000000  // Limit 0x18800000, 800*600*4 = 2MBytes * 2

#define HORIZONTAL_PIXEL    800
#define ALL_CHAR_OF_1LINE   (HORIZONTAL_PIXEL/8)
#define VERTICAL_PIXEL      600
#define ALL_CHAR_OF_ROW     (VERTICAL_PIXEL/8)
#define ALL_DISP_ADDRESS    (HORIZONTAL_PIXEL*VERTICAL_PIXEL*4)
#define ALL_DISP_CHARACTOR  (HORIZONTAL_PIXEL*VERTICAL_PIXEL)

#define DEBUG
//#define MOTOR_OFF

void cam_i2c_init(volatile unsigned *mt9d111_axi_iic) {
    mt9d111_axi_iic[64] = 0x2// reset tx fifo ,address is 0x100, i2c_control_reg
    mt9d111_axi_iic[64] = 0x1// enable i2c
}

void cam_i2x_write_sync(void) {
    // unsigned c;

    // c = *cam_i2c_rx_fifo;
    // while ((c & 0x84) != 0x80)
        // c = *cam_i2c_rx_fifo; // No Bus Busy and TX_FIFO_Empty = 1
    usleep(1000);
}

void cam_i2c_write(volatile unsigned *mt9d111_axi_iic, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
    mt9d111_axi_iic[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    mt9d111_axi_iic[66] = write_addr;
    mt9d111_axi_iic[66] = (write_data >> 8)|0xff;           // first data
    mt9d111_axi_iic[66] = 0x200 | (write_data & 0xff);      // second data
    cam_i2x_write_sync();
}

// Motor
//
void motor_settings(XPwm *motorLp, XPwm *motorRp){
    XPwm_DisableAutoRestart(motorLp);
    while(!XPwm_IsIdle(motorLp)) ;
    XPwm_Start(motorLp);
    XPwm_EnableAutoRestart(motorLp);
    
    XPwm_DisableAutoRestart(motorRp);
    while(!XPwm_IsIdle(motorRp)) ;
    XPwm_Start(motorRp);
    XPwm_EnableAutoRestart(motorRp);
}

void Stopped_Zybot(XPwm *motorLp, XPwm *motorRp){
    XPwm_Set_sw_late_V(motorLp, 0);
    XPwm_Set_sw_late_V(motorRp, 0);
}


int main()
{
    int fd0, fd1, fd2, fd3, fd4, fd5, fd6, fd7, fd8, fd9, fd10;
    volatile unsigned *bmdc_axi_lites0, *bmdc_axi_lites1;
    volatile unsigned *dmaw4gabor_0;
    volatile unsigned *axis_switch_0, *axis_switch_1;
    volatile unsigned *mt9d111_inf_axis_0;
    volatile unsigned *mt9d111_axi_iic;
    volatile unsigned *axi_gpio_0;
    volatile unsigned *frame_buffer_bmdc;
    char  attr[1024];
    unsigned long  phys_addr;
    int i;
    XDmar4resize_gray xdmar;
    XResize_gray resg;
    XStraight_conv_nn2_axis2 stcnn;
    XPwm motorL, motorR;
    XPwm *motorLp, *motorRp;
    
    motorLp = &motorL;
    motorRp = &motorR;

    // Bitmap Display Controller 0 AXI4 Lite Slave (UIO6)
    fd6 = open("/dev/uio6", O_RDWR); // bitmap_display_controller 0 axi4 lite
    if (fd6 < 1){
        fprintf(stderr, "/dev/uio6 (bitmap_disp_cntrler_axi_master_0) open error\n");
        exit(-1);
    }
    bmdc_axi_lites0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd6, 0);
    if (!bmdc_axi_lites0){
        fprintf(stderr, "bmdc_axi_lites0 mmap error\n");
        exit(-1);
    }
    
    // Bitmap Display Controller 1 AXI4 Lite Slave (UIO7)
    fd7 = open("/dev/uio7", O_RDWR); // bitmap_display_controller axi4 lite
    if (fd7 < 1){
        fprintf(stderr, "/dev/uio7 (bitmap_disp_cntrler_axi_master_0) open error\n");
        exit(-1);
    }
    bmdc_axi_lites1 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd7, 0);
    if (!bmdc_axi_lites1){
        fprintf(stderr, "bmdc_axi_lites1 mmap error\n");
        exit(-1);
    }

    // dmaw4gabor_0 (UIO1)
    fd1 = open("/dev/uio1", O_RDWR); // dmaw4gabor_0 interface AXI4 Lite Slave
    if (fd1 < 1){
        fprintf(stderr, "/dev/uio1 (dmaw4gabor_0) open error\n");
        exit(-1);
    }
    dmaw4gabor_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
    if (!dmaw4gabor_0){
        fprintf(stderr, "dmaw4gabor_0 mmap error\n");
        exit(-1);
    }
    
    // mt9d111 i2c AXI4 Lite Slave (UIO0)
    fd0 = open("/dev/uio0", O_RDWR); // mt9d111 i2c AXI4 Lite Slave
    if (fd0 < 1){
        fprintf(stderr, "/dev/uio0 (mt9d111_axi_iic) open error\n");
        exit(-1);
    }
    mt9d111_axi_iic = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
    if (!mt9d111_axi_iic){
        fprintf(stderr, "mt9d111_axi_iic mmap error\n");
        exit(-1);
    }

    // mt9d111 inf axis AXI4 Lite Slave (UIO5)
    fd5 = open("/dev/uio5", O_RDWR); // mt9d111 inf axis AXI4 Lite Slave
    if (fd5 < 1){
        fprintf(stderr, "/dev/uio5 (mt9d111_inf_axis_0) open error\n");
        exit(-1);
    }
    mt9d111_inf_axis_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd5, 0);
    if (!mt9d111_inf_axis_0){
        fprintf(stderr, "mt9d111_inf_axis_0 mmap error\n");
        exit(-1);
    }

    // axis_switch_0 (UIO2)
    fd2 = open("/dev/uio2", O_RDWR); // axis_switch_0 interface AXI4 Lite Slave
    if (fd2 < 1){
        fprintf(stderr, "/dev/uio2 (axis_switch_0) open error\n");
        exit(-1);
    }
    axis_switch_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
    if (!axis_switch_0){
        fprintf(stderr, "axis_switch_0 mmap error\n");
        exit(-1);
    }
    
    // axis_switch_1 (UIO3)
    fd3 = open("/dev/uio3", O_RDWR); // axis_switch_1 interface AXI4 Lite Slave
    if (fd3 < 1){
        fprintf(stderr, "/dev/uio3 (axis_switch_1) open error\n");
        exit(-1);
    }
    axis_switch_1 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
    if (!axis_switch_1){
        fprintf(stderr, "axis_switch_1 mmap error\n");
        exit(-1);
    }
    
    // axi_gpio_0 (UIO8)
    fd8 = open("/dev/uio8", O_RDWR); // axi_gpio_0 interface AXI4 Lite Slave
    if (fd8 < 1){
        fprintf(stderr, "/dev/uio8 (axi_gpio_0) open error\n");
        exit(-1);
    }
    axi_gpio_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd8, 0);
    if (!axi_gpio_0){
        fprintf(stderr, "axi_gpio_8 mmap error\n");
        exit(-1);
    }
    
    // udmabuf0
    fd9 = open("/dev/udmabuf0", O_RDWR | O_SYNC); // frame_buffer, The chache is disabled. 
    if (fd9 == -1){
        fprintf(stderr, "/dev/udmabuf0 open error\n");
        exit(-1);
    }
    frame_buffer_bmdc = (volatile unsigned *)mmap(NULL, 5760000, PROT_READ|PROT_WRITE, MAP_SHARED, fd9, 0);
    if (!frame_buffer_bmdc){
        fprintf(stderr, "frame_buffer_bmdc mmap error\n");
        exit(-1);
    }

    // axis_switch_1, 1to2 ,Select M00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    axis_switch_1[16] = 0x0// 0x40 = 0
    axis_switch_1[17] = 0x80000000// 0x44 = 0x80000000, disable
    axis_switch_1[18] = 0x80000000// 0x48 = 0x80000000, disable
    axis_switch_1[19] = 0x80000000// 0x4C = 0x80000000, disable
    axis_switch_1[0] = 0x2// Comit registers
    
    // axis_switch_0, 2to1, Select S00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    axis_switch_0[16] = 0x0// 0x40 = 0;
    axis_switch_0[0] = 0x2// Comit registers
    
    // phys_addr of udmabuf0
    fd10 = open("/sys/devices/virtual/udmabuf/udmabuf0/phys_addr", O_RDONLY);
    if (fd10 == -1){
        fprintf(stderr, "/sys/devices/virtual/udmabuf/udmabuf0/phys_addr open error\n");
        exit(-1);
    }
    read(fd10, attr, 1024);
    sscanf(attr, "%lx", &phys_addr);  
    close(fd10);
    printf("phys_addr = %x\n", (int)phys_addr);
    
    // DMAW4Gabor Initialization sequence
    dmaw4gabor_0[6] = (unsigned int)phys_addr; // Data signal of frame_buffer0
    dmaw4gabor_0[8] = (unsigned int)phys_addr+ALL_DISP_ADDRESS; // Data signal of frame_buffer1
    dmaw4gabor_0[0] = 0x1// ap_start = 1
    dmaw4gabor_0[0] = 0x80// auto_restart = 1

    // bitmap display controller settings
    bmdc_axi_lites0[0] = (unsigned int)phys_addr; // Bitmap Display Controller 0 start
    bmdc_axi_lites1[0] = (unsigned int)phys_addr; // Bitmap Display Controller 1 start
    mt9d111_inf_axis_0[0] = (unsigned int)phys_addr; // Camera Interface start (Address is dummy)

    // CMOS Camera initialize, MT9D111
    cam_i2c_init(mt9d111_axi_iic);
    
    cam_i2c_write(mt9d111_axi_iic, 0xba, 0xf00x1);        // Changed regster map to IFP page 1
    cam_i2c_write(mt9d111_axi_iic, 0xba, 0x970x20);   // RGB Mode, RGB565

    mt9d111_inf_axis_0[1] = 0;

    // Initialization of xdmar4resize_gray, xresize_gray, xstraight_conv_nn2_axis2
    if(XDmar4resize_gray_Initialize(&xdmar, "dmar4resize_gray_0") != XST_SUCCESS){
        fprintf(stderr, "dmar4resize_gray_0 open error\n");
        exit(-1);
    }
    if(XResize_gray_Initialize(&resg, "resize_gray_0") != XST_SUCCESS){
        fprintf(stderr, "resize_gray_0 open error\n");
        exit(-1);
    }
    if(XStraight_conv_nn2_axis2_Initialize(&stcnn, "straight_conv_nn2_axis2_0") != XST_SUCCESS){
        fprintf(stderr, "straight_conv_nn2_axis2 open error\n");
        exit(-1);
    }

    XDmar4resize_gray_Set_frame_buffer0(&xdmar ,(unsigned int)phys_addr);
    XDmar4resize_gray_Set_frame_buffer1(&xdmar ,(unsigned int)phys_addr+ALL_DISP_ADDRESS);
    XDmar4resize_gray_Start(&xdmar);
    XDmar4resize_gray_EnableAutoRestart(&xdmar);

    XResize_gray_Start(&resg);
    XResize_gray_EnableAutoRestart(&resg);

    XStraight_conv_nn2_axis2_Start(&stcnn);
    XStraight_conv_nn2_axis2_EnableAutoRestart(&stcnn);

    // Initialization of motor
    if (XPwm_Initialize(motorLp, "pwm_0") != XST_SUCCESS){
        fprintf(stderr,"pwm_0 (Left) open error\n");
        exit(-1);
    }
    if (XPwm_Initialize(motorRp, "pwm_1") != XST_SUCCESS){
        fprintf(stderr,"pwm_1 (Right) open error\n");
        exit(-1);
    }
    // The Motors is rotated in the forward direction.
    XPwm_Set_sw_late_V(motorLp, 0);
    XPwm_Set_dir_V(motorLp, 1);

    XPwm_Set_sw_late_V(motorRp, 0);
    XPwm_Set_dir_V(motorRp, 0);

    motor_settings(motorLp, motorRp);

    // main loop
    printf("White line Tracking start. \n");
    while(1){
        usleep(10000); // 10 ms Wait

        while(!XStraight_conv_nn2_axis2_Get_outs_V_vld(&stcnn)) ;
        switch((int)XStraight_conv_nn2_axis2_Get_outs_V(&stcnn)){
            case 0 : // left turn
#ifndef MOTOR_OFF
                XPwm_Set_sw_late_V(&motorL, 15);
                XPwm_Set_sw_late_V(&motorR, 25);
#endif
#ifdef DEBUG
                printf("Left turn\n"); fflush(stdout);
#endif
                break;
            case 1 : // straight
#ifndef MOTOR_OFF
                XPwm_Set_sw_late_V(&motorL, 22);
                XPwm_Set_sw_late_V(&motorR, 22);
#endif
#ifdef DEBUG
                printf("Go straight\n"); fflush(stdout);
#endif
                break;
            default : // 2, right turn
#ifndef MOTOR_OFF
                XPwm_Set_sw_late_V(&motorL, 25);
                XPwm_Set_sw_late_V(&motorR, 15);
#endif
#ifdef DEBUG
                printf("Right turn\n"); fflush(stdout);
#endif
        }
    }


    munmap((void *)bmdc_axi_lites0, 0x10000);
    munmap((void *)bmdc_axi_lites1, 0x10000);
    munmap((void *)dmaw4gabor_0, 0x10000);
    munmap((void *)mt9d111_inf_axis_0, 0x10000);
    munmap((void *)mt9d111_axi_iic, 0x10000);
    munmap((void *)axis_switch_0, 0x10000);
    munmap((void *)axis_switch_1, 0x10000);
    munmap((void *)axi_gpio_0, 0x10000);
    munmap((void *)frame_buffer_bmdc, 576000);
    
    close(fd0);
    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);
    close(fd5);
    close(fd6);
    close(fd7);
    close(fd8);
    close(fd9);
    
    return(0);
}


Makefile を貼っておく。

# Makefile(wl_traceing_cnn)
# Referred to http://www.ie.u-ryukyu.ac.jp/~e085739/c.makefile.tuts.html

PROGRAM = wl_traceing_cnn
OBJS = wl_traceing_cnn.o xpwm_linux.o xpwm.o xdmar4resize_gray_linux.o xdmar4resize_gray.o xresize_gray_linux.o xresize_gray.o xstraight_conv_nn2_axis2_linux.o xstraight_conv_nn2_axis2.o

CC = gcc
CFLAGS = -Wall -O2

.SUFFIXES: .c .o

.PHONY: all

all: wl_traceing_cnn

wl_traceing_cnn: $(OBJS)
    $(CC) -Wall -o $@ $(OBJS)
    
.c.o:
    $(CC) $(CFLAGS) -c $<

    
.PHONY: clean
clean:
    $(RM) $(PROGRAM) $(OBJS)

  1. 2017年09月22日 04:19 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワーク・システムの製作6(実機で確認2)

白線追従走行用畳み込みニューラルネットワーク・システムの製作5(実機で確認)”の続き。

前回は、白線追従走行用畳み込みニューラルネットワークが動作しているかどうか確認するために各出力の値を出力するように、Vivado HLS プロジェクトの straight_conv_nn2_axis3 を変更した。今回は、Vivado HLS プロジェクトの straight_conv_nn2_axis3 を変更したのだが、関数名は straight_conv_nn2_axis2 にしてあるので、今までのstraight_conv_nn2_axis2 IP と入れ替えることができるので、入れ替えて、ZYBO_0_172_8 フォルダのVivado プロジェクトでビットストリームの生成を行って、実機で試してみよう。

Vivado プロジェクトで論理合成、インプリメント、ビットストリームの生成を行った。結果を示す。
wlt_cnn_202_170919.png

問題ない。

ハードウェアをエクスポートして、SDK を立ち上げ、wl_tracing_cnn アプリケーションソフトを変更した。
wlt_cnn_203_170919.png

実機で確認すると、各出力の値も変化が無い。これはおかしい。
wl_tracing_cnn アプリケーションソフトを良く見直してみると、dmar4resize_gray のframe_buffer0 とframe_buffer1 にアドレスを入れていなかった。。。orz

dmar4resize_gray のframe_buffer0 とframe_buffer1 にアドレスをセットすると変化した。
wlt_cnn_204_170919.png

これで良さそう。

白線ボードに持っていってチェックした。
最初の状態では、出力は 0 で左旋回となった。
wlt_cnn_205_170921.jpg

2番目の状態では、出力は 1 で直進となった。
wlt_cnn_206_170921.jpg

3番目の状態では、出力は 2 で右旋回となった。
wlt_cnn_207_170921.jpg

大体良さそうだ。
後は、Linux 版の白線追従走行アプリケーションソフトを作って、ミニ・ロボットカーを走らせたい。

ベアメタル・アプリケーションの wl_tracing_cnn.c を貼っておく。

/* * wl_tracing_cnn.c * *  Created on: 2017/09/18 *      Author: Masaaki */
// ベアメタル・アプリケーションでは、CNN がきちんと動作しているを確認するのみとする
// 2017/09/19 : 直進、左旋回、右旋回の各出力の値を表示するように変更
//

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "xil_io.h"
#include "xparameters.h"
#include "sleep.h"

#include "xdmaw4gabor.h"
#include "xdmar4resize_gray.h"
#include "xresize_gray.h"
#include "xstraight_conv_nn2_axis2.h"

#define NUMBER_OF_WRITE_FRAMES    3 // Note: If not at least 3 or more, the image is not displayed in succession.

#define HORIZONTAL_PIXELS    800
#define VERTICAL_LINES        600
#define PIXEL_NUM_OF_BYTES    4

#define FRAME_BUFFER_ADDRESS 0x10000000
#define ALL_DISP_ADDRESS    (HORIZONTAL_PIXELS*VERTICAL_LINES*PIXEL_NUM_OF_BYTES)

void cam_i2c_init(volatile unsigned *mt9d111_i2c_axi_lites) {
    mt9d111_i2c_axi_lites[64] = 0x2// reset tx fifo ,address is 0x100, i2c_control_reg
    mt9d111_i2c_axi_lites[64] = 0x1// enable i2c
}

void cam_i2x_write_sync(void) {
    // unsigned c;

    // c = *cam_i2c_rx_fifo;
    // while ((c & 0x84) != 0x80)
        // c = *cam_i2c_rx_fifo; // No Bus Busy and TX_FIFO_Empty = 1
    usleep(1000);
}

void cam_i2c_write(volatile unsigned *mt9d111_i2c_axi_lites, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
    mt9d111_i2c_axi_lites[66] = 0x100 | (device_addr & 0xfe);   // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    mt9d111_i2c_axi_lites[66] = write_addr;
    mt9d111_i2c_axi_lites[66] = (write_data >> 8)|0xff;         // first data
    mt9d111_i2c_axi_lites[66] = 0x200 | (write_data & 0xff);        // second data
    cam_i2x_write_sync();
}

int main(){
    XDmar4resize_gray xdmar;
    XResize_gray resg;
    XStraight_conv_nn2_axis2 stcnn;
    XDmaw4gabor xdma4g;
    int i;
    uint32_t res;
    int result[4];

    // axis_switch_1, 1to2 ,Select M00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x40), 0x0);
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x44), 0x80000000); // disable
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x48), 0x80000000); // disable
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR), 0x2); // Commit registers

    // axis_switch_0, 2to1, Select S00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR+0x40), 0x0);
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR), 0x2); // Commit registers

    XDmaw4gabor_Initialize(&xdma4g, 0);
    XDmaw4gabor_Set_frame_buffer0(&xdma4g, FRAME_BUFFER_ADDRESS);
    XDmaw4gabor_Set_frame_buffer1(&xdma4g, FRAME_BUFFER_ADDRESS+ALL_DISP_ADDRESS);
    XDmaw4gabor_Start(&xdma4g);
    XDmaw4gabor_EnableAutoRestart(&xdma4g);

    // mt9d111_inf_axis_0, axi_iic_0, bitmap_disp_cntrler_axi_master_0
    volatile unsigned int *bmdc0_axi_lites;
    volatile unsigned int *bmdc1_axi_lites;
    volatile unsigned int *mt9d111_axi_lites;
    volatile unsigned int *mt9d111_i2c_axi_lites;

    bmdc0_axi_lites = (volatile unsigned *)XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_0_BASEADDR;
    bmdc1_axi_lites = (volatile unsigned *)XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_1_BASEADDR;
    mt9d111_axi_lites = (volatile unsigned *)XPAR_CAMERA_INTERFACE_MT9D111_INF_AXIS_0_BASEADDR;
    mt9d111_i2c_axi_lites = (volatile unsigned *)XPAR_CAMERA_INTERFACE_AXI_IIC_0_BASEADDR;

    bmdc0_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Bitmap Display Controller 0 start
    bmdc1_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Bitmap Display Controller 1 start
    mt9d111_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)

    // CMOS Camera initialize, MT9D111
    cam_i2c_init(mt9d111_i2c_axi_lites);

    cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0xf00x1);      // Changed regster map to IFP page 1
    cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0x970x20);        // RGB Mode, RGB565

    mt9d111_axi_lites[1] = 0// One_shot_mode is disabled

    XDmar4resize_gray_Initialize(&xdmar, 0);
    XResize_gray_Initialize(&resg, 0);
    XStraight_conv_nn2_axis2_Initialize(&stcnn, 0);

    XDmar4resize_gray_Set_frame_buffer0(&xdmar ,FRAME_BUFFER_ADDRESS);
    XDmar4resize_gray_Set_frame_buffer1(&xdmar ,FRAME_BUFFER_ADDRESS+ALL_DISP_ADDRESS);
    XDmar4resize_gray_Start(&xdmar);
    XDmar4resize_gray_EnableAutoRestart(&xdmar);

    XResize_gray_Start(&resg);
    XResize_gray_EnableAutoRestart(&resg);

    XStraight_conv_nn2_axis2_Start(&stcnn);
    XStraight_conv_nn2_axis2_EnableAutoRestart(&stcnn);

    while(1){
        sleep(1);

        while(!XStraight_conv_nn2_axis2_Get_outs_V_vld(&stcnn)) ;
        printf("out = %d\n", (int)XStraight_conv_nn2_axis2_Get_outs_V(&stcnn));
        for(i=0; i<2; i++){
            XStraight_conv_nn2_axis2_Read_dot2_V_Words(&stcnn, i, &res, 1);
            result[i*2] = res & 0xffff;
            if(result[i*2] & 0x8000// minus
                result[i*2] = 0xffff0000 | result[i*2]; // Sign extension

            result[i*2+1] = (res & 0xffff0000) >> 16;
            if(result[i*2+1] & 0x8000// minus
                result[i*2+1] = 0xffff0000 | result[i*2+1]; // Sign extension
        }
        for(i=0; i<3; i++)
            printf("result[%d] = %x ", i , result[i]);
        printf("\n");
    }

    return(0);
}

  1. 2017年09月21日 05:14 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワーク・システムの製作5(実機で確認)

白線追従走行用畳み込みニューラルネットワーク・システムの製作4(BOOT.binとデバイスツリー)”の続き。

前回は、BOOT.bin と devicetree.dtb を作成して、ZYBO でUbuntu を立ち上げ、デバイスが見えるかどうか?を確かめた。今回は、SDKを使用したベアメタル・アプリケーションで、実際に白線追従走行用畳み込みニューラルネットワークが動作するかどうか?を確かめる。

SDK で wl_tracing_cnn アプリケーション・プロジェクトを作成し、wl_tarcing_cnn.c を作成した。
wlt_cnn_196_170919.png

白線はないけど、何か結果が出ると思い、部屋の中の画像でやってみることにした。結果は、手とかをカメラの前で振っても結果は変わらずに 1 つまり直進だった。
wlt_cnn_197_170919.png

ちょっとこれでは、最大値の出力番号だけ表示しているため、値が変わっているのか?変わっていないのかが分からない?
そこで、straight_conv_nn2_axis2 のVivado HLS プロジェクトを少し変更することにした。これは、白線追従走行用畳み込みニューラルネットワークが入っているIP だ。
straight_conv_nn2_axis3 とプロジェクトを新規作成して、ファイル名もstraight_conv_nn2_axis3.cpp, straight_conv_nn2_axis3_tb.cpp と変更したが、関数の名前だけはstraight_conv_nn2_axis2 にしておいた。こうすると、IP にしたときの名前が同じなので、既存のstraight_conv_nn2_axis2 IP と取り換えることができる。
3つの出力を出力できるように変更した。
wlt_cnn_198_170919.png

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

Latency は前よりも 4 クロック増えている。
リソース使用量はBRAM_18K は増えているが、FF と LUT は減っている。
AXI4 Lite Slave のアドレスを示す。

//------------------------Address Info-------------------
// 0x00 : Control signals
//        bit 0  - ap_start (Read/Write/COH)
//        bit 1  - ap_done (Read/COR)
//        bit 2  - ap_idle (Read)
//        bit 3  - ap_ready (Read)
//        bit 7  - auto_restart (Read/Write)
//        others - reserved
// 0x04 : Global Interrupt Enable Register
//        bit 0  - Global Interrupt Enable (Read/Write)
//        others - reserved
// 0x08 : IP Interrupt Enable Register (Read/Write)
//        bit 0  - Channel 0 (ap_done)
//        bit 1  - Channel 1 (ap_ready)
//        others - reserved
// 0x0c : IP Interrupt Status Register (Read/TOW)
//        bit 0  - Channel 0 (ap_done)
//        bit 1  - Channel 1 (ap_ready)
//        others - reserved
// 0x10 : Data signal of ap_return
//        bit 31~0 - ap_return[31:0] (Read)
// 0x18 : Data signal of outs_V
//        bit 1~0 - outs_V[1:0] (Read)
//        others  - reserved
// 0x1c : Control signal of outs_V
//        bit 0  - outs_V_ap_vld (Read/COR)
//        others - reserved
// 0x20 ~
// 0x27 : Memory 'dot2_V' (3 * 16b)
//        Word n : bit [15: 0] - dot2_V[2n]
//                 bit [31:16] - dot2_V[2n+1]
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)


dot2_V が増えているのが分かった。

次に、Export RTL を行った。こちらも結果を示す。
wlt_cnn_201_170919.png

こちらも問題ないようだ。これでIP となった。

straight_conv_nn2_axis3.cpp を貼っておく。

// straight_conv_nn2_axis3.cpp
// 2017/09/09 by marsee
// 畳み込み層のカーネル数 2
// AXI4 Stream入力 番号出力
// 2017/09/18 : dot2[3]の出力も追加
//

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

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

#define REDUSED_ROW        45
#define REDUSED_COULMN    60
#define NUM_OF_KERNELS    2
#define COULMN_PIXELS    56
#define ROW_PIXELS        10
#define ALL_PIXELS        560
#define NUM_OF_OUTPUT    3

int max_ap_fixed(ap_fixed<167, AP_TRN_ZERO, AP_SAT> out[NUM_OF_OUTPUT], ap_uint<2> &out_num);

int straight_conv_nn2_axis2(hls::stream<ap_axiu<32,1,1,1> >& ins, ap_uint<2> &outs,
        ap_fixed<167, AP_TRN_ZERO, AP_SAT> dot2[NUM_OF_OUTPUT]){
#pragma HLS INTERFACE s_axilite port=dot2
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE s_axilite port=outs
#pragma HLS INTERFACE axis register both port=ins
    ap_ufixed<80, AP_TRN_ZERO, AP_SAT> buf[ROW_PIXELS][COULMN_PIXELS];
    ap_fixed<136, AP_TRN_ZERO, AP_SAT> conv_out[NUM_OF_KERNELS][ROW_PIXELS-4][COULMN_PIXELS-4];
    ap_fixed<136, AP_TRN_ZERO, AP_SAT> pool_out[NUM_OF_KERNELS][(ROW_PIXELS-4)/2][(COULMN_PIXELS-4)/2];
    ap_fixed<167, AP_TRN_ZERO, AP_SAT> dot1[100];
    ap_axiu<32,1,1,1> pix;

    do {
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
    // user が 1になった時にフレームがスタートする
        ins >> pix;
    } while(pix.user == 0);

    // 10 x 56 に整形
    buf_copy1: for(int i=0; i<REDUSED_ROW; i++){
        buf_copy2: for(int j=0; j<REDUSED_COULMN; j++){
            if (!(i==0 && j==0))    // 最初の入力はすでに入力されている
                ins >> pix;    // AXI4-Stream からの入力

            if((i>=33 && i<33+ROW_PIXELS) && (j>=2 && j<2+COULMN_PIXELS)){
                buf[i-33][j-2] = (ap_ufixed<80, AP_TRN_ZERO, AP_SAT>)((ap_ufixed<168, AP_TRN_ZERO, AP_SAT>)(pix.data & 0xff) / 256);
            }
        }
    }

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

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

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

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

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

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

    max_ap_fixed(dot2, outs);

    return(0);
}

int max_ap_fixed(ap_fixed<167, AP_TRN_ZERO, AP_SAT> out[NUM_OF_OUTPUT], ap_uint<2> &out_num){
    int max_id;
    ap_fixed<167, AP_TRN_ZERO, AP_SAT> max;

    for(int i=0; i<NUM_OF_OUTPUT; i++){
        if(i == 0){
            max = out[0];
            max_id = 0;
        }else if(out[i]>max){
            max = out[i];
            max_id = i;
        }
    }
    out_num = (ap_uint<2>)max_id;

    return(0);
}


straight_conv_nn2_axis3_tb.cpp を貼っておく。

// straight_conv_nn2_axis3_tb.cpp
// 2017/09/09 by marsee
//
// 2017/09/18 : straight_conv_nn2_axis3.cpp に dot2[3]の出力も追加
//

#include <iostream>
#include "hls_opencv.h"
#include "ap_axi_sdata.h"
#include "hls_video.h"

#define MAX_HEIGHT    600
#define MAX_WIDTH    800

typedef hls::stream<ap_axiu<32,1,1,1> > AXI_STREAM;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC1> GRAY_IMAGE;

using namespace cv;

#define NUM_OF_OUTPUT    3

#define MAX_LOOP_COUNT    11
//#define MAX_LOOP_COUNT    1    // for C/RTL Co-Simulation

#define STRAIGHT_IMAGE_NAME        "straight"
#define LEFT_TURN_IMAGE_NAME    "left_turn"
#define RIGHT_TURN_IMAGE_NAME    "right_turn"

int straight_conv_nn2_axis2(hls::stream<ap_axiu<32,1,1,1> >& ins, ap_uint<2> &outs,
        ap_fixed<167, AP_TRN_ZERO, AP_SAT> dot2[NUM_OF_OUTPUT]);
int resize_gray(AXI_STREAM& ins, AXI_STREAM& outs);
int main_output_loop(char *buf);

int main () {
    char buf[200];

    sprintf(buf, "%s", STRAIGHT_IMAGE_NAME);
    main_output_loop(buf);

    sprintf(buf, "%s", LEFT_TURN_IMAGE_NAME);
    main_output_loop(buf);

    sprintf(buf, "%s", RIGHT_TURN_IMAGE_NAME);
    main_output_loop(buf);

    return(0);
}

int main_output_loop(char *buf){
    char bmp_file_name[200];
    ap_uint<2> outs;
    AXI_STREAM src_axi, dst_axi;
    Mat src;
    ap_fixed<167, AP_TRN_ZERO, AP_SAT> dot2[NUM_OF_OUTPUT];

    for(int i=0; i<MAX_LOOP_COUNT; i++){
        sprintf(bmp_file_name, "%s%d.bmp", buf, i);

        // OpenCV で 画像を読み込む
        src = imread(bmp_file_name);

        // BGR から RGBへ変換
        Mat src_rgb;
        cvtColor(src, src_rgb, CV_BGR2RGB);

        // Mat フォーマットから AXI4 Stream へ変換
        cvMat2AXIvideo(src_rgb, src_axi);

        // resize_gray() 関数をコール
        resize_gray(src_axi, dst_axi);

        straight_conv_nn2_axis2(dst_axi, outs, dot2);

        printf("*%s\n", bmp_file_name);
        printf("outs = %d\n", (int)outs);
        for(int i=0; i<NUM_OF_OUTPUT; i++)
            printf("dot2[%d] = %f ", i, (float)dot2[i]);
        printf("\n");
    }

    return(0);
}

int resize_gray(AXI_STREAM& ins, AXI_STREAM& outs){

    RGB_IMAGE org_img(600800);
    GRAY_IMAGE org_img_g(600800);
    GRAY_IMAGE resize_img_g(4560);
    RGB_IMAGE resize_img(4560);

    hls::AXIvideo2Mat(ins, org_img);
    hls::CvtColor<HLS_RGB2GRAY>(org_img, org_img_g);
    hls::Resize(org_img_g, resize_img_g);
    hls::CvtColor<HLS_GRAY2RGB>(resize_img_g, resize_img);
    hls::Mat2AXIvideo(resize_img, outs);

    return(0);
}


  1. 2017年09月20日 05:12 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワーク・システムの製作4(BOOT.binとデバイスツリー)

白線追従走行用畳み込みニューラルネットワーク・システムの製作3(SDK)”の続き。

前回は、SDKでアプリケーションソフトを作成してカメラ画像が表示できることが確認できた。今回は、SDK でFSBL を作成してから、BOOT.bin を作成した。そして、デバイスツリーのソースをUbuntu 上でコンパイルして devicetree.dtb を作成し、ZYBO のMicro SD カードに書き込んで、/sys/devices/amba.0 以下のディレクトリを確認した。

最初に、SDK のFile メニューからNew -> Application Project を選択して、FSBL アプリケーション・プロジェクトを作成した。
wlt_cnn_186_170917.png

Next ボタンをクリックして、Zynq FSBL を選択してFinish ボタンをクリックする。
wlt_cnn_187_170917.png

FSBL とFSBL_bsp が作成された。
wlt_cnn_188_170917.png

FSBL アプリケーション・プロジェクトで右クリックし、右クリックメニューから、Create Boot Image を選択する。
Create Boot Image ダイアログで、u-boot.elf を追加して、Create Image ボタンをクリックする。
wlt_cnn_189_170917.png

BOOT.bin が生成された。
wlt_cnn_190_170917.png

次に、Ubuntu でZYBO用のzynq-zybo.dts を編集して、dmar4resize_gray, resize_gray, straight_conv_nn2_axis2 のエントリを追加した。
wlt_cnn_191_170917.png

dtc -I dts -O dtb -o devicetree.dtb zynq-zybo.dts
コマンドでコンパイルして、devicetree.dtb を生成した。
wlt_cnn_192_170917.png

ZYBO のMicro SD カードにBOOT.bin とdevicetree.dtb をコピー&ペーストした。
wlt_cnn_193_170917.png

Micro SD カードをZYBO に挿入して、電源ON でブートした。
/sys/devices/amba.0 を見ると、デバイスが表示された。
wlt_cnn_194_170917.png

dmar4resize_gray, resize_gray, straight_conv_nn2_axis2 も入っていた。
uio の番号を表示した。やはり、zynq-zybo.dts に書いてある順番に番号が振られていく。
wlt_cnn_195_170917.png

zynq-zybo.dts を貼っておく。

/*
 * Device Tree for Zybo board
 * Partially generated by Device Tree Generator 1.1
 *
 * (C) Copyright 2007-2013 Xilinx, Inc.
 * (C) Copyright 2007-2013 Michal Simek
 * (C) Copyright 2007-2012 PetaLogix Qld Pty Ltd
 * (C) Copyright 2014 Digilent, Inc. 
 *
 * Michal SIMEK <monstr@monstr.eu>
 * Tinghui Wang <steven.wang@digilentinc.com> 
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 *
 */


/dts-v1/;
/ {
    #address-cells = <1>;
    #size-cells = <1>;
    compatible = "xlnx,zynq-7000";
    model = "Xilinx Zynq";
    aliases {
        ethernet0 = &ps7_ethernet_0;
        serial0 = &ps7_uart_1;

        spi0 = &ps7_qspi_0;
    } ;
    chosen {
/*        bootargs = "console=ttyPS0,115200 root=/dev/ram rw earlyprintk"; */
        bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=1 coherent_pool=16M";
        linux,stdout-path = "/amba@0/serial@e0001000";
    } ;
    cpus {
        #address-cells = <1>;
        #size-cells = <0>;
        ps7_cortexa9_0: cpu@0 {
            bus-handle = <&ps7_axi_interconnect_0>;
            clock-latency = <1000>;
            clocks = <&clkc 3>;
            compatible = "arm,cortex-a9";
            device_type = "cpu";
            interrupt-handle = <&ps7_scugic_0>;
            /* operating-points = <666667 1000000 333334 1000000 >; */
            operating-points = <650000 1000000 >;
            reg = <0x0>;
        } ;
        ps7_cortexa9_1: cpu@1 {
            bus-handle = <&ps7_axi_interconnect_0>;
            clocks = <&clkc 3>;
            compatible = "arm,cortex-a9";
            device_type = "cpu";
            interrupt-handle = <&ps7_scugic_0>;
            reg = <0x1>;
        } ;
    } ;
    pmu {
        compatible = "arm,cortex-a9-pmu";
        interrupt-parent = <&ps7_scugic_0>;
        interrupts = <0 5 4>, <0 6 4>;
        reg = <0xf8891000 0x1000>, <0xf8893000 0x1000>;
        reg-names = "cpu0""cpu1";
    } ;
    ps7_ddr_0: memory@0 {
        device_type = "memory";
        reg = <0x0 0x20000000>;
    } ;
    ps7_axi_interconnect_0: amba@0 {
        #address-cells = <1>;
        #size-cells = <1>;
        compatible = "xlnx,ps7-axi-interconnect-1.00.a""simple-bus";
        ranges ;
        ps7_afi_0: ps7-afi@f8008000 {
            compatible = "xlnx,ps7-afi-1.00.a";
            reg = <0xf8008000 0x1000>;
        } ;
        ps7_afi_1: ps7-afi@f8009000 {
            compatible = "xlnx,ps7-afi-1.00.a";
            reg = <0xf8009000 0x1000>;
        } ;
        ps7_afi_2: ps7-afi@f800a000 {
            compatible = "xlnx,ps7-afi-1.00.a";
            reg = <0xf800a000 0x1000>;
        } ;
        ps7_afi_3: ps7-afi@f800b000 {
            compatible = "xlnx,ps7-afi-1.00.a";
            reg = <0xf800b000 0x1000>;
        } ;
        ps7_ddrc_0: ps7-ddrc@f8006000 {
            compatible = "xlnx,zynq-ddrc-1.0";
            reg = <0xf8006000 0x1000>;
            xlnx,has-ecc = <0x0>;
        } ;
        ps7_dev_cfg_0: ps7-dev-cfg@f8007000 {
            clock-names = "ref_clk""fclk0""fclk1""fclk2""fclk3";
            clocks = <&clkc 12>, <&clkc 15>, <&clkc 16>, <&clkc 17>, <&clkc 18>;
            compatible = "xlnx,zynq-devcfg-1.0";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 8 4>;
            reg = <0xf8007000 0x100>;
        } ;
        ps7_dma_s: ps7-dma@f8003000 {
            #dma-cells = <1>;
            #dma-channels = <8>;
            #dma-requests = <4>;
            clock-names = "apb_pclk";
            clocks = <&clkc 27>;
            compatible = "arm,primecell""arm,pl330";
            interrupt-names = "abort""dma0""dma1""dma2""dma3",
                "dma4""dma5""dma6""dma7";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 13 4>, <0 14 4>, <0 15 4>, <0 16 4>, <0 17 4>, <0 40 4>, <0 41 4>, <0 42 4>, <0 43 4>;
            reg = <0xf8003000 0x1000>;
        } ;
        ps7_ethernet_0: ps7-ethernet@e000b000 {
            #address-cells = <1>;
            #size-cells = <0>;
            clock-names = "ref_clk""aper_clk";
            clocks = <&clkc 13>, <&clkc 30>;
            compatible = "xlnx,ps7-ethernet-1.00.a";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 22 4>;
            phy-handle = <&phy0>;
            phy-mode = "rgmii-id";
            reg = <0xe000b000 0x1000>;
            xlnx,eth-mode = <0x1>;
            xlnx,has-mdio = <0x1>;
            xlnx,ptp-enet-clock = <108333336>;
            mdio {
                #address-cells = <1>;
                #size-cells = <0>;
                phy0: phy@1 {
                    compatible = "realtek,RTL8211E";
                    device_type = "ethernet-phy";
                    reg = <1>;
                } ;
            } ;
        } ;
        ps7_globaltimer_0: ps7-globaltimer@f8f00200 {
            clocks = <&clkc 4>;
            compatible = "arm,cortex-a9-global-timer";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <1 11 0x301>;
            reg = <0xf8f00200 0x100>;
        } ;
        ps7_gpio_0: ps7-gpio@e000a000 {
            #gpio-cells = <2>;
            clocks = <&clkc 42>;
            compatible = "xlnx,zynq-gpio-1.0";
            emio-gpio-width = <64>;
            gpio-controller ;
            gpio-mask-high = <0xc0000>;
            gpio-mask-low = <0xfe81>;
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 20 4>;
            reg = <0xe000a000 0x1000>;
        } ;
        ps7_iop_bus_config_0: ps7-iop-bus-config@e0200000 {
            compatible = "xlnx,ps7-iop-bus-config-1.00.a";
            reg = <0xe0200000 0x1000>;
        } ;
        ps7_ocmc_0: ps7-ocmc@f800c000 {
            compatible = "xlnx,zynq-ocmc-1.0";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 3 4>;
            reg = <0xf800c000 0x1000>;
        } ;
        ps7_pl310_0: ps7-pl310@f8f02000 {
            arm,data-latency = <3 2 2>;
            arm,tag-latency = <2 2 2>;
            cache-level = <2>;
            cache-unified ;
            compatible = "arm,pl310-cache";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 2 4>;
            reg = <0xf8f02000 0x1000>;
        } ;
        ps7_qspi_0: ps7-qspi@e000d000 {
            clock-names = "ref_clk""pclk";
            clocks = <&clkc 10>, <&clkc 43>;
            compatible = "xlnx,zynq-qspi-1.0";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 19 4>;
            is-dual = <0>;
            num-cs = <1>;
            reg = <0xe000d000 0x1000>;
            xlnx,fb-clk = <0x1>;
            xlnx,qspi-mode = <0x0>;
            #address-cells = <1>;
            #size-cells = <0>;
            flash@0 {
                compatible = "n25q128";
                reg = <0x0>;
                spi-tx-bus-width = <1>;
                spi-rx-bus-width = <4>;
                spi-max-frequency = <50000000>;
                #address-cells = <1>;
                #size-cells = <1>;
                partition@qspi-fsbl-uboot {
                    label = "qspi-fsbl-uboot";
                    reg = <0x0 0x400000>;
                };
                partition@qspi-linux {
                    label = "qspi-linux";
                    reg = <0x400000 0x500000>;
                };
                partition@qspi-device-tree {
                    label = "qspi-device-tree";
                    reg = <0x900000 0x20000>;
                };
                partition@qspi-user {
                    label = "qspi-user";
                    reg = <0x920000 0x6E0000>;
                };
            };

        } ;
        ps7_qspi_linear_0: ps7-qspi-linear@fc000000 {
            clock-names = "ref_clk""aper_clk";
            clocks = <&clkc 10>, <&clkc 43>;
            compatible = "xlnx,ps7-qspi-linear-1.00.a";
            reg = <0xfc000000 0x1000000>;
        } ;
        ps7_scugic_0: ps7-scugic@f8f01000 {
            #address-cells = <2>;
            #interrupt-cells = <3>;
            #size-cells = <1>;
            compatible = "arm,cortex-a9-gic""arm,gic";
            interrupt-controller ;
            num_cpus = <2>;
            num_interrupts = <96>;
            reg = <0xf8f01000 0x1000>, <0xf8f00100 0x100>;
        } ;
        ps7_scutimer_0: ps7-scutimer@f8f00600 {
            clocks = <&clkc 4>;
            compatible = "arm,cortex-a9-twd-timer";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <1 13 0x301>;
            reg = <0xf8f00600 0x20>;
        } ;
        ps7_scuwdt_0: ps7-scuwdt@f8f00620 {
            clocks = <&clkc 4>;
            compatible = "xlnx,ps7-scuwdt-1.00.a";
            device_type = "watchdog";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <1 14 0x301>;
            reg = <0xf8f00620 0xe0>;
        } ;
        ps7_sd_0: ps7-sdio@e0100000 {
            clock-frequency = <50000000>;
            clock-names = "clk_xin""clk_ahb";
            clocks = <&clkc 21>, <&clkc 32>;
            compatible = "arasan,sdhci-8.9a";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 24 4>;
            reg = <0xe0100000 0x1000>;
            xlnx,has-cd = <0x1>;
            xlnx,has-power = <0x0>;
            xlnx,has-wp = <0x1>;
        } ;
        ps7_slcr_0: ps7-slcr@f8000000 {
            #address-cells = <1>;
            #size-cells = <1>;
            compatible = "xlnx,zynq-slcr""syscon";
            ranges ;
            reg = <0xf8000000 0x1000>;
            clkc: clkc@100 {
                #clock-cells = <1>;
                clock-output-names = "armpll""ddrpll""iopll""cpu_6or4x""cpu_3or2x",
                    "cpu_2x""cpu_1x""ddr2x""ddr3x""dci",
                    "lqspi""smc""pcap""gem0""gem1",
                    "fclk0""fclk1""fclk2""fclk3""can0",
                    "can1""sdio0""sdio1""uart0""uart1",
                    "spi0""spi1""dma""usb0_aper""usb1_aper",
                    "gem0_aper""gem1_aper""sdio0_aper""sdio1_aper""spi0_aper",
                    "spi1_aper""can0_aper""can1_aper""i2c0_aper""i2c1_aper",
                    "uart0_aper""uart1_aper""gpio_aper""lqspi_aper""smc_aper",
                    "swdt""dbg_trc""dbg_apb";
                compatible = "xlnx,ps7-clkc";
                fclk-enable = <0xf>;
                ps-clk-frequency = <50000000>;
                reg = <0x100 0x100>;
            } ;
        } ;
        ps7_ttc_0: ps7-ttc@f8001000 {
            clocks = <&clkc 6>;
            compatible = "cdns,ttc";
            interrupt-names = "ttc0""ttc1""ttc2";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 10 4>, <0 11 4>, <0 12 4>;
            reg = <0xf8001000 0x1000>;
        } ;
        ps7_uart_1: serial@e0001000 {
            clock-names = "uart_clk""pclk";
            clocks = <&clkc 24>, <&clkc 41>;
            compatible = "xlnx,xuartps""cdns,uart-r1p8";
            current-speed = <115200>;
            device_type = "serial";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 50 4>;
            port-number = <0>;
            reg = <0xe0001000 0x1000>;
            xlnx,has-modem = <0x0>;
        } ;
        ps7_usb_0: ps7-usb@e0002000 {
            clocks = <&clkc 28>;
            compatible = "xlnx,ps7-usb-1.00.a""xlnx,zynq-usb-1.00.a";
            dr_mode = "host";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 21 4>;
            phy_type = "ulpi";
            reg = <0xe0002000 0x1000>;
            xlnx,usb-reset = "MIO 46";
        } ;
        ps7_xadc: ps7-xadc@f8007100 {
            clocks = <&clkc 12>;
            compatible = "xlnx,zynq-xadc-1.00.a";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 7 4>;
            reg = <0xf8007100 0x20>;
        } ;
        
        mt9d111_axi_iic@0x41600000 {
            compatible = "generic-uio";
            reg = < 0x41600000 0x10000>;
        };
        dmaw4gabor_0@43cb0000 {
            compatible = "generic-uio";
            reg = < 0x43cb0000 0x10000 >;
        };
        axis_switch_0@0x43c10000 {
            compatible = "generic-uio";
            reg = < 0x43c10000 0x10000 >;
        };
        axis_switch_1@0x43c20000 {
            compatible = "generic-uio";
            reg = < 0x43c20000 0x10000 >;
        };
        lap_filter_axis_0@0x43c30000 {
            compatible = "generic-uio";
            reg = < 0x43c30000 0x10000>;
        };    
        mt9d111_inf_axis_0@0x43C40000 {
            compatible = "generic-uio";
            reg = < 0x43C40000 0x10000>;
        };
        bitmap_disp_cntrler_axi_master_0@0x43c00000 {
            compatible = "generic-uio";
            reg = < 0x43c00000 0x10000>;
        };
        bitmap_disp_cntrler_axi_master_1@0x43c50000 {
            compatible = "generic-uio";
            reg = < 0x43c50000 0x10000>;
        };
        axi_gpio_0@0x41200000 {
            compatible = "generic-uio";
            reg = < 0x41200000 0x10000>;
        };
        frame_buffer_bmdc@0x17800000 {
            compatible = "generic-uio";
            reg = < 0x17800000 0x1000000>;
        };
        pwm_0@0x43c60000 {
            compatible = "generic-uio";
            reg = < 0x43c60000 0x10000>;
        };
        pwm_1@0x43c70000 {
            compatible = "generic-uio";
            reg = < 0x43c70000 0x10000>;
        };
        motor_monitor_0@0x43c80000 {
            compatible = "generic-uio";
            reg = < 0x43c80000 0x10000>;
        };
        motor_monitor_1@0x43c90000 {
            compatible = "generic-uio";
            reg = < 0x43c90000 0x10000>;
        };
        dmar4resize_gray_0@0x43ca0000 {
            compatible = "generic-uio";
            reg = < 0x43ca0000 0x10000>;
        };
        rgb2hsv_0@0x43cc0000 {
            compatible = "generic-uio";
            reg = < 0x43cc0000 0x10000>;
        };
        ultrasoninc_sensor_inf_0@0x43cd0000 {
            compatible = "generic-uio";
            reg = < 0x43cd0000 0x10000>;
        };
        resize_gray_0@0x43ce0000 {
            compatible = "generic-uio";
            reg = < 0x43ce0000 0x10000>;
        };
        straight_conv_nn2_axis2_0@0x43cf0000 {
            compatible = "generic-uio";
            reg = < 0x43cf0000 0x10000>;
        };
    } ;
} ;

  1. 2017年09月18日 07:28 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0
»