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