Handel-Cについて
の編集
https://www.am.ics.keio.ac.jp/proj/asap/wiki/index.php?Handel-C%A4%CB%A4%C4%A4%A4%A4%C6
[
トップ
] [
編集
|
差分
|
バックアップ
|
添付
|
リロード
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
-- 雛形とするページ --
(no template pages)
*[[Handel-Cについて]] [#t2a478f7] ※これはVisionグループOBのfukudaさんのページから持ってきました。 fukudaさんのwiki→http://www.am.ics.keio.ac.jp/members/fukuda/wiki/index.php?Kyoshow Celoxica社((もともとHandel-CはOxford大学の1グループが開発していて、それが独立して設立されたのがCeloxicaらしい))のHandel-Cは、C言語をハードウェア向けに拡張した((ANSI-Cの文法に、HoareのCSPの理論を加えたらしい))言語である。~ 開発環境およびコンパイラは、同社のDK3を利用する。~ 回路を意識せずに、処理したいことを記述することによってLSIを設計することができる。~ また、合成の対象をFPGAに絞っているため、プロセス技術や細かいタイミングに起因する~ トラブルがユーザの設計に影響を与える可能性が小さい。~ Handel-Cで書かれたソースコードはVerilogHDLやVHDL,EDIFに変換される。~ ただし、性能や回路面積についてはVerilogHDLやVHDLで直接記述したほうが 良い結果が得られる。 ●DK3による開発フロー +プロジェクトの作成 +ソースコードの記述 +デバッグ 「Build」→「Set Active Configuration」で「Debug」を指定する。 デバッグモードでビルド(F7)すると、次のようなデバッグ機能が利用可能になる。 (Verilog HDLやVHDLへ変換するときは、デバッグコードはコメントアウトする必要あり) ++ソースコードデバッグ 変数の値を表示しながら、ステップ実行を行ったり(F11)、 ブレークポイントの指定等を行うことができる。 ++プラグインの利用 Handel-Cと外部の接続を定義するinterface文を使うと、 デバッグ時に入出力信号をVisual C++などで作成したDLLと結合することができるらしい。 ++chanin/chanout chanin/chanoutを利用して、外部ファイルから入力を行ったり 結果をファイルへ出力したりする。 (例) > chanin input with {infile = "ina.txt"}; //ファイルから入力 > chanout output with {outfile = "out.txt"}; //ファイルへ出力 > > input ? x; > output ! 5; または、 > chanout 8 stdout; //ディスプレイに表示させたい > stdout ! 5; ++C/C++関数のコール C/C++で書いた関数をそのまま使用できる。 その際、Handel-Cコードには下のような宣言が必要になる。 > extern "C" // 外部関数がC++なら、 extern "C++" になる > { > int printf(const char *fmt, ...); //標準ライブラリも利用できる > unsigned short user_func(void); //自分で定義したのも利用できる > } +Logic estimation 「Build」→「Set Active Configuration」で「EDIF」を指定。 「Project」→「Settings」の「Linker」タブで、「Generate estimation info」にチェックを入れる。 これでビルドすると、EDIFフォルダ内にクリティカルパスやLUT数の情報がHTML形式で保存される。 +VerilogHDL(VHDL)へのコンパイル 「Build」→「Set Active Configuration」で「Verilog(VHDL)」を指定。 これでビルドすれば、Verilog(VHDL)フォルダ内に*.v(vhd)ファイルが生成される。 ●Handel-Cのサンプル とりあえずVerilogやEDIFに変換できるサンプルコードを下に置いておきます。 set family = XilinxVirtexII; set part = "xc2v6000bf957-4"; set clock = external; set reset = external; void main (void) { unsigned int 4 DOut; interface port_in(unsigned int 4 DIn1) DataIn1(); interface port_in(unsigned int 4 DIn2) DataIn2(); interface port_out() DataOut(DOut); DOut = DataIn1.DIn1 + DataIn2.DIn2; } ●特徴 -bit幅の指定 好きなbit幅を指定することができる。 > unsigned int 8 x; キャストによってbit幅を変えるのは無理みたい。 また、次のようにbitを選択することができる。 (例) > unsigned int 8 x; > unsigned int 1 y; > unsigned int 5 z; > > x = 0b01001001; > y = x[4]; //0b0 > z = x[7:3]; //0b01001 -Handel-C特有の演算子 -- <- (Take LSBs) -- \\ (Drop LSBs) 最下位の数bitだけ残したり、切り落としたりする。 (例) > unsigned int 8 x; > unsigned int 4 y; > unsigned int 4 z; > > x = 0b11000111; > y = x <- 4; // 0b0111 > z = x \\ 4; // 0b1100 -- @ (Concatenation) 複数の変数を連結する。 (例) > unsigned int 8 x; > unsigned int 4 y; > unsigned int 4 z; > > y = 0xC; > z = 0x7; > x = y @ z; // 0xC7 また、0をパディングするために用いられる。 (例) > unsigned int 8 x; > unsigned int 8 y; > unsigned int 16 z; > > z = (0 @ x) * (0 @ y); // 上位8bitを0で埋める -Timing 1代入文には、必ず1クロックと定められている。 delayは何もせずに1クロック消費し、リソースの競合を避けるために使われる。 また、チャネルを用いた通信にも1クロックかかる。 ==や<、>=などの比較にはクロックはかからない。 -並列処理 なにも指定しなければ、暗黙的にシーケンシャルな回路が生成される (seq文が省略されていると見なされる)。 並列処理を行いたいときはpar文を用いる。 (例) > par > { > x = 1; > { > delay; > x = 2; > } > } &ref(http://www.am.ics.keio.ac.jp/members/fukuda/image/handel_c/par01.jpg); 早く処理が終わった分岐部分は、最も遅い分岐の処理が終わるのを待つ。 -Channel 並列に処理している分岐間でのデータの受け渡しにはチャネルが用いられる。 > Channel ! Expression; // 送信 > Channel ? Variable; // 受信 送信側は受信側が準備できるまで待機する。逆に、受信側も送信側が準備できるまで待機する。 (例) > par > { > { > a = b; > c = d; > link ! x; > } > link ? y; > } この場合、タイミングは下表のようになる。 |COLOR(red):Cycle|COLOR(red):Branch 1|COLOR(red):Branch 2| |1|a = b;|delay| |2|c = d;|delay| |3|Channel output|Channel input| //&ref(http://www.am.ics.keio.ac.jp/members/fukuda/image/handel_c/channel01.jpg); -変数の共有について 変数のスコープは、下図のようになっている。 &ref(http://www.am.ics.keio.ac.jp/members/fukuda/image/handel_c/scope01.jpg); 上のようなスコープだと、並列処理をしている複数のプロセスが 一つの変数を同時に変更するようなコードが書けてしまう(コンパイルが通ってしまう)。 こんなときはprialtを使うとよい。 (例) > prialt { > case chan1 ? y: > //statement > break; > case chan2 ? y: > //statement > break; > default: // なくてもよい > //statement > break; > } prialtは、最初に準備のできたチャネルを選択して通信を行う。 複数のチャネルが同時に準備できた場合は、上に書かれたものが優先的に選択される。 defaultなしのprialtの場合、どれかのチャネルが準備できるまで待機しつづける。 defaultありのprialtの場合、どのチャネルも準備できていないなら、defaultの 処理を行い、prialtから抜ける。 ●ファンクションとマクロ ||Return value?|Typed return values?|Called by reference?|Shared hardware?| |Functions|COLOR(green):Can have|COLOR(blue):YES|COLOR(red):NO|COLOR(blue):YES| |Arrays of functions|COLOR(green):Can have|COLOR(blue):YES|COLOR(red):NO|COLOR(blue):YES| |Inline functions|COLOR(green):Can have|COLOR(blue):YES|COLOR(red):NO|COLOR(red):NO| |Preprocessor macros|COLOR(green):Can have|COLOR(red):NO|COLOR(blue):YES|COLOR(red):NO| |Macro expressions|COLOR(blue):Must have|COLOR(red):NO|COLOR(blue):YES|COLOR(red):NO| |Shared expression|COLOR(blue):Must have|COLOR(red):NO|COLOR(blue):YES|COLOR(blue):YES| |Macro procedures|COLOR(red):None|COLOR(red):NO|COLOR(blue):YES|COLOR(red):NO| -ファンクションとマクロの例(変数を1.5倍する) --Function void f_sesqui (int *d, int s) // "shared" function without return { *d = s; *d += ((*d) >> 1); } int rf_sesqui (int s) // "shared" function with return { int ret; ret = s; ret += (ret >> 1); return ret; } --Array of function void af_sesqui [5] (int *d, int s) { *d = s; *d += ((*d) >> 1); } --Inline function void inline if_sesqui (int *d, int s) { *d = s; *d += ((*d) >> 1); } --Preprocessor macro #define de_sesqui (s) ((s) + ((s) >> 1)) #define dp_sesqui (d,s) ((d) = (s) + ((s) >> 1)) --Macro expression macro expr me_sesqui (s) = s + (s >> 1); --Shared expression shared expr se_sesqui (s) = s + (s >> 1); --Macro procedure macro proc mp_sesqui (d, s) { d = s; d += (d >> 1); } --呼び方 { int 5 x, y; x = 10; f_sesqui (&y, x); // Function without return y = rf_sesqui (x); // Function with return af_sesqui[2] (&y, x); // Array of Function if_sesqui (&y, x); // Inline Function y = de_sesqui (x); // Preprocessor macro with return dp_sesqui (y, x); // Preprocessor macro without return y = me_sesqui (x); // Macro expression y = se_sesqui (x); // Shared expression mp_sesqui (y, x); // Macro procedure } -注意点 次の記述は許されていない。 > y = f(g(x)); > y = f(x) + g(z); また、再帰も使えない。 -ハードウェアの共有について ファンクションを用いてハードウェアの共有を行えば、回路の面積を小さく抑えられる。 並列処理中に、異なるブロックで同じファンクションを使ってはならない。 その場合は関数の配列やインライン関数を用いる。→回路は増大する。 -クロックについて Macro expression と Shared expression は、変数に代入された時に1クロックかかる。 それ以外は、処理内容に応じたクロック数が必要になる。 ●雑記 -main関数について main関数の引数と戻り値はvoidと決まっている。 main関数はクロックと関連付けられ、異なるクロックで動作するパーツが 他に存在する場合は、複数のmain関数が必要になる。 -familyとpart ターゲットとするデバイスは何か > set family = XilinxVirtexII; > set part = "xc2v6000-4bf957"; partは、「Project」→「Setting」の「Chip」タブで見れる。 -clockとreset クロックとリセットの信号を外から引っ張ってくる > set clock = external; > set reset = external; ISEを通すには必要。 -interface > signal unsigned char OutData; > interface bus_in(unsigned InputData) InputPort(); > interface bus_out() OutputPort( OutData ); Verilogに落としたときに、この記述がモジュールの入出力になります。 これがないと中身のある回路ができないぽいです ●知っていると便利 -Macroの便利なオペレータ --Select --ifselect --let ... in ●良いコードの書き方 -タイミングに関して どんなに複雑なステートメントでも、ちゃんと組み合わせ回路を生成してくれる。 例えば以下の2つのコードは両方とも1クロックサイクルで実行される。 > x = y; > x = (((y * z) + (w * v)) << 2) <- 7; しかし、遅延が大きくなって動作周波数が落ちるので 簡単な論理を並列に動作させるように工夫すべきである。 --divisionやmodulo,multiplicationは大きな論理が形成される。 シフト演算やパイプライン処理でなんとかするべき --wide adderはcarry rippleのために深い論理を形成する。 short adderを複数利用し、多段にする方がよい --greater thanやless thanも深い論理を生成する。 ==や!=で代用する方法を考えるべき --複雑な式は多段にすること (例) > x = a + b + c + d + e + f + g + h; は、以下のように書き換えるとよい。 > par > { > temp1 = a + b; > temp2 = c + d; > temp3 = e + f; > temp4 = g + h; > } > par > { > temp1 = temp1 + temp2; > temp3 = temp3 + temp4; > } > x = temp1 + temp3; --Empty statement 次のようなコードは、遅延が大きくなるため、避けるべき > if ( a > b ) > x++; > if ( b > c ) > x++; > if ( c > d ) > x++; これらの比較がひとつもhitしない場合、全ての比較が1クロック内で行われなければならない。 1クロックで1つの比較が行われるように、下のように書き換えた方がよい > if ( a > b ) { > x++; > } else { > delay; > } > if ( b > c ) { > x++; > } else { > delay; > } > if ( c > d ) { > x++; > } else { > delay; > } ●CとHandel-Cの比較メモ -Statements |両方|Cのみ|Handel-Cのみ| |switch||par| |do...while||delay| |while||?| |if...else||!| |for||prialt| |break||seq| |continue||ifselect| |return||| |goto||| |assert||| -Type |両方|Cのみ|Handel-Cのみ| |int|double|chan| |unsigned|float|ram| |char|union|rom| |long||wom| |short||mpram| |enum||signal| |register||chanin| |static||chanout| |extern||undefined| |struct||interface| |volatile||<>| |void||inline| |const||typeof| |auto||| |signed||| |typedef||| -Expression |両方|Cのみ|Handel-Cのみ| |* (pointer indirection)|sizeof|select(...)| |& (address of)||width(...)| |他、全ての演算子が使えます||@| |||\\| |||<-| |||[:]| |||let...in| (souichi) &counter(all);
タイムスタンプを変更しない
*[[Handel-Cについて]] [#t2a478f7] ※これはVisionグループOBのfukudaさんのページから持ってきました。 fukudaさんのwiki→http://www.am.ics.keio.ac.jp/members/fukuda/wiki/index.php?Kyoshow Celoxica社((もともとHandel-CはOxford大学の1グループが開発していて、それが独立して設立されたのがCeloxicaらしい))のHandel-Cは、C言語をハードウェア向けに拡張した((ANSI-Cの文法に、HoareのCSPの理論を加えたらしい))言語である。~ 開発環境およびコンパイラは、同社のDK3を利用する。~ 回路を意識せずに、処理したいことを記述することによってLSIを設計することができる。~ また、合成の対象をFPGAに絞っているため、プロセス技術や細かいタイミングに起因する~ トラブルがユーザの設計に影響を与える可能性が小さい。~ Handel-Cで書かれたソースコードはVerilogHDLやVHDL,EDIFに変換される。~ ただし、性能や回路面積についてはVerilogHDLやVHDLで直接記述したほうが 良い結果が得られる。 ●DK3による開発フロー +プロジェクトの作成 +ソースコードの記述 +デバッグ 「Build」→「Set Active Configuration」で「Debug」を指定する。 デバッグモードでビルド(F7)すると、次のようなデバッグ機能が利用可能になる。 (Verilog HDLやVHDLへ変換するときは、デバッグコードはコメントアウトする必要あり) ++ソースコードデバッグ 変数の値を表示しながら、ステップ実行を行ったり(F11)、 ブレークポイントの指定等を行うことができる。 ++プラグインの利用 Handel-Cと外部の接続を定義するinterface文を使うと、 デバッグ時に入出力信号をVisual C++などで作成したDLLと結合することができるらしい。 ++chanin/chanout chanin/chanoutを利用して、外部ファイルから入力を行ったり 結果をファイルへ出力したりする。 (例) > chanin input with {infile = "ina.txt"}; //ファイルから入力 > chanout output with {outfile = "out.txt"}; //ファイルへ出力 > > input ? x; > output ! 5; または、 > chanout 8 stdout; //ディスプレイに表示させたい > stdout ! 5; ++C/C++関数のコール C/C++で書いた関数をそのまま使用できる。 その際、Handel-Cコードには下のような宣言が必要になる。 > extern "C" // 外部関数がC++なら、 extern "C++" になる > { > int printf(const char *fmt, ...); //標準ライブラリも利用できる > unsigned short user_func(void); //自分で定義したのも利用できる > } +Logic estimation 「Build」→「Set Active Configuration」で「EDIF」を指定。 「Project」→「Settings」の「Linker」タブで、「Generate estimation info」にチェックを入れる。 これでビルドすると、EDIFフォルダ内にクリティカルパスやLUT数の情報がHTML形式で保存される。 +VerilogHDL(VHDL)へのコンパイル 「Build」→「Set Active Configuration」で「Verilog(VHDL)」を指定。 これでビルドすれば、Verilog(VHDL)フォルダ内に*.v(vhd)ファイルが生成される。 ●Handel-Cのサンプル とりあえずVerilogやEDIFに変換できるサンプルコードを下に置いておきます。 set family = XilinxVirtexII; set part = "xc2v6000bf957-4"; set clock = external; set reset = external; void main (void) { unsigned int 4 DOut; interface port_in(unsigned int 4 DIn1) DataIn1(); interface port_in(unsigned int 4 DIn2) DataIn2(); interface port_out() DataOut(DOut); DOut = DataIn1.DIn1 + DataIn2.DIn2; } ●特徴 -bit幅の指定 好きなbit幅を指定することができる。 > unsigned int 8 x; キャストによってbit幅を変えるのは無理みたい。 また、次のようにbitを選択することができる。 (例) > unsigned int 8 x; > unsigned int 1 y; > unsigned int 5 z; > > x = 0b01001001; > y = x[4]; //0b0 > z = x[7:3]; //0b01001 -Handel-C特有の演算子 -- <- (Take LSBs) -- \\ (Drop LSBs) 最下位の数bitだけ残したり、切り落としたりする。 (例) > unsigned int 8 x; > unsigned int 4 y; > unsigned int 4 z; > > x = 0b11000111; > y = x <- 4; // 0b0111 > z = x \\ 4; // 0b1100 -- @ (Concatenation) 複数の変数を連結する。 (例) > unsigned int 8 x; > unsigned int 4 y; > unsigned int 4 z; > > y = 0xC; > z = 0x7; > x = y @ z; // 0xC7 また、0をパディングするために用いられる。 (例) > unsigned int 8 x; > unsigned int 8 y; > unsigned int 16 z; > > z = (0 @ x) * (0 @ y); // 上位8bitを0で埋める -Timing 1代入文には、必ず1クロックと定められている。 delayは何もせずに1クロック消費し、リソースの競合を避けるために使われる。 また、チャネルを用いた通信にも1クロックかかる。 ==や<、>=などの比較にはクロックはかからない。 -並列処理 なにも指定しなければ、暗黙的にシーケンシャルな回路が生成される (seq文が省略されていると見なされる)。 並列処理を行いたいときはpar文を用いる。 (例) > par > { > x = 1; > { > delay; > x = 2; > } > } &ref(http://www.am.ics.keio.ac.jp/members/fukuda/image/handel_c/par01.jpg); 早く処理が終わった分岐部分は、最も遅い分岐の処理が終わるのを待つ。 -Channel 並列に処理している分岐間でのデータの受け渡しにはチャネルが用いられる。 > Channel ! Expression; // 送信 > Channel ? Variable; // 受信 送信側は受信側が準備できるまで待機する。逆に、受信側も送信側が準備できるまで待機する。 (例) > par > { > { > a = b; > c = d; > link ! x; > } > link ? y; > } この場合、タイミングは下表のようになる。 |COLOR(red):Cycle|COLOR(red):Branch 1|COLOR(red):Branch 2| |1|a = b;|delay| |2|c = d;|delay| |3|Channel output|Channel input| //&ref(http://www.am.ics.keio.ac.jp/members/fukuda/image/handel_c/channel01.jpg); -変数の共有について 変数のスコープは、下図のようになっている。 &ref(http://www.am.ics.keio.ac.jp/members/fukuda/image/handel_c/scope01.jpg); 上のようなスコープだと、並列処理をしている複数のプロセスが 一つの変数を同時に変更するようなコードが書けてしまう(コンパイルが通ってしまう)。 こんなときはprialtを使うとよい。 (例) > prialt { > case chan1 ? y: > //statement > break; > case chan2 ? y: > //statement > break; > default: // なくてもよい > //statement > break; > } prialtは、最初に準備のできたチャネルを選択して通信を行う。 複数のチャネルが同時に準備できた場合は、上に書かれたものが優先的に選択される。 defaultなしのprialtの場合、どれかのチャネルが準備できるまで待機しつづける。 defaultありのprialtの場合、どのチャネルも準備できていないなら、defaultの 処理を行い、prialtから抜ける。 ●ファンクションとマクロ ||Return value?|Typed return values?|Called by reference?|Shared hardware?| |Functions|COLOR(green):Can have|COLOR(blue):YES|COLOR(red):NO|COLOR(blue):YES| |Arrays of functions|COLOR(green):Can have|COLOR(blue):YES|COLOR(red):NO|COLOR(blue):YES| |Inline functions|COLOR(green):Can have|COLOR(blue):YES|COLOR(red):NO|COLOR(red):NO| |Preprocessor macros|COLOR(green):Can have|COLOR(red):NO|COLOR(blue):YES|COLOR(red):NO| |Macro expressions|COLOR(blue):Must have|COLOR(red):NO|COLOR(blue):YES|COLOR(red):NO| |Shared expression|COLOR(blue):Must have|COLOR(red):NO|COLOR(blue):YES|COLOR(blue):YES| |Macro procedures|COLOR(red):None|COLOR(red):NO|COLOR(blue):YES|COLOR(red):NO| -ファンクションとマクロの例(変数を1.5倍する) --Function void f_sesqui (int *d, int s) // "shared" function without return { *d = s; *d += ((*d) >> 1); } int rf_sesqui (int s) // "shared" function with return { int ret; ret = s; ret += (ret >> 1); return ret; } --Array of function void af_sesqui [5] (int *d, int s) { *d = s; *d += ((*d) >> 1); } --Inline function void inline if_sesqui (int *d, int s) { *d = s; *d += ((*d) >> 1); } --Preprocessor macro #define de_sesqui (s) ((s) + ((s) >> 1)) #define dp_sesqui (d,s) ((d) = (s) + ((s) >> 1)) --Macro expression macro expr me_sesqui (s) = s + (s >> 1); --Shared expression shared expr se_sesqui (s) = s + (s >> 1); --Macro procedure macro proc mp_sesqui (d, s) { d = s; d += (d >> 1); } --呼び方 { int 5 x, y; x = 10; f_sesqui (&y, x); // Function without return y = rf_sesqui (x); // Function with return af_sesqui[2] (&y, x); // Array of Function if_sesqui (&y, x); // Inline Function y = de_sesqui (x); // Preprocessor macro with return dp_sesqui (y, x); // Preprocessor macro without return y = me_sesqui (x); // Macro expression y = se_sesqui (x); // Shared expression mp_sesqui (y, x); // Macro procedure } -注意点 次の記述は許されていない。 > y = f(g(x)); > y = f(x) + g(z); また、再帰も使えない。 -ハードウェアの共有について ファンクションを用いてハードウェアの共有を行えば、回路の面積を小さく抑えられる。 並列処理中に、異なるブロックで同じファンクションを使ってはならない。 その場合は関数の配列やインライン関数を用いる。→回路は増大する。 -クロックについて Macro expression と Shared expression は、変数に代入された時に1クロックかかる。 それ以外は、処理内容に応じたクロック数が必要になる。 ●雑記 -main関数について main関数の引数と戻り値はvoidと決まっている。 main関数はクロックと関連付けられ、異なるクロックで動作するパーツが 他に存在する場合は、複数のmain関数が必要になる。 -familyとpart ターゲットとするデバイスは何か > set family = XilinxVirtexII; > set part = "xc2v6000-4bf957"; partは、「Project」→「Setting」の「Chip」タブで見れる。 -clockとreset クロックとリセットの信号を外から引っ張ってくる > set clock = external; > set reset = external; ISEを通すには必要。 -interface > signal unsigned char OutData; > interface bus_in(unsigned InputData) InputPort(); > interface bus_out() OutputPort( OutData ); Verilogに落としたときに、この記述がモジュールの入出力になります。 これがないと中身のある回路ができないぽいです ●知っていると便利 -Macroの便利なオペレータ --Select --ifselect --let ... in ●良いコードの書き方 -タイミングに関して どんなに複雑なステートメントでも、ちゃんと組み合わせ回路を生成してくれる。 例えば以下の2つのコードは両方とも1クロックサイクルで実行される。 > x = y; > x = (((y * z) + (w * v)) << 2) <- 7; しかし、遅延が大きくなって動作周波数が落ちるので 簡単な論理を並列に動作させるように工夫すべきである。 --divisionやmodulo,multiplicationは大きな論理が形成される。 シフト演算やパイプライン処理でなんとかするべき --wide adderはcarry rippleのために深い論理を形成する。 short adderを複数利用し、多段にする方がよい --greater thanやless thanも深い論理を生成する。 ==や!=で代用する方法を考えるべき --複雑な式は多段にすること (例) > x = a + b + c + d + e + f + g + h; は、以下のように書き換えるとよい。 > par > { > temp1 = a + b; > temp2 = c + d; > temp3 = e + f; > temp4 = g + h; > } > par > { > temp1 = temp1 + temp2; > temp3 = temp3 + temp4; > } > x = temp1 + temp3; --Empty statement 次のようなコードは、遅延が大きくなるため、避けるべき > if ( a > b ) > x++; > if ( b > c ) > x++; > if ( c > d ) > x++; これらの比較がひとつもhitしない場合、全ての比較が1クロック内で行われなければならない。 1クロックで1つの比較が行われるように、下のように書き換えた方がよい > if ( a > b ) { > x++; > } else { > delay; > } > if ( b > c ) { > x++; > } else { > delay; > } > if ( c > d ) { > x++; > } else { > delay; > } ●CとHandel-Cの比較メモ -Statements |両方|Cのみ|Handel-Cのみ| |switch||par| |do...while||delay| |while||?| |if...else||!| |for||prialt| |break||seq| |continue||ifselect| |return||| |goto||| |assert||| -Type |両方|Cのみ|Handel-Cのみ| |int|double|chan| |unsigned|float|ram| |char|union|rom| |long||wom| |short||mpram| |enum||signal| |register||chanin| |static||chanout| |extern||undefined| |struct||interface| |volatile||<>| |void||inline| |const||typeof| |auto||| |signed||| |typedef||| -Expression |両方|Cのみ|Handel-Cのみ| |* (pointer indirection)|sizeof|select(...)| |& (address of)||width(...)| |他、全ての演算子が使えます||@| |||\\| |||<-| |||[:]| |||let...in| (souichi) &counter(all);
テキスト整形のルールを表示する