SystemCのレポート処理
SystemCのV2.1からレポート出力処理を簡単に制御するためのエラーレポートシステムが標準化されています。
エラーメッセージやトラッキングレポートなど発生元の特定し、デバッグを容易にすることは不可欠です。
メッセージには、Information、Warning、Error、Fatalの4つの種類があるようです。
この4つのメッセージについて出力方法を指定したり、動作を指定したりすることができます。
画面出力やログ出力を簡単に切り替えることができます。
簡単にメモ書きを残します。
エラーメッセージやトラッキングレポートなど発生元の特定し、デバッグを容易にすることは不可欠です。
メッセージには、Information、Warning、Error、Fatalの4つの種類があるようです。
この4つのメッセージについて出力方法を指定したり、動作を指定したりすることができます。
画面出力やログ出力を簡単に切り替えることができます。
簡単にメモ書きを残します。
レポート使いかた1ー簡単な例
以下に簡単な例を紹介。
- サンプル
#include <systemc.h>
const char* sim_name = "test"; // メッセージID名
int sc_main( int argc, char* argv[] )
{
sc_report_handler::set_log_file_name("sample_run.log"); // ログファイル設定
sc_report_handler::stop_after( SC_ERROR, 100 ); // シミュレーション終了指定
sc_report_handler::set_actions( sim_name, SC_INFO, SC_DISPLAY | SC_LOG ); // 動作指定
SC_REPORT_INFO( sim_name, "sample report1" );
sc_start( 100, SC_NS );
SC_REPORT_INFO( sim_name, "sample report2" );
return 0;
}
set_log_file_nameはメッセージを出力するレポートファイル名を指定します。
どこで、そのメッセージが出力されているかのグループ分けのために使用します。
とりあえずはファイル名やモジュール名等を指定するとよいかもしれません。
stop_afterはレポート情報の回数からシミュレーションを停止するタイミングを指定することができます。stop_after( SC_ERROR, 100 )は「ERROR(エラー)」レベルのメッセージの数(SC_REPORT_ERRORの実行回数)が100回となったらシミュレーションを停止させます。ゼロに設定するとdisableです。
今回のサンプルでは意味ないです。
set_actionsはメッセージ処理に対する動作を設定することができます。et_actions( sim_name, SC_INFO, SC_DISPLAY | SC_LOG )は、「INFO(情報)」レベルのメッセージを画面出力とファイル出力に設定しています。
どこで、そのメッセージが出力されているかのグループ分けのために使用します。
とりあえずはファイル名やモジュール名等を指定するとよいかもしれません。
stop_afterはレポート情報の回数からシミュレーションを停止するタイミングを指定することができます。stop_after( SC_ERROR, 100 )は「ERROR(エラー)」レベルのメッセージの数(SC_REPORT_ERRORの実行回数)が100回となったらシミュレーションを停止させます。ゼロに設定するとdisableです。
今回のサンプルでは意味ないです。
set_actionsはメッセージ処理に対する動作を設定することができます。et_actions( sim_name, SC_INFO, SC_DISPLAY | SC_LOG )は、「INFO(情報)」レベルのメッセージを画面出力とファイル出力に設定しています。
- 画面表示
Info: test: sample report1 Info: test: sample report2
標準出力(std::cout)にレポートを出力するにはset_actionsでSC_DISPLAYを設定します。
- レポートファイル出力(sample_run.log)
0 s: Info: test: sample report2 100 ns: Info: test: sample report2
ファイルに出力するには、set_log_file_nameにて出力ファイル名を設定して、かつ、set_actionsにてSC_LOGを設定します。
ファイルへの出力には経過時間も記録されるみたいです。
デフォルトの動作はすべてのメッセージレベルはログ出力となっているので、ログファイル指定するだけで出力されるはずです。
ファイルへの出力には経過時間も記録されるみたいです。
デフォルトの動作はすべてのメッセージレベルはログ出力となっているので、ログファイル指定するだけで出力されるはずです。
レポート使いかた2ー練習用
いろいろ試してみました。
以下にサンプルコードを載せます。実際に使うときはもっときれいに書きたいものです。
以下にサンプルコードを載せます。実際に使うときはもっときれいに書きたいものです。
このサンプルは、レポート処理の動作を見るために作ったものです。
モジュールはMOD1とMOD2があります。
モジュールはそれぞれスレッドを持っていて、定期的にメッセージを出力させています。
モジュールはMOD1とMOD2があります。
モジュールはそれぞれスレッドを持っていて、定期的にメッセージを出力させています。
メッセージの制御は、sc_mainで行います。
はじめの状態は、単にデフォルト設定のままで、ログファイル("sample_run.log")出力するだけです。
コメントアウトされているsc_actionsやsc_stop_afterを有効にすることでメッセージ制御が行えます。
はじめの状態は、単にデフォルト設定のままで、ログファイル("sample_run.log")出力するだけです。
コメントアウトされているsc_actionsやsc_stop_afterを有効にすることでメッセージ制御が行えます。
- サンプルコード(sample_report02.cpp)
#include <systemc.h>
const char* id_name1 = "ID_1";
const char* id_name2 = "ID_2";
SC_MODULE( MOD1 ) {
SC_CTOR( MOD1 ) {
SC_THREAD( thread );
}
void thread() {
int cnt = 0;
while (true) {
++cnt;
wait( 10, SC_NS );
if (cnt%80==0) SC_REPORT_FATAL( id_name1, "sample Fatal1" );
else if (cnt%50==0) SC_REPORT_ERROR( id_name1, "sample Error1" );
else if (cnt%30==0) SC_REPORT_WARNING( id_name1, "sample Warning1" );
else if (cnt%10==0) SC_REPORT_INFO( id_name1, "sample Info1" );
}
}
};
SC_MODULE( MOD2 ) {
SC_CTOR( MOD2 ) {
SC_THREAD( thread );
}
void thread() {
int cnt = 0;
while (true) {
++cnt;
wait( 15, SC_NS );
if (cnt%100==0) SC_REPORT_FATAL( id_name2, "sample Fatal1" );
else if (cnt%70==0) SC_REPORT_ERROR( id_name2, "sample Error1" );
else if (cnt%40==0) SC_REPORT_WARNING( id_name2, "sample Warning1" );
else if (cnt%20==0) SC_REPORT_INFO( id_name2, "sample Info1" );
}
}
};
int sc_main( int argc, char* argv[] )
{
MOD1 mod1("mod1");
MOD2 mod2("mod2");
// 以下、メッセージの制御
sc_report_handler::set_log_file_name("sample_run.log");
//sc_report_handler::set_actions( SC_ERROR, SC_DISPLAY | SC_LOG | SC_CACHE_REPORT );
//sc_report_handler::set_actions( SC_FATAL, SC_DISPLAY | SC_LOG | SC_CACHE_REPORT );
//sc_report_handler::suppress( SC_THROW );
//sc_report_handler::stop_after( SC_FATAL, 10 );
//sc_report_handler::set_actions( SC_INFO, SC_DISPLAY | SC_LOG );
//sc_report_handler::stop_after( SC_FATAL, 10 );
//sc_report_handler::stop_after( SC_ERROR, 10 );
//sc_report_handler::set_actions( id_name1, SC_WARNING, SC_LOG | SC_CACHE_REPORT );
// シミュレーション実行
sc_start( 1., SC_MS );
// シミュレーション終了後の処理
cout << endl;
cout << " ****** end-time = " << sc_time_stamp() << " ******" << endl;
cout << endl;
sc_report *rp = sc_report_handler::get_cached_report();
if (rp) {
cout << "--- Cache Messgage ---" << endl;
cout << rp->get_msg() << endl;
cout << "--- Cache Messgage end ---" << endl;
}
cout << endl;
cout << "--- " << id_name1 << " ---" << endl;
cout << " Info count = " << sc_report_handler::get_count( id_name1, SC_INFO ) << endl;
cout << " Warning count = " << sc_report_handler::get_count( id_name1, SC_WARNING ) << endl;
cout << " Error count = " << sc_report_handler::get_count( id_name1, SC_ERROR ) << endl;
cout << " Fatal count = " << sc_report_handler::get_count( id_name1, SC_FATAL ) << endl;
cout << "--- " << id_name2 << " ---" << endl;
cout << " Info count = " << sc_report_handler::get_count( id_name2, SC_INFO ) << endl;
cout << " Warning count = " << sc_report_handler::get_count( id_name2, SC_WARNING ) << endl;
cout << " Error count = " << sc_report_handler::get_count( id_name2, SC_ERROR ) << endl;
cout << " Fatal count = " << sc_report_handler::get_count( id_name2, SC_FATAL ) << endl;
cout << "--- TOTAL ---" << endl;
cout << " Info count = " << sc_report_handler::get_count( SC_INFO ) << endl;
cout << " Warning count = " << sc_report_handler::get_count( SC_WARNING ) << endl;
cout << " Error count = " << sc_report_handler::get_count( SC_ERROR ) << endl;
cout << " Fatal count = " << sc_report_handler::get_count( SC_FATAL ) << endl;
return 0;
}
- 画面出力例
・・・ Error: ID_1: sample Error1 In file: report_sample02.cpp:15 In process: mod1.thread @ 500 ns ****** end-time = 500 ns ****** --- Cache Messgage --- sample Error1 --- Cache Messgage end --- --- ID_1 --- Info count = 3 Warning count = 1 Error count = 1 Fatal count = 0 --- ID_2 --- Info count = 1 Warning count = 0 Error count = 0 Fatal count = 0 --- TOTAL --- Info count = 4 Warning count = 1 Error count = 1 Fatal count = 0
デフォルトのレポートの動作では、エラーメッセージが表示されると、throwへとばされて、シミュレーションが終了してしまいます。
通常ならば、エラーが出力された時点でシミュレーションが止まっても問題ないと思いますが、継続して実行したい場合もあります。
その時は、以下のような設定をします。
通常ならば、エラーが出力された時点でシミュレーションが止まっても問題ないと思いますが、継続して実行したい場合もあります。
その時は、以下のような設定をします。
sc_report_handler::set_actions( SC_ERROR, SC_DISPLAY | SC_LOG | SC_CACHE_REPORT ); // SC_THROWをはずす
SC_ERRORの動作をデフォルト設定から上書きします。
ためしに設定を有効にして実行してみます。
- 実行結果
・・・ Fatal: ID_1: sample Fatal1 In file: report_sample02.cpp:15 In process: mod1.thread @ 800 ns アボートしました
今度は、Fatalメッセージが出力されると同時に、アボートしてしまいました。
これは、Fatalのデフォルト設定にSC_ABORTが設定されているためです。
先ほどのERROR同様に、SC_ABORTをはずして設定を上書きすれば止まらなくなります。
これは、Fatalのデフォルト設定にSC_ABORTが設定されているためです。
先ほどのERROR同様に、SC_ABORTをはずして設定を上書きすれば止まらなくなります。
sc_report_handler::set_actions( SC_ERROR, SC_DISPLAY | SC_LOG | SC_CACHE_REPORT ); // SC_ABORTをはずす
設定して、実行するとシミュレーションは1ms(sc_startに設定した時間)経過して止まると思います。
今度は、FATALメッセージが10回表示されたら、シミュレーションを終了するようにします。
設定は以下を追加します。
設定は以下を追加します。
sc_report_handler::stop_after( SC_FATAL, 10 );
設定して実行すると、TOTALのFatal count値が10でシミュレーションが終了すると思います。
stop_afterは、IDを指定することもできます。
stop_afterは、IDを指定することもできます。
sc_report_handler::stop_after( id_name2, SC_FATAL, 10 ); // id_name2="ID_2"
上記の設定にして実行すると、ID_2のFATALメッセージが10回表示された時点でシミュレーションが終了すると思います。
すべてのメッセージを画面出力させたくないとき
すべてのメッセージを画面出力させたくないときは、以下を設定します。
sc_report_handler::suppress( SC_DISPLAY );
解除するときは、suppress()を実行すればよいようです。
逆に強制的に画面出力させるときは、force( SC_DISPLAY )とすればよいようです。
逆に強制的に画面出力させるときは、force( SC_DISPLAY )とすればよいようです。
リファレンス
sc_report_handler
次を参照してください。
sc_actions
メッセージに対して動作を指定することができます。
static sc_actions set_actions( sc_severity, sc_actions = SC_UNSPECIFIED );
メッセージレベルごとに動作を指定します。
static sc_actions set_actions( const char* msg_type, sc_actions = SC_UNSPECIFIED );
IDごとに動作を指定します。
static sc_actions set_actions( const char* msg_type, sc_severity, sc_actions = SC_UNSPECIFIED );
メッセージレベルとIDごとに動作を指定します。
sc_report
次を参照してください。
メッセージの分類(レベル)一覧
メッセージには以下のような種類があります。
SC_INFO | 情報出力 |
SC_WARNING | 警告、問題かもしれないことを知らせる |
SC_ERROR | 重大な問題 |
SC_FATAL | 致命的な問題、デフォルトではシミュレーションを終了 |
メッセージ動作一覧
メッセージのレベルごとに動作を指定することができます。
SC_UNSPECIFIED | |
SC_DO_NOTHING | 何もしない |
SC_THROW | レポートとの内容に対応するC++の例外を発生。 |
SC_LOG | レポートをログに出力する。通常はディスク上のファイルへ出力。 |
SC_DISPLAY | レポートを画面出。 |
SC_INTERRUPT | シミュレーションを一時停止。sc_interrupt_hereをよぶ。 |
SC_CACHE_REPORT | レポートのコピーを保存。get_cached_repot()より後に取得できる。 |
SC_STOP | sc_stop()をよぶ。 |
SC_ABORT | sc_abort()をよぶ。 |
デフォルトの動作
デフォルトの動作は次のように設定されているようです。
SC_DEFAULT_INFO_ACTIONS (SC_LOG | SC_DISPLAY) SC_DEFAULT_WARNING_ACTIONS (SC_LOG | SC_DISPLAY) SC_DEFAULT_ERROR_ACTIONS (SC_LOG | SC_CACHE_REPORT | SC_THROW) SC_DEFAULT_FATAL_ACTIONS (SC_LOG | SC_DISPLAY | SC_CACHE_REPORT | SC_ABORT)
全てのメッセージは(ログファイル名が設定されていれば)ファイル出力します。
FATAL時、シミュレーションはアボートします。
FATAL時、シミュレーションはアボートします。
メッセージ表示用マクロ
SC_REPORT_INFO(id,msg) | 情報メッセージに使用 |
SC_REPORT_WARNING(id,msg) | ワーニングメッセージに使用 |
SC_REPORT_ERROR(id,msg) | エラーメッセージに使用 |
SC_REPORT_FATAL(id,msg) | 致命的エラーメッセージに使用 |
sc_assert(expr) | アサート、assertのかわりに使用 |
sc_assertは以下のようにdefine定義されています。
#define sc_assert(expr) \ ((void) ((expr) ? 0 : (SC_REPORT_FATAL( SC_ID_ASSERTION_FAILED_ , #expr ), 0)))
その他
SystemCのログファイルからVCDファイルを生成するツールを作ってみました。
てきとうなので、うまくうごかなかったらごめんなさい。
てきとうなので、うまくうごかなかったらごめんなさい。

- 使いかた
% ./sysclog2vcd.pl <ログファイル名> % gtkwave sysclog.vcd &
以上