AWS F1インスタンス用サンプルcl_hello_worldのAFIをロードして動作させてみる #fpga

AWSのFPGAを搭載したF1インスタンスを試すには、FPGAに回路をロードする必要があります。今回は、実際にF1インスタンスを起動して、前回ビルドしたイメージ(AFI)をFPGAにロードし、その動作を確認してみました。

はじめに

前回の記事でaws-fpgaで提供されていたサンプルカスタムロジックをビルドして、FPGA用のイメージを作成してみました。aws ec2コマンドがfpga用に拡張されており、create-fpga-imageサブコマンドを使うことで、FPGAイメージを作成し、そのIDが返されます。以下は前回の実行結果です。

$ aws ec2 create-fpga-image --name cl_hello_world_test1 --description cl_hello_world_test1 --input-storage-location Bucket=cl_hello_world_01,Key=dcp/17_04_26-145828.Developer_CL.tar --logs-storage-location Bucket=cl_hello_world_01,Key=log
{
    "FpgaImageId": "afi-087de794473334559",
    "FpgaImageGlobalId": "agfi-0c023fead7942c8e0"
}

今回は、このイメージをF1インスタンスにロードしてみます。

F1インスタンスを起動する

まずはF1インスタンスを起動します。

AWSコンソールにログインし、EC2の画面を開きます。まずはリージョンとしてN.Virginiaを選択し、Launch Instanceボタンを押します。AMIとしてAMI Marketplaceから"FPGA Developer AMI"を選択します。

fpga-select-ami

そして、インスタンスタイプとして"f1.2xlarge"を選びます。

fpga-select-f1-instance-type

SDKとしてgithubから取得したaws-fpgaが必要ですが、前回使用したEBSのスナップショットを再使用することにします。スナップショット名で検索して選択します。このEBSは、~/src/project_dataにマウントされます。

fpga-select-ebs-snapshot

あとはデフォルトのままインスタンスを起動します。インスタンスが起動するまでしばらく待ってから、Connectボタンを押し、ホスト名を確認。SSHキーを指定してSSHで接続します。ユーザ名はcentosですのでご注意ください。

$ ssh -i ~/.ssh/your-key.pem centos@ec2-XX-XX-XX-XX.compute-1.amazonaws.com
The authenticity of host 'ec2-XX-XX-XX-XX.compute-1.amazonaws.com (XX.XX.XX.XX)' can't be established.
ECDSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'ec2-XX-XX-XX-XX.compute-1.amazonaws.com,XX.XX.XX.XX' (ECDSA) to the list of known hosts.
Last login: Thu Apr 20 16:43:01 2017 from 72-21-196-69.amazon.com
 ___ ___  ___   _     ___  _____   __    _   __  __ ___
| __| _ \/ __| /_\   |   \| __\ \ / /   /_\ |  \/  |_ _|
| _||  _/ (_ |/ _ \  | |) | _| \ V /   / _ \| |\/| || |
|_| |_|  \___/_/ \_\ |___/|___| \_/   /_/ \_\_|  |_|___|
AMI Version:        1.2.1
Readme:             /home/centos/src/README.md
GUI Setup Steps:    /home/centos/src/GUI_README.md
AMI Release Notes:  /home/centos/src/RELEASE_NOTES.md
Xilinx Tools:       /opt/Xilinx/
Developer Support:  https://github.com/aws/aws-fpga/blob/master/README.md#developer-support

AFIをロードするための準備

インスタンス起動後はまっさらな状態(EBSスナップショットをマウントしたsrc/project_data を除く)のため、以後のawsの操作のためアカウント情報を設定しておく必要があります。aws configureコマンドを使ってアクセスキーとシークレット、そしてリージョンとしてus-east-1(=N.Virginia)を設定しておきます。

$ aws configure
AWS Access Key ID [None]: your-access-key
AWS Secret Access Key [None]: your-secret
Default region name [None]: us-east-1
Default output format [None]:

次にSDK側の準備をします。src/project_dataにaws-fpgaディレクトリが見えるのを確認します。このディレクトリにあるsdk_setup.shスクリプトを読み込みます。このときコマンドのビルドやインストールを行うので、すこし時間がかかります。

[centos@ip-172-31-63-238 centos]$ cd src/project_data/aws-fpga/
[centos@ip-172-31-63-238 aws-fpga]$ source sdk_setup.sh
Done setting environment variables.
Entering /home/centos/src/project_data/aws-fpga/sdk/userspace/utils
rm -f *.o *.a ../lib/libutils.a
cc -DCONFIG_LOGLEVEL=0 -DFPGA_PCI_BARS_MAX=64 -g -std=gnu99 -fPIC -Wall -Werror -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -I. -I../include -I/usr/include   -c -o io.o io.c
...省略...
AWS FPGA: Copying Amazon FPGA Image (AFI) Management Tools to /usr/bin
AWS FPGA: Done with Amazon FPGA Image (AFI) Management Tools install.
Done with SDK install.
Done with AWS SDK setup.

