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