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

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

FPGAの部屋

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

Ultra96用PMOD拡張ボードでカメラ入力1(mt9d111_inf_axis IP の作成1)

Ultra96 ボードでデバイスツリー・オーバーレイをテストする6”でUltra96 のデバイスツリー・オーバーレイは完成したので、次は、以前作製したUltra96用PMOD拡張ボードのPMOD にカメラ(MT9D111)を接続してカメラ画像を表示したいのだが、残念ながらDisplayPort が表示出来ていない。よって、その前段階として、Ultra96用PMOD拡張ボードにMT9D111は接続するのだが、Frame Buffer のメモリにDMA Write するだけのVivado 2018.2 プロジェクトを作成したい。そのFrame Buffer をARM プロセッサで読んで、BMP ファイルにできればパソコンへX Window 経由で表示できるはずだ。
キャッシュにも書けるようになっているし、その環境は十分に整っている。Ultra96用PMOD拡張ボードの動作チェックも行うことができる。

まずは、最初にカメラMT9D111 とのインターフェース用のAXI4-Stream 出力のIP を作成する必要がある。さて、そのmt9d111_inf_axis IP を作っていこう。

まずは、ボードファイルUltra96v1:1.2 を使用して、mt9d111_axis_mpsoc プロジェクトを作成した。

次に、カメラのデータを受けるための非同期FIFO の pixel_fifo を作っていこう。このFIFO は入力のクロックはカメラのクロックで、出力のクロックはAXI4-Stream のクロックなため、非同期FIFO として実装する。
最初にIP Catalog を表示し、「fifo」で検索して、FIFO Generator をダブルクリックしてダイアログを表示させた。
mt9d111_axis_mpsoc_1_181030.png

最初のFIFO Generator のダイアログ画面を示す。Basic タブだ。
最初に、Component Name に pixel_fifo と入力する。
Fifo Implementaion で Independent Clocks Block RAM を選択する。
mt9d111_axis_mpsoc_2_181030.png

次は、Native Ports タブをクリックする。
Read Mode のラジオボタンをクリックして、First Word Fall Through モードにする。
Data Port Parameters の Write Width と Read Width は 34 に、Write Depth と Read Depth は 512 とする。
mt9d111_axis_mpsoc_3_181030.png

Status Flags タブで、Optional Flags でAlmost Full Flag とAlmost Empty Flag 、overflow 、underflow のチェックボックスにチェックを入れて活かす。
mt9d111_axis_mpsoc_4_181030.png

Data Counts タブで、Data Count Options の More Accurate Data Counts にチェックを入れる。またRead Data Count(Synchronized with Read Clk) にチェックを入れる。
mt9d111_axis_mpsoc_5_181030.png

Summary タブで確認して、OK ボタンをクリックする。
mt9d111_axis_mpsoc_6_181030.png

これで pixel_fifo が生成された。
  1. 2018年10月31日 04:40 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96 ボードでデバイスツリー・オーバーレイをテストする6

Ultra96 ボードでデバイスツリー・オーバーレイをテストする5”の続き。

前回は、Ultra96 でデバイスツリー・オーバーレイでLinux が動作中にデバイスツリーを入れ替えて、異なるハードウェアを動作させることができた。今回は、そのやり方を紹介する。

デバイスツリー・オーバーレイを行うのは、negative と DMA_pow2 だ。2つのディレクトリともに lddtovray.sh と rmdtovray.sh を用意してある。 lddtovray.sh はデバイスツリー・オーバーレイをロードするバッチ・ファイルで、rmdtovray.sh はデバイスツリー・オーバーレイを削除するバッチ・ファイルだ。

negative の lddtovray.sh を示す。

#!/bin/bash

sudo mkdir /config/device-tree/overlays/fpga
sudo cp fpga-load.dtb /config/device-tree/overlays/fpga/dtbo
sudo mkdir /config/device-tree/overlays/fclk0
sudo cp fclk0-zynqmp.dtb /config/device-tree/overlays/fclk0/dtbo
sudo mkdir /config/device-tree/overlays/negative
sudo cp negative.dtb /config/device-tree/overlays/negative/dtbo


negative の rmdtovray.sh を示す。

!/bin/bash

sudo rmdir /config/device-tree/overlays/negative
sudo rmdir /config/device-tree/overlays/fclk0
sudo rmdir /config/device-tree/overlays/fpga


DMA_pow2 の lddtovray.sh を示す。

#!/bin/bash

sudo mkdir /config/device-tree/overlays/fpga
sudo cp fpga-load.dtb /config/device-tree/overlays/fpga/dtbo
sudo mkdir /config/device-tree/overlays/fclk0
sudo cp fclk0-zynqmp.dtb /config/device-tree/overlays/fclk0/dtbo
sudo mkdir /config/device-tree/overlays/DMA_pow2_test
sudo cp DMA_pow2_test.dtb /config/device-tree/overlays/DMA_pow2_test/dtbo


DMA_pow2 の rmdtovray.sh を示す。

!/bin/bash

sudo rmdir /config/device-tree/overlays/DMA_pow2_test/
sudo rmdir /config/device-tree/overlays/fclk0
sudo rmdir /config/device-tree/overlays/fpga/


lddtovray.sh と rmdtovray.sh を使用したデバイスツリー・オーバーレイを使用して、negative を実行してから、DMA_pow2 を実行する方法を示す。
1. 最初に negative のデバイスツリー・オーバーレイをロードする。
2. ./negative_test2 を実行する。
3. negative のデバイスツリー・オーバーレイを削除する。
4. DMA_pow2 のデバイスツリー・オーバーレイをロードする。
5. ./DMA_pow2_test2 を実行する。

cd ~/examples/negative
./lddtovray.sh
sudo ./negative_test2
./rmdtovray.sh
cd ../DMA_pow2
./lddtovray.sh
sudo ./DMA_pow2_test2


Ultra96_ikwzm_105_181029.png
Ultra96_ikwzm_106_181029.png
Ultra96_ikwzm_107_181029.png

その後は、./rmdtovray.sh を行えば、また、異なるハードウェアをロードして試すことができる。とても便利だ。
ikzwm さん、ありがとうございます。
  1. 2018年10月30日 05:14 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96 のuEnv.txt のbootargs に cpuidle.off=1を追加した

twitter で話題になっていたJTAGアダプタを付けていると、Linux 起動時にハングアップしたりする問題だが、私も1,2回なったことがあるので、対処方法を実行することにした。

twitter での話題はここにある。ひでみさんが解決方法を教えてくれた。

ひでみさんのツィートによると「AR# 69143 2017.x-2018.x Zynq UltraScale+ MPSoC: XSDB を Linux CPU アイドルに接続」に対処方法が書いてあるそうだ。

それによると、bootargs に cpuidle.off=1を追加すれば良いとのことだった。
bootargs が書いてあるのは uEnv.txt なので、そこに追加しよう。

ikwzm さんの Debian だと、/boot ディレクトリに第1パーティションがマウントされていた。
cd /boot
sudo vi uEnv.txt
で編集を行って、bootargs に cpuidle.off=1を追加した.
Ultra96_ikwzm_104_181029.png

ciniml さんと同じように xsdb で targets コマンドを使用して、ステータスを見てみた。
source /opt/Xilinx/Vivado/2018.2/settings64.sh
xsdb
connect
targets

Ultra96_ikwzm_108_181030.png

ciniml さんと同じ結果で、すべての APU が Running になっている。

disconnect
exit

して xsdb を終了した。
  1. 2018年10月30日 04:49 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96 ボードでデバイスツリー・オーバーレイをテストする5

Ultra96 ボードでデバイスツリー・オーバーレイをテストする4”の続き。

前回は「アプリケーション・ソフトを作成して、起動したところSegmentation fault になってしまって困っている。uio にデータを書き込むところでSegmentation fault になっているようだ。」ということだった。今回はSegmentation fault を克服するべく頑張った。ハードウェアではなく、ソフトウェアそれもVivado HLSのドライバに問題があったようだ。

いろいろと ikwzm さんに教えていただいてやってみた。ありがとうございました。
まずは、Vivado 2018.2 の DMA_pow2_test のブロック・デザインで、レジスタ設定用のAXIポートを変更したりした。それでも、うまく行かないので、ikwzm さんの”ZynqMP-FPGA-Linux Example (2) for Ultra96”をやってみることにした。

negative.bin を/lib/firmware にコピーして、FPGA のビットストリームをロードし、fclkをデバイスツリー・オーバーレイで変更して、uio と udmabuf をデバイスツリー・オーバーレイで生成した。

sudo python3 negative.py
を実行すると成功した。
Ultra96_ikwzm_95_181029.png

次に、Vivado HLS のドライバを使用して、C でアプリケーション・ソフトを書いた。
Ultra96_ikwzm_96_181029.png

その、negative_test.c を示す。

// negative_test.c
// 2018/10/28 by marsee

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>

#include "xnegative.h"

int main(){
    XNegative xnegative_ap;
    volatile unsigned int *udmabuf4_buf;
    int udmabuf4_fd, fd_phys_addr;
    char  attr[1024];
    unsigned long  phys_addr;
    int Xneg_status;
    int i;
    
    // udmabuf4
    udmabuf4_fd = open("/dev/udmabuf4", O_RDWR); // frame_buffer, The chache is enabled. 
    if (udmabuf4_fd == -1){
        fprintf(stderr, "/dev/udmabuf4 open error\n");
        exit(-1);
    }
    udmabuf4_buf = (volatile unsigned int *)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, udmabuf4_fd, 0);
    if (!udmabuf4_buf){
        fprintf(stderr, "udmabuf4_buf mmap error\n");
        exit(-1);
    }

    // phys_addr of udmabuf4
    fd_phys_addr = open("/sys/class/udmabuf/udmabuf4/phys_addr", O_RDONLY);
    if (fd_phys_addr == -1){
        fprintf(stderr, "/sys/class/udmabuf/udmabuf4/phys_addr open error\n");
        exit(-1);
    }
    read(fd_phys_addr, attr, 1024);
    sscanf(attr, "%lx", &phys_addr);  
    close(fd_phys_addr);
    printf("phys_addr = %x\n", (int)phys_addr);

    printf("1"); fflush(stdout);
    // data set
    for(i=0; i<10; i++){
        udmabuf4_buf[i] = i;
    }
    printf("1"); fflush(stdout);
        
    Xneg_status = XNegative_Initialize(&xnegative_ap, "negative-uio");
    if (Xneg_status != XST_SUCCESS){
        fprintf(stderr, "Could not Initialize XNegative\n");
        return(-1);
    }
    printf("1"); fflush(stdout);
    
    XNegative_Set_in_r(&xnegative_ap, phys_addr);
    printf("1"); fflush(stdout);
    XNegative_Set_out_r(&xnegative_ap, (phys_addr+10*sizeof(int)));
    printf("1"); fflush(stdout);
    XNegative_Set_size(&xnegative_ap, (u32)10);

    printf("1"); fflush(stdout);
    XNegative_Start(&xnegative_ap);
    printf("1"); fflush(stdout);
    
    while(!XNegative_IsDone(&xnegative_ap));

    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, udmabuf4_buf[i], i, udmabuf4_buf[10+i]);
    }

    return(0);
}


コンパイルして、起動したところ Segmentation fault になってしまった。ikwzm さんのPython コードは問題なく動作しているので、これは、ハードウェアの問題ではなくソフトウェアの問題だということがわかった。
Ultra96_ikwzm_98_181029.png

次に、Vivado HLS のドライバを使用しない C のソースコードを書いてみた。negative_test2.c だ。
Ultra96_ikwzm_97_181029.png

negative_test2.c を示す。

// negative_test2.c
// 2018/10/28 by marsee
//

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

int main(){
    volatile unsigned int *udmabuf4_buf;
    int udmabuf4_fd, fd_phys_addr;
    char  attr[1024];
    unsigned long  phys_addr;
    int fd1;
    volatile unsigned int *negative;
    int i;
    
    // udmabuf4
    udmabuf4_fd = open("/dev/udmabuf4", O_RDWR|O_SYNC); // frame_buffer, The chache is enabled. 
    if (udmabuf4_fd == -1){
        fprintf(stderr, "/dev/udmabuf4 open error\n");
        exit(-1);
    }
    udmabuf4_buf = (volatile unsigned int *)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, udmabuf4_fd, 0);
    if (!udmabuf4_buf){
        fprintf(stderr, "udmabuf4_buf mmap error\n");
        exit(-1);
    }

    // phys_addr of udmabuf4
    fd_phys_addr = open("/sys/class/udmabuf/udmabuf4/phys_addr", O_RDONLY);
    if (fd_phys_addr == -1){
        fprintf(stderr, "/sys/class/udmabuf/udmabuf4/phys_addr open error\n");
        exit(-1);
    }
    read(fd_phys_addr, attr, 1024);
    sscanf(attr, "%lx", &phys_addr);  
    close(fd_phys_addr);
    printf("phys_addr = %x\n", (int)phys_addr);

    // data set
    for(i=0; i<10; i++){
        udmabuf4_buf[i] = i;
    }

    // uio initialize (uio1)
    fd1 = open("/dev/uio1", O_RDWR|O_SYNC); // negative IP
    if (fd1 < 1){
        fprintf(stderr, "/dev/uio1 (negative) open error\n");
        exit(1);
    }
    negative = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
    if (!negative){
        fprintf(stderr, "negative mmap error\n");
        exit(1);
    }
    
    negative[6] = phys_addr; // Data signal of in_r
    negative[8] = phys_addr+10*sizeof(int); // Data signal of out_r
    negative[10] = 10; // Data signal of size
    
    negative[0] = 1; // ap_start
    
    while (!(negative[0] & 0x2)) ; // ap_done ?
    
    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, udmabuf4_buf[i], i, udmabuf4_buf[10+i]);
    }
    
    munmap((void *)negative, 0x10000);
    close(fd1);
    munmap((void *)udmabuf4_buf, 0x1000);
    close(udmabuf4_fd);
    
    return(0);
}


negative_test2.c をコンパイルして実行したところ、成功した。なお、ikwzm さんの”ZynqMP-FPGA-Linux Example (2) for Ultra96”のZynq UltraScale+ MPSoC のAXI4 Master 用のポートは S_AXI_HP0_FPD を使用していてキャッシュに書けるポートを使用してない。よって、udmabuf をキャッシュOFF モードにするため、udmabuf4 をオープンするときのオプションに O_SYNC を加えている。
Ultra96_ikwzm_99_181029.png

これで成功したということは、Vivado HLS のドライバの関数を使用するとSegmentation fault になるということだ。Vivado HLS のドライバが原因だったようだ。

さて、自分の 2 乗IP に戻ろう。
Vivado 2018.2 のブロック・デザインを示す。最初のブロック・デザイン同様に、Zynq UltraScale+ MPSoC のレジスタ設定用のポートは M_AXI_HPM0_FPD を使用した。なお、Ultra96 のボードファイルはUltra96v1 1.2 を使用している。
Ultra96_ikwzm_100_181029.png

なお、DMP_pow2 IP のPROT value は "010" に、CACHE value は "1111" に設定してある。
Ultra96_ikwzm_44_181020.png

Vivado HLS のドライバを使用しない DMA_pow2_test2.c を作成した。
Ultra96_ikwzm_103_181029.png

DMA_pow2_test2.c を示す。

// DMA_pow2_test2.c
// 2018/10/28 by marsee
//

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

int main(){
    volatile unsigned int *udmabuf4_buf;
    int udmabuf4_fd, fd_phys_addr;
    char  attr[1024];
    unsigned long  phys_addr;
    int fd1;
    volatile unsigned int *dma_pow2;
    int i;
    
    // udmabuf4
    udmabuf4_fd = open("/dev/udmabuf4", O_RDWR); // frame_buffer, The chache is enabled. 
    if (udmabuf4_fd == -1){
        fprintf(stderr, "/dev/udmabuf4 open error\n");
        exit(-1);
    }
    udmabuf4_buf = (volatile unsigned int *)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, udmabuf4_fd, 0);
    if (!udmabuf4_buf){
        fprintf(stderr, "udmabuf4_buf mmap error\n");
        exit(-1);
    }

    // phys_addr of udmabuf4
    fd_phys_addr = open("/sys/class/udmabuf/udmabuf4/phys_addr", O_RDONLY);
    if (fd_phys_addr == -1){
        fprintf(stderr, "/sys/class/udmabuf/udmabuf4/phys_addr open error\n");
        exit(-1);
    }
    read(fd_phys_addr, attr, 1024);
    sscanf(attr, "%lx", &phys_addr);  
    close(fd_phys_addr);
    printf("phys_addr = %x\n", (int)phys_addr);

    // data set
    for(i=0; i<20; i++){
        udmabuf4_buf[i] = i;
    }

    // uio initialize (uio1)
    fd1 = open("/dev/uio1", O_RDWR|O_SYNC); // dma_pow2 IP
    if (fd1 < 1){
        fprintf(stderr, "/dev/uio1 (dma_pow2) open error\n");
        exit(1);
    }
    dma_pow2 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
    if (!dma_pow2){
        fprintf(stderr, "dma_pow2 mmap error\n");
        exit(1);
    }
    printf("Address of int size is %d\n", sizeof(int *));
    
    dma_pow2[6] = phys_addr; // Data signal of in_r
    dma_pow2[8] = phys_addr+10*sizeof(int); // Data signal of out_r
    
    dma_pow2[0] = 1; // ap_start
    
    while (!(dma_pow2[0] & 0x2)) ; // ap_done ?
    
    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, udmabuf4_buf[i], i, udmabuf4_buf[10+i]);
    }
    
    munmap((void *)dma_pow2, 0x10000);
    close(fd1);
    munmap((void *)udmabuf4_buf, 0x1000);
    close(udmabuf4_fd);
    
    return(0);
}


デバイスツリー・オーバーレイを行って、コンパイルした DMA_pow2_test2 を実行したところ実行できたのだが、値が合わない。
これは、ikwzm さんの”ZynqMP-FPGA-Linux Example (2) for Ultra96”では、boot.bin に regs.init が入っていないので、M_AXI_HPM0_FPD でキャッシュに書けなかったためだった。(ikwzm さんの”UltraZed 向け Debian GNU/Linux で AXI HPC port を使う (基礎編)”の”boot.bin による設定”を参照)

自分で作った boot.bin に regs.init を入れたので、これをSDカードの第1パーティションのULTRA96_BOO に書いた。
Ultra96_ikwzm_102_181029.png

そして、Debian をブートしてから、もう一度、DMA_pow2_test2 を実行したところ、(当然、前準備は実行している)成功した。
Ultra96_ikwzm_101_181029.png

やっとうまく行って、本当に良かった。
つまり、Vivado HLS のドライバは、Zynq UltraScale+ MPSoC では使い物にならないんじゃないかな?
やたらと u32 使っているし、DMA_pow2_test2 の実行結果でも分かるように int * のサイズは 8 バイトだったので、アドレスは 64 ビットになっているはずだ。。。
  1. 2018年10月29日 05:01 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96 ボードでデバイスツリー・オーバーレイをテストする4

前回の uio がロードできない現象は、使用していた uEnv.txt の ”boot_args”に”uio_pdrv_genirq.of_id=generic-uio”が書いてなかったことだった。これを機会に ikwzm さんの ZynqMP-FPGA-Linux/target/Ultra96/boot のファイルをSDカードの第1パーティションのULTRA96_BOO のファイルとすべて交換したところ uio がロードできるようになった。
uio はロードできるようになったが、アプリケーション・ソフトを作成して、起動したところSegmentation fault になってしまって困っている。uio にデータを書き込むところでSegmentation fault になっているようだ。

まずは、 ikwzm さんの ZynqMP-FPGA-Linux/target/Ultra96/boot のファイルをSDカードの第1パーティションのULTRA96_BOO のファイルとすべて交換した。ULTRA96_BOO の内容を示す。
Ultra96_ikwzm_86_181027.png

~/examples/DMA_pow2 ディレクトリに行って、デバイスツリー・オーバーレイでFPGAのビットストリーム、PSからPLに出力されるクロック fclk 、uio と udmabuf をロードした。
cd ~/examples/DMA_pow2/
sudo mkdir /config/device-tree/overlays/fpga
sudo cp fpga-load.dtb /config/device-tree/overlays/fpga/dtbo
sudo mkdir /config/device-tree/overlays/fclk0
sudo cp fclk0-zynqmp.dtb /config/device-tree/overlays/fclk0/dtbo
sudo mkdir /config/device-tree/overlays/DMA_pow2_test
sudo cp DMA_pow2_test.dtb /config/device-tree/overlays/DMA_pow2_test/dtbo

Ultra96_ikwzm_87_181027.png

ls -l /sys/class/uio*
をすると、やっと uio1 が見えた。良かった。。。
more /sys/class/uio/uio1/name
をすると dma_pow2-uio が見えた。
Ultra96_ikwzm_88_181027.png

ここまで、出来たので、アプリケーション・ソフトを作って動作を確認してみよう。
~/examples/DMA_pow2/drivers/ ディレクトリを作成して、その下に DMA_pow2_test.c を作成した。
Ultra96_ikwzm_89_181027.png

// DMA_pow2_test.c
// 2018/10/25 by marsee

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>

#include "xdma_pow2.h"

int main(){
    XDma_pow2 xdma_pow2_ap;
    volatile unsigned int *udmabuf4_buf;
    int udmabuf4_fd, fd_phys_addr;
    char  attr[1024];
    unsigned long  phys_addr;
    int Xdma_status;
    int i;
    
    // udmabuf4
    udmabuf4_fd = open("/dev/udmabuf4", O_RDWR); // frame_buffer, The chache is enabled. 
    if (udmabuf4_fd == -1){
        fprintf(stderr, "/dev/udmabuf4 open error\n");
        exit(-1);
    }
    udmabuf4_buf = (volatile unsigned int *)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, udmabuf4_fd, 0);
    if (!udmabuf4_buf){
        fprintf(stderr, "udmabuf4_buf mmap error\n");
        exit(-1);
    }

    // phys_addr of udmabuf4
    fd_phys_addr = open("/sys/class/udmabuf/udmabuf4/phys_addr", O_RDONLY);
    if (fd_phys_addr == -1){
        fprintf(stderr, "/sys/class/udmabuf/udmabuf4/phys_addr open error\n");
        exit(-1);
    }
    read(fd_phys_addr, attr, 1024);
    sscanf(attr, "%lx", &phys_addr);  
    close(fd_phys_addr);
    printf("phys_addr = %x\n", (int)phys_addr);

    // data set
    for(i=0; i<10; i++){
        udmabuf4_buf[i] = i;
    }
        
    Xdma_status = XDma_pow2_Initialize(&xdma_pow2_ap, "dma_pow2-uio");
    if (Xdma_status != XST_SUCCESS){
        fprintf(stderr, "Could not Initialize XDMA_pow2\n");
        return(-1);
    }
    
    XDma_pow2_Set_in_r(&xdma_pow2_ap, phys_addr);
    XDma_pow2_Set_out_r(&xdma_pow2_ap, (phys_addr+10*sizeof(int)));

    XDma_pow2_Start(&xdma_pow2_ap);
    
    while(!XDma_pow2_IsDone(&xdma_pow2_ap));

    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, udmabuf4_buf[i], i, udmabuf4_buf[10+i]);
    }

    return(0);
}


Makefile を作成した。
Ultra96_ikwzm_90_181027.png

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

PROGRAM = DMA_pow2_test
OBJS = DMA_pow2_test.o xdma_pow2_linux.o xdma_pow2.o

CC = gcc
CFLAGS = -Wall -O2

.SUFFIXES: .c .o

.PHONY: all

all: DMA_pow2_test

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

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


~/examples/DMA_pow2/drivers/ ディレクトリに、DMA_pow2 IP のdriver の xdma_pow2_linux.c、 xdma_pow2.h、 xdma_pow2.c、 xdma_pow2_hw.h をコピーした。
make
したところ、DMA_pow2_test が出来た。
DMA_pow2_test を起動したところ、Segmentation fault になってしまった。
どこでSegmentation fault が出るのか?を確かめることにした。
DMA_pow2_test.c にたくさん printf("1"); fflush(stdout); を埋め込んだ。printf("1"); だけではだめで、すぐに 1 を出力させるために、fflush(stdout); が必要だ。プリントしてもバッファリングされるためSegmentation fault まで表示されずに終わってしまう。
Ultra96_ikwzm_92_181027.png

これで、make して DMA_pow2_test を実行した。
Ultra96_ikwzm_93_181027.png

1 は 3 個表示してSegmentation fault だったので、

XDma_pow2_Set_in_r(&xdma_pow2_ap, phys_addr);

でSegmentation fault になっている。つまり、uio1 のDMA_pow2 IP のレジスタに書き込むときにSegmentation fault となっているようだった。

ここで、トラブルシューティングするのだが、ikwzm さんの”UltraZed 向け Debian GNU/Linux で AXI HPC port を使う (実践編1)”のVivado プロジェクトのブロック・デザインをよく見てみると、DMA_pow2 IP が接続されているZynqMP のポートは、M_AXI_HPM0_LPD だった。私の使用していたのは、M_AXI_HPM0_FPD ポートだったので、M_AXI_HPM0_LPD に変更した。
Ultra96_ikwzm_94_181028.png

これで、Vivado 2018.2 で論理合成、インプリメンテーション、ビットストリームを行って、bin ファイルを生成して、Ultra96 にFTPしてやってみたが、やはり、Segmentation fault だった。

次に、ikwzm さんにUltra96 のボードファイルは複数あるということで、Avnet の Github の bdf プロジェクトを見るとUltra96v1 と Ultra96v2 がある。どちらもVivado 2018.2 にインストールして、ikwzm さんが使用している Ultra96v1 の 1.2 バージョンを使用して、Vivado 2018.2 のプロジェクトを作り直してみたが、やはり、Segmentation fault だった。
  1. 2018年10月28日 05:55 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:3

Ultra96 ボードでデバイスツリー・オーバーレイをテストする3

Ultra96 ボードでデバイスツリー・オーバーレイをテストする2”の続き。

前回は、デバイスツリー・オーバーレイでFPGAのビットストリーム、PSからPLに出力されるクロック fclk 、uio と udmabuf がロード出来た。実は、uio がロードされていないようなのだ。今回は、その原因を探ってみよう。

まずは、Ultra96 のDebian を起動直後に /sys/class ディレクトリに行ってみる。
そうすると uio ディレクトリがあって、その下に uio0 がすでにある。
その uio の名前を見ると axi-pmon だった。
Ultra96_ikwzm_79_181026.png

次に、~/examples/DMA_pow2 ディレクトリに行って、デバイスツリー・オーバーレイでFPGAのビットストリーム、PSからPLに出力されるクロック fclk 、uio と udmabuf をロードした。
cd ~/examples/DMA_pow2/
sudo mkdir /config/device-tree/overlays/fpga
sudo cp fpga-load.dtb /config/device-tree/overlays/fpga/dtbo
sudo mkdir /config/device-tree/overlays/fclk0
sudo cp fclk0-zynqmp.dtb /config/device-tree/overlays/fclk0/dtbo
sudo mkdir /config/device-tree/overlays/DMA_pow2_test
sudo cp DMA_pow2_test.dtb /config/device-tree/overlays/DMA_pow2_test/dtbo

Ultra96_ikwzm_80_181026.png

デバイスツリー・オーバーレイした後で、/sys/class/ ディレクトリを見ても axi-pmon の uio0 だけだった。これは、uio が追加されていない?
/sys/class/udamabuf が増えていて、その下に udmabuf4 が追加されている。udmabuf は問題ないようだ。
Ultra96_ikwzm_81_181026.png

/sys/class/fclkcfg/ ディレクトリが増えていて、その下に、 fclk0 が追加されている。
Ultra96_ikwzm_85_181026.png

次に、デバイスツリー・オーバーレイを削除した。
sudo rmdir /config/device-tree/overlays/DMA_pow2_test/
sudo rmdir /config/device-tree/overlays/fclk0
sudo rmdir /config/device-tree/overlays/fpga/

下の図で、DMA_pow2_test を rmdir した後で、 ls を行ったところ udmabuf4 が無くなっている。成功しているようだ。
これでもう一度、デバイスツリー・オーバーレイを行える。
Ultra96_ikwzm_82_181026.png

次に、DMA_pow2_test.dts に uio をもう1つ追加してみた。IP はなくて、アドレスはマップされていないのだが、uio0 がすでにあってロードされないならば、uio1 にならば追加できるのではないか?という考えだ。
Ultra96_ikwzm_83_181026.png

DMA_pow2_test.dts を dtc でコンパイルして、デバイスツリー・オーバーレイでFPGAのビットストリーム、PSからPLに出力されるクロック fclk 、uio と udmabuf をもう一度ロードしてみたが、やはり uio0 だけで uio1 はロードされていなかった。
Ultra96_ikwzm_84_181026.png

uio がロードできないのがおかしいので、ikwzm さんの配布されているSDカードのイメージを試してみようと思う。
  1. 2018年10月26日 05:58 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96 ボードでデバイスツリー・オーバーレイをテストする2

Ultra96 ボードでデバイスツリー・オーバーレイをテストする1”の続き。

前回は、ikwzm さんの”UltraZed 向け Debian GNU/Linux で AXI HPC port を使う (実践編1)”を参照しながら、デバイスツリー・オーバーレイをやってみたが、fclkcfg をロードした時点で失敗してしまった。今回は、ikwzm さんが Ultra96 ボードのSDカードのイメージを含んだ”kwzm/ZynqMP-FPGA-Linux”を公開してくれたので、SDカードのブート・パーティションのdtb だけをそれと入れ替えてやってみよう。

まずは、”kwzm/ZynqMP-FPGA-Linux”の”Ultra96”ページを見ながら git clone した。
git clone git://github.com/ikwzm/ZynqMP-FPGA-Linux
cd ZynqMP-FPGA-Linux
git checkout v2018.2.1-rc1
git lfs pull


ZynqMP-FPGA-Linux/target/Ultra96/boot ディレクトリのdevicetree-4.14.0-xlnx-v2018.2-zynqmp-fpga-ultra96.dtb をMicroSD カードの第1パーティションのULTRA96_BOO に system.dtb と名前を変更してコピーした。
Ultra96_ikwzm_72_181024.png

Ultra96 ボードのMicroSD スロットに入れて電源ON。
ブートは成功し、問題無かった。
fpga ユーザーでログインした。
cd examples/DMA_pow2
sudo mkdir /config/device-tree/overlays/fpga
sudo cp fpga-load.dtb /config/device-tree/overlays/fpga/dtbo
sudo mkdir /config/device-tree/overlays/fclk0
sudo cp fclk0-zynqmp.dtb /config/device-tree/overlays/fclk0/dtbo

Ultra96_ikwzm_73_181024.png

シリアル・コンソールにデバイスツリー・オーバーレイのメッセージが表示された。

[  105.706727] fpga_manager fpga0: writing DMA_pow2_test_wrapper.bin to Xilinx ZynqMP FPGA Manager
[  135.918071] fclkcfg: loading out-of-tree module taints kernel.
[  135.925556] fclkcfg amba:fclk0: driver installed.
[  135.930291] fclkcfg amba:fclk0: device name    : fclk0
[  135.935415] fclkcfg amba:fclk0: clock  name    : pl0_ref
[  135.940705] fclkcfg amba:fclk0: clock  rate    : 99999999
[  135.946108] fclkcfg amba:fclk0: clock  enabled : 1
[  135.950869] fclkcfg amba:fclk0: remove rate    : 1000000
[  135.956164] fclkcfg amba:fclk0: remove enable  : 0


Ultra96_ikwzm_74_181024.png

うまく行ったみたいだ。

次に、uio と udmabuf のロードを行う。
UltraZed 向け Debian GNU/Linux で AXI HPC port を使う (実践編1)のUio とUdmabuf の準備”を参考に DMA_pow2_test.dts を書いた。
Ultra96_ikwzm_75_181024.png

/dts-v1/;/plugin/;
/ {
    fragment@0 {
        target-path = "/amba_pl@0";
        #address-cells = <2>;
        #size-cells = <2>;

        __overlay__ {
            #address-cells = <2>;
            #size-cells = <2>;

            dma_pow2-uio {
                compatible = "generic-uio";
                reg = <0x0 0x00A0000000 0x0 0x10000>;
            };

            dma_pow2-udmabuf4 {
                compatible  = "ikwzm,udmabuf-0.10.a";
                device-name = "udmabuf4";
                size = <0x00001000>;
            };
        };
    };
};


dtc で DMA_pow2_test.dts をコンパイルして、dtb に変換してから、ロードした。
dtc -I dts -O dtb -o DMA_pow2_test.dtb DMA_pow2_test.dts
sudo mkdir /config/device-tree/overlays/DMA_pow2_test
sudo cp DMA_pow2_test.dtb /config/device-tree/overlays/DMA_pow2_test/dtbo

Ultra96_ikwzm_76_181024.png

シリアル・コンソールを見ると、 udmabuf がロードされているのが分かる。
Ultra96_ikwzm_77_181025.png

ls -la で uio と udmabuf を見たところ、両方共ロードされていた。
更に、fpga ユーザーでも uio と udmabuf を扱えるようにファイルのパーミッションを 666 にしておく。
ls -la /dev/uio*
ls -la /dev/udmabuf*
sudo chmod 666 /dev/uio*
sudo chmod 666 /dev/udmabuf*

Ultra96_ikwzm_78_181025.png

なお、現在の”kwzm/ZynqMP-FPGA-Linux”の”build-v2018.2”の”ZynqMP-FPGA-Linux/target/Ultra96/boot ディレクトリのdevicetree-4.14.0-xlnx-v2018.2-zynqmp-fpga-ultra96.dtb” では uio と udmabuf のロードがうまく行かなかった。その代わりに、”ikwzm/devicetree-4.14.0-xlnx-v2018.2-zynqmp-fpga-ultra96.dtb”を使用している。この dtb だとうまく uio と udmabuf がロード出来た。この dtb と dts は近日中に”kwzm/ZynqMP-FPGA-Linux”の v2018.2.1-rc2 として ikwzm さんがリリースされるとのことだ。

(追記)
ZynqMP-FPGA-Linux/doc/install/ultra96.md”を見ると、v2018.2.1-rc2 がリリースされたようだ。
  1. 2018年10月24日 06:54 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96 ボードでデバイスツリー・オーバーレイをテストする1

デバイスツリー・オーバーレイをテストするためのVivado 2018.2 のプロジェクトを作成する2”の続き。

前回は、デバイスツリー・オーバーレイをテストするためのVivado 2018.2 のプロジェクトで、SDK を起動して、ベアメタル・アプリケーションで2乗回路が動作することを確認した。今回は、ikwzm さんの”UltraZed 向け Debian GNU/Linux で AXI HPC port を使う (実践編1)”を参照しながら、デバイスツリー・オーバーレイをやってみよう。

まずは、bin ファイルを作成しよう。
ここからは、パソコン側の作業だ。
DMA_pow2_warpper.bif を作成した。
Ultra96_ikwzm_67_181023.png

bootgen で bin ファイルに変換する。
bootgen -image DMA_pow2_test_wrapper.bif -arch zynqmp -w -o DMA_pow2_test_wrapper.bin

bin ファイルが生成された。
Ultra96_ikwzm_60_181020.png

次に、デバイスツリー・オーバーレイでFPGA のコンフィグレーションをやってみる。
ここからは、Ultra96 ボード上のDebian での作業となる。
fpga-load.dts を作成した。
Ultra96_ikwzm_61_181022.png

bin ファイルをFTP で持ってきたので、/lib/firmware/ にコピーする。
sudo cp DMA_pow2_test_wrapper.bin /lib/firmware/
ls /lib/firmware/

Ultra96_ikwzm_62_181022.png

dtc で fpga-load.dts をコンパイルした。
dtc -I dts -O dtb -o fpga-load.dtb fpga-load.dts
Ultra96_ikwzm_68_181023.png

Warning が出ている。

fpga-load.dtb: Warning (unit_address_vs_reg): Node /fragment@0 has a unit name, but no reg property


fpgaをコンフィグレーションしてみよう。
sudo mkdir /config/device-tree/overlays/fpga
sudo cp fpga-load.dtb /config/device-tree/overlays/fpga/dtbo

Ultra96_ikwzm_63_181022.png

シリアル・コンソールに

fpga_manager fpga0: writing DMA_pow2_test_wrapper.bin to Xilinx ZynqMP FPGA Manager

と表示された。
Ultra96_ikwzm_64_181022.png

成功だ。ただ、DONE のLED が一瞬でも消えなかったのが気になる。

次に、デバイスツリー・オーバーレイでクロックの設定を行う。
fclk0-zynqmp.dts を作成した。
Ultra96_ikwzm_65_181022.png

デバイスツリーをコンパイルした。
dtc -I dts -O dtb -o fclk0-zynqmp.dtb fclk0-zynqmp.dts
Ultra96_ikwzm_69_181023.png

fpga-load.dts のときと同じWarning が出た。

デバイスツリーをロードする。
sudo mkdir /config/device-tree/overlays/fclk0
sudo cp fclk0-zynqmp.dtb /config/device-tree/overlays/fclk0/dtbo

Ultra96_ikwzm_66_181022.png

エラーになってしまったようだ。
Ultra96_ikwzm_70_181023.png

[ 1826.637372] OF: resolver: no symbols in root of device tree.
[ 1826.643042] OF: resolver: overlay phandle fixup failed: -22
[ 1826.648592] create_overlay: Failed to resolve tree


dpkg -l してみると fclkcfg-4.14.0 があった。
Ultra96_ikwzm_71_181023.png
  1. 2018年10月23日 04:48 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

デバイスツリー・オーバーレイをテストするためのVivado 2018.2 のプロジェクトを作成する2

デバイスツリー・オーバーレイをテストするためのVivado 2018.2 のプロジェクトを作成する”の続き。

前回は、その DMA_pow2 IP を使用してVivado 2018.2 でDMA_pow2_test プロジェクトを作成し、論理合成、インプリメンテーション、ビットストリームの生成を行って成功した。今回は、SDKを使用して、ベアメタル・アプリケーションを作成して、動作をチェックする。

まずは、Vivado 2018.2 でハードウェアをエクスポートした。
次に、Vivado 2018.2 からSDK を立ち上げた。
Ultra96_ikwzm_51_181020.png

Aplication Project を新規作成する。
Project Name を test_dma として、 Next > ボタンをクリックする。
Ultra96_ikwzm_52_181020.png

Available Templates から Empty Application を選択して、Finish ボタンをクリックした。
Ultra96_ikwzm_53_181020.png

test_dma 、 test_dma_bsp プロジェクトが作成された。
test_dma プロジェクトを展開して、Debug/src を展開して、src で右クリックし、New -> Source File を選択すると、ダイアログが開く。
Source File に test_dma.c と入力してFinish ボタンをクリックする。
Ultra96_ikwzm_54_181020.png

