bambooflow Note

レポート処理

最終更新:

Bot(ページ名リンク)

- view
メンバー限定 登録/ログイン

SystemCのレポート処理



SystemCのV2.1からレポート出力処理を簡単に制御するためのエラーレポートシステムが標準化されています。
エラーメッセージやトラッキングレポートなど発生元の特定し、デバッグを容易にすることは不可欠です。
メッセージには、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(情報)」レベルのメッセージを画面出力とファイル出力に設定しています。


  • 画面表示
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があります。
モジュールはそれぞれスレッドを持っていて、定期的にメッセージを出力させています。

メッセージの制御は、sc_mainで行います。
はじめの状態は、単にデフォルト設定のままで、ログファイル("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をはずして設定を上書きすれば止まらなくなります。
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を指定することもできます。
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 )とすればよいようです。



リファレンス

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時、シミュレーションはアボートします。


メッセージ表示用マクロ


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
  • 使いかた
% ./sysclog2vcd.pl <ログファイル名>
% gtkwave sysclog.vcd &

以上
記事メニュー
ウィキ募集バナー