FPGAを操作するコマンド

/usr/binにコマンドがインストールされたようですので、確認してみます。いくつかそれらしいコマンドができています。

$ ls /usr/bin/fpga-*
/usr/bin/fpga-clear-local-image           /usr/bin/fpga-load-local-image
/usr/bin/fpga-describe-local-image        /usr/bin/fpga-local-cmd
/usr/bin/fpga-describe-local-image-slots  /usr/bin/fpga-set-virtual-dip-switch
/usr/bin/fpga-get-virtual-dip-switch      /usr/bin/fpga-start-virtual-jtag
/usr/bin/fpga-get-virtual-led

コマンドを試してみます。

まずは、fpga-describe-local-image-slotsコマンドでFPGAが挿入されているスロットの一覧を表示します。ハードウェアにアクセスするため実行には管理者権限が必要なためsudoを使います。

$ sudo fpga-describe-local-image-slots
AFIDEVICE    0       0x1d0f      0x1042      0000:00:1d.0

0番のスロットが存在することがわかります。

次にfpga-describe-local-imageコマンドでロードされているイメージを確認します。-S 0 オプションでスロットを指定が必要です。スロットの指定は他のコマンドでも必要になります。

$ sudo fpga-describe-local-image -S 0
AFI          0       none                    cleared           1        ok               0       0x04151701
AFIDEVICE    0       0x1d0f      0x1042      0000:00:1d.0

ステータスがclearedとなっているので、イメージはロードされていないようです。

F1インスタンスにはvirtual-ledという仮想LEDなるものが用意されているようです。ハードウェア開発ではLEDを使って点灯状態を目で見て確認するなんてことをよくやります。クラウドのFPGAでは直接見ることができませんが、その代わりにピンに出力した信号の状態を、ソフトウェア的に取得することができる仕組みが用意されているようです。

fpga-get-virtual-ledコマンドを実行すると16ビット分の信号が得られます。

$ sudo fpga-get-virtual-led -S 0
FPGA slot id 0 have the following Virtual LED:
1111-1111-1111-1111

LEDは出力ですが、これとは別にvirtual-dip-switchなるものがあり、16ビット分の信号を入力することができるようです。getで状態取得、setで状態設定ができます。

$ sudo /usr/bin/fpga-get-virtual-dip-switch -S 0
FPGA slot id 0 has the following Virtual DIP Switches:
0000-0000-0000-0000
$ sudo fpga-set-virtual-dip-switch -S 0 -D 1111111111111111
FPGA slot id 0 has the following Virtual DIP Switches:
1111-1111-1111-1111

AFIをロードする

FPGAの回路を定義しているイメージについての操作ですが、README.mdに従い、まずはclearから始めます。

fpga-clear-local-imageコマンドを実行してみます。実行直後にfpga-describe-local-imageで確認するとbusyになりますが、10秒くらい経過後に確認してみると、clearedとなっています。イメージのロードには若干の時間を要するようです。また、イメージのロードは非同期で行われるようです(ロードの完了を待たずにコマンドが終了します)。

$ sudo fpga-clear-local-image -S 0
$ sudo fpga-describe-local-image -S 0
AFI          0       none                    busy              2        ok               0       0x04151701
AFIDEVICE    0       0x1d0f      0x1042      0000:00:1d.0
$ sudo fpga-describe-local-image -S 0
AFI          0       none                    cleared           1        ok               0       0x04151701
AFIDEVICE    0       0x1d0f      0x1042      0000:00:1d.0

いよいよイメージをロードしてみます。fpga-load-local-imageコマンドを使って、-IオプションでAFIのAGFI-ID (Amazon Global FPGA Image)を指定します。このAFIはcl_hello_worldカスタムロジックをビルドしてイメージを作成したときに得たIDです。IDは、AFIとAGFIの2種類がありますが、ここで使用するのはAGFIです。

fpga-load-local-imageを実行して、少し待ってからfpga-describe-local-imageで確認してみると、ステータスがloadedとなっています。無事に(あっさりと?)イメージのロードに成功したようです。

$ sudo fpga-load-local-image -S 0 -I agfi-0c023fead7942c8e0
$ sudo fpga-describe-local-image -S 0
AFI          0       agfi-0c023fead7942c8e0  loaded            0        ok               0       0x04151701
AFIDEVICE    0       0x1d0f      0x1042      0000:00:1d.0

FPGAの動作を確認してみる

FPGAにロードされた回路の動作を確認するためのコードがサンプル内に用意されています。

