bambooflow Note

ユーザデータタイプ

最終更新:

bambooflow

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

SystemCでユーザデータタイプを使う


sc_signal<>やsc_buffer<>を介したデータやりとりは、既に定義されたbool,int,sc_int<>等は問題なく使うことができます。
しかし、ユーザが独自に構造体を定義して、それを受渡しする場合問題が生じる。
ここでは、sc_signal<>もしくはsc_buffer<>でユーザデータタイプを使用する方法をメモします。

ユーザデータタイプを使うときの問題


次のコードを見てください。

struct StrData {
    bool valid;
    int  data;
 };
 
 int sc_main( int, char** ) {
     sc_signal<StrData> sig;
 }
 

上記をコンパイルしようとすると、次のようなエラーが発生します。

/usr/local/systemc-2.2.0/include/sysc/communication/sc_signal.h: In member function ‘void sc_core::sc_signal<IF>::write(const T&) [with T = StrData]’: main.cpp:119: instantiated from here /usr/local/systemc-2.2.0/include/sysc/communication/sc_signal.h:221: error: no match for ‘operator==’ in ‘((sc_core::sc_signal<StrData>*)this)->sc_core::sc_signal<StrData>::m_new_val == ((sc_core::sc_signal<StrData>*)this)->sc_core::sc_signal<StrData>::m_cur_val’ ・・・ ・・・
はじめなんじゃこりゃってなりますが、‘operator==’がどうやら足りないというメッセージのようです。
なにか工夫をしないといけないようです。


ユーザデータタイプを使うための解決


ユーザデータタイプをsc_signal<>やsc_buffer<>で使う場合は、次の3つを定義してあげます。
  1. bool operator==()
  2. sc_trace()
  3. ostream& operator<<()

具体的には、次のように修正します。

struct StrData {
    bool valid;
    int  data;
 
    // sc_signal<>で使う
    bool operator==(const StrData& other) const {
        return ( (valid == other.valid)
            && (data == other.data) );
    }   
};
 
// トレース時使用する
void sc_trace( sc_trace_file*& tf, const StrData& trans, std::string name )
{
    sc_trace( tf, trans.valid, name + ".valid" );
    sc_trace( tf, trans.data, name + ".data" );
}
 
// SystemCで使う
ostream& operator<<( ostream& os, const StrData& trans )
{
    os << "(" << trans.valid << ", " << trans.data << ")";
    return os;
}
 
int sc_main( int, char** ) {
    sc_signal<StrData> sig;
}
 

構造体1つを扱うのにこれだけ定義が増えるのはちょっと面倒臭いですが、これもSystemCの仕様なのでしかたないです。

ここで、operator==はちゃんと書かないとダメですが、sc_trace()とoperator<<()の関数の中身は、ないと不便なだけで書かなくてもコンパイルできます。
面倒臭いときは、わたしは省略しちゃいます。


bool operator==()はなぜ必要?


次のコードを見てください。

SC_MODULE(MOD)
{
    sc_in<StrData>  din;
 
    SC_CTOR(MOD) {
        SC_METHOD( method );
        sensitive << din;      // dinが変化したとき
    }
    void method() {
        std::cout << "din = " << din.read() << std::endl;
    }
};
 

メソッドであるmethod()がよばれるのは、sensitive<<dinよりdinが変化したときであるとわかります。
「変化した」というのをSystemCではどうやって判断しているかというと内部で"=="で比較しています。なので"=="で比較できるというのが前提でSystemCが設計されているので、ないとコンパイル時に"operator==が無い"と怒られるわけです。
SystemCデータタイプであるsc_int<>やsc_fixed<>はちゃんとoperator==が定義されているので、そんなことは気にしなくても使えます。


テンプレートを使用したユーザデータタイプの場合


次のようなテンプレートを使ったデータタイプを見てみます。

template <typename DT, int N>
struct Payload {
    bool w_flag;
    int  address;
    DT   data[N];
};
 


次のように修正します。

template <typename DT, int N>
struct Payload {
    bool w_flag;
    int  address;
    DT   data[N];
 
    // sc_signal<> で必要
    template<typename ODT,int ON>
    bool operator==( const Payload<ODT,ON>& other) const {
        bool ret;
        ret = (w_flag == other.w_flag)
            && (address == other.address);
        for (int i=0; i<N; i++)
            ret = ret && (data[i] == other.data[i]);
        return ret;
    }
};
 
// トレースで必要
template <typename DT, int N>
void sc_trace( sc_trace_file*& tf, const Payload<DT,N>& trans, std::string name )
{
    sc_trace( tf, trans.w_flag, name + ".w_flag" );
    sc_trace( tf, trans.address, name + ".address" );
    for (int i=0; i<N; i++) {
        std::ostringstream oss;
        oss << name << ".data_" << i;
        sc_trace( tf, trans.address, oss.str() );
    }
}
 
// SystemCで必要
template <typename DT, int N>
ostream& operator<<( ostream& os, const Payload<DT,N>& trans )
{
    os << "("
        << trans.w_flag << ", "
        << trans.address << ", ";
    for (int i=0; i<N; i++)
        os << (int)trans.data[i] << ", ";
    os << ")";
    return os;
}
 
記事メニュー
目安箱バナー