sc_bv_base.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2006 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   sc_bv_base.cpp -- Arbitrary size bit vector class.
00021 
00022   Original Author: Gene Bushuyev, Synopsys, Inc.
00023 
00024  *****************************************************************************/
00025 
00026 /*****************************************************************************
00027 
00028   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00029   changes you are making here.
00030 
00031       Name, Affiliation, Date:
00032   Description of Modification:
00033 
00034  *****************************************************************************/
00035 
00036 
00037 // $Log: sc_bv_base.cpp,v $
00038 // Revision 1.1.1.1  2006/12/15 20:31:36  acg
00039 // SystemC 2.2
00040 //
00041 // Revision 1.4  2006/04/11 23:12:26  acg
00042 //   Andy Goodrich: Fixed bug in parsing of extended string constants like
00043 //   0bus1110011.
00044 //
00045 // Revision 1.3  2006/01/13 18:53:53  acg
00046 // Andy Goodrich: added $Log command so that CVS comments are reproduced in
00047 // the source.
00048 //
00049 
00050 #include "sysc/datatypes/bit/sc_bit_ids.h"
00051 #include "sysc/datatypes/bit/sc_bv_base.h"
00052 #include "sysc/datatypes/fx/sc_fix.h"
00053 #include "sysc/datatypes/fx/sc_ufix.h"
00054 
00055 
00056 namespace sc_dt
00057 {
00058 
00059 // ----------------------------------------------------------------------------
00060 //  CLASS : sc_bv_base
00061 //
00062 //  Arbitrary size bit vector base class.
00063 // ----------------------------------------------------------------------------
00064 
00065 void
00066 sc_bv_base::init( int length_, bool init_value )
00067 {
00068     // check the length
00069     if( length_ <= 0 ) {
00070     SC_REPORT_ERROR( sc_core::SC_ID_ZERO_LENGTH_, 0 );
00071     }
00072     // allocate memory for the data and control words
00073     m_len = length_;
00074     m_size = (m_len - 1) / SC_DIGIT_SIZE + 1;
00075     m_data = new sc_digit[m_size];
00076     // initialize the bits to 'init_value'
00077     sc_digit dw = init_value ? ~SC_DIGIT_ZERO : SC_DIGIT_ZERO;
00078     int sz = m_size;
00079     for( int i = 0; i < sz; ++ i ) {
00080     m_data[i] = dw;
00081     }
00082     clean_tail();
00083 }
00084 
00085 
00086 void
00087 sc_bv_base::assign_from_string( const std::string& s )
00088 {
00089     // s must have been converted to bin
00090     int len = m_len;
00091     int s_len = s.length() - 1;
00092     int min_len = sc_min( len, s_len );
00093     int i = 0;
00094     for( ; i < min_len; ++ i ) {
00095     char c = s[s_len - i - 1];
00096     if( c != '0' && c != '1' ) {
00097         SC_REPORT_ERROR( sc_core::SC_ID_CANNOT_CONVERT_,
00098             "string can contain only '0' and '1' characters" );
00099     }
00100     set_bit( i, sc_logic_value_t( c - '0' ) );
00101     }
00102     // if formatted, fill the rest with sign(s), otherwise fill with zeros
00103     sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t( s[0] - '0' )
00104                                      : sc_logic_value_t( 0 ));
00105     for( ; i < len; ++ i ) {
00106     set_bit( i, fill );
00107     }
00108 }
00109 
00110 
00111 // constructors
00112 
00113 sc_bv_base::sc_bv_base( const char* a )
00114     : m_len( 0 ), m_size( 0 ), m_data( 0 )
00115 {
00116     std::string s = convert_to_bin( a );
00117     init( s.length() -  1 );
00118     assign_from_string( s );
00119 }
00120 
00121 sc_bv_base::sc_bv_base( const char* a, int length_ )
00122     : m_len( 0 ), m_size( 0 ), m_data( 0 )
00123 {
00124     init( length_ );
00125     assign_from_string( convert_to_bin( a ) );
00126 }
00127 
00128 sc_bv_base::sc_bv_base( const sc_bv_base& a )
00129     : m_len( a.m_len ),
00130       m_size( a.m_size ),
00131       m_data( new sc_digit[m_size] )
00132 {
00133     // copy the bits
00134     int sz = m_size;
00135     for( int i = 0; i < sz; ++ i ) {
00136     m_data[i] = a.m_data[i];
00137     }
00138 }
00139 
00140 
00141 // assignment operators
00142 
00143 sc_bv_base&
00144 sc_bv_base::operator = ( const char* a )
00145 {
00146     assign_from_string( convert_to_bin( a ) );
00147     return *this;
00148 }
00149 
00150 
00151 #if 0
00152 
00153 // bitwise complement
00154 
00155 sc_bv_base&
00156 sc_bv_base::b_not()
00157 {
00158     int sz = m_size;
00159     for( int i = 0; i < sz; ++ i ) {
00160     m_data[i] = ~m_data[i];
00161     }
00162     clean_tail();
00163     return *this;
00164 }
00165 
00166 
00167 // bitwise left shift
00168 
00169 sc_bv_base&
00170 sc_bv_base::operator <<= ( int n )
00171 {
00172     if( n < 0 ) {
00173     char msg[BUFSIZ];
00174     std::sprintf( msg,
00175          "left shift operation is only allowed with positive "
00176          "shift values, shift value = %d", n );
00177     SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
00178     }
00179     int sz = m_size;
00180     if( n >= m_len ) {
00181     for( int i = 0; i < sz; ++ i ) {
00182         m_data[i] = SC_DIGIT_ZERO;
00183     }
00184     // clean_tail();
00185     return *this;
00186     }
00187     int wn = n / SC_DIGIT_SIZE;
00188     int bn = n % SC_DIGIT_SIZE;
00189     if( wn != 0 ) {
00190     // shift words
00191     int i = sz - 1;
00192     for( ; i >= wn; -- i ) {
00193         m_data[i] = m_data[i - wn];
00194     }
00195     for( ; i >= 0; -- i ) {
00196         m_data[i] = SC_DIGIT_ZERO;
00197     }
00198     }
00199     if( bn != 0 ) {
00200     // shift bits
00201     for( int i = sz - 1; i >= 1; -- i ) {
00202         m_data[i] <<= bn;
00203         m_data[i] |= m_data[i - 1] >> (SC_DIGIT_SIZE - bn);
00204     }
00205     m_data[0] <<= bn;
00206     }
00207     clean_tail();
00208     return *this;
00209 }
00210 
00211 
00212 // bitwise right shift
00213 
00214 sc_bv_base&
00215 sc_bv_base::operator >>= ( int n )
00216 {
00217     if( n < 0 ) {
00218     char msg[BUFSIZ];
00219     std::sprintf( msg,
00220          "right shift operation is only allowed with positive "
00221          "shift values, shift value = %d", n );
00222     SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
00223     }
00224     int sz = m_size;
00225     if( n >= m_len ) {
00226     for( int i = 0; i < sz; ++ i ) {
00227         m_data[i] = SC_DIGIT_ZERO;
00228     }
00229     // clean_tail();
00230     return *this;
00231     }
00232     int wn = n / SC_DIGIT_SIZE;
00233     int bn = n % SC_DIGIT_SIZE;
00234     if( wn != 0 ) {
00235     // shift words
00236     int i = 0;
00237     for( ; i < (sz - wn); ++ i ) {
00238         m_data[i] = m_data[i + wn];
00239     }
00240     for( ; i < sz; ++ i ) {
00241         m_data[i] = SC_DIGIT_ZERO;
00242     }
00243     }
00244     if( bn != 0 ) {
00245     // shift bits
00246     for( int i = 0; i < (sz - 1); ++ i ) {
00247         m_data[i] >>= bn;
00248         m_data[i] |= m_data[i + 1] << (SC_DIGIT_SIZE - bn);
00249     }
00250     m_data[sz - 1] >>= bn;
00251     }
00252     clean_tail();
00253     return *this;
00254 }
00255 
00256 
00257 // bitwise left rotate
00258 
00259 sc_bv_base&
00260 sc_bv_base::lrotate( int n )
00261 {
00262     if( n < 0 ) {
00263     char msg[BUFSIZ];
00264     std::sprintf( msg,
00265          "left rotate operation is only allowed with positive "
00266          "rotate values, rotate value = %d", n );
00267     SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
00268     }
00269     int len = m_len;
00270     n %= len;
00271     *this = (*this << n) | (*this >> (len - n));
00272     return *this;
00273 }
00274 
00275 
00276 // bitwise right rotate
00277 
00278 sc_bv_base&
00279 sc_bv_base::rrotate( int n )
00280 {
00281     if( n < 0 ) {
00282     char msg[BUFSIZ];
00283     std::sprintf( msg,
00284          "right rotate operation is only allowed with positive "
00285          "rotate values, rotate value = %d", n );
00286     SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
00287     }
00288     int len = m_len;
00289     n %= len;
00290     *this = (*this >> n) | (*this << (len - n));
00291     return *this;
00292 }
00293 
00294 #endif
00295 
00296 
00297 // ----------------------------------------------------------------------------
00298 
00299 // convert formatted string to binary string
00300 
00301 const std::string
00302 convert_to_bin( const char* s )
00303 {
00304     // Beware: logic character strings cannot start with '0x' or '0X',
00305     //         because this is seen as a hexadecimal encoding prefix!
00306 
00307     if( s == 0 ) {
00308     SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_, 
00309         "character string is zero" );
00310     }
00311     if( *s == 0 ) {
00312     SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_, 
00313         "character string is empty");
00314     }
00315 
00316     int n = strlen( s );
00317     int i = 0;
00318     if( s[0] == '-' || s[0] == '+' ) {
00319     ++ i;
00320     }
00321     if( n > (i + 2) && s[i] == '0' )
00322     {
00323         if (s[i+1] == 'b' || s[i+1] == 'B' )
00324     {
00325         if ( s[i+2] == '0' || s[i+2] == '1' )
00326         {
00327         std::string str( &s[2] );
00328             str += "F";
00329             return str;
00330         }
00331     }
00332         if ( s[i+1] == 'b' || s[i+1] == 'B' ||
00333          s[i+1] == 'c' || s[i+1] == 'C' ||
00334          s[i+1] == 'd' || s[i+1] == 'D' ||
00335          s[i+1] == 'o' || s[i+1] == 'O' ||
00336          s[i+1] == 'x' || s[i+1] == 'X') 
00337         {
00338         try {
00339         // worst case length = n * 4
00340         sc_fix a( s, n * 4, n * 4, SC_TRN, SC_WRAP, 0, SC_ON );
00341         std::string str = a.to_bin();
00342         str += "F"; // mark the string as formatted
00343         // get rid of prefix (0b) and redundant leading bits
00344         const char* p = str.c_str() + 2;
00345         while( p[1] && p[0] == p[1] ) {
00346             ++ p;
00347         }
00348         return std::string( p );
00349         } catch( sc_core::sc_report ) {
00350         char msg[BUFSIZ];
00351         std::sprintf( msg, "character string '%s' is not valid", s );
00352         SC_REPORT_ERROR( sc_core::SC_ID_CANNOT_CONVERT_, msg );
00353         // never reached
00354         return std::string();
00355         }
00356     }
00357 
00358     }
00359 
00360     // bin by default
00361 
00362     std::string str( s );
00363     str += "U"; // mark the string as unformatted
00364     return str;
00365 }
00366 
00367 // convert binary string to formatted string
00368 
00369 const std::string
00370 convert_to_fmt( const std::string& s, sc_numrep numrep, bool w_prefix )
00371 {
00372     int n = s.length();
00373     std::string str("0bus");
00374     // str += "0bus";
00375     str += s;
00376     sc_ufix a( str.c_str(), n, n, SC_TRN, SC_WRAP, 0, SC_ON );
00377     return a.to_string( numrep, w_prefix );
00378 }
00379 
00380 } // namespace sc_dt

Generated on Wed Jan 21 15:32:07 2009 for SystemC by  doxygen 1.5.5