SytemCで固定小数点
固定小数点の使い方についてメモしておく。
忘れっぽいので。。。
忘れっぽいので。。。
IEEE1666のLRMを見るとグラフつきでわかりやすいかも。
種類
よく使うのは、sc_fixed、sc_ufixedの2つだけ。
他はあまり使わない。。。
他はあまり使わない。。。
- 高速版、符号付固定小数点
- sc_dt::sc_fixed_fast< W, I, Q, O, N >
- 高速版、符号なし固定小数点
- sc_dt::sc_ufixed_fast< W, I, Q, O, N >
高速版は、32ビットOSにおいて、途中の計算を53ビットに制限して(double)高速化を実現しているらしい。
精度は落ちるかもしれないので、よく検討するべし。
精度は落ちるかもしれないので、よく検討するべし。
- 動的サイズ、高速版:符号付固定小数点
- sc_dt::sc_fix_fast
- 動的サイズ、高速版:符号なし固定小数点
- sc_dt::sc_ufix_fast
sc_fixed(テンプレート型)とsc_fix(テンプレート型)の違いがある。
テンプレート・パラメータ
パラメータ | 値の型 | 説明 |
W | int(正の値) | 全体のビット幅(ワード長) |
I | int | 整数部のビット幅、正負の値が指定できる |
Q | sc_q_mode | 量子化モード(省略可) |
O | sc_o_mode | オーバーフローモード(省略可) |
N | int | オーバーフロー用ビット数(省略可、Oのためのオプション) |
量子化モード(誤差)
第3番目のパラメータで丸め方向を決めることができる。
SC_RND | 正の無限方向への丸め |
SC_RND_ZERO | ゼロ方向への丸め |
SC_RND_MIN_INF | 負の無限方向への丸め |
SC_RND_INF | 無限方向への丸め |
SC_RND_CONV | 収束丸め |
SC_TRN(デフォルト) | 切捨て |
SC_TRN_ZERO | ゼロ方向へ切捨て |
SC_RND
- 正の方向への丸め (rounding to plus infinity)
例)
y = sc_fixed<3,2,SC_RND>(x);
代入前[ x ] | 代入後[ y ] | |
-側 | 0b10.11 (-1.25) | 0b11.0 (-1.0) |
+側 | 0b01.01 ( 1.25) | 0b01.1 ( 1.5) |
LSB-1番目のビットが、1ならば上へ、0ならば下へ。
SC_RND_ZERO
- ゼロ方向への丸め (rounding to zero)
例)
y = sc_fixed<3,2,SC_RND_ZERO>(x);
代入前[ x ] | 代入後[ y ] | |
-側 | 0b10.11 (-1.25) | 0b11.0 (-1.0) |
+側 | 0b01.01 ( 1.25) | 0b01.0 ( 1.0) |
SC_RND_MIN_INF
- マイナス方向への丸め (rounding to minus infinity)
例)
y = sc_fixed<3,2,SC_RND_MIN_ZERO>(x);
代入前[ x ] | 代入後[ y ] | |
-側 | 0b10.11 (-1.25) | 0b10.1 (-1.5) |
+側 | 0b01.01 ( 1.25) | 0b01.0 ( 1.0) |
SC_RND_INF
- 無限方向への丸め (rounding to infinity)
例)
y = sc_fixed<3,2,SC_RND_ZERO>(x);
代入前[ x ] | 代入後[ y ] | |
-側 | 0b10.11 (-1.25) | 0b10.1 (-1.5) |
+側 | 0b01.01 ( 1.25) | 0b01.1 ( 1.5) |
SC_RND_CONV
- 収束丸め (convergent rounding)
例)
y = sc_fixed<3,2,SC_RND_CONV>(x);
代入前[ x ] | 代入後[ y ] | |
-側 | 0b10.11 (-1.25) | 0b11.0 (-1.0) |
+側 | 0b01.01 ( 1.25) | 0b01.0 ( 1.0) |
0b10.11(-1.25) <= x <= 0b11.01(-0.75) | y = 0b11.0(-1.0) |
0b11.10(-0.75) < x < 0b11.11(-0.25) | y = 0b11.1(-0.5) |
0b11.10(-0.25) <= x <= 0b00.01( 0.25) | y = 0b00.0( 0.0) |
0b00.01( 0.25) < x < 0b00.11( 0.75) | y = 0b00.0( 0.5) |
0b00.11( 0.75) <= x <= 0b01.01( 1.25) | y = 0b01.0( 1.0) |
(<=,<=)と(<,<)とが交互。奇数と偶数とで異なる。
Convergent Roundingは特定の用途に用いられるらしい。
Convergent Roundingは特定の用途に用いられるらしい。
SC_TRN (デフォルト)
- 切捨て (truncation)
例)
y = sc_fixed<3,2,SC_TRN>(x);
代入前[ x ] | 代入後[ y ] | |
-側 | 0b10.11 (-1.25) | 0b10.1 (-1.5) |
+側 | 0b01.01 ( 1.25) | 0b01.0 ( 1.0) |
これは、デフォルト。
計算は切捨てなので高速だが、精度が出ない。
精度をあげるならば、SC_RNDを使う。
計算は切捨てなので高速だが、精度が出ない。
精度をあげるならば、SC_RNDを使う。
SC_TRN_ZERO
- ゼロ方向へ切捨て (truncation to zero)
例)
y = sc_fixed<3,2,SC_TRN_ZERO>(x);
代入前[ x ] | 代入後[ y ] | |
-側 | 0b10.11 (-1.25) | 0b11.0 (-1.0) |
+側 | 0b01.01 ( 1.25) | 0b01.0 ( 1.0) |
オーバーフローモード
オーバーフローを起こした場合、4番目と5番目のパラメータにより調整することができる。
種類は、飽和もしくは折り返しがある。
種類は、飽和もしくは折り返しがある。
SC_SAT | 単純飽和 |
SC_SAT_SYM | 対称飽和 |
SC_SAT_ZERO | ゼロ飽和 |
SC_WRAP(デフォルト) | 折り返し |
SC_WRAP_SM | sign magnitude折り返し |
単純飽和は、最大値を超えたら最大値まで減少、最小値を下回ったら最小値まで増加させる。
対称飽和は、最大値側は単純飽和とおなじ。最小値を下回ったら"-最大値"まで増加させる。
ゼロ飽和は、オーバーフローを起こしたら、値をゼロにする。
対称飽和は、最大値側は単純飽和とおなじ。最小値を下回ったら"-最大値"まで増加させる。
ゼロ飽和は、オーバーフローを起こしたら、値をゼロにする。
折り返しは、収まらない上位ビットを削除。
パラメータNでを使用する。
パラメータNでを使用する。
SC_SAT
- 単純飽和
例)
y = sc_fixed<3,3,SC_SAT>(x)
代入前[ x ] | 代入後[ y ] | 備考 | |
-側 | -6 | -4 | オーバーフロー |
-5 | -4 | オーバーフロー | |
-4 | -4 | ||
-3 | -3 | ||
-2 | -2 | ||
-1 | -1 | ||
0 | 0 | ||
1 | 1 | ||
2 | 2 | ||
3 | 3 | ||
4 | 3 | オーバーフロー | |
+側 | 5 | 3 | オーバーフロー |
上限よりも下限の飽和する絶対値は異なることに注意。
SC_SAT_ZERO
- ゼロ飽和
例)
y = sc_fixed<3,3,SC_SAT_ZERO>(x)
代入前[ x ] | 代入後[ y ] | 備考 | |
-側 | -6 | 0 | オーバーフロー |
-5 | 0 | オーバーフロー | |
-4 | -4 | ||
-3 | -3 | ||
-2 | -2 | ||
-1 | -1 | ||
0 | 0 | ||
1 | 1 | ||
2 | 2 | ||
3 | 3 | ||
4 | 0 | オーバーフロー | |
+側 | 5 | 0 | オーバーフロー |
オーバーフローすると、ゼロ値となる。
SC_SAT_SYM
- 対称飽和
例)
y = sc_fixed<3,3,SC_SAT_SYM>(x)
代入前[ x ] | 代入後[ y ] | 備考 | |
-側 | -6 | -3 | オーバーフロー |
-5 | -3 | オーバーフロー | |
-4 | -3 | オーバーフロー | |
-3 | -3 | ||
-2 | -2 | ||
-1 | -1 | ||
0 | 0 | ||
1 | 1 | ||
2 | 2 | ||
3 | 3 | ||
4 | 3 | オーバーフロー | |
+側 | 5 | 3 | オーバーフロー |
-側のオーバーフロー値は、+側の絶対値と同じとなる。
SC_WRAP (デフォルト)
ラップアラウンド。~
- n_bit=0
- n_bit>0
SC_WRAP_SM
符号つき絶対値ラップアラウンド
- n_bits=0
- n_bits>0
固定小数点のコンパイル
SC_INCLUDE_FXをsystemc.hをインクルードする前に定義する必要がある。
これがないと、コンパイルが通らずエラーとなる。
これがないと、コンパイルが通らずエラーとなる。
#define SC_INCLUDE_FX #include "systemc.h"
もしくは、コンパイル時に"-D"で指定する。
-DSC_INCLUDE_FX
関連
SC_FX_EXCLUDE_OTHER
SC_FX_EXCLUDE_OTHER
使い方例
オーバーフロー有無の確認
sc_fixed<4,4> a(1.0); // ワード長4ビット,整数4ビット
sc_fixed<4,4> b(1.0);
sc_fixed<4,4> c(8.0);
sc_fixed<4,4> d(8.0);
sc_fixed<4,4> z;
cout << "o_flag = " << z.overflow_flag() << endl;
z = a * b; // 1.0 x 1.0 => 1.0 : オーバーフローなし
cout << "z = " << z << endl;
cout << "o_flag = " << z.overflow_flag() << endl;
z = c * d; // 8.0 x 8.0 => 64.0 : オーバーフロー発生
cout << "z = " << z << endl;
cout << "o_flag = " << z.overflow_flag() << endl;
- 結果
o_flag = 0 z = 1 o_flag = 0 z = 0 o_flag = 1 <= オーバーフロー発生を確認
固定小数点<==>sc_uint変換
よさそうな方法が思いつかないので、とりあえず。
- sc_fixed<> ==> sc_uint<>変換
sc_fixed<4,2> 1(1.25); // 1.25 (0b01.01)
sc_uint<4> x, y;
x = a; // 1.00 (0b00001), 整数部のみを代入
y = a.range( a.wl()-1, 0 ); // 5 (0b00101), ビット列を単純代入
- sc_uint<> ==> sc_fixed<>変換
sc_uint<4> a(5); // 5 (0b00101)
sc_fixed<6,4> x;
sc_fixed<4,2> y;
x = a; // 5.00 (0b0101.00), 整数として代入
y.range( y.wl()-1, 0 ) = a; // 1.25 (0b01.01), ビット列を単純代入