⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scfx_rep.cpp

📁 system C源码 一种替代verilog的语言
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    //    // do it    //    if( lhs.m_sign != rhs.m_sign )    {	add_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );	result.m_sign = lhs.m_sign;    }    else    {	int cmp = compare_abs( lhs, rhs );	if( cmp == 1 )	{	    sub_mants( len_mant, result.m_mant, lhs_mant, rhs_mant );	    result.m_sign = lhs.m_sign;	}	else if ( cmp == -1 )	{	    sub_mants( len_mant, result.m_mant, rhs_mant, lhs_mant );	    result.m_sign = -rhs.m_sign;	} else {	    result.m_mant.clear();	    result.m_sign = 1;	}    }    result.find_sw();    result.round( max_wl );    return &result;}// ----------------------------------------------------------------------------//  MUL// ----------------------------------------------------------------------------union word_short{    word l;    struct    {#if defined( SC_BIG_ENDIAN )        half_word u;        half_word l;#elif defined( SC_LITTLE_ENDIAN )        half_word l;        half_word u;#endif    } s;};#if defined( SC_BIG_ENDIAN )static const int half_word_incr = -1;#elif defined( SC_LITTLE_ENDIAN )static const int half_word_incr = 1;#endifvoidmultiply( scfx_rep& result, const scfx_rep& lhs, const scfx_rep& rhs,	  int max_wl ){    //    // check for special cases    //    if( lhs.is_nan() || rhs.is_nan()    ||  lhs.is_inf() && rhs.is_zero()    ||  lhs.is_zero() && rhs.is_inf() )    {	result.set_nan();	return;    }    if( lhs.is_inf() || rhs.is_inf() )    {	result.set_inf( lhs.m_sign * rhs.m_sign );	return;    }        if( lhs.is_zero() || rhs.is_zero() ) {	result.set_zero( lhs.m_sign * rhs.m_sign );	return;    }    //    // do it    //    int len_lhs = lhs.m_msw - lhs.m_lsw + 1;    int len_rhs = rhs.m_msw - rhs.m_lsw + 1;    int new_size = sc_max( min_mant, len_lhs + len_rhs );    int new_wp   = ( lhs.m_wp - lhs.m_lsw ) + ( rhs.m_wp - rhs.m_lsw );    int new_sign = lhs.m_sign * rhs.m_sign;    result.resize_to( new_size );    result.m_mant.clear();    result.m_wp    = new_wp;    result.m_sign  = new_sign;    result.m_state = scfx_rep::normal;    half_word *s1 = lhs.m_mant.half_addr( lhs.m_lsw );    half_word *s2 = rhs.m_mant.half_addr( rhs.m_lsw );    half_word *t = result.m_mant.half_addr();    len_lhs <<= 1;    len_rhs <<= 1;    int i1, i2;    for( i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr )    {	register word_short ls;	ls.l = 0;	half_word v1 = s1[i1];	for( i2  = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr )	{	    ls.l  += v1 * s2[i2];	    ls.s.l = ls.s.u + ( ( t[i2] += ls.s.l ) < ls.s.l );	    ls.s.u = 0;	}	t[i2] = ls.s.l;	t += half_word_incr;    }    result.find_sw();    result.round( max_wl );}// ----------------------------------------------------------------------------//  DIV// ----------------------------------------------------------------------------scfx_rep*div_scfx_rep( const scfx_rep& lhs, const scfx_rep& rhs, int div_wl ){    scfx_rep& result = *new scfx_rep;    //    // check for special cases    //    if( lhs.is_nan() || rhs.is_nan() || lhs.is_inf() && rhs.is_inf() ||	lhs.is_zero() && rhs.is_zero() )    {	result.set_nan();	return &result;    }    if( lhs.is_inf() || rhs.is_zero() )    {	result.set_inf( lhs.m_sign * rhs.m_sign );	return &result;    }    if( lhs.is_zero() || rhs.is_inf() )    {	result.set_zero( lhs.m_sign * rhs.m_sign );	return &result;    }    //    // do it    //    // compute one bit more for rounding    div_wl ++;    result.resize_to( sc_max( n_word( div_wl ) + 1, min_mant ) );    result.m_mant.clear();    result.m_sign = lhs.m_sign * rhs.m_sign;    int msb_lhs = scfx_find_msb( lhs.m_mant[lhs.m_msw] )	        + ( lhs.m_msw - lhs.m_wp ) * bits_in_word;    int msb_rhs = scfx_find_msb( rhs.m_mant[rhs.m_msw] )	        + ( rhs.m_msw - rhs.m_wp ) * bits_in_word;    int msb_res = msb_lhs - msb_rhs;    int to_shift = -msb_res % bits_in_word;    int result_index;    int c = ( msb_res % bits_in_word >= 0 ) ? 1 : 0;    result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word;    result.m_wp   = (result.size() - c) - msb_res / bits_in_word;    scfx_rep remainder = lhs;    // align msb from remainder to msb from rhs    remainder.lshift( to_shift );    // make sure msw( remainder ) < size - 1    if( remainder.m_msw == remainder.size() - 1 )	remainder.resize_to( remainder.size() + 1, 1 );    // make sure msw( remainder ) >= msw( rhs )!    int msw_diff = rhs.m_msw - remainder.m_msw;    if (msw_diff > 0)	remainder.resize_to( remainder.size() + msw_diff, -1 );    int counter;    for( counter = div_wl; counter && ! remainder.is_zero(); counter -- )    {	if( compare_msw_ff( rhs, remainder ) <= 0 )	{	    result.set_bin( result_index );	    sub_with_index( remainder.m_mant, remainder.m_msw, remainder.m_lsw,			    rhs.m_mant, rhs.m_msw, rhs.m_lsw );	}	result_index --;	remainder.shift_left( 1 );        remainder.m_lsw = remainder.find_lsw();    }    // perform convergent rounding, if needed    if( counter == 0 )    {	int index = result_index + 1 - result.m_wp * bits_in_word;	scfx_index x = result.calc_indices( index );	scfx_index x1 = result.calc_indices( index + 1 );	if( result.o_bit_at( x ) && result.o_bit_at( x1 ) )	    result.q_incr( x );	result.m_r_flag = true;    }    result.find_sw();    return &result;}// ----------------------------------------------------------------------------//  destructive shift mantissa to the left// ----------------------------------------------------------------------------voidscfx_rep::lshift( int n ){    if( n == 0 )        return;    if( n < 0 )    {        rshift( -n );	return;    }    if( is_normal() )    {        int shift_bits  = n % bits_in_word;	int shift_words = n / bits_in_word;	// resize if needed	if( m_msw == size() - 1 &&	    scfx_find_msb( m_mant[m_msw] ) >= bits_in_word - shift_bits )	    resize_to( size() + 1, 1 );	// do it	m_wp -= shift_words;	shift_left( shift_bits );	find_sw();    }}// ----------------------------------------------------------------------------//  destructive shift mantissa to the right// ----------------------------------------------------------------------------voidscfx_rep::rshift( int n ){    if( n == 0 )        return;    if( n < 0 )    {        lshift( -n );	return;    }    if( is_normal() )    {        int shift_bits  = n % bits_in_word;	int shift_words = n / bits_in_word;	// resize if needed	if( m_lsw == 0 && scfx_find_lsb( m_mant[m_lsw] ) < shift_bits )	    resize_to( size() + 1, -1 );	// do it	m_wp += shift_words;	shift_right( shift_bits );	find_sw();    }}// ----------------------------------------------------------------------------//  FRIEND FUNCTION : compare_abs////  Compares the absolute values of two scfx_reps, excluding the special cases.// ----------------------------------------------------------------------------intcompare_abs( const scfx_rep& a, const scfx_rep& b ){    // check for zero    word a_word = a.m_mant[a.m_msw];    word b_word = b.m_mant[b.m_msw];      if( a_word == 0 || b_word == 0 )    {	if( a_word != 0 )	    return 1;	if( b_word != 0 )	    return -1;	return 0;    }    // compare msw index    int a_msw = a.m_msw - a.m_wp;    int b_msw = b.m_msw - b.m_wp;    if( a_msw > b_msw )	return 1;    if( a_msw < b_msw )	return -1;    // compare content    int a_i = a.m_msw;    int b_i = b.m_msw;    while( a_i >= a.m_lsw && b_i >= b.m_lsw )    {	a_word = a.m_mant[a_i];	b_word = b.m_mant[b_i];	if( a_word > b_word )	    return 1;	if( a_word < b_word )	    return -1;	-- a_i;	-- b_i;    }    bool a_zero = true;    while( a_i >= a.m_lsw )    {	a_zero = a_zero && ( a.m_mant[a_i] == 0 );	-- a_i;    }      bool b_zero = true;    while( b_i >= b.m_lsw )    {	b_zero = b_zero && ( b.m_mant[b_i] == 0 );	-- b_i;    }    // assertion: a_zero || b_zero == true    if( ! a_zero && b_zero )	return 1;    if( a_zero && ! b_zero )	return -1;    return 0;}// ----------------------------------------------------------------------------//  FRIEND FUNCTION : cmp_scfx_rep////  Compares the values of two scfx_reps, including the special cases.// ----------------------------------------------------------------------------intcmp_scfx_rep( const scfx_rep& a, const scfx_rep& b ){    // handle special cases    if( a.is_nan() || b.is_nan() )    {#if 0	if( a.is_nan() && b.is_nan() )	{	    return 0;	}#endif	return 2;    }    if( a.is_inf() || b.is_inf() )    {	if( a.is_inf() )	{	    if( ! a.is_neg() )	    {		if( b.is_inf() && ! b.is_neg() )		{		    return 0;		}		else		{		    return 1;		}	    }	    else	    {		if( b.is_inf() && b.is_neg() )		{		    return 0;		}		else		{		    return -1;		}	    }	}	if( b.is_inf() )	{	    if( ! b.is_neg() )	    {		return -1;	    }	    else	    {		return 1;	    }	}    }      if( a.is_zero() && b.is_zero() )    {	return 0;    }    // compare sign    if( a.m_sign != b.m_sign )    {	return a.m_sign;    }    return ( a.m_sign * compare_abs( a, b ) );}// ----------------------------------------------------------------------------//  PRIVATE METHOD : quantization////  Performs destructive quantization.// ----------------------------------------------------------------------------voidscfx_rep::quantization( const scfx_params& params, bool& q_flag ){    scfx_index x = calc_indices( params.iwl() - params.wl() );    if( x.wi() < 0 )        return;    if( x.wi() >= size() )        resize_to( x.wi() + 1, 1 );    bool qb = q_bit( x );    bool qz = q_zero( x );    q_flag = ( qb || ! qz );    if( q_flag )    {        switch( params.q_mode() )	{            case SC_TRN:			// truncation	    {	        if( is_neg() )		    q_incr( x );		break;	    }            case SC_RND:			// rounding to plus infinity	    {	        if( ! is_neg() )		{		    if( qb )			q_incr( x );		}		else		{		    if( qb && ! qz )			q_incr( x );		}		break;	    }            case SC_TRN_ZERO:			// truncation to zero	    {	        break;	    }            case SC_RND_INF:			// rounding to infinity	    {	        if( qb )		    q_incr( x );		break;	    }            case SC_RND_CONV:			// convergent rounding	    {		if( qb && ! qz || qb && qz && q_odd( x ) )		    q_incr( x );		break;	    }            case SC_RND_ZERO:			// rounding to zero	    {		if( qb && ! qz )		    q_incr( x );		break;	    }            case SC_RND_MIN_INF:		// rounding to minus infinity	    {		if( ! is_neg() )		{		    if( qb && ! qz )			q_incr( x );		}		else		{		    if( qb )			q_incr( x );		}		break;	    }            default:	        ;	}	q_clear( x );		find_sw();    }}// ----------------------------------------------------------------------------//  PRIVATE METHOD : overflow////  Performs destructive overflow handling.// ----------------------------------------------------------------------------voidscfx_rep::overflow( const scfx_params& params, bool& o_flag ){    scfx_index x = calc_indices( params.iwl() - 1 );    if( x.wi() >= size() )        resize_to( x.wi() + 1, 1 );    if( x.wi() < 0 )    {        resize_to( size() - x.wi(), -1 );        x.wi( 0 );    }    bool zero_left = o_zero_left( x );    bool bit_at = o_bit_at( x );    bool zero_right = o_zero_right( x );    bool under = false;    bool over = false;    sc_enc enc = params.enc();    if( enc == SC_TC_ )    {	if( is_neg() )	{	    if( params.o_mode() == SC_SAT_SYM )		under = ( ! zero_left || bit_at );	    else		under = ( ! zero_left || zero_left && bit_at && ! zero_right );	}	else	    over = ( ! zero_left || bit_at );    }    else    {	if( is_neg() )	    under = ( ! is_zero() );        else	    over = ( ! zero_left );    }    o_flag = ( under || over );    if( o_flag )    {	scfx_index x2 = calc_indices( params.iwl() - params.wl() );	if( x2.wi() < 0 )	{	    resize_to( size() - x2.wi(), -1 );	    x.wi( x.wi() - x2.wi() );	    x2.wi( 0 );	}	switch( params.o_mode() )	{            case SC_WRAP:			// wrap-around	    {		int n_bits = params.n_bits();		if( n_bits == 0 )		{		    // wrap-around all 'wl' bits		    toggle_tc();		    o_extend( x, enc );		    toggle_tc();		}		else if( n_bits < params.wl() )		{		    scfx_index x3 = calc_indices( params.iwl() - 1 - n_bits );		    // wrap-around least significant 'wl - n_bits' bits;		    // saturate most significant 'n_bits' bits		    toggle_tc();		    o_set( x, x3, enc, under );		    o_extend( x, enc );		    toggle_tc();		}		else		{		    // saturate all 'wl' bits		    if( under )			o_set_low( x, enc );		    else			o_set_high( x, x2, enc );		}		break;	    }            case SC_SAT:			// saturation	    {		if( under )		    o_set_low( x, enc );		else		    o_set_high( x, x2, enc );		break;	    }            case SC_SAT_SYM:			// symmetrical saturation	    {		if( under )		{		    if( enc == SC_TC_ )			o_set_high( x, x2, SC_TC_, -1 );		    else			o_set_low( x, SC_US_ );		}		else		    o_set_high( x, x2, enc );		break;	    }            case SC_SAT_ZERO:			// saturation to zero	    {		set_zero();		break;	    }            case SC_WRAP_SM:			// sign magnitude wrap-around	    {		SC_ERROR_IF_( enc == SC_US_,			      sc_core::SC_ID_WRAP_SM_NOT_DEFINED_ );		int n_bits = params.n_bits();		if( n_bits == 0 )		{		    scfx_index x4 = calc_indices( params.iwl() );		    if( x4.wi() >= size() )			resize_to( x4.wi() + 1, 1 );		    toggle_tc();		    if( o_bit_at( x4 ) != o_bit_at( x ) )			o_invert( x2 );		    o_extend( x, SC_TC_ );		    toggle_tc();		}		else if( n_bits == 1 )		{		    toggle_tc();		    if( is_neg() != o_bit_at( x ) )			o_invert( x2 );		    o_extend( x, SC_TC_ );		    toggle_tc();		}		else if( n_bits < params.wl() )		{		    scfx_index x3 = calc_indices( params.iwl() - 1 - n_bits );		    scfx_index x4 = calc_indices( params.iwl() - n_bits );		    // wrap-around least significant 'wl - n_bits' bits;		    // saturate most significant 'n_bits' bits		    toggle_tc();		    if( is_neg() == o_bit_at( x4 ) )			o_invert( x2 );		    o_set( x, x3, SC_TC_, under );		    o_extend( x, SC_TC_ );		    toggle_tc();		}		else		{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -