JavaRockではじめる
高位合成言語による気楽なFPGA開発

三好 健文
株式会社イーツリーズ・ジャパン

1

ESS2013 2013.10.16

(JavaRockではじめる)
高位合成言語による気楽なFPGA開発

三好 健文
株式会社イーツリーズ・ジャパン

2

ESS2013 2013.10.16

今日の流れFPGAと高位合成処理系について
FPGAとは高位合成の例
JavaRockの実装と設計
デモ!!

3

ESS2013 2013.10.16

新世代のESL合成ソリューション
FPGAとはBluespec System Verilogのすすめ
Field Programmable Gate Array
本章では，高位設計言語である Bluespec System Verilog を紹介する．この言語では，コンパイル時にしっかりエラー検出ができ，また，さまざまなライブ
ラリも提供している．FPGA や ASIC が大規模化し複雑な回路を設計する機会が増えてきた今，知っておくべき技術だろう．
（編集部）

論理回路・データパスを自由に作り込める
クロックレベルの同期と並列性の活用
Verilog HDL や VHDL を使った設計で，

三好 健文

HDL がドレスを着たお姫さまだとすると，コンパイル時― あぁ〜，数字って 32 ビットだった．うっかりキャスト
されていたよ…

にエラーをしっかり検出してくれるが故にコンパイルを通すのが困難な反面，コンパイルさえ通れば合成した回路が― テスト・ベンチのステート・マシンを書くのが面倒だな．

きちんと動作してくれる Bluespec はパワフルなツンデレ― モジュールのインスタンシーエーションで入出力ピン

娘と筆者はイメージしています（図 2）．

をつなぎ忘れていたという思いをしたことはありませんか？
単純な記述の羅列や細かいミスへの注力が続くと，本来力を入れるべき，アーキテクチャの設計まで億劫になってしまいます．また，「コンパイル（論理合成）は通るのに，
シミュレーションや FPGA 上で動作させると，何かおかしい」という事態に頭を悩ませ，原因はうっかりミスだったということも一度や二度ではないと思います．
記述の手間がもっと省けて，コンパイル時に強力にエラー・チェックしてくれる HDL 言語ないかなあ…という
要 求 に 応 え て く れ る の が Bluespec System Verilog で す（図 1）．VHDL がまじめなキャリア・ウーマン，Verilog

4

出典: CQ出版▲ 図 2 Interface
Bluespec 2011年2月号よりSystem Verilog は ツ
ンデレ娘

ESS2013 2013.10.16

きっちりしていてキャリアも長い VHDL，あいまFPGAの活用シーン
独自の回路を実現できるハードウェア
特定の処理を低消費電力で高性能処理
デバイスに近い処理を簡単に実現
自由なI/Oポートの定義

ASIC開発のプロトタイプとして
特定用途向け少数生産の製品として
5

ESS2013 2013.10.16

FPGAの応用事例

1)

DB，金融，油田探索
2)1) http://www.thenewstribe.com/2012/11/01/infotech-becomes-pakistans-first-netezza-certified-ibm-partner/2) http://techon.nikkeibp.co.jp/article/NEWS/20110502/191552/

6

ESS2013 2013.10.16

例) freeocean
ハードウェアWebキャッシュサーバ: freeocean
2006年に販売開始
最大スループット: 1Gbps
最大同時処理コネクション数: 50万
秒間同時接続数: 約2万HTTPリクエスト
最大消費電力: 約160W

7

ESS2013 2013.10.16

演算リソースとしてのFPGAの魅力
数値計算性能内蔵DSPを活用して...
http://www.altera.com/literature/wp/wp-01142-teraflops.pdf< 1.25 TFLOPS, 10〜12GFLOPS/W
CPUと比べて高い処理能力
Smith-Waterman 法による多重配列アライメン ト処理とモンテカルロ法
ベースの金融シミュレーショ ンを FPGA で実行した場合,それぞれ CPUに比べ て 228 倍と 545 倍高速に処理できた[ 1 ] Reconfigurable Computing in the Multi-Core Era.
In Internal Workshop on Highly-Efficient Accelerators
and Reconfigurable Technologies, 2010.
8

ESS2013 2013.10.16

FPGAアプリケーションの研究事例@FPGA2013, FPL2013, FCCM2013
A Fully Pipelined FPGA Architecture for Stochastic Simulation of Chemical
Systems
A Hardware Accelerated Approach for Imaging Flow Cytometry
Accelerating Solvers for Global Atmospheric Equations though Mixed-Precision
Data Flow Engine
An FPGA Based Parallel Architecture For Music Melody Matching
An FPGA Memcached ApplianceHigh Throughput and Programmable Online Traﬃc Classiﬁer on FPGA
Join Operation for Relational Databases

30+

A Packet Classiﬁer using LUT cascades Based on EVMDDs(k)Memory Eﬃcient IP Lookup in 100Gbps Networks
A Flexible Hash Table Design for 10GBps Key-Value Stores in FPGAs
A Secure Copreocessor for Database Applications

Fast, FPGA-based Rainbow Table Creation for Attacking Encrypted Mobile
Communications

9

.....

ESS2013 2013.10.16

FPGA上のプログラミングとは論理回路構成要素の演算内容を決める
論理回路構成要素同士をどう接続するかを決める

cf. http://commons.wikimedia.org/wiki/File:Two_women_operating_ENIAC_(full_resolution).jpg

10

ESS2013 2013.10.16

FPGA上のプログラミングとは

1)

3)
2)
1) http://japan.xilinx.com/support/documentation/data_sheets/ds180_7Series_Overview.pdf2) http://hitechglobal.com/boards/virtex7_v2000t.htm3) http://http://low-powerdesign.com/sleibson/2011/10/25/generation-jumping-2-5d-xilinxvirtex-7-2000t-fpga-delivers-1954560-logic-cells-consumes-only-20w/

11

ESS2013 2013.10.16

FPGAの開発手法の主役
HDL(Hardware Description Language)
によるRTL(Register Transfer Level)設計
a
b

+

f
g

>

x
y

+1

h

counterclk
12

ESS2013 2013.10.16

HDLによる設計のメリット/デメリット
メリット
ロジックを抽象化した式/構文で設計できる
クロックレベルのデータ制御
細粒度の並列性の活用

