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 <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_ufix.hh" 68#include "systemc/ext/dt/fx/scfx_other_defs.hh" 69#include "systemc/ext/dt/int/sc_signed.hh" 70#include "systemc/ext/dt/int/sc_uint_base.hh" 71#include "systemc/ext/dt/int/sc_unsigned.hh" 72#include "systemc/ext/dt/misc/sc_concatref.hh" 73 74// explicit template instantiations 75namespace sc_core 76{ 77 78template class sc_vpool<sc_dt::sc_uint_bitref>; 79template class sc_vpool<sc_dt::sc_uint_subref>; 80 81} // namespace sc_core 82 83namespace sc_dt 84{ 85 86// to avoid code bloat in sc_uint_concat<T1,T2> 87 88void 89sc_uint_concref_invalid_length(int length) 90{ 91 std::stringstream msg; 92 msg << "sc_uint_concref<T1,T2> initialization: length = " << length << 93 "violates 1 <= length <= " << SC_INTWIDTH; 94 SC_REPORT_ERROR(sc_core::SC_ID_OUT_OF_BOUNDS_, msg.str().c_str()); 95 sc_core::sc_abort(); // can't recover from here 96} 97 98 99 100// ---------------------------------------------------------------------------- 101// CLASS : sc_uint_bitref 102// 103// Proxy class for sc_uint bit selection (r-value and l-value). 104// ---------------------------------------------------------------------------- 105 106sc_core::sc_vpool<sc_uint_bitref> sc_uint_bitref::m_pool(9); 107 108// concatenation methods: 109 110// #### OPTIMIZE 111void 112sc_uint_bitref::concat_set(int64 src, int low_i) 113{ 114 sc_uint_base aa(1); 115 *this = aa = (low_i < 64) ? src >> low_i : src >> 63; 116} 117 118void 119sc_uint_bitref::concat_set(const sc_signed &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 = (src < 0) ? (int_type)-1 : 0; 126} 127 128void 129sc_uint_bitref::concat_set(const sc_unsigned &src, int low_i) 130{ 131 sc_uint_base aa(1); 132 if (low_i < src.length()) 133 *this = aa = 1 & (src >> low_i); 134 else 135 *this = aa = 0; 136} 137 138void 139sc_uint_bitref::concat_set(uint64 src, int low_i) 140{ 141 sc_uint_base aa(1); 142 *this = aa = (low_i < 64) ? src >> low_i : 0; 143} 144 145 146// other methods 147void 148sc_uint_bitref::scan(::std::istream &is) 149{ 150 bool b; 151 is >> b; 152 *this = b; 153} 154 155 156// ---------------------------------------------------------------------------- 157// CLASS : sc_uint_subref_r 158// 159// Proxy class for sc_uint part selection (l-value). 160// ---------------------------------------------------------------------------- 161 162bool 163sc_uint_subref_r::concat_get_ctrl(sc_digit *dst_p, int low_i) const 164{ 165 int dst_i; // Word in dst_p now processing. 166 int end_i; // Highest order word in dst_p to process. 167 int left_shift; // Left shift for val. 168 uint_type mask; // Mask for bits to extract or keep. 169 170 dst_i = low_i / BITS_PER_DIGIT; 171 left_shift = low_i % BITS_PER_DIGIT; 172 end_i = (low_i + (m_left-m_right)) / BITS_PER_DIGIT; 173 174 mask = ~(~UINT_ZERO << left_shift); 175 dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & mask)); 176 177 dst_i++; 178 for (; dst_i <= end_i; dst_i++) 179 dst_p[dst_i] = 0; 180 181 return false; 182} 183 184bool 185sc_uint_subref_r::concat_get_data(sc_digit *dst_p, int low_i) const 186{ 187 int dst_i; // Word in dst_p now processing. 188 int end_i; // Highest order word in dst_p to process. 189 int high_i; // Index of high order bit in dst_p to set. 190 int left_shift; // Left shift for val. 191 uint_type mask; // Mask for bits to extract or keep. 192 bool result; // True if inserting non-zero value. 193 uint_type val; // Selection value extracted from m_obj_p. 194 195 dst_i = low_i / BITS_PER_DIGIT; 196 left_shift = low_i % BITS_PER_DIGIT; 197 high_i = low_i + (m_left-m_right); 198 end_i = high_i / BITS_PER_DIGIT; 199 mask = ~mask_int[m_left][m_right]; 200 val = (m_obj_p->m_val & mask) >> m_right; 201 result = val != 0; 202 203 // PROCESS THE FIRST WORD: 204 mask = ~(~UINT_ZERO << left_shift); 205 dst_p[dst_i] = (sc_digit)(((dst_p[dst_i] & mask)) | 206 ((val << left_shift) & DIGIT_MASK)); 207 208 switch (end_i - dst_i) { 209 // BITS ARE ACROSS TWO WORDS: 210 case 1: 211 dst_i++; 212 val >>= (BITS_PER_DIGIT-left_shift); 213 dst_p[dst_i] = (sc_digit)val; 214 break; 215 216 // BITS ARE ACROSS THREE WORDS: 217 case 2: 218 dst_i++; 219 val >>= (BITS_PER_DIGIT-left_shift); 220 dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); 221 val >>= BITS_PER_DIGIT; 222 dst_p[dst_i] = (sc_digit)val; 223 break; 224 225 // BITS ARE ACROSS THREE WORDS: 226 case 3: 227 dst_i++; 228 val >>= (BITS_PER_DIGIT-left_shift); 229 dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); 230 val >>= BITS_PER_DIGIT; 231 dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK); 232 val >>= BITS_PER_DIGIT; 233 dst_p[dst_i] = (sc_digit)val; 234 break; 235 } 236 return result; 237} 238 239// ---------------------------------------------------------------------------- 240// CLASS : sc_uint_subref 241// 242// Proxy class for sc_uint part selection (r-value and l-value). 243// ---------------------------------------------------------------------------- 244 245sc_core::sc_vpool<sc_uint_subref> sc_uint_subref::m_pool(9); 246 247// assignment operators 248 249sc_uint_subref & 250sc_uint_subref::operator = (uint_type v) 251{ 252 uint_type val = m_obj_p->m_val; 253 uint_type mask = mask_int[m_left][m_right]; 254 val &= mask; 255 val |= (v << m_right) & ~mask; 256 m_obj_p->m_val = val; 257 m_obj_p->extend_sign(); 258 return *this; 259} 260 261sc_uint_subref & 262sc_uint_subref::operator = (const sc_signed &a) 263{ 264 sc_uint_base aa(length()); 265 return (*this = aa = a); 266} 267 268sc_uint_subref & 269sc_uint_subref::operator = (const sc_unsigned &a) 270{ 271 sc_uint_base aa(length()); 272 return (*this = aa = a); 273} 274 275sc_uint_subref & 276sc_uint_subref::operator = (const sc_bv_base &a) 277{ 278 sc_uint_base aa(length()); 279 return (*this = aa = a); 280} 281 282sc_uint_subref & 283sc_uint_subref::operator = (const sc_lv_base &a) 284{ 285 sc_uint_base aa(length()); 286 return (*this = aa = a); 287} 288 289// concatenation methods: 290 291// #### OPTIMIZE 292void 293sc_uint_subref::concat_set(int64 src, int low_i) 294{ 295 sc_uint_base aa(length()); 296 *this = aa = (low_i < 64) ? src >> low_i : src >> 63; 297} 298 299void 300sc_uint_subref::concat_set(const sc_signed &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 = (src < 0) ? (int_type)-1 : 0; 307} 308 309void 310sc_uint_subref::concat_set(const sc_unsigned &src, int low_i) 311{ 312 sc_uint_base aa(length()); 313 if (low_i < src.length()) 314 *this = aa = src >> low_i; 315 else 316 *this = aa = 0; 317} 318 319void 320sc_uint_subref::concat_set(uint64 src, int low_i) 321{ 322 sc_uint_base aa(length()); 323 *this = aa = (low_i < 64) ? src >> low_i : 0; 324} 325 326// other methods 327void 328sc_uint_subref::scan(::std::istream &is) 329{ 330 std::string s; 331 is >> s; 332 *this = s.c_str(); 333} 334 335 336// ---------------------------------------------------------------------------- 337// CLASS : sc_uint_base 338// 339// Base class for sc_uint. 340// ---------------------------------------------------------------------------- 341 342// support methods 343 344void 345sc_uint_base::invalid_length() const 346{ 347 std::stringstream msg; 348 msg << "sc_uint[_base] initialization: length = " << m_len << 349 " violates 1 <= length <= " << SC_INTWIDTH; 350 SC_REPORT_ERROR(sc_core::SC_ID_OUT_OF_BOUNDS_, msg.str().c_str()); 351 sc_core::sc_abort(); // can't recover from here} 352} 353 354void 355sc_uint_base::invalid_index(int i) const 356{ 357 std::stringstream msg; 358 msg << "sc_uint[_base] bit selection: index = " << i << 359 " violates 0 <= index <= " << (m_len - 1); 360 SC_REPORT_ERROR(sc_core::SC_ID_OUT_OF_BOUNDS_, msg.str().c_str()); 361 sc_core::sc_abort(); // can't recover from here 362} 363 364void 365sc_uint_base::invalid_range(int l, int r) const 366{ 367 std::stringstream msg; 368 msg << "sc_uint[_base] part selection: " << 369 "left = " << l << ", right = " << r << " violates " << 370 (m_len - 1) << " >= left >= right >= 0"; 371 SC_REPORT_ERROR(sc_core::SC_ID_OUT_OF_BOUNDS_, msg.str().c_str()); 372 sc_core::sc_abort(); // can't recover from here 373} 374 375 376void 377sc_uint_base::check_value() const 378{ 379 uint_type limit = (~UINT_ZERO >> m_ulen); 380 if (m_val > limit) { 381 std::stringstream msg; 382 msg << "sc_uint[_base]: value does not fit into a length of " << m_len; 383 SC_REPORT_WARNING(sc_core::SC_ID_OUT_OF_BOUNDS_, msg.str().c_str()); 384 } 385} 386 387 388// constructors 389sc_uint_base::sc_uint_base(const sc_bv_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_lv_base &v) : 396 m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len) 397{ 398 check_length(); 399 *this = v; 400} 401sc_uint_base::sc_uint_base(const sc_int_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_signed_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} 413sc_uint_base::sc_uint_base(const sc_unsigned_subref_r &v) : 414 m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len) 415{ 416 check_length(); 417 *this = v.to_uint64(); 418} 419 420sc_uint_base::sc_uint_base(const sc_signed &a) : 421 m_val(0), m_len(a.length()), m_ulen(SC_INTWIDTH - m_len) 422{ 423 check_length(); 424 *this = a.to_uint64(); 425} 426 427sc_uint_base::sc_uint_base(const sc_unsigned &a) : 428 m_val(0), m_len(a.length()), m_ulen(SC_INTWIDTH - m_len) 429{ 430 check_length(); 431 *this = a.to_uint64(); 432} 433 434// assignment operators 435 436sc_uint_base & 437sc_uint_base::operator = (const sc_signed &a) 438{ 439 int minlen = sc_min(m_len, a.length()); 440 int i = 0; 441 for (; i < minlen; ++i) { 442 set(i, a.test(i)); 443 } 444 bool sgn = a.sign(); 445 for (; i < m_len; ++i) { 446 // sign extension 447 set(i, sgn); 448 } 449 extend_sign(); 450 return *this; 451} 452 453sc_uint_base & 454sc_uint_base::operator = (const sc_unsigned &a) 455{ 456 int minlen = sc_min(m_len, a.length()); 457 int i = 0; 458 for (; i < minlen; ++i) { 459 set(i, a.test(i)); 460 } 461 for (; i < m_len; ++i) { 462 // zero extension 463 set(i, 0); 464 } 465 extend_sign(); 466 return *this; 467} 468 469 470sc_uint_base & 471sc_uint_base::operator = (const sc_bv_base &a) 472{ 473 int minlen = sc_min(m_len, a.length()); 474 int i = 0; 475 for (; i < minlen; ++i) { 476 set(i, a.get_bit(i)); 477 } 478 for (; i < m_len; ++i) { 479 // zero extension 480 set(i, 0); 481 } 482 extend_sign(); 483 return *this; 484} 485 486sc_uint_base & 487sc_uint_base::operator = (const sc_lv_base &a) 488{ 489 int minlen = sc_min(m_len, a.length()); 490 int i = 0; 491 for (; i < minlen; ++i) { 492 set(i, sc_logic(a.get_bit(i)).to_bool()); 493 } 494 for (; i < m_len; ++i) { 495 // zero extension 496 set(i, 0); 497 } 498 extend_sign(); 499 return *this; 500} 501 502sc_uint_base & 503sc_uint_base::operator = (const char *a) 504{ 505 if (a == 0) { 506 SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 507 "character string is zero"); 508 } else if (*a == 0) { 509 SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 510 "character string is empty"); 511 } else try { 512 int len = m_len; 513 sc_ufix aa(a, len, len, SC_TRN, SC_WRAP, 0, SC_ON); 514 return this->operator = (aa); 515 } catch(const sc_core::sc_report &) { 516 std::stringstream msg; 517 msg << "character string '" << a << "' is not valid"; 518 SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, msg.str().c_str()); 519 } 520 return *this; 521} 522 523 524// explicit conversion to character string 525const std::string 526sc_uint_base::to_string(sc_numrep numrep) const 527{ 528 int len = m_len; 529 sc_ufix aa(*this, len, len, SC_TRN, SC_WRAP, 0, SC_ON); 530 return aa.to_string(numrep); 531} 532 533const std::string 534sc_uint_base::to_string(sc_numrep numrep, bool w_prefix) const 535{ 536 int len = m_len; 537 sc_ufix aa(*this, len, len, SC_TRN, SC_WRAP, 0, SC_ON); 538 return aa.to_string(numrep, w_prefix); 539} 540 541 542// reduce methods 543bool 544sc_uint_base::and_reduce() const 545{ 546 return (m_val == (~UINT_ZERO >> m_ulen)); 547} 548 549bool 550sc_uint_base::or_reduce() const 551{ 552 return (m_val != uint_type(0)); 553} 554 555bool 556sc_uint_base::xor_reduce() const 557{ 558 uint_type mask = ~UINT_ZERO; 559 uint_type val = m_val; 560 int n = SC_INTWIDTH; 561 do { 562 n >>= 1; 563 mask >>= n; 564 val = ((val & (mask << n)) >> n) ^ (val & mask); 565 } while (n != 1); 566 return (val != uint_type(0)); 567} 568 569 570bool 571sc_uint_base::concat_get_ctrl(sc_digit *dst_p, int low_i) const 572{ 573 int dst_i; // Word in dst_p now processing. 574 int end_i; // Highest order word in dst_p to process. 575 int left_shift; // Left shift for val. 576 uint_type mask; // Mask for bits to extract or keep. 577 578 dst_i = low_i / BITS_PER_DIGIT; 579 left_shift = low_i % BITS_PER_DIGIT; 580 end_i = (low_i + (m_len - 1)) / BITS_PER_DIGIT; 581 582 // PROCESS THE FIRST WORD: 583 mask = ~(~UINT_ZERO << left_shift); 584 dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & mask)); 585 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_uint_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_uint_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 result; // True if inserting non-zero value. 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 result = val != 0; 624 625 // MASK OFF DATA TO BE TRANSFERRED BASE 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 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 result; 665} 666 667// #### OPTIMIZE 668void 669sc_uint_base::concat_set(int64 src, int low_i) 670{ 671 *this = (low_i < 64) ? src >> low_i : src >> 63; 672} 673 674void 675sc_uint_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_uint_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_uint_base::concat_set(uint64 src, int low_i) 694{ 695 *this = (low_i < 64) ? src >> low_i : 0; 696} 697 698 699// other methods 700void 701sc_uint_base::scan(::std::istream &is) 702{ 703 std::string s; 704 is >> s; 705 *this = s.c_str(); 706} 707 708} // namespace sc_dt 709