LoginSignup
0
0

More than 5 years have passed since last update.

フィボナッチを求める回路をFortRockとMessagePack-RPCでFPGAに実装してみた(シミュレーション編)

Posted at

はじめに

高位合成友の会第三回(2015年12月8日)で発表のあった高位合成ツールの中で、唯一、当日までに試すことの出来なかった FortRock ですが、ちょっと遅れましたがフィボナッチを求める回路を記述してシミュレーションしてみました。
FortRock は LLVMを用いた Fortran ベースの高位合成ツールです。
高位合成友の会での FortRock の発表スライドはこちらです。

用意するもの

  • Xilinx Vivado 2015.3
  • FortRock
  • clang++-3.6 (FortRock をコンパイルするのに必要)
  • gfortran-4.8 (FortRock で高位合成するのに必要)
  • LLVM 3.4 (FortRock で高位合成するのに必要)
  • dragonegg-4.8 (FortRock で高位合成するのに必要)
  • Ruby 1.9.3 以降
  • msgpack-vhdl-examples

ブロック図

akgeo2.jpg

ソースコード

フィボナッチを求めるFortranのソースコードです。

fib.f
      SUBROUTINE FIB(N,O)
      INTEGER N,O,I,CURR,NEXT,PREV
      CURR = 0
      NEXT = 1
      I    = 0
 0001 CONTINUE
      IF(I >= N)THEN
        GOTO 0002
      ENDIF
      PREV = CURR
      CURR = NEXT
      NEXT = NEXT + PREV
      I = I + 1
      GOTO 0001
 0002 CONTINUE
      O = CURR
      RETURN
      END

手順

事前の準備

FortRock を使うためには、gfortran-4.8、dragonegge-4.8、llvm-3.4 が必要です。
また、FortRock をコンパイルするのに clang++-3.6 が必要です。

shell% sudo apt-get install gfortran-4.8
shell% sudo apt-get install dragonegge-4.8
shell% sudo apt-get install llvm-3.4

FortRock をインストール

shell% git clone https://github.com/nyakuo/FortRock.git
shell% cd FortRock/src
shell% make

これで FortRock/src/ に fortrock.so が出来ていれば、成功です。

msgpack-vhdl-examplesリポジトリと各submodule をダウンロード

shell% git clone git://github.com/ikwzm/msgpack-vhdl-examples.git
shell% cd msgpack-vhdl-examples
shell% git submodule init
shell% git submodule update

fib.f をテスト

今回、初めてFortran を使うので、試しに次のようなプログラムを作って fib.f をテストしました。

fib_test.f
      program fib_test
      implicit none
      integer i, n, o
      n = 7
      i = 0
 1000 call fib(i,o)
      print *,i,o
      if (i < n) then
         i = i + 1
         goto 1000
      endif
      end
shell% cd examples/fibonacci/src/main/fortrock
shell% gfortran-4.8 -O1 -o ./fib_test ./fib_test.f ./fib.f 
shell% ./fib_test
           0           0
           1           1
           2           1
           3           2
           4           3
           5           5
           6           8
           7          13

fib.fをFortRockで高位合成

shell% cd examples/fibonacci/src/main/fortrock
shell% gfortran-4.8 -O1 ./fib.f -fplugin=/usr/lib/gcc/x86_64-linux-gnu/4.8/plugin/dragonegg.so -fplugin-arg-dragonegg-emit-ir -S -o ./0fib00.s
shell% opt-3.4 -load ~/work/FortRock/src/fortrock.so -instnamer -fortrock ./0fib00.s -S
opt-3.4: CommandLine Error: Argument 'info-output-file' defined more than once!
opt-3.4: CommandLine Error: Argument 'track-memory' defined more than once!
opt-3.4: CommandLine Error: Argument 'version' defined more than once!
opt-3.4: CommandLine Error: Argument 'print-all-options' defined more than once!
opt-3.4: CommandLine Error: Argument 'print-options' defined more than once!
opt-3.4: CommandLine Error: Argument 'help-hidden' defined more than once!
opt-3.4: CommandLine Error: Argument 'help' defined more than once!
opt-3.4: CommandLine Error: Argument 'help-list-hidden' defined more than once!
opt-3.4: CommandLine Error: Argument 'help-list' defined more than once!
opt-3.4: CommandLine Error: Argument 'time-passes' defined more than once!
opt-3.4: CommandLine Error: Argument 'print-after-all' defined more than once!
opt-3.4: CommandLine Error: Argument 'print-before-all' defined more than once!
opt-3.4: CommandLine Error: Argument 'print-after' defined more than once!
opt-3.4: CommandLine Error: Argument 'print-before' defined more than once!
opt-3.4: CommandLine Error: Argument 'debug-pass' defined more than once!
; ModuleID = './0fib00.s'
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64--linux-gnu"

