00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #ifndef SCFX_IEEE_H
00046 #define SCFX_IEEE_H
00047
00048
00049 #include "sysc/datatypes/fx/sc_fxdefs.h"
00050
00051
00052 namespace sc_dt
00053 {
00054
00055
00056 union ieee_double;
00057 class scfx_ieee_double;
00058 union ieee_float;
00059 class scfx_ieee_float;
00060
00061
00062
00063
00064
00065
00066
00067
00068 union ieee_double
00069 {
00070
00071 double d;
00072
00073 struct
00074 {
00075 #if defined( SC_BIG_ENDIAN )
00076 unsigned negative:1;
00077 unsigned exponent:11;
00078 unsigned mantissa0:20;
00079 unsigned mantissa1:32;
00080 #elif defined( SC_LITTLE_ENDIAN )
00081 unsigned mantissa1:32;
00082 unsigned mantissa0:20;
00083 unsigned exponent:11;
00084 unsigned negative:1;
00085 #endif
00086 } s;
00087
00088 };
00089
00090
00091 const unsigned int SCFX_IEEE_DOUBLE_BIAS = 1023U;
00092
00093 const int SCFX_IEEE_DOUBLE_E_MAX = 1023;
00094 const int SCFX_IEEE_DOUBLE_E_MIN = -1022;
00095
00096 const unsigned int SCFX_IEEE_DOUBLE_M_SIZE = 52;
00097
00098
00099
00100
00101
00102
00103
00104
00105 class scfx_ieee_double
00106 {
00107
00108 ieee_double m_id;
00109
00110 public:
00111
00112 scfx_ieee_double();
00113 scfx_ieee_double( double );
00114 scfx_ieee_double( const scfx_ieee_double& );
00115
00116 scfx_ieee_double& operator = ( double );
00117 scfx_ieee_double& operator = ( const scfx_ieee_double& );
00118
00119 operator double() const;
00120
00121 unsigned int negative() const;
00122 void negative( unsigned int );
00123 int exponent() const;
00124 void exponent( int );
00125 unsigned int mantissa0() const;
00126 void mantissa0( unsigned int );
00127 unsigned int mantissa1() const;
00128 void mantissa1( unsigned int );
00129
00130 bool is_zero() const;
00131 bool is_subnormal() const;
00132 bool is_normal() const;
00133 bool is_inf() const;
00134 bool is_nan() const;
00135
00136 void set_inf();
00137 void set_nan();
00138
00139 int msb() const;
00140 int lsb() const;
00141
00142 static const scfx_ieee_double nan();
00143 static const scfx_ieee_double inf( int );
00144
00145 };
00146
00147
00148
00149
00150 inline
00151 scfx_ieee_double::scfx_ieee_double()
00152 {
00153 m_id.d = 0.0;
00154 }
00155
00156 inline
00157 scfx_ieee_double::scfx_ieee_double( double d )
00158 {
00159 m_id.d = d;
00160 }
00161
00162 inline
00163 scfx_ieee_double::scfx_ieee_double( const scfx_ieee_double& a )
00164 {
00165 m_id.d = a.m_id.d;
00166 }
00167
00168
00169 inline
00170 scfx_ieee_double&
00171 scfx_ieee_double::operator = ( double d )
00172 {
00173 m_id.d = d;
00174 return *this;
00175 }
00176
00177 inline
00178 scfx_ieee_double&
00179 scfx_ieee_double::operator = ( const scfx_ieee_double& a )
00180 {
00181 m_id.d = a.m_id.d;
00182 return *this;
00183 }
00184
00185
00186 inline
00187 scfx_ieee_double::operator double() const
00188 {
00189 return m_id.d;
00190 }
00191
00192
00193 inline
00194 unsigned int
00195 scfx_ieee_double::negative() const
00196 {
00197 return m_id.s.negative;
00198 }
00199
00200 inline
00201 void
00202 scfx_ieee_double::negative( unsigned int a )
00203 {
00204 m_id.s.negative = a;
00205 }
00206
00207 inline
00208 int
00209 scfx_ieee_double::exponent() const
00210 {
00211 return m_id.s.exponent - SCFX_IEEE_DOUBLE_BIAS;
00212 }
00213
00214 inline
00215 void
00216 scfx_ieee_double::exponent( int a )
00217 {
00218 m_id.s.exponent = SCFX_IEEE_DOUBLE_BIAS + a;
00219 }
00220
00221 inline
00222 unsigned int
00223 scfx_ieee_double::mantissa0() const
00224 {
00225 return m_id.s.mantissa0;
00226 }
00227
00228 inline
00229 void
00230 scfx_ieee_double::mantissa0( unsigned int a )
00231 {
00232 m_id.s.mantissa0 = a;
00233 }
00234
00235 inline
00236 unsigned int
00237 scfx_ieee_double::mantissa1() const
00238 {
00239 return m_id.s.mantissa1;
00240 }
00241
00242 inline
00243 void
00244 scfx_ieee_double::mantissa1( unsigned int a )
00245 {
00246 m_id.s.mantissa1 = a;
00247 }
00248
00249
00250 inline
00251 bool
00252 scfx_ieee_double::is_zero() const
00253 {
00254 return ( exponent() == SCFX_IEEE_DOUBLE_E_MIN - 1 &&
00255 mantissa0() == 0U && mantissa1() == 0U );
00256 }
00257
00258 inline
00259 bool
00260 scfx_ieee_double::is_subnormal() const
00261 {
00262 return ( exponent() == SCFX_IEEE_DOUBLE_E_MIN - 1 &&
00263 ( mantissa0() != 0U || mantissa1() != 0U ) );
00264 }
00265
00266 inline
00267 bool
00268 scfx_ieee_double::is_normal() const
00269 {
00270 return ( exponent() >= SCFX_IEEE_DOUBLE_E_MIN &&
00271 exponent() <= SCFX_IEEE_DOUBLE_E_MAX );
00272 }
00273
00274 inline
00275 bool
00276 scfx_ieee_double::is_inf() const
00277 {
00278 return ( exponent() == SCFX_IEEE_DOUBLE_E_MAX + 1 &&
00279 mantissa0() == 0U && mantissa1() == 0U );
00280 }
00281
00282 inline
00283 bool
00284 scfx_ieee_double::is_nan() const
00285 {
00286 return ( exponent() == SCFX_IEEE_DOUBLE_E_MAX + 1 &&
00287 ( mantissa0() != 0U || mantissa1() != 0U ) );
00288 }
00289
00290
00291 inline
00292 void
00293 scfx_ieee_double::set_inf()
00294 {
00295 exponent( SCFX_IEEE_DOUBLE_E_MAX + 1 );
00296 mantissa0( 0U );
00297 mantissa1( 0U );
00298 }
00299
00300 inline
00301 void
00302 scfx_ieee_double::set_nan()
00303 {
00304 exponent( SCFX_IEEE_DOUBLE_E_MAX + 1 );
00305 mantissa0( (unsigned int) -1 );
00306 mantissa1( (unsigned int) -1 );
00307 }
00308
00309
00310 #define MSB_STATEMENT(x,n) if( x >> n ) { x >>= n; i += n; }
00311
00312 inline
00313 int
00314 scfx_ieee_double::msb() const
00315 {
00316 unsigned int m0 = mantissa0();
00317 unsigned int m1 = mantissa1();
00318 if( m0 != 0 )
00319 {
00320 int i = 0;
00321 MSB_STATEMENT(m0,16);
00322 MSB_STATEMENT(m0,8);
00323 MSB_STATEMENT(m0,4);
00324 MSB_STATEMENT(m0,2);
00325 MSB_STATEMENT(m0,1);
00326 return ( i - 20 );
00327 }
00328 else if( m1 != 0 )
00329 {
00330 int i = 0;
00331 MSB_STATEMENT(m1,16);
00332 MSB_STATEMENT(m1,8);
00333 MSB_STATEMENT(m1,4);
00334 MSB_STATEMENT(m1,2);
00335 MSB_STATEMENT(m1,1);
00336 return ( i - 52 );
00337 }
00338 else
00339 {
00340 return 0;
00341 }
00342 }
00343
00344 #undef MSB_STATEMENT
00345
00346 #define LSB_STATEMENT(x,n) if( x << n ) { x <<= n; i -= n; }
00347
00348 inline
00349 int
00350 scfx_ieee_double::lsb() const
00351 {
00352 unsigned int m0 = mantissa0();
00353 unsigned int m1 = mantissa1();
00354 if( m1 != 0 )
00355 {
00356 int i = 31;
00357 LSB_STATEMENT(m1,16);
00358 LSB_STATEMENT(m1,8);
00359 LSB_STATEMENT(m1,4);
00360 LSB_STATEMENT(m1,2);
00361 LSB_STATEMENT(m1,1);
00362 return ( i - 52 );
00363 }
00364 else if( m0 != 0 )
00365 {
00366 int i = 31;
00367 LSB_STATEMENT(m0,16);
00368 LSB_STATEMENT(m0,8);
00369 LSB_STATEMENT(m0,4);
00370 LSB_STATEMENT(m0,2);
00371 LSB_STATEMENT(m0,1);
00372 return ( i - 20 );
00373 }
00374 else
00375 {
00376 return 0;
00377 }
00378 }
00379
00380 #undef LSB_STATEMENT
00381
00382
00383 inline
00384 const scfx_ieee_double
00385 scfx_ieee_double::nan()
00386 {
00387 scfx_ieee_double id;
00388 id.set_nan();
00389 return id;
00390 }
00391
00392 inline
00393 const scfx_ieee_double
00394 scfx_ieee_double::inf( int sign )
00395 {
00396 scfx_ieee_double id( sign );
00397 id.set_inf();
00398 return id;
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408 union ieee_float
00409 {
00410
00411 float f;
00412
00413 struct
00414 {
00415 #if defined( SC_BIG_ENDIAN )
00416 unsigned negative:1;
00417 unsigned exponent:8;
00418 unsigned mantissa:23;
00419 #elif defined( SC_LITTLE_ENDIAN )
00420 unsigned mantissa:23;
00421 unsigned exponent:8;
00422 unsigned negative:1;
00423 #endif
00424 } s;
00425
00426 };
00427
00428
00429 const unsigned int SCFX_IEEE_FLOAT_BIAS = 127U;
00430
00431 const int SCFX_IEEE_FLOAT_E_MAX = 127;
00432 const int SCFX_IEEE_FLOAT_E_MIN = -126;
00433
00434 const unsigned int SCFX_IEEE_FLOAT_M_SIZE = 23;
00435
00436
00437
00438
00439
00440
00441
00442
00443 class scfx_ieee_float
00444 {
00445
00446 ieee_float m_if;
00447
00448 public:
00449
00450 scfx_ieee_float();
00451 scfx_ieee_float( float );
00452 scfx_ieee_float( const scfx_ieee_float& );
00453
00454 scfx_ieee_float& operator = ( float );
00455 scfx_ieee_float& operator = ( const scfx_ieee_float& );
00456
00457 operator float() const;
00458
00459 unsigned int negative() const;
00460 void negative( unsigned int );
00461 int exponent() const;
00462 void exponent( int );
00463 unsigned int mantissa() const;
00464 void mantissa( unsigned int );
00465
00466 bool is_zero() const;
00467 bool is_subnormal() const;
00468 bool is_normal() const;
00469 bool is_inf() const;
00470 bool is_nan() const;
00471
00472 void set_inf();
00473 void set_nan();
00474
00475 };
00476
00477
00478
00479
00480 inline
00481 scfx_ieee_float::scfx_ieee_float()
00482 {
00483 m_if.f = 0.0;
00484 }
00485
00486 inline
00487 scfx_ieee_float::scfx_ieee_float( float f )
00488 {
00489 m_if.f = f;
00490 }
00491
00492 inline
00493 scfx_ieee_float::scfx_ieee_float( const scfx_ieee_float& a )
00494 {
00495 m_if.f = a.m_if.f;
00496 }
00497
00498
00499 inline
00500 scfx_ieee_float&
00501 scfx_ieee_float::operator = ( float f )
00502 {
00503 m_if.f = f;
00504 return *this;
00505 }
00506
00507 inline
00508 scfx_ieee_float&
00509 scfx_ieee_float::operator = ( const scfx_ieee_float& a )
00510 {
00511 m_if.f = a.m_if.f;
00512 return *this;
00513 }
00514
00515
00516 inline
00517 scfx_ieee_float::operator float() const
00518 {
00519 return m_if.f;
00520 }
00521
00522
00523 inline
00524 unsigned int
00525 scfx_ieee_float::negative() const
00526 {
00527 return m_if.s.negative;
00528 }
00529
00530 inline
00531 void
00532 scfx_ieee_float::negative( unsigned int a )
00533 {
00534 m_if.s.negative = a;
00535 }
00536
00537 inline
00538 int
00539 scfx_ieee_float::exponent() const
00540 {
00541 return m_if.s.exponent - SCFX_IEEE_FLOAT_BIAS;
00542 }
00543
00544 inline
00545 void
00546 scfx_ieee_float::exponent( int a )
00547 {
00548 m_if.s.exponent = SCFX_IEEE_FLOAT_BIAS + a;
00549 }
00550
00551 inline
00552 unsigned int
00553 scfx_ieee_float::mantissa() const
00554 {
00555 return m_if.s.mantissa;
00556 }
00557
00558 inline
00559 void
00560 scfx_ieee_float::mantissa( unsigned int a )
00561 {
00562 m_if.s.mantissa = a;
00563 }
00564
00565
00566 inline
00567 bool
00568 scfx_ieee_float::is_zero() const
00569 {
00570 return ( exponent() == SCFX_IEEE_FLOAT_E_MIN - 1 && mantissa() == 0U );
00571 }
00572
00573 inline
00574 bool
00575 scfx_ieee_float::is_subnormal() const
00576 {
00577 return ( exponent() == SCFX_IEEE_FLOAT_E_MIN - 1 && mantissa() != 0U );
00578 }
00579
00580 inline
00581 bool
00582 scfx_ieee_float::is_normal() const
00583 {
00584 return ( exponent() >= SCFX_IEEE_FLOAT_E_MIN &&
00585 exponent() <= SCFX_IEEE_FLOAT_E_MAX );
00586 }
00587
00588 inline
00589 bool
00590 scfx_ieee_float::is_inf() const
00591 {
00592 return ( exponent() == SCFX_IEEE_FLOAT_E_MAX + 1 && mantissa() == 0U );
00593 }
00594
00595 inline
00596 bool
00597 scfx_ieee_float::is_nan() const
00598 {
00599 return ( exponent() == SCFX_IEEE_FLOAT_E_MAX + 1 && mantissa() != 0U );
00600 }
00601
00602
00603 inline
00604 void
00605 scfx_ieee_float::set_inf()
00606 {
00607 exponent( SCFX_IEEE_FLOAT_E_MAX + 1 );
00608 mantissa( 0U );
00609 }
00610
00611 inline
00612 void
00613 scfx_ieee_float::set_nan()
00614 {
00615 exponent( SCFX_IEEE_FLOAT_E_MAX + 1 );
00616 mantissa( (unsigned int) -1 );
00617 }
00618
00619
00620
00621
00622
00623
00624
00625
00626 inline
00627 double scfx_pow2( int exp )
00628 {
00629 scfx_ieee_double r;
00630 if( exp < SCFX_IEEE_DOUBLE_E_MIN )
00631 {
00632 r = 0.0;
00633
00634 exp -= SCFX_IEEE_DOUBLE_E_MIN;
00635 if( ( exp += 20 ) >= 0 )
00636 {
00637 r.mantissa0( 1U << exp );
00638 }
00639 else if( ( exp += 32 ) >= 0 )
00640 {
00641 r.mantissa1( 1U << exp );
00642 }
00643 }
00644 else if( exp > SCFX_IEEE_DOUBLE_E_MAX )
00645 {
00646 r.set_inf();
00647 }
00648 else
00649 {
00650 r = 1.0;
00651 r.exponent( exp );
00652 }
00653 return r;
00654 }
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664 inline
00665 double
00666 uint64_to_double( uint64 a )
00667 {
00668 #if defined( _MSC_VER )
00669
00670 double tmp = static_cast<double>( static_cast<int64>( a ) );
00671 return ( tmp >= 0 ) ? tmp : tmp + sc_dt::scfx_pow2( 64 );
00672 #else
00673 return static_cast<double>( a );
00674 #endif
00675 }
00676
00677 }
00678
00679
00680 #endif
00681
00682