test_dma.c が生成された。
test_dma.c のコードを書いた。
セーブすると、ビルドされて test_dma.elf が生成された。
Ultra96_ikwzm_55_181020.png

Ultra96 をJTAG モードにして、電源ON。
SDK のXilinx メニューからProgram FPGA を選択し、FPGAにビット・ファイルをダウンロードした。
Ultra96_ikwzm_56_181020.png

アプリケーション・ソフトを走らせる前に gtkterm を起動した。(Windows だったら Tera Term を起動)
sudo gtkterm

そして、stdin, stdout に使用する psu_uart_0 を psu_uart_1 に変更した。(”SDKでstdin, stdout に割り当てられるデバイスを変更”を参照のこと)

SDK の test_dma/Binaries/test_dma.elf を右クリックし、右クリックメニューから Run As -> 1 Launch on Hardware (System Debugger) を選択して、アプリケーション・ソフトを走らせた。
Ultra96_ikwzm_57_181020.png

アプリケーション・ソフトが起動して、gtkterm に表示された。
Ultra96_ikwzm_58_181020.png

うまく 2乗されている。

最後に test_dma.c を貼っておく。

// test_dma.c
// Created on: 2017/12/02
//      Author: masaaki

#include <stdio.h>
#include "xdma_pow2.h"
#include "xparameters.h"

volatile int data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
volatile int result[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

int main(){
    XDma_pow2 XDMA_pow2_ap;
    XDma_pow2_Config *XDMA_pow2_apPtr;
    int i;

    // Look Up the device configuration
    XDMA_pow2_apPtr = XDma_pow2_LookupConfig(0);
    if (!XDMA_pow2_apPtr){
        fprintf(stderr, "XDma_pow2 configuration failed.\n");
        return(-1);
    }

    // Initialize the Device
    int Xlap_status = XDma_pow2_CfgInitialize(&XDMA_pow2_ap, XDMA_pow2_apPtr);
    if (Xlap_status != XST_SUCCESS){
        fprintf(stderr, "Could not Initialize XDma_pow2\n");
        return(-1);
    }

    XDma_pow2_Set_in_r(&XDMA_pow2_ap, (u32)&data[0]);
    XDma_pow2_Set_out_r(&XDMA_pow2_ap, (u32)&result[0]);

    XDma_pow2_Start(&XDMA_pow2_ap);

    while(!XDma_pow2_IsDone(&XDMA_pow2_ap)) ;

    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, data[i], i, result[i]);
    }

    return 0;

}

  1. 2018年10月22日 04:20 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

デバイスツリー・オーバーレイをテストするためのVivado 2018.2 のプロジェクトを作成する

Vivado HLS でDMA Readしたデータを2乗し、DMA WriteするUltra96ボード用 IP を作成”でメモリからDMA Read したデータを 2 乗して、DMA Write でメモリに書き戻すVivado HLS 2018.2 のIP が出来た。今回は、その DMA_pow2 IP を使用してVivado 2018.2 でDMA_pow2_test プロジェクトを作成する。

最初にUltra96 のボード・ファイルを使用して、DMA_pow2_test プロジェクトを作成した。

次にやることは、プロジェクト作成時に DMA_pow2_test ディレクトリが作成されているので、そのディレクトリの下に DMA_pow2 ディレクトリを作成して、”Vivado HLS でDMA Readしたデータを2乗し、DMA WriteするUltra96ボード用 IP を作成”で作成した xilinx_com_hls_DMA_pow2_1_0.zip の中身を展開して入れた。
Ultra96_ikwzm_59_181020.png

DMA_pow2_test プロジェクトで、Flow Navigator から IP Catalog をクリックして、IP Catalog を表示し、Add Repository でDMA pow2 IP をリポジトリに追加した。これで、DMA_pow2 IP がIP Integrator から使用することができる。

次に、Create Block Design をクリックして、DMA_pow2_test ブロック・デザインを作成した。
完成したDMA_pow2_test ブロック・デザインを示す。
Ultra96_ikwzm_43_181020.png

Zynq UltraScale+ MPSoC の設定を示す。
AXI HPM0_FPD と AXI_HP0_FPD を使用している。
Ultra96_ikwzm_41_181020.png

PL への出力クロックは 100 MHz に設定されている。
Ultra96_ikwzm_42_181020.png

Vivado HLS 2018.2 で作成したDMP_pow2 IP のPROT value は "010" に、CACHE value は "1111" に設定した。(ikwzm さんの”UltraZed 向け Debian GNU/Linux で AXI HPC port を使う (実践編1)”を参照した)
Ultra96_ikwzm_44_181020.png

Address Editor を示す。アドレスの割当を知ることができる。
Ultra96_ikwzm_45_181020.png

Validate Design を行うと、クリティカル・ワーニングが 1 つ出たが、問題ないと思う。
Ultra96_ikwzm_47_181020.png

ブロック・デザインをセーブして、プロジェクト・トップとなる DMA_pow2_test.v を作成した。
Ultra96_ikwzm_46_181020.png

これで準備が整った。今回はPS と PL で完結していて外にポートが出ていないので、制約ファイルの必要がない。
論理合成、インプリメンテーション、ビットストリームの生成を行った。成功した。結果を示す。
Ultra96_ikwzm_48_181020.png
Ultra96_ikwzm_49_181020.png

PL のリソース使用量もほんの少しだ。

DMA_pow2_test/DMA_pow2_test.runs/impl_1 に DMA_pow2_test_wrapper.bit が出来た。
  1. 2018年10月21日 06:02 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS でDMA Readしたデータを2乗し、DMA WriteするUltra96ボード用 IP を作成

Ultra96 で ikwzm さんのDebian9 Root File Systemを動かしてみる4”でAXI HPC port を Inner Share として使用するための設定を行った。次には、デバイスツリー・オーバーレイを試すためのPLのハードウェアを作成する。そのために今回は、Vivado HLS 2018.2 を使用して、データをDMA Read で持ってきて、2乗し、そして、DMA Writeで書き込むIP を作成しよう。

ソースコードの DMA_pow2.cpp を示す。

// DMA_pow2.cpp
// 2018/05/08 by marsee
//

int DMA_pow2(volatile int *in, volatile int *out){
#pragma HLS INTERFACE m_axi depth=10 port=out offset=slave
#pragma HLS INTERFACE m_axi depth=10 port=in offset=slave
#pragma HLS INTERFACE s_axilite port=return

    for (int i=0; i<10; i++){
        int temp = in[i];
        out[i] = temp * temp;
    }

    return(0);
}


テストベンチの DMA_pow2_tb.cpp を示す。

// DMA_pow2_tb.cpp
// 2018/05/08 by marsee
//

#include <iostream>

int DMA_pow2(volatile int *in, volatile int *out);

int main(){
    int data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int result[10];

    DMA_pow2(data, result);

    for(int i=0; i<10; i++){
        std::cout << "data[" << i << "]= " << data[i] <<
                ", result[" << i << "] = " <<
                result[i] << std::endl;
    }
}


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

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

2乗されている。

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

Estimated は 8.75 ns でLatency は 42 クロックだった。
Loop1 のIteration Latency が 3 なので、3 クロックに 1 回出力されることになる。
リソース使用量は、BRAM_18K が 2 個、DSP48E が 3 個、FF が 806 個、LUT が 1001 個、URAM が 0 個使用された。

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

ちょうど 100 クロックかかった。

C シミュレーションの波形を示す。
Ultra96_ikwzm_37_181020.png
Ultra96_ikwzm_38_181020.png

Write は 3 クロックに 1 回であることが見て取れる。

最後に Export RTL を行って、IP 化した。結果を示す。
Ultra96_ikwzm_39_181020.png

CP archieved post-implementation は 2.748 ns で十分 10 ns を満足している。

solution1/impl/ip ディレクトリに xilinx_com_hls_DMA_pow2_1_0.zip が生成された。
Ultra96_ikwzm_40_181020.png
  1. 2018年10月20日 05:52 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Anaconda でインストールしたJupyter Notebookを任意のフォルダから実行する方法

Windows 10 の Anaconda でインストールしたJupyter Notebookを任意のフォルダから実行したい。特に C: ドライブにSSD が入っているとあまり容量に余裕がない場合は、D: ドライブで思う存分、学習用の画像ファイルを扱いたい(GBオーダーの容量を必要とするため)。という欲求があるので、C: ドライブじゃないところから起動したい。

PowerShell を立ち上げて jupyter notebook で起動するとKeras が使えなかった。

Jupyter Notebook のプロパティを立ち上げると、リンク先が

D:\Anaconda3\python.exe D:\Anaconda3\cwp.py D:\Anaconda3 D:\Anaconda3\python.exe D:\Anaconda3\Scripts\jupyter-notebook-script.py %USERPROFILE%

になっていた。
Anaconda_d_drive_1_181019.png

C:\Users\<ユーザー名>フォルダに jupyter-notebook_d.bat を作った。
jupyter-notebook_d.bat の中身を示す。

D:\Anaconda3\python.exe D:\Anaconda3\cwp.py D:\Anaconda3 D:\Anaconda3\python.exe D:\Anaconda3\Scripts\jupyter-notebook-script.py D:\User


これをPowerShell で起動すれば、Jupyter Notebook で、D:\User から表示された。
Anaconda_d_drive_3_181019.png

これで、Windows 10 の Anaconda でインストールしたJupyter Notebookを任意のフォルダから実行することができる。
  1. 2018年10月19日 12:50 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Ultra96 で ikwzm さんのDebian9 Root File Systemを動かしてみる4

Ultra96 で ikwzm さんのDebian9 Root File Systemを動かしてみる3”の続き。

前回は、ikwzm さんの配布されているLinux カーネルに変更したら各種パッケージをインストールできて、nautilus や geany もインストールできて起動できた。次はデバイスツリー・オーバーレイがうまく行くかどうか?を確認したい。今回は、AXI HPC port を Inner Share として使用するための設定を行う。

参考にするのは、いつもお世話になっております ikwzm さんの”UltraZed 向け Debian GNU/Linux で AXI HPC port を使う (基礎編)”だ。ここに、Zynq UltraScale+ MPSoC(ZynqMP) の PS-PL Interface のShare モードについて詳しく書かれている。
そして、Outer Share はLinux 4.14 で対応していないので、AXI HPC ポートをInner Share に設定する方法が書いてある。それをやってみようと思う。

やり方は、regs.init というファイルを用意する。(詳しい方法は”UltraZed 向け Debian GNU/Linux で AXI HPC port を使う (基礎編)”を参照)

.set. 0xFF41A040 = 0x3;


Ultra96_ikwzm_32_181019.png

boot.bin を生成するのだが、boot.bin は前回”Ultra96用Yocto Linuxのビルドの続き3(boot.binの生成、Linux Kernel のビルド)”で生成した。
その、build_bootbin.bif を下のように書き換えた。

the_ROM_image:
{
  [init] regs.init
  [pmufw_image, destination_cpu=a53-0] pmufw.elf
  [bootloader, destination_cpu=a53-0] fsbl.elf
  [destination_device=pl] ex_board_test_wrapper.bit
  [destination_cpu=a53-0, exception_level=el-3] bl31.elf
  [destination_cpu=a53-0, exception_level=el-2] u-boot.elf
}


次に、boot.bin を生成した。
bootgen -arch zynqmp -image build_bootbin.bif -o i boot.bin -w on -log trace > bootgen_log.txt

boot.bin が生成されて、bootgen_log.txt のログが生成された。
bootgen_log.txt を見てみると、regs.init の記述が取り込まれているのが分かるので大丈夫だろう?
bootgen_log.txt を示す。

[TRACE]  : Command Line parsing started
[TRACE]  : Command: -arch zynqmp -image build_bootbin.bif -o i boot.bin -w on -log trace
[INFO]   : Command line parsing completed successfully
[INFO]   : Bootgen Version - 2017.4, Nov 23, 2017
[TRACE]  : BIF File: build_bootbin.bif
[TRACE]  : BIF file parsing started
[TRACE]  : Creating ZYNQ MP Factory
[INFO]   : Filename: regs.init
[INFO]   : Filename: pmufw.elf
[INFO]   : Filename: fsbl.elf
[INFO]   : Parsing Partition Data
[INFO]   : Filename: ex_board_test_wrapper.bit
[INFO]   : Parsing Partition Data
[INFO]   : Filename: bl31.elf
[INFO]   : Parsing Partition Data
[INFO]   : Filename: u-boot.elf
[INFO]   : Parsing Partition Data
[INFO]   : BIF file parsing completed successfully
[INFO]   : Building image - the_ROM_image
[INFO]   : Started RE parsing : regs.init
[INFO]   : count [0xff41a040], value = 3
[INFO]   : Done RE parsing : regs.init. Added 1 regiter pairs
[TRACE]  : Setting Core as 2
[INFO]   : Building the Partition Header Table
[TRACE]  : Creating ZYNQ MP Factory
[INFO]   : After build 
           -- Dump of Binary Image ----
           00000000 Len: 000008b8 Res: 00000000 "BootHeader"
           00000000 Len: 00000040 Res: 00000000 "ImageHeaderTable"
           00000000 Len: 00000020 Res: 00000000 "ImageHeader fsbl.elf"
           00000000 Len: 00000030 Res: 00000000 "ImageHeader ex_board_test_wrapper.bit"
           00000000 Len: 00000020 Res: 00000000 "ImageHeader bl31.elf"
           00000000 Len: 00000020 Res: 00000740 "ImageHeader u-boot.elf"
           00000000 Len: 00000040 Res: 00000000 "PartitionHeader fsbl.elf.0"
           00000000 Len: 00000040 Res: 00000000 "PartitionHeader ex_board_test_wrapper.bit.0"
           00000000 Len: 00000040 Res: 00000000 "PartitionHeader bl31.elf.0"
           00000000 Len: 00000040 Res: 00000000 "PartitionHeader u-boot.elf.0"
           00000000 Len: 00000040 Res: 00001600 "PartitionHeader Null"
           00000000 Len: 00036dc8 Res: 00000000 "fsbl.elf.0"
           00000000 Len: 0054f89c Res: 00000000 "ex_board_test_wrapper.bit.0"
           00000000 Len: 0000c500 Res: 00000000 "bl31.elf.0"
           00000000 Len: 000b93d8 Res: 00000000 "u-boot.elf.0"
           -- End of Dump
[INFO]   : After align 
           -- Dump of Binary Image ----
           00000000 Len: 000008b8 Res: 00000000 "BootHeader"
           000008c0 Len: 00000040 Res: 00000000 "ImageHeaderTable"
           00000900 Len: 00000020 Res: 00000000 "ImageHeader fsbl.elf"
           00000940 Len: 00000030 Res: 00000000 "ImageHeader ex_board_test_wrapper.bit"
           00000980 Len: 00000020 Res: 00000000 "ImageHeader bl31.elf"
           000009c0 Len: 00000020 Res: 00000740 "ImageHeader u-boot.elf"
           00001100 Len: 00000040 Res: 00000000 "PartitionHeader fsbl.elf.0"
           00001140 Len: 00000040 Res: 00000000 "PartitionHeader ex_board_test_wrapper.bit.0"
           00001180 Len: 00000040 Res: 00000000 "PartitionHeader bl31.elf.0"
           000011c0 Len: 00000040 Res: 00000000 "PartitionHeader u-boot.elf.0"
           00001200 Len: 00000040 Res: 00001600 "PartitionHeader Null"
           00002800 Len: 00036dc8 Res: 00000000 "fsbl.elf.0"
           00039600 Len: 0054f89c Res: 00000000 "ex_board_test_wrapper.bit.0"
           00588ec0 Len: 0000c500 Res: 00000000 "bl31.elf.0"
           005953c0 Len: 000b93d8 Res: 00000000 "u-boot.elf.0"
           -- End of Dump
[INFO]   : Partition Information: 
[INFO]   : Image: fsbl.elf
[INFO]   :      1. Partition: fsbl.elf.0,  Size: 224712
[INFO]   : Image: ex_board_test_wrapper.bit
[INFO]   :      2. Partition: ex_board_test_wrapper.bit.0,  Size: 5568668
[INFO]   : Image: bl31.elf
[INFO]   :      3. Partition: bl31.elf.0,  Size: 50432
[INFO]   : Image: u-boot.elf
[INFO]   :      4. Partition: u-boot.elf.0,  Size: 758744
[INFO]   : After Link 
           -- Dump of Binary Image ----
           00000000 Len: 000008b8 Res: 00000000 "BootHeader"
           000008c0 Len: 00000040 Res: 00000000 "ImageHeaderTable"
           00000900 Len: 00000020 Res: 00000000 "ImageHeader fsbl.elf"
           00000940 Len: 00000030 Res: 00000000 "ImageHeader ex_board_test_wrapper.bit"
           00000980 Len: 00000020 Res: 00000000 "ImageHeader bl31.elf"
           000009c0 Len: 00000020 Res: 00000740 "ImageHeader u-boot.elf"
           00001100 Len: 00000040 Res: 00000000 "PartitionHeader fsbl.elf.0"
           00001140 Len: 00000040 Res: 00000000 "PartitionHeader ex_board_test_wrapper.bit.0"
           00001180 Len: 00000040 Res: 00000000 "PartitionHeader bl31.elf.0"
           000011c0 Len: 00000040 Res: 00000000 "PartitionHeader u-boot.elf.0"
           00001200 Len: 00000040 Res: 00001600 "PartitionHeader Null"
           00002800 Len: 00036dc8 Res: 00000000 "fsbl.elf.0"
           00039600 Len: 0054f89c Res: 00000000 "ex_board_test_wrapper.bit.0"
           00588ec0 Len: 0000c500 Res: 00000000 "bl31.elf.0"
           005953c0 Len: 000b93d8 Res: 00000000 "u-boot.elf.0"
           -- End of Dump


この生成された boot.bin をMicroSD カードの第1パーティションのULTRA96_BOOの boot.bin を交換して、Ultra96 でブートしてみたが、問題なくDebian がブートされて、nautilus や geany も起動した。
Ultra96 ボード用 Debian ROOT FS のLinux起動用MicroSD カード用ファイルの使用方法”のULTRA96_BOOの boot.bin も今回生成した boot.bin に変更した。
  1. 2018年10月19日 05:23 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96 ボード用 Debian ROOT FS のLinux起動用MicroSD カード用ファイルの使用方法

Ultra96 で ikwzm さんのDebian9 Root File Systemを動かしてみる3”のUltra96 ボード用 Debian ROOT FS のLinux起動用MicroSD カード用ファイルの使用方法を書いておく。このファイルは 500 MB 以上あって巨大なので、今のところGoogle ドライブに置いているのだが、そのためもあって公開するかどうか?迷っている。Ultra96 勉強会の参加者には公開しようと思っている。

使用方法だが、まずはMicroSD カードをフォーマットする。”Ultra96用Yocto LinuxのMicroSDカードのフォーマット”を見て、Ubuntu でMicro SD カードをフォーマットして欲しい。
注意点としては、パソコンによってMicroSD カードのドライブが違うと思うので、必ず lsblk でMicroSD カードのドライブ名を確認して欲しい。
MicroSD カードは 8 GB以上のクラス10 相当を使用して欲しい。

まずは指定されたURL を見るとROOT_FS と ULTRA96_BOO の2つのディレクトリがある。(表示をデフォルトからリスト表示に変更しています)
Ultra96_ikwzm_29_181018.png

ULTRA96_BOO には、8 個のファイルがある。Image_org は元のLinux カーネルなのでいらないのだが、一応入れてある。
Ultra96_ikwzm_30_181018.png

