Synthesijerで作ったモジュールをMessagePack-RPCで制御する(アーキテクチャ編)

#はじめに
[MessagePack-RPCを使ってFPGAを制御](http://qiita.com/ikwzm/items/2644c6e50a7049c75d49)の続きです。
今回は Synthesijer で作ったモジュールを MessagePack-RPC で制御する方法を紹介します。
プロジェクトの全ソースコードは[こちら](https://github.com/ikwzm/msgpack-vhdl-examples/tree/master/examples/accumulator)にあります。
次のような論理合成可能なJavaのコードを例にします。

````Java:Accumulator.java
public class Accumulator {
    public int reg;
    public int add(int x) {
        reg = reg + x;
        return reg;
    }
}
````

#アーキテクチャ

##全体のブロック図

![akgeo1.jpg](https://qiita-image-store.s3.amazonaws.com/0/24981/b3899aa8-f2a1-cdfa-013a-095a0488e625.jpeg)

## Accumulator_Server

Accumulator_Server はJavaで記述しSynthesijerで高位合成した Accumulatorと、MsgPack-RPC-VHDLを使って構築したMsgPack_RPC_Serverの二つで構成されます。


###Accumulator

````Java:Accumulator.java
public class Accumulator {
    public int reg;
    public int add(int x) {
        reg = reg + x;
        return reg;
    }
}
````

上のJavaコードをSynthesijerで高位合成したものです。Synthesijer によって、次のようなentityを持つVHDLファイルが生成されます。

````VHDL:Accumulator.vhd
entity Accumulator is
  port (
    clk : in std_logic;
    reset : in std_logic;
    reg_in : in signed(32-1 downto 0);
    reg_we : in std_logic;
    reg_out : out signed(32-1 downto 0);
    add_x : in signed(32-1 downto 0);
    add_return : out signed(32-1 downto 0);
    add_busy : out std_logic;
    add_req : in std_logic
  );
end Accumulator;
````

###Unpacker
シリアライズされたMessagePack-RPCのリクエストメッセージを AXI4-Streamインターフェースから受け取って内部形式に変換します。

###Requester
メソッド名を解析して該当するメソッドインターフェース(add_if、set_if、get_if)にmsgidとparamを渡します。

###Responder
メソッドインターフェース(add_if、set_if、get_if)からのレスポンス出力要求を調停して、レスポンスメッセージを構築します。

###Packer
レスポンスメッセージをMessagePack形式にシリアライズして AXI4-Streamインターフェースから出力します。

###set_if
public宣言された変数(reg)に値を設定するモジュールです。
次のようなMessagePack-RPC リクエストを受け付けます。
````
[0, msgid, "$SET", [{"reg": value}]]
````
メソッド名は"\$SET"です。頭に\$がついているのは、単にJavaのメソッドと名前がかぶらなようにするためです。
パラメータは変数名と設定する値が対になっているmapを指定します。
この例では変数名に"reg"、値は整数を指定します。
成功すれば次のようなレスポンスが返ってきます。
````
[1, msgid, nil, nil]
````
###get_if
public宣言された変数(reg)から値を読むモジュールです。
次のようなMessagePack-RPC リクエストを受け付けます。
````
[0, msgid, "$GET", [{"reg": nil}]]
````
メソッド名は"\$GET"です。頭に\$がついているのは、単にJavaのメソッドと名前がかぶらなようにするためです。
パラメータは読み出したい変数の名前と読み出す数またはnilが対になっているmapを指定します。
この例では変数名に"reg"、値はnilを指定します。
成功すれば次のように、読み出した変数の名前と読み出した値が対になったmapが返ってきます。
````add
[1, msgid, nil, [{"reg": value}]]
````

###add_if
addメソッドを呼び出すモジュールです。
次のようなMessagePack-RPCリクエストを受け付けます。
````
[0, msgid, "add", [value]]
````
valueにはaddメソッドに渡す引数を指定します。
成功すれば次のように、addメソッドの戻り値が返ってきます。
````
[1, msgid, nil, result]
````
add_ifはAccumulator に対して引数をadd_xに出力し、リクエスト信号(add_req)を'1'にします。
Accumulatorはリクエスト信号(add_req)に対してビジー信号(add_busy)に'1'を出力して、処理が終わるとビジー信号に'0'を出力して結果をadd_return に出力します。
add_if はaccumulator からの結果(add_return)を内部形式に変換してmsgidと一緒にResponderに渡します。


## PTTY_AXI


PTTY_AXI はAXI4-Streamの入出力インターフェースをホストからはシリアルインターフェースとして見せるためのIPです。

* ホストとのインターフェースはAXI4です。

* Accumulator_ServerとのインターフェースはAXI4-Streamです。

* 送信と受信に各々128バイトのバッファを持っています。


## /dev/zptty


/dev/zpttyはPTTY_AXIを介してAccumulator_Serverの入出力をあたかもシリアルポートに見せるためのデバイスドライバです。
このドライバを使うことにより、Accumulator_ServerとのMessagePack-RPCのやりとりはシリアルポートを介して行うように見えます。
/dev/zpttyは、Linux標準のttyコア部と、PTTY_AXI固有のドライバ部zptty.koで構成されます。


## Client


Linuxのユーザー空間で動作するクライアントプログラムです。
このクライアントプログラムがMessagePack-RPCのリクエストメッセージを作成し/dev/zpttyを介してAccumulator_Serverに送信します。
そしてAccumulator_ServerからのMessagePack-RPCのレスポンスメッセージを/dev/zpttyを介して受信します。




#課題

現時点では未だ実装途中のため、次のような課題が残っています。
 
 - ~~add_if、set_if、get_if はVHDLでゴリゴリ書かなければなりません。    将来的には、[MessagePack IDL Compiler](https://github.com/msgpack-rpc/msgpack-rpc/tree/master/idl)から生成するか、Synthesijerから自動的に生成することを考えています。~~
 - msgpack-vhdl ver.0.2.0 以降、Synthesijer が生成した VHDL からインターフェース回路を生成するスクリプト([msgpack-rpc-synthesijer-ifgen](https://github.com/ikwzm/msgpack-vhdl/blob/master/tools/msgpack-rpc-synthesijer-ifgen))が追加されています。
 - ~~public変数やメソッドのパラメータ、戻り値の型は整数のみです。~~
 - msgpack-vhdl ver.0.2.0 以降、public 変数に配列がサポートされました。

#参照

[MessagePack (http://msgpack.org/)](http://msgpack.org/)
[MessagePack-RPC (https://github.com/msgpack-rpc/msgpack-rpc)](https://github.com/msgpack-rpc/msgpack-rpc)
[MessagePack for VHDL (https://github.com/ikwzm/msgpack-vhdl)](https://github.com/ikwzm/msgpack-vhdl)
[MessagePack for VHDL Examples (https://github.com/ikwzm/msgpack-vhdl-examples)](https://github.com/ikwzm/msgpack-vhdl-examples)
[MessagePack-RPCを使ってFPGAを制御](http://qiita.com/ikwzm/items/2644c6e50a7049c75d49)
[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(IP-Package編)](http://qiita.com/ikwzm/items/924fc3fd59bdf7da55a2)
[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(ZYNQ論理合成編)](http://qiita.com/ikwzm/items/0254f1d49602095b5cde)
[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(TTYドライバ編)](http://qiita.com/ikwzm/items/533b905f7d1eb2e6c4d5)
[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(MessagePack-Ruby編)](http://qiita.com/ikwzm/items/f742e2c9b5d9642d8857)
[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(リモートサーバー編)](http://qiita.com/ikwzm/items/cfde888094c7c73f4ba6)