##はじめに
Synthesijerで作ったモジュールをMessagePack-RPCで制御する話もいよいよ最終コーナーです。
今回は、Synthesijerで作った MessagePack-RPC サーバーを、ZYNQ+Linux 上のクライアントから呼び出す例を示します。
クライアントには MessagePack-Ruby を使います。他の言語でも出来るかもしれません。
ただ、現在、私の環境(ZYNQ+Debian8(jessie))では、MessagePack-RPC-Ruby のインストールが上手くいかなかったので、今回はMessagePack-RPC-Rubyは使っていません。
##準備
次の ruby パッケージが必要です。
- msgpack-ruby
- serialport
これらをインストールします。Debian8(jessie)ではこれらのインストールはgem では失敗するので apt-get を使います。
shell# apt-get install ruby-msgpack
shell# apt-get install ruby-serialport
##クライアントのコード例
accumulator_server.rb
require 'msgpack'
require 'serialport'
class AccumulatorServer
def initialize
@port = SerialPort.new("/dev/zptty0", 38400)
@port.read_timeout = 1000
@port.flow_control = SerialPort::HARD
@unpacker = MessagePack::Unpacker.new(@port)
@msgid = 0
end
def call(method, args)
@msgid = (@msgid+1) % 256
req = [0, @msgid, method, args].to_msgpack
@port.write(req)
@unpacker.each do |obj|
type, resid, error, result = obj
if (error == nil) then
return result
else
puts error
return nil
end
break
end
end
def get_regs
result = call('$GET', [{"reg" => nil}])
if result != nil
return result[0]["reg"]
else
return nil
end
end
def set_regs(arg)
result = call('$SET', [{"reg" => arg}])
end
def add(arg)
return call('add', [arg])
end
end
```
##テスト用スクリプト
```ruby:test.rb
require_relative 'accumulator_server'
acc = AccumulatorServer.new
rnd = Random.new
acc_reg=1
acc.set_regs(acc_reg)
(0..1000).to_a.each do |n|
num = rnd.rand(0..10000)
curr_reg = acc.get_regs
add_reg = acc.add(num)
next_reg = acc.get_regs
acc_reg = acc_reg + num
status = ((acc_reg == next_reg) && (acc_reg == add_reg)) ? "OK" : "NG"
puts "#{status} : reg = #{curr_reg}; add(#{num}) => #{add_reg}; reg = #{next_reg}"
end
acc_reg=1
acc.set_regs(acc_reg)
(0..1000).to_a.each do |n|
num = rnd.rand(-10000..0)
curr_reg = acc.get_regs
add_reg = acc.add(num)
next_reg = acc.get_regs
acc_reg = acc_reg + num
status = ((acc_reg == next_reg) && (acc_reg == add_reg)) ? "OK" : "NG"
puts "#{status} : reg = #{curr_reg}; add(#{num}) => #{add_reg}; reg = #{next_reg}"
end
acc.call("sub", [1])
acc.call("add", 1)
acc.call("add", "a")
```
test.rb を ruby で実行します。
```
shell% ruby test.rb
:
(中略)
:
OK : reg = -4898220; add(-3407) => -4901627; reg = -4901627
OK : reg = -4901627; add(-6936) => -4908563; reg = -4908563
NoMethodError
ArgumentError
ArgumentError
```
##参照
[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で制御する(アーキテクチャ編)](http://qiita.com/ikwzm/items/6cb623b057a687ff4a8e)
[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/drafts/533b905f7d1eb2e6c4d5)