gdb で sc_uintの加算の仕組みを見てみよう

データ型について今週は見ていったので、もう少し。

  • サンプルコード
#include <stdio.h>
#include <systemc.h>

int main (int argc, char* argv[]) {

  sc_uint<8> a,b;
  sc_uint<9> c;

  a = 2; b = 30;
  c = a + b;

  cout << "a = " << a.to_string() 
       << ", b = " << b.to_string() 
       << ", c = " << c.to_string()
       << endl; 

  return 0;
}

gdbで c = a + b;部分をブレークポイントに設定しステップ実行。
下記はそのログになります。

$> gdb main
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
http://bugs.launchpad.net/gdb-linaro/...
Reading symbols from /xxx/main...done.
(gdb) b 10
Breakpoint 1 at 0x804b10e: file main.cpp, line 10.
(gdb) r
Starting program: /xxx/main 

Breakpoint 1, main (argc=1, argv=0xbffff024) at main.cpp:10
10    c = a + b;
(gdb) s
sc_dt::sc_uint_base::operator unsigned long long (this=0xbfffef40)
    at /usr/local/lib/systemc-2.2.0/include/sysc/datatypes/int/sc_uint_base.h:783
783     { return m_val; }
(gdb) 
sc_dt::sc_uint_base::operator unsigned long long (this=0xbfffef2c)
    at /usr/local/lib/systemc-2.2.0/include/sysc/datatypes/int/sc_uint_base.h:783
783     { return m_val; }
(gdb) 
sc_dt::sc_uint<9>::operator= (this=0xbfffef18, v=32)
    at /usr/local/lib/systemc-2.2.0/include/sysc/datatypes/int/sc_uint.h:185
185     { sc_uint_base::operator = ( v ); return *this; }
(gdb) 
sc_dt::sc_uint_base::operator= (this=0xbfffef18, v=32)
    at /usr/local/lib/systemc-2.2.0/include/sysc/datatypes/int/sc_uint_base.h:589
589     { m_val = v; extend_sign(); return *this; }
(gdb) 
sc_dt::sc_uint_base::extend_sign (this=0xbfffef18)
    at /usr/local/lib/systemc-2.2.0/include/sysc/datatypes/int/sc_uint_base.h:542
542         m_val &= ( ~UINT_ZERO >> m_ulen );
(gdb) 
543     }
(gdb) 
main (argc=1, argv=0xbffff024) at main.cpp:15
15         << endl; 
(gdb) 
a = 2, b = 30, c = 32
17    return 0;

メモ

sc_uintのクラスはoperator+のオーバーロードをしていないようです。
上を見ると加算の前にuint_type(自分の環境だとunsigned long long)の キャスト演算子オーバーロードが行われていて、sc_uint_baseのメンバであるm_valが戻されている。
ちなみにm_valは値が格納されていて型はuint_type。

つまり足し算とかは普通の組み込み型でやってるようだ。
しかし、sc_biguintは対応出来型がないので、加算のオーバーロードを定義している。
だから、sc_uintはsc_biguintより早いのかな。

※組み込み型へのキャスト演算子は「組み込み型を必要としている文中で、ユーザ定義型が使われているときに呼び出される」(別に組み込み型だけに限った話ではないが。)

ちなみに、sc_biguint<>でやるとこのような感じですが、
詳細を見る際には SystemCをインストールする際に -g を付ける必要があります。
C++側に実装されています。

Breakpoint 1, main (argc=1, argv=0xbffff024) at main.cpp:10
10	  c = a + b;
(gdb) s
sc_dt::sc_biguint<9>::operator= (this=0xbfffef18, v=...)
    at /usr/local/lib/systemc-2.2.0/include/sysc/datatypes/int/sc_biguint.h:195
195		{ sc_unsigned::operator = ( v ); return *this; }
(gdb) 
sc_dt::sc_unsigned::~sc_unsigned (this=0xbfffef04, __in_chrg=<optimized out>)
    at /usr/local/lib/systemc-2.2.0/include/sysc/datatypes/int/sc_unsigned.h:1045
1045		{
(gdb) 
1047		        delete [] digit;
(gdb) 
1049		}
(gdb) 
sc_dt::sc_value_base::~sc_value_base (this=0xbfffef04, __in_chrg=<optimized out>)
    at /usr/local/lib/systemc-2.2.0/include/sysc/datatypes/misc/sc_value_base.h:80
80	    virtual ~sc_value_base() {};
(gdb) 
main (argc=1, argv=0xbffff024) at main.cpp:15
15	       << endl; 
(gdb) 
a = 2, b = 30, c = 32
17	  return 0;
(gdb)