デメリット“状態”を自分で管理しなければいけない
デバッグ/動作検証が難しい
アルゴリズムを設計するには記述が煩雑
13

ESS2013 2013.10.16

HDLによる設計のデメリットを克服する方法
FPGAを使うのをやめる
FPGAとは別にプロセッサを持ってくる
FPGAの中にプロセッサを作る

高位合成言語/処理系の活用
より抽象度の高い設計をする

14

ESS2013 2013.10.16

HDLによる設計のデメリットを克服する方法
FPGAを使うのをやめる
FPGAとは別にプロセッサを持ってくる
大
増
の
ト
ス
コ
守
保
ス
FPGAの中にプロセッサを作る
ー
ソ
/
境
環

高位合成言語/処理系の活用
より抽象度の高い設計をする

15

ESS2013 2013.10.16

HDLによる設計のデメリットを克服する方法
FPGAを使うのをやめる
FPGAとは別にプロセッサを持ってくる
FPGAの中にプロセッサを作る

高位合成言語/処理系の活用
より抽象度の高い設計をする

16

ESS2013 2013.10.16高位合成言語/処理系に何を求めるか
記述コストの軽減
高い抽象度の表現方法を利用したい
言語習得のコストは低く抑えたい

動作検証/デバッグコストの軽減
短時間で動作を確認したい
見通しよく手軽なデバッグをしたい

FPGAのパフォーマンスの活用
粗粒度，細粒度の並列性を活用したい
IPコア，FPGA内蔵機能を活用したい
17

ESS2013 2013.10.16

沢山の高位合成言語/処理系
ベース

言語名

C

ImpulseC, SpecC, GorillaC, AutoESL, CWBなど沢山

C++

SystemC, OCAPI, HP-MachineJava

JHDL, Lime, MaxCompiler, Sea Cucumber, JavaRock

C#

Kiwi

PythonPHDL, MyHDL

Ruby

RHDL

ML

CPAH

Fortran

DeepC Compiler, ROCCC, SRC-6

HaksellLava, Bluespec System Verilog

Matlab

MATCH, DEFACTO Compiler

18

ESS2013 2013.10.16高位合成処理系市場の推移

AutoESL，OpenCL，ImupluseC，CWB...などなどなど
19

ESS2013 2013.10.16高位合成言語の例
Vivado ESL (AutoESL)
ImpulseC
Bluespec System Verilog

20

ESS2013 2013.10.16

Vivado ESL (AutoESL)
C，C++，SystemCをサポート
アルゴリズム合成
インターフェイス合成(グローバル変数，関数の引数，戻り値)最適化
制御およびデータパスの抽出
スケジューリングおよびバインディング
任意精度データ型
並列化

21

ESS2013 2013.10.16

Vivado HLSでソート
int main() {!
int tmp;!
int max_i = SIZE - 1;!
int a, b;!
int i, j;!
for (i = 0; i <= max_i - 1; i++) {!
!
int max_j = SIZE - 1 - i;!
!
for (j = 1; j <= max_j; j++) {!
!
!
a = ar[j];!
!
!
b = ar[j - 1];!
!
!
if (a < b) {!
!
!
!
ar[j - 1] = a;!
!
!
!
ar[j] = b;
!
!
!
}
!
!
}
!
}
!
return 0;}

22

ESS2013 2013.10.16

Vivado HLSでソート

23

ESS2013 2013.10.16

Vivado HLSでソート
library IEEE;
use IEEE.std_logic_1164.all;use IEEE.numeric_std.all;entity main isport (
ap_clk : IN STD_LOGIC;
ap_rst : IN STD_LOGIC;
ap_start : IN STD_LOGIC;
ap_done : OUT STD_LOGIC;
ap_idle : OUT STD_LOGIC;
ap_ready : OUT STD_LOGIC;
ar_address0 : OUT STD_LOGIC_VECTOR (8 downto 0);
ar_ce0 : OUT STD_LOGIC;
ar_we0 : OUT STD_LOGIC;
ar_d0 : OUT STD_LOGIC_VECTOR (31 downto 0);
ar_q0 : IN STD_LOGIC_VECTOR (31 downto 0);
ar_address1 : OUT STD_LOGIC_VECTOR (8 downto 0);
ar_ce1 : OUT STD_LOGIC;
ar_we1 : OUT STD_LOGIC;
ar_d1 : OUT STD_LOGIC_VECTOR (31 downto 0);
ar_q1 : IN STD_LOGIC_VECTOR (31 downto 0) );end;

ポインタ渡しはデュアルポートRAMになるみたい

architecture behav of main is-- snip -begin

クロックに同期して値をレジスタに保存-- snip ---- ap_reg assign process. -ap_reg_proc : process(ap_clk)
begin
if (ap_clk'event and ap_clk = '1') thenif (((ap_ST_st3_fsm_2 = ap_CS_fsm) and (ap_const_lv1_0 = tmp_fu_96_p2))) thenar_addr_1_reg_145 <= tmp_3_fu_106_p1(9 - 1 downto 0);
end if;if (((ap_ST_st3_fsm_2 = ap_CS_fsm) and (ap_const_lv1_0 = tmp_fu_96_p2))) thenar_addr_reg_139 <= tmp_2_fu_101_p1(9 - 1 downto 0);
end if;if ((ap_ST_st2_fsm_1 = ap_CS_fsm)) theni_1_reg_120 <= i_1_fu_74_p2;
end if;-- snip -end if;
end process;max_j_cast2_reg_125(31 downto 9) <= "00000000000000000000000";

24

ESS2013 2013.10.16

Vivado HLSでソート-- the next state (ap_NS_fsm) of the state machine. -ap_NS_fsm_assign_proc : process (ap_start , ap_CS_fsm , exitcond1_fu_68_p2 , tmp_fu_96_p2)
begincase ap_CS_fsm iswhen ap_ST_st1_fsm_0 =>if (not((ap_start = ap_const_logic_0))) thenap_NS_fsm <= ap_ST_st2_fsm_1;
else
ap_NS_fsm <= ap_ST_st1_fsm_0;
end if;when ap_ST_st2_fsm_1 =>if (not((exitcond1_fu_68_p2 = ap_const_lv1_0))) thenap_NS_fsm <= ap_ST_st1_fsm_0;
else
ap_NS_fsm <= ap_ST_st3_fsm_2;
end if;-- snip -end case;end process;ステートマシン-- snip -exitcond1_fu_68_p2 <= "1" when (i_reg_43 = ap_const_lv9_1FF) else "0";i_1_fu_74_p2 <= std_logic_vector(unsigned(i_reg_43) + unsigned(ap_const_lv9_1));
j_fu_90_p2 <= std_logic_vector(unsigned(indvar_reg_54) + unsigned(ap_const_lv32_1));
max_j_cast2_fu_86_p1 <= std_logic_vector(resize(unsigned(max_j_fu_80_p2),32));
max_j_fu_80_p2 <= (i_reg_43 xor ap_const_lv9_1FF);
tmp_2_fu_101_p1 <= std_logic_vector(resize(signed(j_fu_90_p2),64));
tmp_3_fu_106_p1 <= std_logic_vector(resize(signed(indvar_reg_54),64));
tmp_4_fu_111_p2 <= "1" when (signed(ar_q0) < signed(ar_q1)) else "0";tmp_fu_96_p2 <= "1" when (signed(j_fu_90_p2) > signed(max_j_cast2_reg_125)) else "0";-- snip --25

計算は組み合わせ回路でESS2013 2013.10.16

ImpulseC
ANSI-Cが入力
Stream-Cの商用化

各プロセスはANSI-設計

H/W process

S/W process

H/W process

プロセスレベル並列化



データストリームはFIFO

CSPベースの並列動作モデル

S/W process

H/W process

hw/sw

pragmaによる合成制約(Pipeline，Unroll，StageDelayなど)

c.f. iLink アイリンク合同会社, “ANSI-C記述でhwモジュール生成

26＋ CPUコアとのhw/sw協調設計 CoDeveloper doc_Ver3.6”

ESS2013 2013.10.16

ImpulseCでソート// Read values from the stream
i = 0;
while ( co_stream_read(sortinput, &nSample, sizeof(co_int32)) == co_err_none ) {#pragma CO PIPELINE	

IF_SIM(samplesread++;)	ar[i++] = nSample;}// Sort Body
for (i = 0; i <= max_i - 1; i++) {	

max_j = SIZE - 1 - i;	for (j = 1; j <= max_j; j++) {		

a = ar[j];		b = ar[j - 1];		

if (a < b) {			ar[j - 1] = a;			ar[j] = b;
	

	

}
	

}
}
// Write values to the stream
for(i = 0; i < SIZE; i++){	

co_stream_write(sortoutput, &(ar[i]), sizeof(co_int32));
	

IF_SIM(sampleswritten++;)}27

ESS2013 2013.10.16

ImpulseCでソート

28

ESS2013 2013.10.16

ImpulseCでソート
library impulse;
use impulse.components.all;entity sortproc is
port (signal reset : in std_ulogic;
signal sclk : in std_ulogic;
signal clk : in std_ulogic;
signal p_sortinput_rdy : in std_ulogic;
signal p_sortinput_en : inout std_ulogic;
signal p_sortinput_eos : in std_ulogic;
signal p_sortinput_data : in std_ulogic_vector (31 downto 0);
signal p_sortoutput_rdy : in std_ulogic;
signal p_sortoutput_en : inout std_ulogic;
signal p_sortoutput_eos : out std_ulogic;
signal p_sortoutput_data : out std_ulogic_vector (31 downto 0));end sortproc;

入出力はストリーム(FIFO)

process (r_suif_tmp3,ni207_suif_tmp0,ni213_suif_tmp2,ni210_suif_tmp1,thisState)
begincase thisState iswhen init =>nextState <= b0s0;
when b0s0 =>nextState <= b1s0;
when b1s0 =>nextState <= b2s0;
when b2s0 =>nextState <= b3s0;
when b3s0 =>nextState <= b4s0;
when b4s0 =>nextState <= b5s0;
when b5s0 =>if ((not ni210_suif_tmp1(0)) = '1') thennextState <= b8s0;
else
nextState <= b5s1;
end if;when b5s1 =>nextState <= b5s2;
when b5s2 =>nextState <= b5s3;
when b5s3 =>if (ni213_suif_tmp2(0) = '1') thennextState <= b6s0;
elsif ((not ni213_suif_tmp2(0)) = '1') thennextState <= b7s0;
else
nextState <= b5s3;
end if;

状態遷移

29

ESS2013 2013.10.16

Vivado HLSでソート
s_b2_stall <= '0' when (s_b2_vstall and s_b2_stage) = "000" else '1';s_b2_vwrite(0) <= s_b2_stage(0) when s_b2_stall = '0' and s_b2_final = '0' else '0';s_b2_vwrite(1) <= s_b2_stage(1) when s_b2_stall = '0' and s_b2_final = '0' else '0';s_b2_vwrite(2) <= s_b2_stage(2) when s_b2_stall = '0' else '0';s_b2_vcont(0) <= (s_b2_stage(0) and not s_b2_vbreak(0)) and not s_b2_final;
s_b2_vcont(1) <= s_b2_stage(1) and not s_b2_final;
s_b2_vcont(2) <= '0';s_b2_final <= '0';s_b2_flushing <= '1' when s_b2_state = flush else s_b2_final;
s_b2_flushed <='1' when s_b2_stall = '0' and (s_b2_vflush or s_b2_stage) = "000" else
'1' when s_b2_vflush(2) = '1' else'0';with s_b2_state selects_b2_done <='0' when init,'0' when run,s_b2_flushed when flush,'0' when others;-- b3s0ni206_i <= X"00000000";

いろいろな計算式-- b4s0
ni208_max_j <= sub(X"000001ff", r_i);
ni209_j <= X"00000001";-- b5s0ni210_suif_tmp1 <= "0000000000000000000000000000000" & cmp_less_equal_s(r_j, r_max_j);

process (clk)begin
if (clk'event and clk='1') thencase thisState iswhen b1s0 =>r_i <= ni201_i;
when b2s0 =>if (s_b2_vwrite(1) = '1') thenr_i <= ni205_i;
end if;when b3s0 =>r_i <= ni206_i;
when b8s0 =>r_i <= ni215_i;
when b9s0 =>r_i <= ni216_i;
when b10s0 =>r_i <= ni219_i;
when others =>end case;end if;end process;process (clk)begin
if (clk'event and clk='1') thencase thisState iswhen b4s0 =>r_max_j <= ni208_max_j;
when others =>end case;end if;end process;

クロックに合わせて状態に合わせてレジスタにセット30

ESS2013 2013.10.16

Bluespec System Verilog
Verilogに似た構文/中身はHaskellぽい強い型付け言語
RTL合成も検証も一貫した記述

型によるコンパイル時チェック
副作用の明示的な記述

多数のライブラリ
有限ステートマシン
サーバレスポンス/リクエスト
31

ESS2013 2013.10.16

BSVのコード例
module mkTest(Test_ifc);
Reg#(Bit#(26)) counter <- mkReg(0);rule r0;
counter <= counter + 1;
endrulemethod Bit#(26) result();
return readReg(counter);module mkTest(CLK, RST_N, result, RDY_result);
endmethod
input CLK;
endmodule
input RST_N;/* snip */// register counter
assign counter$D_IN = counter + 26'd1 ;assign counter$EN = 1'd1 ;/* snip */always@(posedge CLK)
begin
if (!RST_N)
begin
counter <= `BSV_ASSIGNMENT_DELAY 26'd0;
end
else
begin
if (counter$EN) counter <= `BSV_ASSIGNMENT_DELAY counter$D_IN;
end
end/* snip */endmodule // mkTest

32

ESS2013 2013.10.16

BSVでソート
import Vector::*;import DReg::*;interface BubSort_ifc#(type size_t);
method Action start(Vector #(size_t, int) a);
method Vector#(size_t, int) result();
endinterface
module mkBubSort(BubSort_ifc#(size_t));
Vector#(size_t, Reg#(int)) x <- replicateM(mkReg(0));
Reg#(Bool) init <- mkReg(True);
rule print_version(init);
action!
$display("Bubble Sort");!
init <= False;
endaction
endrulefunction Bool sorted();Bool flag = True;for(Integer i = 0; i < valueOf(size_t) - 1; i = i + 1) begin!
if(!(x[i] <= x[i+1])) flag = flag && False;
end
return flag;
endfunction
for(Integer i = 0; i < valueof(size_t) - 1; i = i + 1) begin
rule swap((x[i] > x[i+1]));!
x[i] <= x[i + 1];!
x[i+1] <= x[i];endruleend
method Action start(Vector#(size_t, int) a);writeVReg(x, a);endmethod
method Vector#(size_t, int) result() if(sorted());
return readVReg(x);endmethod
endmodule

33

ESS2013 2013.10.16

BSVでソート

34

ESS2013 2013.10.16

http://javarock.sourceforge.net/

JavaRockとは

http://javarock.sourceforge.net/

JavaRockの目指すところ
JavaプログラムをそのままHDLに変換→FPGA上のHWにする
追加構文，データ型は導入しない
記述に制限は加える“HDLで書けることをJavaで書けるようにする”ではない“Javaで書けることを全部HDLにする”ではない.java%
Java  %



JVM%

Java  % 

JavaRock%  

.vhdl%

/

36

第391回 PTT 2013. 6. 28

高位合成処理系 入力言語として見たJava
クラスによるオブジェクト指向設計←HWのモジュール設計との親和性が高そう
Threadやwait-notify，synchronizedの仕組み←言語仕様内で並列性の記述ができそう
明示的なポインタを扱う必要がない←言語の想定するメモリ構造から自由になれそう

コンパイラでがんばれるか？
動的な振る舞いがたくさんある←HW化するのは厄介そう
37

ESS2013 2013.10.16

JavaRockの設計方針
JavaプログラムをそのままHW化する
追加構文，データ型は導入しない
記述に制限は加える
プログラムカウンタをステートマシンに置換
まずは，１文１ステート
forやwhileに合わせたステートマシン生成
メソッド呼び出し相当のHDLコード生成

38

ESS2013 2013.10.16

JavaRockの設計方針“HDLで書けることをJavaで書けるようにする”ではない“Javaで書けることを全部HDLにする”ではない

Java(のサブセット）を実行可能なHDLコード規約
あるいはフェッチのないJavaプロセッサの生成

39

ESS2013 2013.10.16

コードの例40

ESS2013 2013.10.16

コンパイルフロー
.java
.java

Java
Flontend
Java Compiler
Compiler Frontend

Java
BackendJava Compiler
Compiler Backend

.vhd
.vhdl

.class.classSynthesis/Place& RouteSynthesis + Place&Route41

ESS2013 2013.10.16

JVM

FPGA

ソフトウェアとハードウェアで同じ動作

15 connect6 のデバッグで用いたクラスのクラス図

vgaの Javaの活用手法の検討
SwingFrame
VGAJavaTest

図 17
vga
VGAIf

SwingCanvas

9

VGA グラフィクス描画ハードウェアをソフトウェアでデバッグ

monitor
VGAWrapper

HDL modules

Executable as Software

Implement-able onto FPGA

JVM

FPGA

グラフィクス描画ハードウェア設計のためのクラス構造

FTPPlayer.java として Java で実装する．

15 に ，Java で 実 装 し た connect6 を デ バッ

る 際 に 利 用 し た ク ラ ス 群 の ク ラ ス 図 を 示 す．

Player と Calculator からなる ICFPT で提図 18

図 17connect6
VGA グラフィクス描画ハードウェアをソフトウェアでデれたプレイヤは，他の幾つかのプレーバッグ

VGA グラフィクス描画ハードウェア

装と共に Player インターフェイスを実装するク作成した描画対象である SwingFrame をインスタンシ

である．このクラスのインスタンスは，Game とエーションすることで図 17 に示すようにソフトウェ

42

ESS2013 2013.10.16

どうやってJavaをHDLにするかソースコードレベルでHDLに変換
.java
.java

Java
Flontend
Java Compiler
Compiler Frontend

Java
BackendJava Compiler
Compiler Backend

.vhd
.vhdl

.class.classSynthesis/Place& RouteSynthesis + Place&Route44

ESS2013 2013.10.16

Javaのソースコード解析
OpenJDK(http://openjdk.java.net)のjavacを活用
コンパイラ本体: com.sun.tools.javac.main.JavaCompiler.java

コンパイル処理の途中にフックを追加
genCode(Env<AttrContext> env, JCClassDecl cdef) 〜与えられたソースコードをJavaRockツリーに変換
compile(List<JavaFileObject> sourceFileObjects,
List<String> classnames,
Iterable<? extends Processor> processors)〜

クラス間の関係の解析，モジュールの結合を決定
最適化
コード生成
45

ESS2013 2013.10.16

width変数のビット幅を指定する

Java構文木をHDL構文木に変換
classvar decl
method decl
var decl
block
expr statement
var decl
block
while
for
if
報処理学会論文誌
continueblock
return

ンを

変換する
る

expr
ident
binary expr
unary expr
method invocation
May 2007
assignexpr
parensarray accessentity図 3 Java の構文木の一部
architecture
signal decl
process

1: publ2: pub
3:
i
4:
f
5:
6:
}
7:
r
8: }
9: }

図

のモジュールにアクセスするJava プログラムをコン
state machine

expr
expr statement
パイルできるように，
JRHIとして，そのHDL ライ
statemachineident
while
binary expr
forunary expr
ブラリの入出力ポートを変数として持つラッパークラ
ifmethod invocation
continue
expr
parensreturnスを Java で記述する．
HDL
で処理されたモジュール
array accessassignblockを利用するクラスは，このラッパークラスに宣言され
図4

JavaRock で扱う46VHDL の構文木 (抜粋)

Java

定義さ

と類似

くは直

ESS2013 2013.10.16

図 4 JavaRock で扱う VHDL の構文木 (抜粋)

生成する基本モジュール

ation

r

ン

イ

ラ

ル

れ

1: public class sum{
2: public int sum(int[] a){3:
int sum = 0;4:for(int i = 0; i < a.length; i++){5:sum += a[i];6:}7:return sum;
8: }
9: }

Vol.
48
No.
5
FPGA
向け高位合成言語としての
図 5 与えられた配列の合計値を求める Java のプログラム
sum: entity

1
notify_method_busy
2
3
4
sum_method_busy
5
output_port_sum[31:0]
6
7
8
9
10
11
12
13
ESS2013 2013.10.16

Javanotify_method_requestのクラスを VHDL エンティティに，クラス内で
sum: process

定義されたメソッドはそのエンティティのプロセスに，

sum_method_request
input_port_sum_a_length
input_port_sum_a_we[0:0]
input_port_sum_a_wdata[31:0]
input_port_sum_a_waddr[31:0]
resetと類似する要素に変換できるが，Java の制御構文の多くは直接 VHDL に変換することはできない．そのたり，め Java のプログラムと同様のデータ処理を実現する

ラ

ためのハードウェアアーキテクチャを作る必要がある．
47clkコード生成規約: 基本的なストラテジ
Javaの1文を1ステートとするステートマシン
ブロック文はさらにステートマシンを分割
if，while，for，{}
配列アクセスはBRAMアクセスに分解

48

ESS2013 2013.10.16

sum: entity
notify_method_request

sum: process
sum_method_request
1: public class sum{
input_port_sum_a_length
2: public int sum(int[] a){
input_port_sum_a_we[0:0]3:
int sum = 0;
input_port_sum_a_wdata[31:0]
4:
for(int i = 0; i < a.length; i++){ation
5:
sum += a[i];input_port_sum_a_waddr[31:0]
6:
}
reset
r

ン

イ

notify_method_busy
sum_method_busy
output_port_sum[31:0]

7:
return sum;
8: }
9: }

clk

図6

図 5 与えられた配列の合計値を求める Java のプログラム

図 5 から生成されるハードウェアアーキテクチャの外観

Java のクラスを VHDL エンティティに，クラス内でステート変数

conv_integer(sum_method_state) is
ラ 1: case定義されたメソッドはそのエンティティのプロセスに，

2:
ル 3:
4:
れ 5:
6:
7:
り，

...
when
2 =>
と類似する要素に変換できるが，Java の制御構文の多sum_0 <= conv_std_logic_vector(0, 31-0+1);
sum_method_state<= sum_method_state+ 1;
くは直接 VHDLに変換することはできない．そのた
when 3 =>上記のJavaコードに相当するステート...
め Java のプログラムと同様のデータ処理を実現する

ラ

ためのハードウェアアーキテクチャを作る必要がある．
図7

文のステートマシンへの変換例

ationr

ン

1: public class sum{
2: public int sum(int[] a){3:
int sum = 0;4:for(int i = 0; i < a.length; i++){5:sum += a[i];6:}7:return sum;
8: }
9: }

図 5 与えられた配列の合計値を求める Java のプログラム

イ

Java のクラスを
VHDL エンティティに，クラス内で長くなるので次のスライドへラ

定義されたメソッドはそのエンティティのプロセスに，

ルと類似する要素に変換できるが，Java の制御構文の多れ

くは直接 VHDL に変換することはできない．そのたり，め Java のプログラムと同様のデータ処理を実現する

ラ

ためのハードウェアアーキテクチャを作る必要がある．

intJavasum の活用手法の検討
= 0;
ての

5:
sum += a[i];assignfor(inti = 0; i < a.length; 6:i++){ }
parensexpr
sum += a[i];7:return sum;array
access}1: case conv_integer(sum_method_state) is8: }ステート変数
2: ...
return9: }3:
when sum;
3 =>

4:
}
部

5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:

5

このforループのステート変数
case conv_integer(state_counter_sum_1) iswhen 0 =>i_1 <= conv_std_logic_vector(0, 31-0+1);
state_counter_sum_1 <= state_counter_sum_1 + 1;
when 1 =>if (conv_integer(i_1) < input_port_sum_a_length) thenstate_counter_sum_1 <= state_counter_sum_1 + 1;
else
sum_method_state <= sum_method_state + 1;
state_counter_sum_1 <= (others => ’0’);
end if;when 2 =>
cond式
init式
...
when 3 =>i_1 <= conv_std_logic_vector(conv_integer(i_1 + 1), 31-0+1);
state_counter_sum_1 <= conv_std_logic_vector(1, 32);
when others => state_counter_sum_1 <= (others => ’0’);
end case;
update式
when 4 =>...

図 5 与えられた配列

図 5 与えられた配列の合計値を求める Java のプ
ログラムをコン，その HDL ライ
Java のクラスを VH
va のクラスを VHDL定義されたメソッド
エンティティに，ク持つラッパークラ

義されたメソッドはそのエンティティのプされたモジュール
と類似する要素に変類似する要素に変換できるが，の制御クラスに宣言され
くは直接Java
VHDLにationr

ン

1: public class sum{
2: public int sum(int[] a){3:
int sum = 0;4:for(int i = 0; i < a.length; i++){5:sum += a[i];6:}7:return sum;
8: }
9: }

図 5 与えられた配列の合計値を求める Java のプログラム

イ

Java のクラスを
VHDL エンティティに，クラス内でこれも，長くなるので次のスライドへラ

定義されたメソッドはそのエンティティのプロセスに，

ルと類似する要素に変換できるが，Java の制御構文の多れ

くは直接 VHDL に変換することはできない．そのたり，め Java のプログラムと同様のデータ処理を実現する

ラ

ためのハードウェアアーキテクチャを作る必要がある．

for(int i = 0; i < a.length; i++){sum += a[i];メモリアクセスのステート変数} 1: when 2 =>2:case conv_integer(state_counter_sum_2) is
読むアドレスを指定
returnsum;
3:when 0 =>4:
5:
6:

case conv_integer(array_index_operation_state_counter_3) iswhen 0 =>param_input_port_sum_a_raddr <=conv_std_logic_vector(conv_integer(i_1), 11-1-0+1);
7:array_index_operation_state_counter_3 <=array_index_operation_state_counter_3 + 1;
8:when 1 =>9:array_index_operation_state_counter_3 <= (others => ’0’);10:
state_counter_sum_2 <= state_counter_sum_2 + 1;
11:
when others => array_index_operation_state_counter_3 <=(others => ’0’);
12:
end case;
13:
when 1 =>14:
sum_0 <= conv_std_logic_vector(
conv_integer(sum_0 + param_input_port_sum_a_rdata), 31-0+1);
15:
state_counter_sum_1 <= state_counter_sum_1 + 1;
16:
state_counter_sum_2 <= (others => ’0’);17:
when others => state_counter_sum_2 <= (others => ’0’);18:
end case;
１サイクル待たないといけない
19: when 3 =>データを読んでsumに加算
20: ...

図5与えられた配列の合計値を求める Java のプロ

a のクラスを VHDL エンティティに，ク義されたメソッドはそのエンティティのプロ

類似する要素に変換できるが，Java の制御は直接 VHDL に変換することはできないコード生成規約: メソッド呼び出しJavapublic class Hoge{// メソッド定義
public int zero(){ return 0; }呼ぶ側callerHoge hoge = new Hoge();...
hoge.zero(); // メソッド呼出し

呼ばれる側
callee_req <= ’1’

time

こういう枠にはめる．

set parameters_busy <= ’1’_req <= ’0’
wait formethod execution

method execution_busy <= ’0’

54

ESS2013 2013.10.16

ationr

ン

1: public class sum{
2: public int sum(int[] a){3:
int sum = 0;4:for(int i = 0; i < a.length; i++){5:sum += a[i];6:}7:return sum;
8: }
9: }

図 5 与えられた配列の合計値を求める Java のプログラム

イ

Java のクラスを
VHDL エンティティに，クラス内でこれも，長くなるので次のスライドへラ

定義されたメソッドはそのエンティティのプロセスに，

ルと類似する要素に変換できるが，Java の制御構文の多れ

くは直接 VHDL に変換することはできない．そのたり，め Java のプログラムと同様のデータ処理を実現する

ラ

ためのハードウェアアーキテクチャを作る必要がある．

sum += a[i];class sum{ 5:c int sum(int[]
6: a){ }xprsum= 0;conv_integer(sum_method_state)
7:
return sum;is
1:
case
ss
(int
= 0;
< a.length;i++){}
2: i when
0 =>i 8:if(sum_method_request= ’1’) thenum 3:+= a[i];9:}4:sum_method_busy <= ’1’;

メソッドが呼び出されるのを待つ5:
sum_method_state <= sum_method_state + 1;
urn6:sum;else7:
sum_method_busy <= ’0’;8:
end if;9:
when 1 =>10:
if(sum_method_request = ’0’) then11:
sum_method_state <= sum_method_state + 1;
12:
end if;13:
when 2 =>
この間にパラメタを引き渡す
14:
...
15:
when 4 =>16:
output_port_sum <= conv_std_logic_vector(conv_integer(sum_0), 31-0+1);17:
sum_method_state <= (others => ’0’);
15:
when 5 =>16:
sum_method_busy <= ’0’;17:
sum_method_state <= (others => ’0’);18:
when others => sum_method_state <= (others => ’0’);
19: end case;コン

図 5 与えられた配列の合計値を求め与えられた配列の合計値を求める Java のプログ

ライJava のクラスを VHDL エンテ

クラ
定義されたメソッドはそのエンテ
のクラスを
VHDL
エンティティに，クラールと類似する要素に変換できるが，れたメソッドはそのエンティティのプロセ
終わったら，返戻値をセットしておしまい
され
くは直接 VHDLに変換することJavaRockでソート
public class BubbleSort{
private final int[] br = new int[512];
public void test(int[] ar){for(int i = 0; i < ar.length; i++){ br[i] = ar[i]; }for(int i = 0; i <= (ar.length-1) - 1; i++){for(int j = 1; j <= ar.length - 1 - i; j++){int a = br[j];int b = br[j-1];
if(a < b){br[j-1] = a;br[j] = b;}}}}public int get(int i){ return br[i]; }}57

ESS2013 2013.10.16

JavaRockでソート

58

ESS2013 2013.10.16

FPGAを活用するために

FPGAを“活用”するために並列化
細粒度自動並列化
ユーザによるThreadレベル並列化
HDLモジュールの利用
JavaRock Hardware Interface(JRHI)
JavaRock HDL

60

ESS2013 2013.10.16

並列化手法
演算レベルの並列性→基本ブロック内の自動並列化
タスク・データレベルの並列性→JavaのスレッドをHWにマッピング
パイプライン並列性→wait-notifyで記述→JavaRock HDLでの記述

61

ESS2013 2013.10.16

JavaのスレッドをHWにマッピング
通常の関数呼び出し

led obj0 = new led();echo obj1 = new echo();sc1602̲test obj2 = new sc1602̲test();callercallee_req <= ’1’
set parameters

obj0.start();obj1.start();obj2.start();_busy <= ’1’_req <= ’0’

スレッドの生成＆実行
public class led extends Thread{counter c = new counter();boolean ﬂag;
public void run(){while(true){c.up();
int v = c.read();if(v == 1000000){c.clear();ﬂag = !ﬂag;}}}}

public class echo extends Thread{
rs232c obj = new rs232c();byte[] data = new byte[128];

wait formethod execution

method_busy <= ’0’

public void run(){while(true){
obj.write((byte)ʼ>ʼ);スレッドの場合
int i = 0;byte c = 0;
callercalleeboolean ﬂag = true;_req <= ’1’
while(true){set parametersc = obj.read();_busy <= ’1’
if(c == (byte)ʼ\nʼ || c == (byte)ʼ\rʼ){break;_req <= ’0’}else{
data[i] = c;wait fori++;method execution
method}_busy <= ’0’}for(int j = 0; j < i; j++){c = data[j]62

ESS2013 2013.10.16

HDLモジュールの活用
IPコア，手書きHDLモジュールの活用
ハードウェアを意識したJavaコード記述支援

Java  

JRHI

JavaRock HDL

JavaとRTLの間を埋める

VHDL, Verilog,  

FPGA

Javaで書けない(書きにくい)
モジュール

63

ESS2013 2013.10.16

JavaRock Hardware Interface
VHDL/Verilogで記述したモジュールを使いたい
Javaからみて自然な形でアクセスしたい
Javaプログラム中に変な記述をいれたくない

VHDL/Verilogモジュールの入出力をJavaの変数
HDL中で定義したブロックRAMを配列にみせる

64

ESS2013 2013.10.16

JRHIの使いどころ
メモリ
グラフィクスコントローラ→制御タイミングが重要
FPGA内部の専用HWリソース→BlockRAM(内蔵メモリ)→DSP
既存のHDLコードの活用

65

ESS2013 2013.10.16

JavaRock Hardware Interface
entity sc1602̲wrapper isport (
clk : in std̲logic;
pLCD̲RS : out std̲logic;
pLCD̲E : out std̲logic;
pLCD̲DB : out std̲logic̲vector(3 downto 0);
pLCD̲RW : out std̲logic;

sc1602̲wapper
pReq
pBusy
pWrWe
pWrData[7:0]pWrAddr[31:0]

pReq : in std̲logic;
pBusy : out std̲logic;
pWrData : in std̲logic̲vector(7 downto 0);
pWrAddr : in std̲logic̲vector(31 downto 0);
pWrWe : in std̲logic;

SC1602Wrapper
pReq: boolean
pBusy: boolean
pWrWe: boolean
pWrData: byte
pWrAddr: int

reset : in std̲logic;);
end sc1602̲wrapper;

使いたいHDLモジュール
public class SC1602Wrapper extends VHDLSimpleLibrary implements JavaRockComponentIface{public boolean pReq;
public boolean pBusy;public boolean pWrWe;
public byte pWrData;public int pWrAddr;
public SC1602Wrapper(String... args){
super(“sc1602̲wrapper”, args);

JRHIクラス
66

ESS2013 2013.10.16

JRHIの利用
public class SC1602Wrapper extends VHDLSimpleLibrary implements JavaRockComponentIface{public boolean pReq;
public boolean pBusy;public boolean pWrWe;
public byte pWrData;public int pWrAddr;
public SC1602Wrapper(String... args){
super(“sc1602̲wrapper”, args);

用意したJRHIクラス

public class SC1602̲USER{
private ﬁnal SC1602Wrapper obj = new SC1602Wrapper();
public void put(){
obj.pWrData = (byte)ʼaʼ;
obj.pWrAddr = 0;
obj.pWrWr = true;
obj.pWrWr = false;
obj.pReq = true;
obj.pReq = false;}

Javaプログラムとしてコンパイルが可能
JavaRockでHDLなsc1602̲wrapperと組み合わせる

使う側67

ESS2013 2013.10.16

もう一歩すすんだJRHIの活用
public class MemoryDevice extends 〜{
public byte[] byte̲data;
public int[] int̲data;
public MemoryDevice(String... args){
super(“memory”, args);

JRHIクラス
public class MemoryDevice̲USER{
private ﬁnal MemoryDevice obj = new MemoryDevice();public void put(){
obj.byte̲data[0] = (byte)100;
obj.int̲data[0] = 1000;}

使う側

ヒープメモリの一部をHDLモジュール内のメモリに見せるというような使い方が可能
68

ESS2013 2013.10.16

JavaRock HDL
アノテーションによるJavaのHDL化

69

ESS2013 2013.10.16

アノテーション

アノテーション
@javarockhdl

概要

対象

このクラスがJavaRockHDLであることを示す

クラス

@raw

メソッド内のifやwhileの条件判定式をHDLに直接変換

メソッド

@auto

メソッドが呼び出されることなく動作するようにする

メソッド@width変数のbit幅を定義する@no_wait

メソッド終了を待たずメソッド呼出し元の処理を進める

変数

70

メソッド

ESS2013 2013.10.16

JavaRockの制限
インスタンスはファイナルでの生成のみ
スタティックなHWモジュールとして合成
インスタンスの共有は不可
管理用の信号のアービトレーション未実装
浮動小数点数演算は不可
配列はプリミティブ型(除ﬂoat/double)のみ/とか%とか未サポート
71

ESS2013 2013.10.16

適用事例
1/4
今後の課題
倒立振子 (by 宇都宮大学 大川先生)マイコン• FPGA倒立振子ロボットを完成させる• モジュールの結合テスト
制御分野にFPGAを導入したい• モジュールを結合したうえでの並列化
電気自動車の制御< 50μ秒• 倒立振子の制御動作を確認
2013/3/7
第75回全国大会

倒立振子

FPGA
倒立振子

15

評価結果(平均化処理)
3.8m秒@H8→ 6.3μ秒@FPGA
平均化処理にマイコンで1.5ミリ秒かかっていたのがFPGAで2.9マイクロ秒に短縮

経過時間(マイクロ秒)

25

22.68

20
15

11.7

10
5

2.88

0
10要素

50要素

100要素

植竹 他 "倒立振子ロボットのFPGAを用いた超高速制御"
情報処理学会第75回全国大会
72

ESS2013 2013.10.16

ཧ

ಉ

ॲ

ʷ

ͷࢽ
ε

Table 5 Performance comparison in edge detection

適用事例 2/4

ಈ࡞प೾਺ [MHz]ԋࢉʹඞཁͳΫϩοΫ਺

JavaRock

178

61439

खॻ͖

153

4096

Reconﬁgurable Android (by 農工大 中條研)
ද 6 SHA-1 ͷ࣮ߦ࣌ؒ

SHA-1

Execution
time of SHA-1
Vol.53 No.2Table
1–96(Feb.
2012)࣮ߦ࣌ؒ [ms]ɼJava ʹΑΔ‫ه‬ड़ͷΈ

3360

อ

Andoird NDK Λ࢖༻

51.7

ͯ

͖

(XC6SLX45T)৘ใॲཧֶձ࿦จࢽ
Vol.53 No.2 41.3
1–9 (Feb. 2012)
FPGA ࢖༻ʢखॻ͖ʣFPGA ࢖༻ʢJavaRockʣ 209
ද 7 Τοδ‫ݕ‬ग़ͷ࣮ߦ࣌ؒ

エッジ検出

a

Table 7 Execution (3x3ラプラシアンフィルタ)
time of edge detection͜ͷ 1 ͭͷϒϩοΫͷ‫͔͔ʹࢉܭ‬ΔΫϩοΫ਺ΛΧ΢ϯτ

A

ͨ͠ɽΤοδ‫ݕ‬ग़ʹؔͯ͠͸ 64 ʷ ࣮ߦ࣌ؒ64 ͷը૾ͷ֤ըૉͷೖ[ms]Λ

Java ʹΑΔ‫ه‬ड़ͷΈ
392
ྗ͔Βग़ྗ·Ͱʹ͔͔ΔΫϩοΫ਺ͱͳ͍ͬͯΔɽ

k

Andoird NDKΛ࢖༻͞Βʹɼ࣮‫Ͱ্ػ‬CPU
ͱ FPGA8.85
Ͱ௨৴Λߦ͍ɼ࣮ࡍͷಉFPGA ࢖༻ʢखॻ͖ʣ
8.83 ͸ 1Mbyte ͷσʔॲཧʹ͔͔ͬͨ࣌ؒΛଌఆͨ͠ɽ
SHA-1

ɼ

λΛɼΤοδ‫ݕ‬ग़ʹ͸ 512 ʷ 512 ͷϞϊΫϩը૾Λ࢖༻͠

FPGA ࢖༻ʢJavaRockʣ 105

booleanA;

private void func0 (){A = true ;}private void func1 (){A = false ;}ਤ 11 1 ͭͷม਺ʹର͢Δෳ਺ϝιου͑ͨɽൺֱͱͯ͠ɼAndroid ࣮‫Ͱ্ػ‬ͷ Java ʹΑΔ‫ه‬ड़ͷck ʹ͓͚Δϝιου‫ͼݺ‬ग़͠ ʢbʣThread ʹΑ
Fig. 11 Writing a variable from mulΈͷ࣮ߦ࣌ؒͱɼ
NDKʹΑΔ
C‫ʹޠݴ‬ΑΔ‫ه‬ड़Λར༻͠
6.1 ಋೖίετ(Atom Z530 1.6GHz)
ͨ৔߹ͷ࣮ߦ࣌ؒΛଌఆͨ͠ɽ
SHA-1 ͷ֤࣮ߦ࣌ؒΛද͸‫ࡏݱ‬ϑϦʔͰެ։͞Ε͓ͯΓ[1]ɼJava ͷ࣮6
hod call JavaRockof JavaRockʢbʣparallel processing
ਤ 10 Application Reference Platform for Image ProceʹɼΤοδ‫ݕ‬ग़ͷ֤࣮ߦ࣌ؒΛද7ʹࣔ͢ɽ͜ͷͱ͖ɼ‫ܭ‬ߦ‫ ͱڥ؀‬JavaRock ͷ jar ϑΝΠϧΛ༻ҙ͑͢͠͞Ε͹։‫͔఺؍‬Β๬·͍͠΋ͷͰ͋Γɼ࢓༷มߋ
ESS2013 2013.10.16
73

適用事例 3/4
文字列処理
ハードウェアシステムのコンソールなど“192.168.10.1” → 0xc0, 0xa8, 0x0a, 0x01

74

ESS2013 2013.10.16

適用事例 4/4

hand-coded primitive protocol. It is efficient and highspeed, however, difficult to develop complex system andhard to maintain. It is shown that the overhead of ORB
protocol processing compared to RAW protocol system isvery small (about 70us).

ORB Engine with JavaRock
The system clock frequency of the FPGA is 50MHz. As

compared to the software ORB on MicroBlaze soft-coreprocessor shown in Figure 5, the latency time was reduced
dramatically (from 1.5ms to 200 us, @ 50MHz).

Networked FPGA system based on ORB
1000

Delay [us]800

ORB (PC)
ORB (FPGA)
Raw (PC)
Raw (FPGA)

600
400
200

0
1

2

3
Remote Calls

4

5

Figure 11 Measurement performance of the synthesized ORB
Protocol Engine compared to RAW protocol system

75

0

0

tor Outpute) and angle (Frame)degree]60
6000
T. Ohkawa et al., "Reconfigurable
and Hardwired
z ORB Engine on FPGA by Javato-HDL Synthesizer for 40
Realtime Application," angle
Proc. 4th International4000
out Reconfigurable Technologies
Symposium on Highly Efficient Accelerators and
20
2000(HEART 2013), June 2013.

ESS2013 2013.10.16

デモ

main

MadelbrotもどきLチカ

SC1602文字表示

まとめ
高位合成言語/処理系を紹介しました
JavaRockのコード生成を紹介しました
JavaRockでの事例を紹介しました78

ESS2013 2013.10.16

少し先のJavaRockについて
もっとJavaらしいプログラムのHDL化
オブジェクトの動的生成
インスタンスチェインの取り扱い
JavaRock-Thrash成果の取り込み
浮動小数点数演算使用する演算リソースを設定できるように
レジスタ共有，ループアンローリング
演算のチェインニング
79

ESS2013 2013.10.16