狠狠撸

狠狠撸Share a Scribd company logo
LLVMを用いた
Fortranベースの高位合成ツール
FortRockの開発
東京農工大学工学府
情報工学専攻 中條研究室
山下 貴大
FortRockとは
● FortranプログラムをVerilog HDLに変換
○ パーサにgfortranを使用
○ DragonEggによってLLVM IRを得る
○ LLVM IRをModulePassによってVerilog HDLに変換する
■ FortRockのコア部分
2
高位合成友の会15/12/08
動機
● Fortran
○ 従来の科学技術計算で用いられてきた
■ 資産が膨大 & 現在も開発されている
● Fortran資産をハードウェア化したいというニーズ
○ ハードウェアに関する知識が必要
○ ハードウェア記述言語によるアルゴリズムの実装が困難
3
高位合成友の会15/12/08
Fortranベースの高位合成
● Fortran → HDL
○ 存在しない
● Fortran → C → C言語ベースの高位合成 → HDL
○ 手動
■ 手間がかかる
■ バグが発生する可能性
○ F2c → C言語ベースの高位合成
■ FORTRAN 77までしか対応していない
→ 科学技術計算では不適
4
高位合成友の会15/12/08
F2JRT - (Fortran to JavaRock-Thrash)
● JavaRock-Thrash
○ Java言語ベースの高位合成技術
○ Verilog HDLを出力
○ Javaのスレッドに対応
○ 一部文法に制限
● F2JRT
○ Fortranから JavaRock-Thrash で利用可能な
Javaコードに変換する
5
高位合成友の会15/12/08
F2JRT の問題点
● Javaが対応していない文法
○ Fortranのgoto
● 最適化が困難
○ JavaRock-Thrash で性能がでるJavaソース
コードを出力する必要
6
高位合成友の会15/12/08
目的と目標
● 目的
○ Fortran資産の活用
■ Fortranから直接HDLを出力
■ FPGA上で実行
● 目標
○ Fortran言語による高位合成の有用性の検証
7
高位合成友の会15/12/08
FortRockの処理の流れ
Fortran言語で記述されたプログラムをLLVM IRを
経由してVerilog HDLを出力
8
FortRock
入力
Fortran
中間表現
LLVM IR
出力
Verilog HDL
DragonEgg
(LLVMフロントエンド)
FortRock Core
高位合成友の会15/12/08
FortRockの処理フロー
1. gfortranとDragonEggを用いてLLVM IRに変換
2. instnamerパスの実行
3. FortRockCoreの処理
a. runOnModule()
i. 演算器のインスタンス化
ii. グローバル変数のインスタンス化
iii. モジュールの入出力のインスタンス化
iv. ラベルのインスタンス化
v. 変数のインスタンス化
vi. 命令のDFG化
b. generate()
i. スケジューリング
ii. 最適化
iii. step信号のビット幅の修正
iv. Verilog HDLの出力処理
9
高位合成友の会15/12/08
環境
● Ubuntu15.04
● C++
● gfortran-4.8
○ 入力Fortranプログラムのコンパイラ
● DragonEgg-4.8
○ gfortran-4.8のプラグイン
● LLVM-3.4
○ FortRockの実行
● clang++3.6
○ FortRockのコンパイル
10
高位合成友の会15/12/08
FortRockの処理フロー
1. gfortranとDragonEggを用いてLLVM IRに変換
2. instnamerパスの実行
3. FortRockCoreの処理
a. runOnModule()
i. 演算器のインスタンス化
ii. グローバル変数のインスタンス化
iii. モジュールの入出力のインスタンス化
iv. ラベルのインスタンス化
v. 変数のインスタンス化
vi. 命令のDFG化
b. generate()
i. スケジューリング
ii. 最適化
iii. step信号のビット幅の修正
iv. Verilog HDLの出力処理
11
高位合成友の会15/12/08
gfortranとDragonEggを用いてLLVM IRに変換
12
GFORTRAN := gfortran-4.8
DRAGONEGG := /usr/lib/gcc/x86_64-linux-gnu/4.
8/plugin/dragonegg.so
OUTPUT_LLVM := ./out.s
$(GFORTRAN) -O1 $(INPUT_FORTRAN) 
-fplugin=$(DRAGONEGG) 
-fplugin-arg-dragonegg-emit-ir -S -o $(OUTPUT_LLVM)
高位合成友の会15/12/08
出力されるLLVM IRの違い
; Function Attrs: nounwind uwtable
define void @lcm_(i32* noalias %i, i32* noalias %j, i32*
noalias %ret_lcm) unnamed_addr #0 {
entry:
%i_addr = alloca i32*, align 8
%j_addr = alloca i32*, align 8
%ret_lcm_addr = alloca i32*, align 8
%ir = alloca i32
%ir1 = alloca i32
%ir2 = alloca i32
%"alloca point" = bitcast i32 0 to i32
store i32* %i, i32** %i_addr, align 1
store i32* %j, i32** %j_addr, align 1
store i32* %ret_lcm, i32** %ret_lcm_addr, align 1
%0 = load i32** %i_addr, align 8
%1 = load i32** %j_addr, align 8
%2 = load i32** %ret_lcm_addr, align 8
%"ssa point" = bitcast i32 0 to i32
br label %"2"
13
; Function Attrs: nounwind uwtable
define void @lcm_(i32* noalias nocapture readonly %i,
i32*noalias nocapture readonly %j, i32* noalias
nocapture %ret_lcm) unnamed_addr #0 {
entry:
%0 = load i32* %i, align 4
%1 = load i32* %j, align 4
%2 = icmp slt i32 %0, %1
%. = select i1 %2, i32 %1, i32 %0
%.1 = select i1 %2, i32 %0, i32 %1
%3 = srem i32 %., %.1
%4 = icmp slt i32 %3, 1
br i1 %4, label %"8", label %"7"
13
-O0での出力 (一部) -O1での出力 (一部)
高位合成友の会15/12/08
出力されるLLVM IRの違い
; Function Attrs: nounwind uwtable
define void @lcm_(i32* noalias %i, i32* noalias %j, i32*
noalias %ret_lcm) unnamed_addr #0 {
entry:
%i_addr = alloca i32*, align 8
%j_addr = alloca i32*, align 8
%ret_lcm_addr = alloca i32*, align 8
%ir = alloca i32
%ir1 = alloca i32
%ir2 = alloca i32
%"alloca point" = bitcast i32 0 to i32
store i32* %i, i32** %i_addr, align 1
store i32* %j, i32** %j_addr, align 1
store i32* %ret_lcm, i32** %ret_lcm_addr, align 1
%0 = load i32** %i_addr, align 8
%1 = load i32** %j_addr, align 8
%2 = load i32** %ret_lcm_addr, align 8
%"ssa point" = bitcast i32 0 to i32
br label %"2"
14
; Function Attrs: nounwind uwtable
define void @lcm_(i32* noalias nocapture readonly %i,
i32*noalias nocapture readonly %j, i32* noalias
nocapture %ret_lcm) unnamed_addr #0 {
entry:
%0 = load i32* %i, align 4
%1 = load i32* %j, align 4
%2 = icmp slt i32 %0, %1
%. = select i1 %2, i32 %1, i32 %0
%.1 = select i1 %2, i32 %0, i32 %1
%3 = srem i32 %., %.1
%4 = icmp slt i32 %3, 1
br i1 %4, label %"8", label %"7"
14
-O0での出力 (一部) -O1での出力 (一部)
高位合成友の会15/12/08
FortRockの処理フロー
1. gfortranとDragonEggを用いてLLVM IRに変換
2. instnamerパスの実行
3. FortRockCoreの処理
a. runOnModule()
i. 演算器のインスタンス化
ii. グローバル変数のインスタンス化
iii. モジュールの入出力のインスタンス化
iv. ラベルのインスタンス化
v. 変数のインスタンス化
vi. 命令のDFG化
b. generate()
i. スケジューリング
ii. 最適化
iii. step信号のビット幅の修正
iv. Verilog HDLの出力処理
15
高位合成友の会15/12/08
LLVMのPass
● Pass
○ LLVMにおける処理の単位
○ LLVM IRに対して最適化処理などを行う
○ 再利用可能
● Passの種類
○ ImuutablePass, ModulePass, FunctionPass,
LoopPass, RegionPass, BasicBlockPass
● ModulePass
○ Moduleに対して実行される
○ Module: LLVM IR 全体
16
処理前 LLVM IR
処理後 LLVM IR
Pass A
Pass B
高位合成友の会15/12/08
LLVMのPass
● Pass
○ LLVMにおける処理の単位
○ LLVM IRに対して最適化処理などを行う
○ 再利用可能
● Passの種類
○ ImuutablePass, ModulePass, FunctionPass,
LoopPass, RegionPass, BasicBlockPass
● ModulePass
○ Moduleに対して実行される
○ Module: LLVM IR 全体
17
LLVM IR
Module
Global Variable
Function
BasicBlock
Instruction
高位合成友の会15/12/08
LLVMのPass
18
gfortranの出力
LLVM IR
Verilog HDL
Instnamer
FortRock
● Pass
○ LLVMにおける処理の単位
○ LLVM IRに対して最適化処理などを行う
○ 再利用可能
● Passの種類
○ ImuutablePass, ModulePass, FunctionPass,
LoopPass, RegionPass, BasicBlockPass
● ModulePass
○ Moduleに対して実行される
○ Module: LLVM IR 全体
● 既存のPassの効果
○ ループ展開によって性能向上
高位合成友の会15/12/08
FortRockの処理フロー
1. gfortranとDragonEggを用いてLLVM IRに変換
2. instnamerパスの実行
3. FortRockCoreの処理
a. runOnModule()
i. 演算器のインスタンス化
ii. グローバル変数のインスタンス化
iii. モジュールの入出力のインスタンス化
iv. ラベルのインスタンス化
v. 変数のインスタンス化
vi. 命令のDFG化
b. generate()
i. スケジューリング
ii. 最適化
iii. step信号のビット幅の修正
iv. Verilog HDLの出力処理
19
高位合成友の会15/12/08
Instnamerパスの実行
20
● Instnamer
○ Assign names to anonymous
instructions
○ LLVM IRに変数名を与える
define void @lcm_(i32* noalias nocapture
readonly %i, i32* noalias nocapture readonly %j,
i32* noalias nocapture %ret_lcm)
unnamed_addr #0 {
entry:
%tmp = load i32* %i, align 4
%tmp1 = load i32* %j, align 4
%tmp2 = icmp slt i32 %tmp, %tmp1
%. = select i1 %tmp2, i32 %tmp1, i32 %tmp
%.1 = select i1 %tmp2, i32 %tmp, i32 %tmp1
%tmp3 = srem i32 %., %.1
%tmp4 = icmp slt i32 %tmp3, 1
br i1 %tmp4, label %"8", label %"7"
20
高位合成友の会15/12/08
FortRockの処理フロー
1. gfortranとDragonEggを用いてLLVM IRに変換
2. instnamerパスの実行
3. FortRockCoreの処理
a. runOnModule()
i. 演算器のインスタンス化
ii. グローバル変数のインスタンス化
iii. モジュールの入出力のインスタンス化
iv. ラベルのインスタンス化
v. 変数のインスタンス化
vi. 命令のDFG化
b. generate()
i. スケジューリング
ii. 最適化
iii. step信号のビット幅の修正
iv. Verilog HDLの出力処理
21
高位合成友の会15/12/08
FortRockの出力規則 - SUBROUTINE
subroutine calc (A, B, C)
integer A, B, C
C = A + B
return
end
22
CALC
A
B
C
req
fin
res
clk
32
32
32
入力
SUBROUTINE
出力
モジュール
ADD
高位合成友の会15/12/08
FortRockの出力規則 - SUBROUTINE
subroutine calc (A, B, C)
integer, A, B, C
C = A + B
return
end
23
CALC
A
B
C
req
fin
res
clk
32
32
32
入力
SUBROUTINE
出力
モジュール
ADD
最後の引数を出力と定義
高位合成友の会15/12/08
FortRockの出力規則 - SUBROUTINE
subroutine calc (A, B, C)
integer, A, B, C
C = A + B
return
end
24
CALC
A
B
C
req
fin
res
clk
32
32
32
入力
SUBROUTINE
出力
モジュール
ADD
Request信号
Finish信号
Reset信号
Clock信号
高位合成友の会15/12/08
FortRockの出力規則 - SUBROUTINE
subroutine calc (A, B, C)
integer, A, B, C
C = A + B
return
end
25
CALC
A
B
C
req
fin
res
clk
32
32
32
入力
SUBROUTINE
出力
モジュール
ADD
IPコアはモジュール間で
共有されない
高位合成友の会15/12/08
出力される回路のステートマシン
26
Reset
State1
Step 1
Step 2
Finish State
fin <= 1
Request
???
???
Reset状態で待機
if res == 1
Request待機状態
1クロックで1stepの処理を実行
br命令などで別のstateに遷移
fin信号を1にして呼び出し元
に処理の終了を通知
高位合成友の会15/12/08
FortRockの実装方針
● LLVMとは粗結合にする
○ 問題の切り分け
■ LLVMかFortRockか
○ 操作できる範囲を制限
■ バグの抑制
■ 引き継ぎ,他者による開発
○ LLVMのバージョンアップの簡単化
■ 最新版はLLVM 3.8
● LLVM IR → FortRockのデータ構造
27
FortRockで扱うデータ構造
Element
Node Node
Operator
Node
高位合成友の会15/12/08
FortRockの処理フロー
1. gfortranとDragonEggを用いてLLVM IRに変換
2. instnamerパスの実行
3. FortRockCoreの処理
a. runOnModule()
i. 演算器のインスタンス化
ii. グローバル変数のインスタンス化
iii. モジュールの入出力のインスタンス化
iv. ラベルのインスタンス化
v. 変数のインスタンス化
vi. 命令のDFG化
vii. generate()
1. スケジューリング
2. 最適化
3. step信号のビット幅の修正
4. Verilog HDLの出力処理
28
高位合成友の会15/12/08
FortRockのデータ構造
● Element
○ LLVM IRの1つの命令に対応
○ Node,Operator によって構成
○ 実行されるState, Stepの情報を保持
● Node
○ 入出力,変数,定数を表す
● Operator
○ 演算器を表す
29
Element
Node Node
Operator
Node
高位合成友の会15/12/08
FortRockのデータ構造
● Element
○ LLVM IRの1つの命令に対応
○ Node,Operator によって構成
● Node
○ 入出力,変数,定数を表す
● Operator
○ 演算器を表す
A + B = C
%c = add %a, %b
30
Element
A B
add
C
高位合成友の会15/12/08
FortRockのデータ構造
● Element
○ LLVM IRの1つの命令に対応
○ Node,Operator によって構成
● Node
○ 入出力,変数を表す
● Operator
○ 演算器を表す
※ ElementはNodeを継承
31
Element
Element Node
Operator
Node
高位合成友の会15/12/08
FortRockの処理フロー
1. gfortranとDragonEggを用いてLLVM IRに変換
2. instnamerパスの実行
3. FortRockCoreの処理
a. runOnModule()
i. 演算器のインスタンス化
ii. グローバル変数のインスタンス化
iii. モジュールの入出力のインスタンス化
iv. ラベルのインスタンス化
v. 変数のインスタンス化
vi. 命令のDFG化
vii. generate()
1. スケジューリング
2. 最適化
3. step信号のビット幅の修正
4. Verilog HDLの出力処理
32
高位合成友の会15/12/08
演算器のインスタンス化
xmlの設定ファイルを入力
● use_ip_core
○ IPコアを使用するか
● latency
○ IPコアのレイテンシ
● module_name
○ IPコアの名前
● instance_name
○ インスタンス名
● num_module
○ IPコアのインスタンスの数
33
● io : 入出力ポートの情報
○ port_name : ポート名
○ bit_width : ポートのビット幅
○ type : ポートの種類
■ input
■ output
■ clock
■ clock_enable
高位合成友の会15/12/08
FortRockの処理フロー
1. gfortranとDragonEggを用いてLLVM IRに変換
2. instnamerパスの実行
3. FortRockCoreの処理
a. runOnModule()
i. 演算器のインスタンス化
ii. グローバル変数のインスタンス化
iii. モジュールの入出力のインスタンス化
iv. ラベルのインスタンス化
v. 変数のインスタンス化
vi. 命令のDFG化
vii. generate()
1. スケジューリング
2. 最適化
3. step信号のビット幅の修正
4. Verilog HDLの出力処理
34
高位合成友の会15/12/08
各種インスタンス化
● インスタンス化
○ FortRockのデータ構造で実態を定義
● グローバル変数
○ 主に配列
● モジュールの入出力
○ Nodeとして定義
● ラベル
○ ステートマシンのStateに対応する定数
● 変数
○ Nodeとして定義
35
高位合成友の会15/12/08
FortRockの処理フロー
1. gfortranとDragonEggを用いてLLVM IRに変換
2. instnamerパスの実行
3. FortRockCoreの処理
a. runOnModule()
i. 演算器のインスタンス化
ii. グローバル変数のインスタンス化
iii. モジュールの入出力のインスタンス化
iv. ラベルのインスタンス化
v. 変数のインスタンス化
vi. 命令のDFG化
vii. generate()
1. スケジューリング
2. 最適化
3. step信号のビット幅の修正
4. Verilog HDLの出力処理
36
高位合成友の会15/12/08
命令のDFG化
37
Element
Node Node
Operator
Node
Element
Node Node
Operator
Node
latency
latency
???
● 命令列をElementに変換
● 演算器latencyにより実行タイミング
を指定
● 各BasicBlockに対して実行
高位合成友の会15/12/08
FortRockの処理フロー
1. gfortranとDragonEggを用いてLLVM IRに変換
2. instnamerパスの実行
3. FortRockCoreの処理
a. runOnModule()
i. 演算器のインスタンス化
ii. グローバル変数のインスタンス化
iii. モジュールの入出力のインスタンス化
iv. ラベルのインスタンス化
v. 変数のインスタンス化
vi. 命令のDFG化
vii. generate()
1. スケジューリング
2. 最適化
3. step信号のビット幅の修正
4. Verilog HDLの出力処理
38
高位合成友の会15/12/08
スケジューリング
● 同時に実行可能な命令を重ねる
○ Elementの入力が使用可能となるStep
○ ElementのOperatorが使用可能となるStep
○ Elementがメモリアクセスの場合
■ アクセス対象のポートが利用可能なStep
● ポートは複数
39
Element
Node Node
Operator
Node
Element
Node Node
Operator
Node
高位合成友の会15/12/08
FortRockの処理フロー
1. gfortranとDragonEggを用いてLLVM IRに変換
2. instnamerパスの実行
3. FortRockCoreの処理
a. runOnModule()
i. 演算器のインスタンス化
ii. グローバル変数のインスタンス化
iii. モジュールの入出力のインスタンス化
iv. ラベルのインスタンス化
v. 変数のインスタンス化
vi. 命令のDFG化
vii. generate()
1. スケジューリング
2. 最適化
3. step信号のビット幅の修正
4. Verilog HDLの出力処理
40
高位合成友の会15/12/08
最適化
● Elementの入力をElementの出力で置換
○ Elementの出力を一度レジスタに保存
→ ElementのOperatorの出力を
Elementの入力とする
● 効果
○ レジスタ使用数が削減
○ 処理サイクル数が削減
※ この為にElementはNodeを継承する
41
Element
Node
Operator
Node
Node Node
Operator
高位合成友の会15/12/08
FortRockの処理フロー
1. gfortranとDragonEggを用いてLLVM IRに変換
2. instnamerパスの実行
3. FortRockCoreの処理
a. runOnModule()
i. 演算器のインスタンス化
ii. グローバル変数のインスタンス化
iii. モジュールの入出力のインスタンス化
iv. ラベルのインスタンス化
v. 変数のインスタンス化
vi. 命令のDFG化
vii. generate()
1. スケジューリング
2. 最適化
3. step信号のビット幅の修正
4. Verilog HDLの出力処理
42
高位合成友の会15/12/08
Phi命令の出力
Phi命令
遷移元によって返り値が変化する
例
%c = phi [0, %entry], [%tmp1, %3]
FortRockではVerilogのfunction文で
出力
43
wire [63:0] w_phi_r_c;
assign w_phi_r_c =
phi_r_c(r_sys_prev_state, pb_ZERO, r_tmp1);
function [63:0] phi_r_c;
input [2:0] r_sys_prev_state;
input [63:0] pb_ZERO;
input [63:0] r_tmp1;
case (r_sys_prev_state)
entry: phi_r_c = pb_ZERO;
l_tmp3: phi_r_c = r_tmp1;
endcase
endfunction
43
高位合成友の会15/12/08
現状
● 現状
○ FortranからVerilog HDLへの変
換
■ 一部命令は未対応
○ IPコアを用いた演算
○ 浮動小数点演算
■ 剰余演算は未対応
○ 命令の並列実行
■ 基本ブロック内に限定
44
高位合成友の会15/12/08
今後の展望
● FortRockで数値流体力学計算のプログラムを回路化
○ 必要となる未実装な命令の実装
● 配列のマルチポート対応
○ 主にスケジューリング
○ 現状では1ポート
● DRAM対応
45

More Related Content

高位合成友の会蔼ドワンゴ,2015年12月8日