2018年5月23日水曜日

SystemC で全信号の sc_trace() をなるべく楽にする方法(2)

以前「インスタンス階層ツリーを出してくれる機能はなさげ」と書いたけど,SystemC の全信号を階層付きでリストアップする方法はあることがわかった.
Why sc_object menber function trace() deprecated?
ただしリンク先にもあるように,一発で全信号を波形ダンプする方法があるわけではない.
# 信号名の一覧が取得できるだけ
しかし階層付きの信号一覧取得できれば,ほぼ目的は達成したと言って良い.というわけでコード.
void all_trace( sc_trace_file *tf, std::vector<sc_object*>& children ){
for( std::vector<sc_object*>::iterator i = children.begin(); i != children.end(); ++i ){
if ( std::string(( *i )->kind()) == "sc_module" ){
sc_module* mptr = dynamic_cast<sc_module*>(*i);
std::vector<sc_object*> r_children = mptr->get_child_objects();
all_trace(tf, r_children);
}else if(
std::string(( *i )->kind()) == "sc_in"
|| std::string(( *i )->kind()) == "sc_out"
|| std::string(( *i )->kind()) == "sc_inout"
|| std::string(( *i )->kind()) == "sc_signal"
){
cout << ( *i )->name() << '\n';
}
}
}
int sc_main( int argc, char **argv ){
sc_trace_file *ScppTraceFile = sc_create_vcd_trace_file( "simple_dma" );
ScppTraceFile->set_time_unit( 1.0, SC_NS );
// ...
sim_top sim_top0( "sim_top0" );
#ifdef LIST_ALL_SIGNAL
std::vector<sc_object*> top = sc_get_top_level_objects();
all_trace( ScppTraceFile, top );
exit( 0 );
#else
#include "trace_all_signal.h"
#endif
// ...
}

最初に -DLIST_ALL_SIGNAL 付きでコンパイルして実行すると信号一覧が取得できる.それをスクリプトで適当に sc_trace() のコードに変換して trace_all_signal.h を生成する.あとは -DLIST_ALL_SIGNAL なしでコンパイル・実行すれば全信号のトレース付きで sim 実行される.
↓取得できる信号一覧
sim_top0.port_0
sim_top0.signal_0
sim_top0.signal_1
...
sim_top0.SimpleDma0.clk
sim_top0.SimpleDma0.nrst
sim_top0.SimpleDma0.RegAddr
sim_top0.SimpleDma0.RegWData
...
sim_top0.SimpleDma0.u_SimpleDmaReg(0).clk
sim_top0.SimpleDma0.u_SimpleDmaReg(0).nrst
sim_top0.SimpleDma0.u_SimpleDmaReg(0).Addr
view raw exec.log hosted with ❤ by GitHub
sc_trace( ScppTraceFile, sim_top0.port_0, "sim_top0.port_0" );
sc_trace( ScppTraceFile, sim_top0.signal_0, "sim_top0.signal_0" );
sc_trace( ScppTraceFile, sim_top0.signal_1, "sim_top0.signal_1" );
...
sc_trace( ScppTraceFile, sim_top0->SimpleDma0.clk, "sim_top0.SimpleDma0.clk" );
sc_trace( ScppTraceFile, sim_top0->SimpleDma0.nrst, "sim_top0.SimpleDma0.nrst" );
sc_trace( ScppTraceFile, sim_top0->SimpleDma0.RegAddr, "sim_top0.SimpleDma0.RegAddr" );
sc_trace( ScppTraceFile, sim_top0->SimpleDma0.RegWData, "sim_top0.SimpleDma0.RegWData" );
...
sc_trace( ScppTraceFile, sim_top0->SimpleDma0->u_SimpleDmaReg[0].clk, "sim_top0.SimpleDma0.u_SimpleDmaReg(0).clk" );
sc_trace( ScppTraceFile, sim_top0->SimpleDma0->u_SimpleDmaReg[0].nrst, "sim_top0.SimpleDma0.u_SimpleDmaReg(0).nrst" );
sc_trace( ScppTraceFile, sim_top0->SimpleDma0->u_SimpleDmaReg[0].Addr, "sim_top0.SimpleDma0.u_SimpleDmaReg(0).Addr" );
↑生成した trace_all_signal.h

前回の方法は,全モジュールに sc_trace() を埋め込むので記述が分散してそれなりに手間だが,今回の方法は 1箇所の記述で対応できるので楽といえば楽.

ただし,信号の配列の場合やメンバイニシャライザで信号名していない場合,取得した信号名はテンポラリな名前になってしまうため C++ 上の変数名と不一致を起こしコンパイルエラーになってしまう (上の例でいうと,sim_top0.signal_0 は存在せず,そのような変数名は trace_all_sighal.h から省かなければならない).

●各モジュールに sc_trace() 埋め込み
◎全信号をもれなくトレース可能
◎配列信号でも,正確な信号名を設定できる
×記述が分散する
×信号の増減は所詮手動で対応しなければならない

●全信号自動リストアップ
◎信号の増減に自動的に対応できる
◎1箇所にコードがまとまるのでメンテが楽
×2回コンパイルが必要
×name 設定していない (出来ない) 信号のトレース不可

楽さを取るか,もれなく信号をダンプするか.悩ましいところだなぁ.

0 件のコメント:

コメントを投稿