LoginSignup
2
3

More than 5 years have passed since last update.

Synthesijerで作ったモジュールをMessagePack-RPCで制御する(MessagePack-Ruby編)

Posted at

はじめに

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

テスト用スクリプト

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)
MessagePack for VHDL Examples (https://github.com/ikwzm/msgpack-vhdl-examples)
MessagePack-RPCを使ってFPGAを制御
Synthesijerで作ったモジュールをMessagePack-RPCで制御する(アーキテクチャ編)
Synthesijerで作ったモジュールをMessagePack-RPCで制御する(IP-Package編)
Synthesijerで作ったモジュールをMessagePack-RPCで制御する(ZYNQ論理合成編)
Synthesijerで作ったモジュールをMessagePack-RPCで制御する(TTYドライバ編)

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3