scfx_ieee.h revision 12027
1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20/***************************************************************************** 21 22 scfx_ieee.h - 23 24 Original Author: Martin Janssen, Synopsys, Inc. 25 26 *****************************************************************************/ 27 28/***************************************************************************** 29 30 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 31 changes you are making here. 32 33 Name, Affiliation, Date: 34 Description of Modification: 35 36 *****************************************************************************/ 37 38// $Log: scfx_ieee.h,v $ 39// Revision 1.3 2011/08/24 22:05:43 acg 40// Torsten Maehne: initialization changes to remove warnings. 41// 42// Revision 1.2 2011/08/07 18:55:24 acg 43// Philipp A. Hartmann: added guard for __clang__ to get the clang platform 44// working. 45// 46// Revision 1.1.1.1 2006/12/15 20:20:04 acg 47// SystemC 2.3 48// 49// Revision 1.3 2006/01/13 18:53:58 acg 50// Andy Goodrich: added $Log command so that CVS comments are reproduced in 51// the source. 52// 53 54#ifndef SCFX_IEEE_H 55#define SCFX_IEEE_H 56 57 58#include "sysc/datatypes/fx/sc_fxdefs.h" 59 60 61namespace sc_dt 62{ 63 64// classes defined in this module 65union ieee_double; 66class scfx_ieee_double; 67union ieee_float; 68class scfx_ieee_float; 69 70#define SCFX_MASK_(Size) \ 71 ((1u << (Size))-1u) 72 73// ---------------------------------------------------------------------------- 74// UNION : ieee_double 75// 76// IEEE 754 double-precision format. 77// ---------------------------------------------------------------------------- 78 79union ieee_double 80{ 81 82 double d; 83 84 struct 85 { 86#if defined( SC_BIG_ENDIAN ) 87 unsigned negative:1; 88 unsigned exponent:11; 89 unsigned mantissa0:20; 90 unsigned mantissa1:32; 91#elif defined( SC_LITTLE_ENDIAN ) 92 unsigned mantissa1:32; 93 unsigned mantissa0:20; 94 unsigned exponent:11; 95 unsigned negative:1; 96#endif 97 } s; 98 99}; 100 101 102const unsigned int SCFX_IEEE_DOUBLE_BIAS = 1023U; 103 104const int SCFX_IEEE_DOUBLE_E_MAX = 1023; 105const int SCFX_IEEE_DOUBLE_E_MIN = -1022; 106 107const unsigned int SCFX_IEEE_DOUBLE_M_SIZE = 52; 108const unsigned int SCFX_IEEE_DOUBLE_M0_SIZE = 20; 109const unsigned int SCFX_IEEE_DOUBLE_M1_SIZE = 32; 110const unsigned int SCFX_IEEE_DOUBLE_E_SIZE = 11; 111 112 113 114// ---------------------------------------------------------------------------- 115// CLASS : scfx_ieee_double 116// 117// Convenient interface to union ieee_double. 118// ---------------------------------------------------------------------------- 119 120class scfx_ieee_double 121{ 122 123 ieee_double m_id; 124 125public: 126 127 scfx_ieee_double(); 128 scfx_ieee_double( double ); 129 scfx_ieee_double( const scfx_ieee_double& ); 130 131 scfx_ieee_double& operator = ( double ); 132 scfx_ieee_double& operator = ( const scfx_ieee_double& ); 133 134 operator double() const; 135 136 unsigned int negative() const; 137 void negative( unsigned int ); 138 int exponent() const; 139 void exponent( int ); 140 unsigned int mantissa0() const; 141 void mantissa0( unsigned int ); 142 unsigned int mantissa1() const; 143 void mantissa1( unsigned int ); 144 145 bool is_zero() const; 146 bool is_subnormal() const; 147 bool is_normal() const; 148 bool is_inf() const; 149 bool is_nan() const; 150 151 void set_inf(); 152 void set_nan(); 153 154 int msb() const; // most significant non-zero bit 155 int lsb() const; // least significant non-zero bit 156 157 static const scfx_ieee_double nan(); 158 static const scfx_ieee_double inf( int ); 159 160}; 161 162 163// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 164 165inline 166scfx_ieee_double::scfx_ieee_double() : m_id() 167{ 168 m_id.d = 0.0; 169} 170 171inline 172scfx_ieee_double::scfx_ieee_double( double d ) : m_id() 173{ 174 m_id.d = d; 175} 176 177inline 178scfx_ieee_double::scfx_ieee_double( const scfx_ieee_double& a ) : m_id(a.m_id) 179{ 180 // m_id.d = a.m_id.d; 181} 182 183 184inline 185scfx_ieee_double& 186scfx_ieee_double::operator = ( double d ) 187{ 188 m_id.d = d; 189 return *this; 190} 191 192inline 193scfx_ieee_double& 194scfx_ieee_double::operator = ( const scfx_ieee_double& a ) 195{ 196 m_id.d = a.m_id.d; 197 return *this; 198} 199 200 201inline 202scfx_ieee_double::operator double() const 203{ 204 return m_id.d; 205} 206 207 208inline 209unsigned int 210scfx_ieee_double::negative() const 211{ 212 return m_id.s.negative; 213} 214 215inline 216void 217scfx_ieee_double::negative( unsigned int a ) 218{ 219 m_id.s.negative = a & SCFX_MASK_(1); 220} 221 222inline 223int 224scfx_ieee_double::exponent() const 225{ 226 return m_id.s.exponent - SCFX_IEEE_DOUBLE_BIAS; 227} 228 229inline 230void 231scfx_ieee_double::exponent( int a ) 232{ 233 m_id.s.exponent = (SCFX_IEEE_DOUBLE_BIAS + a) 234 & SCFX_MASK_(SCFX_IEEE_DOUBLE_E_SIZE); 235} 236 237inline 238unsigned int 239scfx_ieee_double::mantissa0() const 240{ 241 return m_id.s.mantissa0; 242} 243 244inline 245void 246scfx_ieee_double::mantissa0( unsigned int a ) 247{ 248 m_id.s.mantissa0 = a & SCFX_MASK_(SCFX_IEEE_DOUBLE_M0_SIZE); 249} 250 251inline 252unsigned int 253scfx_ieee_double::mantissa1() const 254{ 255 return m_id.s.mantissa1; 256} 257 258inline 259void 260scfx_ieee_double::mantissa1( unsigned int a ) 261{ 262 m_id.s.mantissa1 = a; // & SCFX_MASK_(SCFX_IEEE_DOUBLE_M1_SIZE); 263} 264 265 266inline 267bool 268scfx_ieee_double::is_zero() const 269{ 270 return ( exponent() == SCFX_IEEE_DOUBLE_E_MIN - 1 && 271 mantissa0() == 0U && mantissa1() == 0U ); 272} 273 274inline 275bool 276scfx_ieee_double::is_subnormal() const 277{ 278 return ( exponent() == SCFX_IEEE_DOUBLE_E_MIN - 1 && 279 ( mantissa0() != 0U || mantissa1() != 0U ) ); 280} 281 282inline 283bool 284scfx_ieee_double::is_normal() const 285{ 286 return ( exponent() >= SCFX_IEEE_DOUBLE_E_MIN && 287 exponent() <= SCFX_IEEE_DOUBLE_E_MAX ); 288} 289 290inline 291bool 292scfx_ieee_double::is_inf() const 293{ 294 return ( exponent() == SCFX_IEEE_DOUBLE_E_MAX + 1 && 295 mantissa0() == 0U && mantissa1() == 0U ); 296} 297 298inline 299bool 300scfx_ieee_double::is_nan() const 301{ 302 return ( exponent() == SCFX_IEEE_DOUBLE_E_MAX + 1 && 303 ( mantissa0() != 0U || mantissa1() != 0U ) ); 304} 305 306 307inline 308void 309scfx_ieee_double::set_inf() 310{ 311 exponent( SCFX_IEEE_DOUBLE_E_MAX + 1 ); 312 mantissa0( 0U ); 313 mantissa1( 0U ); 314} 315 316inline 317void 318scfx_ieee_double::set_nan() 319{ 320 exponent( SCFX_IEEE_DOUBLE_E_MAX + 1 ); 321 mantissa0( (unsigned int) -1 ); 322 mantissa1( (unsigned int) -1 ); 323} 324 325 326#define MSB_STATEMENT(x,n) if( x >> n ) { x >>= n; i += n; } 327 328inline 329int 330scfx_ieee_double::msb() const 331{ 332 unsigned int m0 = mantissa0(); 333 unsigned int m1 = mantissa1(); 334 if( m0 != 0 ) 335 { 336 int i = 0; 337 MSB_STATEMENT(m0,16); 338 MSB_STATEMENT(m0,8); 339 MSB_STATEMENT(m0,4); 340 MSB_STATEMENT(m0,2); 341 MSB_STATEMENT(m0,1); 342 return ( i - 20 ); 343 } 344 else if( m1 != 0 ) 345 { 346 int i = 0; 347 MSB_STATEMENT(m1,16); 348 MSB_STATEMENT(m1,8); 349 MSB_STATEMENT(m1,4); 350 MSB_STATEMENT(m1,2); 351 MSB_STATEMENT(m1,1); 352 return ( i - 52 ); 353 } 354 else 355 { 356 return 0; 357 } 358} 359 360#undef MSB_STATEMENT 361 362#define LSB_STATEMENT(x,n) if( x << n ) { x <<= n; i -= n; } 363 364inline 365int 366scfx_ieee_double::lsb() const 367{ 368 unsigned int m0 = mantissa0(); 369 unsigned int m1 = mantissa1(); 370 if( m1 != 0 ) 371 { 372 int i = 31; 373 LSB_STATEMENT(m1,16); 374 LSB_STATEMENT(m1,8); 375 LSB_STATEMENT(m1,4); 376 LSB_STATEMENT(m1,2); 377 LSB_STATEMENT(m1,1); 378 return ( i - 52 ); 379 } 380 else if( m0 != 0 ) 381 { 382 int i = 31; 383 LSB_STATEMENT(m0,16); 384 LSB_STATEMENT(m0,8); 385 LSB_STATEMENT(m0,4); 386 LSB_STATEMENT(m0,2); 387 LSB_STATEMENT(m0,1); 388 return ( i - 20 ); 389 } 390 else 391 { 392 return 0; 393 } 394} 395 396#undef LSB_STATEMENT 397 398 399inline 400const scfx_ieee_double 401scfx_ieee_double::nan() 402{ 403 scfx_ieee_double id; 404 id.set_nan(); 405 return id; 406} 407 408inline 409const scfx_ieee_double 410scfx_ieee_double::inf( int sign ) 411{ 412 scfx_ieee_double id( sign ); 413 id.set_inf(); 414 return id; 415} 416 417 418// ---------------------------------------------------------------------------- 419// UNION : ieee_float 420// 421// IEEE 754 single-precision format. 422// ---------------------------------------------------------------------------- 423 424union ieee_float 425{ 426 427 float f; 428 429 struct 430 { 431#if defined( SC_BIG_ENDIAN ) 432 unsigned negative:1; 433 unsigned exponent:8; 434 unsigned mantissa:23; 435#elif defined( SC_LITTLE_ENDIAN ) 436 unsigned mantissa:23; 437 unsigned exponent:8; 438 unsigned negative:1; 439#endif 440 } s; 441 442}; 443 444 445const unsigned int SCFX_IEEE_FLOAT_BIAS = 127U; 446 447const int SCFX_IEEE_FLOAT_E_MAX = 127; 448const int SCFX_IEEE_FLOAT_E_MIN = -126; 449 450const unsigned int SCFX_IEEE_FLOAT_M_SIZE = 23; 451const unsigned int SCFX_IEEE_FLOAT_E_SIZE = 8; 452 453 454// ---------------------------------------------------------------------------- 455// CLASS : scfx_ieee_float 456// 457// Convenient wrapper to union ieee_float. 458// ---------------------------------------------------------------------------- 459 460class scfx_ieee_float 461{ 462 463 ieee_float m_if; 464 465public: 466 467 scfx_ieee_float(); 468 scfx_ieee_float( float ); 469 scfx_ieee_float( const scfx_ieee_float& ); 470 471 scfx_ieee_float& operator = ( float ); 472 scfx_ieee_float& operator = ( const scfx_ieee_float& ); 473 474 operator float() const; 475 476 unsigned int negative() const; 477 void negative( unsigned int ); 478 int exponent() const; 479 void exponent( int ); 480 unsigned int mantissa() const; 481 void mantissa( unsigned int ); 482 483 bool is_zero() const; 484 bool is_subnormal() const; 485 bool is_normal() const; 486 bool is_inf() const; 487 bool is_nan() const; 488 489 void set_inf(); 490 void set_nan(); 491 492}; 493 494 495// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 496 497inline 498scfx_ieee_float::scfx_ieee_float() : m_if() 499{ 500 m_if.f = 0.0; 501} 502 503inline 504scfx_ieee_float::scfx_ieee_float( float f ) : m_if() 505{ 506 m_if.f = f; 507} 508 509inline 510scfx_ieee_float::scfx_ieee_float( const scfx_ieee_float& a ) : m_if(a.m_if) 511{ 512 // m_if.f = a.m_if.f; 513} 514 515 516inline 517scfx_ieee_float& 518scfx_ieee_float::operator = ( float f ) 519{ 520 m_if.f = f; 521 return *this; 522} 523 524inline 525scfx_ieee_float& 526scfx_ieee_float::operator = ( const scfx_ieee_float& a ) 527{ 528 m_if.f = a.m_if.f; 529 return *this; 530} 531 532 533inline 534scfx_ieee_float::operator float() const 535{ 536 return m_if.f; 537} 538 539 540inline 541unsigned int 542scfx_ieee_float::negative() const 543{ 544 return m_if.s.negative; 545} 546 547inline 548void 549scfx_ieee_float::negative( unsigned int a ) 550{ 551 m_if.s.negative = a & SCFX_MASK_(1); 552} 553 554inline 555int 556scfx_ieee_float::exponent() const 557{ 558 return m_if.s.exponent - SCFX_IEEE_FLOAT_BIAS; 559} 560 561inline 562void 563scfx_ieee_float::exponent( int a ) 564{ 565 m_if.s.exponent = (SCFX_IEEE_FLOAT_BIAS + a) 566 & SCFX_MASK_(SCFX_IEEE_FLOAT_E_SIZE); 567} 568 569inline 570unsigned int 571scfx_ieee_float::mantissa() const 572{ 573 return m_if.s.mantissa; 574} 575 576inline 577void 578scfx_ieee_float::mantissa( unsigned int a ) 579{ 580 m_if.s.mantissa = a & SCFX_MASK_(SCFX_IEEE_FLOAT_M_SIZE); 581} 582 583 584inline 585bool 586scfx_ieee_float::is_zero() const 587{ 588 return ( exponent() == SCFX_IEEE_FLOAT_E_MIN - 1 && mantissa() == 0U ); 589} 590 591inline 592bool 593scfx_ieee_float::is_subnormal() const 594{ 595 return ( exponent() == SCFX_IEEE_FLOAT_E_MIN - 1 && mantissa() != 0U ); 596} 597 598inline 599bool 600scfx_ieee_float::is_normal() const 601{ 602 return ( exponent() >= SCFX_IEEE_FLOAT_E_MIN && 603 exponent() <= SCFX_IEEE_FLOAT_E_MAX ); 604} 605 606inline 607bool 608scfx_ieee_float::is_inf() const 609{ 610 return ( exponent() == SCFX_IEEE_FLOAT_E_MAX + 1 && mantissa() == 0U ); 611} 612 613inline 614bool 615scfx_ieee_float::is_nan() const 616{ 617 return ( exponent() == SCFX_IEEE_FLOAT_E_MAX + 1 && mantissa() != 0U ); 618} 619 620 621inline 622void 623scfx_ieee_float::set_inf() 624{ 625 exponent( SCFX_IEEE_FLOAT_E_MAX + 1 ); 626 mantissa( 0U ); 627} 628 629inline 630void 631scfx_ieee_float::set_nan() 632{ 633 exponent( SCFX_IEEE_FLOAT_E_MAX + 1 ); 634 mantissa( (unsigned int) -1 ); 635} 636 637 638// ---------------------------------------------------------------------------- 639// FUNCTION : scfx_pow2 640// 641// Computes 2.0**exp in double-precision. 642// ---------------------------------------------------------------------------- 643 644inline 645double scfx_pow2( int exp ) 646{ 647 scfx_ieee_double r; 648 if( exp < SCFX_IEEE_DOUBLE_E_MIN ) 649 { 650 r = 0.0; 651 // handle subnormal case 652 exp -= SCFX_IEEE_DOUBLE_E_MIN; 653 if( ( exp += 20 ) >= 0 ) 654 { 655 r.mantissa0( 1U << exp ); 656 } 657 else if( ( exp += 32 ) >= 0 ) 658 { 659 r.mantissa1( 1U << exp ); 660 } 661 } 662 else if( exp > SCFX_IEEE_DOUBLE_E_MAX ) 663 { 664 r.set_inf(); 665 } 666 else 667 { 668 r = 1.0; 669 r.exponent( exp ); 670 } 671 return r; 672} 673 674 675// ---------------------------------------------------------------------------- 676// FUNCTION : uint64_to_double 677// 678// Platform independent conversion from double uint64 to double. 679// Needed because VC++6 doesn't support this conversion. 680// ---------------------------------------------------------------------------- 681 682inline 683double 684uint64_to_double( uint64 a ) 685{ 686#if defined( _MSC_VER ) || defined( __clang__ ) 687 // conversion from uint64 to double not implemented; use int64 688 double tmp = static_cast<double>( static_cast<int64>( a ) ); 689 return ( tmp >= 0 ) ? tmp : tmp + sc_dt::scfx_pow2( 64 ); 690#else 691 return static_cast<double>( a ); 692#endif 693} 694 695} // namespace sc_dt 696 697#undef SCFX_MASK_ 698 699#endif 700 701// Taf! 702