ラベル TE0720 の投稿を表示しています。 すべての投稿を表示
ラベル TE0720 の投稿を表示しています。 すべての投稿を表示

2017年8月12日土曜日

TE0720 No.4 (BNN-PYNQを動かしてみる 2)

TE0720でBNN-PYNQを動かすことが出来た。
以下は前回に続いてBNN-PYNQが動くまでの記録。

gdb (GNU debugger)で例外が出る原因を調べてみた。
例外が発生しているのはシェアードライブラリ(python_hw-cnv-pynq.so)の中であり、これはpythonからダイナミックリンクされるのでpythonごと gdb で追えば何か判るのではないかと考えた。

run ./x.py としてx.pyスクリプトを実行させると、以下のようにSIGILLシグナルを受けて停止したが、かまわず cont と打って実行を継続させた。

すると、あのterminate called after throwing an instance of 'char const*'というメッセージが表示され、SIGABRTシグナルを受けてプログラムが停止した。ここでバックトレースを確認した。


関数FoldedMVInitの400行目で例外がthrowされているようだ。python_hw-cnv-pynq.soはデバッグ用の情報も付いているようなので、gdbを一旦終了しBNN-PYNQのソースファイルを/home/xilinx/test-newswg/下に展開してgdbを起動して上述と同じところまで操作した。
次に関数 FoldedMVInitをリスト表示し400行目付近を見てみた。

accelBuffer用の領域確保に失敗して例外を投げているようだ。そこで397行目にブレークポイントを設定してプログラムを再実行した。



accelBufInの確保も失敗してnullポインタが返ってきているようだ。
そこで、今度はallocAccelBuffer関数の中を追ってみることにした。

allocAccelBuffer内部では引数をcma_allocに渡してcma領域を確保していた。cma_allocはContiguous memory allocatorでカーネル内部に物理アドレスが連続したバッファを確保するための関数らしい。今の場合は30MB分の連続領域を確保しようとしている。ステップ実行したところ、cma_allocからnullポインタが返っていることが判った。

現在のOSのcma領域がどうなっているか確認したところ、そもそも全体でも16MB分の領域しかないことが判った。


そこで容量を128MBに増やしてみた。


増量して、cma_allocをコールする直前での空き容量を見ると70MBあるので今度は大丈夫の筈だが、ステップ実行してcma_allocからの戻り値を見るとnullポインタが返されていた。


そこで、今度はcma_allocの中を追ってみることにした。cma_allocのソースファイルは無いので、アセンブラレベルでのステップ実行になったが、その結果 ioctl コールでエラーが返っていることが判った。






現状のカーネルはpetalinuxのカーネルでバージョンは4.9.0なのだが、もしかしたらcma_allocのioctlコールの引数仕様がカーネル4.9.0で動作しているデバイスドライバの仕様と違っているのかも知れない。そこで、カーネルをPYNQのカーネルに代えてみることにしたのだが、カーネルのファイル名やファイル形式、デバイスツリーのファイル名等がpetalinuxとPYNQとでは異なっており、そのためにu-bootも変更することになってしまった。ところが、Xilinxのgitリポジトリからu-bootをcloneしてビルドして動かしてみたところ、mmcを認識しない。。。仕方がないのでZYBOのu-bootを使うことにした。


上記構成のSDカードにして起動し x.py を実行したところ例外は発生しなくなった。

PYNQのカーネルのバージョンは4.6.0だった。4.6.0と4.9.0ではcma_alloc関連の仕様が変わっているのかも知れない。また、4.9.0ではFPGAのコンフィグレーションのFPGA managerが追加になっているのでそれに関連してxdevcfgも変わっている可能性もある。。 ともあれ、例外が発生しなくなったのでjupyter notebookでCifar10.ipynbを実行してみた。


実行できた!!

で、推論をハードウェアで実行(PLにダウンロードして実行)した場合とソフトウェアのみで実行した場合との差は801108 / 3199 = 250倍となった。 ARMのシングルコアのみで実行するよりも推論部をPLにダウンロードしてハードで実行させると250倍高速に実行できた、ということだ。本物のPYNQボードだとどの位なんだろうか?





Road-Signs-Batch(道路標識の識別)も実行してみた。


こちらも実行できた。




カーネル 4.9.0でioctlがなぜsyscall エラーになるのかという点など、まだ頭の中に?マークがあるが、なんとか動くようになったので良かった。 ワーイ \(^_^)/


2017年8月6日日曜日

TE0720 No.3 (BNN-PYNQを動かしてみる)

今度は BNN-PYNQ をTE0720で動かせるかをやってみている。
BNNはBinarized Neural Network (BNN) (2値化ニューラルネットワーク)のことで、BNN-PYNQはPYNQ-Z1ボードのシステム向けのBNNの実装だ。PYNQ-Z1に搭載されているZynqデバイスはZYNQ XC7Z020-1CLG400C、TE0720のそれはXC7Z020-1CLG484Cであり、ピン数は異なるがコアは同じXC7Z020なので動くんじゃないかと考えた。そのためには、PYNQ用のLinuxシステムをTE0720で動かす必要がある。PYNQ-Z1のprecompiled image(pynq_z1_image_2017_02_10.zipPYNQのGitHubからダウンロードして中を見てみた。

pynq_z1_image_2017_02_10.imgはディスクまるごとのイメージでboot用パーティションとrootfs用のパーティションが入っている。そこで、それぞれのパーティションのイメージをddコマンドで抽出した。

必要なのはrootfsの方なので、これをcpioイメージに変換しておく。

前回のブログで作成したpetalinuxのSDカードのrootfsパーティションの内容を、抽出したPYNQのrootfsに書き換え、TE0720に装着して起動してみた。

起動してコマンドプロンプト表示まで行くのだが、キー入力を受け付けない。
現状、FPGAのPL部はTE0720のsampleデザインになっており、PYNQ-Z1ボードのそれとは異なる。起動時の処理で初期化か何かでPL部にアクセスをしていた場合は当然ハングアップする可能性は考えられる。ただし、BNN-PYNQはBNNの推論部をFPGA Overlaysの機能を使ってシステム起動後にFPGAにダウンロードして動かしているはずであり、起動時のPL部にはその回路は入っていないはずである。GitHubからPYNQのプロジェクトをダウンロードし、VivadoでBlock Designを見てみた。

Arduino sheild用の回路やHDMI、GPIO等の回路が入っているようだ。これらを起動時に初期設定しているのかも知れない。そこで、rootfsの/etc/rc 関係を見てみたところ rc.local にあった。

各シェルスクリプトの内容を確認した結果、4_boot_leds.shでPL部のGPIOを介してボード上のLEDのon/offをしていることが判った。そこで、rc.localの4_boot_leds.shの呼び出し部分をコメントアウトするように変更し、再度TE0720に装着して起動してみたところ、今度はキー入力も受け付けるようになった。

イーサネットも動作しておりDHCPでIPも取得できている。

そこで、開発PCのブラウザからTE0720のJupyter notebookのポートにアクセスしてみた。

アクセスできた。
そこで、次にBNN-PYNQのGitHubのQuickStartの記載内容に従って、BNN-PYNQをインストールした。

  sudo pip3.6 install git+https://github.com/Xilinx/BNN-PYNQ.git

すると、Jupyter notebookの項目にbnnが現れた。


Cifar10.ipynbを選択して実行してみた。

が、Jupyter notebookカーネルが死んでしまった。 orz

cell単位でステップ実行してみると、最初のcellでカーネルが死んでしまっていた。
overlayでPL部にダウンロードするBNN-PYNQのBlock DesignをVivadoで見ると以下のようであった。

これを見るとデバイス外部への入出力は無いので、TE0720でも動きそうな気がするのだが・・・
そこで、スクリプトをpythonスクリプトとしてダウンロードし手動で実行してみた。


terminate called after throwing an instance of 'char const*'というメッセージが出て終了してしまっていた。念の為、最初のセルの内容だけのスクリプトを書いて実行してみた。

classifier = bnn.CnvClassifier('cifar10')でエラーになっているようだ。
そこから、/opt/python3.6/lib/python3.6/site-packages/にあるpynqディレクトリ下のスクリプトやbnnディレクトリ下のスクリプトを追ってみた。回路情報(bitファイル)の/dev/xdevcfgへの書き込みは成功しているようだが、その後のpython_hw-cnv-pynq.soというライブラリ内部で例外が発生しているようだ。ソースコードを見ると、このpython_hw-cnv-pynq.soはパラメータのダウンロードを行うライブラリのようだ。なぜここで例外になる??? うーむ……


2017年7月30日日曜日

TE0720 No.2 (petalinux-image-full の build とインストール)

TE0720には出荷時設定でPetalinuxがインストールされているが、これは最小構成のものなので linux が動くということは判るがそれ以上のことはできそうにない。 GCCなどの開発ツールも入ったもっとリッチな環境にしたいし、いい機会なのでPetalinuxのビルドをやってみることにした。
基本的なビルド方法については、TrenzのWikiページを参考にした。

PetaLinux KICKstart
https://wiki.trenz-electronic.de/display/PD/PetaLinux+KICKstart#PetaLinuxKICKstart-PetalinuxProjectCreation-ShortHOWTO

Reference Design
http://www.trenz-electronic.de/fileadmin/docs/Trenz_Electronic/TE0720/Reference_Design/2016.4/test_board/te0720-test_board_noprebuilt-vivado_2016.4-build_08_20170529092723.zip

上記 Wiki にしたがってビルドしてできるPetalinuxはTE0720に入っているのと同じ最小構成のものだ。これをカスタマイズしたいが、 petalinux-config -c rootfs で1項目づつ追加する方法は面倒くさすぎてとてもじゃないがやってられない。 他になにか方法はないかと調べてみたところ、Petalinux-v2017.2-final には petalinux-image-full.bb というレシピファイルが存在することが判った。
※. petalinux-image-full.bbはインストレーションファイルのPetaLinux 2017.2 オープン コンポーネント ソース コード(petalinux-v2017.2-open_components.tar.gz)に含まれているのでpetalinux-v2017.2-final-installer.runと共にこれもインストールする必要がある。 (2018.08.19追記)

その内容を見るとgccの開発環境やX、openCV等、全部入りのレシピのようだ。

で、試行錯誤した結果、なんとかビルドすることが出来、望みのリッチな環境にすることができた。

やり方としてはちょっとダサいが、上記 Petalinux KICKstart に準じて最小構成のビルドをした後、oe-init-build-envをsourceし bitbake コマンドで rootfs のみ、即ち、 petalinux-image-full のみをビルドした。 因みに、oe-init-build-env はPetalinux インストールディレクトリ下のpetalinux-v2017.2-final/components/yocto/source/arm/layers/coreディレクトリにある。

以下、その手順

1. TE0720用最小構成のPetalinuxのビルド
 TE0720用のvivadoのhdfファイルと、device-tree、fsblが必要なので、上記 Reference Designをダウンロードし、_readme.txt に従って vivado 2016.4 でプロジェクトの生成まで実行し終了する。 petalinux-image-full.bb はpetalinux-v2016.4-finalには存在せず、petalinux-v2017.2-finalに存在するので、hdfファイルもvivado 2017.2で生成する必要がある。そのため、vivado 2016.4で生成したプロジェクトをvivado 2017.2で開き直し、そのバージョンでbitstream生成しhardwareのエクスポートをする必要がある。

次に、test_board/os ディレクトリ下に petalinux のプロジェクトを生成する。実際はプロジェクトを生成するディレクトリはどこでも良いが Reference Desginはtest_board/os 下に作成しているのでそれに準じた。


作成したTE0720ディレクトリ下にvivadoでエクスポートしたhdfファイルをコピーし、petalinux-config を実行する。



Configurationメニューが開くのでコンソール用シリアルポートやrootfs関連を設定する。

・ コンソール用シリアルポートは初期状態ではps7_uart_1になっているが、TE0720はps7_uart_0をコンソール用シリアルポートとしているのでps7_uart_0に変更する。
 トップメニューから、Subsystem AUTO Hardware Settings > Serial Settings > Primary stdin/stdout へと進み、ps7_uart_0を選択する。

・ Root filesystemの格納先をINITRAMFSからSDカードに変更する。
 トップメニューから、Image Packaging Configuration > Root filesystem type へと進み、SD cardを選択する。

・ デバイスツリー dtb イメージの格納先をSDカードに変更する。
 トップメニューから、Subsystem AUTO Hardware Settings > Advanced bootable images storage Settings > dtb image settings > image storage media へと進み、primary sdを選択する。

以上の項目を設定したらSaveしてConfiguration画面をExitする。
次に、fsbl等をTE0720用に変更したいところだが、build コマンドを実行しないと変更対象のfsblファイル群が生成されないので、ここで petalinux-build コマンドを実行する。

ビルド終了後、device-tree ファイルとfsblの変更を行う。

・Reference Designのsystem_top.dtsをsystem-user.dtsiにコピー
  test_board/os 下で、
  cp ./petalinux/project-spec/meta-user/recipes-dt/device-tree/files/system-top.dts./TE0720/project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi
  し、system_user.dtsiの1,3〜10行目を削除する。
変更前

変更後


・ fsblの変更
  Reference Designのfsbl_hooks.c、te_fsbl*.* をTE0720プロジェクトのfsblディレクトリ下にコピーする。
   test_board/os/TE0720 下で、
   cp ../../sw_lib/sw_apps/zynq_fsbl/src/fsbl_hooks.c  ./components/plnx_workspace/fsbl/src/fsbl_hooks.c
   cp ../../sw_lib/sw_apps/zynq_fsbl/src/te_fsbl*.*  ./components/plnx_workspace/fsbl/src/

  fsbl_hooks.cはFsblHookBeforeHandoff()関数からte_FsblHookBeforeHandoff()をコールするように変更されており、te_FsblHookBeforeHandoff()ではイーサネットのMACアドレスの設定やUSB-PHYのリセット等を行っている。USB-PHYのリセットはTE0720のシステムコントローラを介して行うようになっており、このシステムコントローラのI/FはI2Cで、Reference DesignではPSのIIC_1に接続されている。

上記変更後、再度 petalinux_build コマンドを実行する。
ビルドが完了したら、BOOT.BINを作成しておく。
test_boars/os/TE0720/images/linuxディレクトリに移動し、petalinux-packageコマンドでBOOT.binを生成する。

 
…と、ここまでが最小構成のPetalinux作成。ふぅ〜

2. petalinux-image-full のビルド
oe-init-build-envをsourceする。

次にbitbakeコマンドでpetalinux-image-fullをビルドする。

ここで必要なのはrootfsのみであるので -c do_image_cpioを付加する。また、これを付けないと、u-bootやfsblもビルドしにいってエラーになるので必ず付ける。

ビルドが始まった様子

ビルドが始まるとインタネット上のリポジトリからソースファイルを並列的に取得している様子で、ネットワーク負荷が重くなり、他のブラウザ等からのネットアクセスが一時的に出来なくり、暫くすると復旧するが、ビルド完了までにはかなり時間がかかる。特に上記のChecking sstate mirror object availabilityはもしかしてプログラムがハングアップしてんのか?って位に進捗が判りづらい。

ビルド中

ビルド成功


この方法の場合、イメージファイルはimage/linux/下ではなく、build/tmp/work/plnx_arm-xilinx-linux-gnueabi/petalinux-image-full/1.0-r0/deploy-petalinux-image-full-image-complete下に生成される。


これで全部入りのrootfsが出来た。 やったー \(^_^)/

SDカードに焼いて動くかどうかを見てみる。
SDカードにFAT32とext4形式の2つのパーティションを作成する。

FAT32にはimage/linuxディレクトリ下のBOOT.bin、image.ub、system.dtbをコピーする。

ext4パーティションにはrootfsをコピーするが、imageファイルがcpio形式なのでext4ディレクトリ上で以下のように展開する。

cpioファイルへのパスが長過ぎるのでシンボリックリンクを貼ってからcpioにそのファイル名を与えた。展開後は削除する。

展開できた。

syncコマンドを実行後SDカードをアンマウントし、TE0720に装着して起動すると無事Linuxが起動し、ログインプロンプトが表示された。

が、ここで問題発生。rootのパスワードが不明。どうやら root ではないようだ。
そこで、SDカードを開発PCにマウントしなおして、etc/passwdとetc/shadowをsudo vi で開いてrootのパスワードの部分を消去した。

passwdファイルのroot:x:0:0:・・・のx(shadowフアイルは*)を削除


これで、パスワード無しでログインできる。
ログイン後はパスワードを設定しておく。

/bin, /sbin, /usr/bin 等の各ディレクトリ下を見てみた。

/bin


/sbin


/usr/bin


/usr/sbin


/usr/libexec


/usr/include


gcc, pythonのバージョン


X WindowのウィンドウマネージャはMatchboxが入っている。


これだけ入っていれば色々遊べるだろう。


ERROR: Failed to spawn fakeroot worker to run ...

なにかと忙しくてなかなか趣味の時間を確保できない。 ...orz  家の開発機のOSはLinux Mintなのだが、最近バージョンを22に更新したところ、myCNC用のpetalinuxをビルドできなくなってしまった。ビルドの途中で ERROR: Failed to spawn ...