SC_CTHREADを活かすためにsc_signalに拡張を試みた話

私が嫌い苦手な SC_CTHREADを使えるように出来ないかなと思い、
sc_signalへの拡張をトライしてみました。っていうお話です。
先に結論だけ書いておくと、面倒臭くなって拡張断念しました。

背景

なぜ SC_CTHREADが嫌い苦手かというと、抽象度が低いからになります。
では、抽象度が高ければどうなのか?
抽象度がもし高ければ、リセット部分と動作部分が分離されるので、
意外に使えるのではないかと思ってます。

では、抽象度を上げるためにどうすればいいか?
一つの答えが、sensitive リストへの信号をクロックにしなければいいと思いました。

つまり、

SC_CTHREAD(a_cthread, clk.pos());

部分が、

SC_CTHREAD(a_cthread, hoge.event());

みたいになれば、クロック・ドリブンというよりイベント・ドリブンなプロセスに
なると思ったからです。

なぜ sc_signalを拡張対象に?

SC_THREADやSC_METHODは

sensitive << sc_event

といった sc_eventを登録するのですが、SC_CTHREADは sc_event_finderを使います。
そのため、拡張するなら sc_eventではなく sc_signalのほうが良いと判断しました。

  • sc_event_finder and sc_event_finder_tのクラス定義
class sc_event_finder implementation-defined ;

template <class IF>
class sc_event_finder_t
: public sc_event_finder
{
  public:
    sc_event_finder_t( const sc_port_base& port_, const sc_event& (IF::*event_method_) () const );
     // Other members
    implementation-defined
};

クラス定義を見てもらえば分かるのですが、Interface部分が必要になってます。
sc_signalだと以下のように諸々入っているので OKかなと思ったわけです。

f:id:kocha2012:20121220003438p:plain

sc_signalを拡張する

my_sc_signalクラスにて、pos(), neg()を追加するようなコードを書いてみました。
SystemCのライブラリを覗いてみるとわかるのですが、bool型だけ部分特殊化を使って
個別に定義してあることが多いので、今回は sc_signal<bool>部分を継承してみました。

  • my_sc_signal.h
#include <systemc.h>

class my_sc_signal : public sc_signal<bool> {

public:
    // constructors
    my_sc_signal()
    : m_neg_finder_p(0), m_pos_finder_p(0)
    {}
 
    // destructor
    virtual ~my_sc_signal()
    {
        delete m_neg_finder_p;
        delete m_pos_finder_p;
    }

    // use for positive edge sensitivity
    sc_event_finder& pos() const
    {
        if ( !m_pos_finder_p )
    {
        m_pos_finder_p = new sc_event_finder_t<if_type>(
            *this, &if_type::posedge_event );
    } 
    return *m_pos_finder_p;
    }

    // use for negative edge sensitivity
    sc_event_finder& neg() const
    {
        if ( !m_neg_finder_p )
    {
        m_neg_finder_p = new sc_event_finder_t<if_type>(
            *this, &if_type::negedge_event );
    } 
    return *m_neg_finder_p;
    }

private:
    mutable sc_event_finder* m_neg_finder_p;
    mutable sc_event_finder* m_pos_finder_p;

};

my_sc_signalを作ったところで、コンパイルしてみると以下のようなエラーが出ます。

my_sc_signal.h:24: error: no matching function for call to 
  'sc_core::sc_event_finder_t >
  ::sc_event_finder_t(const my_sc_signal&, const sc_core::sc_event& (
  sc_core::sc_signal_in_if::*)()const)'
...
my_sc_signal.h:35: error: no matching function for call to
  'sc_core::sc_event_finder_t >
  ::sc_event_finder_t(const my_sc_signal&, const sc_core::sc_event& (
  sc_core::sc_signal_in_if::*)()const)'

なにを言っているんだ。。。

そ、そんなバカな。。。

恐る恐る sc_event_finder_tのクラス定義を見ると、

sc_event_finder_t( const sc_port_base& port_, const sc_event& (IF::*event_method_) () const );

第一引数が sc_port_baseになっていますね。
はい。sc_signalは sc_port_baseは継承していません。。。
sc_portだと、モジュールの外との接続が必須になるので、それは嫌だなと。
なんてこったい(´・ω・`)

というような絶望を味わいファントムへ。。。

まとめ

SC_CTHREADが嫌い苦手だが、リセット部分と動作部分をわかりやすく?
記述出来るので、抽象度を上げるために内部で活用出来る信号(イベント)を
定義しようとしたが、sc_port に阻まれて面倒臭くなって止めたというお話でした。

※本記事が愚痴みたいになってしまったかもしれませんが、
 そういう訳ではなく、SC_CTHREADがどう作られているか?
 また、sc_event_finderとは何か?など感じてもらえればと思って書いてます。

次回は衝撃的な展開が待ってます。