module asm "\09.ident\09\22GCC: (Ubuntu 4.8.4-1ubuntu15) 4.8.4 LLVM: 3.4.2\22"

; Function Attrs: nounwind uwtable
define void @fib_(i32* noalias nocapture readonly %n, i32* noalias nocapture %o) unnamed_addr #0 {
entry:
  %tmp = load i32* %n, align 4
  %tmp1 = icmp sgt i32 %tmp, 0
  br i1 %tmp1, label %"4.lr.ph", label %"5"

"4.lr.ph":                                        ; preds = %entry
  %tmp2 = load i32* %n, align 4
  br label %"4"

"4":                                              ; preds = %"4", %"4.lr.ph"
  %tmp3 = phi i32 [ 1, %"4.lr.ph" ], [ %tmp6, %"4" ]
  %tmp4 = phi i32 [ 0, %"4.lr.ph" ], [ %tmp7, %"4" ]
  %tmp5 = phi i32 [ 0, %"4.lr.ph" ], [ %tmp3, %"4" ]
  %tmp6 = add i32 %tmp3, %tmp5
  %tmp7 = add i32 %tmp4, 1
  %tmp8 = icmp sgt i32 %tmp2, %tmp7
  br i1 %tmp8, label %"4", label %"5"

"5":                                              ; preds = %"4", %entry
  %.lcssa = phi i32 [ 0, %entry ], [ %tmp3, %"4" ]
  store i32 %.lcssa, i32* %o, align 4
  ret void
}

attributes #0 = { nounwind uwtable "no-frame-pointer-elim-non-leaf"="false" }

途中で出力するLLVMファイルの名前が 0fib00.s としているのは、何故かモジュール名の前に1文字、後ろに2文字つけないと、Verilog-HDL のモジュール名が正常に生成されないからです。
また、opt-3.4 で CommandLine Error が出ていますが、とりあえず気にしないでください。
output.v が生成されていれば成功です。

なお、output.v を Verilog でシミュレーション/論理合成するには、Add、multiplier、Divider等の演算モジュールが必要です。実際には Add しか使わないのですが、何故か output.v には multiplier と Divider のインスタンスも含まれているのでとりあえずダミーでもいいから用意しておきます。

operator.v
module Add(a,b,clk,ce,s);
   input  signed[31:0] a;
   input  signed[31:0] b;
   input               clk;
   input               ce;
   output signed[31:0] s;
   reg    signed[31:0] s;

   always @(posedge clk)
     if (ce)
       s <= a + b;
endmodule

module multiplier(a,b,clk,ce,p);
   input  signed[31:0] a;
   input  signed[31:0] b;
   input               clk;
   input               ce;
   output signed[31:0] p;
   reg    signed[31:0] p;

   always @(posedge clk)
     if (ce)
       p <= a * b;
endmodule

module Divider(dividend,divisor,clk,quotient,fractional,rfd);
   input  signed[31:0] dividend;
   input  signed[31:0] divisor;
   input               clk;
   output signed[31:0] quotient;
   output signed[31:0] fractional;
   output signed[31:0] rfd;
endmodule

テストシナリオの作成

すでに作成済みのテストシナリオ(examples/fibonacci/src/test/scenarios/test_1_32.snr)を用意しています。このテストシナリオを使う場合は、以下の手順は飛ばしてください。

AXI4_Stream_Master_PlayerおよびAXI4_Stream_Slave_Player用のテストシナリオを作ります。

shell% cd examples/fibonacci/src/test/scenarios
shell% ruby test_1_32.rb

test_1_32.rb はテストシナリオ(YAML形式)を生成するためのrubyスクリプトです。

Vivado プロジェクトの作成

Vivado プロジェクトを作成するためのTclファイル(create_project.tcl)を用意しています。
Vivadoを起動して次のメニューからTclファイルを実行してください。

Vivado > Tools > Run Tcl Script... > examples/fibonacci/sim/vivado/fortrock/create_project.tcl

シミュレーションを実行

前節で作った Vivado プロジェクトを開き、次のようにシミュレーションを実行してください。

Vivado > Flow > Run Simulation > Run Behavioral Simulation

結果

とりあえずシミュレーションすることは出来ました。
n=0~42までの計算結果もあっています。
参考までにn=2の時のシミュレーション波形を示します。

fibonacci_fortrock_wave.jpg

シミュレーション時のログは次の通りです。
fibonacci_fortrock_log.jpg

参考

0
0
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
0
0