sc_uint_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_uint_base.cpp -- contains interface definitions between sc_uint and 23 sc_signed, sc_unsigned, and definitions for sc_uint_subref. 24 25 Original Author: Ali Dasdan, Synopsys, Inc. 26 27 *****************************************************************************/ 28 29/***************************************************************************** 30 31 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 32 changes you are making here. 33 34 Name, Affiliation, Date: 35 Description of Modification: 36 37 *****************************************************************************/ 38 39 40// $Log: sc_uint_base.cpp,v $ 41// Revision 1.5 2011/02/18 20:19:15 acg 42// Andy Goodrich: updating Copyright notice. 43// 44// Revision 1.4 2010/02/04 22:23:29 acg 45// Andy Goodrich: fixed bug in concatenation reads for part selections, 46// the mask being used was 32 bits and should have been 64 bits. 47// 48// Revision 1.3 2008/06/19 17:47:57 acg 49// Andy Goodrich: fixes for bugs. See 2.2.1 RELEASENOTES. 50// 51// Revision 1.2 2007/11/04 21:27:00 acg 52// Andy Goodrich: changes to make sure the proper value is returned from 53// concat_get_data(). 54// 55// Revision 1.1.1.1 2006/12/15 20:20:05 acg 56// SystemC 2.3 57// 58// Revision 1.3 2006/01/13 18:49:32 acg 59// Added $Log command so that CVS check in comments are reproduced in the 60// source. 61// 62 63#include "sysc/kernel/sc_macros.h" 64#include "sysc/datatypes/int/sc_signed.h" 65#include "sysc/datatypes/int/sc_unsigned.h" 66#include "sysc/datatypes/int/sc_uint_base.h" 67#include "sysc/datatypes/int/sc_int_ids.h" 68#include "sysc/datatypes/bit/sc_bv_base.h" 69#include "sysc/datatypes/bit/sc_lv_base.h" 70#include "sysc/datatypes/misc/sc_concatref.h" 71#include "sysc/datatypes/fx/sc_ufix.h" 72#include "sysc/datatypes/fx/scfx_other_defs.h" 73 74 75namespace sc_dt 76{ 77 78// to avoid code bloat in sc_uint_concat<T1,T2> 79 80void 81sc_uint_concref_invalid_length( int length ) 82{ 83 char msg[BUFSIZ]; 84 std::sprintf( msg, 85 "sc_uint_concref<T1,T2> initialization: length = %d " 86 "violates 1 <= length <= %d", 87 length, SC_INTWIDTH ); 88 SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); 89} 90 91 92 93// ---------------------------------------------------------------------------- 94// CLASS : sc_uint_bitref 95// 96// Proxy class for sc_uint bit selection (r-value and l-value). 97// ---------------------------------------------------------------------------- 98 99sc_core::sc_vpool<sc_uint_bitref> sc_uint_bitref::m_pool(9); 100 101// concatenation methods: 102 103// #### OPTIMIZE 104void sc_uint_bitref::concat_set(int64 src, int low_i) 105{ 106 sc_uint_base aa( 1 ); 107 *this = aa = (low_i < 64) ? src >> low_i : src >> 63; 108} 109 110void sc_uint_bitref::concat_set(const sc_signed& src, int low_i) 111{ 112 sc_uint_base aa( 1 ); 113 if ( low_i < src.length() ) 114 *this = aa = 1 & (src >> low_i); 115 else 116 *this = aa = (src < 0) ? (int_type)-1 : 0; 117} 118 119void sc_uint_bitref::concat_set(const sc_unsigned& src, int low_i) 120{ 121 sc_uint_base aa( 1 ); 122 if ( low_i < src.length() ) 123 *this = aa = 1 & (src >> low_i); 124 else 125 *this = aa = 0; 126} 127 128void sc_uint_bitref::concat_set(uint64 src, int low_i) 129{ 130 sc_uint_base aa( 1 ); 131 *this = aa = (low_i < 64) ? src >> low_i : 0; 132} 133 134 135// other methods 136 137void 138sc_uint_bitref::scan( ::std::istream& is ) 139{ 140 bool b; 141 is >> b; 142 *this = b; 143} 144 145 146// ---------------------------------------------------------------------------- 147// CLASS : sc_uint_subref_r 148// 149// Proxy class for sc_uint part selection (l-value). 150// ---------------------------------------------------------------------------- 151 152bool sc_uint_subref_r::concat_get_ctrl( sc_digit* dst_p, int low_i ) const 153{ 154 int dst_i; // Word in dst_p now processing. 155 int end_i; // Highest order word in dst_p to process. 156 int left_shift; // Left shift for val. 157 uint_type mask; // Mask for bits to extract or keep. 158 159 dst_i = low_i / BITS_PER_DIGIT; 160 left_shift = low_i % BITS_PER_DIGIT; 161 end_i = (low_i + (m_left-m_right)) / BITS_PER_DIGIT; 162 163 mask = ~(-1 << left_shift); 164 dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & mask)); 165 166 dst_i++; 167 for ( ; dst_i <= end_i; dst_i++ ) dst_p[dst_i] = 0; 168 169 return false; 170} 171 172bool sc_uint_subref_r::concat_get_data( sc_digit* dst_p, int low_i ) const 173{ 174 int dst_i; // Word in dst_p now processing. 175 int end_i; // Highest order word in dst_p to process. 176 int high_i; // Index of high order bit in dst_p to set. 177 int left_shift; // Left shift for val. 178 uint_type mask; // Mask for bits to extract or keep. 179 bool result; // True if inserting non-zero value. 180 uint_type val; // Selection value extracted from m_obj_p. 181 182 dst_i = low_i / BITS_PER_DIGIT; 183 left_shift = low_i % BITS_PER_DIGIT; 184 high_i = low_i + (m_left-m_right); 185 end_i = high_i / BITS_PER_DIGIT; 186 mask = ~mask_int[m_left][m_right]; 187 val = (m_obj_p->m_val & mask) >> m_right; 188 result = val != 0; 189 190 191 // PROCESS THE FIRST WORD: 192 193 mask = ~(-1 << left_shift); 194 dst_p[dst_i] = (sc_digit)(((dst_p[dst_i] & mask)) | 195 ((val << left_shift) & DIGIT_MASK)); 196 197 switch ( end_i - dst_i ) 198 { 199 // BITS ARE ACROSS TWO WORDS: 200 201 case 1: 202 dst_i++; 203 val >>= (BITS_PER_DIGIT-left_shift); 204 dst_p[dst_i] = (sc_digit)val; 205 break; 206 207 // BITS ARE ACROSS THREE WORDS: 208 209 case 2: 210 dst_i++; 211 val >>= (BITS_PER_DIGIT-left_shift); 212 dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); 213 val >>= BITS_PER_DIGIT; 214 dst_p[dst_i] = (sc_digit)val; 215 break; 216 217 // BITS ARE ACROSS THREE WORDS: 218 219 case 3: 220 dst_i++; 221 val >>= (BITS_PER_DIGIT-left_shift); 222 dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); 223 val >>= BITS_PER_DIGIT; 224 dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); 225 val >>= BITS_PER_DIGIT; 226 dst_p[dst_i] = (sc_digit)val; 227 break; 228 } 229 return result; 230} 231 232// ---------------------------------------------------------------------------- 233// CLASS : sc_uint_subref 234// 235// Proxy class for sc_uint part selection (r-value and l-value). 236// ---------------------------------------------------------------------------- 237 238sc_core::sc_vpool<sc_uint_subref> sc_uint_subref::m_pool(9); 239 240// assignment operators 241 242sc_uint_subref& 243sc_uint_subref::operator = ( uint_type v ) 244{ 245 uint_type val = m_obj_p->m_val; 246 uint_type mask = mask_int[m_left][m_right]; 247 val &= mask; 248 val |= (v << m_right) & ~mask; 249 m_obj_p->m_val = val; 250 m_obj_p->extend_sign(); 251 return *this; 252} 253 254sc_uint_subref& 255sc_uint_subref::operator = ( const sc_signed& a ) 256{ 257 sc_uint_base aa( length() ); 258 return ( *this = aa = a ); 259} 260 261sc_uint_subref& 262sc_uint_subref::operator = ( const sc_unsigned& a ) 263{ 264 sc_uint_base aa( length() ); 265 return ( *this = aa = a ); 266} 267 268sc_uint_subref& 269sc_uint_subref::operator = ( const sc_bv_base& a ) 270{ 271 sc_uint_base aa( length() ); 272 return ( *this = aa = a ); 273} 274 275sc_uint_subref& 276sc_uint_subref::operator = ( const sc_lv_base& a ) 277{ 278 sc_uint_base aa( length() ); 279 return ( *this = aa = a ); 280} 281 282// concatenation methods: 283 284// #### OPTIMIZE 285void sc_uint_subref::concat_set(int64 src, int low_i) 286{ 287 sc_uint_base aa( length() ); 288 *this = aa = (low_i < 64) ? src >> low_i : src >> 63; 289} 290 291void sc_uint_subref::concat_set(const sc_signed& src, int low_i) 292{ 293 sc_uint_base aa( length() ); 294 if ( low_i < src.length() ) 295 *this = aa = src >> low_i; 296 else 297 *this = aa = (src < 0) ? (int_type)-1 : 0; 298} 299 300void sc_uint_subref::concat_set(const sc_unsigned& src, int low_i) 301{ 302 sc_uint_base aa( length() ); 303 if ( low_i < src.length() ) 304 *this = aa = src >> low_i; 305 else 306 *this = aa = 0; 307} 308 309void sc_uint_subref::concat_set(uint64 src, int low_i) 310{ 311 sc_uint_base aa( length() ); 312 *this = aa = (low_i < 64) ? src >> low_i : 0; 313} 314 315// other methods 316 317void 318sc_uint_subref::scan( ::std::istream& is ) 319{ 320 std::string s; 321 is >> s; 322 *this = s.c_str(); 323} 324 325 326// ---------------------------------------------------------------------------- 327// CLASS : sc_uint_base 328// 329// Base class for sc_uint. 330// ---------------------------------------------------------------------------- 331 332// support methods 333 334void 335sc_uint_base::invalid_length() const 336{ 337 char msg[BUFSIZ]; 338 std::sprintf( msg, 339 "sc_uint[_base] initialization: length = %d violates " 340 "1 <= length <= %d", 341 m_len, SC_INTWIDTH ); 342 SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); 343} 344 345void 346sc_uint_base::invalid_index( int i ) const 347{ 348 char msg[BUFSIZ]; 349 std::sprintf( msg, 350 "sc_uint[_base] bit selection: index = %d violates " 351 "0 <= index <= %d", 352 i, m_len - 1 ); 353 SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); 354} 355 356void 357sc_uint_base::invalid_range( int l, int r ) const 358{ 359 char msg[BUFSIZ]; 360 std::sprintf( msg, 361 "sc_uint[_base] part selection: left = %d, right = %d violates " 362 "%d >= left >= right >= 0", 363 l, r, m_len - 1 ); 364 SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); 365} 366 367 368void 369sc_uint_base::check_value() const 370{ 371 uint_type limit = (~UINT_ZERO >> m_ulen); 372 if( m_val > limit ) { 373 char msg[BUFSIZ]; 374 std::sprintf( msg, "sc_uint[_base]: value does not fit into a length of %d", 375 m_len ); 376 SC_REPORT_WARNING( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); 377 } 378} 379 380 381// constructors 382 383sc_uint_base::sc_uint_base( const sc_bv_base& v ) 384 : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) 385{ 386 check_length(); 387 *this = v; 388} 389sc_uint_base::sc_uint_base( const sc_lv_base& v ) 390 : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) 391{ 392 check_length(); 393 *this = v; 394} 395sc_uint_base::sc_uint_base( const sc_int_subref_r& v ) 396 : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) 397{ 398 check_length(); 399 *this = v.to_uint64(); 400} 401sc_uint_base::sc_uint_base( const sc_signed_subref_r& v ) 402 : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) 403{ 404 check_length(); 405 *this = v.to_uint64(); 406} 407sc_uint_base::sc_uint_base( const sc_unsigned_subref_r& v ) 408 : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len ) 409{ 410 check_length(); 411 *this = v.to_uint64(); 412} 413 414sc_uint_base::sc_uint_base( const sc_signed& a ) 415 : m_val( 0 ), m_len( a.length() ), m_ulen( SC_INTWIDTH - m_len ) 416{ 417 check_length(); 418#if 0 419 for( int i = m_len - 1; i >= 0; -- i ) { 420 set( i, a.test( i ) ); 421 } 422 extend_sign(); 423#else 424 *this = a.to_uint64(); 425#endif 426} 427 428sc_uint_base::sc_uint_base( const sc_unsigned& a ) 429 : m_val( 0 ), m_len( a.length() ), m_ulen( SC_INTWIDTH - m_len ) 430{ 431 check_length(); 432#if 0 433 for( int i = m_len - 1; i >= 0; -- i ) { 434 set( i, a.test( i ) ); 435 } 436 extend_sign(); 437#else 438 *this = a.to_uint64(); 439#endif 440} 441 442// assignment operators 443 444sc_uint_base& 445sc_uint_base::operator = ( const sc_signed& a ) 446{ 447 int minlen = sc_min( m_len, a.length() ); 448 int i = 0; 449 for( ; i < minlen; ++ i ) { 450 set( i, a.test( i ) ); 451 } 452 bool sgn = a.sign(); 453 for( ; i < m_len; ++ i ) { 454 // sign extension 455 set( i, sgn ); 456 } 457 extend_sign(); 458 return *this; 459} 460 461sc_uint_base& 462sc_uint_base::operator = ( const sc_unsigned& a ) 463{ 464 int minlen = sc_min( m_len, a.length() ); 465 int i = 0; 466 for( ; i < minlen; ++ i ) { 467 set( i, a.test( i ) ); 468 } 469 for( ; i < m_len; ++ i ) { 470 // zero extension 471 set( i, 0 ); 472 } 473 extend_sign(); 474 return *this; 475} 476 477 478sc_uint_base& 479sc_uint_base::operator = ( const sc_bv_base& a ) 480{ 481 int minlen = sc_min( m_len, a.length() ); 482 int i = 0; 483 for( ; i < minlen; ++ i ) { 484 set( i, a.get_bit( i ) ); 485 } 486 for( ; i < m_len; ++ i ) { 487 // zero extension 488 set( i, 0 ); 489 } 490 extend_sign(); 491 return *this; 492} 493 494sc_uint_base& 495sc_uint_base::operator = ( const sc_lv_base& a ) 496{ 497 int minlen = sc_min( m_len, a.length() ); 498 int i = 0; 499 for( ; i < minlen; ++ i ) { 500 set( i, sc_logic( a.get_bit( i ) ).to_bool() ); 501 } 502 for( ; i < m_len; ++ i ) { 503 // zero extension 504 set( i, 0 ); 505 } 506 extend_sign(); 507 return *this; 508} 509 510sc_uint_base& 511sc_uint_base::operator = ( const char* a ) 512{ 513 if( a == 0 ) { 514 SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, 515 "character string is zero" ); 516 } 517 if( *a == 0 ) { 518 SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, 519 "character string is empty" ); 520 } 521 try { 522 int len = m_len; 523 sc_ufix aa( a, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); 524 return this->operator = ( aa ); 525 } catch( sc_core::sc_report ) { 526 char msg[BUFSIZ]; 527 std::sprintf( msg, "character string '%s' is not valid", a ); 528 SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg ); 529 // never reached 530 return *this; 531 } 532} 533 534 535// explicit conversion to character string 536 537const std::string 538sc_uint_base::to_string( sc_numrep numrep ) const 539{ 540 int len = m_len; 541 sc_ufix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); 542 return aa.to_string( numrep ); 543} 544 545const std::string 546sc_uint_base::to_string( sc_numrep numrep, bool w_prefix ) const 547{ 548 int len = m_len; 549 sc_ufix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON ); 550 return aa.to_string( numrep, w_prefix ); 551} 552 553 554// reduce methods 555 556bool 557sc_uint_base::and_reduce() const 558{ 559 return ( m_val == (~UINT_ZERO >> m_ulen) ); 560} 561 562bool 563sc_uint_base::or_reduce() const 564{ 565 return ( m_val != uint_type( 0 ) ); 566} 567 568bool 569sc_uint_base::xor_reduce() const 570{ 571 uint_type mask = ~UINT_ZERO; 572 uint_type val = m_val; 573 int n = SC_INTWIDTH; 574 do { 575 n >>= 1; 576 mask >>= n; 577 val = ((val & (mask << n)) >> n) ^ (val & mask); 578 } while( n != 1 ); 579 return ( val != uint_type( 0 ) ); 580} 581 582 583bool sc_uint_base::concat_get_ctrl( sc_digit* dst_p, int low_i ) const 584{ 585 int dst_i; // Word in dst_p now processing. 586 int end_i; // Highest order word in dst_p to process. 587 int left_shift; // Left shift for val. 588 uint_type mask; // Mask for bits to extract or keep. 589 590 dst_i = low_i / BITS_PER_DIGIT; 591 left_shift = low_i % BITS_PER_DIGIT; 592 end_i = (low_i + (m_len-1)) / BITS_PER_DIGIT; 593 594 // PROCESS THE FIRST WORD: 595 596 mask = ~((uint_type)-1 << left_shift); 597 dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & mask)); 598 599 dst_i++; 600 for ( ; dst_i <= end_i; dst_i++ ) dst_p[dst_i] = 0; 601 return false; 602} 603 604//------------------------------------------------------------------------------ 605//"sc_uint_base::concat_get_data" 606// 607// This method transfers the value of this object instance to the supplied 608// array of sc_unsigned digits starting with the bit specified by low_i within 609// the array of digits. 610// 611// Notes: 612// (1) we don't worry about masking the high order data we transfer since 613// concat_get_data() is called from low order bit to high order bit. So 614// the bits above where we place ours will be filled in by someone else. 615// 616// dst_p -> array of sc_unsigned digits to be filled in. 617// low_i = first bit within dst_p to be set. 618//------------------------------------------------------------------------------ 619bool sc_uint_base::concat_get_data( sc_digit* dst_p, int low_i ) const 620{ 621 int dst_i; // Word in dst_p now processing. 622 int end_i; // Highest order word in dst_p to process. 623 int high_i; // Index of high order bit in dst_p to set. 624 int left_shift; // Left shift for val. 625 uint_type mask; // Mask for bits to extract or keep. 626 bool result; // True if inserting non-zero value. 627 uint_type val; // Value for this object. 628 629 dst_i = low_i / BITS_PER_DIGIT; 630 left_shift = low_i % BITS_PER_DIGIT; 631 high_i = low_i + (m_len-1); 632 end_i = high_i / BITS_PER_DIGIT; 633 val = m_val; 634 result = val != 0; 635 636 // MASK OFF DATA TO BE TRANSFERRED BASE ON WIDTH: 637 638 if ( m_len < 64 ) 639 { 640 mask = ~((uint_type)-1 << m_len); 641 val &= mask; 642 } 643 644 // PROCESS THE FIRST WORD: 645 646 mask = ~((uint_type)-1 << left_shift); 647 dst_p[dst_i] = (sc_digit)(((dst_p[dst_i] & mask)) | 648 ((val << left_shift) & DIGIT_MASK)); 649 650 switch ( end_i - dst_i ) 651 { 652 // BITS ARE ACROSS TWO WORDS: 653 654 case 1: 655 dst_i++; 656 val >>= (BITS_PER_DIGIT-left_shift); 657 dst_p[dst_i] = (sc_digit)val; 658 break; 659 660 // BITS ARE ACROSS THREE WORDS: 661 662 case 2: 663 dst_i++; 664 val >>= (BITS_PER_DIGIT-left_shift); 665 dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); 666 val >>= BITS_PER_DIGIT; 667 dst_p[dst_i] = (sc_digit)val; 668 break; 669 670 // BITS ARE ACROSS FOUR WORDS: 671 672 case 3: 673 dst_i++; 674 val >>= (BITS_PER_DIGIT-left_shift); 675 dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); 676 val >>= BITS_PER_DIGIT; 677 dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); 678 val >>= BITS_PER_DIGIT; 679 dst_p[dst_i] = (sc_digit)val; 680 break; 681 682 } 683 return result; 684} 685 686// #### OPTIMIZE 687void sc_uint_base::concat_set(int64 src, int low_i) 688{ 689 *this = (low_i < 64) ? src >> low_i : src >> 63; 690} 691 692void sc_uint_base::concat_set(const sc_signed& src, int low_i) 693{ 694 if ( low_i < src.length() ) 695 *this = src >> low_i; 696 else 697 *this = (src < 0) ? (int_type)-1 : 0; 698} 699 700void sc_uint_base::concat_set(const sc_unsigned& src, int low_i) 701{ 702 if ( low_i < src.length() ) 703 *this = src >> low_i; 704 else 705 *this = 0; 706} 707 708void sc_uint_base::concat_set(uint64 src, int low_i) 709{ 710 *this = (low_i < 64) ? src >> low_i : 0; 711} 712 713 714// other methods 715 716void 717sc_uint_base::scan( ::std::istream& is ) 718{ 719 std::string s; 720 is >> s; 721 *this = s.c_str(); 722} 723 724} // namespace sc_dt 725 726 727// Taf! 728