注意(2017年7月29日追記)
この記事は Linux Kernel 4.4 時点に投稿したものであり、古い内容が含まれています。Linux Kernel 4.10 以降、FPGA 関連は大きく進歩しました。詳しくは「Linux Kernel 4.10 でのFPGAのサポート事情」を参照してください。
はじめに
Linux FPGA Manager Framework とは
Linux Kernel 4.4.4 から FPGA Manager Framework が追加されました。これはLinux から異なる種類の FPGA をコンフィギュレーションするための共通インターフェースを提供するためのものです。
FPGA Manager Framework は次の図のような構成になっています。
図1 FPGA Manager Framework
Linux Kernel 4.4.4 では、FPGA ベンダーの Xilinx 社がこのフレームワークに対応した Zynq 用の Low Level FPGA Driver を提供しています。同じく Altera 社は Altera-SoC用の Low Level FPGA Driver を提供しています。
準備
Linux Kernel のビルド
私が FPGA Manager の動作を確認した Linux のバージョンは4.4.4です。通常は FPGA Manager オプションはオフになっているので、このオプションをオンにして Linux Kernel をビルドしておく必要があります。
具体的には make menuconfig で Device Drivers ---> FPGA Configuration Support ---> FPGA Configuration Framework をオンにするか、.config にCONFIG_FPGA=y を追加します。
また、使用する FPGA にあわせて Low Level FPGA Driver も組み込む必要があります。
Zynq の場合は、make menuconfig で Device Drivers ---> FPGA Configuration Support ---> Xilinx Zynq FPGA をオンにするか、.config に CONFIG_FPGA_MGR_ZYNQ_FPGA=y を追加します。
Altera-SoC の場合は、make menuconfig で Device Drivers ---> FPGA Configuration Support ---> Altera SOCFPGA FPGA Managerをオンにするか、.config にCONFIG_FPGA_MGR_SOCFPGA=y を追加します。
fpgacfg (FPGA Configuration Interface for Linux FPGA Manager Framework)
現時点(2016年4月)の Linux Kernel にはFPGA Manager Framework と Zynq用のLow Level FPGA Driver と Altera-SoC 用の Low Level FPGA Driver が提供されていますが、何故か Higher Level Interface が提供されていません。したがって、現時点では FPGA のコンフィギュレーションはカーネル内部からしか行えません。
そこで、簡易的な Higher Level Interface として作ったのが fpgacfg です。このデバイスドライバを組み込むことで、ユーザー側からFPGA のコンフィギュレーションを行うことが出来るようになります。
https://github.com/ikwzm/fpgacfg
下記のようにダウンロードして、Makefile を適当に修正してコンパイルしてください。
shell$ git clone https://github.com/ikwzm/fpgacfg.git
shell$ cd fpgacfg
shell$ make
試用例
fpgacfg のインストール (Zynq)
Device Tree に次のようなエントリ(fpgacfg0)を追加します。
devcfg@f8007000 は、もともと Device Tree に追加されている Zynq 用の Low Level FPGA Driver です。
fpgacfg は、どの Low Level FPGA Driver を制御するかを指定する必要があります。ここでは、fpga-manager-path に "/amba/devcfg@f8007000" を書くことによって、devcfg@f8007000 を指定しています。
/dts-v1/;
/ {
:
(中略)
:
amba {
devcfg@f8007000 {
compatible = "xlnx,zynq-devcfg-1.0";
reg = <0xf8007000 0x100>;
interrupt-parent = <0x3>;
interrupts = <0x0 0x8 0x4>;
clocks = <0x1 0xc>;
clock-names = "ref_clk";
syscon = <0x5>;
};
:
(中略)
:
fpgacfg0 {
compatible = "ikwzm,fpgacfg-0.10.a";
fpga-manager-path = "/amba/devcfg@f8007000";
};
:
(後略)
:
上記の Device Tree を使って Linux を起動した後、次のようにfpgacfg をロードします。
zynq# insmod insmod fpgacfg.ko
[ 2699.188074] fpgacfg amba:fpgacfg0: driver probe start.
[ 2699.193477] fpgacfg amba:fpgacfg0: driver installed.
[ 2699.198361] fpgacfg amba:fpgacfg0: device name : fpgacfg0
[ 2699.203875] fpgacfg amba:fpgacfg0: fpga manager : Xilinx Zynq FPGA Manager
アンインストールするには rmmod を使います。
zynq# rmmod fpgacfg
[ 3129.269938] fpgacfg amba:fpgacfg0: driver unloaded
また、Device Tree Overlay を使ってインストールすることも出来ます。Device Tree Overlay を使うには、次のような Device Tree を用意します。
/dts-v1/;
/ {
fragment@0 {
target-path = "/amba";
__overlay__ {
fpgacfg0 {
compatible = "ikwzm,fpgacfg-0.10.a";
fpga-manager-path = "/amba/devcfg@f8007000";
};
};
};
};
この Device Tree を こちらのDevice Tree Blob Overlay Configuration File System を使ってインストールする場合は次のようにします。
zynq# mkdir /config/device-tree/overlays/fpgacfg0
zynq# dtc -I dts -O dtb -o /config/device-tree/overlays/fpgacfg0/stbo fpgacfg0.dts
zynq# echo 1 > /config/device-tree/overlays/fpgacfg0/status
zynq# insmod fpgacfg.ko
[ 2699.188074] fpgacfg amba:fpgacfg0: driver probe start.
[ 2699.193477] fpgacfg amba:fpgacfg0: driver installed.
[ 2699.198361] fpgacfg amba:fpgacfg0: device name : fpgacfg0
[ 2699.203875] fpgacfg amba:fpgacfg0: fpga manager : Xilinx Zynq FPGA Manager
fpgacfg のインストール (Altera-SoC)
Device Tree に次のようなエントリ(fpgacfg0)を追加します。
fpgamgr@ff706000 は、もともと Device Tree に追加されている Altera-SoC 用の Low Level FPGA Driver です。
fpgacfg は、どの Low Level FPGA Driver を制御するかを指定する必要があります。ここでは、fpga-manager-path に "/soc/fpgamgr@ff706000" を書くことによって、fpgamgr@ff706000 を指定しています。
/dts-v1/;
/ {
:
(中略)
:
soc {
fpgamgr@ff706000 {
compatible = "altr,socfpga-fpga-mgr";
reg = <0xff706000 0x1000 0xffb90000 0x1000>;
interrupts = <0x0 0xaf 0x4>;
};
:
(中略)
:
fpgacfg0 {
compatible = "ikwzm,fpgacfg-0.10.a";
fpga-manager-path = "/soc/fpgamgr@ff706000";
};
:
(後略)
:
上記の Device Tree を使って Linux を起動した後、次のようにfpgacfg をロードします。
socfpga# insmod insmod fpgacfg.ko
[ 304.854598] fpgacfg soc:fpgacfg0: driver probe start.
[ 304.859864] fpgacfg soc:fpgacfg0: driver installed.
[ 304.864773] fpgacfg soc:fpgacfg0: device name : fpgacfg0
[ 304.870160] fpgacfg soc:fpgacfg0: fpga manager : Altera SOCFPGA FPGA Manager
アンインストールするには rmmod を使います。
socfpga# rmmod fpgacfg
[ 411.269938] fpgacfg soc:fpgacfg0: driver unloaded
また、Device Tree Overlay を使ってインストールすることも出来ます。Device Tree Overlay を使うには、次のような Device Tree を用意します。
/dts-v1/;
/ {
fragment@0 {
target-path = "/soc";
__overlay__ {
fpgacfg0 {
compatible = "ikwzm,fpgacfg-0.10.a";
fpga-manager-path = "/soc/fpgamgr@ff706000";
};
};
};
};
この Device Tree を こちらのDevice Tree Blob Overlay Configuration File System を使ってインストールする場合は次のようにします。
socfgpa# mkdir /config/device-tree/overlays/fpgacfg0
socfpga# dtc -I dts -O dtb -o /config/device-tree/overlays/fpgacfg0/stbo fpgacfg0.dts
socfgpa# echo 1 > /config/device-tree/overlays/fpgacfg0/status
socfpga# insmod fpgacfg.ko
[ 304.854598] fpgacfg soc:fpgacfg0: driver probe start.
[ 304.859864] fpgacfg soc:fpgacfg0: driver installed.
[ 304.864773] fpgacfg soc:fpgacfg0: device name : fpgacfg0
[ 304.870160] fpgacfg soc:fpgacfg0: fpga manager : Altera SOCFPGA FPGA Manager
デバイスファイル
fpgacfgをinsmodでカーネルにロードすると、次のようなデバイスファイルが作成されます。<device-name>には、fpgacfg0等のデバイス名が入ります。
- /dev/<device-name>
- /sys/class/fpgacfg/<device-name>/buffer_state
- /sys/class/fpgacfg/<device-name>/data_buffer_size
- /sys/class/fpgacfg/<device-name>/data_format
- /sys/class/fpgacfg/<device-name>/data_store_size
- /sys/class/fpgacfg/<device-name>/flags
- /sys/class/fpgacfg/<device-name>/fpga_mgr_state
- /sys/class/fpgacfg/<device-name>/head_buffer_size
- /sys/class/fpgacfg/<device-name>/head_store_size
- /sys/class/fpgacfg/<device-name>/is_partial_bitstream
- /sys/class/fpgacfg/<device-name>/load_start
- /sys/class/fpgacfg/<device-name>/max_data_size
/dev/<device-name>
/dev/<device-name>はFPGAの各種コンフィギュレーションファイルをFPGAに書き込むのに使います。
zynq# cp design_1_wrapper.bit /dev/fpgacfg0
FPGAのコンフィギュレーションファイルフォーマットとしては、RBF(Raw Binary Format)か、Xilinx Bitstream Formatのどちらかを後述の /sys/class/fpgacfg/<device-name>/data_format で指定する事ができます。
残念ながら、FPGA Manager の仕様上、FPGAのコンフィギュレーションデータをリードバックすることは出来ません。
/sys/class/fpgacfg/<device-name>/data_format
このファイルはFPGAコンフィギュレーションファイルのフォーマットを指定します。
このファイルに0を書くことで、RBF(Raw Binary Format)を指定します。
このファイルに1を書くことで、Xilinx Bitstream Format を指定します。
このファイルを読むことで、現在設定されているフォーマットが判ります。
当然ですが、Xilinx Bitstream Format はXilinx社製の FPGA でしか使えません。RBF(Raw Binary Format) はAltera社製 FPGA でも Xilinx 社製 FPGA でも使えます。
/sys/class/fgpacfg/<device-name>/max_data_size
max_data_size はFPGA コンフィギュレーションファイルフォーマットがRBF(Raw Binary Format)の場合に、ファイルのバイト数を指定します。
ファイルのバイト数を指定する理由は、FPGA Manager はメモリ上にコンフィギュレーションデータが全て展開されてからで無ければFPGAのコンフィギュレーションを行いません。そのために一度カーネル内部のバッファにコンフィギュレーションデータを蓄えます。Raw Binary Format はファイル内にデータの大きさの情報が無いので、どのくらいバッファを用意しなければならないか判りません。そこで、max_data_size で確保するバッファの大きさを指定する必要があるのです。
Xilinx Bitstream Format の場合は、ヘッダ部にデータのサイズがあるので、max_data_size を指定する必要はありません。
zynq# ls -la
rwxr-xr-x 2 ichiro ichiro 4096 4月 13 13:46 .
drwxr-xr-x 21 ichiro ichiro 4096 4月 8 05:42 ..
-rw-r--r-- 1 ichiro ichiro 2083776 4月 12 14:26 design_1_wrapper.bin
zynq# echo 2083776 >/sys/class/fpgacfg/fpgacfg0/max_data_size
zynq# cat /sys/class/fpgacfg/fpgacfg0/max_data_size
2083776
zynq# cp design_1_wrapper.bin /dev/fpgacfg0
/sys/class/fpgacfg/<device-name>/load_start
FPGAコンフィギュレーションデータをFPGAにロードする事を指定します。
このファイルに1を書くことで、ロードを開始します。
このファイルに0を書いておくことで、ロードを遅らせることが出来ます。例えば次のように、あらかじめ /sys/class/fpga/<device-name>/load_startに0を書いておいてから、/dev/<device-name> にFPGAコンフィギュレーションデータを書き込んだ場合、すぐにはFPGAのロードを行いません。この後、/sys/class/fpgacfg<device-name>/load_start に1を書き込んだ時点で FPGA のロードを開始します。
zynq# echo 0 > /sys/class/fpgacfg/fpgacfg0/load_start
zynq# cp design_1_wrapper.bin /dev/fpgacfg0
zynq# cat /sys/class/fpgacfg/fpgacfg0/buffer_state
data fill
zynq# echo 1 > /sys/class/fpgacfg/fpgacfg0/load_start
zynq# cat /sys/class/fpgacfg/fpgacfg0/buffer_state
done
また、あらかじめ/sys/class/fpgacfg/<device-name>/load_start に1を書いておいてから、/dev/<device-name> にFPGAコンフィギュレーションデータを書き込んだ場合、すぐにはFPGAのロードを開始します。
zynq# echo 1 > /sys/class/fpgacfg/fpgacfg0/load_start
zynq# cp design_1_wrapper.bin /dev/fpgacfg0
zynq# cat /sys/class/fpgacfg/fpgacfg0/buffer_state
done
/sys/class/fpgacfg/<device-name>/is_partial_bitstream
FPGA コンフィギュレーションデータが Partial Reconfiguration 用かどうかを指定します。このファイルに1を書くことで、Partial Reconfiguration 用であることを指定します。
Partial Reconfiguration は、現時点では Xilinx 社製の FPGA にしか対応していません。と言っても、Partial Reconfiguration を行うには別途に有償のライセンスが必要なため、現時点では動作を確認していません。
Altera 社製の Low Level FPGA Driver は対応していないようでした。
/sys/class/fpgacfg/<device-name>/flags
FPGA Manager に渡す各種フラグを指定します。とは言っても、現時点で有効なフラグは Xilinx社製FPGA 用の Partial Reconfiguration がBit0 に割り当てられているだけのようです。
/sys/class/fpgacfg/<device-name>/buffer_state
現在のバッファの状態を示します。主にデバッグ用です。書き込みはできません。次の文字列が読めます。
- "none"
- "empty"
- "header store"
- "data store"
- "data fill"
- "fpga load"
- "done"
- "error"
/sys/class/fpgacfg/<device-name>/fpga_mgr_state
現在のFPGA Managerの状態を示します。主にデバッグ用です。書き込みはできません。次の文字列が読めます。
- "unknown"
- "power off"
- "power up"
- "reset"
- "firmware request"
- "firmware request error"
- "write init"
- "write init error"
- "write"
- "write error"
- "write complete"
- "write complete error"
- "operating"
所感
一時は Linux が正式に FPGA をサポートしたといって喜んでいたのですが、いざ蓋を開けてみれば、実は Framework と Low Level FPGA Driver だけしかなくてユーザー側からは使えないという残念なことになっていました。この点については、こちらの記事でも述べたとおり、Device Tree Overlay も同様でした。ちゃんと使えるようになるにはもう少しかかりそうです。ここらへんをもう少し詳しく以下の記事にしました。詳細はそちらをご覧ください。
Xilinx 社製 FPGA の場合は、かつては xdevcfg というデバイスドライバが用意されていました。Linux のメインラインには含まれていませんが、Xilinx 社が提供している Linux カーネルには含まれています。xdevcfg はユーザー側から FPGA のコンフィギュレーションやリードバックが出来て大変便利だったのですが、今回、正式に FPGA Manager が Linux カーネルに導入されたことにより、もしかしたら xdevcfg が使えなくなるかもしれません。Low Level のハードウェアを奪い合うことになるからです。
Higher Level Interface が提供されていない状態で xdevcfg が使えなくなることは Xilinx ユーザーにとっては迷惑なだけです。早急に Higher Level Interface が Linux に導入されることを期待します。
ブートイメージと使用例の提供
上記の FPGA Manager に対応した Linux Kernel 4.4.7 のビルド済みのイメージと fpgacfg をこちらに用意しました。
このイメージの説明や使用例は次の記事を参考にしてください。
- 「FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(ブートイメージの提供)」@Qiita
- 「FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(ZYBO-Examples)」@Qiita