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 #ifndef SCFX_MANT_H
00050 #define SCFX_MANT_H
00051 
00052 
00053 #include "sysc/datatypes/fx/scfx_ieee.h"
00054 #include "sysc/datatypes/fx/scfx_utils.h"
00055 #include "sysc/kernel/sc_macros.h"
00056 
00057 #include <pthread.h> 
00058 
00059 
00060 namespace sc_dt
00061 {
00062 
00063 
00064 class scfx_mant;
00065 class scfx_mant_ref;
00066 
00067 
00068 typedef unsigned int  word;       
00069 typedef unsigned short half_word;
00070 
00074 
00075 struct scfx_mant_free_words_lock {
00076     static pthread_mutex_t m_mutex;
00077     explicit scfx_mant_free_words_lock();
00078     ~scfx_mant_free_words_lock();
00079 };
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 class scfx_mant
00089 {
00090 
00091     word* m_array;
00092     int   m_size;
00093 
00094 public:
00095 
00096     explicit scfx_mant( std::size_t );
00097              scfx_mant( const scfx_mant& );
00098 
00099     scfx_mant& operator = ( const scfx_mant& );
00100 
00101     ~scfx_mant();
00102 
00103     void clear();
00104 
00105     void resize_to( int, int = 0 );
00106 
00107     int size() const;
00108 
00109     word  operator [] ( int ) const;
00110     word& operator [] ( int );
00111 
00112     half_word  half_at( int ) const;
00113     half_word& half_at( int );
00114 
00115     half_word* half_addr( int = 0 ) const;
00116 
00117 private:
00118 
00119     static word* alloc( std::size_t );
00120     static void free( word*, std::size_t );
00121 
00122     static word* alloc_word( std::size_t size );
00123     static void free_word( word* array, std::size_t size );
00124 
00125 };
00126 
00127 
00128 
00129 
00130 inline
00131 int
00132 scfx_mant::size() const
00133 {
00134     return m_size;
00135 }
00136 
00137 
00138 inline
00139 word*
00140 scfx_mant::alloc( std::size_t size )
00141 {
00142 #if defined( SC_BIG_ENDIAN )
00143     return alloc_word( size ) + ( size - 1 );
00144 #elif defined( SC_LITTLE_ENDIAN )
00145     return alloc_word( size );
00146 #endif
00147 }
00148 
00149 inline
00150 void
00151 scfx_mant::free( word* mant, std::size_t size )
00152 {
00153 #if defined( SC_BIG_ENDIAN )
00154     free_word( mant - ( size - 1 ), size );
00155 #elif defined( SC_LITTLE_ENDIAN )
00156     free_word( mant, size );
00157 #endif
00158 }
00159 
00160 inline
00161 word
00162 scfx_mant::operator[]( int i ) const
00163 {
00164     SC_ASSERT_( i >= 0 && i < m_size, "mantissa index out of range" );
00165 #if defined( SC_BIG_ENDIAN )
00166     return m_array[-i];
00167 #elif defined( SC_LITTLE_ENDIAN )
00168     return m_array[i];
00169 #endif
00170 }
00171 
00172 inline
00173 word&
00174 scfx_mant::operator[]( int i )
00175 {
00176     SC_ASSERT_( i >= 0 && i < m_size, "mantissa index out of range" );
00177 #if defined( SC_BIG_ENDIAN )
00178     return m_array[-i];
00179 #elif defined( SC_LITTLE_ENDIAN )
00180     return m_array[i];
00181 #endif
00182 }
00183 
00184 inline
00185 scfx_mant::scfx_mant( std::size_t size )
00186 : m_array(0), m_size(size)
00187 {
00188     m_array = alloc( size );
00189 }
00190 
00191 inline
00192 scfx_mant::scfx_mant( const scfx_mant& rhs )
00193 : m_array(0), m_size(rhs.m_size)
00194 {
00195     m_array = alloc( m_size );
00196     for( int i = 0; i < m_size; i ++ )
00197     {
00198         (*this)[i] = rhs[i];
00199     }
00200 }
00201 
00202 inline
00203 scfx_mant&
00204 scfx_mant::operator = ( const scfx_mant& rhs )
00205 {
00206     if( &rhs != this )
00207     {
00208         if( m_size != rhs.m_size )
00209         {
00210             free( m_array, m_size );
00211             m_array = alloc( m_size = rhs.m_size );
00212         }
00213 
00214         for( int i = 0; i < m_size; i ++ )
00215         {
00216             (*this)[i] = rhs[i];
00217         }
00218     }
00219     return *this;
00220 }
00221 
00222 inline
00223 scfx_mant::~scfx_mant()
00224 {
00225     if( m_array != 0 )
00226     {
00227         free( m_array, m_size );
00228     }
00229 }
00230 
00231 inline
00232 void
00233 scfx_mant::clear()
00234 {
00235     for( int i = 0; i < m_size; i ++ )
00236     {
00237         (*this)[i] = 0;
00238     }
00239 }
00240 
00241 inline
00242 void
00243 scfx_mant::resize_to( int size, int restore )
00244 {
00245     if( size == m_size )
00246     {
00247         return;
00248     }
00249 
00250     if( ! m_array )
00251     {
00252         m_array = alloc( m_size = size );
00253     }
00254     else
00255     {
00256         word* p = alloc( size );
00257 
00258         if( restore )
00259         {
00260             int end = sc_min( size, m_size );
00261             if( restore == 1 )          
00262             {
00263                 for( int i = 0; i < size; i ++ )
00264                 {
00265                     if( i < end )
00266                     {
00267 #if defined( SC_BIG_ENDIAN )
00268                         p[-i] = m_array[-i];
00269 #elif defined( SC_LITTLE_ENDIAN )
00270                         p[i] = m_array[i];
00271 #endif
00272                     }
00273                     else
00274                     {
00275 #if defined( SC_BIG_ENDIAN )
00276                         p[-i] = 0;
00277 #elif defined( SC_LITTLE_ENDIAN )
00278                         p[i] = 0;
00279 #endif
00280                     }
00281                 }
00282             }
00283             else                        
00284             {
00285                 for( int i = 0; i < size; i ++ )
00286                 {
00287                     if( i < end )
00288                     {
00289 #if defined( SC_BIG_ENDIAN )
00290                         p[-size+1+i] = m_array[-m_size+1+i];
00291 #elif defined( SC_LITTLE_ENDIAN )
00292                         p[size-1-i] = m_array[m_size-1-i];
00293 #endif
00294                     }
00295                     else
00296                     {
00297 #if defined( SC_BIG_ENDIAN )
00298                         p[-size+1+i] = 0;
00299 #elif defined( SC_LITTLE_ENDIAN )
00300                         p[size-1-i] = 0;
00301 #endif
00302                     }
00303                 }
00304             }
00305         }
00306 
00307         free( m_array, m_size );
00308         m_array = p;
00309         m_size = size;
00310     }
00311 }
00312 
00313 inline
00314 half_word
00315 scfx_mant::half_at( int i ) const
00316 {
00317     SC_ASSERT_( ( i >> 1 ) >= 0 && ( i >> 1 ) < m_size,
00318                 "mantissa index out of range" );
00319 #if defined( SC_BIG_ENDIAN )
00320     return reinterpret_cast<half_word*>( m_array )[-i];
00321 #elif defined( SC_LITTLE_ENDIAN )
00322     return reinterpret_cast<half_word*>( m_array )[i];
00323 #endif
00324 }
00325 
00326 inline
00327 half_word&
00328 scfx_mant::half_at( int i )
00329 {
00330     SC_ASSERT_( ( i >> 1 ) >= 0 && ( i >> 1 ) < m_size,
00331                 "mantissa index out of range" );
00332 #if defined( SC_BIG_ENDIAN )
00333     return reinterpret_cast<half_word*>( m_array )[-i];
00334 #elif defined( SC_LITTLE_ENDIAN )
00335     return reinterpret_cast<half_word*>( m_array )[i];
00336 #endif
00337 }
00338 
00339 inline
00340 half_word*
00341 scfx_mant::half_addr( int i ) const
00342 {
00343     SC_ASSERT_( i >= 0 && i < m_size, "mantissa index out of range" );
00344 #if defined( SC_BIG_ENDIAN )
00345     return reinterpret_cast<half_word*>( m_array - i ) + 1;
00346 #elif defined( SC_LITTLE_ENDIAN )
00347     return reinterpret_cast<half_word*>( m_array + i );
00348 #endif
00349 }
00350 
00351 
00352 
00353 
00354 
00355 
00356 inline
00357 void
00358 complement( scfx_mant& target, const scfx_mant& source, int size )
00359 {
00360     for( int i = 0; i < size; i ++ )
00361     {
00362         target[i] = ~source[i];
00363     }
00364 }
00365 
00366 
00367 
00368 
00369 
00370 
00371 inline
00372 void
00373 inc( scfx_mant& mant )
00374 {
00375     for( int i = 0; i < mant.size(); i ++ )
00376     {
00377         if( ++ mant[i] )
00378         {
00379             break;
00380         }
00381     }
00382 }
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 class scfx_mant_ref
00392 {
00393 
00394     scfx_mant* m_mant;
00395     bool       m_not_const;
00396 
00397 public:
00398 
00399     scfx_mant_ref();
00400     scfx_mant_ref( const scfx_mant& );
00401     scfx_mant_ref( scfx_mant* );
00402 
00403     scfx_mant_ref& operator = ( const scfx_mant& );
00404     scfx_mant_ref& operator = ( scfx_mant* );
00405 
00406     ~scfx_mant_ref();
00407 
00408     operator scfx_mant&();
00409 
00410     word operator [] ( int );
00411 
00412 private:
00413 
00414     void remove_it();
00415 
00416     scfx_mant_ref( const scfx_mant_ref& );
00417     scfx_mant_ref& operator = ( const scfx_mant_ref& );
00418 
00419     void* operator new( std::size_t sz ) { return ::operator new( sz ); }
00420 
00421 };
00422 
00423 
00424 
00425 
00426 inline
00427 void
00428 scfx_mant_ref::remove_it()
00429 {
00430     if( m_not_const )
00431     {
00432         delete m_mant;
00433     }
00434 }
00435 
00436 inline
00437 scfx_mant_ref::scfx_mant_ref()
00438 : m_mant( 0 ), m_not_const( false )
00439 {}
00440 
00441 inline
00442 scfx_mant_ref::scfx_mant_ref( const scfx_mant& mant )
00443 : m_mant( const_cast<scfx_mant*>( &mant ) ), m_not_const( false )
00444 {}
00445 
00446 inline
00447 scfx_mant_ref::scfx_mant_ref( scfx_mant* mant )
00448 : m_mant( mant ), m_not_const( true )
00449 {}
00450 
00451 inline
00452 scfx_mant_ref&
00453 scfx_mant_ref::operator = ( const scfx_mant& mant )
00454 {
00455     remove_it();
00456 
00457     m_mant = const_cast<scfx_mant*>( &mant );
00458     m_not_const = false;
00459 
00460     return *this;
00461 }
00462 
00463 inline
00464 scfx_mant_ref&
00465 scfx_mant_ref::operator = ( scfx_mant* mant )
00466 {
00467     remove_it();
00468 
00469     m_mant = mant;
00470     m_not_const = true;
00471 
00472     return *this;
00473 }
00474 
00475 inline
00476 scfx_mant_ref::~scfx_mant_ref()
00477 {
00478     remove_it();
00479 }
00480 
00481 inline
00482 scfx_mant_ref::operator scfx_mant&()
00483 {
00484     
00485     return *m_mant;
00486 }
00487 
00488 inline
00489 word
00490 scfx_mant_ref::operator [] ( int i )
00491 {
00492     return (*m_mant)[i];
00493 }
00494 
00495 } 
00496 
00497 
00498 #endif
00499 
00500