FC2カウンター FPGAの部屋

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

FPGAの部屋

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

FPGAの部屋のまとめサイトの更新(2017年7月14日)

FPGAの部屋のまとめサイトを更新しました。
DNNAWS-FPGA を追加して、その他のカテゴリーの記事を更新しました。
なお、以前あったDeep Learning はDNN とマージしました。
  1. 2017年07月14日 03:58 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

aws/aws-fpgaをやってみた3

aws/aws-fpgaをやってみた2”の続き。

前回は、デザインをビルドしてみたが、失敗してしまった。今回はシミュレーションを試みてみよう。なお、AWSは使用していないで、ローカルのパソコンで行っている。

今回は、「AWS EC2 F1について、みんなでワイワイ調べる会 サンプルデザインのテストベンチ&テストプログラムを開発するチーム 活動報告 2017.07.08」に基づいてやってみた。
また、元になったマニュアルは、「RTL Simulation for Verilog/VHDL Custom Logic Design with AWS HDK」だ。

まずは、~/aws-fpga/cl/examples/cl_hello_world/verif/scripts ディレクトリのMakefile.vivado とwaves.tcl を修正する。
aws-fpga_12_170710.png

Makefile.vivado のxsim に -g オプションを追加して、GUI を立ち上げる。
aws-fpga_13_170710.png

waves.tcl の quit をコメントアウトした。こうしないとxsim が終了してしまうそうだ。
aws-fpga_14_170710.png

make をしてもエラーだった。
aws-fpga_15_170710.png

そういえば、source hdk_setup.sh を実行した後で、VirtualBox のVM を落としてしまったので、パスなどの設定が無くなってしまったようだ。
もう一度、~/aws-fpga に戻って source hdk_setup.sh を実行した。
、~/aws-fpga/cl/examples/cl_hello_world/verif/scripts ディレクトリに行って、make を実行した。
aws-fpga_17_170710.png

Vivado が立ち上がったが、internal exception が発生してしまった。。。
aws-fpga_16_170710.png

シミュレーションも失敗してしまった。
結局、ビルドもシミュレーションもうまく行かなかった。残念だが、AWS で試したほうが良さそうだ。
  1. 2017年07月12日 04:27 |
  2. AWS-FPGA
  3. | トラックバック:0
  4. | コメント:0

aws/aws-fpgaをやってみた2

aws/aws-fpgaをやってみた1”の続き。

コメント欄で教えて頂いた

expected_memory_usage=30000000

を変更する方法でもう一度やってみた。値は、

expected_memory_usage=16000000

とした。

まずは、~/aws-fpga/hdk/common/shell_stabel/build/scripts/aws_build_dcp_from_cl.sh の45行目の

expected_memory_usage=30000000

expected_memory_usage=16000000

に変更した。
aws-fpga_18_170711.png

「AWS EC2 F1についえ、みんなでワイワイ調べる会 カスタムロジックサンプル解析 CLサンプル解析班」の資料の14ページを参考に記述を変更した。

~/aws-fpga/hdk/common/shell_stabel/build/scripts/aws_build_dcp_from_cl.sh の42 行目の foreground を 1 に変更した。
aws-fpga_19_170711.png

同じく、aws_build_dcp_from_cl.sh の 218 行目の -mode batch を削除した。
aws-fpga_20_170711.png

~/aws-fpga/cl/examples/cl_hello_world/build/scripts/encrypt.tcl の encrypt -k で始まる行をコメントアウトした。
aws-fpga_22_170711.png

これは資料には書いていなかったが、CL_DIR 環境変数を ~/aws-fpga/cl/examples/cl_hello_world に指定した。
aws-fpga_21_170711.png

./aws_build_dcp_from_cl.sh
を起動した。
aws-fpga_24_170711.png

Vivado は立ち上がったがライセンス・エラーになった。xcvu9p-flgb2104 のライセンスはあるのだが?
aws-fpga_23_170711.png

エラー・メッセージを示す。

[Common 17-348] Failed to get the license for feature 'Synthesis' and/or device 'xcvu9p-flgb2104'. Explanation: The license feature Synthesis could not be found.
Resolution: Check the status of your licenses in the Vivado License Manager. For debug help search Xilinx Support for "Licensing FAQ".


Vivado 2017.1 を立ち上げて、xcvu9p-flgb2104 のプロジェクトも作ることができる。
aws-fpga_25_170711.png

Ubuntu 14.04 にVivado 2017.1 をインストールするのは仕様外なので仕方ないかもしれない?
おかしなことに、ライセンスは入れたのだが、Vivado License Manager ではライセンスは見えないのだ?
やはり、サポート対象のUbuntu 16.04 にVivado 2017.1 を入れる必要があるだろう。通常はVivado Design Editionをインストールすることができないので、”Ubuntu 16.04 にVivado Design Edition がインストールできない”のコメント欄を参照のこと。

やはり、AWSを使ってやった方が良さそうだ。。。

これ以上は面倒になったので、詳しくは、「AWS EC2 F1についえ、みんなでワイワイ調べる会 カスタムロジックサンプル解析 CLサンプル解析班」の資料の「回路図を表示させてみよう(4)」以降のページをご覧ください。。。(資料を作ってくれてありがとうございました)
  1. 2017年07月11日 04:50 |
  2. AWS-FPGA
  3. | トラックバック:0
  4. | コメント:0

aws/aws-fpgaをやってみた1

2017年7月8日(土)に、「AWS EC2 F1について、みんなでワイワイ調べる会」に参加して、「サンプルデザインのHDLコードを解析するチーム(Hello World & DMA)」になったのだが、「Ubuntu 16.04 にVivado Design Edition がインストールできない」という理由でVirtualBox 上のUbuntu 16.04 にVivado WebPACK Edition しかインストールしていなくて、たいして貢献できなくて申し訳ないので、Ubuntu 14.04 上にVivado をインストールしてリベンジしてみた。

最初に、VirtualBox 上に最新版の Vivado 2017.2 をインストールしてみた。
次に、aws/aws-fpga からgit clone した。詳しくはWeb サイトを見てほしい。
git clone https://github.com/aws/aws-fpga
aws-fpga_1_170709.png

cd aws-fpga
source hdk_setup.sh

HostID_all0_2_170709.png

やはり、指定では、Vivado 2017.1 なのに、2017.2 をインストールしたので、エラーが出てしまった。
~/aws-fpga/hdk/supported_vivado_versions.txt を見ると 2017.1 と書いてあったので、2017.2 に書き換えた。
aws-fpga_3_170709.png

もう一度、
source hdk_setup.sh
を実行すると、curl がインストールされていないというエラーだった。
aws-fpga_4_170709.png

sudo apt-get install curl でインストールした。
もう一度、source hdk_setup.shを実行した。良い感じで実行されていたが。。。
aws-fpga_4_170709.png

IP Catalog の revision が違うというエラーになってしまった。Vivado のバージョンが違うので仕方がない。。。
aws-fpga_6_170709.png

と言う訳で、せっかくインストールしたVivado Design Edition 2017.2 をアンインストールして、Vivado Design Edition 2017.2 をインストールした。
再再度、source hdk_setup.shを実行した。今度は通った。図は始まりと終わりを示す。
aws-fpga_7_170709.png
aws-fpga_8_170709.png

全部のログを示す。

masaaki@masaaki-VirtualBox:~/aws-fpga$ source hdk_setup.sh 
INFO: Using Vivado v2017.1 (64-bit)
INFO: Setting up environment variables
INFO: Using HDK shell version shell_v04151701
INFO: HDK shell is up-to-date
INFO: DDR4 model files in /home/masaaki/aws-fpga/hdk/common/verif/models/ddr4_model/ do NOT exist. Running model creation step.
INFO:   Building in /home/masaaki/aws-fpga/ddr4_model_build
INFO:   This could take 5-10 minutes, please be patient!
/home/masaaki/aws-fpga/hdk/common/verif/scripts/init.sh: 18: /home/masaaki/aws-fpga/hdk/common/verif/scripts/init.sh: [[: not found
/home/masaaki/aws-fpga/hdk/common/verif/scripts/init.sh: 23: /home/masaaki/aws-fpga/hdk/common/verif/scripts/init.sh: [[: not found
/home/masaaki/aws-fpga/hdk/common/verif/scripts/init.sh: 29: /home/masaaki/aws-fpga/hdk/common/verif/scripts/init.sh: [[: not found

****** Vivado v2017.1 (64-bit)
  **** SW Build 1846317 on Fri Apr 14 18:54:47 MDT 2017
  **** IP Build 1846188 on Fri Apr 14 20:52:08 MDT 2017
    ** Copyright 1986-2017 Xilinx, Inc. All Rights Reserved.

source /home/masaaki/aws-fpga/hdk/common/verif/scripts/init.tcl
# set_msg_config -severity INFO -suppress
# set_msg_config -severity STATUS -suppress
# set_msg_config -severity WARNING -suppress
CRITICAL WARNING: [Common 17-1355] You are suppressing all messages of type 'WARNING'. You may potentially disregard important DRC, CDC, and implementation messages that can negatively impact your design.  If this is not desired, please run 'reset_msg_config -suppress -severity {WARNING}' to undo this change.
# set_msg_config -string {exportsim} -suppress
# set_msg_config -string {IP_Flow} -suppress
# create_project -force tmp_ddr ./tmp -part xcvu9p-flgb2104-2-i 
# add_files -norecurse $::env(HDK_COMMON_DIR)/shell_stable/design/ip/ddr4_core/ddr4_core.xci
INFO: [IP_Flow 19-234] Refreshing IP repositories
INFO: [IP_Flow 19-1704] No user IP repositories specified
INFO: [IP_Flow 19-2313] Loaded Vivado IP repository '/opt/Xilinx/Vivado/2017.1/data/ip'.
add_files: Time (s): cpu = 00:00:05 ; elapsed = 00:00:07 . Memory (MB): peak = 1308.211 ; gain = 213.969 ; free physical = 474 ; free virtual = 18367
# export_ip_user_files -of_objects  [get_files  $::env(HDK_COMMON_DIR)/shell_stable/design/ip/ddr4_core/ddr4_core.xci] -force -quiet
# open_example_project -force -dir ./tmp/tmp_ddr_ex [get_ips  ddr4_core]
INFO: [IP_Flow 19-1686] Generating 'Examples' target for IP 'ddr4_core'...
INFO: [Device 21-403] Loading part xcvu9p-flgb2104-2-i

****** Vivado v2017.1 (64-bit)
  **** SW Build 1846317 on Fri Apr 14 18:54:47 MDT 2017
  **** IP Build 1846188 on Fri Apr 14 20:52:08 MDT 2017
    ** Copyright 1986-2017 Xilinx, Inc. All Rights Reserved.

source /home/masaaki/aws-fpga/hdk/common/shell_stable/design/ip/ddr4_core/ddr4_core_ex.tcl -notrace
INFO: [open_example_project] Creating new example project...
INFO: [open_example_project] Importing original IP ...
INFO: [IP_Flow 19-234] Refreshing IP repositories
INFO: [IP_Flow 19-1704] No user IP repositories specified
INFO: [IP_Flow 19-2313] Loaded Vivado IP repository '/opt/Xilinx/Vivado/2017.1/data/ip'.
import_ip: Time (s): cpu = 00:00:05 ; elapsed = 00:00:06 . Memory (MB): peak = 1316.215 ; gain = 8.012 ; free physical = 219 ; free virtual = 17375
INFO: [open_example_project] Generating the example project IP ...
INFO: [open_example_project] Adding example synthesis HDL files ...
INFO: [open_example_project] Adding example XDC files ...
INFO: [open_example_project] Adding simulation HDL files ...
INFO: [open_example_project] Sourcing example extension scripts ...
Post processing the example_design
update_compile_order: Time (s): cpu = 00:00:08 ; elapsed = 00:00:09 . Memory (MB): peak = 1316.645 ; gain = 0.418 ; free physical = 311 ; free virtual = 17369
INFO: [open_example_project] Rebuilding all the top level IPs ...
INFO: [exportsim-Tcl-35] Exporting simulation files for "XSIM" (Xilinx Vivado Simulator)...
INFO: [exportsim-Tcl-29] Script generated: '/home/masaaki/aws-fpga/ddr4_model_build/tmp/tmp_ddr_ex/ddr4_core_ex/ddr4_core_ex.ip_user_files/sim_scripts/ddr4_core/xsim/ddr4_core.sh'
Generating merged BMM file for the design top 'sim_tb_top'...
Generating merged BMM file for the design top 'sim_tb_top'...
INFO: [exportsim-Tcl-35] Exporting simulation files for "MODELSIM" (Mentor Graphics ModelSim Simulator)...
INFO: [exportsim-Tcl-29] Script generated: '/home/masaaki/aws-fpga/ddr4_model_build/tmp/tmp_ddr_ex/ddr4_core_ex/ddr4_core_ex.ip_user_files/sim_scripts/ddr4_core/modelsim/ddr4_core.sh'
INFO: [exportsim-Tcl-35] Exporting simulation files for "QUESTA" (Mentor Graphics Questa Advanced Simulator)...
INFO: [exportsim-Tcl-29] Script generated: '/home/masaaki/aws-fpga/ddr4_model_build/tmp/tmp_ddr_ex/ddr4_core_ex/ddr4_core_ex.ip_user_files/sim_scripts/ddr4_core/questa/ddr4_core.sh'
INFO: [exportsim-Tcl-35] Exporting simulation files for "IES" (Cadence Incisive Enterprise Simulator)...
INFO: [exportsim-Tcl-29] Script generated: '/home/masaaki/aws-fpga/ddr4_model_build/tmp/tmp_ddr_ex/ddr4_core_ex/ddr4_core_ex.ip_user_files/sim_scripts/ddr4_core/ies/ddr4_core.sh'
INFO: [exportsim-Tcl-35] Exporting simulation files for "VCS" (Synopsys Verilog Compiler Simulator)...
INFO: [exportsim-Tcl-29] Script generated: '/home/masaaki/aws-fpga/ddr4_model_build/tmp/tmp_ddr_ex/ddr4_core_ex/ddr4_core_ex.ip_user_files/sim_scripts/ddr4_core/vcs/ddr4_core.sh'
INFO: [exportsim-Tcl-35] Exporting simulation files for "RIVIERA" (Aldec Riviera-PRO Simulator)...
INFO: [exportsim-Tcl-29] Script generated: '/home/masaaki/aws-fpga/ddr4_model_build/tmp/tmp_ddr_ex/ddr4_core_ex/ddr4_core_ex.ip_user_files/sim_scripts/ddr4_core/riviera/ddr4_core.sh'
INFO: [exportsim-Tcl-35] Exporting simulation files for "ACTIVEHDL" (Aldec Active-HDL Simulator)...
INFO: [exportsim-Tcl-29] Script generated: '/home/masaaki/aws-fpga/ddr4_model_build/tmp/tmp_ddr_ex/ddr4_core_ex/ddr4_core_ex.ip_user_files/sim_scripts/ddr4_core/activehdl/ddr4_core.sh'
INFO: [open_example_project] Open Example Project completed
INFO: [Common 17-206] Exiting Vivado at Sun Jul  9 18:03:27 2017...
open_example_project: Time (s): cpu = 00:00:36 ; elapsed = 00:00:44 . Memory (MB): peak = 2018.074 ; gain = 678.875 ; free physical = 531 ; free virtual = 17600
# exit
INFO: [Common 17-206] Exiting Vivado at Sun Jul  9 18:03:28 2017...
Copying files to /home/masaaki/aws-fpga/hdk/common/verif/models/ddr4_model
Copying files to /home/masaaki/aws-fpga/hdk/common/verif/models/ddr4_rdimm_wrapper
INFO: DDR4 model build passed.
INFO: ATTENTION: Don't forget to set the CL_DIR variable for the directory of your Custom Logic.
INFO: AWS HDK setup PASSED.
masaaki@masaaki-VirtualBox:~/aws-fpga$ 


何がどうなっているか、よくわからないがとにかく通った。

~/aws-fpga/hdk/cl/examples を見ると、cl_dram_dma, cl_hello_world, common のディレクトリがある。
そのうちの cl_hello_world をやってみることにする。
aws-fpga_9_170709.png

~/aws-fpga/hdk/cl/examples/cl_hello_world/build/scripts ディレクトリに行ってみた。
aws-fpga_10_170709.png

Vivado のプロジェクトはないので、「How to build and submit your Custom Logic (CL) to AWS」を参考に、とりあえず、~/aws-fpga/hdk/cl/examples/cl_hello_world/build/scripts ディレクトリで
./aws_build_dcp_from_cl.sh
をやってみたが、エラーになってしまった。
aws-fpga_11_170710.png

エラーの内容は、

ERROR: YOUR INSTANCE has less memory than is necessary for certain builds. This means that your builds will take longer than expected.
To change to an instance type with more memory, please check our instance resize guide: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-resize.html

で、メモリは10GB 程度割り当てているのだが、だめだそうだ。
やはり、この辺りはAWS EC2 F1 インスタンスを使ってビルドするしかないのかもしれない?
  1. 2017年07月10日 04:36 |
  2. AWS-FPGA
  3. | トラックバック:0
  4. | コメント:2

「メアリと魔女の花」(映画)を見てきました

今日は、「メアリと魔女の花」(映画)を見てきました。良くも悪くもジブリらしい映画でした。
良かったのですが、もうちょっと、新機軸のアニメ映画を見てみたい気もしました。
  1. 2017年07月09日 20:40 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Ubuntu 16.04 にVivado Design Edition がインストールできない

Ubuntu 16.04 にVivado のDesign Edition がインストールできない。(現在のバージョンは、2017.2)

理由は、HostID が ”000000000000”になってしまうからだ。
HostID_all0_1_170709.png

原因は、Ubuntu 16 では、イーサネットの名前が enp0s3 とかになってしまって、eth0 が無くなってしまったからのようだ。
HostID_all0_2_170709.png

AR# 60510 ライセンス - Vivado License Manager (VLM) に使用するマシンの HostID が「000000000000」と表示される”を見つけてやってみたが、私のUbuntu 16.04 ではファイルが無いと言われてダメだった。

Vivado のライセンス・マネージャーがUbuntu 16.04 に対応してくれることを望む。
(2017/07/10:まっちゃんさんのアドバイスのおかげで eth0 にできました。ありがとうございました。詳しくはコメント欄をご覧ください。)

なお、WebPACKはライセンスが必要ないので、問題なくインストールすることができた。
Ubuntu16.04にVivado 2016.4をインストール”を参照。
  1. 2017年07月09日 08:48 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:3

手書き数字認識用畳み込みニューラルネットワーク回路の製作7(ハードとソフトの比較)

手書き数字認識用畳み込みニューラルネットワーク回路の製作6(PYNQボードで動作確認)”の続き。

前回は、mnist_conv_nn_test.c を作成して、手書き数字を認識してみたところ、今のところ 100 % の精度で手書き数字を認識することができた。今回は、ハードウェアのMNISTの手書き数字を認識する時間とソフトウェアでMNISTの手書き数字を認識する時間を比較してみようと思う。

ハードウェアの手書き数字を認識時間とソフトウェアの手書き数字を認識時間を比べるためにmnist_conv_soft_test.c を作成した。ソフトウェアの手書き数字の認識は、float で演算している。更に、カーソルを動かすのが面倒なため、それぞれの方向キーをシフトキーを押したときに、5ピクセルずつ移動できるように改良した。なお、時間の計測には、”SDKのベアメタル・アプリケーションで時間を計測する方法(Zynq)”で試したXTime_GetTime() を使用している。
hand_draw_num_100_170708.png

mnist_conv_soft_test.elf を起動して、1 を認識してみた。
hand_draw_num_90_170706.png

ハードウェアの実行時間は 12.9 ms 程度、ソフトウェアの実行時間は 34.2 ms 程度だった。ハードウェアの方がソフトウェアより、約 2.66 倍速い。

2 を認識してみた。
hand_draw_num_91_170706.png

3 を認識してみた。
hand_draw_num_92_170706.png

4 を認識してみた。
hand_draw_num_93_170706.png

5 を認識してみた。
hand_draw_num_94_170706.png

6 を認識してみた。
hand_draw_num_95_170706.png

7 を認識してみた。
hand_draw_num_96_170706.png

8 を認識してみた。
hand_draw_num_97_170706.png

9 を認識してみた。
hand_draw_num_98_170706.png

0 を認識してみた。
hand_draw_num_99_170706.png

ハードウェアの実行時間はほとんど変動はない。ソフトウェアの実行時間にもそれほど変動はないので、約 2.7 倍ハードウェアの方が速いという結果だった。ハードウェア、ソフトウェア共に精度は今のところ 100 % だった。
ソフトウェアの方が float というハンデはあるが、ハードウェアの方が速かった。だが、ソフトウェアもチューニングするとどうなるかわからないと思う。まあ、ハードウェアにオフロードして、仕様を満足できたので良かったと思う。

最後に、mnist_conv_soft_test.c を貼っておく。
なお、

float buf[28][28];
float conv_out[10][24][24];
float pool_out[10][12][12];
float dot1[100];
float dot2[10];

をグローバル変数にしたのは、ローカル変数にしていては動作がおかしかったからだ。スタックに積むことができる大きさに制限があるのかもしれない?

/* * mnist_conv_soft_test.c * *  Created on: 2017/07/06 *      Author: ono */

#include <stdio.h>
#include <stdlib.h>
#include "xaxivdma.h"
#include "xil_io.h"
#include "xparameters.h"
#include "sleep.h"
#include "xgpio.h"
#include "xtime_l.h"

#include "xmnist_conv_nn.h"
#include "xsquare_frame_gen.h"
#include "af1_bias_float.h"
#include "af1_weight_float.h"
#include "af2_bias_float.h"
#include "af2_weight_float.h"
#include "conv1_bias_float.h"
#include "conv1_weight_float.h"

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

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

int max_int(int out[10]);
int max_float(float out[10]);
int mnist_conv_nn_float(int in[22400], int addr_offset, float out[10]);
float conv_rgb2y_soft(int rgb);

static XAxiVdma_DmaSetup Vdma0_WriteCfg;
float buf[28][28];
float conv_out[10][24][24];
float pool_out[10][12][12];
float dot1[100];
float dot2[10];

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

void cam_i2x_write_sync(void) {
    // unsigned c;

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

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

int main(){
    XMnist_conv_nn mcnn;
    XSquare_frame_gen sf_gen;
    int inbyte_in;
    int xval, yval;
    int i, res;
    int result[10];
    float result_float[10];
    static XGpio GPIOInstance_Ptr;
    int XGpio_Status;
    int max_id;
    XAxiVdma_Config *XAxiVdma0_Config;
    XAxiVdma XAxiVdma0;
    int XAxiVdma0_Status;
    int result_disp = 0;
    int conv_addr;
    int max_id_float;
    XTime start_time, end_time;

    // AXI VDMA Initialization sequence
    XAxiVdma0_Config = XAxiVdma_LookupConfig(XPAR_CAMERA_INTERFACE_AXI_VDMA_0_DEVICE_ID); // Look up the hardware configuration for a device instance
    if (XAxiVdma0_Config == NULL){
        fprintf(stderr, "No AXI VDMA found\n");
        return(-1);
    }

    XAxiVdma0_Status = XAxiVdma_CfgInitialize(&XAxiVdma0, XAxiVdma0_Config, XAxiVdma0_Config->BaseAddress); // Initialize the driver with hardware configuration
    if (XAxiVdma0_Status != XST_SUCCESS){
        fprintf(stderr, "XAxiVdma_CfgInitialize() failed\n");
        return(-1);
    }

    XAxiVdma_Reset(&XAxiVdma0, XAXIVDMA_WRITE);
    while(XAxiVdma_ResetNotDone(&XAxiVdma0, XAXIVDMA_WRITE)) ;

    XAxiVdma0_Status = XAxiVdma_SetFrmStore(&XAxiVdma0, NUMBER_OF_WRITE_FRAMES, XAXIVDMA_WRITE); // Set the number of frame store buffers to use.

    Vdma0_WriteCfg.VertSizeInput = VERTICAL_LINES;
    Vdma0_WriteCfg.HoriSizeInput = HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES;
    Vdma0_WriteCfg.Stride = HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES; // Indicates the number of address bytes between the first pixels of each video line.
    Vdma0_WriteCfg.FrameDelay = 0// Indicates the minimum number of frame buffers the Genlock slave is to be behind the locked master. This field is only used if the channel is enabled for Genlock Slave operations. This field has no meaning in other Genlock modes.
    Vdma0_WriteCfg.EnableCircularBuf = 1// Indicates frame buffer Circular mode or frame buffer Park mode.  1 = Circular Mode Engine continuously circles through frame buffers.
    Vdma0_WriteCfg.EnableSync = 0// Enables Genlock or Dynamic Genlock Synchronization. 0 = Genlock or Dynamic Genlock Synchronization disabled.
    Vdma0_WriteCfg.PointNum = 0// No Gen-Lock
    Vdma0_WriteCfg.EnableFrameCounter = 0// Endless transfers
    Vdma0_WriteCfg.FixedFrameStoreAddr = 0// We are not doing parking

    XAxiVdma0_Status = XAxiVdma_DmaConfig(&XAxiVdma0, XAXIVDMA_WRITE, &Vdma0_WriteCfg);
    if (XAxiVdma0_Status != XST_SUCCESS){
        fprintf(stderr, "XAxiVdma_DmaConfig() failed\n");
        return(-1);
    }

    // Frame buffer address set
    unsigned int frame_addr = (unsigned int)FRAME_BUFFER_ADDRESS;
    for (i=0; i<NUMBER_OF_WRITE_FRAMES; i++){
        Vdma0_WriteCfg.FrameStoreStartAddr[i] = frame_addr;
        //frame_addr += HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES * VERTICAL_LINES;
    }

    XAxiVdma0_Status = XAxiVdma_DmaSetBufferAddr(&XAxiVdma0, XAXIVDMA_WRITE, Vdma0_WriteCfg.FrameStoreStartAddr);
    if (XAxiVdma0_Status != XST_SUCCESS){
        fprintf(stderr, "XAxiVdma_DmaSetBufferAddr() failed\n");
        return(-1);
    }

    // Mnist_conv_nn, Square_frame_gen Initialize
    XMnist_conv_nn_Initialize(&mcnn, 0);
    XSquare_frame_gen_Initialize(&sf_gen, 0);

    // square_frame_gen initialize
    XSquare_frame_gen_Set_x_pos(&sf_gen, HORIZONTAL_PIXELS/2);
    xval = HORIZONTAL_PIXELS/2;
    XSquare_frame_gen_Set_y_pos(&sf_gen, VERTICAL_LINES/2);
    yval = VERTICAL_LINES/2;
    XSquare_frame_gen_Set_width(&sf_gen, 28);
    XSquare_frame_gen_Set_height(&sf_gen, 28);
    XSquare_frame_gen_Set_off_on(&sf_gen, 1); // on

    // XSquare_frame_gen start
    XSquare_frame_gen_DisableAutoRestart(&sf_gen);
    while(!XSquare_frame_gen_IsIdle(&sf_gen)) ;
    XSquare_frame_gen_Start(&sf_gen);
    XSquare_frame_gen_EnableAutoRestart(&sf_gen);

    // mnist_conv_nn initialize
    XMnist_conv_nn_Set_addr_offset(&mcnn, HORIZONTAL_PIXELS/2);
    XMnist_conv_nn_Set_in_r(&mcnn, FRAME_BUFFER_ADDRESS+HORIZONTAL_PIXELS*(VERTICAL_LINES/2)*sizeof(int));

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

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

    // VDMA start
    XAxiVdma0_Status = XAxiVdma_DmaStart(&XAxiVdma0, XAXIVDMA_WRITE);
    if (XAxiVdma0_Status != XST_SUCCESS){
        fprintf(stderr, "XAxiVdma_DmaStart() failed\n");
        return(-1);
    }

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

    bmdc_axi_lites = (volatile unsigned *)XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_0_BASEADDR;
    mt9d111_axi_lites = (volatile unsigned *)XPAR_CAMERA_INTERFACE_MT9D111_INF_AXIS_0_BASEADDR;
    mt9d111_i2c_axi_lites = (volatile unsigned *)XPAR_CAMERA_INTERFACE_AXI_IIC_0_BASEADDR;

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

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

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

    mt9d111_axi_lites[1] = 0// One_shot_mode is disabled

    // AXI GPIO Initialization
    XGpio_Status = XGpio_Initialize(&GPIOInstance_Ptr,XPAR_AXI_GPIO_0_DEVICE_ID);
    if(XST_SUCCESS != XGpio_Status)
        print("GPIO INIT FAILED\n\r");
    // AXI GPIO Set the Direction(output setting)
    XGpio_SetDataDirection(&GPIOInstance_Ptr, 10);

    while(1){
        printf("mnist_conv_nn_test, <h> : left, <k> : up, <j> : down, <l> : right, <q> : exit\n");
        inbyte_in = inbyte();
        switch(inbyte_in) {
            case 'h' : // left
            case 'H' : // left -5
                if(inbyte_in == 'h' && xval > 0)
                    --xval;
                else if(inbyte_in == 'H' && xval >= 5)
                    xval -= 5;
                XSquare_frame_gen_Set_x_pos(&sf_gen, xval);
                XMnist_conv_nn_Set_addr_offset(&mcnn, xval);
                printf("X_POS = %d, Y_POS = %d\n", xval, yval);
                break;
            case 'l' : // right
            case 'L' : // right +5
                if(inbyte_in == 'l' && xval < HORIZONTAL_PIXELS-28)
                    xval++;
                else if(inbyte_in == 'L' && xval <= HORIZONTAL_PIXELS-28-5)
                    xval += 5;
                XSquare_frame_gen_Set_x_pos(&sf_gen, xval);
                XMnist_conv_nn_Set_addr_offset(&mcnn, xval);
                printf("X_POS = %d, Y_POS = %d\n", xval, yval);
                break;
            case 'k' : // up
            case 'K' : // up -5
                if(inbyte_in == 'k' && yval > 0)
                    --yval;
                else if(inbyte_in == 'K' && yval >= 5)
                    yval -= 5;
                XSquare_frame_gen_Set_y_pos(&sf_gen, yval);
                XMnist_conv_nn_Set_in_r(&mcnn, FRAME_BUFFER_ADDRESS+HORIZONTAL_PIXELS*yval*sizeof(int));
                printf("X_POS = %d, Y_POS = %d\n", xval, yval);
                break;
            case 'j' : // down
            case 'J' : // down +5
                if(inbyte_in == 'j' && xval < VERTICAL_LINES-28)
                    yval++;
                else if(inbyte_in == 'J' && xval <= VERTICAL_LINES-28-5)
                    yval += 5;
                XSquare_frame_gen_Set_y_pos(&sf_gen, yval);
                XMnist_conv_nn_Set_in_r(&mcnn, FRAME_BUFFER_ADDRESS+HORIZONTAL_PIXELS*yval*sizeof(int));
                printf("X_POS = %d, Y_POS = %d\n", xval, yval);
                break;
            case 'r' : // result check
                result_disp = 1;
                break;
            case 'q' : // exit
                return(0);
        }

        if(result_disp){
            printf("\nHardware\n");
            // XMnist_conv_nn start
            XMnist_conv_nn_DisableAutoRestart(&mcnn);
            while(!XMnist_conv_nn_IsIdle(&mcnn));
            XTime_GetTime(&start_time);
            XMnist_conv_nn_Start(&mcnn);
            while(!XMnist_conv_nn_IsIdle(&mcnn));
            XTime_GetTime(&end_time);
            printf("conv_time = %f ms\n", (float)((long)end_time-(long)start_time)/325000.0);

            // mnist cnn result check
            for(i=0; i<5; i++){
                XMnist_conv_nn_Read_out_V_Words(&mcnn, i, &res, 1);
                result[i*2] = res & 0x0fff;
                if(result[i*2] & 0x800// minus
                    result[i*2] = 0xfffff000 | result[i*2]; // Sign extension

                result[i*2+1] = (res & 0x0fff0000) >> 16;
                if(result[i*2+1] & 0x800// minus
                    result[i*2+1] = 0xfffff000 | result[i*2+1]; // Sign extension
            }

            max_id = max_int(result);
            XGpio_DiscreteWrite(&GPIOInstance_Ptr, 1, max_id);

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

            printf("\nSoftware\n");
            conv_addr = FRAME_BUFFER_ADDRESS+HORIZONTAL_PIXELS*yval*sizeof(int);
            XTime_GetTime(&start_time);
            mnist_conv_nn_float((int *)conv_addr, xval, result_float);
            XTime_GetTime(&end_time);
            max_id_float = max_float(result_float);
            printf("conv_time = %f ms\n", (float)((long)end_time-(long)start_time)/325000.0);
            for(i=0; i<10; i++){
                printf("result_float[%d] = %f\n", i, result_float[i]);
            }
            printf("max_id_float = %d\n", max_id_float);

            result_disp = 0;
        }
    }
}

int max_int(int out[10]){
    int max_id;
    int max, i;

    for(i=0; i<10; i++){
        if(i == 0){
            max = out[0];
            max_id = 0;
        }else if(out[i]>max){
            max = out[i];
            max_id = i;
        }
    }
    return(max_id);
}

int mnist_conv_nn_float(int in[22400], int addr_offset, float out[10]){

    // 手書き数字の値を表示
    /*for (int i=0; i<28; i++){        for (int j=0; j<800; j++){            if (j>=addr_offset && j<addr_offset+28)                printf("%2x, ", (int)(conv_rgb2y_soft(in[i*800+j])*256.0));        }        printf("\n");    } */

    buf_copy1: for(int i=0; i<28; i++){
        buf_copy2: for(int j=0; j<800; j++){
            if (j>=addr_offset && j<addr_offset+28)
                buf[i][j-addr_offset] = (float)0.99609375 - (float)conv_rgb2y_soft(in[i*800+j]);
        }
    }

    // Convolutional Neural Network 5x5 kernel, Stride = 1, Padding = 0
    // + ReLU
    CONV1: for(int i=0; i<10; i++){    // カーネルの個数
        CONV2: for(int j=0; j<24; j++){
            CONV3: for(int k=0; k<24; 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_fweight[i][0][m][n];
                    }
                }
                conv_out[i][j][k] += conv1_fbias[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<10; i++){
        POOL2: for(int j=0; j<24; j += 2){
            POOL3: for(int k=0; k<24; 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<10; i++){
            af1_dot3: for(int j=0; j<12; j++){
                af1_dot4: for(int k=0; k<12; k++){
                    dot1[col] += pool_out[i][j][k]*af1_fweight[i*12*12+j*12+k][col];
                }
            }
        }
        dot1[col] += af1_fbias[col];

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

    af2_dot1: for(int col=0; col<10; col++){
        dot2[col] = 0;
        af2_dot2: for(int row=0; row<100; row++){
            dot2[col] += dot1[row]*af2_fweight[row][col];
        }
        dot2[col] += af2_fbias[col];

        out[col] = dot2[col];
    }

    return(0);
}

int max_float(float out[10]){
    int max_id;
    float max;

    for(int i=0; i<10; i++){
        if(i == 0){
            max = out[0];
            max_id = 0;
        }else if(out[i]>max){
            max = out[i];
            max_id = i;
        }
    }
    return(max_id);
}


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

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

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

    if (y >= 256)
        y = 255;

    y_float = (float)y/256.0;

    return(y_float);
}

  1. 2017年07月08日 04:50 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0