📄 sc_unsigned.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. *****************************************************************************//***************************************************************************** sc_unsigned.cpp -- Arbitrary precision signed arithmetic. This file includes the definitions of sc_unsigned_bitref, sc_unsigned_subref, and sc_unsigned classes. The first two classes are proxy classes to reference one bit and a range of bits of a sc_unsigned number, respectively. This file also includes sc_nbcommon.cpp and sc_nbfriends.cpp, which contain the definitions shared by sc_unsigned. Original Author: Ali Dasdan, Synopsys, Inc. *****************************************************************************//***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Description of Modification: *****************************************************************************/// $Log: sc_unsigned.cpp,v $// Revision 1.2 2007/02/22 21:34:49 acg// Andy Goodrich: cleaned up comments in concat_get_ctrl and concat_get_data.//// Revision 1.1.1.1 2006/12/15 20:31:36 acg// SystemC 2.2//// Revision 1.3 2006/01/13 18:49:32 acg// Added $Log command so that CVS check in comments are reproduced in the// source.//#include <ctype.h>#include <math.h>#include "sysc/kernel/sc_cmnhdr.h"#include "sysc/kernel/sc_macros.h"#include "sysc/datatypes/int/sc_unsigned.h"#include "sysc/datatypes/int/sc_signed.h"#include "sysc/datatypes/int/sc_int_base.h"#include "sysc/datatypes/int/sc_uint_base.h"#include "sysc/datatypes/int/sc_int_ids.h"#include "sysc/datatypes/bit/sc_bv_base.h"#include "sysc/datatypes/bit/sc_lv_base.h"#include "sysc/datatypes/misc/sc_concatref.h"#include "sysc/datatypes/fx/sc_ufix.h"#include "sysc/datatypes/fx/scfx_other_defs.h"namespace sc_dt{// Pool of temporary instances:// The sc_unsigned pool is used by the concatenation support.// The bit and part reference pools allow references to be returned.sc_core::sc_vpool<sc_unsigned> sc_unsigned::m_pool(8); sc_core::sc_vpool<sc_unsigned_bitref> sc_unsigned_bitref::m_pool(9); sc_core::sc_vpool<sc_unsigned_subref> sc_unsigned_subref::m_pool(9); // -----------------------------------------------------------------------------// SECTION: Public members - Invalid selections.// -----------------------------------------------------------------------------voidsc_unsigned::invalid_index( int i ) const{ char msg[BUFSIZ]; std::sprintf( msg, "sc_biguint bit selection: index = %d violates " "0 <= index <= %d", i, nbits - 2 ); SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );}voidsc_unsigned::invalid_range( int l, int r ) const{ char msg[BUFSIZ]; std::sprintf( msg, "sc_biguint part selection: left = %d, right = %d \n" " violates either (0 <= left <= %d) or (0 <= right <= %d)", l, r, nbits-2, nbits-2 ); SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );}// ----------------------------------------------------------------------------// SECTION: Public members - Concatenation support.// ----------------------------------------------------------------------------// Most public members are included from sc_nbcommon.inc. However, some // concatenation support appears here to optimize between the signed and// unsigned cases.// Insert this object's value at the specified place in a vector of big style// values.bool sc_unsigned::concat_get_ctrl( sc_digit* dst_p, int low_i ) const{ int dst_i; // Index to next word to set in dst_p. int end_i; // Index of high order word to set. int left_shift; // Amount to shift value left. sc_digit mask; // Mask for partial word sets. // CALCULATE METRICS FOR DATA MOVEMENT: dst_i = low_i / BITS_PER_DIGIT; end_i = (low_i + nbits - 2) / BITS_PER_DIGIT; left_shift = low_i % BITS_PER_DIGIT; // MOVE FIRST WORD (IT MAY BE PARTIAL) AND THEN ANY OTHERS: // // We may "clobber" upper bits, but they will be written at some point // anyway. mask = ~(-1 << left_shift); dst_p[dst_i] = ( dst_p[dst_i] & ~mask ); dst_i++; for ( ; dst_i <= end_i; dst_i++ ) dst_p[dst_i] = 0; return false;}bool sc_unsigned::concat_get_data( sc_digit* dst_p, int low_i ) const{ int dst_i; // Index to next word to set in dst_p. int end_i; // Index of high order word to set. int high_i; // Index w/in word of high order bit. int left_shift; // Amount to shift value left. sc_digit left_word; // High word component for set. sc_digit mask; // Mask for partial word sets. bool result; // True if inserting non-zero data. int right_shift; // Amount to shift value right. sc_digit right_word; // Low word component for set. int real_bits; // nbits - 1. int src_i; // Index to next word to get from digit. // CALCULATE METRICS FOR DATA MOVEMENT: real_bits = nbits - 1; // Remove that extra sign bit. dst_i = low_i / BITS_PER_DIGIT; high_i = low_i + real_bits - 1; end_i = high_i / BITS_PER_DIGIT; left_shift = low_i % BITS_PER_DIGIT; switch ( sgn ) { // POSITIVE SOURCE VALUE: case SC_POS: result = true; // ALL DATA TO BE MOVED IS IN A SINGLE WORD: if ( dst_i == end_i ) { mask = ~(-1 << real_bits) << left_shift; dst_p[dst_i] = ( dst_p[dst_i] & ~mask ) | ((digit[0] << left_shift) & mask); // #### We really want zero propogation on the top! } // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED: else if ( left_shift == 0 ) { for ( src_i = 0; dst_i < end_i; dst_i++, src_i++ ) { dst_p[dst_i] = digit[src_i]; } high_i = high_i % BITS_PER_DIGIT; mask = ~(-2 << high_i) & DIGIT_MASK; dst_p[dst_i] = digit[src_i] & mask; } // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED: else { high_i = high_i % BITS_PER_DIGIT; right_shift = BITS_PER_DIGIT - left_shift; mask = ~(-1 << left_shift); right_word = digit[0]; dst_p[dst_i] = (dst_p[dst_i] & mask) | ((right_word << left_shift) & DIGIT_MASK); for ( src_i = 1, dst_i++; dst_i < end_i; dst_i++, src_i++ ) { left_word = digit[src_i]; dst_p[dst_i] = ((left_word << left_shift)&DIGIT_MASK) | (right_word >> right_shift); right_word = left_word; } left_word = digit[src_i]; mask = ~(-2 << high_i) & DIGIT_MASK; dst_p[dst_i] = ((left_word << left_shift) | (right_word >> right_shift)) & mask; } break; // VALUE IS ZERO: default: result = false; // ALL DATA TO BE MOVED IS IN A SINGLE WORD: if ( dst_i == end_i ) { mask = ~(-1 << nbits) << left_shift; dst_p[dst_i] = dst_p[dst_i] & ~mask; } // DATA IS IN MORE THAN ONE WORD, BUT IS WORD ALIGNED: else if ( left_shift == 0 ) { for ( src_i = 0; dst_i < end_i; dst_i++, src_i++ ) { dst_p[dst_i] = 0; } high_i = high_i % BITS_PER_DIGIT; mask = ~(-2 << high_i) & DIGIT_MASK; dst_p[dst_i] = 0; } // DATA IS IN MORE THAN ONE WORD, AND NOT WORD ALIGNED: else { high_i = high_i % BITS_PER_DIGIT; right_shift = BITS_PER_DIGIT - left_shift; mask = ~(-1 << left_shift); dst_p[dst_i] = (dst_p[dst_i] & mask); for ( dst_i++; dst_i <= end_i; dst_i++ ) { dst_p[dst_i] = 0; } } break; } return result;}// Return this object instance's bits as a uint64 without sign extension.uint64 sc_unsigned::concat_get_uint64() const{ uint64 result; switch ( sgn ) { case SC_POS: result = 0; if ( ndigits > 2 ) result = digit[2]; if ( ndigits > 1 ) result = (result << BITS_PER_DIGIT) | digit[1]; result = (result << BITS_PER_DIGIT) | digit[0]; break; default: result = 0; break; } return result;}// #### OPTIMIZEvoid sc_unsigned::concat_set(int64 src, int low_i) { *this = (low_i < 64) ? src >> low_i : src >> 63;}void sc_unsigned::concat_set(const sc_signed& src, int low_i){ if ( low_i < src.length() ) *this = src >> low_i; else *this = (src<0) ? (int_type)-1 : 0;} void sc_unsigned::concat_set(const sc_unsigned& src, int low_i){ if ( low_i < src.length() ) *this = src >> low_i; else *this = 0;}void sc_unsigned::concat_set(uint64 src, int low_i){ *this = (low_i < 64) ? src >> low_i : 0;}// ----------------------------------------------------------------------------// SECTION: Public members - Reduction methods.// ----------------------------------------------------------------------------bool sc_unsigned::and_reduce() const{ int i; // Digit examining. if ( sgn == SC_ZERO ) return false; for ( i = 0; i < ndigits-1; i++ ) if ( (digit[i] & DIGIT_MASK) != DIGIT_MASK ) return false; if ( (digit[i] & ~(-1 << ((nbits-1) % BITS_PER_DIGIT))) == (sc_digit)~(-1 << ((nbits-1) % BITS_PER_DIGIT))) return true; return false;}bool sc_unsigned::or_reduce() const{ return ( sgn == SC_ZERO ) ? false : true;}bool sc_unsigned::xor_reduce() const{ int i; // Digit examining. int odd; // Flag for odd number of digits. odd = 0; for ( i = 0; i < nbits-1; i++ ) if ( test(i) ) odd = ~odd; return odd ? true : false;}// ----------------------------------------------------------------------------// SECTION: Public members - Assignment operators.// ----------------------------------------------------------------------------// assignment operatorsconst sc_unsigned&sc_unsigned::operator = ( const char* a ){ if( a == 0 ) { SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, "character string is zero" ); } if( *a == 0 ) { SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, "character string is empty" ); } try { int len = length(); sc_ufix aa( a, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); return this->operator = ( aa ); } catch( sc_core::sc_report ) { char msg[BUFSIZ]; std::sprintf( msg, "character string '%s' is not valid", a ); SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); // never reached } return *this;} const sc_unsigned&sc_unsigned::operator=(int64 v){ sgn = get_sign(v); if ( sgn == SC_ZERO ) { vec_zero(ndigits, digit); } else { from_uint(ndigits, digit, (uint64) v); convert_SM_to_2C_to_SM(); } return *this;}const sc_unsigned&sc_unsigned::operator=(uint64 v){ if (v == 0) { sgn = SC_ZERO; vec_zero(ndigits, digit); } else { sgn = SC_POS; from_uint(ndigits, digit, v); convert_SM_to_2C_to_SM(); } return *this;}const sc_unsigned&sc_unsigned::operator=(long v){ sgn = get_sign(v); if ( sgn == SC_ZERO ) { vec_zero(ndigits, digit); } else { from_uint(ndigits, digit, (unsigned long) v); convert_SM_to_2C_to_SM(); } return *this;}const sc_unsigned&sc_unsigned::operator=(unsigned long v){ if (v == 0) { sgn = SC_ZERO; vec_zero(ndigits, digit); } else { sgn = SC_POS; from_uint(ndigits, digit, v); convert_SM_to_2C_to_SM(); } return *this;}const sc_unsigned&sc_unsigned::operator=(double v){ is_bad_double(v); sgn = SC_POS; register int i = 0; while (floor(v) && (i < ndigits)) {#ifndef WIN32 digit[i++] = (sc_digit) floor(remainder(v, DIGIT_RADIX));#else digit[i++] = (sc_digit) floor(fmod(v, DIGIT_RADIX));#endif v /= DIGIT_RADIX; } vec_zero(i, ndigits, digit); convert_SM_to_2C_to_SM(); return *this; }// ----------------------------------------------------------------------------const sc_unsigned&sc_unsigned::operator = ( const sc_bv_base& v ){ int minlen = sc_min( nbits, v.length() ); int i = 0; for( ; i < minlen; ++ i ) { safe_set( i, v.get_bit( i ), digit ); } for( ; i < nbits; ++ i ) { safe_set( i, 0, digit ); // zero-extend } convert_2C_to_SM(); return *this;}const sc_unsigned&sc_unsigned::operator = ( const sc_lv_base& v ){ int minlen = sc_min( nbits, v.length() ); int i = 0; for( ; i < minlen; ++ i ) { safe_set( i, sc_logic( v.get_bit( i ) ).to_bool(), digit ); } for( ; i < nbits; ++ i ) { safe_set( i, 0, digit ); // zero-extend } convert_2C_to_SM(); return *this;}// explicit conversion to character stringconst std::stringsc_unsigned::to_string( sc_numrep numrep ) const{ int len = length(); sc_ufix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); return aa.to_string( numrep );}const std::stringsc_unsigned::to_string( sc_numrep numrep, bool w_prefix ) const{ int len = length(); sc_ufix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); return aa.to_string( numrep, w_prefix );}// ----------------------------------------------------------------------------// SECTION: Interfacing with sc_int_base// ----------------------------------------------------------------------------const sc_unsigned& sc_unsigned::operator= (const sc_int_base& v){ return operator=((int64) v); }const sc_unsigned& sc_unsigned::operator+=(const sc_int_base& v){ return operator+=((int64) v); }const sc_unsigned& sc_unsigned::operator-=(const sc_int_base& v){ return operator-=((int64) v); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -