ラプラシアン・フィルタをソフトウェアで実装し、ハードウェアにオフロードする

ZedBoard Linux上でカメラの画像を処理する1(準備編)
ZedBoard Linux上でカメラ画像を処理しようと思う。まずは現状確認と手段の検討をした。
ZedBoard Linux上でカメラの画像を処理する2(準備編2)
今回は、フレーム・バッファのアドレスをファイルに書いておくようにするのが目的だ。 ZedBoardのLinux起動時に、Linuxのペンギンが写っている既存のフレームバッファをアドレスを取得して、カメラ・インターフェイスIPとビッ トマップ・ディスプレイ・コントローラIPのフレームバッファ・スタート・アドレス・レジスタにWrite するようなCソフトウェアを実行している。そのソフトウェアでフレーム・バッファの開始アドレスをfb_start_addr.txtというファイルに書いて おくようにしようと思う。そのために起動時のCソフトウェアを変更した。
今のところ、SDKリモートデバッグ経由だが、ZedBoardのLinux上で起動して、fb_start_addr.txt に開始アドレスが入るのを確認できた。
ZedBoard Linux上でカメラの画像を処理する3(ラプラシアンフィルタ1)
ラプラシアンフィルタを実行するCのソフトウェア(Laplacian_Filter.c)を作製した。ISE14.4だとデバックができない。
ZedBoard Linux上でカメラの画像を処理する4(ラプラシアンフィルタ2)
”ZedBoard Linux上でカメラの画像を処理する3(ラプラシアンフィルタ1)”でどうしても、ラプラシアン・フィルタのソフトウェアで、fb_start_addr.txt をオープンすることが出来なかった。今回は、修正済みのカメラ画像表示用ソフトウェアの cam_disp3_linux.elf を予めSDカードに書き込んでから、ラプラシアン・フィルタのソフトウェアをSDKリモートデバッグすることにした。
SDK14.6 にして、何度かビルドしてやってみたら、デバックができるようになった。
ZedBoard Linux上でカメラの画像を処理する5(ラプラシアンフィルタ3)
いろいろと物理アドレスと論理アドレス変換について迷ったが、mmap()を使えば行けそうだ と見込みがついて、ラプラシアン・フィルタをカメラ画像に掛けたのだが、まだ途中でmmap()に失敗してしまう。何故かは分からないが、mmap()を2つ アクティブにしているからなのだろうか?
最初にラプラシアン・フィルタを掛けた画像を下に示す。途中で、mmap() が失敗してしまうまで、ラプラシアン・フィルタ結果が表示されている。
ZedBoard Linux上でカメラの画像を処理する6(ラプラシアンフィルタ4)
Digilent Linux 上でのラプラシアン・フィルタのCソフトウエア完成しました。やった~~~。嬉しいですね。。。
原因は、setup_io() で、malloc() で取ったメモリ領域を free() していないことでした。setup_io() は引用してきたんですが、かなり処理に抜けがありました。open() した"/dev/mem"も close() してなかったですね。
ZedBoard Linux上でカメラの画像を処理する7(ラプラシアンフィルタ5)
Readするときにいちいち mmap() してからReadして、munmap() しているので、とっても遅い。今度は、ラプラシアン・フィルタリングを完了するまでに、139秒かかっている。
ソ フトウエアのプロファイリング1(mmap(), munmap() の時間計測)
ソフトウェアの動作時間は139秒だった。何処に時間がかかっているかをプロファイリングしよ うと思う。使用するのは、gettimeofday() だ。”システムプログラム(第4週)”を参考にプログラムしていく。
ソフトウエアのプロファイリ ング2(mmap(), munmap() の時間計測2)
mmap()の数をカウントした。
1個のピクセルデータをmmap()で読むソフトウェアと、ReadとWriteの2つの mmap() 領域を用意して、それぞれ現在取得している領域が外れた時に munmap() して、もう一度領域を取り直すソフトウェアを実行時間を比較して、mmap(), munmap() 関連の実行時間とそれ以外の実行時間を計算で求めた。
ソフトウエアのプロファイリ ング3(最適化)
今回は更に最適化を図る。mmap(), munmap() が遅いので、極力少なくすることを考える。
ラプラシアン・フィルタの実装は、3ライン分読んでからラプラシアン・フィルタを掛けるようにした。これで、ピクセルデータRead時のアドレスは連続す るので、Readのmmap(), munmap() の数とWriteのmmap(), munmap() の数は等しくなるはずだ。最初は3ライン分のピクセルをReadするが、次からは後にReadした2ラインは使用できるので、1ラインだけのReadになる。
ソフトウエアのプロファイリ ング4(ハードウェアと同じ方式)
今度は、フレームの最初に2ラインを読んでから、2つピクセルを保存した後で、1つピクセルを 読みながら、真ん中のラプラシアン・フィルタの値を計算していく。これで、”画像のエッジ検出6(3X3での方式の検討)”で実装したハードウェアと同じ方式 になった。
実行したところ、”ソフトウエアのプロファイリング3(最適化)”よりも、更に 5msec ほど速くなった。
ラプラシアン・フィルタのC ソフトをVivado HLSで
ソ フトウエアのプロファイリング4(ハードウェアと同じ方式)”のラプラシアン・フィルタのCソフトウェアをVivado HLSでコンパイルしてHDLコードの落として使ってみたい。そのため、Cプログラムを修正してVivado HLSでプロジェクトを作製してコンパイルしてみた。
ソフトウェアで使っていたCプログラムをそのまま、Vivado HLSで変換したので、変換できず、エラーでコンパイルできなかった。
Vivado HLSでラプラシアン・フィルタ式のみをaxi lite slaveモジュールにする1
今回は、3x3のラプラシアン・フィルタの式のみを、以前Vivado HLSのサンプルしてやってみた axi lite を元に変更してみようと思う。
C Synthesis まで行った。
Vivado HLSでラプラシアン・フィルタ式のみをaxi lite slaveモジュールにする2
Verilog HDLのCo-Simulation し、カスタムIPとして出力した。使用したCソフトウェアの laplacian_filter.c を貼っておく。
Vivado HLSで作ったラプラシアン・フィルタIPを使ってみる1
"Vivado HLSでラプラシアン・フィルタ式のみをaxi lite slaveモジュールにする2"でラプラシアン・フィルタの式のみをEDKの pcore として出力したので、XPSのプロジェクトに入れてハードウェア化してLinuxのソフトウェアから使ってみようと思う。
XPSプロジェクトにラプラシアン・フィルタ式のみの axi lite slave カスタムIPをAdd IPして、Project Navigator に戻りビットストリームの生成まで。
Vivado HLSで作ったラプラシアン・フィルタIPを使ってみる2
前回、ビットストリームの生成まで出来たので、今回はSDKにハードウェアをエクスポートして ソフトウェアを作る。
SDカードにBOOT.bin を書き込むところまで。
Vivado HLSでラプラシアン・フィルタ式のみをaxi lite slaveモジュールにする3
記事が前後してしまったが、Vivado HLSで生成されたVerilog HDLコードをシミュレーションしてみようと思う。
生成されたVerilogはC言語のテストベンチでCo-Simulation してみたがタイミングチャートにして表示する方法がわからなかった。そこで、ISEのプロジェクトを作って、ISimでシミュレーションしてみた。
Vivado HLSで作ったラプラシアン・フィルタIPを使ってみる3
今までのDigilent社のLinuxにカメラ回路とビットマップ・ディスプレイ・ コントローラを付けた回路に、Vivado HLSで作ったラプラシアン・フィルタの AXI4 Lite Slave IP を追加して、XPSプロジェクトを構成して、論理合成、インプリメントした。ソフトウェアを作って実行したところ、1.94sec かかって、最適化したソフトウェアの 5倍の実行時間になった。
Vivado HLSで作ったラプラシアン・フィルタIPを使ってみる4
Vivado HLSで作ったラプラシアン・フィルタの AXI4 Lite Slave IP を追加した時のCのソースコードを貼った。
Vivado HLSで作ったラプラシアン・フィルタIPを使ってみる5
今回は、ChipScope を使用して、AXI4 Lite Slave バスのバス・トランザクションを見た。
Vivado HLSでラプラシアン・フィルタ関数をaxi masterモジュールにする1
ラプラシアン・フィルタ関数自体をVivado HLSで、AXI4 Master を使用したIPとして生成することにした。
Vivado HLSで合成はできたが、画像のフレームバッファが固定値なので、使いものにならない。
Vivado HLSでラプラシアン・フィルタ関数をaxi masterモジュールにする2
前回、Vivado HLS の Export RTL で EDK用の pcore を作ってみたが、カメラ画像フレーム・バッファ読み込み用アドレスとラプラシアン・フィルタの結果を書き出すフレーム・バッファのアドレスは、parameter 指定の固定アドレスだったので、AXI4 Lite Slave でAXI4 Master のRead/Writeするアドレスを渡す仕様に変更した。Vivado HLSのCソースコードを貼った。
Vivado HLSで作ったラプラシアン・フィルタAXI4 Master IPを使う1
Vivado HLSでラプラシアン・フィルタ関数をaxi masterモジュールにする2”で作ったAXI4 Lite Slave と AXI4 Master の 2種類のAXIバスを実装するラプラシアン・フィルタ IPをXPSのカスタムIPとして使って見ようと思う。
XPSにラプラシアン・フィルタ AX4 Master IP をAdd IPして、接続するまで。
Vivado HLSで作ったラプラシアン・フィルタAXI4 Master IPを使う2
Project Navigator に戻って論理合成、インプリメントを行ったが、問題なく終了した。
SDKでCソフトウェアを作製、実機でテストしたが、ap_done が上がらずにソフトウェアが終了できなかった。
Vivado HLSで作ったラプラシアン・フィルタAXI4 Master IPを使う3
前回は、Vivado HLSで作ったAXI4 Lite Slave と AXI4 Master の 2種類のAXIバスを実装するラプラシアン・フィルタ IPをXPSのカスタムIPとして、SDKからのソフトウェア制御で使用してみたら動作しなかった(ap_done がアサートされなかった)という問題が合った。
今回は、XPSプロジェクトに入れてあったChipScope AXI Monitor を使用してAXI4バスのトランザクションを見ることにした。
AXI4 Lite Slave は問題無し、AXI4 Master Readは問題ないが、AXI4 Master Write のアクセスが無かった。
ラプラシアン・フィルタの AXI4 Master IPを作製する1(仕様の検討)
Vivado HLSでラプラシアン・フィルタをAXI Master で構成するC言語のソースを書いて、IPとしてZedBoardのLinux用ハードウェアに実装してみたが、動作しなかった。そこで、Vivado HLSが出力したIPのトップファイルのポート構成はそのままで、自分でHDLを書いて、ラプラシアン・フィルタのAXI4 Master IPを完成させてみることにした。