ダウンロードすると圧縮ファイルになるが、解凍して、MicroSD カードの第1パーティションの ULTRA96_BOO にコピーする。

次に、ROOT_FS ディレクトリには、debian0-rootfs-vanilla_ultra96.tgz がある。
Ultra96_ikwzm_31_181018.png

これをダウンロードして、MicroSD カードの第2パーティションのROOT_FS に解凍しながら書き込む。
まずは、debian9-rootfs-vanilla_ultra96.tgz があるディレクトリに cd する。使用するコマンドは、私だったら
sudo tar xfz debian9-rootfs-vanilla_ultra96.tgz -C /media/masaaki/ROOT_FS
sync


/media/masaaki/ROOT_FS のパス名は当然ながら変わると思うので、自分のパソコンにマウントされたMicroSD カードの第2パーティションのマウント・パスを指定して欲しい。

これで、全部のファイルをMicroSD カードに書けたので、MicroSD カードのマウントを外す。
Ultra96 ボードにMicroSD カードを挿入して電源ON する。

シリアル・コンソールを開いて、ログイン・プロンプトが出たら、最初は root でログインする。root のパスワードは admin だ。(書いちゃって良いのだろうか?)
ログインしたら、/home/fpga ディレクトリのファイルをすべて、(下位のディレクトリまですべて)のオーナーを fpga に変更する。
chown -R fpga:fpga /home/fpga

そして、
exit
してから、fpga ユーザーで入り直す。パスワードは fpga だ。ただし、勉強会でやるとしたら、fpga ユーザーが参加人数だけいるので、passwd でパスワードを変更しておいたほうが良いと思う。

他人のUltra96 に入りまくってしまうかもしれない?その場合は、いたずらしないように。。。

無線LAN の設定方法は、まずは無線LAN のSSID を確認する。
wpa_passphrase <SSID> <パスフレーズ>
Ultra96_Yocto_57_180921.png

を実行すると、psk に暗号化されたパスフレーズが出力されるので、それをコピーする。
/etc/network/interfaces.d/ ディレクトリに wlan0 があるので、SSID と先程、wpa_passphrase で取得したpsk に書かれた暗号化されたパスフレーズを書き込む。
cd /etc/network/interfaces.d/
sudo vi wlan0

Ultra96_Yocto_58_180921.png

これで無線LAN の設定は終了したので、
sudo reboot
でリブートすれば、無線LAN がつながるはずだ。なお、Bluetooth はつながらない。ファームが失敗しているようだ。
  1. 2018年10月18日 05:10 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96 で ikwzm さんのDebian9 Root File Systemを動かしてみる3

Ultra96 で ikwzm さんのDebian9 Root File Systemを動かしてみる2”の続き。

前回パッケージをインストールしたが、warning が出てしまった。今回は、ikwzm さんの配布しているLinux カーネルに入れ替えて、もう一度パッケージをインストールしてみよう。更に、パッケージのインストールを追加して、nautilus と geany を起動できた。

まずは、Linux カーネルを ikwzm さんのLinux カーネルに変更した。
UltraZed 向け Debian GNU/Linux (v2018.2版) ブートイメージの提供”を git clone したときの ZynqMP-FPGA/target/UltraZed-EG-IOCC/boot/ディレクトリの image-4.14.0-xlnx-v2018.2-zynqmp-fpga の名前を Image に変更して、MicroSD カードの ULTRA96_BOO パーティションのImage と変更した。
MicroSD カードをUltra96 に入れて電源ONしてブートした。
fpga ユーザーでログインして、debian ディレクトリに cd をした。
sudo dpkg -i fclkcfg-4.14.0-xlnx-v2018.2-zynqmp-fpga_1.0.0-1_arm64.deb
sudo dpkg -i udmabuf-4.14.0-xlnx-v2018.2-zynqmp-fpga_1.2.3-1_arm64.deb

共に成功した。
Ultra96_ikwzm_20_181016.png

これが成功したので、
Ultra96用Yocto Linuxのビルドの続き6(WLANの設定)
”Ultra96用Yocto Linuxのビルドの続き7(WLANの設定2)
の設定を行って無線LAN を設定した。

リブートしてから、ip addr show を実行すると、 wlan0 に IP アドレスが割り振られていた。成功だ。
Ultra96_ikwzm_21_181016.png

これで apt が使用できるようなったので、
sudo apt update
Ultra96_ikwzm_22_181016.png

sudo apt upgrade
Ultra96_ikwzm_23_181016.png

xbase-clients xterm をインストールした。
sudo apt install xbase-clients xterm
Ultra96_ikwzm_24_181016.png

Ubuntu 18.04 のパソコンから Ultra96 のDebian に ssh ログインを行った。
ssh 192.168.3.28 -X -l fpga
だがホスト・キーの関係でログインできなかった。
Ultra96_ikwzm_25_181016.png

ホスト・キーを
ssh-keygen -f "/home/masaaki/.ssh/known_hosts" -R "192.168.3.28"
で削除してもう一度
ssh 192.168.3.28 -X -l fpga
でログインできた。
Ultra96_ikwzm_26_181016.png

次に、nautilus と geany を X window で起動しよう。
sudo apt install nautilus
nautilus &
で nauitlus は起動したが、日本語フォントが入っていないので、文字がトーフになっている。

そこで、日本語フォントをインストールした。
sudo apt install fonts-vlgothic
sudo apt install fonts-horai-umefont
sudo apt install fonts-umeplus


これで nautilus &
で nauitlus を起動するときちんと表示できてる。
Ultra96_ikwzm_27_181016.png

sudo apt install geany
で geany をインストールした。
geany & で起動すると起動できた。
Ultra96_ikwzm_28_181016.png

最後に起動メッセージを貼っておく。

PMUFW: v1.0


U-Boot 2018.01 (Sep 14 2018 - 20:02:18 +0900) Xilinx ZynqMP ZCU100 RevC

I2C:   ready
DRAM:  2 GiB
EL Level: EL2
Chip ID: zu3eg
MMC:   sdhci@ff160000: 0 (SD), sdhci@ff170000: 1
Using default environment