aws-fpga/hdk/cl/examples/cl_hello_world/software/runtime/ にcdして、make allします。そうすると test_hello_worldという実行バイナリが作られます。

$ cd aws-fpga/hdk/cl/examples/cl_hello_world/software/runtime/
$ make all
gcc -DCONFIG_LOGLEVEL=4 -g -Wall -I/home/centos/src/project_data/aws-fpga/sdk/userspace/include   -c -o test_hello_world.o test_hello_world.c
gcc -DCONFIG_LOGLEVEL=4 -g -Wall -I/home/centos/src/project_data/aws-fpga/sdk/userspace/include -o test_hello_world test_hello_world.o  -lfpga_mgmt -lrt -lpthread

これを実行してみます。これもsudoが必要です。

$ sudo ./test_hello_world
AFI PCI  Vendor ID: 0x1d0f, Device ID 0xf000
===== Starting with peek_poke_example =====
register: 0xdeadbeef
Resulting value matched expected value 0xdeadbeef. It worked!
Developers are encourged to modify the Virtual DIP Switch by calling the linux shell command to demonstrate how AWS FPGA Virtual DIP switches can be used to change a CustomLogic functionality:
$ fpga-set-virtual-dip-switch -S (slot-id) -D (16 digit setting)

In this example, setting a virtual DIP switch to zero clears the corresponding LED, even if the peek-poke example would set it to 1.
For instance:
# fpga-set-virtual-dip-switch -S 0 -D 1111111111111111
# fpga-get-virtual-led  -S 0
FPGA slot id 0 have the following Virtual LED:
1010-1101-1101-1110
# fpga-set-virtual-dip-switch -S 0 -D 0000000000000000
# fpga-get-virtual-led  -S 0
FPGA slot id 0 have the following Virtual LED:
0000-0000-0000-0000

FPGAの内部のレジスタから16進数で、0xdeadbeef という想定通りの32bit値が読み出しできたようです。

表示されたテキストによると、virtual-ledとvirtual-dip-switchが連携するようです。これも試してみます。

まずはDIP Switchのすべてのビットを1にします。そうするとLEDは、1010-1101-1101-1110 = 0xADDE となります。この値は、さきほどの0xdeadbeefの上位16ビットのバイト順を入れ替えたもののようです。

$ sudo fpga-set-virtual-dip-switch -S 0 -D 1111111111111111
$ sudo fpga-get-virtual-led  -S 0
FPGA slot id 0 have the following Virtual LED:
1010-1101-1101-1110

まずはDIP Switchのすべてのビットを0にします。そうするとLEDのすべてのビットが0になります。DIP SwitchとLEDが連携しているようです。

$ sudo fpga-set-virtual-dip-switch -S 0 -D 0000000000000000
$ sudo fpga-get-virtual-led  -S 0
FPGA slot id 0 have the following Virtual LED:
0000-0000-0000-0000

DIP Switchに適当なビットパターンを与えてみます。LEDには0xADDEとAND(論理積)した値が得られるようです。

$ sudo fpga-set-virtual-dip-switch -S 0 -D 0101010101010101
$ sudo fpga-get-virtual-led  -S 0
FPGA slot id 0 have the following Virtual LED:
0000-0101-0101-0100

ロジックの中身はどのようになっているのでしょうか。回路はVerilogという言語で記述されています。中身を覗いてみると、以下のような記述がされています。コードはいろいろと記述がありますが、肝心の箇所はこの部分です。

ファイル: aws-fpga/hdk/cl/examples/cl_hello_world/design/cl_hello_world.sv

assign hello_world_q_byte_swapped[31:0] = {hello_world_q[7:0],   hello_world_q[15:8],
                                           hello_world_q[23:16], hello_world_q[31:24]};
always_ff @(posedge clk_main_a0)
   if (!rst_main_n_sync) begin                    // Reset
      vled_q[15:0] <= 16'h0000;
   end
   else begin
      vled_q[15:0] <= hello_world_q[15:0];
   end

// The Virtual LED outputs will be masked with the Virtual DIP switches.
assign pre_cl_sh_status_vled[15:0] = vled_q[15:0] & sh_cl_status_vdip_q2[15:0];

回路は単純ですが、記述通りに動作しているようです。

F1インスタンスの価格

ちなみにF1インスタンスの価格ですが、f1.2xlarge は$1.65/hourとなっています。使い終わったら、忘れずに停止しておきましょう。

fpga-f1-pricelist

まとめ

aws-fpgaのHDKのサンプルCL_HELLO_WORLDをビルドしたイメージをロードして動作を確認することができました。トリビアルなサンプルでしたが、中身の単純さの割に、イメージのビルドに非常に長時間要するのが印象的です。本格的な開発ではシミュレータの活用など、ツール群を使いこなしていく必要があります。こちらも試して見たいところです。

参考