Vivado HLS 2013.3でラプラシアン・フィルタ関数をaxi masterモジュールにする
Xilinxのサイトに、Vivado 2013.3 と ISE14.7 が出ているということをツイッターで教えてもらったので、早速、Vivado 2013.3 をインストールした。そして、再度、Vivado HLSでラプラシアン・フィルタ関数をaxi masterモジュールにしてみた。
ラプラシアン・フィルタのCソースを少し変更したので、貼っておく。キャストが違っていて、 warnningがでていたので、その点を修正した。
Vivado HLS 2013.3 で作ったラプラシアン・フィルタAXI4 Master IPを使う1
Vivado HLS 2013.3でラプラシアン・フィルタ関数をaxi masterモジュールにする”でC言語からHDLに合成したラプラシアン・フィル タIPをDigilent LinuxのXPSプロジェクトに組み込んで、動作を確認したが、結果から言うと動作しなかった。
Vivado HLS 2013.3 で作ったラプラシアン・フィルタAXI4 Master IPを使う2
Vivado HLS 2013.3 で作ったラプラシアン・フィルタAXI4 Master IPを使う1” でVivado HLS 2013.3 でC言語から合成したIPが動かないということを書いた。今回は、予め入れておいたChipScope を使用して、ラプラシアン・フィルタAXI4 Master IPの2つのAXI4 Masterバスと1つのAXI4 Lite Slaveバスの波形を見てみた。

AXI4 Master アクセスのラプラシアン・フィルタ IP1(構想)
以前にもラプラシアン・フィルタをFPGAのハードウェアで作ったことがあるが、それは、1連 のパイプラインされた構造だった。1ピクセルの画像データが入ってきて、パイプラインにデータが満たされていれば、ラプラシアン・フィルタ後のデータが出てく る構造だ。
今回はわざとこの構造は取らずに、C言語からHLSで合成したようにシリアライズしてみようと思うのだが、なかなかわざと遅くしようと作ったことがなの で、戸惑っている。ともかくC言語からHDLを合成したようにメモリベースで、ある程度シリアライズされた構成で作ってみようと思う。
AXI4 Master アクセスのラプラシアン・フィルタ IP2(現在作成中)
”AXI4 Master アクセスのラプラシアン・フィルタ IP1(構想)”の構想を元に、現在、AXI4 Master アクセスのラプラシアン・フィルタ IPを作製中だ。
AXI4 Master アクセスのラプラシアン・フィルタ IP3(シミュレーション)
AXI4 Master アクセスのラプラシアン・フィルタ IPが出来てシミュレーションを行った。
AXI4 Master アクセスのラプラシアン・フィルタ IP4(シミュレーション2)
前回の AXI4 Master アクセスのラプラシアン・フィルタ IP には欠点があった。それは、ラプラシアン・フィルタ結果をDDR3 SDRAMにWrite するときに終了をブロックしていないことだ。もし、AXI4 Write Transaction の終了、次のAXI4 Read Transaction より長く掛かってしまった場合は、write_data FIFOが溢れてしまう危険がある。現在のところwrite_data FIFOがFULLなった時ののデータ停止は行っていない。つまり手抜きです。。。
その代わり、AXI4 Write Transaction の終了までブロックするようにメインのステートマシンを変更した。メインのステートマシンを下に示す。
AXI4 Master アクセスのラプラシアン・フィルタ IP5(lap_filter_axim.v のHDLソース)
現在のところの lap_filter_axim.v を貼っておく。
AXI4 Master アクセスのラプラシアン・フィルタ IP6(lap_filter_axim_LiteS_if.v のHDLソース)
Vivado HLSでラプラシアン・フィルタ AXI Master IP を作った際のAXI4 Lite Slave モジュール lap_filter_axim_LiteS_if.v を貼っておく。
AXI4 Master アクセスのラプラシアン・フィルタ IP6(line_read_and_y.v と Dual_Port_Memory.v)
下位モジュールの line_read_and_y.v と Dual_Port_Memory.v を貼っておく。
AXI4 Master アクセスのラプラシアン・フィルタ IP7(インプリメント1)
MPDファイルやPAOファイルを作って、カスタムIPとしてXPSプロジェクトにADD IPして、ISEから論理合成、インプリメントを行った。
AXI4 Master アクセスのラプラシアン・フィルタ IP8(インプリメント2、実機テスト)
インプリメントと実機テストを行ったが、ラプラシアン・フィルタ画像がおかしかった。HDL コードの Writeアドレスの増加ステップがおかしかったので、修正を行った。
AXI4 Master アクセスのラプラシアン・フィルタ IP9(できた。完成)
バグを修正したら、できました。完成です。ラプラシアン・フィルタのAXI4 Master IPへのハードウェア・オフロードが完成しました。
lap_filter_axim.c、lap_fil_axim_uty.c と lap_fil_axim_uty.h を貼っておきます。

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする3
S様にVivado HLSについてお尋ねしたら、私のラプラシアン・フィルタを評価していただけるということなので、お願いしたら、デバックして頂いた。その知見を元に、私なりに今までのラ プラシアン・フィルタのコードを見なおしてみたい。
最初のCシミュレーションは、Visual Studio 2012 でやることにした。
Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする4
前回は、Visual Studio 2012 でVivado HLS 2013.4 に使うためのCソースをシミュレーションしてみた。うまく行ったので、今回は、Vivado HLS 2013.4 に持ってきてCシミュレーションやCからHDLへの合成、IP化などを行った。
Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする5(単体シミュレーション)
前回、Vivado HLS 2013.4 でラプラシアンフィルタのAXI4 Master IPを生成できたので、今度は単体シミュレーションを行った。
Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする6(実機でテスト)
実機でテストを行った。うまくは行ったのだが、画像は全体的に強調されていて、余計な線が入っ ている。
Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする7(ソース公開)
前回までのソースを公開します。使用は自己責任でお願いします。なお、バグを見つけたらコメン ト欄で教えて下さい。よろしくお願いします。
Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする8(Directive)
Vivado HLS 2013.4 でラプラシアンフィルタのCソースコードをVerilog HDLで書かれたIPとして高位合成をして、できたIPを実機でテストしてみたところ、結果はちょっとおかしいが、無事に動作した。今回は、実行時間が約 100msec 程度と遅いので、もう少し早くしてみようと思う。そのためには、Directiveを追加する必要がある。
さてDirectiveを追加していこう。とりあえず、forループを展開するDirective の UNROLL を RGBピクセルを白黒ビクセルに変換する conv_rgb2y() に入れていこう。
Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする9(Directive2)
前回は、UNROLL Directive を入れてたが効果は得られなかった。あれからPIPELINE Directive を試してみたが、大きいループにPIPELINE Directive 属性を付加すると時間がかかりすぎる。小さいループにPIPELINE Directive をかけても他がPIPELINE化されていないので、効果なしという結果になるような気がする。

inserted by FC2 system