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