📄 scfx_rep.cpp
字号:
if( under ) o_set_low( x, SC_TC_ ); else o_set_high( x, x2, SC_TC_ ); } break; } default: ; } find_sw(); }}// ----------------------------------------------------------------------------// PUBLIC METHOD : cast//// Performs a destructive cast operation on a scfx_rep.// ----------------------------------------------------------------------------voidscfx_rep::cast( const scfx_params& params, bool& q_flag, bool& o_flag ){ q_flag = false; o_flag = false; // check for special cases if( is_zero() ) { if( is_neg() ) m_sign = 1; return; } // perform casting quantization( params, q_flag ); overflow( params, o_flag ); // check for special case: -0 if( is_zero() && is_neg() ) m_sign = 1;}// ----------------------------------------------------------------------------// make sure, the two mantissas are aligned// ----------------------------------------------------------------------------voidalign( const scfx_rep& lhs, const scfx_rep& rhs, int& new_wp, int& len_mant, scfx_mant_ref& lhs_mant, scfx_mant_ref& rhs_mant ){ bool need_lhs = true; bool need_rhs = true; if( lhs.m_wp != rhs.m_wp || lhs.size() != rhs.size() ) { int lower_bound_lhs = lhs.m_lsw - lhs.m_wp; int upper_bound_lhs = lhs.m_msw - lhs.m_wp; int lower_bound_rhs = rhs.m_lsw - rhs.m_wp; int upper_bound_rhs = rhs.m_msw - rhs.m_wp; int lower_bound = sc_min( lower_bound_lhs, lower_bound_rhs ); int upper_bound = sc_max( upper_bound_lhs, upper_bound_rhs ); new_wp = -lower_bound; len_mant = sc_max( min_mant, upper_bound - lower_bound + 1 ); if( new_wp != lhs.m_wp || len_mant != lhs.size() ) { lhs_mant = lhs.resize( len_mant, new_wp ); need_lhs = false; } if( new_wp != rhs.m_wp || len_mant != rhs.size() ) { rhs_mant = rhs.resize( len_mant, new_wp ); need_rhs = false; } } if( need_lhs ) { lhs_mant = lhs.m_mant; } if( need_rhs ) { rhs_mant = rhs.m_mant; }}// ----------------------------------------------------------------------------// compare two mantissas// ----------------------------------------------------------------------------intcompare_msw_ff( const scfx_rep& lhs, const scfx_rep& rhs ){ // special case: rhs.m_mant[rhs.m_msw + 1] == 1 if( rhs.m_msw < rhs.size() - 1 && rhs.m_mant[rhs.m_msw + 1 ] != 0 ) { return -1; } int lhs_size = lhs.m_msw - lhs.m_lsw + 1; int rhs_size = rhs.m_msw - rhs.m_lsw + 1; int size = sc_min( lhs_size, rhs_size ); int lhs_index = lhs.m_msw; int rhs_index = rhs.m_msw; int i; for( i = 0; i < size && lhs.m_mant[lhs_index] == rhs.m_mant[rhs_index]; i ++ ) { lhs_index --; rhs_index --; } if( i == size ) { if( lhs_size == rhs_size ) { return 0; } if( lhs_size < rhs_size ) { return -1; } else { return 1; } } if( lhs.m_mant[lhs_index] < rhs.m_mant[rhs_index] ) { return -1; } else { return 1; }}// ----------------------------------------------------------------------------// divide the mantissa by ten// ----------------------------------------------------------------------------unsigned intscfx_rep::divide_by_ten(){#if defined( SC_BIG_ENDIAN ) half_word* hw = (half_word*) &m_mant[m_msw];#elif defined( SC_LITTLE_ENDIAN ) half_word* hw = ( (half_word*) &m_mant[m_msw] ) + 1;#endif unsigned int remainder = 0; word_short ls; ls.l = 0;#if defined( SC_BIG_ENDIAN ) for( int i = 0, end = ( m_msw - m_wp + 1 ) * 2; i < end; i ++ )#elif defined( SC_LITTLE_ENDIAN ) for( int i = 0, end = -( m_msw - m_wp + 1 ) * 2; i > end; i -- )#endif { ls.s.u = static_cast<half_word>( remainder ); ls.s.l = hw[i]; remainder = ls.l % 10; ls.l /= 10; hw[i] = ls.s.l; } return remainder;}// ----------------------------------------------------------------------------// multiply the mantissa by ten// ----------------------------------------------------------------------------voidscfx_rep::multiply_by_ten(){ int size = m_mant.size() + 1; scfx_mant mant8( size ); scfx_mant mant2( size ); size --; mant8[size] = (m_mant[size - 1] >> (bits_in_word - 3)); mant2[size] = (m_mant[size - 1] >> (bits_in_word - 1)); while( -- size ) { mant8[size] = ( m_mant[size] << 3 ) | ( m_mant[size - 1] >> ( bits_in_word - 3 ) ); mant2[size] = ( m_mant[size] << 1 ) | ( m_mant[size - 1] >> ( bits_in_word - 1 ) ); } mant8[0] = ( m_mant[0] << 3 ); mant2[0] = ( m_mant[0] << 1 ); add_mants( m_mant.size(), m_mant, mant8, mant2 );#if 0 for( int i = size() - 1; i > 0; i -- ) { m_mant[i] = ( m_mant[i] << 3 ) | ( m_mant[i-1] >> ( bits_in_word - 3 ) ) + ( m_mant[i] << 1 ) | ( m_mant[i-1] >> ( bits_in_word - 1 ) ); } m_mant[0] = ( m_mant[0] << 3 ) + ( m_mant[0] << 1 );#endif}// ----------------------------------------------------------------------------// normalize// ----------------------------------------------------------------------------voidscfx_rep::normalize( int exponent ){ int shift = exponent % bits_in_word; if( shift < 0 ) { shift += bits_in_word; } if( shift ) { shift_left( shift ); } find_sw(); m_wp = (shift - exponent) / bits_in_word;}// ----------------------------------------------------------------------------// return a new mantissa that is aligned and resized// ----------------------------------------------------------------------------scfx_mant*scfx_rep::resize( int new_size, int new_wp ) const{ scfx_mant *result = new scfx_mant( new_size ); result->clear(); int shift = new_wp - m_wp; for( int j = m_lsw; j <= m_msw; j ++ ) { (*result)[j+shift] = m_mant[j]; } return result;}// ----------------------------------------------------------------------------// set a single bit// ----------------------------------------------------------------------------voidscfx_rep::set_bin( int i ){ m_mant[i >> 5] |= 1 << ( i & 31 );}// ----------------------------------------------------------------------------// set three bits// ----------------------------------------------------------------------------voidscfx_rep::set_oct( int i, int n ){ if( n & 1 ) { m_mant[i >> 5] |= 1 << ( i & 31 ); } i ++; if( n & 2 ) { m_mant[i >> 5] |= 1 << ( i & 31 ); } i ++; if( n & 4 ) { m_mant[i >> 5] |= 1 << ( i & 31 ); }}// ----------------------------------------------------------------------------// set four bits// ----------------------------------------------------------------------------voidscfx_rep::set_hex( int i, int n ){ if( n & 1 ) { m_mant[i >> 5] |= 1 << ( i & 31 ); } i ++; if( n & 2 ) { m_mant[i >> 5] |= 1 << ( i & 31 ); } i ++; if( n & 4 ) { m_mant[i >> 5] |= 1 << ( i & 31 ); } i ++; if( n & 8 ) { m_mant[i >> 5] |= 1 << ( i & 31 ); }}// ----------------------------------------------------------------------------// PRIVATE METHOD : shift_left//// Shifts a scfx_rep to the left by a MAXIMUM of bits_in_word - 1 bits.// ----------------------------------------------------------------------------voidscfx_rep::shift_left( int n ){ if( n != 0 ) { int shift_left = n; int shift_right = bits_in_word - n; SC_ASSERT_( !(m_mant[size()-1] >> shift_right), "shift_left overflow" ); for( int i = size() - 1; i > 0; i -- ) { m_mant[i] = ( m_mant[i] << shift_left ) | ( m_mant[i-1] >> shift_right ); } m_mant[0] <<= shift_left; }}// ----------------------------------------------------------------------------// PRIVATE METHOD : shift_right//// Shifts a scfx_rep to the right by a MAXIMUM of bits_in_word - 1 bits.// ----------------------------------------------------------------------------voidscfx_rep::shift_right( int n ){ if( n != 0 ) { int shift_left = bits_in_word - n; int shift_right = n; SC_ASSERT_( !(m_mant[0] << shift_left), "shift_right overflow" ); for( int i = 0; i < size() - 1; i ++ ) { m_mant[i] = ( m_mant[i] >> shift_right ) | ( m_mant[i+1] << shift_left ); } m_mant[size()-1] >>= shift_right; }}// ----------------------------------------------------------------------------// METHOD : get_bit//// Tests a bit, in two's complement.// ----------------------------------------------------------------------------boolscfx_rep::get_bit( int i ) const{ if( ! is_normal() ) return false; scfx_index x = calc_indices( i ); if( x.wi() >= size() ) return is_neg(); if( x.wi() < 0 ) return false; const_cast<scfx_rep*>( this )->toggle_tc(); bool result = ( m_mant[x.wi()] & ( 1 << x.bi() ) ) != 0; const_cast<scfx_rep*>( this )->toggle_tc(); return result;}// ----------------------------------------------------------------------------// METHOD : set//// Sets a bit, in two's complement, between iwl-1 and -fwl.// ----------------------------------------------------------------------------boolscfx_rep::set( int i, const scfx_params& params ){ if( ! is_normal() ) return false; scfx_index x = calc_indices( i ); if( x.wi() >= size() ) { if( is_neg() ) return true; else resize_to( x.wi() + 1, 1 ); } else if( x.wi() < 0 ) { resize_to( size() - x.wi(), -1 ); x.wi( 0 ); } toggle_tc(); m_mant[x.wi()] |= 1 << x.bi(); if( i == params.iwl() - 1 ) o_extend( x, params.enc() ); // sign extension toggle_tc(); find_sw(); return true;}// ----------------------------------------------------------------------------// METHOD : clear//// Clears a bit, in two's complement, between iwl-1 and -fwl.// ----------------------------------------------------------------------------boolscfx_rep::clear( int i, const scfx_params& params ){ if( ! is_normal() ) return false; scfx_index x = calc_indices( i ); if( x.wi() >= size() ) { if( ! is_neg() ) return true; else resize_to( x.wi() + 1, 1 ); } else if( x.wi() < 0 ) return true; toggle_tc(); m_mant[x.wi()] &= ~( 1 << x.bi() ); if( i == params.iwl() - 1 ) o_extend( x, params.enc() ); // sign extension toggle_tc(); find_sw(); return true;}// ----------------------------------------------------------------------------// METHOD : get_slice// ----------------------------------------------------------------------------boolscfx_rep::get_slice( int i, int j, const scfx_params&, sc_bv_base& bv ) const{ if( is_nan() || is_inf() ) return false; // get the bits int l = j; for( int k = 0; k < bv.length(); ++ k ) { bv[k] = get_bit( l ); if( i >= j ) ++ l; else -- l; } return true;}boolscfx_rep::set_slice( int i, int j, const scfx_params& params, const sc_bv_base& bv ){ if( is_nan() || is_inf() ) return false; // set the bits int l = j; for( int k = 0; k < bv.length(); ++ k ) { if( bv[k].to_bool() ) set( l, params ); else clear( l, params ); if( i >= j ) ++ l; else -- l; } return true;}// ----------------------------------------------------------------------------// METHOD : print// ----------------------------------------------------------------------------voidscfx_rep::print( ::std::ostream& os ) const{ os << to_string( SC_DEC, -1, SC_E );}// ----------------------------------------------------------------------------// METHOD : dump// ----------------------------------------------------------------------------voidscfx_rep::dump( ::std::ostream& os ) const{ os << "scfx_rep" << ::std::endl; os << "(" << ::std::endl; os << "mant =" << ::std::endl; for( int i = size() - 1; i >= 0; i -- ) { char buf[BUFSIZ]; std::sprintf( buf, " %d: %10u (%8x)", i, (int) m_mant[i], (int) m_mant[i] ); os << buf << ::std::endl; } os << "wp = " << m_wp << ::std::endl; os << "sign = " << m_sign << ::std::endl; os << "state = "; switch( m_state ) { case normal: os << "normal"; break; case infinity: os << "infinity"; break; case not_a_number: os << "not_a_number"; break; default: os << "unknown"; } os << ::std::endl; os << "msw = " << m_msw << ::std::endl; os << "lsw = " << m_lsw << ::std::endl; os << ")" << ::std::endl;}// ----------------------------------------------------------------------------// METHOD : get_type// ----------------------------------------------------------------------------voidscfx_rep::get_type( int& wl, int& iwl, sc_enc& enc ) const{ if( is_nan() || is_inf() ) { wl = 0; iwl = 0; enc = SC_TC_; return; } if( is_zero() ) { wl = 1; iwl = 1; enc = SC_US_; return; } int msb = ( m_msw - m_wp ) * bits_in_word + scfx_find_msb( m_mant[ m_msw ] ) + 1; while( get_bit( msb ) == get_bit( msb - 1 ) ) { -- msb; } int lsb = ( m_lsw - m_wp ) * bits_in_word + scfx_find_lsb( m_mant[ m_lsw ] ); if( is_neg() ) { wl = msb - lsb + 1; iwl = msb + 1; enc = SC_TC_; } else { wl = msb - lsb; iwl = msb; enc = SC_US_; }}// ----------------------------------------------------------------------------// PRIVATE METHOD : round//// Performs convergent rounding (rounding to even) as in floating-point.// ----------------------------------------------------------------------------voidscfx_rep::round( int wl ){ // check for special cases if( is_nan() || is_inf() || is_zero() ) return; // estimate effective wordlength and compare int wl_effective; wl_effective = ( m_msw - m_lsw + 1 ) * bits_in_word; if( wl_effective <= wl ) return; // calculate effective wordlength and compare int msb = scfx_find_msb( m_mant[m_msw] ); int lsb = scfx_find_lsb( m_mant[m_lsw] ); wl_effective = ( m_msw * bits_in_word + msb ) - ( m_lsw * bits_in_word + lsb ) + 1; if( wl_effective <= wl ) return; // perform rounding int wi = m_msw - ( wl - 1 ) / bits_in_word; int bi = msb - ( wl - 1 ) % bits_in_word; if( bi < 0 ) { -- wi; bi += bits_in_word; } scfx_index x( wi, bi ); if( q_bit( x ) && ! q_zero( x ) || q_bit( x ) && q_zero( x ) && q_odd( x ) ) q_incr( x ); q_clear( x ); find_sw(); m_r_flag = true;}} // namespace sc_dt// Taf!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -