FPGAにOpenCLを実装してみた

本記事では，Altera SDK for OpenCL(AOCL)を用いて，Altera社製のFPGAボードにopenCLで書かれたプログラムを実装する方法を紹介します．

#概要
現在，CPUやGPU，DSPなどの異なる演算デバイスを組み合わせた並列計算機を構成して，演算能力の向上させ，様々な分野で使用されている数値シミュレーションを高速化する手法が一般的に取られています．

しかし，開発環境が並列計算機を構成するプロセッサのベンダに依存しており，ソフトウェアの可搬性を維持しつつより高性能なデバイスへの乗り換えが困難です．

OpenCL(英：Open Computing Language)はヘテロジニアスな並列計算機環境に適したプログラミングモデルであり，ソフトウェアの可搬性を維持しつつより高性能なデバイスへの乗り換えが可能となります．

さらに，OpenCLを用いると，計算機を構成するプロセッサによってそれぞれ特有のAPI（Application Programming Interface）や記述を用いずとも，各種デバイスに実装が可能となります．

#実装手順

- 前準備
    - ボードの準備
    - ソフトウェアのインストール
- 開発環境の構築
    - ブートカード作成
    - ボードの初期設定
    - BSPのインストール
    - 環境変数の設定
    - 環境のテスト
    - クロス開発環境の構築
- プログラム実装
- 動作確認
<br>

#■前準備
#####ボードの準備
Altera社から発売されている，DE1-SoCにプログラムを実装しました．DE-1SoCのスペックは以下の通りとなっています．

表1．DE1-SoCのスペック
<img src="https://qiita-image-store.s3.amazonaws.com/0/153905/4fdd040b-3f16-55f4-f4c6-cfea34d86f9a.jpeg" width=50%>

#####ソフトウェアのインストール
以下のソフトウェアをCentos6.8にインストールしました．
・Quartus Prime スタンダード・エディション
・Cyclone V Device Support
・Intel SDK for OpenCL（旧Altera SDK for OpenCL）
・SoC Embedded Design Suite
※root権限でインストールすることをオススメします．
また，Altera SDK for OpenCLを使用するには，有償のライセンスが必要です（2017年9月28日現在）．OpenCLに対応している製品を購入すると，ライセンスも一緒についてくるそうです．Altera DE1-SoCの場合は，OpenCL対応デバイスでしたが，ライセンスはついていなかったので，別途，1年ライセンスを公式サイトから購入しました．

#■開発環境の構築
#####ブートカードの作成
下記サイトから，BSP(Board Support Package) for Altera SDK OpenCL 16.0内にあるDE1-SoC OpenCL BSP V1.1(.zip)をダウンロードし，解凍すると，linux_sd_card_image.zipがあります．

[BSP(Board Support Package) for Altera SDK OpenCL 16.0](http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&No=836&PartNo=4)

linux_sd_card_image.zipを解凍すると，linux_sd_card_image.imgがあります．
このイメージファイルをWin32DiskImagerなとのソフトを用いてmicroSDカードに書き込み，ブートカードを作成します．使用するSDカードは4[GB]以上である必要があります．
SDカードにイメージの書き込みが終わり，ブートカード作成が完了したら，DE1のカードスロットに差し込んでください．

#####ボードの初期設定
DE1-SoCボードの裏面にあるディップスイッチを，以下のように設定して下さい．
ディップスイッチを以下のように設定することで，SDカードからのブートが有効になります．

<img src="https://qiita-image-store.s3.amazonaws.com/0/153905/699d0465-9a98-5d46-bfd6-1682291c93ce.jpeg" width=30%>

#####BSPのインストール
先程，ダウンロードし解凍したフォルダ内にある「de1soc」フォルダをboardフォルダ内に全て移動して下さい．

<pre>/root/intelFPGA/16.1/hld/board/</pre>

boardディレクトリ以下には，開発対象となるボードパッケージが格納されています．

#####環境変数の設定
環境変数を以下に示しました．本サイトでは，各種ソフトをrootディレクトリ配下にインストールしました．

```environment_list.sh
export ALTERAOCLSDKROOT=/root/intelFPGA/16.1/hld
export QSYS_ROOTDIR=/root/intelFPGA/16.1/quartus/sopc_builder/bin
 
#使用するボードの種類
export AOCL_BOARD_PACKAGE_ROOT=/root/intelFPGA/16.1/hld/board/de1soc
export PATH=$ALTERAOCLSDKROOT/bin:$PATH
export PATH=$ALTERAOCLSDKROOT/linux64/bin:$PATH
export PATH=$ALTERAOCLSDKROOT/host/linux64/bin:$PATH
export PATH=$QSYS_ROOTDIR:$PATH
export PATH=/root/intelFPGA/16.1/quartus/bin:$PATH
 
export LD_LIBRARY_PATH=$ALTERAOCLSDKROOT/host/linux64/lib
export LD_LIBRARY_PATH=$AOCL_BOARD_PACKAGE_ROOT/linux64/lib
export LD_LIBRARY_PATH=/root/intelFPGA/16.1/embedded/ds-5/sw/gcc/arm-linux-gnueabihf/bin
 
#ライセンスのセットアップ
export LM_LICENSE_FILE=/root/Downloads/license.dat
export PATH=/root/intelFPGA/16.1/embedded/ds-5/bin:$PATH
export PATH=/root/intelFPGA/16.1/embedded/ds-5/sw:$PATH
```

#####環境のテスト
各種ソフトウェアのインストール，環境変数のセットが完了したら以下のコマンドを入力してください．

<pre>aoc --list-boards</pre>

上記のコマンドを実行すると，下記のような出力を得ることができると思います．

<pre>Board list:
  de1soc_sharedonly
</pre>
もし．aocコマンドが実行できなかった場合は，環境変数の設定が正しく行われてない可能性があります．envコマンドを実行することで，パスの設定を確認することが出来ます．de1soc_sharedonlyと表示されれば，OKです．

#####クロス開発環境の構築
Centos6.8上でコンパイルしたホストコードを，DE1で実行するために，クロス開発環境をCentos上に構築します．環境構築は簡単で，以下のシェルを実行すればOKです．

<pre>/root/intelFPGA/16.1/embedded/embedded_command_shell.sh</pre>


#■プログラムの実装
2つのN要素ベクトルの加算を計算するプログラムを実装します．このプログラムは，Altera社からサンプルプログラムとして提供されており，先ほどダウンロードしたBSPのフォルダ内にあります．

サンプルプログラム「vector_add」のディレクトリに移動します．

<pre>cd /root/intelFPGA/16.1/hld/board/de1soc/examples/</pre>

ディレクトリ移動後に，以下のコマンドを実行すると，カーネルがコンパイルされます．

<pre>aoc -g -v --report device/vectorAdd.cl -o bin/vectorAdd.aocx --board de1soc_sharedonly</pre>

※環境にもよりますが，コンパイルには，20分から30分程度かかります．
コンパイルが成功すると，binフォルダにvectorAdd.aocxファイルが生成されます．

コンパイルが終了したら，

<pre>make all</pre>

を実行し，ホストプログラムをARM上で動くようにクロスコンパイルします．
※以下のようなwarningメッセージが出た場合，無視してもOKです．
<pre>arm-linux-gnueabihf-g++  host/src/ten1.cpp ./common/src/AOCL_Utils.cpp -o ten1  -I/root/intelFPGA/16.1/hld/host/include  -I./common/inc -Ihost/inc -L/root/intelFPGA/16.1/hld/board/de1soc/arm32/lib -L/root/intelFPGA/16.1/hld/host/arm32/lib -L/root/intelFPGA/16.1/hld/host/arm32/lib -Wl,--no-as-needed -lalteracl -lalterammdpcie -lstdc++ -lelf -lstdc++
/root/intelFPGA/16.1/embedded/ds-5/sw/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: warning: libacl_emulator_kernel_rt.so, needed by /root/intelFPGA/16.1/hld/board/de1soc/arm32/lib/libalteracl.so, not found (try using -rpath or -rpath-link)
</pre>

#■動作確認
DE1-SoCをイーサネットケーブルでLANに接続し，本体の電源を入れて下さい．
TeratermなどでDE1にログインして下さい．この時，ユーザはrootで，パスワード無しで入れます．
以下の2つのファイルをSCPなどを用いて，DE1-SoCにデータを送ります．

- vectorAdd.aocx　（カーネルをコンパイルしたもの）
- vectorAdd　（クロスコンパイルされたデータ）

上記，2データをDE1-SoC上にコピーしたら，以下のコマンドをDE1-SoC上で実行して下さい．

<pre>source ./init_opencl.sh</pre>

上記コマンドを実行すると，DE1-SoC上でaoclコマンドなどが使用可能となります．
次に，以下のコマンドを入力することで，プログラムを実行することが出来ます．

<pre>./vectorAdd</pre>

上記コマンドを実行しても，プログラムが起動しない場合は，以下のコマンドを実行してから，再度試して下さい．

<pre>aocl program /dev/acl0 vectorAdd.aocx</pre>

上記のコマンドが成功すると「Reprogramming was Successful!」と出力されます．

vector addプログラムが成功すると，「verification : PASS」と出力されます．

###参考文献
[DE1-SoC OpenCL BSP](http://www.terasic.com.tw/attachment/archive/836/DE1SOC_OpenCL_v02.pdf)