summaryrefslogtreecommitdiff
path: root/ext/systemc/src/sysc/datatypes/fx/scfx_rep.h
diff options
context:
space:
mode:
Diffstat (limited to 'ext/systemc/src/sysc/datatypes/fx/scfx_rep.h')
-rw-r--r--ext/systemc/src/sysc/datatypes/fx/scfx_rep.h842
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!