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