Comments
Description
Transcript
Cプログラムからのハードウェア設計: Handel
Cプログラムからのハードウェア設計: Handel-CとDK4の学習 松本 剛史 [email protected] 大規模集積システム設計教育研究センター 演習のスケジュール > 1日目(10/6):動作合成の概要とDK4の使用法 > 2日目(10/20):Handel-C言語の文法,設計フローの習得 > 3日目(10/27):実例を題材としたHandel-C記述の習得 > 4日目(11/10):Elegantシステムを用いた上位設計手法 > 5日目(11/17):Handel-C言語を使った自由課題の設計 > 6日目(12/1):報告会 > 報告会後に演習レポート提出(期限は後日指定) 2 概要 > FPGAボード (RC100)を使ったシステム設計 > プログラミング言語を使ったハードウェア設計 > Handel-C(言語)とDK4(コンパイラ/シミュレータ)の習得 > 実例: 7セグメント表示とブロック崩しゲーム (演習課題) > 自由課題の設計 3 用語の説明と使用するツール > RC100: FPGAボード > Handel-C: C言語を拡張し たプログラミング言語 > DK4: Handel-C用の論理 合成/デバッガ/シミュレー タ > Agilent (旧Celoxica): Handel-C/DK4を開発して いる会社 > DK4: Handel-C用の論理合 成/デバッガ/シミュレータ > Project Navigator: FPGA の配置配線(Xilinx社) > File Transfer Utility: BITフ ァイルのダウンロード > RC100: FPGAボード > Xilinx: FPGA用の論理合 成ツールを開発している会社 4 RC-100 開発ボード > Xilinx Spartan2-200 FPGA > 2MB ZBT SRAM, in 2 36-bit banks. 8MB Flash RAM > ビデオ入力デコーダ, VGA 出力DAコンバータ > 50 pin 拡張ボード用コネクタ, PS/2ポート×2, パラレルポート > クロック発振器 (最大80MHz) ボード上にCPUはありません! 5 実験環境 > PCと設計用ツールは一人に一つずつ アカウント:enshu パスワード:cad2008 > RC100(FPGAボード)は一人に一台 > RC100のVGA出力を使う場合は、PCとケーブルをシェアする 6 Handel-C言語の特徴 > RTL(リソースシェアリングやスケジューリングはしない)の設計が可能 > ソフトウェアの開発技術がそのまま使える > C/C++の文法の一部がそのまま使える > ハードウェアとソフトウェアの設計を同時に行なうことができる > ハードウェアを知らない人でもとっつきやすい 7 従来フローとの比較 Executable Executable Specification Specification Software Software VHDL/ VHDL/ Verilog Verilog Handel-C Handel-C Simulator Simulator Simulator Simulator Simulator Simulator VHDL System System Model Model Synthesis Synthesis EDIF EDIF ASIC ASIC Flow Flow Place Place and and Route Route Target Target Device Device 8 論理合成と動作合成 > RTL記述からネットリスト(ゲートレベルの回路記述)を 生成するのが論理合成 > 動作記述からRTLを生成するのが動作合成 9 動作合成の例 10 RTL記述とネットリストの例 11 動作合成 > スケジューリング > アロケーション > バインディング > 制約条件を満たすまでスケジューリング・アロケーション ・バインディングを繰り返し実行する 12 スケジューリング 動作記述をコントロールフローグラフ(CFG)に 展開してコントロールステップに割り当てる作業 13 スケジューリング(制約条件) 14 アロケーション > 論理合成のテクノロジマッピングに相当する > ライブラリの中から条件に合った演算器を各演算に 割り当てる 15 アロケーション(制約条件) 16 バインディング > 演算器の共有方法を決定する 17 バインディングの例 バインディングによってマルチプレクサの数や 結線数が大幅に変わることがある 18 演習の目的 > 演算のスケジューリング方法や演算器の共有方法 によって実行ステップ数(速度性能)や回路規模およ びクロック周波数が変化することを確認する > ソフトウェアプログラミングとハードウェア設計の違 いを体験する 19 本演習での設計のフロー > Handel-C言語で回路を記述する > DK4上でシミュレーション、デバッ グ および論理合成を行なう > Xilinx Project Navigatorで FPGA上の配置配線を決定し、ダ ウンロード用のbitデータを作成す る > File Transfer Utilityでbitデ ータをFPGAにダウンロードする Handel-C Simulate FPGA Vendor’s Tools 1 Register A Q1 D Q4 ENB Netlist Place And Route > RC100で動作確認を行なう > エラーがあればHandel-Cの記述 まで戻って修正する 20 DK4の操作練習 準備するファイル > Handel-C言語で記述されたプログラムソース … sample1.c > DK4でコンパイルする際の設定が記述された設定ファイル … sample1.hp > ワークスペースを定義するためのファイル … sample1.hw sample1.hwの例 #@hw project sample1.hp sample1.hpの例 #@hp type XilinxVirtex setting Debug lib:stdlib.hcl true setting Debug lib:rc100.hcl true setting EDIF lib:stdlib.hcl true setting EDIF lib:rc100.hcl true document sample1.c { type c } 21 DK4の起動 > sample1.hwまたはDKのアイコンをダブルクリック > DKのアイコンから起動した場合は File → Open Workspace をクリック 22 シミュレータ(デバッガ)の起動(1/3) > Build→Set Active Configuration…をクリック > Debugを指定してOK! 23 シミュレータ(デバッガ)の起動(2/3) > Build→Start Debug→Step Into をクリック あるいは ソースファイルの画面 をクリックした後F11キーでステップ実行 (1回目の場合、コンパイルするかと聞かれる。YESでバイナリを生成する) 24 シミュレータ(デバッガ)の起動(3/3) > F11キーでステップ実行 > display1とdisplay2(重なる場合移動する)が同時に変化する(並列動作する)ことを確認する > Debug→Stop Debuggingでデバッガを終了する 25 論理合成(1/2) > Build→Set Active Configuration…をクリック > EDIFを指定してOK! 26 論理合成(2/2) > Build→Build sample1をクリック > 0 errors, 0 warningsであることを確認する 27 EDIFファイルの確認 > EDIFは論理回路のネットリストを表現する標準フォーマットの一つ > ネットリスト : セルの名前とその入出力ポートの接続関係が記述されたリスト WordPadを使って表示させる (cell XOR2 (cellType GENERIC) (view view_1 (viewType NETLIST) (interface (port I0 (direction INPUT)) (port I1 (direction INPUT)) (port O (direction OUTPUT)) ) ) ) (cell OR4 (cellType GENERIC) …… …… 28 Project Navigator の起動 > Project Navigatorのアイコンをクリック > 下図のようなウィンドウが立ち上がることを確認する 29 FPGAの配置配線(1/5) > File→New Projectをクリックし、Project Nameはここではsample1とする > Project LocationはHandel-Cソースがあるフォルダのフォルダを指定し、その 他の変数は図のとおり記述して 次へ 30 FPGAの配置配線(2/5) > Input DesignのところにEDIFフォルダの中のsample1.edfを指定する > Copy のチェックを外す 31 FPGAの配置配線(3/5) > FPGAの種類、速度、パッケージ、スピードを指定する(デフォルトのままで可) > 最後に確認して完了 32 FPGAの配置配線(4/5) > sample.edfをクリックしEDIFファイルが表示されることを確認する > Inplement Designをダブルクリックすると配置配線がはじまる > Gnenrate Programming Fileをクリックしてダウンロード用のファイルに変換する 33 FPGAの配置配線(5/5) > 配置配線が正常に終了すると緑色のチェックマークが表示される > Warningがある場合は!が表示されるがwarningなので一応無視できる 34 FPGAへのダウンロード(1/3) > PCのプリンタポートとボードのパラレルポートを接続する > RC100ボードの電源をONにする(緑色LEDが点灯する) 35 FPGAへのダウンロード(2/3) > File Transfer Utility 2(FTU2) を起動する > Please select a boardボタンをクリックして、Celoxica RC100を 選択する。 > FPGAへ書き込みを選択する > Browseボタンをクリックして、.bitファイルを選択する。 36 FPGAへのダウンロード(3/3) > Configureボタンをクリックすることで、ダウンロードが開始し 、7セグメントLEDがルーレット状に点灯する 37 Handel-C 言語 Variables Bit manipulation operators Timing model Par {...} Signals Channels Functions Interface 38 文法の特徴 > ISO-C (ANSI-C) 準拠… if, while, switch etc including 関数, 構造体, ポインタが使用可能 > ハードウェア記述用に拡張されたいくつかの文法を持つ par{…} 記述により並列動作を記述できる 変数に対して任意のビット幅を指定できる 演算に必要なクロック数を指定できる ビット操作が可能 資源の共有やスケジュールを明示的に記述できる RAMやROMおよび外部ピンへの接続を明示的に記述できる 39 変数定義 > Integer タイプのみをサポート > 符号なしの変数はunsigned で定義する(指定がない場合はsigned) > 変数のビット幅を指定できる 変数はハードウェアのレジスタに対応する void main(void) { unsigned 6 a; a=45; } a= 1 MSB 5 0 1 1 0 1 = 0x2d LSB 0 40 ビット操作命令 << 左シフト >> 右シフト <- 最下位ビットを取り出す ¥¥ 最下位ビットを切り捨てる @ ビット接続 [] ビット範囲指定 41 ビット接続の例 [MSB :LSB ] ビット選択 (ビットの範囲) 1 0 1 1 = 0xb a= b= 0 1 = 0x1 c = a@b c= 1 0 1 1 0 1 = 0x2d 42 ビット切り捨ての例 [MSB :LSB ] ビット選択 (ビットの範囲) a= 1 0 1 1 1 0 1 1 0 1 = 0x2d b = a¥¥2 b= = 0xb 43 ビット選択の例 [MSB :LSB ] ビット選択 (ビットの範囲) a= 1 0 1 1 0 0 1 1 0 1 = 0x2d b = a[4:1] b= = 0x6 44 タイミングモデル > 変数の代入とdelay文は1クロックサイクルを必要とする > それ以外の動作には遅延は発生しない void main(void) { … a=b+c+d; … } b c + a d Cf. Assembler for a Typical Microprocessor LOAD B,REG1 LOAD C,REG2 ADD REG1,REG2 LOAD D,REG2 ADD REG1,REG2 STORE REG1,A 3 Clock Cycles 3 Clock Cycles 1 Clock Cycle 3 Clock Cycles 1 Clock Cycle 3 Clock Cycles 45 並列動作の記述 > 通常の記述では逐次動作するハードウェアが合成される。 > par{…} 記述で囲まれた動作が同時に実行される(並列動作する)。 Sequential Block // 3 Clock Cycles { a=1; b=2; c=3; } Parallel Block // 1 Clock Cycles { par{ a=1; b=2; c=3; } } 46 並列動作の記述例 void main(void) { … a = 1; a = 1; 1 par { a = a + 1; b = 5; a = 2 b = 5 2 } par { a = 5 b = 6 3 b = b + 1; a = b; } } 47 並列動作の記述例 macro proc ParExample() { unsigned 4 Tenths, Count; unsigned 3 Circle; Count = 0; Circle = 0; <<< 途中省略 >>> while (1) { par /*run the two displays in parallel*/ { { Count = (Count == 15) ? 0 : (Count + 1); DisplayOutput1 = HexDisplayEncode1[Count]; } { Circle = (Circle == 5) ? 0 : (Circle + 1); DisplayOutput2 = CircleDisplayEncode[Circle]; } } } } 48 逐次動作と比較してみよう! macro proc ParExample() { unsigned 4 Tenths, Tenth4, Count; unsigned 3 Circle; Count = 0; Circle = 0; 新しい変数の定義 <<< 途中省略 >>> while (1) { #ifndef DEBUG Tenths = 4; TimeDelay(Tenths); 遅延の挿入 #endif // par /*run the two displays in parallel*/ { { Count = (Count == 15) ? 0 : (Count + 1); コメントアウト DisplayOutput1 = HexDisplayEncode1[Count]; } #ifndef DEBUG 遅延の挿入 Tenth4 = 4; TimeDelay(Tenth4); #endif { Circle = (Circle == 5) ? 0 : (Circle + 1); DisplayOutput2 = CircleDisplayEncode[Circle]; } } } } 演習1 : par文をコメントアウトした場合としない場合の動作を比較せよ 49 演習で使うmain関数(ソースの末尾) void main(void) { <<< 省略 >>> 該当する例題の コメントを外す /* Uncomment to run par{} example. */ // ParExample(); /* Uncomment to run channel examples. */ // par // { // ChanCount(); // ChanCircle(); // } /* Uncomment to run drop example. */ // DropExample(); /* Uncomment to run take example. */ // TakeExample(); …… …… 50 Signal変数 > あるクロックサイクルで代入された値をそのクロックサイクル内に限り読み出 すことができる Signal変数に代入した値を同じクロックサイクル内で読み出すことができる 上記以外のクロックサイクルでは値の代入は行なわれない // 2 Clock Cycles int 15 a, b; signal <int> sig; a = 7; par { sig = a; b = sig; } 51 Signal変数の使用例 macro proc SignalExample() { unsigned 4 Tenths, Count1, Count2, Count3; signal <unsigned 4> CountSig; Count1 = 0; Count2 = 0; Count3 = 0; <<< 途中省略 >>> while (1) { Count1 = (Count1 == 15) ? 0 : (Count1 + 1); par { CountSig = Count1+1; /*assign value to the signal*/ Signal変数からの代入 Count2 = CountSig; /*use the value from the signal*/ Count3 = Count1+1; /*...and use it again here*/ } <<< 途中省略 >>> } 52 } Unsigned変数で置き換えた記述 macro proc SignalExample() { unsigned 4 Tenths, Count1, Count2, Count3; unsigned 4 CountSig; Count1 = 0; Count2 = 0; Count3 = 0; <<< 途中省略 >>> while (1) { Count1 = (Count1 == 15) ? 0 : (Count1 + 1); par { CountSig = Count1+1; /*assign value to the signal*/ Count2 = CountSig; /*use the value from the signal*/ Count3 = Count1+1; /*...and use it again here*/ } <<< 途中省略 >>> } 演習2 : 1ページ前の記述とこの記述の動作をボード上で比較せよ 53 Signal変数とUnsigned変数の違い Integerの場合 Count1 1 Signalの場合 CountSig + Count1 + 1 Count1 1 + Count1 1 + CountSig CountSig Count2 Count3 Count2 Count3 54 Channel変数 > プロセス間通信 並列実行されるプロセス間の同期を取るために使われる チャンネルによって接続された双方のプロセスが通信可能状態になるまで待たされる c a b Chan c; //Declaration { { … c!a; … } … c?b; … //write a to c //read c to b } 55 Channel変数の使用例 macro proc ChanCount() { <<< 省略 >>> while (1) { do { <<< カウントアップ>>> } while (Count != 16); Counted ! 0; /*write to channel*/ Circled ? Temp; /*read from channel*/ } } チャンネルを書き込むまで chanel read 以降の処理が待たされる macro proc ChanCircle() { <<< 省略 >>> while (1) { Counted ? Temp; /*read from channel*/ do { do { <<< ルーレット >>> } while (Circle != 6); } while(Loops); Circled ! 0; /*write to channel*/ } } 56 Channel変数を使った演習 macro proc ChanCount() { <<< 省略 >>> while (1) { do { <<< カウントアップ>>> } while (Count != 16); Counted ! 0; /*write to channel*/ Circled ? Temp;/*read from channel*/ } } 演習3 : Channelの記述をコメントア ウトした場合としない場合を比較せよ macro proc ChanCircle() { <<< 省略 >>> while (1) { Counted ? Temp;/*read from channel*/ do { do { <<< ルーレット >>> } while (Circle != 6); } while(Loops); Circled ! 0; /*write to channel*/ } } 57 関数 > 繰り返し実行される文をマクロ化する > ハードウェア向けの拡張 同一の関数が並列に呼び出される場合は配列関数を使う 例) par{ a=mult[0](b,c); d=mult[1](e,f); } 58 関数の使用例 > e.g. Multiplication // 2 Multipliers,seq void main(void) { … a=b*c; d=e*f; … } // 1 Multiplier void main(void) { … a=mult(b,c); d=mult(e,f); … } // 2 Multipliers,par void main(void) { par{ a=mult[0](b,c); d=mult[1](e,f); } } unsigned mult(a,b) mult[2](a,b) { return a*b; } 59 設計誤りとその対処法 > 機能的なエラー シミュレーションとデバッガを使って修正する 参考) imageprocDebug.c > 遅すぎる回路 RC100 のクロックは20 MHz 組み合わせ回路の遅延を削減する手法を導入する design0 design1 design2 X = A*B*C*D*E*F par {X1 = A*B*C ; X2 = D*E*F;} X = X1*X2; par {X1 = A*B*C ; X2 = D*E*F; X = X1*X2;} > 大きすぎる回路 Xilinx ツールがコンパイルできない可能性がある シーケンシャルな回路に変形する 60 まとめ > 並列動作と逐次動作 Par{}記述により明示的に並列実行を指定する 並列動作は実行ステップ数を小さくできるがゲート数が多くなる > プロセス間通信 ハードウェア特有の拡張 チャンネルを使ってプロセス間で通信することによりプロセス間で同期を取 ることができる > Signal変数 クロックに同期しない代入が可能(ハードウェアの配線に相当) 多用すると直列パスが長くなり高速動作ができなくなる 61 演習課題 > 演習1 : sample1のpar文をコメントアウトした場 合としない場合の動作を比較せよ > 演習2 : sample1のsignal変数とunsigned変数 の動作をボード上で比較せよ > 演習3 : sample1のChannelの記述をコメントア ウトした場合としない場合を比較せよ 62 演習資料とデータのダウンロード: http://www.cad.u-tokyo.ac.jp/ から、「講義資料」へ そこからsample1.zipをダウンロードし、C:¥Enshu内で解凍 Handel-C の文法、RC-100の詳しい利用法: 1. 2. 3. 4. DK4のヘルプファイルを参考してください C:¥Program Files¥Celoxica¥DK¥Documentation C:¥Program Files¥Celoxica¥PDK¥Documentation C:¥Program Files¥Celoxica¥RC100¥Manuals 63