ModelSim で $messagelog を使う のバックアップソース(No.1)
更新[[公開メモ]] #contents * $messagelog [#qc78c59d] verilog でテストベンチを書く際に画面にテキストを表示するには通常 $display を使うのですが、ModelSim では $messagelog を使うと便利です。 テストベンチに LANG:verilog always @(posedge iclk_int) if (full & we) $messagelog("Write strobe was asserted while fifo is full.", "Error") などと書いておけば、$display のように出力ウィンドウにメッセージを表示すると共に、 下図のように wave ウィンドウの message 欄にメッセージが表示された時刻を示す ▼ が表示されます(&COLOR(blue){青丸};)。 &attach_ref; ▼ の上にカーソルを持って行けば表示されたメッセージを見ることができますので、 $display に表示された時刻を目で追うような苦労から解放されます。 また、message 欄のタイトル部分(&COLOR(red){赤丸};)をクリックすることで、 アクティブなカーソルを次の ▼ まで飛ばすことができます。 そのようにすれば、▼ を目で探す必要もありません。 さらに、メニューの [View] - [Messsage Viewer] にチェックが入っていれば、 wave ウィンドウの隣に Message Viewer タブが出ます(&COLOR(purple){紫丸})。 ここでは、表示されたメッセージを条件別に並べ替えて表示するようなことも可能です。 &attach_ref; (ちょっとメッセージ内容が違っているのは下記のルーチンを使っているためです) * $messagelog を便利に利用するためのマクロ [#u3affc0e] 上記の通り $messagelog はとても便利なのですが、 そのままソースコードに書き込んでしまうと、 ModelSim 以外でテストするのが難しくなってしまいます。 そこで、直接 $messagelog を呼ぶのではなくマクロを使って記述することにしました。 simulation.inc LANG:verilog `ifndef VERBOSE `define VERBOSE 0 `endif `define INFO(msg) \ if(`VERBOSE) \ $messagelog(`"%:S msg.`", "Note") `define ERROR(msg) \ $messagelog(`"%:S msg.`", "Error") `define DONE \ $messagelog(`"%:S Done.`", "Note") `define ASSERT(variable,value) \ if((variable)!=(value)) \ $messagelog(`"%:S Assertion [ variable == value ] was not met.`", "Error") `define ASSERT_ALWAYS(variable,value) \ always @(variable) \ if((variable)!=(value)) \ $messagelog(`"%:S Assertion [ variable == value ] was not met.`", "Error") `define ASSERT_ON_CLK(clk,variable,value) \ always @(clk) \ if((variable)!=(value)) \ $messagelog(`"%:S Assertion [ variable == value @ clk ] was not met.`", "Error") 上記を `include して使うようにしていれば、 ModelSim 以外でシミュレーションする必要が生じたときにも このマクロ定義だけを書き換えれば済みますので、便利だと思います。 * ASSERT マクロ群 [#uc3ec9a3] 本来ならこういったことをするのには OVM とか、 標準の検証ライブラリを使うべきなのでしょうけれど、 使い方を覚えるのが面倒なのに加えて、 記述量を減らしたいという欲求もあって、 上記のようなマクロを書いて使ってしまっています。 ASSERT や ASSERT_ALWAYS などを書くのに SystemVerilog の構文を使っているのですが、 与えた条件からエラーメッセージを自動生成してくれるため、 アサーションを記述するのがとても楽です。 上記 FIFO の例であれば、 LANG:verilog always @(posedge iclk_int) if (full & we) $messagelog("Write strobe was asserted while fifo is full.", "Error") の代わりに LANG:verilog `ASSERT_ON_CLK(posedge iclk_int, full && we, 0); とするだけで、 # ** Error: Assertion [ full && we == 0 @ posedge iclk_int ] was not met. というメッセージが得られます。 これだけだとエラーの発生箇所が分かりませんが、上記の通り Message Viewer を使えば調べられますので、 エラーメッセージはあまり長くしない方が見やすいようです。 * 検証コードをソースに埋め込む [#g854ecdb] 上記のような検証コードはテストベンチに記述しても良いのですが、 ロジックを記述したソースコードに直接埋め込んでおくのが良いようです。 FIFO のソースコード中に LANG:verilog `include "simulation.inc" ... module fifo ( ... ); ... // synthesis translate_off `ASSERT_ON_CLK(posedge iclk_int, full && we, 0); `ASSERT_ON_CLK(posedge oclk_int, empty && re, 0); // synthesis translate_on endmodule のように、synthesis translate_off / synthesis translate_on で挟んで検証コードを埋め込んでおくと、 インプリメント時にはこの部分が無視されるので、 ソースコードを変更することなく検証と合成のどちらも行えます。 *** 注意 [#ybf136d7] 恐らく、この検証コードは Behavior レベルのテストでしか効果がありませんので、 合成結果に対するテストでは別途テストベンチに検証コードを記述する必要があるのだと思います。
Counter: 15248 (from 2010/06/03),
today: 2,
yesterday: 0