📄 scfx_rep.cpp
字号:
/***************************************************************************** The following code is derived, directly or indirectly, from the SystemC source code Copyright (c) 1996-2006 by all Contributors. All Rights reserved. The contents of this file are subject to the restrictions and limitations set forth in the SystemC Open Source License Version 2.4 (the "License"); You may not use this file except in compliance with such restrictions and limitations. You may obtain instructions on how to receive a copy of the License at http://www.systemc.org/. Software distributed by Contributors under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. *****************************************************************************//***************************************************************************** scfx_rep.cpp - 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.cpp,v $// Revision 1.1.1.1 2006/12/15 20:31:36 acg// SystemC 2.2//// Revision 1.3 2006/01/13 18:53:58 acg// Andy Goodrich: added $Log command so that CVS comments are reproduced in// the source.//#include "sysc/utils/sc_machine.h"#include "sysc/datatypes/fx/scfx_rep.h"#include "sysc/datatypes/fx/scfx_ieee.h"#include "sysc/datatypes/fx/scfx_pow10.h"#include "sysc/datatypes/fx/scfx_utils.h"#include "sysc/datatypes/bit/sc_bv_base.h"#include <ctype.h>#include <math.h>namespace sc_dt{// ----------------------------------------------------------------------------// some utilities// ----------------------------------------------------------------------------static scfx_pow10 pow10_fx;static const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int;static inlineintn_word( int x ){ return ( x + bits_in_word - 1 ) / bits_in_word;}// ----------------------------------------------------------------------------// CONSTRUCTORS// ----------------------------------------------------------------------------scfx_rep::scfx_rep(): m_mant( min_mant ), m_r_flag( false ){ set_zero();}scfx_rep::scfx_rep( int a ): m_mant( min_mant ), m_r_flag( false ){ if( a != 0 ) { m_mant.clear(); m_wp = m_msw = m_lsw = 2; m_state = normal; if( a > 0 ) { m_mant[2] = a; m_sign = 1; } else { m_mant[2] = -a; m_sign = -1; } } else set_zero();}scfx_rep::scfx_rep( unsigned int a ): m_mant( min_mant ), m_r_flag( false ){ if( a != 0 ) { m_mant.clear(); m_wp = m_msw = m_lsw = 2; m_state = normal; m_mant[2] = a; m_sign = 1; } else set_zero();}scfx_rep::scfx_rep( long a ): m_mant( min_mant ), m_r_flag( false ){ if( a != 0 ) { m_mant.clear(); m_state = normal; if ( a > 0 ) { m_sign = 1; } else { a = -a; m_sign = -1; } # if defined(SC_LONG_64) m_wp = 1; m_mant[1] = static_cast<word>( a ); m_mant[2] = static_cast<word>( a >> bits_in_word ); find_sw();# else m_wp = 2; m_msw = 2; m_lsw = 2; m_mant[2] = a;# endif } else set_zero();}scfx_rep::scfx_rep( unsigned long a ): m_mant( min_mant ), m_r_flag( false ){ if( a != 0 ) { m_mant.clear(); m_wp = m_msw = m_lsw = 2; m_state = normal;# if defined(SC_LONG_64) m_wp = 1; m_mant[1] = static_cast<word>( a ); m_mant[2] = static_cast<word>( a >> bits_in_word ); find_sw();# else m_wp = 2; m_msw = 2; m_lsw = 2; m_mant[2] = a;# endif m_sign = 1; } else set_zero();}scfx_rep::scfx_rep( double a ): m_mant( min_mant ), m_wp( 0 ), m_state( normal ), m_msw( 0 ), m_lsw( 0 ), m_r_flag( false ){ m_mant.clear(); scfx_ieee_double id( a ); m_sign = id.negative() ? -1 : 1; if( id.is_nan() ) m_state = not_a_number; else if( id.is_inf() ) m_state = infinity; else if( id.is_subnormal() ) { m_mant[0] = id.mantissa1(); m_mant[1] = id.mantissa0(); normalize( id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE ); } else if( id.is_normal() ) { m_mant[0] = id.mantissa1(); m_mant[1] = id.mantissa0() | ( 1 << mantissa0_size ); normalize( id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE ); }}scfx_rep::scfx_rep( int64 a ): m_mant( min_mant ), m_r_flag( false ){ if( a != 0 ) { m_mant.clear(); m_wp = 1; m_state = normal; if( a > 0 ) { m_mant[1] = static_cast<word>( a ); m_mant[2] = static_cast<word>( a >> bits_in_word ); m_sign = 1; } else { m_mant[1] = static_cast<word>( -a ); m_mant[2] = static_cast<word>( (-a) >> bits_in_word ); m_sign = -1; } find_sw(); } else set_zero();}scfx_rep::scfx_rep( uint64 a ): m_mant( min_mant ), m_r_flag( false ){ if( a != 0 ) { m_mant.clear(); m_wp = 1; m_state = normal; m_mant[1] = static_cast<word>( a ); m_mant[2] = static_cast<word>( a >> bits_in_word ); m_sign = 1; find_sw(); } else set_zero();}scfx_rep::scfx_rep( const sc_signed& a ): m_mant( min_mant ), m_r_flag( false ){ if( a.iszero() ) set_zero(); else { int words = n_word( a.length() ); if( words > size() ) resize_to( words ); m_mant.clear(); m_wp = 0; m_state = normal; if( a.sign() ) { sc_signed a2 = -a; for( int i = 0; i < a2.length(); ++ i ) { if( a2[i] ) { scfx_index x = calc_indices( i ); m_mant[x.wi()] |= 1 << x.bi(); } } m_sign = -1; } else { for( int i = 0; i < a.length(); ++ i ) { if( a[i] ) { scfx_index x = calc_indices( i ); m_mant[x.wi()] |= 1 << x.bi(); } } m_sign = 1; } find_sw(); }}scfx_rep::scfx_rep( const sc_unsigned& a ): m_mant( min_mant ), m_r_flag( false ){ if( a.iszero() ) set_zero(); else { int words = n_word( a.length() ); if( words > size() ) resize_to( words ); m_mant.clear(); m_wp = 0; m_state = normal; for( int i = 0; i < a.length(); ++ i ) { if( a[i] ) { scfx_index x = calc_indices( i ); m_mant[x.wi()] |= 1 << x.bi(); } } m_sign = 1; find_sw(); }}// copy constructorscfx_rep::scfx_rep( const scfx_rep& a ): m_mant( a.m_mant ), m_wp( a.m_wp ), m_sign( a.m_sign ), m_state( a.m_state ), m_msw( a.m_msw ), m_lsw( a.m_lsw ), m_r_flag( false ){}// ----------------------------------------------------------------------------// OPERATORS : new, delete//// Memory management for class scfx_rep.// ----------------------------------------------------------------------------union scfx_rep_node{ char data[sizeof( scfx_rep )]; scfx_rep_node* next;};static scfx_rep_node* list = 0;void*scfx_rep::operator new( std::size_t size ){ const int ALLOC_SIZE = 1024; if( size != sizeof( scfx_rep ) ) return ::operator new( size ); if( ! list ) { list = new scfx_rep_node[ALLOC_SIZE]; for( int i = 0; i < ALLOC_SIZE - 1; i ++ ) list[i].next = list + i + 1; list[ALLOC_SIZE - 1].next = 0; } scfx_rep* ptr = reinterpret_cast<scfx_rep*>( list->data ); list = list->next; return ptr;}void scfx_rep::operator delete( void* ptr, std::size_t size ){ if( size != sizeof( scfx_rep ) ) { ::operator delete( ptr ); return; } scfx_rep_node* node = static_cast<scfx_rep_node*>( ptr ); node->next = list; list = node;}// ----------------------------------------------------------------------------// METHOD : from_string//// Convert from character string to sc_fxrep.// ----------------------------------------------------------------------------#define SCFX_FAIL_IF_(cnd) \{ \ if( ( cnd ) ) \ { \ m_state = not_a_number; \ m_mant.clear(); /* to avoid Purify UMRs during assignment */ \ return; \ } \}voidscfx_rep::from_string( const char* s, int cte_wl ){ SCFX_FAIL_IF_( s == 0 || *s == 0 ); scfx_string s2; s2 += s; s2 += '\0'; bool sign_char; m_sign = scfx_parse_sign( s, sign_char ); sc_numrep numrep = scfx_parse_prefix( s ); int base = 0; switch( numrep ) { case SC_DEC: { base = 10; if( scfx_is_nan( s ) ) { // special case: NaN m_state = not_a_number; m_mant.clear(); /* to avoid Purify UMRs during assignment */ return; } if( scfx_is_inf( s ) ) { // special case: Infinity m_state = infinity; m_mant.clear(); /* to avoid Purify UMRs during assignment */ return; } break; } case SC_BIN: case SC_BIN_US: { SCFX_FAIL_IF_( sign_char ); base = 2; break; } case SC_BIN_SM: { base = 2; break; } case SC_OCT: case SC_OCT_US: { SCFX_FAIL_IF_( sign_char ); base = 8; break; } case SC_OCT_SM: { base = 8; break; } case SC_HEX: case SC_HEX_US: { SCFX_FAIL_IF_( sign_char ); base = 16; break; } case SC_HEX_SM: { base = 16; break; } case SC_CSD: { SCFX_FAIL_IF_( sign_char ); base = 2; scfx_csd2tc( s2 ); s = (const char*) s2 + 4; numrep = SC_BIN; break; } default:; } // // find end of mantissa and count the digits and points // const char *end = s; bool based_point = false; int int_digits = 0; int frac_digits = 0; while( *end ) { if( scfx_exp_start( end ) ) break; if( *end == '.' ) { SCFX_FAIL_IF_( based_point ); based_point = true; } else { SCFX_FAIL_IF_( ! scfx_is_digit( *end, numrep ) ); if( based_point ) frac_digits ++; else int_digits ++; } ++ end; } SCFX_FAIL_IF_( int_digits == 0 && frac_digits == 0 ); // [ exponent ] int exponent = 0; if( *end ) { for( const char *e = end + 2; *e; ++ e ) SCFX_FAIL_IF_( ! scfx_is_digit( *e, SC_DEC ) ); exponent = atoi( end + 1 ); } // // check if the mantissa is negative // bool mant_is_neg = false; switch( numrep ) { case SC_BIN: case SC_OCT: case SC_HEX: { const char* p = s; if( *p == '.' ) ++ p; mant_is_neg = ( scfx_to_digit( *p, numrep ) >= ( base >> 1 ) ); break; } default: ; } // // convert the mantissa // switch( base ) { case 2: { int bit_offset = exponent % bits_in_word; int word_offset = exponent / bits_in_word; int_digits += bit_offset; frac_digits -= bit_offset; int words = n_word( int_digits ) + n_word( frac_digits ); if( words > size() ) resize_to( words ); m_mant.clear(); int j = n_word( frac_digits ) * bits_in_word + int_digits - 1; for( ; s < end; s ++ ) { switch( *s ) { case '1': set_bin( j ); case '0': j --; case '.': break; default: SCFX_FAIL_IF_( true ); // should not happen } } m_wp = n_word( frac_digits ) - word_offset; break; } case 8: { exponent *= 3; int_digits *= 3; frac_digits *= 3; int bit_offset = exponent % bits_in_word; int word_offset = exponent / bits_in_word; int_digits += bit_offset; frac_digits -= bit_offset; int words = n_word( int_digits ) + n_word( frac_digits ); if( words > size() ) resize_to( words ); m_mant.clear(); int j = n_word( frac_digits ) * bits_in_word + int_digits - 3; for( ; s < end; s ++ ) { switch( *s ) { case '7': case '6': case '5': case '4': case '3': case '2': case '1': set_oct( j, *s - '0' ); case '0': j -= 3; case '.': break; default: SCFX_FAIL_IF_( true ); // should not happen } } m_wp = n_word( frac_digits ) - word_offset; break; } case 10: { word carry, temp; int length = int_digits + frac_digits; resize_to( sc_max( min_mant, n_word( 4 * length ) ) ); m_mant.clear(); m_msw = m_lsw = 0; for( ; s < end; s ++ ) { switch( *s ) { case '9': case '8': case '7': case '6': case '5': case '4': case '3': case '2': case '1': case '0': multiply_by_ten(); carry = *s - '0'; for ( int i = 0; carry && i < m_mant.size(); i++ ) { temp = m_mant[i]; temp += carry; carry = temp < m_mant[i]; m_mant[i] = temp; } case '.': break; default: SCFX_FAIL_IF_( true ); // should not happen } } m_wp = 0; find_sw(); int denominator = frac_digits - exponent; if( denominator ) { scfx_rep frac_num = pow10_fx( denominator ); scfx_rep* temp_num = div_scfx_rep( const_cast<const scfx_rep&>( *this ), frac_num, cte_wl ); *this = *temp_num; delete temp_num; } break; } case 16: { exponent *= 4; int_digits *= 4; frac_digits *= 4; int bit_offset = exponent % bits_in_word; int word_offset = exponent / bits_in_word; int_digits += bit_offset; frac_digits -= bit_offset; int words = n_word( int_digits ) + n_word( frac_digits ); if( words > size() ) resize_to( words ); m_mant.clear(); int j = n_word( frac_digits ) * bits_in_word + int_digits - 4; for( ; s < end; s ++ ) { switch( *s ) { case 'f': case 'e': case 'd': case 'c': case 'b': case 'a': set_hex( j, *s - 'a' + 10 ); j -= 4; break; case 'F': case 'E': case 'D': case 'C': case 'B': case 'A': set_hex( j, *s - 'A' + 10 ); j -= 4; break; case '9': case '8': case '7': case '6': case '5': case '4': case '3': case '2': case '1': set_hex( j, *s - '0' ); case '0': j -= 4; case '.': break; default: SCFX_FAIL_IF_( true ); // should not happen } } m_wp = n_word( frac_digits ) - word_offset; break; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -