diff options
Diffstat (limited to 'ext/systemc/src/sysc/datatypes/fx/scfx_rep.h')
-rw-r--r-- | ext/systemc/src/sysc/datatypes/fx/scfx_rep.h | 842 |
1 files changed, 842 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/datatypes/fx/scfx_rep.h b/ext/systemc/src/sysc/datatypes/fx/scfx_rep.h new file mode 100644 index 000000000..c5b76ce54 --- /dev/null +++ b/ext/systemc/src/sysc/datatypes/fx/scfx_rep.h @@ -0,0 +1,842 @@ +/***************************************************************************** + + 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_rep.h - + + Original Author: Robert Graulich, Synopsys, Inc. + 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_rep.h,v $ +// Revision 1.6 2011/08/24 22:05:43 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/07/25 10:20:29 acg +// Andy Goodrich: check in aftermath of call to automake. +// +// Revision 1.4 2010/12/07 20:09:08 acg +// Andy Goodrich: Philipp Hartmann's constructor disambiguation fix +// +// Revision 1.3 2010/08/03 15:54:52 acg +// Andy Goodrich: formatting. +// +// Revision 1.2 2010/03/15 18:29:01 acg +// Andy Goodrich: Moved default argument specifications from friend +// declarations to the actual function signatures. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/03/13 20:24:27 acg +// Andy Goodrich: Addition of function declarations, e.g., neg_scfx_rep(), +// to keep gcc 4.x happy. +// +// 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_REP_H +#define SCFX_REP_H + + +#include <climits> + +#include "sysc/datatypes/fx/scfx_mant.h" +#include "sysc/datatypes/fx/scfx_params.h" +#include "sysc/datatypes/fx/scfx_string.h" + + +namespace sc_dt +{ + +// classes defined in this module +class scfx_index; +class scfx_rep; + +// forward class declarations +class sc_bv_base; +class sc_signed; +class sc_unsigned; + +// function declarations +void multiply( scfx_rep&, const scfx_rep&, const scfx_rep&, + int max_wl = SC_DEFAULT_MAX_WL_ ); +scfx_rep* neg_scfx_rep( const scfx_rep& ); +scfx_rep* mult_scfx_rep( const scfx_rep&, const scfx_rep&, + int max_wl = SC_DEFAULT_MAX_WL_ ); +scfx_rep* div_scfx_rep( const scfx_rep&, const scfx_rep&, + int max_wl = SC_DEFAULT_DIV_WL_ ); +scfx_rep* add_scfx_rep( const scfx_rep&, const scfx_rep&, + int max_wl = SC_DEFAULT_MAX_WL_ ); +scfx_rep* sub_scfx_rep( const scfx_rep&, const scfx_rep&, + int max_wl = SC_DEFAULT_MAX_WL_ ); +scfx_rep* lsh_scfx_rep( const scfx_rep&, int ); +scfx_rep* rsh_scfx_rep( const scfx_rep&, int ); +int cmp_scfx_rep( const scfx_rep&, const scfx_rep& ); + + +const int min_mant = 4; + +const int bits_in_int = sizeof(int) * CHAR_BIT; +const int bits_in_word = sizeof(word) * CHAR_BIT; + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_index +// ---------------------------------------------------------------------------- + +class scfx_index +{ + +public: + + scfx_index( int wi_, int bi_ ) : m_wi( wi_ ), m_bi( bi_ ) {} + + int wi() const { return m_wi; } + int bi() const { return m_bi; } + + void wi( int wi_ ) { m_wi = wi_; } + +private: + + int m_wi; + int m_bi; + +}; + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_rep +// +// Arbitrary-precision fixed-point implementation class. +// ---------------------------------------------------------------------------- + +class scfx_rep +{ + enum state + { + normal, + infinity, + not_a_number + }; + +public: + + // constructors + + scfx_rep(); + explicit scfx_rep( int ); + explicit scfx_rep( unsigned int ); + explicit scfx_rep( long ); + explicit scfx_rep( unsigned long ); + explicit scfx_rep( double ); + explicit scfx_rep( const char* ); + explicit scfx_rep( int64 ); + explicit scfx_rep( uint64 ); + explicit scfx_rep( const sc_signed& ); + explicit scfx_rep( const sc_unsigned& ); + + + // copy constructor + + scfx_rep( const scfx_rep& ); + + + // destructor + + ~scfx_rep(); + + + void* operator new( std::size_t ); + void operator delete( void*, std::size_t ); + + + void from_string( const char*, int ); + + double to_double() const; + + const char* to_string( sc_numrep, + int, + sc_fmt, + const scfx_params* = 0 ) const; + + + // assignment operator + + void operator = ( const scfx_rep& ); + + friend void multiply( scfx_rep&, const scfx_rep&, const scfx_rep&, int ); + + friend scfx_rep* neg_scfx_rep( const scfx_rep& ); + friend scfx_rep* mult_scfx_rep( const scfx_rep&, const scfx_rep&, int ); + friend scfx_rep* div_scfx_rep( const scfx_rep&, const scfx_rep&, int ); + friend scfx_rep* add_scfx_rep( const scfx_rep&, const scfx_rep&, int ); + friend scfx_rep* sub_scfx_rep( const scfx_rep&, const scfx_rep&, int ); + friend scfx_rep* lsh_scfx_rep( const scfx_rep&, int ); + friend scfx_rep* rsh_scfx_rep( const scfx_rep&, int ); + + void lshift( int ); + void rshift( int ); + + friend int cmp_scfx_rep( const scfx_rep&, const scfx_rep& ); + + void cast( const scfx_params&, bool&, bool& ); + + bool is_neg() const; + bool is_zero() const; + bool is_nan() const; + bool is_inf() const; + bool is_normal() const; + + void set_zero( int = 1 ); + void set_nan(); + void set_inf( int ); + + bool get_bit( int ) const; + bool set( int, const scfx_params& ); + bool clear( int, const scfx_params& ); + + bool get_slice( int, int, const scfx_params&, sc_bv_base& ) const; + bool set_slice( int, int, const scfx_params&, const sc_bv_base& ); + + void print( ::std::ostream& ) const; + void dump( ::std::ostream& ) const; + + void get_type( int&, int&, sc_enc& ) const; + + friend scfx_rep* quantization_scfx_rep( const scfx_rep&, + const scfx_params&, + bool& ); + friend scfx_rep* overflow_scfx_rep( const scfx_rep&, + const scfx_params&, + bool& ); + + bool rounding_flag() const; + +private: + + friend void align( const scfx_rep&, const scfx_rep&, int&, int&, + scfx_mant_ref&, scfx_mant_ref& ); + friend int compare_msw( const scfx_rep&, const scfx_rep& ); + friend int compare_msw_ff( const scfx_rep& lhs, const scfx_rep& rhs ); + unsigned int divide_by_ten(); + int find_lsw() const; + int find_msw() const; + void find_sw(); + void multiply_by_ten(); + void normalize( int ); + scfx_mant* resize( int, int ) const; + void set_bin( int ); + void set_oct( int, int ); + void set_hex( int, int ); + void shift_left( int ); + void shift_right( int ); + + const scfx_index calc_indices( int ) const; + + void o_extend( const scfx_index&, sc_enc ); + bool o_bit_at( const scfx_index& ) const; + bool o_zero_left( const scfx_index& ) const; + bool o_zero_right( const scfx_index& ) const; + void o_set_low( const scfx_index&, sc_enc ); + void o_set_high( const scfx_index&, const scfx_index&, sc_enc, int = 1 ); + void o_set( const scfx_index&, const scfx_index&, sc_enc, bool ); + void o_invert( const scfx_index& ); + bool q_bit( const scfx_index& ) const; + void q_clear( const scfx_index& ); + void q_incr( const scfx_index& ); + bool q_odd( const scfx_index& ) const; + bool q_zero( const scfx_index& ) const; + + void resize_to( int, int = 0 ); + int size() const; + void toggle_tc(); + + friend void print_dec( scfx_string&, const scfx_rep&, int, sc_fmt ); + friend void print_other( scfx_string&, const scfx_rep&, sc_numrep, int, + sc_fmt, const scfx_params* ); + + void quantization( const scfx_params&, bool& ); + void overflow( const scfx_params&, bool& ); + + friend int compare_abs( const scfx_rep&, const scfx_rep& ); + + void round( int ); + +private: + + scfx_mant m_mant; // mantissa (bits of the value). + int m_wp; // index of highest order word in value. + int m_sign; // sign of value. + state m_state; // value state, e.g., normal, inf, etc. + int m_msw; // index of most significant non-zero word. + int m_lsw; // index of least significant non-zero word. + bool m_r_flag; // true if founding occurred. + +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +void +scfx_rep::set_zero( int sign ) +{ + m_mant.clear(); + m_wp = m_msw = m_lsw = 0; + m_sign = sign; + m_state = normal; +} + +inline +void +scfx_rep::set_nan() +{ + m_mant.resize_to( min_mant ); + m_state = not_a_number; +} + +inline +void +scfx_rep::set_inf( int sign ) +{ + m_mant.resize_to( min_mant ); + m_state = infinity; + m_sign = sign; +} + + +// constructors + +inline +scfx_rep::scfx_rep( const char* s ) +: m_mant( min_mant ), m_wp( 2 ), m_sign( 1 ), m_state( normal ), + m_msw(0), m_lsw(0), m_r_flag( false ) +{ + from_string( s, SC_DEFAULT_CTE_WL_ ); +} + + +// destructor + +inline +scfx_rep::~scfx_rep() +{} + + +// assignment operator + +inline +void +scfx_rep::operator = ( const scfx_rep& f ) +{ + if( &f != this ) + { + m_mant = f.m_mant; + m_wp = f.m_wp; + m_sign = f.m_sign; + m_state = f.m_state; + m_msw = f.m_msw; + m_lsw = f.m_lsw; + round( SC_DEFAULT_MAX_WL_ ); + } +} + +inline +scfx_rep* +neg_scfx_rep( const scfx_rep& a ) +{ + scfx_rep& c = *new scfx_rep( a ); + c.m_sign = - c.m_sign; + return &c; +} + +inline +scfx_rep* +mult_scfx_rep( const scfx_rep& a, const scfx_rep& b, int max_wl ) +{ + scfx_rep& c = *new scfx_rep; + sc_dt::multiply( c, a, b, max_wl ); + return &c; +} + +inline +scfx_rep* +lsh_scfx_rep( const scfx_rep& a, int b ) +{ + scfx_rep& c = *new scfx_rep( a ); + c.lshift( b ); + return &c; +} + +inline +scfx_rep* +rsh_scfx_rep( const scfx_rep& a, int b ) +{ + scfx_rep& c = *new scfx_rep( a ); + c.rshift( b ); + return &c; +} + +inline +int +scfx_rep::size() const +{ + return m_mant.size(); +} + +inline +bool +scfx_rep::is_neg() const +{ + return ( m_sign == -1 ); +} + +inline +bool +scfx_rep::is_zero() const +{ + if( m_state != normal ) + return false; + + for( int i = 0; i < size(); i ++ ) + { + if( m_mant[i] ) + return false; + } + + return true; +} + +inline +bool +scfx_rep::is_nan() const +{ + return ( m_state == not_a_number ); +} + +inline +bool +scfx_rep::is_inf() const +{ + return ( m_state == infinity ); +} + +inline +bool +scfx_rep::is_normal() const +{ + return ( m_state == normal ); +} + +inline +scfx_rep* +quantization_scfx_rep( const scfx_rep& a, + const scfx_params& params, + bool& q_flag ) +{ + scfx_rep& c = *new scfx_rep( a ); + c.quantization( params, q_flag ); + return &c; +} + +inline +scfx_rep* +overflow_scfx_rep( const scfx_rep& a, + const scfx_params& params, + bool& o_flag ) +{ + scfx_rep& c = *new scfx_rep( a ); + c.overflow( params, o_flag ); + return &c; +} + +inline +bool +scfx_rep::rounding_flag() const +{ + return m_r_flag; +} + +inline +void +scfx_rep::resize_to( int new_size, int restore ) +{ + if( restore == -1 ) + { + int size_incr = new_size - size(); + m_wp += size_incr; + m_msw += size_incr; + m_lsw += size_incr; + } + m_mant.resize_to( new_size, restore ); +} + +inline +const scfx_index +scfx_rep::calc_indices( int n ) const +{ + int wi = n / bits_in_word + m_wp; + int bi = n % bits_in_word; + + if( bi < 0 ) + { + bi += bits_in_word; + -- wi; + } + + return scfx_index( wi, bi ); +} + +inline +void +scfx_rep::o_extend( const scfx_index& x, sc_enc enc ) +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + if( enc == SC_US_ || ( m_mant[wi] & ( ((word)1) << bi ) ) == 0 ) + { + if( bi != bits_in_word - 1 ) + m_mant[wi] &= ~( ((word)-1) << ( bi + 1 ) ); + for( int i = wi + 1; i < size(); ++ i ) + m_mant[i] = 0; + m_sign = 1; + } + else + { + if( bi != bits_in_word - 1 ) + m_mant[wi] |= ( ((word)-1) << ( bi + 1 ) ); + for( int i = wi + 1; i < size(); ++ i ) + m_mant[i] = static_cast<word>( -1 ); + m_sign = -1; + } +} + +inline +bool +scfx_rep::o_bit_at( const scfx_index& x ) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + return ( m_mant[wi] & ( ((word)1) << bi ) ) != 0; +} + +inline +bool +scfx_rep::o_zero_left( const scfx_index& x ) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + bool zero = true; + if( bi != bits_in_word - 1 ) + zero = ( m_mant[wi] & ( ((word)-1) << ( bi + 1 ) ) ) == 0; + for( int i = wi + 1; i < size(); ++ i ) + zero = zero && m_mant[i] == 0; + + return zero; +} + +inline +bool +scfx_rep::o_zero_right( const scfx_index& x ) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + bool zero = ( m_mant[wi] & ~( ((word)-1) << bi ) ) == 0; + for( int i = wi - 1; i >= 0; -- i ) + zero = zero && m_mant[i] == 0; + + return zero; +} + +inline +void +scfx_rep::o_set_low( const scfx_index& x, sc_enc enc ) +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + m_mant.clear(); + + if( enc == SC_TC_ ) + { + m_mant[wi] |= ( ((word)1) << bi ); + m_sign = -1; + } + else + m_sign = 1; +} + +inline +void +scfx_rep::o_set_high( const scfx_index& x, const scfx_index& x2, + sc_enc enc, int sign ) +{ + int wi = x.wi(); + int bi = x.bi(); + int wi2 = x2.wi(); + int bi2 = x2.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + SC_ASSERT_( wi2 >= 0 && wi2 < size(), "word index out of range" ); + + int i; + + for( i = 0; i < size(); ++ i ) + m_mant[i] = static_cast<word>( -1 ); + + m_mant[wi] &= ~( ((word)-1) << bi ); + for( i = wi + 1; i < size(); ++ i ) + m_mant[i] = 0; + + m_mant[wi2] &= ( ((word)-1) << bi2 ); + for( i = wi2 - 1; i >= 0; -- i ) + m_mant[i] = 0; + + if( enc == SC_TC_ ) + m_sign = sign; + else + { + m_mant[wi] |= ( ((word)1) << bi ); + m_sign = 1; + } +} + +inline +void +scfx_rep::o_set( const scfx_index& x, const scfx_index& x3, + sc_enc enc, bool under ) +{ + int wi = x.wi(); + int bi = x.bi(); + int wi3 = x3.wi(); + int bi3 = x3.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + SC_ASSERT_( wi3 >= 0 && wi3 < size(), "word index out of range" ); + + if( bi3 != bits_in_word - 1 ) + { + if( under ) + m_mant[wi3] &= ~( ((word)-1) << ( bi3 + 1 ) ); + else + m_mant[wi3] |= ( ((word)-1) << ( bi3 + 1 ) ); + } + for( int i = wi3 + 1; i < size(); ++ i ) + { + if( under ) + m_mant[i] = 0; + else + m_mant[i] = static_cast<word>( -1 ); + } + + if( enc == SC_TC_ ) + { + if( under ) + m_mant[wi] |= ( ((word)1) << bi ); + else + m_mant[wi] &= ~( ((word)1) << bi ); + } +} + +inline +void +scfx_rep::o_invert( const scfx_index& x2 ) +{ + int wi2 = x2.wi(); + int bi2 = x2.bi(); + + m_mant[wi2] ^= ( ((word)-1) << bi2 ); + for( int i = wi2 + 1; i < size(); ++ i ) + m_mant[i] = ~ m_mant[i]; +} + +inline +bool +scfx_rep::q_bit( const scfx_index& x ) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + if( bi != 0 ) + return ( m_mant[wi] & ( ((word)1) << ( bi - 1 ) ) ) != 0; + else if( wi != 0 ) + return ( m_mant[wi - 1] & ( ((word)1) << ( bits_in_word - 1 ) ) ) != 0; + else + return false; +} + +inline +void +scfx_rep::q_clear( const scfx_index& x ) +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + m_mant[wi] &= ( ((word)-1) << bi ); + for( int i = wi - 1; i >= 0; -- i ) + m_mant[i] = 0; +} + +inline +void +scfx_rep::q_incr( const scfx_index& x ) +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + word old_val = m_mant[wi]; + m_mant[wi] += ( ((word)1) << bi ); + if( m_mant[wi] <= old_val ) + { + if( wi + 1 == size() ) + resize_to( size() + 1, 1 ); + + for( int i = wi + 1; i < size(); ++ i ) + { + if( ++ m_mant[i] != 0 ) + break; + } + } +} + +inline +bool +scfx_rep::q_odd( const scfx_index& x ) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + return ( m_mant[wi] & ( ((word)1) << bi ) ) != 0; +} + +inline +bool +scfx_rep::q_zero( const scfx_index& x ) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); + + bool zero; + + if( bi != 0 ) + { + zero = ( m_mant[wi] & ~( ((word)-1) << (bi - 1) ) ) == 0; + for( int i = wi - 1; i >= 0; -- i ) + zero = zero && m_mant[i] == 0; + } + else if( wi != 0 ) + { + zero = ( m_mant[wi - 1] & ~( ((word)-1) << (bits_in_word - 1) ) ) == 0; + for( int i = wi - 2; i >= 0; -- i ) + zero = zero && m_mant[i] == 0; + } + else + zero = true; + + return zero; +} + +inline +int +scfx_rep::find_lsw() const +{ + for( int i = 0; i < size(); i ++ ) + { + if( m_mant[i] ) + return i; + } + return 0; +} + +inline +int +scfx_rep::find_msw() const +{ + for( int i = size() - 1; i >= 0; i -- ) + { + if( m_mant[i] ) + return i; + } + return 0; +} + +inline +void +scfx_rep::find_sw() +{ + m_lsw = find_lsw(); + m_msw = find_msw(); +} + +inline +void +scfx_rep::toggle_tc() +{ + if( is_neg() ) + { + complement( m_mant, m_mant, m_mant.size() ); + inc( m_mant ); + } +} + +} // namespace sc_dt + + +#endif + +// Taf! |