sc_bv_base.cpp revision 12027
1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20/***************************************************************************** 21 22 sc_bv_base.cpp -- Arbitrary size bit vector class. 23 24 Original Author: Gene Bushuyev, Synopsys, Inc. 25 26 *****************************************************************************/ 27 28/***************************************************************************** 29 30 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 31 changes you are making here. 32 33 Name, Affiliation, Date: 34 Description of Modification: 35 36 *****************************************************************************/ 37 38 39// $Log: sc_bv_base.cpp,v $ 40// Revision 1.2 2011/08/24 22:05:40 acg 41// Torsten Maehne: initialization changes to remove warnings. 42// 43// Revision 1.1.1.1 2006/12/15 20:20:04 acg 44// SystemC 2.3 45// 46// Revision 1.4 2006/04/11 23:12:26 acg 47// Andy Goodrich: Fixed bug in parsing of extended string constants like 48// 0bus1110011. 49// 50// Revision 1.3 2006/01/13 18:53:53 acg 51// Andy Goodrich: added $Log command so that CVS comments are reproduced in 52// the source. 53// 54 55#include <string.h> 56 57#include "sysc/datatypes/bit/sc_bit_ids.h" 58#include "sysc/datatypes/bit/sc_bv_base.h" 59#include "sysc/datatypes/fx/sc_fix.h" 60#include "sysc/datatypes/fx/sc_ufix.h" 61 62 63namespace sc_dt 64{ 65 66// ---------------------------------------------------------------------------- 67// CLASS : sc_bv_base 68// 69// Arbitrary size bit vector base class. 70// ---------------------------------------------------------------------------- 71 72void 73sc_bv_base::init( int length_, bool init_value ) 74{ 75 // check the length 76 if( length_ <= 0 ) { 77 SC_REPORT_ERROR( sc_core::SC_ID_ZERO_LENGTH_, 0 ); 78 } 79 // allocate memory for the data and control words 80 m_len = length_; 81 m_size = (m_len - 1) / SC_DIGIT_SIZE + 1; 82 m_data = new sc_digit[m_size]; 83 // initialize the bits to 'init_value' 84 sc_digit dw = init_value ? ~SC_DIGIT_ZERO : SC_DIGIT_ZERO; 85 int sz = m_size; 86 for( int i = 0; i < sz; ++ i ) { 87 m_data[i] = dw; 88 } 89 clean_tail(); 90} 91 92 93void 94sc_bv_base::assign_from_string( const std::string& s ) 95{ 96 // s must have been converted to bin 97 int len = m_len; 98 int s_len = s.length() - 1; 99 int min_len = sc_min( len, s_len ); 100 int i = 0; 101 for( ; i < min_len; ++ i ) { 102 char c = s[s_len - i - 1]; 103 if( c != '0' && c != '1' ) { 104 SC_REPORT_ERROR( sc_core::SC_ID_CANNOT_CONVERT_, 105 "string can contain only '0' and '1' characters" ); 106 } 107 set_bit( i, sc_logic_value_t( c - '0' ) ); 108 } 109 // if formatted, fill the rest with sign(s), otherwise fill with zeros 110 sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t( s[0] - '0' ) 111 : sc_logic_value_t( 0 )); 112 for( ; i < len; ++ i ) { 113 set_bit( i, fill ); 114 } 115} 116 117 118// constructors 119 120sc_bv_base::sc_bv_base( const char* a ) 121 : m_len( 0 ), m_size( 0 ), m_data( 0 ) 122{ 123 std::string s = convert_to_bin( a ); 124 init( s.length() - 1 ); 125 assign_from_string( s ); 126} 127 128sc_bv_base::sc_bv_base( const char* a, int length_ ) 129 : m_len( 0 ), m_size( 0 ), m_data( 0 ) 130{ 131 init( length_ ); 132 assign_from_string( convert_to_bin( a ) ); 133} 134 135sc_bv_base::sc_bv_base( const sc_bv_base& a ) 136 : sc_proxy<sc_bv_base>(), 137 m_len( a.m_len ), 138 m_size( a.m_size ), 139 m_data( new sc_digit[m_size] ) 140{ 141 // copy the bits 142 int sz = m_size; 143 for( int i = 0; i < sz; ++ i ) { 144 m_data[i] = a.m_data[i]; 145 } 146} 147 148 149// assignment operators 150 151sc_bv_base& 152sc_bv_base::operator = ( const char* a ) 153{ 154 assign_from_string( convert_to_bin( a ) ); 155 return *this; 156} 157 158 159#if 0 160 161// bitwise complement 162 163sc_bv_base& 164sc_bv_base::b_not() 165{ 166 int sz = m_size; 167 for( int i = 0; i < sz; ++ i ) { 168 m_data[i] = ~m_data[i]; 169 } 170 clean_tail(); 171 return *this; 172} 173 174 175// bitwise left shift 176 177sc_bv_base& 178sc_bv_base::operator <<= ( int n ) 179{ 180 if( n < 0 ) { 181 char msg[BUFSIZ]; 182 std::sprintf( msg, 183 "left shift operation is only allowed with positive " 184 "shift values, shift value = %d", n ); 185 SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); 186 } 187 int sz = m_size; 188 if( n >= m_len ) { 189 for( int i = 0; i < sz; ++ i ) { 190 m_data[i] = SC_DIGIT_ZERO; 191 } 192 // clean_tail(); 193 return *this; 194 } 195 int wn = n / SC_DIGIT_SIZE; 196 int bn = n % SC_DIGIT_SIZE; 197 if( wn != 0 ) { 198 // shift words 199 int i = sz - 1; 200 for( ; i >= wn; -- i ) { 201 m_data[i] = m_data[i - wn]; 202 } 203 for( ; i >= 0; -- i ) { 204 m_data[i] = SC_DIGIT_ZERO; 205 } 206 } 207 if( bn != 0 ) { 208 // shift bits 209 for( int i = sz - 1; i >= 1; -- i ) { 210 m_data[i] <<= bn; 211 m_data[i] |= m_data[i - 1] >> (SC_DIGIT_SIZE - bn); 212 } 213 m_data[0] <<= bn; 214 } 215 clean_tail(); 216 return *this; 217} 218 219 220// bitwise right shift 221 222sc_bv_base& 223sc_bv_base::operator >>= ( int n ) 224{ 225 if( n < 0 ) { 226 char msg[BUFSIZ]; 227 std::sprintf( msg, 228 "right shift operation is only allowed with positive " 229 "shift values, shift value = %d", n ); 230 SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); 231 } 232 int sz = m_size; 233 if( n >= m_len ) { 234 for( int i = 0; i < sz; ++ i ) { 235 m_data[i] = SC_DIGIT_ZERO; 236 } 237 // clean_tail(); 238 return *this; 239 } 240 int wn = n / SC_DIGIT_SIZE; 241 int bn = n % SC_DIGIT_SIZE; 242 if( wn != 0 ) { 243 // shift words 244 int i = 0; 245 for( ; i < (sz - wn); ++ i ) { 246 m_data[i] = m_data[i + wn]; 247 } 248 for( ; i < sz; ++ i ) { 249 m_data[i] = SC_DIGIT_ZERO; 250 } 251 } 252 if( bn != 0 ) { 253 // shift bits 254 for( int i = 0; i < (sz - 1); ++ i ) { 255 m_data[i] >>= bn; 256 m_data[i] |= m_data[i + 1] << (SC_DIGIT_SIZE - bn); 257 } 258 m_data[sz - 1] >>= bn; 259 } 260 clean_tail(); 261 return *this; 262} 263 264 265// bitwise left rotate 266 267sc_bv_base& 268sc_bv_base::lrotate( int n ) 269{ 270 if( n < 0 ) { 271 char msg[BUFSIZ]; 272 std::sprintf( msg, 273 "left rotate operation is only allowed with positive " 274 "rotate values, rotate value = %d", n ); 275 SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); 276 } 277 int len = m_len; 278 n %= len; 279 *this = (*this << n) | (*this >> (len - n)); 280 return *this; 281} 282 283 284// bitwise right rotate 285 286sc_bv_base& 287sc_bv_base::rrotate( int n ) 288{ 289 if( n < 0 ) { 290 char msg[BUFSIZ]; 291 std::sprintf( msg, 292 "right rotate operation is only allowed with positive " 293 "rotate values, rotate value = %d", n ); 294 SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); 295 } 296 int len = m_len; 297 n %= len; 298 *this = (*this >> n) | (*this << (len - n)); 299 return *this; 300} 301 302#endif 303 304 305// ---------------------------------------------------------------------------- 306 307// convert formatted string to binary string 308 309const std::string 310convert_to_bin( const char* s ) 311{ 312 // Beware: logic character strings cannot start with '0x' or '0X', 313 // because this is seen as a hexadecimal encoding prefix! 314 315 if( s == 0 ) { 316 SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_, 317 "character string is zero" ); 318 } 319 if( *s == 0 ) { 320 SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_, 321 "character string is empty"); 322 } 323 324 int n = strlen( s ); 325 int i = 0; 326 if( s[0] == '-' || s[0] == '+' ) { 327 ++ i; 328 } 329 if( n > (i + 2) && s[i] == '0' ) 330 { 331 if (s[i+1] == 'b' || s[i+1] == 'B' ) 332 { 333 if ( s[i+2] == '0' || s[i+2] == '1' ) 334 { 335 std::string str( &s[2] ); 336 str += "F"; 337 return str; 338 } 339 } 340 if ( s[i+1] == 'b' || s[i+1] == 'B' || 341 s[i+1] == 'c' || s[i+1] == 'C' || 342 s[i+1] == 'd' || s[i+1] == 'D' || 343 s[i+1] == 'o' || s[i+1] == 'O' || 344 s[i+1] == 'x' || s[i+1] == 'X') 345 { 346 try { 347 // worst case length = n * 4 348 sc_fix a( s, n * 4, n * 4, SC_TRN, SC_WRAP, 0, SC_ON ); 349 std::string str = a.to_bin(); 350 str += "F"; // mark the string as formatted 351 // get rid of prefix (0b) and redundant leading bits 352 const char* p = str.c_str() + 2; 353 while( p[1] && p[0] == p[1] ) { 354 ++ p; 355 } 356 return std::string( p ); 357 } catch( sc_core::sc_report ) { 358 char msg[BUFSIZ]; 359 std::sprintf( msg, "character string '%s' is not valid", s ); 360 SC_REPORT_ERROR( sc_core::SC_ID_CANNOT_CONVERT_, msg ); 361 // never reached 362 return std::string(); 363 } 364 } 365 366 } 367 368 // bin by default 369 370 std::string str( s ); 371 str += "U"; // mark the string as unformatted 372 return str; 373} 374 375// convert binary string to formatted string 376 377const std::string 378convert_to_fmt( const std::string& s, sc_numrep numrep, bool w_prefix ) 379{ 380 int n = s.length(); 381 std::string str("0bus"); 382 // str += "0bus"; 383 str += s; 384 sc_ufix a( str.c_str(), n, n, SC_TRN, SC_WRAP, 0, SC_ON ); 385 return a.to_string( numrep, w_prefix ); 386} 387 388} // namespace sc_dt 389