diff options
Diffstat (limited to 'ext/systemc/src/sysc/datatypes/fx/scfx_ieee.h')
-rw-r--r-- | ext/systemc/src/sysc/datatypes/fx/scfx_ieee.h | 701 |
1 files changed, 701 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_ieee.h b/ext/systemc/src/sysc/datatypes/fx/scfx_ieee.h new file mode 100644 index 000000000..b2da95432 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_ieee.h @@ -0,0 +1,701 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_ieee.h - + + Original Author: Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: scfx_ieee.h,v $ +// Revision 1.3 2011/08/24 22:05:43 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.2 2011/08/07 18:55:24 acg +// Philipp A. Hartmann: added guard for __clang__ to get the clang platform +// working. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef SCFX_IEEE_H +#define SCFX_IEEE_H + + +#include "sysc/datatypes/fx/sc_fxdefs.h" + + +namespace sc_dt +{ + +// classes defined in this module +union ieee_double; +class scfx_ieee_double; +union ieee_float; +class scfx_ieee_float; + +#define SCFX_MASK_(Size) \ + ((1u << (Size))-1u) + +// ---------------------------------------------------------------------------- +// UNION : ieee_double +// +// IEEE 754 double-precision format. +// ---------------------------------------------------------------------------- + +union ieee_double +{ + + double d; + + struct + { +#if defined( SC_BIG_ENDIAN ) + unsigned negative:1; + unsigned exponent:11; + unsigned mantissa0:20; + unsigned mantissa1:32; +#elif defined( SC_LITTLE_ENDIAN ) + unsigned mantissa1:32; + unsigned mantissa0:20; + unsigned exponent:11; + unsigned negative:1; +#endif + } s; + +}; + + +const unsigned int SCFX_IEEE_DOUBLE_BIAS = 1023U; + +const int SCFX_IEEE_DOUBLE_E_MAX = 1023; +const int SCFX_IEEE_DOUBLE_E_MIN = -1022; + +const unsigned int SCFX_IEEE_DOUBLE_M_SIZE = 52; +const unsigned int SCFX_IEEE_DOUBLE_M0_SIZE = 20; +const unsigned int SCFX_IEEE_DOUBLE_M1_SIZE = 32; +const unsigned int SCFX_IEEE_DOUBLE_E_SIZE = 11; + + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_ieee_double +// +// Convenient interface to union ieee_double. +// ---------------------------------------------------------------------------- + +class scfx_ieee_double +{ + + ieee_double m_id; + +public: + + scfx_ieee_double(); + scfx_ieee_double( double ); + scfx_ieee_double( const scfx_ieee_double& ); + + scfx_ieee_double& operator = ( double ); + scfx_ieee_double& operator = ( const scfx_ieee_double& ); + + operator double() const; + + unsigned int negative() const; + void negative( unsigned int ); + int exponent() const; + void exponent( int ); + unsigned int mantissa0() const; + void mantissa0( unsigned int ); + unsigned int mantissa1() const; + void mantissa1( unsigned int ); + + bool is_zero() const; + bool is_subnormal() const; + bool is_normal() const; + bool is_inf() const; + bool is_nan() const; + + void set_inf(); + void set_nan(); + + int msb() const; // most significant non-zero bit + int lsb() const; // least significant non-zero bit + + static const scfx_ieee_double nan(); + static const scfx_ieee_double inf( int ); + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +scfx_ieee_double::scfx_ieee_double() : m_id() +{ + m_id.d = 0.0; +} + +inline +scfx_ieee_double::scfx_ieee_double( double d ) : m_id() +{ + m_id.d = d; +} + +inline +scfx_ieee_double::scfx_ieee_double( const scfx_ieee_double& a ) : m_id(a.m_id) +{ + // m_id.d = a.m_id.d; +} + + +inline +scfx_ieee_double& +scfx_ieee_double::operator = ( double d ) +{ + m_id.d = d; + return *this; +} + +inline +scfx_ieee_double& +scfx_ieee_double::operator = ( const scfx_ieee_double& a ) +{ + m_id.d = a.m_id.d; + return *this; +} + + +inline +scfx_ieee_double::operator double() const +{ + return m_id.d; +} + + +inline +unsigned int +scfx_ieee_double::negative() const +{ + return m_id.s.negative; +} + +inline +void +scfx_ieee_double::negative( unsigned int a ) +{ + m_id.s.negative = a & SCFX_MASK_(1); +} + +inline +int +scfx_ieee_double::exponent() const +{ + return m_id.s.exponent - SCFX_IEEE_DOUBLE_BIAS; +} + +inline +void +scfx_ieee_double::exponent( int a ) +{ + m_id.s.exponent = (SCFX_IEEE_DOUBLE_BIAS + a) + & SCFX_MASK_(SCFX_IEEE_DOUBLE_E_SIZE); +} + +inline +unsigned int +scfx_ieee_double::mantissa0() const +{ + return m_id.s.mantissa0; +} + +inline +void +scfx_ieee_double::mantissa0( unsigned int a ) +{ + m_id.s.mantissa0 = a & SCFX_MASK_(SCFX_IEEE_DOUBLE_M0_SIZE); +} + +inline +unsigned int +scfx_ieee_double::mantissa1() const +{ + return m_id.s.mantissa1; +} + +inline +void +scfx_ieee_double::mantissa1( unsigned int a ) +{ + m_id.s.mantissa1 = a; // & SCFX_MASK_(SCFX_IEEE_DOUBLE_M1_SIZE); +} + + +inline +bool +scfx_ieee_double::is_zero() const +{ + return ( exponent() == SCFX_IEEE_DOUBLE_E_MIN - 1 && + mantissa0() == 0U && mantissa1() == 0U ); +} + +inline +bool +scfx_ieee_double::is_subnormal() const +{ + return ( exponent() == SCFX_IEEE_DOUBLE_E_MIN - 1 && + ( mantissa0() != 0U || mantissa1() != 0U ) ); +} + +inline +bool +scfx_ieee_double::is_normal() const +{ + return ( exponent() >= SCFX_IEEE_DOUBLE_E_MIN && + exponent() <= SCFX_IEEE_DOUBLE_E_MAX ); +} + +inline +bool +scfx_ieee_double::is_inf() const +{ + return ( exponent() == SCFX_IEEE_DOUBLE_E_MAX + 1 && + mantissa0() == 0U && mantissa1() == 0U ); +} + +inline +bool +scfx_ieee_double::is_nan() const +{ + return ( exponent() == SCFX_IEEE_DOUBLE_E_MAX + 1 && + ( mantissa0() != 0U || mantissa1() != 0U ) ); +} + + +inline +void +scfx_ieee_double::set_inf() +{ + exponent( SCFX_IEEE_DOUBLE_E_MAX + 1 ); + mantissa0( 0U ); + mantissa1( 0U ); +} + +inline +void +scfx_ieee_double::set_nan() +{ + exponent( SCFX_IEEE_DOUBLE_E_MAX + 1 ); + mantissa0( (unsigned int) -1 ); + mantissa1( (unsigned int) -1 ); +} + + +#define MSB_STATEMENT(x,n) if( x >> n ) { x >>= n; i += n; } + +inline +int +scfx_ieee_double::msb() const +{ + unsigned int m0 = mantissa0(); + unsigned int m1 = mantissa1(); + if( m0 != 0 ) + { + int i = 0; + MSB_STATEMENT(m0,16); + MSB_STATEMENT(m0,8); + MSB_STATEMENT(m0,4); + MSB_STATEMENT(m0,2); + MSB_STATEMENT(m0,1); + return ( i - 20 ); + } + else if( m1 != 0 ) + { + int i = 0; + MSB_STATEMENT(m1,16); + MSB_STATEMENT(m1,8); + MSB_STATEMENT(m1,4); + MSB_STATEMENT(m1,2); + MSB_STATEMENT(m1,1); + return ( i - 52 ); + } + else + { + return 0; + } +} + +#undef MSB_STATEMENT + +#define LSB_STATEMENT(x,n) if( x << n ) { x <<= n; i -= n; } + +inline +int +scfx_ieee_double::lsb() const +{ + unsigned int m0 = mantissa0(); + unsigned int m1 = mantissa1(); + if( m1 != 0 ) + { + int i = 31; + LSB_STATEMENT(m1,16); + LSB_STATEMENT(m1,8); + LSB_STATEMENT(m1,4); + LSB_STATEMENT(m1,2); + LSB_STATEMENT(m1,1); + return ( i - 52 ); + } + else if( m0 != 0 ) + { + int i = 31; + LSB_STATEMENT(m0,16); + LSB_STATEMENT(m0,8); + LSB_STATEMENT(m0,4); + LSB_STATEMENT(m0,2); + LSB_STATEMENT(m0,1); + return ( i - 20 ); + } + else + { + return 0; + } +} + +#undef LSB_STATEMENT + + +inline +const scfx_ieee_double +scfx_ieee_double::nan() +{ + scfx_ieee_double id; + id.set_nan(); + return id; +} + +inline +const scfx_ieee_double +scfx_ieee_double::inf( int sign ) +{ + scfx_ieee_double id( sign ); + id.set_inf(); + return id; +} + + +// ---------------------------------------------------------------------------- +// UNION : ieee_float +// +// IEEE 754 single-precision format. +// ---------------------------------------------------------------------------- + +union ieee_float +{ + + float f; + + struct + { +#if defined( SC_BIG_ENDIAN ) + unsigned negative:1; + unsigned exponent:8; + unsigned mantissa:23; +#elif defined( SC_LITTLE_ENDIAN ) + unsigned mantissa:23; + unsigned exponent:8; + unsigned negative:1; +#endif + } s; + +}; + + +const unsigned int SCFX_IEEE_FLOAT_BIAS = 127U; + +const int SCFX_IEEE_FLOAT_E_MAX = 127; +const int SCFX_IEEE_FLOAT_E_MIN = -126; + +const unsigned int SCFX_IEEE_FLOAT_M_SIZE = 23; +const unsigned int SCFX_IEEE_FLOAT_E_SIZE = 8; + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_ieee_float +// +// Convenient wrapper to union ieee_float. +// ---------------------------------------------------------------------------- + +class scfx_ieee_float +{ + + ieee_float m_if; + +public: + + scfx_ieee_float(); + scfx_ieee_float( float ); + scfx_ieee_float( const scfx_ieee_float& ); + + scfx_ieee_float& operator = ( float ); + scfx_ieee_float& operator = ( const scfx_ieee_float& ); + + operator float() const; + + unsigned int negative() const; + void negative( unsigned int ); + int exponent() const; + void exponent( int ); + unsigned int mantissa() const; + void mantissa( unsigned int ); + + bool is_zero() const; + bool is_subnormal() const; + bool is_normal() const; + bool is_inf() const; + bool is_nan() const; + + void set_inf(); + void set_nan(); + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +scfx_ieee_float::scfx_ieee_float() : m_if() +{ + m_if.f = 0.0; +} + +inline +scfx_ieee_float::scfx_ieee_float( float f ) : m_if() +{ + m_if.f = f; +} + +inline +scfx_ieee_float::scfx_ieee_float( const scfx_ieee_float& a ) : m_if(a.m_if) +{ + // m_if.f = a.m_if.f; +} + + +inline +scfx_ieee_float& +scfx_ieee_float::operator = ( float f ) +{ + m_if.f = f; + return *this; +} + +inline +scfx_ieee_float& +scfx_ieee_float::operator = ( const scfx_ieee_float& a ) +{ + m_if.f = a.m_if.f; + return *this; +} + + +inline +scfx_ieee_float::operator float() const +{ + return m_if.f; +} + + +inline +unsigned int +scfx_ieee_float::negative() const +{ + return m_if.s.negative; +} + +inline +void +scfx_ieee_float::negative( unsigned int a ) +{ + m_if.s.negative = a & SCFX_MASK_(1); +} + +inline +int +scfx_ieee_float::exponent() const +{ + return m_if.s.exponent - SCFX_IEEE_FLOAT_BIAS; +} + +inline +void +scfx_ieee_float::exponent( int a ) +{ + m_if.s.exponent = (SCFX_IEEE_FLOAT_BIAS + a) + & SCFX_MASK_(SCFX_IEEE_FLOAT_E_SIZE); +} + +inline +unsigned int +scfx_ieee_float::mantissa() const +{ + return m_if.s.mantissa; +} + +inline +void +scfx_ieee_float::mantissa( unsigned int a ) +{ + m_if.s.mantissa = a & SCFX_MASK_(SCFX_IEEE_FLOAT_M_SIZE); +} + + +inline +bool +scfx_ieee_float::is_zero() const +{ + return ( exponent() == SCFX_IEEE_FLOAT_E_MIN - 1 && mantissa() == 0U ); +} + +inline +bool +scfx_ieee_float::is_subnormal() const +{ + return ( exponent() == SCFX_IEEE_FLOAT_E_MIN - 1 && mantissa() != 0U ); +} + +inline +bool +scfx_ieee_float::is_normal() const +{ + return ( exponent() >= SCFX_IEEE_FLOAT_E_MIN && + exponent() <= SCFX_IEEE_FLOAT_E_MAX ); +} + +inline +bool +scfx_ieee_float::is_inf() const +{ + return ( exponent() == SCFX_IEEE_FLOAT_E_MAX + 1 && mantissa() == 0U ); +} + +inline +bool +scfx_ieee_float::is_nan() const +{ + return ( exponent() == SCFX_IEEE_FLOAT_E_MAX + 1 && mantissa() != 0U ); +} + + +inline +void +scfx_ieee_float::set_inf() +{ + exponent( SCFX_IEEE_FLOAT_E_MAX + 1 ); + mantissa( 0U ); +} + +inline +void +scfx_ieee_float::set_nan() +{ + exponent( SCFX_IEEE_FLOAT_E_MAX + 1 ); + mantissa( (unsigned int) -1 ); +} + + +// ---------------------------------------------------------------------------- +// FUNCTION : scfx_pow2 +// +// Computes 2.0**exp in double-precision. +// ---------------------------------------------------------------------------- + +inline +double scfx_pow2( int exp ) +{ + scfx_ieee_double r; + if( exp < SCFX_IEEE_DOUBLE_E_MIN ) + { + r = 0.0; + // handle subnormal case + exp -= SCFX_IEEE_DOUBLE_E_MIN; + if( ( exp += 20 ) >= 0 ) + { + r.mantissa0( 1U << exp ); + } + else if( ( exp += 32 ) >= 0 ) + { + r.mantissa1( 1U << exp ); + } + } + else if( exp > SCFX_IEEE_DOUBLE_E_MAX ) + { + r.set_inf(); + } + else + { + r = 1.0; + r.exponent( exp ); + } + return r; +} + + +// ---------------------------------------------------------------------------- +// FUNCTION : uint64_to_double +// +// Platform independent conversion from double uint64 to double. +// Needed because VC++6 doesn't support this conversion. +// ---------------------------------------------------------------------------- + +inline +double +uint64_to_double( uint64 a ) +{ +#if defined( _MSC_VER ) || defined( __clang__ ) + // conversion from uint64 to double not implemented; use int64 + double tmp = static_cast<double>( static_cast<int64>( a ) ); + return ( tmp >= 0 ) ? tmp : tmp + sc_dt::scfx_pow2( 64 ); +#else + return static_cast<double>( a ); +#endif +} + +} // namespace sc_dt + +#undef SCFX_MASK_ + +#endif + +// Taf! |