In:    serial@ff010000
Out:   serial@ff010000
Err:   serial@ff010000
Bootmode: SD_MODE
Net:   Net Initialization Skipped
No ethernet found.
Hit any key to stop autoboot:  0 
switch to partitions #0, OK
mmc0 is current device
Device: sdhci@ff160000
Manufacturer ID: 9f
OEM: 5449
Name: SPCCTran Speed: 25000000
Rd Block Len: 512
SD version 3.0
High Capacity: Yes
Capacity: 14.6 GiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes
reading uEnv.txt
456 bytes read in 10 ms (43.9 KiB/s)
Loaded environment from uEnv.txt
Importing environment from SD ...
Running uenvcmd ...
reading Image
14215680 bytes read in 1285 ms (10.5 MiB/s)
** No boot file defined **
reading system.dtb
33477 bytes read in 19 ms (1.7 MiB/s)
reading Image
14215680 bytes read in 1283 ms (10.6 MiB/s)
## Flattened Device Tree blob at 04000000
   Booting using the fdt blob at 0x4000000
   Loading Device Tree to 000000000fff4000, end 000000000ffff2c4 ... OK

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.14.0-xlnx-v2018.2-zynqmp-fpga (ichiro@sphinx-vm-ubuntu) (gcc version 5.4.0 20160609 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9)) #1 SMP Fri Aug 10 11:05:02 JST 2018
[    0.000000] Boot CPU: AArch64 Processor [410fd034]
[    0.000000] Machine model: ZynqMP ZCU100 RevC
[    0.000000] earlycon: cdns0 at MMIO 0x00000000ff010000 (options '115200n8')
[    0.000000] bootconsole [cdns0] enabled
[    0.000000] efi: Getting EFI parameters from FDT:
[    0.000000] efi: UEFI not found.
[    0.000000] cma: Reserved 256 MiB at 0x0000000070000000
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv1.1 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: MIGRATE_INFO_TYPE not supported.
[    0.000000] random: fast init done
[    0.000000] percpu: Embedded 21 pages/cpu @ffffffc06ff71000 s45080 r8192 d32744 u86016
[    0.000000] Detected VIPT I-cache on CPU0
[    0.000000] CPU features: enabling workaround for ARM erratum 845719
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 517120
[    0.000000] Kernel command line: earlycon clk_ignore_unused root=/dev/mmcblk0p2 rw rootwait root=/dev/mmcblk0p2 rw rootwait
[    0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes)
[    0.000000] Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes)
[    0.000000] Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes)
[    0.000000] Memory: 1786564K/2097152K available (9596K kernel code, 634K rwdata, 3092K rodata, 512K init, 2158K bss, 48444K reserved, 262144K cma-reserved)
[    0.000000] Virtual kernel memory layout:
[    0.000000]     modules : 0xffffff8000000000 - 0xffffff8008000000   (   128 MB)
[    0.000000]     vmalloc : 0xffffff8008000000 - 0xffffffbebfff0000   (   250 GB)
[    0.000000]       .text : 0xffffff8008080000 - 0xffffff80089e0000   (  9600 KB)
[    0.000000]     .rodata : 0xffffff80089e0000 - 0xffffff8008cf0000   (  3136 KB)
[    0.000000]       .init : 0xffffff8008cf0000 - 0xffffff8008d70000   (   512 KB)
[    0.000000]       .data : 0xffffff8008d70000 - 0xffffff8008e0ea00   (   635 KB)
[    0.000000]        .bss : 0xffffff8008e0ea00 - 0xffffff800902a238   (  2159 KB)
[    0.000000]     fixed   : 0xffffffbefe7fd000 - 0xffffffbefec00000   (  4108 KB)
[    0.000000]     PCI I/O : 0xffffffbefee00000 - 0xffffffbeffe00000   (    16 MB)
[    0.000000]     vmemmap : 0xffffffbf00000000 - 0xffffffc000000000   (     4 GB maximum)
[    0.000000]               0xffffffbf00000000 - 0xffffffbf01c00000   (    28 MB actual)
[    0.000000]     memory  : 0xffffffc000000000 - 0xffffffc080000000   (  2048 MB)
[    0.000000] Hierarchical RCU implementation.
[    0.000000]  RCU event tracing is enabled.
[    0.000000]  RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
[    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] GIC: Adjusting CPU interface base to 0x00000000f902f000
[    0.000000] GIC: Using split EOI/Deactivate mode
[    0.000000] arch_timer: cp15 timer(s) running at 100.00MHz (phys).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x171024ee1c, max_idle_ns: 440795203561 ns
[    0.000004] sched_clock: 56 bits at 100MHz, resolution 10ns, wraps every 4398046511100ns
[    0.008389] Console: colour dummy device 80x25
[    0.012645] console [tty0] enabled
[    0.016010] bootconsole [cdns0] disabled
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.14.0-xlnx-v2018.2-zynqmp-fpga (ichiro@sphinx-vm-ubuntu) (gcc version 5.4.0 20160609 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9)) #1 SMP Fri Aug 10 11:05:02 JST 2018
[    0.000000] Boot CPU: AArch64 Processor [410fd034]
[    0.000000] Machine model: ZynqMP ZCU100 RevC
[    0.000000] earlycon: cdns0 at MMIO 0x00000000ff010000 (options '115200n8')
[    0.000000] bootconsole [cdns0] enabled
[    0.000000] efi: Getting EFI parameters from FDT:
[    0.000000] efi: UEFI not found.
[    0.000000] cma: Reserved 256 MiB at 0x0000000070000000
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv1.1 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: MIGRATE_INFO_TYPE not supported.
[    0.000000] random: fast init done
[    0.000000] percpu: Embedded 21 pages/cpu @ffffffc06ff71000 s45080 r8192 d32744 u86016
[    0.000000] Detected VIPT I-cache on CPU0
[    0.000000] CPU features: enabling workaround for ARM erratum 845719
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 517120
[    0.000000] Kernel command line: earlycon clk_ignore_unused root=/dev/mmcblk0p2 rw rootwait root=/dev/mmcblk0p2 rw rootwait
[    0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes)
[    0.000000] Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes)
[    0.000000] Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes)
[    0.000000] Memory: 1786564K/2097152K available (9596K kernel code, 634K rwdata, 3092K rodata, 512K init, 2158K bss, 48444K reserved, 262144K cma-reserved)
[    0.000000] Virtual kernel memory layout:
[    0.000000]     modules : 0xffffff8000000000 - 0xffffff8008000000   (   128 MB)
[    0.000000]     vmalloc : 0xffffff8008000000 - 0xffffffbebfff0000   (   250 GB)
[    0.000000]       .text : 0xffffff8008080000 - 0xffffff80089e0000   (  9600 KB)
[    0.000000]     .rodata : 0xffffff80089e0000 - 0xffffff8008cf0000   (  3136 KB)
[    0.000000]       .init : 0xffffff8008cf0000 - 0xffffff8008d70000   (   512 KB)
[    0.000000]       .data : 0xffffff8008d70000 - 0xffffff8008e0ea00   (   635 KB)
[    0.000000]        .bss : 0xffffff8008e0ea00 - 0xffffff800902a238   (  2159 KB)
[    0.000000]     fixed   : 0xffffffbefe7fd000 - 0xffffffbefec00000   (  4108 KB)
[    0.000000]     PCI I/O : 0xffffffbefee00000 - 0xffffffbeffe00000   (    16 MB)
[    0.000000]     vmemmap : 0xffffffbf00000000 - 0xffffffc000000000   (     4 GB maximum)
[    0.000000]               0xffffffbf00000000 - 0xffffffbf01c00000   (    28 MB actual)
[    0.000000]     memory  : 0xffffffc000000000 - 0xffffffc080000000   (  2048 MB)
[    0.000000] Hierarchical RCU implementation.
[    0.000000]  RCU event tracing is enabled.
[    0.000000]  RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
[    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] GIC: Adjusting CPU interface base to 0x00000000f902f000
[    0.000000] GIC: Using split EOI/Deactivate mode
[    0.000000] arch_timer: cp15 timer(s) running at 100.00MHz (phys).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x171024ee1c, max_idle_ns: 440795203561 ns
[    0.000004] sched_clock: 56 bits at 100MHz, resolution 10ns, wraps every 4398046511100ns
[    0.008389] Console: colour dummy device 80x25
[    0.012645] console [tty0] enabled
[    0.016010] bootconsole [cdns0] disabled
[    0.019923] Calibrating delay loop (skipped), value calculated using timer frequency.. 200.00 BogoMIPS (lpj=400000)
[    0.019936] pid_max: default: 32768 minimum: 301
[    0.020054] Mount-cache hash table entries: 4096 (order: 3, 32768 bytes)
[    0.020071] Mountpoint-cache hash table entries: 4096 (order: 3, 32768 bytes)
[    0.020796] ASID allocator initialised with 65536 entries
[    0.020849] Hierarchical SRCU implementation.
[    0.021187] EFI services will not be available.
[    0.021223] zynqmp_plat_init Platform Management API v1.0
[    0.021231] zynqmp_plat_init Trustzone version v1.0
[    0.021339] smp: Bringing up secondary CPUs ...
[    0.021625] Detected VIPT I-cache on CPU1
[    0.021662] CPU1: Booted secondary processor [410fd034]
[    0.021963] Detected VIPT I-cache on CPU2
[    0.021981] CPU2: Booted secondary processor [410fd034]
[    0.022261] Detected VIPT I-cache on CPU3
[    0.022279] CPU3: Booted secondary processor [410fd034]
[    0.022320] smp: Brought up 1 node, 4 CPUs
[    0.022348] SMP: Total of 4 processors activated.
[    0.022357] CPU features: detected feature: 32-bit EL0 Support
[    0.022368] CPU: All CPU(s) started at EL2
[    0.022384] alternatives: patching kernel code
[    0.023376] devtmpfs: initialized
[    0.027735] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.027763] futex hash table entries: 1024 (order: 5, 131072 bytes)
[    0.033815] xor: measuring software checksum speed
[    0.072016]    8regs     :  2234.000 MB/sec
[    0.112047]    8regs_prefetch:  2053.000 MB/sec
[    0.152079]    32regs    :  2727.000 MB/sec
[    0.192110]    32regs_prefetch:  2381.000 MB/sec
[    0.192118] xor: using function: 32regs (2727.000 MB/sec)
[    0.192212] pinctrl core: initialized pinctrl subsystem
[    0.192917] NET: Registered protocol family 16
[    0.193684] cpuidle: using governor menu
[    0.194304] vdso: 2 pages (1 code @ ffffff80089e6000, 1 data @ ffffff8008d74000)
[    0.194322] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[    0.194927] DMA: preallocated 256 KiB pool for atomic allocations
[    0.226696] zynqmp-pinctrl pinctrl: zynqmp pinctrl initialized
[    0.227579] reset_zynqmp reset-controller: Xilinx zynqmp reset driver probed
[    0.228106] ARM CCI_400_r1 PMU driver probed
[    0.237977] HugeTLB registered 2.00 MiB page size, pre-allocated 0 pages
[    0.304285] raid6: int64x1  gen()   402 MB/s
[    0.372376] raid6: int64x1  xor()   431 MB/s
[    0.440440] raid6: int64x2  gen()   666 MB/s
[    0.508470] raid6: int64x2  xor()   593 MB/s
[    0.576523] raid6: int64x4  gen()  1032 MB/s
[    0.644566] raid6: int64x4  xor()   750 MB/s
[    0.712624] raid6: int64x8  gen()  1096 MB/s
[    0.780678] raid6: int64x8  xor()   724 MB/s
[    0.848771] raid6: neonx1   gen()   717 MB/s
[    0.916774] raid6: neonx1   xor()   833 MB/s
[    0.984853] raid6: neonx2   gen()  1155 MB/s
[    1.052881] raid6: neonx2   xor()  1187 MB/s
[    1.120954] raid6: neonx4   gen()  1502 MB/s
[    1.189002] raid6: neonx4   xor()  1428 MB/s
[    1.257075] raid6: neonx8   gen()  1660 MB/s
[    1.325116] raid6: neonx8   xor()  1526 MB/s
[    1.325123] raid6: using algorithm neonx8 gen() 1660 MB/s
[    1.325130] raid6: .... xor() 1526 MB/s, rmw enabled
[    1.325138] raid6: using neon recovery algorithm
[    1.326202] SCSI subsystem initialized
[    1.326381] usbcore: registered new interface driver usbfs
[    1.326416] usbcore: registered new interface driver hub
[    1.326457] usbcore: registered new device driver usb
[    1.326532] media: Linux media interface: v0.10
[    1.326559] Linux video capture interface: v2.00
[    1.326602] pps_core: LinuxPPS API ver. 1 registered
[    1.326610] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    1.326632] PTP clock support registered
[    1.326661] EDAC MC: Ver: 3.0.0
[    1.327163] zynqmp-ipi ff9905c0.mailbox: Probed ZynqMP IPI Mailbox driver.
[    1.327306] FPGA manager framework
[    1.327422] fpga-region fpga-full: FPGA Region probed
[    1.327512] Advanced Linux Sound Architecture Driver Initialized.
[    1.327828] Bluetooth: Core ver 2.22
[    1.327858] NET: Registered protocol family 31
[    1.327865] Bluetooth: HCI device and connection manager initialized
[    1.327879] Bluetooth: HCI socket layer initialized
[    1.327889] Bluetooth: L2CAP socket layer initialized
[    1.327916] Bluetooth: SCO socket layer initialized
[    1.328595] clocksource: Switched to clocksource arch_sys_counter
[    1.328688] VFS: Disk quotas dquot_6.6.0
[    1.328736] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[    1.334015] NET: Registered protocol family 2
[    1.334382] TCP established hash table entries: 16384 (order: 5, 131072 bytes)
[    1.334497] TCP bind hash table entries: 16384 (order: 6, 262144 bytes)
[    1.334821] TCP: Hash tables configured (established 16384 bind 16384)
[    1.334920] UDP hash table entries: 1024 (order: 3, 32768 bytes)
[    1.334965] UDP-Lite hash table entries: 1024 (order: 3, 32768 bytes)
[    1.335105] NET: Registered protocol family 1
[    1.335315] RPC: Registered named UNIX socket transport module.
[    1.335324] RPC: Registered udp transport module.
[    1.335331] RPC: Registered tcp transport module.
[    1.335337] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    1.335924] hw perfevents: no interrupt-affinity property for /pmu, guessing.
[    1.336093] hw perfevents: enabled with armv8_pmuv3 PMU driver, 7 counters available
[    1.336835] audit: initializing netlink subsys (disabled)
[    1.337271] audit: type=2000 audit(1.323:1): state=initialized audit_enabled=0 res=1
[    1.337318] workingset: timestamp_bits=62 max_order=19 bucket_order=0
[    1.338089] NFS: Registering the id_resolver key type
[    1.338114] Key type id_resolver registered
[    1.338121] Key type id_legacy registered
[    1.338134] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
[    1.338158] jffs2: version 2.2. (NAND) (SUMMARY)  © 2001-2006 Red Hat, Inc.
[    1.363663] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 246)
[    1.363683] io scheduler noop registered
[    1.363691] io scheduler deadline registered
[    1.363709] io scheduler cfq registered (default)
[    1.363718] io scheduler mq-deadline registered
[    1.363725] io scheduler kyber registered
[    1.364987] xilinx-dpdma fd4c0000.dma: Xilinx DPDMA engine is probed
[    1.391678] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    1.394681] cacheinfo: Unable to detect cache hierarchy for CPU 0
[    1.399359] brd: module loaded
[    1.403408] loop: module loaded
[    1.404154] mtdoops: mtd device (mtddev=name/number) must be supplied
[    1.406778] libphy: Fixed MDIO Bus: probed
[    1.407821] tun: Universal TUN/TAP device driver, 1.6
[    1.408030] CAN device driver interface
[    1.408824] usbcore: registered new interface driver asix
[    1.408893] usbcore: registered new interface driver ax88179_178a
[    1.408925] usbcore: registered new interface driver cdc_ether
[    1.408956] usbcore: registered new interface driver net1080
[    1.408987] usbcore: registered new interface driver cdc_subset
[    1.409017] usbcore: registered new interface driver zaurus
[    1.409059] usbcore: registered new interface driver cdc_ncm
[    1.409444] xilinx-axipmon ffa00000.perf-monitor: Probed Xilinx APM
[    1.411593] usbcore: registered new interface driver uas
[    1.411634] usbcore: registered new interface driver usb-storage
[    1.412167] rtc_zynqmp ffa60000.rtc: rtc core: registered ffa60000.rtc as rtc0
[    1.412224] i2c /dev entries driver
[    1.412907] IR NEC protocol handler initialized
[    1.412917] IR RC5(x/sz) protocol handler initialized
[    1.412924] IR RC6 protocol handler initialized
[    1.412930] IR JVC protocol handler initialized
[    1.412937] IR Sony protocol handler initialized
[    1.412944] IR SANYO protocol handler initialized
[    1.412951] IR Sharp protocol handler initialized
[    1.412958] IR MCE Keyboard/mouse protocol handler initialized
[    1.412965] IR XMP protocol handler initialized
[    1.413823] usbcore: registered new interface driver uvcvideo
[    1.413832] USB Video Class driver (1.1.1)
[    1.413896] ltc2952-poweroff ltc2954: pm_power_off already registered
[    1.413910] ltc2952-poweroff: probe of ltc2954 failed with error -16
[    1.414840] cdns-wdt fd4d0000.watchdog: Xilinx Watchdog Timer at ffffff8009035000 with timeout 10s
[    1.415017] Bluetooth: HCI UART driver ver 2.3
[    1.415028] Bluetooth: HCI UART protocol H4 registered
[    1.415036] Bluetooth: HCI UART protocol BCSP registered
[    1.415067] Bluetooth: HCI UART protocol LL registered
[    1.415074] Bluetooth: HCI UART protocol ATH3K registered
[    1.415082] Bluetooth: HCI UART protocol Three-wire (H5) registered
[    1.415124] Bluetooth: HCI UART protocol Intel registered
[    1.415132] Bluetooth: HCI UART protocol QCA registered
[    1.415172] usbcore: registered new interface driver bcm203x
[    1.415206] usbcore: registered new interface driver bpa10x
[    1.415243] usbcore: registered new interface driver bfusb
[    1.415277] usbcore: registered new interface driver btusb
[    1.415285] Bluetooth: Generic Bluetooth SDIO driver ver 0.1
[    1.415338] usbcore: registered new interface driver ath3k
[    1.415451] EDAC MC: ECC not enabled
[    1.415596] EDAC DEVICE0: Giving out device to module zynqmp-ocm-edac controller zynqmp_ocm: DEV ff960000.memory-controller (INTERRUPT)
[    1.416640] sdhci: Secure Digital Host Controller Interface driver
[    1.416649] sdhci: Copyright(c) Pierre Ossman
[    1.416656] sdhci-pltfm: SDHCI platform and OF driver helper
[    1.417987] ledtrig-cpu: registered to indicate activity on CPUs
[    1.418149] usbcore: registered new interface driver usbhid
[    1.418157] usbhid: USB HID core driver
[    1.419536] fpga_manager fpga0: Xilinx ZynqMP FPGA Manager registered
[    1.420280] pktgen: Packet Generator for packet performance testing. Version: 2.75
[    1.420559] Netfilter messages via NETLINK v0.30.
[    1.420734] ip_tables: (C) 2000-2006 Netfilter Core Team
[    1.420901] Initializing XFRM netlink socket
[    1.420977] NET: Registered protocol family 10
[    1.421412] Segment Routing with IPv6
[    1.421463] ip6_tables: (C) 2000-2006 Netfilter Core Team
[    1.421592] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    1.421945] NET: Registered protocol family 17
[    1.421962] NET: Registered protocol family 15
[    1.421985] bridge: filtering via arp/ip/ip6tables is no longer available by default. Update your scripts to load br_netfilter if you need this.
[    1.421998] Ebtables v2.0 registered
[    1.422088] can: controller area network core (rev 20170425 abi 9)
[    1.422136] NET: Registered protocol family 29
[    1.422145] can: raw protocol (rev 20170425)
[    1.422153] can: broadcast manager protocol (rev 20170425 t)
[    1.422163] can: netlink gateway (rev 20170425) max_hops=1
[    1.422435] Bluetooth: RFCOMM TTY layer initialized
[    1.422450] Bluetooth: RFCOMM socket layer initialized
[    1.422467] Bluetooth: RFCOMM ver 1.11
[    1.422483] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[    1.422491] Bluetooth: BNEP filters: protocol multicast
[    1.422500] Bluetooth: BNEP socket layer initialized
[    1.422508] Bluetooth: HIDP (Human Interface Emulation) ver 1.2
[    1.422518] Bluetooth: HIDP socket layer initialized
[    1.422639] 9pnet: Installing 9P2000 support
[    1.422665] Key type dns_resolver registered
[    1.423125] registered taskstats version 1
[    1.423472] Btrfs loaded, crc32c=crc32c-generic
[    1.430537] ff000000.serial: ttyPS1 at MMIO 0xff000000 (irq = 24, base_baud = 6249999) is a xuartps
[    1.430743] serial serial0: tty port ttyPS1 registered
[    1.431111] ff010000.serial: ttyPS0 at MMIO 0xff010000 (irq = 25, base_baud = 6249999) is a xuartps
[    2.799922] console [ttyPS0] enabled
[    2.805168] xilinx-psgtr fd400000.zynqmp_phy: Lane:1 type:8 protocol:4 pll_locked:yes
[    2.813338] PLL: shutdown
[    2.816004] PLL: shutdown
[    2.819001] PLL: enable
[    2.821502] PLL: shutdown
[    2.825135] PLL: enable
[    2.827601] xilinx-dp-snd-codec fd4a0000.zynqmp-display:zynqmp_dp_snd_codec0: Xilinx DisplayPort Sound Codec probed
[    2.838219] xilinx-dp-snd-pcm zynqmp_dp_snd_pcm0: Xilinx DisplayPort Sound PCM probed
[    2.846185] xilinx-dp-snd-pcm zynqmp_dp_snd_pcm1: Xilinx DisplayPort Sound PCM probed
[    2.854539] xilinx-dp-snd-card fd4a0000.zynqmp-display:zynqmp_dp_snd_card: xilinx-dp-snd-codec-dai <-> xilinx-dp-snd-codec-dai mapping ok
[    2.866905] xilinx-dp-snd-card fd4a0000.zynqmp-display:zynqmp_dp_snd_card: xilinx-dp-snd-codec-dai <-> xilinx-dp-snd-codec-dai mapping ok
[    2.879562] xilinx-dp-snd-card fd4a0000.zynqmp-display:zynqmp_dp_snd_card: Xilinx DisplayPort Sound Card probed
[    2.889688] OF: graph: no port node found in /amba/zynqmp-display@fd4a0000
[    2.896651] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[    2.903180] [drm] No driver support for vblank timestamp query.
[    2.909162] xlnx-drm xlnx-drm.0: bound fd4a0000.zynqmp-display (ops 0xffffff8008a97538)
[    3.011076] PLL: enable
[    3.139323] Console: switching to colour frame buffer device 240x67
[    3.164688] zynqmp-display fd4a0000.zynqmp-display: fb0:  frame buffer device
[    3.172028] [drm] Initialized xlnx 1.0.0 20130509 for fd4a0000.zynqmp-display on minor 0
[    3.180138] zynqmp-display fd4a0000.zynqmp-display: ZynqMP DisplayPort Subsystem driver probed
[    3.190856] xilinx-psgtr fd400000.zynqmp_phy: Lane:2 type:0 protocol:3 pll_locked:yes
[    3.201204] xilinx-psgtr fd400000.zynqmp_phy: Lane:3 type:1 protocol:3 pll_locked:yes
[    3.209288] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller
[    3.214773] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 1
[    3.222677] xhci-hcd xhci-hcd.0.auto: hcc params 0x0238f625 hci version 0x100 quirks 0x22010010
[    3.231412] xhci-hcd xhci-hcd.0.auto: irq 33, io mem 0xfe300000
[    3.237432] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
[    3.244206] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    3.251410] usb usb1: Product: xHCI Host Controller
[    3.256248] usb usb1: Manufacturer: Linux 4.14.0-xlnx-v2018.2-zynqmp-fpga xhci-hcd
[    3.263823] usb usb1: SerialNumber: xhci-hcd.0.auto
[    3.268983] hub 1-0:1.0: USB hub found
[    3.272711] hub 1-0:1.0: 1 port detected
[    3.276790] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller
[    3.282250] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 2
[    3.289944] usb usb2: We don't know the algorithms for LPM for this host, disabling LPM.
[    3.298103] usb usb2: New USB device found, idVendor=1d6b, idProduct=0003
[    3.304878] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    3.312082] usb usb2: Product: xHCI Host Controller
[    3.316921] usb usb2: Manufacturer: Linux 4.14.0-xlnx-v2018.2-zynqmp-fpga xhci-hcd
[    3.324496] usb usb2: SerialNumber: xhci-hcd.0.auto
[    3.329583] hub 2-0:1.0: USB hub found
[    3.333302] hub 2-0:1.0: 1 port detected
[    3.338889] i2c i2c-0: Added multiplexed i2c bus 2
[    3.343780] i2c i2c-0: Added multiplexed i2c bus 3
[    3.348672] i2c i2c-0: Added multiplexed i2c bus 4
[    3.353565] i2c i2c-0: Added multiplexed i2c bus 5
[    3.359297] tps65086 6-005e: Device: TPS650864, OTP: C, Rev: 0
[    3.371596] i2c i2c-0: Added multiplexed i2c bus 6
[    3.377729] ina2xx 7-0040: power monitor ina226 (Rshunt = 10000 uOhm)
[    3.384178] i2c i2c-0: Added multiplexed i2c bus 7
[    3.389068] i2c i2c-0: Added multiplexed i2c bus 8
[    3.393967] i2c i2c-0: Added multiplexed i2c bus 9
[    3.398724] pca954x 0-0075: registered 8 multiplexed busses for I2C switch pca9548
[    3.406325] cdns-i2c ff030000.i2c: 100 kHz mmio ff030000 irq 15
[    3.460603] mmc0: SDHCI controller on ff160000.sdhci [ff160000.sdhci] using ADMA 64-bit
[    3.475045] sdhci-arasan ff170000.sdhci: allocated mmc-pwrseq
[    3.517782] mmc0: Problem switching card into high-speed mode!
[    3.526826] mmc1: SDHCI controller on ff170000.sdhci [ff170000.sdhci] using ADMA 64-bit
[    3.538308] mmc0: new SDHC card at address 0001
[    3.546853] mmcblk0: mmc0:0001 SPCC 14.6 GiB 
[    3.547904] input: gpio-keys as /devices/platform/gpio-keys/input/input0
[    3.564305] rtc_zynqmp ffa60000.rtc: setting system clock to 2018-10-16 20:04:02 UTC (1539720242)
[    3.566501]  mmcblk0: p1 p2
[    3.569300] sdhci-arasan ff170000.sdhci: card claims to support voltages below defined range
[    3.581743] mmc1: new high speed SDIO card at address 0001
[    3.582518] wl18xx_driver wl18xx.3.auto: Direct firmware load for ti-connectivity/wl1271-nvs.bin failed with error -2
[    3.582552] wl18xx_driver wl18xx.3.auto: Direct firmware load for ti-connectivity/wl18xx-conf.bin failed with error -2
[    3.582556] wlcore: ERROR could not get configuration binary ti-connectivity/wl18xx-conf.bin: -2
[    3.582558] wlcore: WARNING falling back to default config
[    3.644604] usb 1-1: new high-speed USB device number 2 using xhci-hcd
[    3.661907] of_cfs_init
[    3.667655] of_cfs_init: OK
[    3.673792] clk: Not disabling unused clocks
[    3.681332] ALSA device list:
[    3.687454]   #0: DisplayPort monitor
[    3.695749] EXT4-fs (mmcblk0p2): couldn't mount as ext3 due to feature incompatibilities
[    3.735050] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
[    3.746340] VFS: Mounted root (ext4 filesystem) on device 179:2.
[    3.775876] devtmpfs: mounted
[    3.782242] Freeing unused kernel memory: 512K
[    3.801097] usb 1-1: New USB device found, idVendor=0424, idProduct=2744
[    3.810973] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[    3.821264] usb 1-1: Product: USB2744
[    3.828048] usb 1-1: Manufacturer: Microchip Tech
[    3.866064] hub 1-1:1.0: USB hub found
[    3.872951] hub 1-1:1.0: 4 ports detected
[    3.880468] wlcore: wl18xx HW: 183x or 180x, PG 2.2 (ROM 0x11)
[    3.892886] wlcore: loaded
[    3.932648] usb 2-1: new SuperSpeed USB device number 2 using xhci-hcd
[    3.960969] usb 2-1: New USB device found, idVendor=0424, idProduct=5744
[    3.970719] usb 2-1: New USB device strings: Mfr=2, Product=3, SerialNumber=0
[    3.980890] usb 2-1: Product: USB5744
[    3.987556] usb 2-1: Manufacturer: Microchip Tech
[    4.010048] hub 2-1:1.0: USB hub found
[    4.016814] hub 2-1:1.0: 3 ports detected
[    4.136608] Bluetooth: hci0: change remote baud rate command in firmware
[    4.184607] usb 1-1.4: new high-speed USB device number 3 using xhci-hcd
[    4.293311] usb 1-1.4: New USB device found, idVendor=0424, idProduct=2740
[    4.303224] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[    4.313547] usb 1-1.4: Product: Hub Controller
[    4.320995] usb 1-1.4: Manufacturer: Microchip Tech
[    5.051201] systemd[1]: systemd 232 running in system mode. (+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
[    5.072790] systemd[1]: Detected architecture arm64.

Welcome to Debian GNU/Linux 9 (stretch)!

[    5.133960] systemd[1]: Set hostname to <debian-fpga>.
[    5.822449] systemd[1]: Started Forward Password Requests to Wall Directory Watch.
[  OK  ] Started Forward Password Requests to Wall Directory Watch.
[    5.848841] systemd[1]: Listening on udev Control Socket.
[  OK  ] Listening on udev Control Socket.
[    5.868844] systemd[1]: Created slice User and Session Slice.
[  OK  ] Created slice User and Session Slice.
[    5.888736] systemd[1]: Listening on /dev/initctl Compatibility Named Pipe.
[  OK  ] Listening on /dev/initctl Compatibility Named Pipe.
[    5.916654] systemd[1]: Reached target Remote File Systems.
[  OK  ] Reached target Remote File Systems.
[    5.936729] systemd[1]: Listening on Journal Socket (/dev/log).
[  OK  ] Listening on Journal Socket (/dev/log).
[    5.956867] systemd[1]: Listening on Journal Audit Socket.
[  OK  ] Listening on Journal Audit Socket.
[  OK  ] Created slice System Slice.
[  OK  ] Created slice system-serial\x2dgetty.slice.
         Mounting Debug File System...
[  OK  ] Reached target Slices.
         Mounting POSIX Message Queue File System...
[  OK  ] Created slice system-getty.slice.
[  OK  ] Listening on Journal Socket.
         Starting Remount Root and Kernel File Systems...
         Starting Load Kernel Modules...
         Starting Nameserver information manager...
[  OK  ] Listening on Syslog Socket.
         Starting Journal Service...
[  OK  ] Reached target Swap.
         Starting Create Static Device Nodes in /dev...
[  OK  ] Listening on udev Kernel Socket.
[  OK  ] Started Dispatch Password Requests to Console Directory Watch.
[  OK  ] Reached target Paths.
[  OK  ] Reached target Encrypted Volumes.
[  OK  ] Mounted Debug File System.
[  OK  ] Mounted POSIX Message Queue File System.
[  OK  ] Started Journal Service.
[  OK  ] Started Remount Root and Kernel File Systems.
[  OK  ] Started Load Kernel Modules.
         Mounting Configuration File System...
         Starting Apply Kernel Variables...
         Starting Load/Save Random Seed...
         Starting udev Coldplug all Devices...
         Starting Flush Journal to Persistent Storage...
[  OK  ] Mounted Configuration File System.
[  OK  ] Started Nameserver information manager.
[  OK  ] Started Apply Kernel Variables.
[    6.476264] systemd-journald[1713]: Received request to flush runtime journal from PID 1
[  OK  ] Started Create Static Device Nodes in /dev.
[  OK  ] Started Flush Journal to Persistent Storage.
[  OK  ] Started Load/Save Random Seed.
[  OK  ] Reached target Local File Systems (Pre).
         Mounting /config...
         Starting udev Kernel Device Manager...
[  OK  ] Mounted /config.
[  OK  ] Started udev Coldplug all Devices.
[  OK  ] Started udev Kernel Device Manager.
[  OK  ] Found device /dev/ttyPS0.
[  OK  ] Reached target Bluetooth.
[  OK  ] Reached target Sound Card.
[  OK  ] Listening on Load/Save RF Kill Switch Status /dev/rfkill Watch.
         Starting Load/Save RF Kill Switch Status...
[  OK  ] Found device /dev/mmcblk0p1.
         Mounting /boot...
[  OK  ] Started Load/Save RF Kill Switch Status.
[    8.033186] FAT-fs (mmcblk0p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.
[  OK  ] Mounted /boot.
[  OK  ] Reached target Local File Systems.
         Starting Raise network interfaces...
         Starting Create Volatile Files and Directories...
[  OK  ] Started Create Volatile Files and Directories.
[  OK  ] Reached target System Time Synchronized.
         Starting Update UTMP about System Boot/Shutdown...
[  OK  ] Started Update UTMP about System Boot/Shutdown.
[  OK  ] Reached target System Initialization.
[  OK  ] Started Daily Cleanup of Temporary Directories.
[  OK  ] Started Daily apt download activities.
[  OK  ] Started Daily apt upgrade and clean activities.
[  OK  ] Reached target Timers.
[  OK  ] Listening on Avahi mDNS/DNS-SD Stack Activation Socket.
[  OK  ] Listening on D-Bus System Message Bus Socket.
[  OK  ] Reached target Sockets.
[  OK  ] Reached target Basic System.
         Starting System Logging Service...
[  OK  ] Started Regular background program processing daemon.
[  OK  ] Started D-Bus System Message Bus.
[    8.684616] Bluetooth: hci0 command 0xff05 tx timeout
         Starting Avahi mDNS/DNS-SD Stack...
         Starting Login Service...
[  OK  ] Started System Logging Service.
[  OK  ] Started Login Service.
[  OK  ] Started Avahi mDNS/DNS-SD Stack.
[   10.106853] wlcore: PHY firmware version: Rev 8.2.0.0.242
[   10.206898] wlcore: firmware booted (Rev 8.9.0.0.79)
[   10.222115] IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready
[*     ] A start job is running for Raise network interfaces (8s / 5min 2s)[   14.601057] wlan0: authenticate with 84:af:ec:c5:f2:20
[   14.611769] wlan0: send auth to 84:af:ec:c5:f2:20 (try 1/3)
[   14.641521] wlan0: authenticated
[   14.648609] wlan0: associate with 84:af:ec:c5:f2:20 (try 1/3)
[   14.661736] wlan0: RX AssocResp from 84:af:ec:c5:f2:20 (capab=0x411 status=0 aid=1)
[   14.677201] wlan0: associated
[   14.683609] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
[   14.712713] wlcore: Association completed.
[  *** ] A start job is running for Raise network interfaces (10s / 5min 2s)[   16.876615] Bluetooth: hci0: send command failed
[   16.884628] Bluetooth: hci0: download firmware failed, retrying...
[   ***] A start job is running for Raise network interfaces (11s / 5min 2s)[   17.423611] Bluetooth: hci0: change remote baud rate command in firmware
[**    ] A start job is running for Raise network interfaces (15s / 5min 2s)[   21.868612] Bluetooth: hci0 command 0xff05 tx timeout
[**    ] A start job is running for Raise network interfaces (23s / 5min 2s)[   29.932612] Bluetooth: hci0: send command failed
[   29.940527] Bluetooth: hci0: download firmware failed, retrying...
[***   ] A start job is running for Raise network interfaces (24s / 5min 2s)[   30.479698] Bluetooth: hci0: change remote baud rate command in firmware
         Starting Samba SMB Daemon...
[  OK  ] Started Samba SMB Daemon.
[   34.924662] Bluetooth: hci0 command 0xff05 tx timeout
[  OK  ] Started Raise network interfaces.
[  OK  ] Reached target Network.
         Starting Permit User Sessions...
         Starting OpenBSD Secure Shell server...
[  OK  ] Reached target Network is Online.
         Starting LSB: Start NTP daemon...
         Starting Samba NMB Daemon...
[  OK  ] Started Permit User Sessions.
[  OK  ] Started Serial Getty on ttyPS0.
[  OK  ] Started Getty on tty1.
[  OK  ] Reached target Login Prompts.
[  OK  ] Started OpenBSD Secure Shell server.
[  OK  ] Started Samba NMB Daemon.

Debian GNU/Linux 9 debian-fpga ttyPS0

debian-fpga login: [   42.988688] Bluetooth: hci0: send command failed
[   42.993317] Bluetooth: hci0: download firmware failed, retrying...
[   43.535621] Bluetooth: hci0: change remote baud rate command in firmware
[   47.980649] Bluetooth: hci0 command 0xff05 tx timeout
[   56.044449] Bluetooth: hci0: send command failed
[   56.049083] Bluetooth: hci0: download firmware failed, retrying...

  1. 2018年10月17日 05:07 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96 で ikwzm さんのDebian9 Root File Systemを動かしてみる2

Ultra96 で ikwzm さんのDebian9 Root File Systemを動かしてみる”の続き。

Ultra96 で ikwzm さんのROOT_FS でDebian が立ち上がってログインできるようになったので、今回は、パッケージをインストールしてみよう。

Ultra96_ikwzm_12_181015.png

まずは、Linux Image Package のインストールからやってみよう。
sudo dpkg -i linux-image-4.14.0-xlnx-v2018.2-zynqmp-fpga_4.14.0-xlnx-v2018.2-zynqmp-fpga-1_arm64.deb
Ultra96_ikwzm_13_181015.png

これはうまく行ったようだ。

sudo dpkg -i linux-headers-4.14.0-xlnx-v2018.2-zynqmp-fpga_4.14.0-xlnx-v2018.2-zynqmp-fpga-1_arm64.deb
Ultra96_ikwzm_14_181015.png

これはうまく行かない。
調べてみると、「AR# 14219
MicroBlaze - make を実行すると、「Warning: File `filename' has modification time in the future make[1]: warning: Clock skew detected. Your build may be incomplete」という警告メッセージが表示される
」がヒットして日付が合っていないようだということがわかった。
そこで date コマンドで今日の日付と日時に合わせてからインストールしたところ成功した。
Ultra96_ikwzm_16_181016.png

次に、
sudo dpkg -i fclkcfg-4.14.0-xlnx-v2018.2-zynqmp-fpga_1.0.0-1_arm64.deb
を行ったが、/lib/modules/4.14.0 が無いというエラーだったので、mkdir でディレクトリを作成してからインストールしたが、warning が出ている。
Ultra96_ikwzm_18_181016.png

最後に、
sudo dpkg -i udmabuf-4.14.0-xlnx-v2018.2-zynqmp-fpga_1.2.3-1_arm64.deb
を行ったが、やはり、fclkcfg のときと同じ warning が出ている。
Ultra96_ikwzm_19_181016.png

warning を下に示す。

depmod: WARNING: could not open /lib/modules/4.14.0/modules.order: No such file or directory
depmod: WARNING: could not open /lib/modules/4.14.0/modules.builtin: No such file or directory

  1. 2018年10月16日 05:24 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

トランジスタ技術2018年11月号に記事を書きました

トランジスタ技術2018年11月号「第4章 MNIST向け固定小数点CNNの設計から,各種シミュレーション,実装まで 手書き数字認識用FPGAニューラル・ネットワーク・システムの製作」という記事を書きました。

MNIST を推論する畳み込みニューラル・ネットワークをFPGA で作ったという記事です。28 x 28 ピクセルの四角枠をキーボードで動かして、中に収めた手書き数字を判定するという回路です。ZYBO Z7-20 に実装しました。
ただし、カメラのMT9D111メガピクセルカメラモジュールが在庫切れです。
FPGAの部屋のブログの「2 Mega pixel Camera Module MT9D111 JPEG Out + HQ lens」2 Mega pixel Camera Module MT9D111 JPEG Out + HQ lensは在庫があるようです。

なお、第1章から第3章まではなひたふさんが記事を書かれていて、SDSoC を使ったニューラル・ネットワークの実装の記事もありますので、とてもおもしろいと思います。

Vivado HLSのソースコードがDVDに搭載されていませんでしたので、私のGitHubに上げておきました。
「トランジスタ技術2018年11月号の第4章「手書き数字認識用FPGAニューラル・ネットワーク・システムの製作」のVivado HLSのソースコードです」
よろしくお願いいたします。
  1. 2018年10月14日 04:58 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:2

SqueezeNet for MNIST で層の数を減らして、各層の出力をC のヘッダに出力

今まで SqueezeNet for MNIST をやってきたが、MNIST の手書き数字の分類を行うのにフルのSqueezeNet は大きすぎると思う。
そこで、SqueezeNet の特徴を残しながら、fire 層を 1 層にしたモデルをやってみた。

それとこれが重要なのだが、私は、Vivado HLS で畳み込み層などをC++ で独自に書く訳なのだが、そのコードが正しいという確証が現在、どこからも得られないという問題がある。これは重要な問題で、ニューラルネットワークはロバスト性がありすぎて、途中でコードが間違っていても、あまり結果が変わらないことがよくある。コレを解消するためにKeras で最初の1個のデータだけだが、各層の出力をヘッダとして出力するPython コードを開発した。このデータを使用して、自分で作ったC++ コードの出力するデータと比較することができる。
Jupyter Notebook のファイル名は、squeezenet4mnist2.ipynb

# SqueezeNet for MNIST
https://www.kaggle.com/somshubramajumdar/squeezenet-for-mnist
(Apache License 2.0)を引用してKeras 2に変更し独自のコードを加えた by marsee


```python
# SqueezeNet for MNIST
# 2018/08/02 by marsee
# Keras / Tensorflowで始めるディープラーニング入門 https://qiita.com/yampy/items/706d44417c433e68db0d
# のPythonコードを再利用させて頂いている
# https://www.kaggle.com/somshubramajumdar/squeezenet-for-mnist (Apache License 2.0)を引用して
# Keras 2に変更し独自のコードを加えた

import keras
from keras.datasets import mnist
from keras import backend as K
import pandas as pd
import numpy as np 
from keras.models import Model, Input
from keras.layers import Dense, Dropout, Flatten, Concatenate
from keras.layers import Conv2D, MaxPooling2D, Activation, AveragePooling2D
import keras.utils.np_utils as kutils

batch_size = 128
num_classes = 10
epochs = 10

img_rows, img_cols = 28, 28

(x_train, y_train), (x_test, y_test) = mnist.load_data()

#Kerasのバックエンドで動くTensorFlowとTheanoでは入力チャンネルの順番が違うので場合分けして書いています
if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

y_train = y_train.astype('int32')
y_test = y_test.astype('int32')
y_train = keras.utils.np_utils.to_categorical(y_train, num_classes)
y_test =  keras.utils.np_utils.to_categorical(y_test, num_classes)

# Setup of SqueezeNet (http://arxiv.org/abs/1602.07360), which offers similar performance
# to AlexNet, while using drastically fewer parameters. Tested on CIFAR10, it also performs
# well on MNIST problem

# Uses the latest keras 1.0.2 Functional API

input_layer = Input(shape=(28, 28, 1), name="input")

#conv 1
conv1 = Conv2D(20, (3, 3), padding="valid", kernel_initializer="glorot_uniform", strides=(2, 2))(input_layer)
relu1 = Activation(activation='relu')(conv1)

#maxpool 1
maxpool1 = MaxPooling2D(pool_size=(2,2))(relu1)

#fire 1
fire2_squeeze = Conv2D(10, (1, 1), padding="same", kernel_initializer="glorot_uniform")(maxpool1)
relu2_squeeze = Activation(activation='relu')(fire2_squeeze)

fire2_expand1 = Conv2D(10, (1, 1), padding="same", kernel_initializer="glorot_uniform")(relu2_squeeze)
relu2_expand1 = Activation(activation='relu')(fire2_expand1)
fire2_expand2 = Conv2D(10, (3, 3), padding="same", kernel_initializer="glorot_uniform")(relu2_squeeze)
relu2_expand2 = Activation(activation='relu')(fire2_expand2)

merge1 = Concatenate()([relu2_expand1, relu2_expand2])
fire2 = Activation("linear")(merge1)

#conv 10
conv10 = Conv2D(10, (1, 1), padding="valid", kernel_initializer="glorot_uniform")(fire2)

# The original SqueezeNet has this avgpool1 as well. But since MNIST images are smaller (1,28,28)
# than the CIFAR10 images (3,224,224), AveragePooling2D reduces the image size to (10,0,0), 
# crashing the script.

#avgpool 1
#avgpool10 = AveragePooling2D((13,13))(conv10)

flatten = Flatten()(conv10)

softmax = Dense(10, activation="softmax")(flatten)

model = Model(inputs=input_layer, outputs=softmax)


model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs,
          verbose=1, validation_data=(x_test, y_test))
```

    Using TensorFlow backend.


    x_train shape: (60000, 28, 28, 1)
    60000 train samples
    10000 test samples
    Train on 60000 samples, validate on 10000 samples
    Epoch 1/10
    60000/60000 [==============================] - 8s 128us/step - loss: 0.4393 - acc: 0.8600 - val_loss: 0.1674 - val_acc: 0.9492
    Epoch 2/10
    60000/60000 [==============================] - 7s 118us/step - loss: 0.1489 - acc: 0.9546 - val_loss: 0.1089 - val_acc: 0.9657
    Epoch 3/10
    60000/60000 [==============================] - 7s 118us/step - loss: 0.1123 - acc: 0.9660 - val_loss: 0.0884 - val_acc: 0.9727
    Epoch 4/10
    60000/60000 [==============================] - 7s 118us/step - loss: 0.0940 - acc: 0.9708 - val_loss: 0.0787 - val_acc: 0.9742
    Epoch 5/10
    60000/60000 [==============================] - 7s 120us/step - loss: 0.0820 - acc: 0.9753 - val_loss: 0.0665 - val_acc: 0.9794
    Epoch 6/10
    60000/60000 [==============================] - 7s 118us/step - loss: 0.0745 - acc: 0.9772 - val_loss: 0.0605 - val_acc: 0.9806
    Epoch 7/10
    60000/60000 [==============================] - 7s 119us/step - loss: 0.0689 - acc: 0.9793 - val_loss: 0.0637 - val_acc: 0.9816
    Epoch 8/10
    60000/60000 [==============================] - 7s 118us/step - loss: 0.0643 - acc: 0.9803 - val_loss: 0.0585 - val_acc: 0.9813
    Epoch 9/10
    60000/60000 [==============================] - 7s 117us/step - loss: 0.0600 - acc: 0.9814 - val_loss: 0.0569 - val_acc: 0.9809
    Epoch 10/10
    60000/60000 [==============================] - 7s 120us/step - loss: 0.0574 - acc: 0.9819 - val_loss: 0.0540 - val_acc: 0.9825



```python
# Keras / Tensorflowで始めるディープラーニング入門 https://qiita.com/yampy/items/706d44417c433e68db0d
# のPythonコードを再利用させて頂いている

%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt

plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()

# plot the loss
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
```

SqNet_181013_output_2_0.png SqNet_181013_output_2_1.png 


```python
# 学習済みモデルの保存

from keras.models import load_model

model.save('squeezenet4mnist_model.h5')  # creates a HDF5 file 'my_model.h5'
```


```python
# 学習済みモデルの読み込み

from keras.models import load_model

model = load_model('squeezenet4mnist_model.h5')
```

    Using TensorFlow backend.



```python
# My Mnist CNN (Convolution layerの特徴マップは5個)
# Conv2D - ReLU - MaxPooling - Dence - ReLU - Dence
# 2018/05/25 by marsee
# Keras / Tensorflowで始めるディープラーニング入門 https://qiita.com/yampy/items/706d44417c433e68db0d
# のPythonコードを再利用させて頂いている

import keras
from keras.datasets import mnist
from keras import backend as K
import pandas as pd
import numpy as np 
from keras.models import Model, Input
from keras.layers import Dense, Dropout, Flatten, Concatenate
from keras.layers import Conv2D, MaxPooling2D, Activation, AveragePooling2D
import keras.utils.np_utils as kutils

batch_size = 128
num_classes = 10
epochs = 5

img_rows, img_cols = 28, 28

(x_train, y_train), (x_test, y_test) = mnist.load_data()

#Kerasのバックエンドで動くTensorFlowとTheanoでは入力チャンネルの順番が違うので場合分けして書いています
if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

y_train = y_train.astype('int32')
y_test = y_test.astype('int32')
y_train = keras.utils.np_utils.to_categorical(y_train, num_classes)
y_test =  keras.utils.np_utils.to_categorical(y_test, num_classes)
```

    x_train shape: (60000, 28, 28, 1)
    60000 train samples
    10000 test samples



```python
model.summary()
```

    __________________________________________________________________________________________________
    Layer (type)                    Output Shape         Param #     Connected to                     
    ==================================================================================================
    input (InputLayer)              (None, 28, 28, 1)    0                                            
    __________________________________________________________________________________________________
    conv2d_1 (Conv2D)               (None, 13, 13, 20)   200         input[0][0]                      
    __________________________________________________________________________________________________
    activation_1 (Activation)       (None, 13, 13, 20)   0           conv2d_1[0][0]                   
    __________________________________________________________________________________________________
    max_pooling2d_1 (MaxPooling2D)  (None, 6, 6, 20)     0           activation_1[0][0]               
    __________________________________________________________________________________________________
    conv2d_2 (Conv2D)               (None, 6, 6, 10)     210         max_pooling2d_1[0][0]            
    __________________________________________________________________________________________________
    activation_2 (Activation)       (None, 6, 6, 10)     0           conv2d_2[0][0]                   
    __________________________________________________________________________________________________
    conv2d_3 (Conv2D)               (None, 6, 6, 10)     110         activation_2[0][0]               
    __________________________________________________________________________________________________
    conv2d_4 (Conv2D)               (None, 6, 6, 10)     910         activation_2[0][0]               
    __________________________________________________________________________________________________
    activation_3 (Activation)       (None, 6, 6, 10)     0           conv2d_3[0][0]                   
    __________________________________________________________________________________________________
    activation_4 (Activation)       (None, 6, 6, 10)     0           conv2d_4[0][0]                   
    __________________________________________________________________________________________________
    concatenate_1 (Concatenate)     (None, 6, 6, 20)     0           activation_3[0][0]               
                                                                     activation_4[0][0]               
    __________________________________________________________________________________________________
    activation_5 (Activation)       (None, 6, 6, 20)     0           concatenate_1[0][0]              
    __________________________________________________________________________________________________
    conv2d_5 (Conv2D)               (None, 6, 6, 10)     210         activation_5[0][0]               
    __________________________________________________________________________________________________
    flatten_1 (Flatten)             (None, 360)          0           conv2d_5[0][0]                   
    __________________________________________________________________________________________________
    dense_1 (Dense)                 (None, 10)           3610        flatten_1[0][0]                  
    ==================================================================================================
    Total params: 5,250
    Trainable params: 5,250
    Non-trainable params: 0
    __________________________________________________________________________________________________



```python
# 畳み込み層の重みをCヘッダファイルに書き出す
# 2018/05/31 by marsee

def fwrite_conv_weight(weight, wfile_name, float_wt_name, fixed_wt_name, MAGNIFICATION):
    import datetime
    import numpy as np
    
    f = open(wfile_name, 'w')
    todaytime = datetime.datetime.today()
    f.write('// '+wfile_name+'\n')
    strdtime = todaytime.strftime("%Y/%m/%d %H:%M:%S")
    f.write('// {0} by marsee\n'.format(strdtime))
    f.write("\n")
    
    f.write('const float '+float_wt_name+'['+str(weight.shape[0])+']['+str(weight.shape[1])+']['+str(weight.shape[2])+']['+str(weight.shape[3])+'] = \n{\n')
    for i in range(weight.shape[0]):
        f.write("\t{\n")
        for j in range(weight.shape[1]):
            f.write("\t\t{\n")
            for k in range(weight.shape[2]):
                f.write("\t\t\t{")
                for m in range(weight.shape[3]):
                    f.write(str(weight[i][j][k][m]))
                    if (m==weight.shape[3]-1):
                        f.write("}")
                    else:
                        f.write(",")
                
                if (k==weight.shape[2]-1):
                    f.write("\n\t\t}\n")
                else:
                    f.write(",\n")

            if (j==weight.shape[1]-1):
                f.write("\t}\n")
            else:
                f.write(",\n")
        
        
        if (i==weight.shape[0]-1):
            f.write("};\n")
        else:
            f.write("\t,\n")

    f.write("\n")
    f.write('const ap_fixed<'+str(int(np.log2(MAGNIFICATION))+1)+', 1, AP_TRN, AP_WRAP> '+fixed_wt_name+'['+str(weight.shape[0])+']['+str(weight.shape[1])+']['+str(weight.shape[2])+']['+str(weight.shape[3])+'] = \n{\n')
    for i in range(weight.shape[0]):
        f.write("\t{\n")
        for j in range(weight.shape[1]):
            f.write("\t\t{\n")
            for k in range(weight.shape[2]):
                f.write("\t\t\t{")
                for m in range(weight.shape[3]):
                    w_int = int(weight[i][j][k][m]*MAGNIFICATION+0.5)
                    if (w_int > MAGNIFICATION-1):
                        w_int = MAGNIFICATION-1
                    elif (w_int < -MAGNIFICATION):
                        w_int = -MAGNIFICATION
                    f.write(str(float(w_int)/float(MAGNIFICATION)))
                    if (m==weight.shape[3]-1):
                        f.write("}")
                    else:
                        f.write(",")
                
                if (k==weight.shape[2]-1):
                    f.write("\n\t\t}\n")
                else:
                     f.write(",\n")

            if (j==weight.shape[1]-1):
                f.write("\t}\n")
            else:
                f.write(",\n")
        
        
        if (i==weight.shape[0]-1):
            f.write("};\n")
        else:
            f.write("\t,\n")
 
    f.close()
```


```python
# 畳み込み層と全結合層のバイアスをCヘッダファイルに書き出す
# 2018/05/31 by marsee

def fwrite_bias(bias, wfile_name, float_b_name, fixed_wt_name, MAGNIFICATION):
    import datetime
    import numpy as np
    
    f = open(wfile_name, 'w')
    todaytime = datetime.datetime.today()
    f.write('// '+wfile_name+'\n')
    strdtime = todaytime.strftime("%Y/%m/%d %H:%M:%S")
    f.write('// {0} by marsee\n'.format(strdtime))
    f.write("\n")

    f.write('const float '+float_b_name+'['+str(bias.shape[0])+'] = {\n\t')
    for i in range(bias.shape[0]):
        f.write(str(bias[i]))
        if (i < bias.shape[0]-1):
            f.write(", ")
    f.write("\n};\n")

    f.write("\n")
    f.write('const ap_fixed<'+str(int(np.log2(MAGNIFICATION))+1)+', 1, AP_TRN, AP_WRAP> '+fixed_wt_name+'['+str(bias.shape[0])+'] = {\n\t')
    for i in range(bias.shape[0]):
        b_int = int(bias[i]*MAGNIFICATION+0.5)
        if (b_int > MAGNIFICATION-1):
            b_int = MAGNIFICATION-1
        elif (b_int < -MAGNIFICATION):
            b_int = -MAGNIFICATION
        f.write(str(float(b_int)/float(MAGNIFICATION)))
        if (i < bias.shape[0]-1):
            f.write(", ")
    f.write("\n};\n")

    f.close()
```


```python
# 層のデータを取得してCのヘッダ・ファイルに出力する(float)
# 2018/09/20 by marsee

def fwrite_layer_output(layer_out, wfile_name, layer_output_name):
    import datetime
    import numpy as np
    
    f = open(wfile_name, 'w')
    todaytime = datetime.datetime.today()
    f.write('// '+wfile_name+'\n')
    strdtime = todaytime.strftime("%Y/%m/%d %H:%M:%S")
    f.write('// {0} by marsee\n'.format(strdtime))
    f.write("\n")
    
    f.write('const float '+layer_output_name+'['+str(layer_out.shape[0])+']['+str(layer_out.shape[1])+']['+str(layer_out.shape[2])+']['+str(layer_out.shape[3])+'] = \n{\n')
    for i in range(layer_out.shape[0]):
        f.write("\t{\n")
        for j in range(layer_out.shape[1]):
            f.write("\t\t{\n")
            for k in range(layer_out.shape[2]):
                f.write("\t\t\t{")
                for m in range(layer_out.shape[3]):
                    f.write(str(layer_out[i][j][k][m]))
                    if (m==layer_out.shape[3]-1):
                        f.write("}")
                    else:
                        f.write(",")
                
                if (k==layer_out.shape[2]-1):
                    f.write("\n\t\t}\n")
                else:
                    f.write(",\n")

            if (j==layer_out.shape[1]-1):
                f.write("\t}\n")
            else:
                f.write(",\n")
        
        
        if (i==layer_out.shape[0]-1):
            f.write("};\n")
        else:
            f.write("\t,\n")

    f.write("\n")
    f.close()
```


```python
# 層の出力データを取得する(conv2d_1だけのテスト用)
from keras.models import Model

conv_layer_name = 'conv2d_1'

conv_layer = model.get_layer(conv_layer_name)
conv_layer_wb = conv_layer.get_weights()

conv_layer_model = Model(inputs=model.input,
                                 outputs=model.get_layer(conv_layer_name).output)
x_test_limit = x_test[:1]
y_test_limit = y_test[:10]
print(y_test_limit)
conv_output = conv_layer_model.predict(x_test_limit, verbose=1)
print(conv_output.shape)
fwrite_layer_output(conv_output, 'conv2d_1_output.h', 'conv2d_1_output')
```

    [[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
     [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
     [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
     [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
     [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
     [0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]]
    1/1 [==============================] - 0s 74ms/step
    (1, 13, 13, 20)


# 層の統計情報


```python
# Convolution layerの中間出力を取り出す 
from keras.models import Model
import numpy as np

x_test_limit = x_test[:1]
for num in range(1, 6):
    conv_layer_name = 'conv2d_' + str(num)

    conv_layer = model.get_layer(conv_layer_name)
    conv_layer_wb = conv_layer.get_weights()

    conv_layer_model = Model(inputs=model.input,
                                     outputs=model.get_layer(conv_layer_name).output)
    conv_output = conv_layer_model.predict(x_test, verbose=1)

    conv_layer_weight = conv_layer_wb[0]
    conv_layer_bias = conv_layer_wb[1]

    print(conv_layer_name)
    print(conv_layer_weight.shape)
    print(conv_layer_weight.transpose(3,2,0,1).shape)
    print(conv_layer_bias.shape)
    print(conv_output.shape)

    print("np.max(conv_layer_weight) = {0}".format(np.max(conv_layer_weight)))
    print("np.min(conv_layer_weight) = {0}".format(np.min(conv_layer_weight))) 
    abs_conv_layer_weight = np.absolute(conv_layer_weight)
    print("np.max(abs_conv_layer_weight) = {0}".format(np.max(abs_conv_layer_weight)))
    print("np.min(abs_conv_layer_weight) = {0}".format(np.min(abs_conv_layer_weight))) 

    print("np.max(conv_layer_bias) = {0}".format(np.max(conv_layer_bias)))
    print("np.min(conv_layer_bias) = {0}".format(np.min(conv_layer_bias))) 
    abs_conv_layer_bias = np.absolute(conv_layer_bias)
    print("np.max(abs_conv_layer_bias) = {0}".format(np.max(abs_conv_layer_bias)))
    print("np.min(abs_conv_layer_bias) = {0}".format(np.min(abs_conv_layer_bias))) 

    print("conv_output = {0}".format(conv_output.shape))
    print("np.std(conv_output) = {0}".format(np.std(conv_output)))
    print("np.max(conv_output) = {0}".format(np.max(conv_output)))
    print("np.min(conv_output) = {0}".format(np.min(conv_output))) 

    abs_conv_output = np.absolute(conv_output)
    print("np.max(abs_conv) = {0}".format(np.max(abs_conv_output)))
    print("np.min(abs_conv) = {0}".format(np.min(abs_conv_output))) 
    print("")
    
    # 2018/06/05 修正 畳み込み層の重みの配列は(カーネルサイズh,カーネルサイズw, 入力チャネル, 出力チャネル)ということなので、Pythonコードを修正した。@NORA__0013 さんありがとうございました。

    MAGNIFICATION_CONV = 2 ** (9-1)
    fwrite_conv_weight(conv_layer_weight.transpose(3,2,0,1), 'conv'+str(num)+'_weight.h', 'conv'+str(num)+'_fweight', 'conv'+str(num)+'_weight', MAGNIFICATION_CONV)

    fwrite_bias(conv_layer_bias, 'conv'+str(num)+'_bias.h', 'conv'+str(num)+'_fbias', 'conv'+str(num)+'_bias', MAGNIFICATION_CONV)
    
    conv_output = conv_layer_model.predict(x_test_limit, verbose=1)
    fwrite_layer_output(conv_output, 'conv'+str(num)+'_output.h', 'conv'+str(num)+'output')
```

    10000/10000 [==============================] - 0s 38us/step
    conv2d_1
    (3, 3, 1, 20)
    (20, 1, 3, 3)
    (20,)
    (10000, 13, 13, 20)
    np.max(conv_layer_weight) = 0.4946177303791046
    np.min(conv_layer_weight) = -0.5343244671821594
    np.max(abs_conv_layer_weight) = 0.5343244671821594
    np.min(abs_conv_layer_weight) = 0.00023465760750696063
    np.max(conv_layer_bias) = 0.057732950896024704
    np.min(conv_layer_bias) = -0.08072157949209213
    np.max(abs_conv_layer_bias) = 0.08072157949209213
    np.min(abs_conv_layer_bias) = 2.5581393856555223e-05
    conv_output = (10000, 13, 13, 20)
    np.std(conv_output) = 0.303703248500824
    np.max(conv_output) = 1.8376622200012207
    np.min(conv_output) = -1.7203431129455566
    np.max(abs_conv) = 1.8376622200012207
    np.min(abs_conv) = 4.842877388000488e-08
    
    1/1 [==============================] - 0s 0us/step
    10000/10000 [==============================] - 0s 40us/step
    conv2d_2
    (1, 1, 20, 10)
    (10, 20, 1, 1)
    (10,)
    (10000, 6, 6, 10)
    np.max(conv_layer_weight) = 0.913070023059845
    np.min(conv_layer_weight) = -0.9718273878097534
    np.max(abs_conv_layer_weight) = 0.9718273878097534
    np.min(abs_conv_layer_weight) = 0.0080069899559021
    np.max(conv_layer_bias) = 0.10839419811964035
    np.min(conv_layer_bias) = -0.04171771556138992
    np.max(abs_conv_layer_bias) = 0.10839419811964035
    np.min(abs_conv_layer_bias) = 0.010898223146796227
    conv_output = (10000, 6, 6, 10)
    np.std(conv_output) = 0.9102568626403809
    np.max(conv_output) = 4.971376895904541
    np.min(conv_output) = -2.940309762954712
    np.max(abs_conv) = 4.971376895904541
    np.min(abs_conv) = 1.1175870895385742e-08
    
    1/1 [==============================] - 0s 0us/step
    10000/10000 [==============================] - 0s 44us/step
    conv2d_3
    (1, 1, 10, 10)
    (10, 10, 1, 1)
    (10,)
    (10000, 6, 6, 10)
    np.max(conv_layer_weight) = 0.8710610270500183
    np.min(conv_layer_weight) = -0.6806471347808838
    np.max(abs_conv_layer_weight) = 0.8710610270500183
    np.min(abs_conv_layer_weight) = 0.0008496924419887364
    np.max(conv_layer_bias) = 0.1616363525390625
    np.min(conv_layer_bias) = -0.11668514460325241
    np.max(abs_conv_layer_bias) = 0.1616363525390625
    np.min(abs_conv_layer_bias) = 0.0003539775207173079
    conv_output = (10000, 6, 6, 10)
    np.std(conv_output) = 1.006908655166626
    np.max(conv_output) = 4.752679347991943
    np.min(conv_output) = -3.4257307052612305
    np.max(abs_conv) = 4.752679347991943
    np.min(abs_conv) = 2.9848888516426086e-07
    
    1/1 [==============================] - 0s 999us/step
    10000/10000 [==============================] - 1s 56us/step
    conv2d_4
    (3, 3, 10, 10)
    (10, 10, 3, 3)
    (10,)
    (10000, 6, 6, 10)
    np.max(conv_layer_weight) = 0.6119384765625
    np.min(conv_layer_weight) = -0.6267021894454956
    np.max(abs_conv_layer_weight) = 0.6267021894454956
    np.min(abs_conv_layer_weight) = 0.000530939141754061
    np.max(conv_layer_bias) = 0.09105820208787918
    np.min(conv_layer_bias) = -0.13521511852741241
    np.max(abs_conv_layer_bias) = 0.13521511852741241
    np.min(abs_conv_layer_bias) = 0.000247095333179459
    conv_output = (10000, 6, 6, 10)
    np.std(conv_output) = 1.4005329608917236
    np.max(conv_output) = 7.894415378570557
    np.min(conv_output) = -7.611080169677734
    np.max(abs_conv) = 7.894415378570557
    np.min(abs_conv) = 6.484333425760269e-08
    
    1/1 [==============================] - 0s 0us/step
    10000/10000 [==============================] - 1s 63us/step
    conv2d_5
    (1, 1, 20, 10)
    (10, 20, 1, 1)
    (10,)
    (10000, 6, 6, 10)
    np.max(conv_layer_weight) = 1.1239129304885864
    np.min(conv_layer_weight) = -0.9796998500823975
    np.max(abs_conv_layer_weight) = 1.1239129304885864
    np.min(abs_conv_layer_weight) = 0.0004102856619283557
    np.max(conv_layer_bias) = 0.3322758972644806
    np.min(conv_layer_bias) = -0.23224467039108276
    np.max(abs_conv_layer_bias) = 0.3322758972644806
    np.min(abs_conv_layer_bias) = 0.021110178902745247
    conv_output = (10000, 6, 6, 10)
    np.std(conv_output) = 1.4941357374191284
    np.max(conv_output) = 9.327534675598145
    np.min(conv_output) = -11.037702560424805
    np.max(abs_conv) = 11.037702560424805
    np.min(abs_conv) = 1.5832483768463135e-07
    
    1/1 [==============================] - 0s 999us/step



DNN/Keras/squeezenet4mnist2 ディレクトリの内容を示す。層ごとの出力ファイルの conv?_output.h ができているのが分かる。
squeezenet_69_181013.png

1層目の出力ファイルの conv1_output.h の一部を示す。
squeezenet_70_181013.png
  1. 2018年10月13日 06:55 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Ultra96 で ikwzm さんのDebian9 Root File Systemを動かしてみる

Ultra96 で ikwzm さんのデバイスツリー・オーバーレイや fclkcfg、 udmabuf を動かしたいということで、”UltraZed 向け Debian GNU/Linux (v2018.2版) ブートイメージの提供”の Debian9 Root File System と”Ultra96用Yocto Linuxのビルドの続き4(Micro SD カードの用意、Ultra96で動作確認)”で用意したMicro SD カードの第1パーティションのULTRA96_BOO にコピーした Image, boot,bin, system.dtb, uEnv.txt を使用してUltra96 でDebian をブートしたい。

まずは、”UltraZed 向け Debian GNU/Linux (v2018.2版) ブートイメージの提供”の通りに git を clone して、git lfs pull を行った。
Ultra96_ikwzm_1_181011.png
Ultra96_ikwzm_2_181011.png

ZynqMP-FPGA-Linux ディレクトリの様子を示す。
Ultra96_ikwzm_3_181011.png

”FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(PYNQ-Z1対応)”を試してみる2(Micro SDカードの準備)”を見ながら、Micro SDカードをフォーマットした。
ただし、”UltraZed 向け Debian GNU/Linux (v2018.2版) ブートイメージの提供”の指定通りに第2パーティションは、ext4 にフォーマットした。
フォーマットする前の Micro SDカードの状況を示す。 /dev/sdd として認識されている。

mkfs でフォーマットしているところを示す。第2パーティションは、ext4 にフォーマットしてある。
Ultra96_ikwzm_5_181011.png

フォーマット後の Micro SDカードを示す。
Ultra96_ikwzm_6_181011.png

Ultra96用Yocto Linuxのビルドの続き4(Micro SD カードの用意、Ultra96で動作確認)”を参考にして、 Micro SD カードの第1パーティションのULTRA96_BOO に Image, boot,bin, system.dtb, uEnv.txt をコピーした。
Ultra96_ikwzm_7_181011.png

ZynqMP-FPGA-Linux ディレクトリから、debian9-rootfs-vanilla.tgz を解凍して Micro SDカードの第2パーティションにコピーした。
sudo tar xfz debian9-rootfs-vanilla.tgz -C /media/masaaki/ROOT_FS
Ultra96_ikwzm_8_181011.png

linux-image 、 linux-headers 、 fclkcfg 、udmabuf を /media/masaaki/ROOT_FS/home/fpga/debian/ にコピーした。
Ultra96_ikwzm_9_181011.png

/media/masaaki/ROOT_FS/home/fpga/debian/ の様子を示す。
Ultra96_ikwzm_10_181011.png

Micro SDカードのマウントを解除して、Ultra96 に挿入して電源ON した。
するとDebian が立ち上がったのだが、どうやってもキー入力することができない。
これは困った。
Ultra96_ikwzm_11_181011.png

そして、もっと不思議なことに、以前は入力できていた”Ultra96用Yocto Linuxのビルドの続き5(Debian Root FS で起動)”で作った Micro SDカードもブートはするのだが、同様にどうやってもキー入力することができない。。。本当に謎だ?
この Micro SDカードでは、無線LANを設定してあるので、SSHで入れて、問題なく使用できる。

使用しているUSB-シリアル変換が壊れてしまったのかもしれないので、もう1つ買ってはんだ付けしてみよう。

(2018/10/15:追記)
USB-シリアル変換のICのピンにハンダカスがついてショートしていたようです。ハンダカスを取り除いたところ、問題なくキー入力ができ、ログインできました。
Ultra96_ikwzm_12_181015.png
  1. 2018年10月12日 05:33 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96 で ikwzm さんのDebian を動作させたい

現在、Ultra96 でDebian Root FS を動作させて無線LANまで動かせたが、Debian RootFS はikwzm さんのZYBO 用のものを使用している。これを”UltraZed 向け Debian GNU/Linux (v2018.2版) ブートイメージの提供”のDebian RootFS に変更して、fclkcfg デバイス・ドライバと udmabuf デバイス・ドライバをインストールしてデバイスツリー・オーバーレイをやってみたい。

最初に、”@ikwzmさんのUltraZed 向け Debian GNU/Linux の構築をやってみる6(最新のdtc をビルド)”の通りに最新の device-tree-compiler をビルドした。
  1. 2018年10月10日 05:15 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

ZYBOtを家のコースで走らせてみた

ZYBOt の白線間走行用CNNを含んだVivado 2018.2 プロジェクト2”でビットファイルが生成できた。
生成されたビットファイルを”白線追従用CNNを使用したZYBOtの白線追従走行1(準備編)”を参考にして、fpga-bit-to-bin.py を使用して、ZYBO_0_wrapper.bit を ZYBO_0_wrapper.bin に変換した。
python fpga-bit-to-bin.py --flip ZYBO_0_wrapper.bit ZYBO_0_wrapper.bin
ZYBOt_Keras_69_181008

ZYBOt のZYBO にFTP して書き換えた ZYBO_0_wrapper.bin をアップロードした。

sudo cp ZYBO_0_wrapper.bin /lib/firmware/
で、ZYBO_0_wrapper.bin を /lib/firmware/ ディレクトリにコピペした。

まずは、ホーム・ディレクトリから cd zybot/wl_tracing_cnn を実行して、wl_tracing_cnn ディレクトリに移動した。

参照ブログ”白線追従用CNNを使用したZYBOtの白線追従走行2(準備編2)
sudo dtbocfg.rb -i --dts devicetree.dts wl_tracing_cnn
を実行し、デバイスツリーをロードして、ビットファイルのダウンロード、クロックの設定も行った。
次に、/dev/uio* と /dev/udmabuf0 をすべての人がR/W できるように設定した。
sudo chmod 666 /dev/uio*
sudo chmod 666 /dev/udmabuf0

これで、すべてのユーザーが書き込みできるので、ユーザーモードで wl_tracing_cnn を起動できる。
cd build
./wl_tracing_cnn

これで ZYBOt が走り出した。コースを走らせてみた。
1つ目はバックグランド音楽を付けてみたので、音量注意。




それなりにコースを走れてはいるが、コースを外れてしまう。学習が良くなかったかもしれない?手前から曲がるように学習させてしまったかもしれない?
1回カーブを曲がるようなときはごまかしが効くが、複雑なコースを走るときにはごまかしが効かない。ごまかしというのは
私が操縦してラジコンのように走れせて、それをZYBOt に学習させたほうが良いのではないか?と思う。
  1. 2018年10月09日 05:29 |
  2. Zybot
  3. | トラックバック:0
  4. | コメント:0

ZYBOt の白線間走行用CNNを含んだVivado 2018.2 プロジェクト2

ZYBOt の白線間走行用CNNを含んだVivado 2018.2 プロジェクト1”の続き。

前回は、白線間走行用CNNを course_conv_nn2_axi3 に変更してVivado プロジェクトを論理合成、インプリメンテーションしたが、タイミングエラーになってしまった。今回は、Vivado HLS に戻ってIP を再合成して、タイミングエラーを解消しよう。

Vivado HLS 2018.2 の course_conv_nn2_axi3_k に戻って、Solution Settings -> Synthesis の Uncertainty を 8 ns まで、 1 ns 刻みに変更していったが、Export RTL の CP achieved post-implementation は 9.847 ns で変わらなかった。つまり回路が変わらなかったようだ。下にUncertainty が 6 ns のときの結果を示す。
ZYBOt_Keras_57_181006
ZYBOt_Keras_58_181006

Vivado HLS 2017.4 でも同様にSolution Settings -> Synthesis の Uncertainty を 2 ns から 8 ns まで、 1 ns 刻みに変更していったが、Export RTL の CP achieved post-implementation は 8.221 ns で変化がなかった。Uncertainty がデフォルト値の下に示す IP をVivado で論理合成、インプリメンテーションしてみたが、やはりタイミングエラーだった。
ZYBOt_Keras_60_181006
ZYBOt_Keras_61_181006

ZYBOt_Keras_62_181006

どうやら、このC ソースコードでは、Uncertainty を変更しても回路に変更が無いようだ。こんな時に状況を打開できるのは指示子だと思う。積極的に指示子を入れていって回路を変更してみよう。とりあえずは影響の少なそうなところにPIPELINE 指示子を入れた。
ZYBOt_Keras_63_181008

Uncertainty が 7 ns のときを示す。
ZYBOt_Keras_64_181008
ZYBOt_Keras_65_181008

Latency は約 3.09 ms だが、問題ない。

ZYBOt_Keras_66_181008

Export RTL の CP achieved post-implementation は 7.670 ns なので、良さそう。
この IP をVivado プロジェクトの IP と入れ替えた。
論理合成、インプリメンテーション、ビットストリームの生成を行った。
ZYBOt_Keras_67_181008

Project Summary を示す。
ZYBOt_Keras_68_181008

Timing も問題ない。
  1. 2018年10月08日 06:22 |
  2. Zybot
  3. | トラックバック:0
  4. | コメント:0

ZYBOt の白線間走行用CNNを含んだVivado 2018.2 プロジェクト1

ZYBOt の白線間走行用CNNをVivado HLS 2018.2 でIP化2”で作製した白線間走行用CNN IP を”Kerasで学習した重みとバイアスを使用した白線間走行用CNNのVivado プロジェクト1”の curve_conv_nn2_axis3 _0 を消去して、今回作成した course_conv_nn2_axi3 を Add IP した。

ZYBO_0_182_9_k ディレクトリの ZYBO_0_153 プロジェクトを示す。
ZYBOt_Keras_54_181006

camera_interface モジュールで、curve_conv_nn2_axis3 _0 を消去して、今回作成した course_conv_nn2_axi3 を Add IP した。
ZYBOt_Keras_55_181006

これで、論理合成、インプリメンテーション、ビットストリームの生成を行った。
結果を示す。
ZYBOt_Keras_56_181006

Timing を見ると Worst Negative Slace (WNS) が -0.297 ns で、タイミング・エラーになっていることがわかった。Total Negative Slack (TNS) も -1.752 ns なので、他の所でもタイミングエラーになっているのが分かる。

Open Implemented Design をクリックして、Timing を見ると course_conv_nn2_axis3_0 の内部の Intra-clock Path がエラーになっているのが分かった。
ZYBOt_Keras_53_181006

これは、Vivado HLS での合成結果が 100 MHz で動作しないということなので、Vivado HLS に戻って再合成をしてみようと思う。
  1. 2018年10月07日 11:37 |
  2. Zybot
  3. | トラックバック:0
  4. | コメント:0

ZYBOt の白線間走行用CNNをVivado HLS 2018.2 でIP化2

ZYBOt の白線間走行用CNNをVivado HLS 2018.2 でIP化1”の続き。

前回は、DMA 付きのZYBOt の白線間走行用CNNのC シミュレーションとC コードの合成を行った。今回は、C/RTL 協調シミュレーションとExport RTL を行って、IP 化する。

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

まずは、C/RTL 協調シミュレーションを行った。
ZYBOt_Keras_36_181004

Latency は 178925 クロックだった。100 MHz クロックだとすると約 1.79 ms となる。

C/RTL 協調シミュレーションの波形を見てみよう。
まずは全体波形を見てみよう。
ZYBOt_Keras_37_181004

ins(axis) の ins_TREADY は最初のころ1 - 0 を行き来しているようだ。ここを拡大する。
ZYBOt_Keras_38_181004

細かく 1 になっているのが分かる。まあ、ここのスループットを改善するには、リソースが大量に必要だし、処理速度は 1.79 ms と十分なので、問題ない。60 fps でも 16.7 ms の処理時間で十分間に合う。

最後に Export RTL を行った。
ZYBOt_Keras_52_181006

LUT は 786 個、FF が 690 個、DSP は 4 個、BRAM は 15 個だった。
CP achieved post-implementation は 9.847 ns だった。
  1. 2018年10月05日 04:49 |
  2. Zybot
  3. | トラックバック:0
  4. | コメント:0

ZYBOt の白線間走行用CNNをVivado HLS 2018.2 でIP化1

ZYBOt の白線間走行用CNNをVivado HLS 2018.2 で試しに実装した”で、ZYBOt の白線間走行用CNNの精度が検証できたので、今度はIP化を行う。今回はC シミュレーションとC コードの合成を行う。

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

まずは、”Kerasで学習した重みとバイアスを使用した白線間走行用CNNをIPにする1”と”Kerasで学習した重みとバイアスを使用した白線間走行用CNNをIPにする2”を参照して、Vivado HLS 2018.2 の course_conv_nn2_axis3_k プロジェクトを作成した。
ZYBOt_Keras_32_181004

C シミュレーションを実行した。
ZYBOt_Keras_48_181006

レポートを示す。

INFO: [SIM 2] *************** CSIM start ***************
INFO: [SIM 4] CSIM will launch GCC as the compiler.
   Compiling ../../../course_conv_nn2_axis3_tb.cpp in debug mode
   Compiling ../../../course_conv_nn2_axis3.cpp in debug mode
   Generating csim.exe
test/straight_test/bmp_file231.bmp
test/straight_test/bmp_file185.bmp
test/straight_test/bmp_file238.bmp
test/straight_test/bmp_file184.bmp
test/straight_test/bmp_file101.bmp
test/straight_test/bmp_file198.bmp
test/straight_test/bmp_file72.bmp
test/straight_test/bmp_file115.bmp
test/straight_test/bmp_file65.bmp
test/straight_test/bmp_file100.bmp
test/straight_test/bmp_file102.bmp
test/straight_test/bmp_file117.bmp
test/straight_test/bmp_file74.bmp
test/straight_test/bmp_file113.bmp
test/straight_test/bmp_file73.bmp
test/straight_test/bmp_file76.bmp
test/straight_test/bmp_file103.bmp
test/straight_test/bmp_file68.bmp
test/straight_test/bmp_file75.bmp
test/straight_test/bmp_file240.bmp
test/straight_test/bmp_file232.bmp
test/straight_test/bmp_file235.bmp
test/straight_test/bmp_file104.bmp
test/straight_test/bmp_file187.bmp
test/straight_test/bmp_file201.bmp
test/straight_test/bmp_file233.bmp
test/straight_test/bmp_file197.bmp
test/straight_test/bmp_file199.bmp
test/straight_test/bmp_file116.bmp
test/straight_test/bmp_file239.bmp
test/straight_test/bmp_file186.bmp
test/straight_test/bmp_file188.bmp
test/straight_test/bmp_file234.bmp
test/straight_test/bmp_file67.bmp
test/straight_test/bmp_file114.bmp
Straight error is 0

test/left_test/bmp_file203.bmp
test/left_test/bmp_file94.bmp
correct data = 0, outs = 1
dot2[0] = -2.724609 dot2[1] = 3.486328 dot2[2] = -3.287109 
test/left_test/bmp_file89.bmp
test/left_test/bmp_file214.bmp
test/left_test/bmp_file84.bmp
test/left_test/bmp_file112.bmp
test/left_test/bmp_file105.bmp
test/left_test/bmp_file96.bmp
correct data = 0, outs = 2
dot2[0] = 1.197266 dot2[1] = -7.605469 dot2[2] = 9.322266 
test/left_test/bmp_file109.bmp
test/left_test/bmp_file97.bmp
test/left_test/bmp_file125.bmp
test/left_test/bmp_file123.bmp
test/left_test/bmp_file78.bmp
test/left_test/bmp_file82.bmp
test/left_test/bmp_file107.bmp
test/left_test/bmp_file85.bmp
test/left_test/bmp_file122.bmp
test/left_test/bmp_file124.bmp
test/left_test/bmp_file237.bmp
test/left_test/bmp_file108.bmp
test/left_test/bmp_file70.bmp
test/left_test/bmp_file95.bmp
test/left_test/bmp_file215.bmp
test/left_test/bmp_file88.bmp
test/left_test/bmp_file87.bmp
test/left_test/bmp_file79.bmp
test/left_test/bmp_file120.bmp
test/left_test/bmp_file111.bmp
test/left_test/bmp_file121.bmp
test/left_test/bmp_file80.bmp
test/left_test/bmp_file99.bmp
test/left_test/bmp_file86.bmp
test/left_test/bmp_file213.bmp
test/left_test/bmp_file118.bmp
test/left_test/bmp_file98.bmp
Left error is 2

test/right_test/bmp_file210.bmp
correct data = 2, outs = 0
dot2[0] = 3.501953 dot2[1] = 3.076172 dot2[2] = -9.761719 
test/right_test/bmp_file93.bmp
test/right_test/bmp_file196.bmp
test/right_test/bmp_file192.bmp
test/right_test/bmp_file208.bmp
test/right_test/bmp_file207.bmp
test/right_test/bmp_file219.bmp
test/right_test/bmp_file204.bmp
test/right_test/bmp_file77.bmp
test/right_test/bmp_file119.bmp
correct data = 2, outs = 1
dot2[0] = -6.904297 dot2[1] = 4.335938 dot2[2] = -1.699219 
test/right_test/bmp_file236.bmp
test/right_test/bmp_file221.bmp
test/right_test/bmp_file229.bmp
test/right_test/bmp_file71.bmp
correct data = 2, outs = 1
dot2[0] = -4.986328 dot2[1] = 2.332031 dot2[2] = 0.953125 
test/right_test/bmp_file205.bmp
test/right_test/bmp_file242.bmp
test/right_test/bmp_file206.bmp
test/right_test/bmp_file225.bmp
test/right_test/bmp_file195.bmp
test/right_test/bmp_file226.bmp
test/right_test/bmp_file228.bmp
test/right_test/bmp_file209.bmp
test/right_test/bmp_file211.bmp
correct data = 2, outs = 1
dot2[0] = -1.001953 dot2[1] = 2.556641 dot2[2] = -2.494141 
test/right_test/bmp_file216.bmp
test/right_test/bmp_file202.bmp
test/right_test/bmp_file217.bmp
test/right_test/bmp_file106.bmp
test/right_test/bmp_file246.bmp
test/right_test/bmp_file193.bmp
test/right_test/bmp_file194.bmp
test/right_test/bmp_file223.bmp
test/right_test/bmp_file230.bmp
test/right_test/bmp_file191.bmp
test/right_test/bmp_file218.bmp
test/right_test/bmp_file241.bmp
Right error is 4

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


2 つ同じファイル名が続いているところがある。どうもこのフォルダのファイルをリストするコードが良くないのかもしれない?
とりあえず、精度を確認してみると、(105 - 6) / 105 * 100 = 94.3 % だった。

C コードの合成を行った。レポートを示す。
ZYBOt_Keras_49_181006
ZYBOt_Keras_50_181006

Estimated は 8.313 ns でLatency は 178833 クロックだった。100 MHz クロックだと、約 1.79 ms となる。
リソース使用量は BRAM_18K が 15 個、DSP48E が 8 個、FF が 970 個、LUT が 2805 個となった。

curve_conv_nn2_axis3.cpp を貼っておく。

// curve_conv_nn2_axis3.cpp
// 2017/09/09 by marsee
// 畳み込み層のカーネル数 2
// AXI4 Stream入力 番号出力
// 2017/09/18 : dot2[3]の出力も追加
// 2017/12/13 : 直線に加えてカーブのデータも使用して学習した
// 2018/10/03 : 家のZYBOtコースでKerasを使用して学習した
//

#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<16, 7, AP_TRN_ZERO, AP_SAT> out[NUM_OF_OUTPUT], ap_uint<2> &out_num);

int course_conv_nn2_axis3(hls::stream<ap_axiu<32,1,1,1> >& ins, ap_uint<2> &outs,
        ap_fixed<16, 7, 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<8, 0, AP_TRN_ZERO, AP_SAT> buf[ROW_PIXELS][COULMN_PIXELS];
    ap_fixed<13, 6, AP_TRN_ZERO, AP_SAT> conv_out[NUM_OF_KERNELS][ROW_PIXELS-4][COULMN_PIXELS-4];
    ap_fixed<13, 6, AP_TRN_ZERO, AP_SAT> pool_out[NUM_OF_KERNELS][(ROW_PIXELS-4)/2][(COULMN_PIXELS-4)/2];
    ap_fixed<16, 7, 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<8, 0, AP_TRN_ZERO, AP_SAT>)((ap_ufixed<16, 8, 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<16, 7, AP_TRN_ZERO, AP_SAT> out[NUM_OF_OUTPUT], ap_uint<2> &out_num){
    int max_id;
    ap_fixed<16, 7, 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);
}



course_conv_nn2_axis3_tb.cpp を貼っておく。(2018/10/06:変更、バグフィックス)

// course_conv_nn2_axis3_tb.cpp
// 2018/10/03 by marsee
// Keras を使用して学習した
//

#include <iostream>
#include "hls_opencv.h"
#include "ap_axi_sdata.h"
#include "hls_video.h"
#include <dirent.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 LOOP_COUNT        35  // test_images
#define LOOP_COUNT    1    // for C/RTL Co-Simulation

//#define STRAIGHT_IMAGE_NAME     "train/straight"
//#define LEFT_IMAGE_NAME    "train/left"
//#define RIGHT_IMAGE_NAME   "train/right"
#define STRAIGHT_IMAGE_NAME     "test/straight_test"
#define LEFT_IMAGE_NAME    "test/left_test"
#define RIGHT_IMAGE_NAME   "test/right_test"

const char CUR_DIR[] = ".";
const char PAR_DIR[] = "..";

int course_conv_nn2_axis3(hls::stream<ap_axiu<32,1,1,1> >& ins, ap_uint<2> &outs,
        ap_fixed<16, 7, 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 loop_count, int correct_data);

int main () {
    char buf[200];

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

    sprintf(buf, "%s", LEFT_IMAGE_NAME);
    main_output_loop(buf, LOOP_COUNT, 0);

    sprintf(buf, "%s", RIGHT_IMAGE_NAME);
    main_output_loop(buf, LOOP_COUNT, 2);

    return(0);
}

int main_output_loop(char *buf, int loop_count, int correct_data){
    char bmp_file_name[200];
    ap_uint<2> outs;
    AXI_STREAM src_axi, dst_axi;
    Mat src;
    ap_fixed<16, 7, AP_TRN_ZERO, AP_SAT> dot2[NUM_OF_OUTPUT];
    int err_num = 0;
    DIR *dir;
    struct dirent *dp;

    if((dir=opendir(buf)) == NULL){
        fprintf(stderr, "%s Open Error\n", buf);
        exit(1);
    }

    for(int i=0; i<loop_count;){
        if((dp=readdir(dir)) == NULL){
            fprintf(stderr, "readdir(dir) == NULL\n");
            exit(1);
        }

        if(strcmp(CUR_DIR, dp->d_name)!=0 && strcmp(PAR_DIR, dp->d_name)!=0){
            sprintf(bmp_file_name, "%s/%s", buf, dp->d_name);
        }else{
            continue;
        }
        printf("%s\n", bmp_file_name);

        // 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);

        course_conv_nn2_axis3(dst_axi, outs, dot2);

        if((int)outs != correct_data){
            //printf("*%s\n", bmp_file_name);
            printf("correct data = %d, outs = %d\n", correct_data, (int)outs);
            for(int i=0; i<NUM_OF_OUTPUT; i++)
                printf("dot2[%d] = %f ", i, (float)dot2[i]);
            printf("\n");
            err_num++;
        }
        i++;
    }
    if(correct_data == 1)
        printf("Straight error is %d\n\n", err_num);
    else if(correct_data == 0)
        printf("Left error is %d\n\n", err_num);
    else // if(correct_data == 2)
        printf("Right error is %d\n\n", err_num);

    closedir(dir);
    return(0);
}

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

    RGB_IMAGE org_img(600, 800);
    GRAY_IMAGE org_img_g(600, 800);
    GRAY_IMAGE resize_img_g(45, 60);
    RGB_IMAGE resize_img(45, 60);

    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. 2018年10月04日 05:33 |
  2. Zybot
  3. | トラックバック:0
  4. | コメント:0

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

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

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


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

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

course_conv_nn2.cpp を貼っておく。

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

#include <ap_fixed.h>

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

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

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

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

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

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

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

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

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

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

        out[col] = dot2[col];
    }

    return(0);
}


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

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

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

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

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



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

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