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