69#include "systemc/ext/dt/fx/scfx_ieee.hh" 70#include "systemc/ext/dt/fx/scfx_pow10.hh" 71#include "systemc/ext/dt/fx/scfx_rep.hh" 72#include "systemc/ext/dt/fx/scfx_utils.hh" 73#include "systemc/ext/utils/endian.hh" 74#include "systemc/ext/utils/messages.hh" 75 76namespace sc_dt 77{ 78 79// ---------------------------------------------------------------------------- 80// some utilities 81// ---------------------------------------------------------------------------- 82 83static scfx_pow10 pow10_fx; 84 85static const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int; 86 87static inline int 88n_word(int x) 89{ 90 return (x + bits_in_word - 1) / bits_in_word; 91} 92 93 94// ---------------------------------------------------------------------------- 95// CONSTRUCTORS 96// ---------------------------------------------------------------------------- 97 98scfx_rep::scfx_rep() : 99 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 100 m_r_flag(false) 101{ 102 set_zero(); 103} 104 105scfx_rep::scfx_rep(int a) : m_mant(min_mant), m_wp(), m_sign(), m_state(), 106 m_msw(), m_lsw(), m_r_flag(false) 107{ 108 if (a != 0) { 109 m_mant.clear(); 110 m_wp = m_msw = m_lsw = 2; 111 m_state = normal; 112 if (a > 0) { 113 m_mant[2] = a; 114 m_sign = 1; 115 } else { 116 m_mant[2] = -a; 117 m_sign = -1; 118 } 119 } else { 120 set_zero(); 121 } 122} 123 124scfx_rep::scfx_rep(unsigned int a) : m_mant(min_mant), m_wp(), m_sign(), 125 m_state(), m_msw(), m_lsw(), m_r_flag(false) 126{ 127 if (a != 0) { 128 m_mant.clear(); 129 m_wp = m_msw = m_lsw = 2; 130 m_state = normal; 131 m_mant[2] = a; 132 m_sign = 1; 133 } else { 134 set_zero(); 135 } 136} 137 138scfx_rep::scfx_rep(long a) : 139 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 140 m_r_flag(false) 141{ 142 if (a != 0) { 143 m_mant.clear(); 144 m_state = normal; 145 if (a > 0) { 146 m_sign = 1; 147 } else { 148 a = -a; 149 m_sign = -1; 150 } 151# if SC_LONG_64 152 m_wp = 1; 153 m_mant[1] = static_cast<word>(a); 154 m_mant[2] = static_cast<word>(a >> bits_in_word); 155 find_sw(); 156# else 157 m_wp = 2; 158 m_msw = 2; 159 m_lsw = 2; 160 m_mant[2] = a; 161# endif 162 } else { 163 set_zero(); 164 } 165} 166 167scfx_rep::scfx_rep(unsigned long a) : 168 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 169 m_r_flag(false) 170{ 171 if (a != 0) { 172 m_mant.clear(); 173 m_wp = m_msw = m_lsw = 2; 174 m_state = normal; 175# if SC_LONG_64 176 m_wp = 1; 177 m_mant[1] = static_cast<word>(a); 178 m_mant[2] = static_cast<word>(a >> bits_in_word); 179 find_sw(); 180# else 181 m_wp = 2; 182 m_msw = 2; 183 m_lsw = 2; 184 m_mant[2] = a; 185# endif 186 m_sign = 1; 187 } 188 else 189 set_zero(); 190} 191 192scfx_rep::scfx_rep(double a) : 193 m_mant(min_mant), m_wp(0), m_sign(), m_state(normal), m_msw(0), 194 m_lsw(0), m_r_flag(false) 195{ 196 m_mant.clear(); 197 198 scfx_ieee_double id(a); 199 200 m_sign = id.negative() ? -1 : 1; 201 202 if (id.is_nan()) { 203 m_state = not_a_number; 204 } else if (id.is_inf()) { 205 m_state = infinity; 206 } else if (id.is_subnormal()) { 207 m_mant[0] = id.mantissa1(); 208 m_mant[1] = id.mantissa0(); 209 normalize(id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE); 210 } else if (id.is_normal()) { 211 m_mant[0] = id.mantissa1(); 212 m_mant[1] = id.mantissa0() | (1 << mantissa0_size); 213 normalize(id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE); 214 } 215} 216 217scfx_rep::scfx_rep(int64 a) : 218 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 219 m_r_flag(false) 220{ 221 if (a != 0) { 222 m_mant.clear(); 223 m_wp = 1; 224 m_state = normal; 225 if (a > 0) { 226 m_mant[1] = static_cast<word>(a); 227 m_mant[2] = static_cast<word>(a >> bits_in_word); 228 m_sign = 1; 229 } else { 230 m_mant[1] = static_cast<word>(-a); 231 m_mant[2] = static_cast<word>((-a) >> bits_in_word); 232 m_sign = -1; 233 } 234 find_sw(); 235 } else { 236 set_zero(); 237 } 238} 239 240scfx_rep::scfx_rep(uint64 a) : 241 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 242 m_r_flag(false) 243{ 244 if (a != 0) { 245 m_mant.clear(); 246 m_wp = 1; 247 m_state = normal; 248 m_mant[1] = static_cast<word>(a); 249 m_mant[2] = static_cast<word>(a >> bits_in_word); 250 m_sign = 1; 251 find_sw(); 252 } else { 253 set_zero(); 254 } 255} 256 257scfx_rep::scfx_rep(const sc_signed &a) : 258 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 259 m_r_flag(false) 260{ 261 if (a.iszero()) { 262 set_zero(); 263 } else { 264 int words = n_word(a.length()); 265 if (words > size()) 266 resize_to(words); 267 m_mant.clear(); 268 m_wp = 0; 269 m_state = normal; 270 if (a.sign()) { 271 sc_signed a2 = -a; 272 for (int i = 0; i < a2.length(); ++i) { 273 if (a2[i]) { 274 scfx_index x = calc_indices(i); 275 m_mant[x.wi()] |= 1 << x.bi(); 276 } 277 } 278 m_sign = -1; 279 } else { 280 for (int i = 0; i < a.length(); ++i) { 281 if (a[i]) { 282 scfx_index x = calc_indices(i); 283 m_mant[x.wi()] |= 1 << x.bi(); 284 } 285 } 286 m_sign = 1; 287 } 288 find_sw(); 289 } 290} 291 292scfx_rep::scfx_rep(const sc_unsigned &a) : 293 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 294 m_r_flag(false) 295{ 296 if (a.iszero()) { 297 set_zero(); 298 } else { 299 int words = n_word(a.length()); 300 if (words > size()) 301 resize_to(words); 302 m_mant.clear(); 303 m_wp = 0; 304 m_state = normal; 305 for (int i = 0; i < a.length(); ++i) { 306 if (a[i]) { 307 scfx_index x = calc_indices(i); 308 m_mant[x.wi()] |= 1 << x.bi(); 309 } 310 } 311 m_sign = 1; 312 find_sw(); 313 } 314} 315 316// copy constructor 317scfx_rep::scfx_rep(const scfx_rep &a) : 318 m_mant(a.m_mant), m_wp(a.m_wp), m_sign(a.m_sign), m_state(a.m_state), 319 m_msw(a.m_msw), m_lsw(a.m_lsw), m_r_flag(false) 320{} 321 322 323// ---------------------------------------------------------------------------- 324// OPERATORS : new, delete 325// 326// Memory management for class scfx_rep. 327// ---------------------------------------------------------------------------- 328 329union scfx_rep_node 330{ 331 char data[sizeof(scfx_rep)]; 332 scfx_rep_node *next; 333}; 334 335static scfx_rep_node *list = 0; 336 337void * 338scfx_rep::operator new(std::size_t size) 339{ 340 const int ALLOC_SIZE = 1024; 341 342 if (size != sizeof(scfx_rep)) 343 return ::operator new(size); 344 345 if (!list) { 346 list = new scfx_rep_node[ALLOC_SIZE]; 347 for (int i = 0; i < ALLOC_SIZE - 1; i++) 348 list[i].next = list + i + 1; 349 list[ALLOC_SIZE - 1].next = 0; 350 } 351 352 scfx_rep *ptr = reinterpret_cast<scfx_rep *>(list->data); 353 list = list->next; 354 355 return ptr; 356} 357 358void 359scfx_rep::operator delete(void *ptr, std::size_t size) 360{ 361 if (size != sizeof(scfx_rep)) { 362 ::operator delete(ptr); 363 return; 364 } 365 366 scfx_rep_node *node = static_cast<scfx_rep_node *>(ptr); 367 node->next = list; 368 list = node; 369} 370 371 372// ---------------------------------------------------------------------------- 373// METHOD : from_string 374// 375// Convert from character string to sc_fxrep. 376// ---------------------------------------------------------------------------- 377 378#define SCFX_FAIL_IF_(cnd) \ 379{ \ 380 if ((cnd)) { \ 381 m_state = not_a_number; \ 382 m_mant.clear(); /* to avoid Purify UMRs during assignment */ \ 383 return; \ 384 } \ 385} 386 387void 388scfx_rep::from_string(const char *s, int cte_wl) 389{ 390 SCFX_FAIL_IF_(s == 0 || *s == 0); 391 392 scfx_string s2; 393 s2 += s; 394 s2 += '\0'; 395 396 bool sign_char; 397 m_sign = scfx_parse_sign(s, sign_char); 398 399 sc_numrep numrep = scfx_parse_prefix(s); 400 401 int base = 0; 402 403 switch (numrep) { 404 case SC_DEC: 405 { 406 base = 10; 407 if (scfx_is_nan(s)) { // special case: NaN 408 m_state = not_a_number; 409 m_mant.clear(); /* to avoid Purify UMRs during assignment */ 410 return; 411 } 412 if (scfx_is_inf(s)) { // special case: Infinity 413 m_state = infinity; 414 m_mant.clear(); /* to avoid Purify UMRs during assignment */ 415 return; 416 } 417 break; 418 } 419 case SC_BIN: 420 case SC_BIN_US: 421 { 422 SCFX_FAIL_IF_(sign_char); 423 base = 2; 424 break; 425 } 426 427 case SC_BIN_SM: 428 { 429 base = 2; 430 break; 431 } 432 case SC_OCT: 433 case SC_OCT_US: 434 { 435 SCFX_FAIL_IF_(sign_char); 436 base = 8; 437 break; 438 } 439 case SC_OCT_SM: 440 { 441 base = 8; 442 break; 443 } 444 case SC_HEX: 445 case SC_HEX_US: 446 { 447 SCFX_FAIL_IF_(sign_char); 448 base = 16; 449 break; 450 } 451 case SC_HEX_SM: 452 { 453 base = 16; 454 break; 455 } 456 case SC_CSD: 457 { 458 SCFX_FAIL_IF_(sign_char); 459 base = 2; 460 scfx_csd2tc(s2); 461 s = (const char *)s2 + 4; 462 numrep = SC_BIN; 463 break; 464 } 465 default: 466 ; 467 } 468 469 // 470 // find end of mantissa and count the digits and points 471 // 472 473 const char *end = s; 474 bool based_point = false; 475 int int_digits = 0; 476 int frac_digits = 0; 477 478 while (*end) { 479 if (scfx_exp_start(end)) 480 break; 481 482 if (*end == '.') { 483 SCFX_FAIL_IF_(based_point); 484 based_point = true; 485 } else { 486 SCFX_FAIL_IF_(!scfx_is_digit(*end, numrep)); 487 if (based_point) 488 frac_digits++; 489 else 490 int_digits++; 491 } 492 493 ++end; 494 } 495 496 SCFX_FAIL_IF_(int_digits == 0 && frac_digits == 0); 497 498 // [ exponent ] 499 int exponent = 0; 500 501 if (*end) { 502 for (const char *e = end + 2; *e; ++e) 503 SCFX_FAIL_IF_(!scfx_is_digit(*e, SC_DEC)); 504 exponent = std::atoi(end + 1); 505 } 506 507 // 508 // check if the mantissa is negative 509 // 510 bool mant_is_neg = false; 511 switch (numrep) { 512 case SC_BIN: 513 case SC_OCT: 514 case SC_HEX: 515 { 516 const char *p = s; 517 if (*p == '.') 518 ++p; 519 520 mant_is_neg = (scfx_to_digit(* p, numrep) >= (base >> 1)); 521 break; 522 } 523 default: 524 ; 525 } 526 527 // 528 // convert the mantissa 529 // 530 531 switch (base) { 532 case 2: 533 { 534 int bit_offset = exponent % bits_in_word; 535 int word_offset = exponent / bits_in_word; 536 537 int_digits += bit_offset; 538 frac_digits -= bit_offset; 539 540 int words = n_word(int_digits) + n_word(frac_digits); 541 if (words > size()) 542 resize_to(words); 543 m_mant.clear(); 544 545 int j = n_word(frac_digits) * bits_in_word + int_digits - 1; 546 547 for (; s < end; s++) { 548 switch (*s) { 549 case '1': 550 set_bin(j); 551 M5_FALLTHROUGH; 552 case '0': 553 j--; 554 M5_FALLTHROUGH; 555 case '.': 556 break; 557 default: 558 SCFX_FAIL_IF_(true); // should not happen 559 } 560 } 561 562 m_wp = n_word(frac_digits) - word_offset; 563 break; 564 } 565 case 8: 566 { 567 exponent *= 3; 568 int_digits *= 3; 569 frac_digits *= 3; 570 571 int bit_offset = exponent % bits_in_word; 572 int word_offset = exponent / bits_in_word; 573 574 int_digits += bit_offset; 575 frac_digits -= bit_offset; 576 577 int words = n_word(int_digits) + n_word(frac_digits); 578 if (words > size()) 579 resize_to(words); 580 m_mant.clear(); 581 582 int j = n_word(frac_digits) * bits_in_word + int_digits - 3; 583 584 for (; s < end; s++) { 585 switch (*s) { 586 case '7': case '6': case '5': case '4': 587 case '3': case '2': case '1': 588 set_oct(j, *s - '0'); 589 M5_FALLTHROUGH; 590 case '0': 591 j -= 3; 592 M5_FALLTHROUGH; 593 case '.': 594 break; 595 default: 596 SCFX_FAIL_IF_(true); // should not happen 597 } 598 } 599 600 m_wp = n_word(frac_digits) - word_offset; 601 break; 602 } 603 case 10: 604 { 605 word carry, temp; 606 int length = int_digits + frac_digits; 607 resize_to(sc_max(min_mant, n_word(4 * length))); 608 609 m_mant.clear(); 610 m_msw = m_lsw = 0; 611 612 for (; s < end; s++) { 613 switch (*s) { 614 case '9': case '8': case '7': case '6': case '5': 615 case '4': case '3': case '2': case '1': case '0': 616 multiply_by_ten(); 617 carry = *s - '0'; 618 for (int i = 0; carry && i < m_mant.size(); i++) { 619 temp = m_mant[i]; 620 temp += carry; 621 carry = temp < m_mant[i]; 622 m_mant[i] = temp; 623 } 624 case '.': 625 break; 626 default: 627 SCFX_FAIL_IF_(true); // should not happen 628 } 629 } 630 631 m_wp = 0; 632 find_sw(); 633 634 int denominator = frac_digits - exponent; 635 636 if (denominator) { 637 scfx_rep frac_num = pow10_fx(denominator); 638 scfx_rep *temp_num = 639 div_scfx_rep(const_cast<const scfx_rep &>(*this), 640 frac_num, cte_wl); 641 *this = *temp_num; 642 delete temp_num; 643 } 644 645 break; 646 } 647 case 16: 648 { 649 exponent *= 4; 650 int_digits *= 4; 651 frac_digits *= 4; 652 653 int bit_offset = exponent % bits_in_word; 654 int word_offset = exponent / bits_in_word; 655 656 int_digits += bit_offset; 657 frac_digits -= bit_offset; 658 659 int words = n_word(int_digits) + n_word(frac_digits); 660 if (words > size()) 661 resize_to(words); 662 m_mant.clear(); 663 664 int j = n_word(frac_digits) * bits_in_word + int_digits - 4; 665 666 for (; s < end; s ++) { 667 switch (*s) { 668 case 'f': case 'e': case 'd': case 'c': case 'b': case 'a': 669 set_hex(j, *s - 'a' + 10); 670 j -= 4; 671 break; 672 case 'F': case 'E': case 'D': case 'C': case 'B': case 'A': 673 set_hex(j, *s - 'A' + 10); 674 j -= 4; 675 break; 676 case '9': case '8': case '7': case '6': case '5': 677 case '4': case '3': case '2': case '1': 678 set_hex(j, *s - '0'); 679 M5_FALLTHROUGH; 680 case '0': 681 j -= 4; 682 M5_FALLTHROUGH; 683 case '.': 684 break; 685 default: 686 SCFX_FAIL_IF_(true); // should not happen 687 } 688 } 689 690 m_wp = n_word(frac_digits) - word_offset; 691 break; 692 } 693 } 694 695 m_state = normal; 696 find_sw(); 697 698 // 699 // two's complement of mantissa if it is negative 700 // 701 if (mant_is_neg) { 702 m_mant[m_msw] |= ~0U << scfx_find_msb(m_mant[m_msw]); 703 for (int i = m_msw + 1; i < m_mant.size(); ++i) 704 m_mant[i] = static_cast<word>(-1); 705 complement(m_mant, m_mant, m_mant.size()); 706 inc(m_mant); 707 m_sign *= -1; 708 find_sw(); 709 } 710} 711 712#undef SCFX_FAIL_IF_ 713 714// ---------------------------------------------------------------------------- 715// METHOD : to_double 716// 717// Convert from scfx_rep to double. 718// ---------------------------------------------------------------------------- 719 720double 721scfx_rep::to_double() const 722{ 723 scfx_ieee_double id; 724 725 // handle special cases 726 if (is_nan()) { 727 id.set_nan(); 728 return id; 729 } 730 731 if (is_inf()) { 732 id.set_inf(); 733 id.negative(m_sign < 0); 734 return id; 735 } 736 737 if (is_zero()) { 738 id = 0.; 739 id.negative(m_sign < 0); 740 return id; 741 } 742 743 int msb = scfx_find_msb(m_mant[m_msw]); 744 745 int exp = (m_msw - m_wp) * bits_in_word + msb; 746 747 if (exp > SCFX_IEEE_DOUBLE_E_MAX) { 748 id.set_inf(); 749 id.negative(m_sign < 0); 750 return id; 751 } 752 753 if (exp < SCFX_IEEE_DOUBLE_E_MIN - 754 static_cast<int>(SCFX_IEEE_DOUBLE_M_SIZE)) 755 { 756 id = 0.; 757 return id; 758 } 759 760 int shift = mantissa0_size - msb; 761 762 unsigned int m0; 763 unsigned int m1 = 0; 764 unsigned int guard = 0; 765 766 if (shift == 0) { 767 m0 = m_mant[m_msw] & ~(1 << mantissa0_size); 768 if (m_msw > m_lsw) { 769 m1 = m_mant[m_msw - 1]; 770 if (m_msw - 1 > m_lsw) 771 guard = m_mant[m_msw - 2] >> (bits_in_word - 1); 772 } 773 } else if (shift < 0) { 774 m0 = (m_mant[m_msw] >> -shift) & ~(1 << mantissa0_size); 775 m1 = m_mant[m_msw] << (bits_in_word + shift); 776 if (m_msw > m_lsw) { 777 m1 |= m_mant[m_msw - 1] >> -shift; 778 guard = (m_mant[m_msw - 1] >> (-shift - 1)) & 1; 779 } 780 } else { 781 m0 = (m_mant[m_msw] << shift) & ~(1 << mantissa0_size); 782 if (m_msw > m_lsw) { 783 m0 |= m_mant[m_msw - 1] >> (bits_in_word - shift); 784 m1 = m_mant[m_msw - 1] << shift; 785 if (m_msw - 1 > m_lsw) { 786 m1 |= m_mant[m_msw - 2] >> (bits_in_word - shift); 787 guard = (m_mant[m_msw - 2] >> (bits_in_word - shift - 1)) & 1; 788 } 789 } 790 } 791 792 if (exp < SCFX_IEEE_DOUBLE_E_MIN) { 793 m0 |= (1 << mantissa0_size); 794 795 int subnormal_shift = SCFX_IEEE_DOUBLE_E_MIN - exp; 796 797 if (subnormal_shift < bits_in_word) { 798 m1 = m1 >> subnormal_shift | 799 m0 << (bits_in_word - subnormal_shift); 800 m0 = m0 >> subnormal_shift; 801 } else { 802 m1 = m0 >> (subnormal_shift - bits_in_word); 803 m0 = 0; 804 } 805 806 guard = 0; 807 808 exp = SCFX_IEEE_DOUBLE_E_MIN - 1; 809 } 810 811 id.mantissa0(m0); 812 id.mantissa1(m1); 813 id.exponent(exp); 814 id.negative(m_sign < 0); 815 816 double result = id; 817 818 if (guard != 0) 819 result += m_sign * scfx_pow2(exp - SCFX_IEEE_DOUBLE_M_SIZE); 820 821 return result; 822} 823 824 825// ---------------------------------------------------------------------------- 826// METHOD : to_uint64 827// 828// Convert from scfx_rep to uint64. 829// Truncates towards 0 _then_ wraps; infinities and NaN go to zero. 830// ---------------------------------------------------------------------------- 831 832uint64 833scfx_rep::to_uint64() const 834{ 835 if (!is_normal() || is_zero()) { 836 return 0; 837 } 838 839 uint64 result = 0; 840 int shift = 0; 841 int idx = m_wp; 842 843 // Ignore bits off the top; they modulo out. 844 // Ignore bits off the bottom; we're truncating. 845 while (shift < 64 && m_msw >= idx && idx >= m_lsw) { 846 result += static_cast<uint64>(m_mant[idx]) << shift; 847 shift += bits_in_word; 848 idx += 1; 849 } 850 851 return m_sign > 0 ? result : -result; 852} 853 854 855// ---------------------------------------------------------------------------- 856// METHOD : to_string 857// 858// Convert from scfx_rep to character string. 859// ---------------------------------------------------------------------------- 860 861void 862print_dec(scfx_string &s, const scfx_rep &num, int w_prefix, sc_fmt fmt) 863{ 864 if (num.is_neg()) 865 s += '-'; 866 867 if (w_prefix == 1) { 868 scfx_print_prefix(s, SC_DEC); 869 } 870 871 if (num.is_zero()) { 872 s += '0'; 873 return; 874 } 875 876 // split 'num' into its integer and fractional part 877 scfx_rep int_part = num; 878 scfx_rep frac_part = num; 879 880 int i; 881 882 for (i = int_part.m_lsw; i <= int_part.m_msw && i < int_part.m_wp; i++) 883 int_part.m_mant[i] = 0; 884 int_part.find_sw(); 885 if (int_part.m_wp < int_part.m_lsw) 886 int_part.resize_to(int_part.size() - int_part.m_wp, -1); 887 888 for (i = frac_part.m_msw; 889 i >= frac_part.m_lsw && i >= frac_part.m_wp; i--) 890 frac_part.m_mant[i] = 0; 891 frac_part.find_sw(); 892 if (frac_part.m_msw == frac_part.size() - 1) 893 frac_part.resize_to(frac_part.size() + 1, 1); 894 895 // print integer part 896 int int_digits = 0; 897 int int_zeros = 0; 898 899 if (!int_part.is_zero()) { 900 double int_wl = (int_part.m_msw - int_part.m_wp) * bits_in_word + 901 scfx_find_msb(int_part.m_mant[int_part.m_msw]) + 1; 902 int_digits = (int)std::ceil(int_wl * std::log10(2.)); 903 904 int len = s.length(); 905 s.append(int_digits); 906 907 bool zero_digits = (frac_part.is_zero() && fmt != SC_F); 908 909 for (i = int_digits + len - 1; i >= len; i--) { 910 unsigned int remainder = int_part.divide_by_ten(); 911 s[i] = static_cast<char>('0' + remainder); 912 913 if (zero_digits) { 914 if (remainder == 0) 915 int_zeros++; 916 else 917 zero_digits = false; 918 } 919 } 920 921 // discard trailing zeros from int_part 922 s.discard(int_zeros); 923 924 if (s[len] == '0') { 925 // int_digits was overestimated by one 926 s.remove(len); 927 --int_digits; 928 } 929 } 930 931 // print fractional part 932 int frac_digits = 0; 933 int frac_zeros = 0; 934 935 if (!frac_part.is_zero()) { 936 s += '.'; 937 938 bool zero_digits = (int_digits == 0 && fmt != SC_F); 939 940 double frac_wl = (frac_part.m_wp - frac_part.m_msw) * bits_in_word - 941 scfx_find_msb(frac_part.m_mant[frac_part.m_msw]) - 1; 942 frac_zeros = (int)std::floor(frac_wl * std::log10(2.)); 943 944 scfx_rep temp; 945 sc_dt::multiply(temp, frac_part, pow10_fx(frac_zeros)); 946 frac_part = temp; 947 if (frac_part.m_msw == frac_part.size() - 1) 948 frac_part.resize_to(frac_part.size() + 1, 1); 949 950 frac_digits = frac_zeros; 951 if (!zero_digits) { 952 for (i = 0; i < frac_zeros; i++) 953 s += '0'; 954 frac_zeros = 0; 955 } 956 957 while (!frac_part.is_zero()) { 958 frac_part.multiply_by_ten(); 959 int n = frac_part.m_mant[frac_part.m_msw + 1]; 960 961 if (zero_digits) { 962 if (n == 0) 963 frac_zeros++; 964 else 965 zero_digits = false; 966 } 967 968 if (! zero_digits) 969 s += static_cast<char>('0' + n); 970 971 frac_part.m_mant[frac_part.m_msw + 1] = 0; 972 frac_digits++; 973 } 974 } 975 976 // print exponent 977 if (fmt != SC_F) { 978 if (frac_digits == 0) 979 scfx_print_exp(s, int_zeros); 980 else if (int_digits == 0) 981 scfx_print_exp(s, -frac_zeros); 982 } 983} 984 985void 986print_other(scfx_string &s, const scfx_rep &a, sc_numrep numrep, int w_prefix, 987 sc_fmt fmt, const scfx_params *params) 988{ 989 scfx_rep b = a; 990 991 sc_numrep numrep2 = numrep; 992 993 bool numrep_is_sm = (numrep == SC_BIN_SM || 994 numrep == SC_OCT_SM || 995 numrep == SC_HEX_SM); 996 997 if (numrep_is_sm) { 998 if (b.is_neg()) { 999 s += '-'; 1000 b = *neg_scfx_rep(a); 1001 } 1002 switch (numrep) { 1003 case SC_BIN_SM: 1004 numrep2 = SC_BIN_US; 1005 break; 1006 case SC_OCT_SM: 1007 numrep2 = SC_OCT_US; 1008 break; 1009 case SC_HEX_SM: 1010 numrep2 = SC_HEX_US; 1011 break; 1012 default: 1013 ; 1014 } 1015 } 1016 1017 if (w_prefix != 0) { 1018 scfx_print_prefix(s, numrep); 1019 } 1020 1021 numrep = numrep2; 1022 1023 int msb, lsb; 1024 1025 if (params != 0) { 1026 msb = params->iwl() - 1; 1027 lsb = params->iwl() - params->wl(); 1028 1029 if (params->enc() == SC_TC_ && 1030 (numrep == SC_BIN_US || 1031 numrep == SC_OCT_US || 1032 numrep == SC_HEX_US) && 1033 !numrep_is_sm && 1034 params->wl() > 1) { 1035 --msb; 1036 } else if (params->enc() == SC_US_ && 1037 (numrep == SC_BIN || 1038 numrep == SC_OCT || 1039 numrep == SC_HEX || 1040 numrep == SC_CSD)) { 1041 ++msb; 1042 } 1043 } else { 1044 if (b.is_zero()) { 1045 msb = 0; 1046 lsb = 0; 1047 } else { 1048 msb = (b.m_msw - b.m_wp) * bits_in_word 1049 + scfx_find_msb(b.m_mant[ b.m_msw ]) + 1; 1050 while (b.get_bit(msb) == b.get_bit(msb - 1)) 1051 --msb; 1052 1053 if (numrep == SC_BIN_US || 1054 numrep == SC_OCT_US || 1055 numrep == SC_HEX_US) { 1056 --msb; 1057 } 1058 1059 lsb = (b.m_lsw - b.m_wp) * bits_in_word + 1060 scfx_find_lsb(b.m_mant[b.m_lsw]); 1061 1062 } 1063 } 1064 1065 int step; 1066 1067 switch (numrep) { 1068 case SC_BIN: 1069 case SC_BIN_US: 1070 case SC_CSD: 1071 step = 1; 1072 break; 1073 case SC_OCT: 1074 case SC_OCT_US: 1075 step = 3; 1076 break; 1077 case SC_HEX: 1078 case SC_HEX_US: 1079 step = 4; 1080 break; 1081 default: 1082 SC_REPORT_FATAL(sc_core::SC_ID_ASSERTION_FAILED_, 1083 "unexpected sc_numrep"); 1084 sc_core::sc_abort(); 1085 } 1086 1087 msb = (int)std::ceil(double(msb + 1) / step) * step - 1; 1088 1089 lsb = (int)std::floor(double(lsb) / step) * step; 1090 1091 if (msb < 0) { 1092 s += '.'; 1093 if (fmt == SC_F) { 1094 int sign = (b.is_neg()) ? (1 << step) - 1 : 0; 1095 for (int i = (msb + 1) / step; i < 0; i++) { 1096 if (sign < 10) 1097 s += static_cast<char>(sign + '0'); 1098 else 1099 s += static_cast<char>(sign + 'a' - 10); 1100 } 1101 } 1102 } 1103 1104 int i = msb; 1105 while (i >= lsb) { 1106 int value = 0; 1107 for (int j = step - 1; j >= 0; --j) { 1108 value += static_cast<int>(b.get_bit(i)) << j; 1109 --i; 1110 } 1111 if (value < 10) 1112 s += static_cast<char>(value + '0'); 1113 else 1114 s += static_cast<char>(value + 'a' - 10); 1115 if (i == -1) 1116 s += '.'; 1117 } 1118 1119 if (lsb > 0 && fmt == SC_F) { 1120 for (int i = lsb / step; i > 0; i--) 1121 s += '0'; 1122 } 1123 1124 if (s[s.length() - 1] == '.') 1125 s.discard(1); 1126 1127 if (fmt != SC_F) { 1128 if (msb < 0) 1129 scfx_print_exp(s, (msb + 1) / step); 1130 else if (lsb > 0) 1131 scfx_print_exp(s, lsb / step); 1132 } 1133 1134 if (numrep == SC_CSD) 1135 scfx_tc2csd(s, w_prefix); 1136} 1137 1138const char * 1139scfx_rep::to_string(sc_numrep numrep, int w_prefix, 1140 sc_fmt fmt, const scfx_params *params) const 1141{ 1142 static scfx_string s; 1143 1144 s.clear(); 1145 1146 if (is_nan()) { 1147 scfx_print_nan(s); 1148 } else if (is_inf()) { 1149 scfx_print_inf(s, is_neg()); 1150 } else if (is_neg() && !is_zero() && 1151 (numrep == SC_BIN_US || 1152 numrep == SC_OCT_US || 1153 numrep == SC_HEX_US)) { 1154 s += "negative"; 1155 } else if (numrep == SC_DEC || numrep == SC_NOBASE) { 1156 sc_dt::print_dec(s, *this, w_prefix, fmt); 1157 } else { 1158 sc_dt::print_other(s, *this, numrep, w_prefix, fmt, params); 1159 } 1160 1161 return s; 1162} 1163 1164 1165// ---------------------------------------------------------------------------- 1166// ADD 1167// 1168// add two mantissas of the same size 1169// result has the same size 1170// returns carry of operation 1171// ---------------------------------------------------------------------------- 1172 1173static inline int 1174add_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b) 1175{ 1176 unsigned int carry = 0; 1177 1178 int index = 0; 1179 1180 do { 1181 word x = a[index]; 1182 word y = b[index]; 1183 1184 y += carry; 1185 carry = y < carry; 1186 y += x; 1187 carry += y < x; 1188 result[index] = y; 1189 } while (++index < size); 1190 1191 return (carry ? 1 : 0); 1192} 1193 1194static inline int 1195sub_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b) 1196{ 1197 unsigned carry = 0; 1198 1199 int index = 0; 1200 1201 do { 1202 word x = a[index]; 1203 word y = b[index]; 1204 1205 y += carry; 1206 carry = y < carry; 1207 y = x - y; 1208 carry += y > x; 1209 result[index] = y; 1210 } while (++index < size); 1211 1212 return (carry ? 1 : 0); 1213} 1214 1215scfx_rep * 1216add_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl) 1217{ 1218 scfx_rep &result = *new scfx_rep; 1219 1220 // 1221 // check for special cases 1222 // 1223 if (lhs.is_nan() || rhs.is_nan() || 1224 (lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign)) { 1225 result.set_nan(); 1226 return &result; 1227 } 1228 1229 if (lhs.is_inf()) { 1230 result.set_inf(lhs.m_sign); 1231 return &result; 1232 } 1233 1234 if (rhs.is_inf()) { 1235 result.set_inf(rhs.m_sign); 1236 return &result; 1237 } 1238 1239 // 1240 // align operands if needed 1241 // 1242 scfx_mant_ref lhs_mant; 1243 scfx_mant_ref rhs_mant; 1244 1245 int len_mant = lhs.size(); 1246 int new_wp = lhs.m_wp; 1247 1248 align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant); 1249 1250 // 1251 // size the result mantissa 1252 // 1253 result.resize_to(len_mant); 1254 result.m_wp = new_wp; 1255 1256 // 1257 // do it 1258 // 1259 if (lhs.m_sign == rhs.m_sign) { 1260 add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant); 1261 result.m_sign = lhs.m_sign; 1262 } else { 1263 int cmp = compare_abs(lhs, rhs); 1264 1265 if (cmp == 1) { 1266 sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant); 1267 result.m_sign = lhs.m_sign; 1268 } else if (cmp == -1) { 1269 sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant); 1270 result.m_sign = rhs.m_sign; 1271 } else { 1272 result.m_mant.clear(); 1273 result.m_sign = 1; 1274 } 1275 } 1276 1277 result.find_sw(); 1278 result.round(max_wl); 1279 1280 return &result; 1281} 1282 1283 1284// ---------------------------------------------------------------------------- 1285// SUB 1286// 1287// sub two word's of the same size 1288// result has the same size 1289// returns carry of operation 1290// ---------------------------------------------------------------------------- 1291 1292static inline int 1293sub_with_index(scfx_mant &a, int a_msw, int /*a_lsw*/, 1294 const scfx_mant &b, int b_msw, int b_lsw) 1295{ 1296 unsigned carry = 0; 1297 1298 int size = b_msw - b_lsw; 1299 int a_index = a_msw - size; 1300 int b_index = b_msw - size; 1301 1302 do { 1303 word x = a[a_index]; 1304 word y = b[b_index]; 1305 1306 y += carry; 1307 carry = y < carry; 1308 y = x - y; 1309 carry += y > x; 1310 a[a_index] = y; 1311 1312 a_index++; 1313 b_index++; 1314 } while (size--); 1315 1316 if (carry) { 1317 // special case: a[a_msw + 1] == 1 1318 a[a_msw + 1] = 0; 1319 } 1320 1321 return (carry ? 1 : 0); 1322} 1323 1324scfx_rep * 1325sub_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl) 1326{ 1327 scfx_rep &result = *new scfx_rep; 1328 1329 // 1330 // check for special cases 1331 // 1332 if (lhs.is_nan() || rhs.is_nan() || 1333 (lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign)) { 1334 result.set_nan(); 1335 return &result; 1336 } 1337 1338 if (lhs.is_inf()) { 1339 result.set_inf(lhs.m_sign); 1340 return &result; 1341 } 1342 1343 if (rhs.is_inf()) { 1344 result.set_inf(-1 * rhs.m_sign); 1345 return &result; 1346 } 1347 1348 // 1349 // align operands if needed 1350 // 1351 scfx_mant_ref lhs_mant; 1352 scfx_mant_ref rhs_mant; 1353 1354 int len_mant = lhs.size(); 1355 int new_wp = lhs.m_wp; 1356 1357 align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant); 1358 1359 // 1360 // size the result mantissa 1361 // 1362 result.resize_to(len_mant); 1363 result.m_wp = new_wp; 1364 1365 // 1366 // do it 1367 // 1368 if (lhs.m_sign != rhs.m_sign) { 1369 add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant); 1370 result.m_sign = lhs.m_sign; 1371 } else { 1372 int cmp = compare_abs(lhs, rhs); 1373 1374 if (cmp == 1) { 1375 sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant); 1376 result.m_sign = lhs.m_sign; 1377 } else if (cmp == -1) { 1378 sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant); 1379 result.m_sign = -rhs.m_sign; 1380 } else { 1381 result.m_mant.clear(); 1382 result.m_sign = 1; 1383 } 1384 } 1385 1386 result.find_sw(); 1387 result.round(max_wl); 1388 1389 return &result; 1390} 1391 1392 1393// ---------------------------------------------------------------------------- 1394// MUL 1395// ---------------------------------------------------------------------------- 1396 1397union word_short 1398{ 1399 word l; 1400 struct 1401 { 1402#if defined(SC_BOOST_BIG_ENDIAN) 1403 half_word u; 1404 half_word l; 1405#elif defined(SC_BOOST_LITTLE_ENDIAN) 1406 half_word l; 1407 half_word u; 1408#endif 1409 } s; 1410}; 1411 1412#if defined(SC_BOOST_BIG_ENDIAN) 1413static const int half_word_incr = -1; 1414#elif defined(SC_BOOST_LITTLE_ENDIAN) 1415static const int half_word_incr = 1; 1416#endif 1417 1418void 1419multiply(scfx_rep &result, const scfx_rep &lhs, const scfx_rep &rhs, 1420 int max_wl) 1421{ 1422 // 1423 // check for special cases 1424 // 1425 if (lhs.is_nan() || rhs.is_nan() || 1426 (lhs.is_inf() && rhs.is_zero()) || 1427 (lhs.is_zero() && rhs.is_inf())) { 1428 result.set_nan(); 1429 return; 1430 } 1431 1432 if (lhs.is_inf() || rhs.is_inf()) { 1433 result.set_inf(lhs.m_sign * rhs.m_sign); 1434 return; 1435 } 1436 1437 if (lhs.is_zero() || rhs.is_zero()) { 1438 result.set_zero(lhs.m_sign * rhs.m_sign); 1439 return; 1440 } 1441 1442 // 1443 // do it 1444 // 1445 int len_lhs = lhs.m_msw - lhs.m_lsw + 1; 1446 int len_rhs = rhs.m_msw - rhs.m_lsw + 1; 1447 1448 int new_size = sc_max(min_mant, len_lhs + len_rhs); 1449 int new_wp = (lhs.m_wp - lhs.m_lsw) + (rhs.m_wp - rhs.m_lsw); 1450 int new_sign = lhs.m_sign * rhs.m_sign; 1451 1452 result.resize_to(new_size); 1453 result.m_mant.clear(); 1454 result.m_wp = new_wp; 1455 result.m_sign = new_sign; 1456 result.m_state = scfx_rep::normal; 1457 1458 half_word *s1 = lhs.m_mant.half_addr(lhs.m_lsw); 1459 half_word *s2 = rhs.m_mant.half_addr(rhs.m_lsw); 1460 1461 half_word *t = result.m_mant.half_addr(); 1462 1463 len_lhs <<= 1; 1464 len_rhs <<= 1; 1465 1466 int i1, i2; 1467 1468 for (i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr) { 1469 word_short ls; 1470 ls.l = 0; 1471 1472 half_word v1 = s1[i1]; 1473 1474 for (i2 = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr) { 1475 ls.l += v1 * s2[i2]; 1476 ls.s.l = ls.s.u + ((t[i2] += ls.s.l) < ls.s.l); 1477 ls.s.u = 0; 1478 } 1479 1480 t[i2] = ls.s.l; 1481 t += half_word_incr; 1482 } 1483 1484 result.find_sw(); 1485 result.round(max_wl); 1486} 1487 1488 1489// ---------------------------------------------------------------------------- 1490// DIV 1491// ---------------------------------------------------------------------------- 1492 1493scfx_rep * 1494div_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int div_wl) 1495{ 1496 scfx_rep &result = *new scfx_rep; 1497 1498 // 1499 // check for special cases 1500 // 1501 if (lhs.is_nan() || rhs.is_nan() || (lhs.is_inf() && rhs.is_inf()) || 1502 (lhs.is_zero() && rhs.is_zero())) { 1503 result.set_nan(); 1504 return &result; 1505 } 1506 1507 if (lhs.is_inf() || rhs.is_zero()) { 1508 result.set_inf(lhs.m_sign * rhs.m_sign); 1509 return &result; 1510 } 1511 1512 if (lhs.is_zero() || rhs.is_inf()) { 1513 result.set_zero(lhs.m_sign * rhs.m_sign); 1514 return &result; 1515 } 1516 1517 // 1518 // do it 1519 // 1520 1521 // compute one bit more for rounding 1522 div_wl++; 1523 1524 result.resize_to(sc_max(n_word(div_wl) + 1, min_mant)); 1525 result.m_mant.clear(); 1526 result.m_sign = lhs.m_sign * rhs.m_sign; 1527 1528 int msb_lhs = scfx_find_msb(lhs.m_mant[lhs.m_msw]) + 1529 (lhs.m_msw - lhs.m_wp) * bits_in_word; 1530 int msb_rhs = scfx_find_msb(rhs.m_mant[rhs.m_msw]) + 1531 (rhs.m_msw - rhs.m_wp) * bits_in_word; 1532 1533 int msb_res = msb_lhs - msb_rhs; 1534 int to_shift = -msb_res % bits_in_word; 1535 int result_index; 1536 1537 int c = (msb_res % bits_in_word >= 0) ? 1 : 0; 1538 1539 result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word; 1540 result.m_wp = (result.size() - c) - msb_res / bits_in_word; 1541 1542 scfx_rep remainder = lhs; 1543 1544 // align msb from remainder to msb from rhs 1545 remainder.lshift(to_shift); 1546 1547 // make sure msw(remainder) < size - 1 1548 if (remainder.m_msw == remainder.size() - 1) 1549 remainder.resize_to(remainder.size() + 1, 1); 1550 1551 // make sure msw(remainder) >= msw(rhs)! 1552 int msw_diff = rhs.m_msw - remainder.m_msw; 1553 if (msw_diff > 0) 1554 remainder.resize_to(remainder.size() + msw_diff, -1); 1555 1556 int counter; 1557 1558 for (counter = div_wl; counter && !remainder.is_zero(); counter--) { 1559 if (compare_msw_ff(rhs, remainder) <= 0) { 1560 result.set_bin(result_index); 1561 sub_with_index(remainder.m_mant, remainder.m_msw, remainder.m_lsw, 1562 rhs.m_mant, rhs.m_msw, rhs.m_lsw); 1563 } 1564 result_index--; 1565 remainder.shift_left(1); 1566 remainder.m_lsw = remainder.find_lsw(); 1567 } 1568 1569 // perform convergent rounding, if needed 1570 if (counter == 0) { 1571 int index = result_index + 1 - result.m_wp * bits_in_word; 1572 1573 scfx_index x = result.calc_indices(index); 1574 scfx_index x1 = result.calc_indices(index + 1); 1575 1576 if (result.o_bit_at(x) && result.o_bit_at(x1)) 1577 result.q_incr(x); 1578 1579 result.m_r_flag = true; 1580 } 1581 1582 result.find_sw(); 1583 1584 return &result; 1585} 1586 1587// ---------------------------------------------------------------------------- 1588// destructive shift mantissa to the left 1589// ---------------------------------------------------------------------------- 1590 1591void 1592scfx_rep::lshift(int n) 1593{ 1594 if (n == 0) 1595 return; 1596 1597 if (n < 0) { 1598 rshift(-n); 1599 return; 1600 } 1601 1602 if (is_normal()) { 1603 int shift_bits = n % bits_in_word; 1604 int shift_words = n / bits_in_word; 1605 1606 // resize if needed 1607 if (m_msw == size() - 1 && 1608 scfx_find_msb(m_mant[m_msw]) >= bits_in_word - shift_bits) 1609 resize_to(size() + 1, 1); 1610 1611 // do it 1612 m_wp -= shift_words; 1613 shift_left(shift_bits); 1614 find_sw(); 1615 } 1616} 1617 1618// ---------------------------------------------------------------------------- 1619// destructive shift mantissa to the right 1620// ---------------------------------------------------------------------------- 1621 1622void 1623scfx_rep::rshift(int n) 1624{ 1625 if (n == 0) 1626 return; 1627 1628 if (n < 0) { 1629 lshift(-n); 1630 return; 1631 } 1632 1633 if (is_normal()) { 1634 int shift_bits = n % bits_in_word; 1635 int shift_words = n / bits_in_word; 1636 1637 // resize if needed 1638 if (m_lsw == 0 && scfx_find_lsb(m_mant[m_lsw]) < shift_bits) 1639 resize_to(size() + 1, -1); 1640 1641 // do it 1642 m_wp += shift_words; 1643 shift_right(shift_bits); 1644 find_sw(); 1645 } 1646} 1647 1648 1649// ---------------------------------------------------------------------------- 1650// FRIEND FUNCTION : compare_abs 1651// 1652// Compares the absolute values of two scfx_reps, excluding the special cases. 1653// ---------------------------------------------------------------------------- 1654 1655int 1656compare_abs(const scfx_rep &a, const scfx_rep &b) 1657{ 1658 // check for zero 1659 word a_word = a.m_mant[a.m_msw]; 1660 word b_word = b.m_mant[b.m_msw]; 1661 1662 if (a_word == 0 || b_word == 0) { 1663 if (a_word != 0) 1664 return 1; 1665 if (b_word != 0) 1666 return -1; 1667 return 0; 1668 } 1669 1670 // compare msw index 1671 int a_msw = a.m_msw - a.m_wp; 1672 int b_msw = b.m_msw - b.m_wp; 1673 1674 if (a_msw > b_msw) 1675 return 1; 1676 1677 if (a_msw < b_msw) 1678 return -1; 1679 1680 // compare content 1681 int a_i = a.m_msw; 1682 int b_i = b.m_msw; 1683 1684 while (a_i >= a.m_lsw && b_i >= b.m_lsw) { 1685 a_word = a.m_mant[a_i]; 1686 b_word = b.m_mant[b_i]; 1687 if (a_word > b_word) 1688 return 1; 1689 if (a_word < b_word) 1690 return -1; 1691 --a_i; 1692 --b_i; 1693 } 1694 1695 bool a_zero = true; 1696 while (a_i >= a.m_lsw) { 1697 a_zero = a_zero && (a.m_mant[a_i] == 0); 1698 --a_i; 1699 } 1700 1701 bool b_zero = true; 1702 while (b_i >= b.m_lsw) { 1703 b_zero = b_zero && (b.m_mant[b_i] == 0); 1704 --b_i; 1705 } 1706 1707 // assertion: a_zero || b_zero 1708 1709 if (!a_zero && b_zero) 1710 return 1; 1711 1712 if (a_zero && !b_zero) 1713 return -1; 1714 1715 return 0; 1716} 1717 1718// ---------------------------------------------------------------------------- 1719// FRIEND FUNCTION : cmp_scfx_rep 1720// 1721// Compares the values of two scfx_reps, including the special cases. 1722// ---------------------------------------------------------------------------- 1723 1724int 1725cmp_scfx_rep(const scfx_rep &a, const scfx_rep &b) 1726{ 1727 // handle special cases 1728 1729 if (a.is_nan() || b.is_nan()) { 1730 return 2; 1731 } 1732 1733 if (a.is_inf() || b.is_inf()) { 1734 if (a.is_inf()) { 1735 if (!a.is_neg()) { 1736 if (b.is_inf() && !b.is_neg()) { 1737 return 0; 1738 } else { 1739 return 1; 1740 } 1741 } else { 1742 if (b.is_inf() && b.is_neg()) { 1743 return 0; 1744 } else { 1745 return -1; 1746 } 1747 } 1748 } 1749 if (b.is_inf()) { 1750 if (!b.is_neg()) { 1751 return -1; 1752 } else { 1753 return 1; 1754 } 1755 } 1756 } 1757 1758 if (a.is_zero() && b.is_zero()) { 1759 return 0; 1760 } 1761 1762 // compare sign 1763 if (a.m_sign != b.m_sign) { 1764 return a.m_sign; 1765 } 1766 1767 return (a.m_sign * compare_abs(a, b)); 1768} 1769 1770 1771// ---------------------------------------------------------------------------- 1772// PRIVATE METHOD : quantization 1773// 1774// Performs destructive quantization. 1775// ---------------------------------------------------------------------------- 1776 1777void 1778scfx_rep::quantization(const scfx_params ¶ms, bool &q_flag) 1779{ 1780 scfx_index x = calc_indices(params.iwl() - params.wl()); 1781 1782 if (x.wi() < 0) 1783 return; 1784 1785 if (x.wi() >= size()) 1786 resize_to(x.wi() + 1, 1); 1787 1788 bool qb = q_bit(x); 1789 bool qz = q_zero(x); 1790 1791 q_flag = (qb || ! qz); 1792 1793 if (q_flag) { 1794 switch (params.q_mode()) { 1795 case SC_TRN: // truncation 1796 { 1797 if (is_neg()) 1798 q_incr(x); 1799 break; 1800 } 1801 case SC_RND: // rounding to plus infinity 1802 { 1803 if (!is_neg()) { 1804 if (qb) 1805 q_incr(x); 1806 } else { 1807 if (qb && !qz) 1808 q_incr(x); 1809 } 1810 break; 1811 } 1812 case SC_TRN_ZERO: // truncation to zero 1813 { 1814 break; 1815 } 1816 case SC_RND_INF: // rounding to infinity 1817 { 1818 if (qb) 1819 q_incr(x); 1820 break; 1821 } 1822 case SC_RND_CONV: // convergent rounding 1823 { 1824 if ((qb && !qz) || (qb && qz && q_odd(x))) 1825 q_incr(x); 1826 break; 1827 } 1828 case SC_RND_ZERO: // rounding to zero 1829 { 1830 if (qb && !qz) 1831 q_incr(x); 1832 break; 1833 } 1834 case SC_RND_MIN_INF: // rounding to minus infinity 1835 { 1836 if (!is_neg()) { 1837 if (qb && !qz) 1838 q_incr(x); 1839 } else { 1840 if (qb) 1841 q_incr(x); 1842 } 1843 break; 1844 } 1845 default: 1846 ; 1847 } 1848 q_clear(x); 1849 1850 find_sw(); 1851 } 1852} 1853 1854 1855// ---------------------------------------------------------------------------- 1856// PRIVATE METHOD : overflow 1857// 1858// Performs destructive overflow handling. 1859// ---------------------------------------------------------------------------- 1860 1861void 1862scfx_rep::overflow(const scfx_params ¶ms, bool &o_flag) 1863{ 1864 scfx_index x = calc_indices(params.iwl() - 1); 1865 1866 if (x.wi() >= size()) 1867 resize_to(x.wi() + 1, 1); 1868 1869 if (x.wi() < 0) { 1870 resize_to(size() - x.wi(), -1); 1871 x.wi(0); 1872 } 1873 1874 bool zero_left = o_zero_left(x); 1875 bool bit_at = o_bit_at(x); 1876 bool zero_right = o_zero_right(x); 1877 1878 bool under = false; 1879 bool over = false; 1880 1881 sc_enc enc = params.enc(); 1882 1883 if (enc == SC_TC_) { 1884 if (is_neg()) { 1885 if (params.o_mode() == SC_SAT_SYM) 1886 under = (!zero_left || bit_at); 1887 else 1888 under = (!zero_left || (zero_left && bit_at && ! zero_right)); 1889 } else { 1890 over = (! zero_left || bit_at); 1891 } 1892 } else { 1893 if (is_neg()) 1894 under = (!is_zero()); 1895 else 1896 over = (!zero_left); 1897 } 1898 1899 o_flag = (under || over); 1900 1901 if (o_flag) { 1902 scfx_index x2 = calc_indices(params.iwl() - params.wl()); 1903 1904 if (x2.wi() < 0) { 1905 resize_to(size() - x2.wi(), -1); 1906 x.wi(x.wi() - x2.wi()); 1907 x2.wi(0); 1908 } 1909 1910 switch (params.o_mode()) { 1911 case SC_WRAP: // wrap-around 1912 { 1913 int n_bits = params.n_bits(); 1914 1915 if (n_bits == 0) { 1916 // wrap-around all 'wl' bits 1917 toggle_tc(); 1918 o_extend(x, enc); 1919 toggle_tc(); 1920 } else if (n_bits < params.wl()) { 1921 scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits); 1922 1923 // wrap-around least significant 'wl - n_bits' bits; 1924 // saturate most significant 'n_bits' bits 1925 toggle_tc(); 1926 o_set(x, x3, enc, under); 1927 o_extend(x, enc); 1928 toggle_tc(); 1929 } else { 1930 // saturate all 'wl' bits 1931 if (under) 1932 o_set_low(x, enc); 1933 else 1934 o_set_high(x, x2, enc); 1935 } 1936 break; 1937 } 1938 case SC_SAT: // saturation 1939 { 1940 if (under) 1941 o_set_low(x, enc); 1942 else 1943 o_set_high(x, x2, enc); 1944 break; 1945 } 1946 case SC_SAT_SYM: // symmetrical saturation 1947 { 1948 if (under) { 1949 if (enc == SC_TC_) 1950 o_set_high(x, x2, SC_TC_, -1); 1951 else 1952 o_set_low(x, SC_US_); 1953 } else { 1954 o_set_high(x, x2, enc); 1955 } 1956 break; 1957 } 1958 case SC_SAT_ZERO: // saturation to zero 1959 { 1960 set_zero(); 1961 break; 1962 } 1963 case SC_WRAP_SM: // sign magnitude wrap-around 1964 { 1965 SC_ERROR_IF_(enc == SC_US_,
| 70#include "systemc/ext/dt/fx/scfx_ieee.hh" 71#include "systemc/ext/dt/fx/scfx_pow10.hh" 72#include "systemc/ext/dt/fx/scfx_rep.hh" 73#include "systemc/ext/dt/fx/scfx_utils.hh" 74#include "systemc/ext/utils/endian.hh" 75#include "systemc/ext/utils/messages.hh" 76 77namespace sc_dt 78{ 79 80// ---------------------------------------------------------------------------- 81// some utilities 82// ---------------------------------------------------------------------------- 83 84static scfx_pow10 pow10_fx; 85 86static const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int; 87 88static inline int 89n_word(int x) 90{ 91 return (x + bits_in_word - 1) / bits_in_word; 92} 93 94 95// ---------------------------------------------------------------------------- 96// CONSTRUCTORS 97// ---------------------------------------------------------------------------- 98 99scfx_rep::scfx_rep() : 100 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 101 m_r_flag(false) 102{ 103 set_zero(); 104} 105 106scfx_rep::scfx_rep(int a) : m_mant(min_mant), m_wp(), m_sign(), m_state(), 107 m_msw(), m_lsw(), m_r_flag(false) 108{ 109 if (a != 0) { 110 m_mant.clear(); 111 m_wp = m_msw = m_lsw = 2; 112 m_state = normal; 113 if (a > 0) { 114 m_mant[2] = a; 115 m_sign = 1; 116 } else { 117 m_mant[2] = -a; 118 m_sign = -1; 119 } 120 } else { 121 set_zero(); 122 } 123} 124 125scfx_rep::scfx_rep(unsigned int a) : m_mant(min_mant), m_wp(), m_sign(), 126 m_state(), m_msw(), m_lsw(), m_r_flag(false) 127{ 128 if (a != 0) { 129 m_mant.clear(); 130 m_wp = m_msw = m_lsw = 2; 131 m_state = normal; 132 m_mant[2] = a; 133 m_sign = 1; 134 } else { 135 set_zero(); 136 } 137} 138 139scfx_rep::scfx_rep(long a) : 140 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 141 m_r_flag(false) 142{ 143 if (a != 0) { 144 m_mant.clear(); 145 m_state = normal; 146 if (a > 0) { 147 m_sign = 1; 148 } else { 149 a = -a; 150 m_sign = -1; 151 } 152# if SC_LONG_64 153 m_wp = 1; 154 m_mant[1] = static_cast<word>(a); 155 m_mant[2] = static_cast<word>(a >> bits_in_word); 156 find_sw(); 157# else 158 m_wp = 2; 159 m_msw = 2; 160 m_lsw = 2; 161 m_mant[2] = a; 162# endif 163 } else { 164 set_zero(); 165 } 166} 167 168scfx_rep::scfx_rep(unsigned long a) : 169 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 170 m_r_flag(false) 171{ 172 if (a != 0) { 173 m_mant.clear(); 174 m_wp = m_msw = m_lsw = 2; 175 m_state = normal; 176# if SC_LONG_64 177 m_wp = 1; 178 m_mant[1] = static_cast<word>(a); 179 m_mant[2] = static_cast<word>(a >> bits_in_word); 180 find_sw(); 181# else 182 m_wp = 2; 183 m_msw = 2; 184 m_lsw = 2; 185 m_mant[2] = a; 186# endif 187 m_sign = 1; 188 } 189 else 190 set_zero(); 191} 192 193scfx_rep::scfx_rep(double a) : 194 m_mant(min_mant), m_wp(0), m_sign(), m_state(normal), m_msw(0), 195 m_lsw(0), m_r_flag(false) 196{ 197 m_mant.clear(); 198 199 scfx_ieee_double id(a); 200 201 m_sign = id.negative() ? -1 : 1; 202 203 if (id.is_nan()) { 204 m_state = not_a_number; 205 } else if (id.is_inf()) { 206 m_state = infinity; 207 } else if (id.is_subnormal()) { 208 m_mant[0] = id.mantissa1(); 209 m_mant[1] = id.mantissa0(); 210 normalize(id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE); 211 } else if (id.is_normal()) { 212 m_mant[0] = id.mantissa1(); 213 m_mant[1] = id.mantissa0() | (1 << mantissa0_size); 214 normalize(id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE); 215 } 216} 217 218scfx_rep::scfx_rep(int64 a) : 219 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 220 m_r_flag(false) 221{ 222 if (a != 0) { 223 m_mant.clear(); 224 m_wp = 1; 225 m_state = normal; 226 if (a > 0) { 227 m_mant[1] = static_cast<word>(a); 228 m_mant[2] = static_cast<word>(a >> bits_in_word); 229 m_sign = 1; 230 } else { 231 m_mant[1] = static_cast<word>(-a); 232 m_mant[2] = static_cast<word>((-a) >> bits_in_word); 233 m_sign = -1; 234 } 235 find_sw(); 236 } else { 237 set_zero(); 238 } 239} 240 241scfx_rep::scfx_rep(uint64 a) : 242 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 243 m_r_flag(false) 244{ 245 if (a != 0) { 246 m_mant.clear(); 247 m_wp = 1; 248 m_state = normal; 249 m_mant[1] = static_cast<word>(a); 250 m_mant[2] = static_cast<word>(a >> bits_in_word); 251 m_sign = 1; 252 find_sw(); 253 } else { 254 set_zero(); 255 } 256} 257 258scfx_rep::scfx_rep(const sc_signed &a) : 259 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 260 m_r_flag(false) 261{ 262 if (a.iszero()) { 263 set_zero(); 264 } else { 265 int words = n_word(a.length()); 266 if (words > size()) 267 resize_to(words); 268 m_mant.clear(); 269 m_wp = 0; 270 m_state = normal; 271 if (a.sign()) { 272 sc_signed a2 = -a; 273 for (int i = 0; i < a2.length(); ++i) { 274 if (a2[i]) { 275 scfx_index x = calc_indices(i); 276 m_mant[x.wi()] |= 1 << x.bi(); 277 } 278 } 279 m_sign = -1; 280 } else { 281 for (int i = 0; i < a.length(); ++i) { 282 if (a[i]) { 283 scfx_index x = calc_indices(i); 284 m_mant[x.wi()] |= 1 << x.bi(); 285 } 286 } 287 m_sign = 1; 288 } 289 find_sw(); 290 } 291} 292 293scfx_rep::scfx_rep(const sc_unsigned &a) : 294 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(), 295 m_r_flag(false) 296{ 297 if (a.iszero()) { 298 set_zero(); 299 } else { 300 int words = n_word(a.length()); 301 if (words > size()) 302 resize_to(words); 303 m_mant.clear(); 304 m_wp = 0; 305 m_state = normal; 306 for (int i = 0; i < a.length(); ++i) { 307 if (a[i]) { 308 scfx_index x = calc_indices(i); 309 m_mant[x.wi()] |= 1 << x.bi(); 310 } 311 } 312 m_sign = 1; 313 find_sw(); 314 } 315} 316 317// copy constructor 318scfx_rep::scfx_rep(const scfx_rep &a) : 319 m_mant(a.m_mant), m_wp(a.m_wp), m_sign(a.m_sign), m_state(a.m_state), 320 m_msw(a.m_msw), m_lsw(a.m_lsw), m_r_flag(false) 321{} 322 323 324// ---------------------------------------------------------------------------- 325// OPERATORS : new, delete 326// 327// Memory management for class scfx_rep. 328// ---------------------------------------------------------------------------- 329 330union scfx_rep_node 331{ 332 char data[sizeof(scfx_rep)]; 333 scfx_rep_node *next; 334}; 335 336static scfx_rep_node *list = 0; 337 338void * 339scfx_rep::operator new(std::size_t size) 340{ 341 const int ALLOC_SIZE = 1024; 342 343 if (size != sizeof(scfx_rep)) 344 return ::operator new(size); 345 346 if (!list) { 347 list = new scfx_rep_node[ALLOC_SIZE]; 348 for (int i = 0; i < ALLOC_SIZE - 1; i++) 349 list[i].next = list + i + 1; 350 list[ALLOC_SIZE - 1].next = 0; 351 } 352 353 scfx_rep *ptr = reinterpret_cast<scfx_rep *>(list->data); 354 list = list->next; 355 356 return ptr; 357} 358 359void 360scfx_rep::operator delete(void *ptr, std::size_t size) 361{ 362 if (size != sizeof(scfx_rep)) { 363 ::operator delete(ptr); 364 return; 365 } 366 367 scfx_rep_node *node = static_cast<scfx_rep_node *>(ptr); 368 node->next = list; 369 list = node; 370} 371 372 373// ---------------------------------------------------------------------------- 374// METHOD : from_string 375// 376// Convert from character string to sc_fxrep. 377// ---------------------------------------------------------------------------- 378 379#define SCFX_FAIL_IF_(cnd) \ 380{ \ 381 if ((cnd)) { \ 382 m_state = not_a_number; \ 383 m_mant.clear(); /* to avoid Purify UMRs during assignment */ \ 384 return; \ 385 } \ 386} 387 388void 389scfx_rep::from_string(const char *s, int cte_wl) 390{ 391 SCFX_FAIL_IF_(s == 0 || *s == 0); 392 393 scfx_string s2; 394 s2 += s; 395 s2 += '\0'; 396 397 bool sign_char; 398 m_sign = scfx_parse_sign(s, sign_char); 399 400 sc_numrep numrep = scfx_parse_prefix(s); 401 402 int base = 0; 403 404 switch (numrep) { 405 case SC_DEC: 406 { 407 base = 10; 408 if (scfx_is_nan(s)) { // special case: NaN 409 m_state = not_a_number; 410 m_mant.clear(); /* to avoid Purify UMRs during assignment */ 411 return; 412 } 413 if (scfx_is_inf(s)) { // special case: Infinity 414 m_state = infinity; 415 m_mant.clear(); /* to avoid Purify UMRs during assignment */ 416 return; 417 } 418 break; 419 } 420 case SC_BIN: 421 case SC_BIN_US: 422 { 423 SCFX_FAIL_IF_(sign_char); 424 base = 2; 425 break; 426 } 427 428 case SC_BIN_SM: 429 { 430 base = 2; 431 break; 432 } 433 case SC_OCT: 434 case SC_OCT_US: 435 { 436 SCFX_FAIL_IF_(sign_char); 437 base = 8; 438 break; 439 } 440 case SC_OCT_SM: 441 { 442 base = 8; 443 break; 444 } 445 case SC_HEX: 446 case SC_HEX_US: 447 { 448 SCFX_FAIL_IF_(sign_char); 449 base = 16; 450 break; 451 } 452 case SC_HEX_SM: 453 { 454 base = 16; 455 break; 456 } 457 case SC_CSD: 458 { 459 SCFX_FAIL_IF_(sign_char); 460 base = 2; 461 scfx_csd2tc(s2); 462 s = (const char *)s2 + 4; 463 numrep = SC_BIN; 464 break; 465 } 466 default: 467 ; 468 } 469 470 // 471 // find end of mantissa and count the digits and points 472 // 473 474 const char *end = s; 475 bool based_point = false; 476 int int_digits = 0; 477 int frac_digits = 0; 478 479 while (*end) { 480 if (scfx_exp_start(end)) 481 break; 482 483 if (*end == '.') { 484 SCFX_FAIL_IF_(based_point); 485 based_point = true; 486 } else { 487 SCFX_FAIL_IF_(!scfx_is_digit(*end, numrep)); 488 if (based_point) 489 frac_digits++; 490 else 491 int_digits++; 492 } 493 494 ++end; 495 } 496 497 SCFX_FAIL_IF_(int_digits == 0 && frac_digits == 0); 498 499 // [ exponent ] 500 int exponent = 0; 501 502 if (*end) { 503 for (const char *e = end + 2; *e; ++e) 504 SCFX_FAIL_IF_(!scfx_is_digit(*e, SC_DEC)); 505 exponent = std::atoi(end + 1); 506 } 507 508 // 509 // check if the mantissa is negative 510 // 511 bool mant_is_neg = false; 512 switch (numrep) { 513 case SC_BIN: 514 case SC_OCT: 515 case SC_HEX: 516 { 517 const char *p = s; 518 if (*p == '.') 519 ++p; 520 521 mant_is_neg = (scfx_to_digit(* p, numrep) >= (base >> 1)); 522 break; 523 } 524 default: 525 ; 526 } 527 528 // 529 // convert the mantissa 530 // 531 532 switch (base) { 533 case 2: 534 { 535 int bit_offset = exponent % bits_in_word; 536 int word_offset = exponent / bits_in_word; 537 538 int_digits += bit_offset; 539 frac_digits -= bit_offset; 540 541 int words = n_word(int_digits) + n_word(frac_digits); 542 if (words > size()) 543 resize_to(words); 544 m_mant.clear(); 545 546 int j = n_word(frac_digits) * bits_in_word + int_digits - 1; 547 548 for (; s < end; s++) { 549 switch (*s) { 550 case '1': 551 set_bin(j); 552 M5_FALLTHROUGH; 553 case '0': 554 j--; 555 M5_FALLTHROUGH; 556 case '.': 557 break; 558 default: 559 SCFX_FAIL_IF_(true); // should not happen 560 } 561 } 562 563 m_wp = n_word(frac_digits) - word_offset; 564 break; 565 } 566 case 8: 567 { 568 exponent *= 3; 569 int_digits *= 3; 570 frac_digits *= 3; 571 572 int bit_offset = exponent % bits_in_word; 573 int word_offset = exponent / bits_in_word; 574 575 int_digits += bit_offset; 576 frac_digits -= bit_offset; 577 578 int words = n_word(int_digits) + n_word(frac_digits); 579 if (words > size()) 580 resize_to(words); 581 m_mant.clear(); 582 583 int j = n_word(frac_digits) * bits_in_word + int_digits - 3; 584 585 for (; s < end; s++) { 586 switch (*s) { 587 case '7': case '6': case '5': case '4': 588 case '3': case '2': case '1': 589 set_oct(j, *s - '0'); 590 M5_FALLTHROUGH; 591 case '0': 592 j -= 3; 593 M5_FALLTHROUGH; 594 case '.': 595 break; 596 default: 597 SCFX_FAIL_IF_(true); // should not happen 598 } 599 } 600 601 m_wp = n_word(frac_digits) - word_offset; 602 break; 603 } 604 case 10: 605 { 606 word carry, temp; 607 int length = int_digits + frac_digits; 608 resize_to(sc_max(min_mant, n_word(4 * length))); 609 610 m_mant.clear(); 611 m_msw = m_lsw = 0; 612 613 for (; s < end; s++) { 614 switch (*s) { 615 case '9': case '8': case '7': case '6': case '5': 616 case '4': case '3': case '2': case '1': case '0': 617 multiply_by_ten(); 618 carry = *s - '0'; 619 for (int i = 0; carry && i < m_mant.size(); i++) { 620 temp = m_mant[i]; 621 temp += carry; 622 carry = temp < m_mant[i]; 623 m_mant[i] = temp; 624 } 625 case '.': 626 break; 627 default: 628 SCFX_FAIL_IF_(true); // should not happen 629 } 630 } 631 632 m_wp = 0; 633 find_sw(); 634 635 int denominator = frac_digits - exponent; 636 637 if (denominator) { 638 scfx_rep frac_num = pow10_fx(denominator); 639 scfx_rep *temp_num = 640 div_scfx_rep(const_cast<const scfx_rep &>(*this), 641 frac_num, cte_wl); 642 *this = *temp_num; 643 delete temp_num; 644 } 645 646 break; 647 } 648 case 16: 649 { 650 exponent *= 4; 651 int_digits *= 4; 652 frac_digits *= 4; 653 654 int bit_offset = exponent % bits_in_word; 655 int word_offset = exponent / bits_in_word; 656 657 int_digits += bit_offset; 658 frac_digits -= bit_offset; 659 660 int words = n_word(int_digits) + n_word(frac_digits); 661 if (words > size()) 662 resize_to(words); 663 m_mant.clear(); 664 665 int j = n_word(frac_digits) * bits_in_word + int_digits - 4; 666 667 for (; s < end; s ++) { 668 switch (*s) { 669 case 'f': case 'e': case 'd': case 'c': case 'b': case 'a': 670 set_hex(j, *s - 'a' + 10); 671 j -= 4; 672 break; 673 case 'F': case 'E': case 'D': case 'C': case 'B': case 'A': 674 set_hex(j, *s - 'A' + 10); 675 j -= 4; 676 break; 677 case '9': case '8': case '7': case '6': case '5': 678 case '4': case '3': case '2': case '1': 679 set_hex(j, *s - '0'); 680 M5_FALLTHROUGH; 681 case '0': 682 j -= 4; 683 M5_FALLTHROUGH; 684 case '.': 685 break; 686 default: 687 SCFX_FAIL_IF_(true); // should not happen 688 } 689 } 690 691 m_wp = n_word(frac_digits) - word_offset; 692 break; 693 } 694 } 695 696 m_state = normal; 697 find_sw(); 698 699 // 700 // two's complement of mantissa if it is negative 701 // 702 if (mant_is_neg) { 703 m_mant[m_msw] |= ~0U << scfx_find_msb(m_mant[m_msw]); 704 for (int i = m_msw + 1; i < m_mant.size(); ++i) 705 m_mant[i] = static_cast<word>(-1); 706 complement(m_mant, m_mant, m_mant.size()); 707 inc(m_mant); 708 m_sign *= -1; 709 find_sw(); 710 } 711} 712 713#undef SCFX_FAIL_IF_ 714 715// ---------------------------------------------------------------------------- 716// METHOD : to_double 717// 718// Convert from scfx_rep to double. 719// ---------------------------------------------------------------------------- 720 721double 722scfx_rep::to_double() const 723{ 724 scfx_ieee_double id; 725 726 // handle special cases 727 if (is_nan()) { 728 id.set_nan(); 729 return id; 730 } 731 732 if (is_inf()) { 733 id.set_inf(); 734 id.negative(m_sign < 0); 735 return id; 736 } 737 738 if (is_zero()) { 739 id = 0.; 740 id.negative(m_sign < 0); 741 return id; 742 } 743 744 int msb = scfx_find_msb(m_mant[m_msw]); 745 746 int exp = (m_msw - m_wp) * bits_in_word + msb; 747 748 if (exp > SCFX_IEEE_DOUBLE_E_MAX) { 749 id.set_inf(); 750 id.negative(m_sign < 0); 751 return id; 752 } 753 754 if (exp < SCFX_IEEE_DOUBLE_E_MIN - 755 static_cast<int>(SCFX_IEEE_DOUBLE_M_SIZE)) 756 { 757 id = 0.; 758 return id; 759 } 760 761 int shift = mantissa0_size - msb; 762 763 unsigned int m0; 764 unsigned int m1 = 0; 765 unsigned int guard = 0; 766 767 if (shift == 0) { 768 m0 = m_mant[m_msw] & ~(1 << mantissa0_size); 769 if (m_msw > m_lsw) { 770 m1 = m_mant[m_msw - 1]; 771 if (m_msw - 1 > m_lsw) 772 guard = m_mant[m_msw - 2] >> (bits_in_word - 1); 773 } 774 } else if (shift < 0) { 775 m0 = (m_mant[m_msw] >> -shift) & ~(1 << mantissa0_size); 776 m1 = m_mant[m_msw] << (bits_in_word + shift); 777 if (m_msw > m_lsw) { 778 m1 |= m_mant[m_msw - 1] >> -shift; 779 guard = (m_mant[m_msw - 1] >> (-shift - 1)) & 1; 780 } 781 } else { 782 m0 = (m_mant[m_msw] << shift) & ~(1 << mantissa0_size); 783 if (m_msw > m_lsw) { 784 m0 |= m_mant[m_msw - 1] >> (bits_in_word - shift); 785 m1 = m_mant[m_msw - 1] << shift; 786 if (m_msw - 1 > m_lsw) { 787 m1 |= m_mant[m_msw - 2] >> (bits_in_word - shift); 788 guard = (m_mant[m_msw - 2] >> (bits_in_word - shift - 1)) & 1; 789 } 790 } 791 } 792 793 if (exp < SCFX_IEEE_DOUBLE_E_MIN) { 794 m0 |= (1 << mantissa0_size); 795 796 int subnormal_shift = SCFX_IEEE_DOUBLE_E_MIN - exp; 797 798 if (subnormal_shift < bits_in_word) { 799 m1 = m1 >> subnormal_shift | 800 m0 << (bits_in_word - subnormal_shift); 801 m0 = m0 >> subnormal_shift; 802 } else { 803 m1 = m0 >> (subnormal_shift - bits_in_word); 804 m0 = 0; 805 } 806 807 guard = 0; 808 809 exp = SCFX_IEEE_DOUBLE_E_MIN - 1; 810 } 811 812 id.mantissa0(m0); 813 id.mantissa1(m1); 814 id.exponent(exp); 815 id.negative(m_sign < 0); 816 817 double result = id; 818 819 if (guard != 0) 820 result += m_sign * scfx_pow2(exp - SCFX_IEEE_DOUBLE_M_SIZE); 821 822 return result; 823} 824 825 826// ---------------------------------------------------------------------------- 827// METHOD : to_uint64 828// 829// Convert from scfx_rep to uint64. 830// Truncates towards 0 _then_ wraps; infinities and NaN go to zero. 831// ---------------------------------------------------------------------------- 832 833uint64 834scfx_rep::to_uint64() const 835{ 836 if (!is_normal() || is_zero()) { 837 return 0; 838 } 839 840 uint64 result = 0; 841 int shift = 0; 842 int idx = m_wp; 843 844 // Ignore bits off the top; they modulo out. 845 // Ignore bits off the bottom; we're truncating. 846 while (shift < 64 && m_msw >= idx && idx >= m_lsw) { 847 result += static_cast<uint64>(m_mant[idx]) << shift; 848 shift += bits_in_word; 849 idx += 1; 850 } 851 852 return m_sign > 0 ? result : -result; 853} 854 855 856// ---------------------------------------------------------------------------- 857// METHOD : to_string 858// 859// Convert from scfx_rep to character string. 860// ---------------------------------------------------------------------------- 861 862void 863print_dec(scfx_string &s, const scfx_rep &num, int w_prefix, sc_fmt fmt) 864{ 865 if (num.is_neg()) 866 s += '-'; 867 868 if (w_prefix == 1) { 869 scfx_print_prefix(s, SC_DEC); 870 } 871 872 if (num.is_zero()) { 873 s += '0'; 874 return; 875 } 876 877 // split 'num' into its integer and fractional part 878 scfx_rep int_part = num; 879 scfx_rep frac_part = num; 880 881 int i; 882 883 for (i = int_part.m_lsw; i <= int_part.m_msw && i < int_part.m_wp; i++) 884 int_part.m_mant[i] = 0; 885 int_part.find_sw(); 886 if (int_part.m_wp < int_part.m_lsw) 887 int_part.resize_to(int_part.size() - int_part.m_wp, -1); 888 889 for (i = frac_part.m_msw; 890 i >= frac_part.m_lsw && i >= frac_part.m_wp; i--) 891 frac_part.m_mant[i] = 0; 892 frac_part.find_sw(); 893 if (frac_part.m_msw == frac_part.size() - 1) 894 frac_part.resize_to(frac_part.size() + 1, 1); 895 896 // print integer part 897 int int_digits = 0; 898 int int_zeros = 0; 899 900 if (!int_part.is_zero()) { 901 double int_wl = (int_part.m_msw - int_part.m_wp) * bits_in_word + 902 scfx_find_msb(int_part.m_mant[int_part.m_msw]) + 1; 903 int_digits = (int)std::ceil(int_wl * std::log10(2.)); 904 905 int len = s.length(); 906 s.append(int_digits); 907 908 bool zero_digits = (frac_part.is_zero() && fmt != SC_F); 909 910 for (i = int_digits + len - 1; i >= len; i--) { 911 unsigned int remainder = int_part.divide_by_ten(); 912 s[i] = static_cast<char>('0' + remainder); 913 914 if (zero_digits) { 915 if (remainder == 0) 916 int_zeros++; 917 else 918 zero_digits = false; 919 } 920 } 921 922 // discard trailing zeros from int_part 923 s.discard(int_zeros); 924 925 if (s[len] == '0') { 926 // int_digits was overestimated by one 927 s.remove(len); 928 --int_digits; 929 } 930 } 931 932 // print fractional part 933 int frac_digits = 0; 934 int frac_zeros = 0; 935 936 if (!frac_part.is_zero()) { 937 s += '.'; 938 939 bool zero_digits = (int_digits == 0 && fmt != SC_F); 940 941 double frac_wl = (frac_part.m_wp - frac_part.m_msw) * bits_in_word - 942 scfx_find_msb(frac_part.m_mant[frac_part.m_msw]) - 1; 943 frac_zeros = (int)std::floor(frac_wl * std::log10(2.)); 944 945 scfx_rep temp; 946 sc_dt::multiply(temp, frac_part, pow10_fx(frac_zeros)); 947 frac_part = temp; 948 if (frac_part.m_msw == frac_part.size() - 1) 949 frac_part.resize_to(frac_part.size() + 1, 1); 950 951 frac_digits = frac_zeros; 952 if (!zero_digits) { 953 for (i = 0; i < frac_zeros; i++) 954 s += '0'; 955 frac_zeros = 0; 956 } 957 958 while (!frac_part.is_zero()) { 959 frac_part.multiply_by_ten(); 960 int n = frac_part.m_mant[frac_part.m_msw + 1]; 961 962 if (zero_digits) { 963 if (n == 0) 964 frac_zeros++; 965 else 966 zero_digits = false; 967 } 968 969 if (! zero_digits) 970 s += static_cast<char>('0' + n); 971 972 frac_part.m_mant[frac_part.m_msw + 1] = 0; 973 frac_digits++; 974 } 975 } 976 977 // print exponent 978 if (fmt != SC_F) { 979 if (frac_digits == 0) 980 scfx_print_exp(s, int_zeros); 981 else if (int_digits == 0) 982 scfx_print_exp(s, -frac_zeros); 983 } 984} 985 986void 987print_other(scfx_string &s, const scfx_rep &a, sc_numrep numrep, int w_prefix, 988 sc_fmt fmt, const scfx_params *params) 989{ 990 scfx_rep b = a; 991 992 sc_numrep numrep2 = numrep; 993 994 bool numrep_is_sm = (numrep == SC_BIN_SM || 995 numrep == SC_OCT_SM || 996 numrep == SC_HEX_SM); 997 998 if (numrep_is_sm) { 999 if (b.is_neg()) { 1000 s += '-'; 1001 b = *neg_scfx_rep(a); 1002 } 1003 switch (numrep) { 1004 case SC_BIN_SM: 1005 numrep2 = SC_BIN_US; 1006 break; 1007 case SC_OCT_SM: 1008 numrep2 = SC_OCT_US; 1009 break; 1010 case SC_HEX_SM: 1011 numrep2 = SC_HEX_US; 1012 break; 1013 default: 1014 ; 1015 } 1016 } 1017 1018 if (w_prefix != 0) { 1019 scfx_print_prefix(s, numrep); 1020 } 1021 1022 numrep = numrep2; 1023 1024 int msb, lsb; 1025 1026 if (params != 0) { 1027 msb = params->iwl() - 1; 1028 lsb = params->iwl() - params->wl(); 1029 1030 if (params->enc() == SC_TC_ && 1031 (numrep == SC_BIN_US || 1032 numrep == SC_OCT_US || 1033 numrep == SC_HEX_US) && 1034 !numrep_is_sm && 1035 params->wl() > 1) { 1036 --msb; 1037 } else if (params->enc() == SC_US_ && 1038 (numrep == SC_BIN || 1039 numrep == SC_OCT || 1040 numrep == SC_HEX || 1041 numrep == SC_CSD)) { 1042 ++msb; 1043 } 1044 } else { 1045 if (b.is_zero()) { 1046 msb = 0; 1047 lsb = 0; 1048 } else { 1049 msb = (b.m_msw - b.m_wp) * bits_in_word 1050 + scfx_find_msb(b.m_mant[ b.m_msw ]) + 1; 1051 while (b.get_bit(msb) == b.get_bit(msb - 1)) 1052 --msb; 1053 1054 if (numrep == SC_BIN_US || 1055 numrep == SC_OCT_US || 1056 numrep == SC_HEX_US) { 1057 --msb; 1058 } 1059 1060 lsb = (b.m_lsw - b.m_wp) * bits_in_word + 1061 scfx_find_lsb(b.m_mant[b.m_lsw]); 1062 1063 } 1064 } 1065 1066 int step; 1067 1068 switch (numrep) { 1069 case SC_BIN: 1070 case SC_BIN_US: 1071 case SC_CSD: 1072 step = 1; 1073 break; 1074 case SC_OCT: 1075 case SC_OCT_US: 1076 step = 3; 1077 break; 1078 case SC_HEX: 1079 case SC_HEX_US: 1080 step = 4; 1081 break; 1082 default: 1083 SC_REPORT_FATAL(sc_core::SC_ID_ASSERTION_FAILED_, 1084 "unexpected sc_numrep"); 1085 sc_core::sc_abort(); 1086 } 1087 1088 msb = (int)std::ceil(double(msb + 1) / step) * step - 1; 1089 1090 lsb = (int)std::floor(double(lsb) / step) * step; 1091 1092 if (msb < 0) { 1093 s += '.'; 1094 if (fmt == SC_F) { 1095 int sign = (b.is_neg()) ? (1 << step) - 1 : 0; 1096 for (int i = (msb + 1) / step; i < 0; i++) { 1097 if (sign < 10) 1098 s += static_cast<char>(sign + '0'); 1099 else 1100 s += static_cast<char>(sign + 'a' - 10); 1101 } 1102 } 1103 } 1104 1105 int i = msb; 1106 while (i >= lsb) { 1107 int value = 0; 1108 for (int j = step - 1; j >= 0; --j) { 1109 value += static_cast<int>(b.get_bit(i)) << j; 1110 --i; 1111 } 1112 if (value < 10) 1113 s += static_cast<char>(value + '0'); 1114 else 1115 s += static_cast<char>(value + 'a' - 10); 1116 if (i == -1) 1117 s += '.'; 1118 } 1119 1120 if (lsb > 0 && fmt == SC_F) { 1121 for (int i = lsb / step; i > 0; i--) 1122 s += '0'; 1123 } 1124 1125 if (s[s.length() - 1] == '.') 1126 s.discard(1); 1127 1128 if (fmt != SC_F) { 1129 if (msb < 0) 1130 scfx_print_exp(s, (msb + 1) / step); 1131 else if (lsb > 0) 1132 scfx_print_exp(s, lsb / step); 1133 } 1134 1135 if (numrep == SC_CSD) 1136 scfx_tc2csd(s, w_prefix); 1137} 1138 1139const char * 1140scfx_rep::to_string(sc_numrep numrep, int w_prefix, 1141 sc_fmt fmt, const scfx_params *params) const 1142{ 1143 static scfx_string s; 1144 1145 s.clear(); 1146 1147 if (is_nan()) { 1148 scfx_print_nan(s); 1149 } else if (is_inf()) { 1150 scfx_print_inf(s, is_neg()); 1151 } else if (is_neg() && !is_zero() && 1152 (numrep == SC_BIN_US || 1153 numrep == SC_OCT_US || 1154 numrep == SC_HEX_US)) { 1155 s += "negative"; 1156 } else if (numrep == SC_DEC || numrep == SC_NOBASE) { 1157 sc_dt::print_dec(s, *this, w_prefix, fmt); 1158 } else { 1159 sc_dt::print_other(s, *this, numrep, w_prefix, fmt, params); 1160 } 1161 1162 return s; 1163} 1164 1165 1166// ---------------------------------------------------------------------------- 1167// ADD 1168// 1169// add two mantissas of the same size 1170// result has the same size 1171// returns carry of operation 1172// ---------------------------------------------------------------------------- 1173 1174static inline int 1175add_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b) 1176{ 1177 unsigned int carry = 0; 1178 1179 int index = 0; 1180 1181 do { 1182 word x = a[index]; 1183 word y = b[index]; 1184 1185 y += carry; 1186 carry = y < carry; 1187 y += x; 1188 carry += y < x; 1189 result[index] = y; 1190 } while (++index < size); 1191 1192 return (carry ? 1 : 0); 1193} 1194 1195static inline int 1196sub_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b) 1197{ 1198 unsigned carry = 0; 1199 1200 int index = 0; 1201 1202 do { 1203 word x = a[index]; 1204 word y = b[index]; 1205 1206 y += carry; 1207 carry = y < carry; 1208 y = x - y; 1209 carry += y > x; 1210 result[index] = y; 1211 } while (++index < size); 1212 1213 return (carry ? 1 : 0); 1214} 1215 1216scfx_rep * 1217add_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl) 1218{ 1219 scfx_rep &result = *new scfx_rep; 1220 1221 // 1222 // check for special cases 1223 // 1224 if (lhs.is_nan() || rhs.is_nan() || 1225 (lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign)) { 1226 result.set_nan(); 1227 return &result; 1228 } 1229 1230 if (lhs.is_inf()) { 1231 result.set_inf(lhs.m_sign); 1232 return &result; 1233 } 1234 1235 if (rhs.is_inf()) { 1236 result.set_inf(rhs.m_sign); 1237 return &result; 1238 } 1239 1240 // 1241 // align operands if needed 1242 // 1243 scfx_mant_ref lhs_mant; 1244 scfx_mant_ref rhs_mant; 1245 1246 int len_mant = lhs.size(); 1247 int new_wp = lhs.m_wp; 1248 1249 align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant); 1250 1251 // 1252 // size the result mantissa 1253 // 1254 result.resize_to(len_mant); 1255 result.m_wp = new_wp; 1256 1257 // 1258 // do it 1259 // 1260 if (lhs.m_sign == rhs.m_sign) { 1261 add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant); 1262 result.m_sign = lhs.m_sign; 1263 } else { 1264 int cmp = compare_abs(lhs, rhs); 1265 1266 if (cmp == 1) { 1267 sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant); 1268 result.m_sign = lhs.m_sign; 1269 } else if (cmp == -1) { 1270 sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant); 1271 result.m_sign = rhs.m_sign; 1272 } else { 1273 result.m_mant.clear(); 1274 result.m_sign = 1; 1275 } 1276 } 1277 1278 result.find_sw(); 1279 result.round(max_wl); 1280 1281 return &result; 1282} 1283 1284 1285// ---------------------------------------------------------------------------- 1286// SUB 1287// 1288// sub two word's of the same size 1289// result has the same size 1290// returns carry of operation 1291// ---------------------------------------------------------------------------- 1292 1293static inline int 1294sub_with_index(scfx_mant &a, int a_msw, int /*a_lsw*/, 1295 const scfx_mant &b, int b_msw, int b_lsw) 1296{ 1297 unsigned carry = 0; 1298 1299 int size = b_msw - b_lsw; 1300 int a_index = a_msw - size; 1301 int b_index = b_msw - size; 1302 1303 do { 1304 word x = a[a_index]; 1305 word y = b[b_index]; 1306 1307 y += carry; 1308 carry = y < carry; 1309 y = x - y; 1310 carry += y > x; 1311 a[a_index] = y; 1312 1313 a_index++; 1314 b_index++; 1315 } while (size--); 1316 1317 if (carry) { 1318 // special case: a[a_msw + 1] == 1 1319 a[a_msw + 1] = 0; 1320 } 1321 1322 return (carry ? 1 : 0); 1323} 1324 1325scfx_rep * 1326sub_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl) 1327{ 1328 scfx_rep &result = *new scfx_rep; 1329 1330 // 1331 // check for special cases 1332 // 1333 if (lhs.is_nan() || rhs.is_nan() || 1334 (lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign)) { 1335 result.set_nan(); 1336 return &result; 1337 } 1338 1339 if (lhs.is_inf()) { 1340 result.set_inf(lhs.m_sign); 1341 return &result; 1342 } 1343 1344 if (rhs.is_inf()) { 1345 result.set_inf(-1 * rhs.m_sign); 1346 return &result; 1347 } 1348 1349 // 1350 // align operands if needed 1351 // 1352 scfx_mant_ref lhs_mant; 1353 scfx_mant_ref rhs_mant; 1354 1355 int len_mant = lhs.size(); 1356 int new_wp = lhs.m_wp; 1357 1358 align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant); 1359 1360 // 1361 // size the result mantissa 1362 // 1363 result.resize_to(len_mant); 1364 result.m_wp = new_wp; 1365 1366 // 1367 // do it 1368 // 1369 if (lhs.m_sign != rhs.m_sign) { 1370 add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant); 1371 result.m_sign = lhs.m_sign; 1372 } else { 1373 int cmp = compare_abs(lhs, rhs); 1374 1375 if (cmp == 1) { 1376 sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant); 1377 result.m_sign = lhs.m_sign; 1378 } else if (cmp == -1) { 1379 sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant); 1380 result.m_sign = -rhs.m_sign; 1381 } else { 1382 result.m_mant.clear(); 1383 result.m_sign = 1; 1384 } 1385 } 1386 1387 result.find_sw(); 1388 result.round(max_wl); 1389 1390 return &result; 1391} 1392 1393 1394// ---------------------------------------------------------------------------- 1395// MUL 1396// ---------------------------------------------------------------------------- 1397 1398union word_short 1399{ 1400 word l; 1401 struct 1402 { 1403#if defined(SC_BOOST_BIG_ENDIAN) 1404 half_word u; 1405 half_word l; 1406#elif defined(SC_BOOST_LITTLE_ENDIAN) 1407 half_word l; 1408 half_word u; 1409#endif 1410 } s; 1411}; 1412 1413#if defined(SC_BOOST_BIG_ENDIAN) 1414static const int half_word_incr = -1; 1415#elif defined(SC_BOOST_LITTLE_ENDIAN) 1416static const int half_word_incr = 1; 1417#endif 1418 1419void 1420multiply(scfx_rep &result, const scfx_rep &lhs, const scfx_rep &rhs, 1421 int max_wl) 1422{ 1423 // 1424 // check for special cases 1425 // 1426 if (lhs.is_nan() || rhs.is_nan() || 1427 (lhs.is_inf() && rhs.is_zero()) || 1428 (lhs.is_zero() && rhs.is_inf())) { 1429 result.set_nan(); 1430 return; 1431 } 1432 1433 if (lhs.is_inf() || rhs.is_inf()) { 1434 result.set_inf(lhs.m_sign * rhs.m_sign); 1435 return; 1436 } 1437 1438 if (lhs.is_zero() || rhs.is_zero()) { 1439 result.set_zero(lhs.m_sign * rhs.m_sign); 1440 return; 1441 } 1442 1443 // 1444 // do it 1445 // 1446 int len_lhs = lhs.m_msw - lhs.m_lsw + 1; 1447 int len_rhs = rhs.m_msw - rhs.m_lsw + 1; 1448 1449 int new_size = sc_max(min_mant, len_lhs + len_rhs); 1450 int new_wp = (lhs.m_wp - lhs.m_lsw) + (rhs.m_wp - rhs.m_lsw); 1451 int new_sign = lhs.m_sign * rhs.m_sign; 1452 1453 result.resize_to(new_size); 1454 result.m_mant.clear(); 1455 result.m_wp = new_wp; 1456 result.m_sign = new_sign; 1457 result.m_state = scfx_rep::normal; 1458 1459 half_word *s1 = lhs.m_mant.half_addr(lhs.m_lsw); 1460 half_word *s2 = rhs.m_mant.half_addr(rhs.m_lsw); 1461 1462 half_word *t = result.m_mant.half_addr(); 1463 1464 len_lhs <<= 1; 1465 len_rhs <<= 1; 1466 1467 int i1, i2; 1468 1469 for (i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr) { 1470 word_short ls; 1471 ls.l = 0; 1472 1473 half_word v1 = s1[i1]; 1474 1475 for (i2 = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr) { 1476 ls.l += v1 * s2[i2]; 1477 ls.s.l = ls.s.u + ((t[i2] += ls.s.l) < ls.s.l); 1478 ls.s.u = 0; 1479 } 1480 1481 t[i2] = ls.s.l; 1482 t += half_word_incr; 1483 } 1484 1485 result.find_sw(); 1486 result.round(max_wl); 1487} 1488 1489 1490// ---------------------------------------------------------------------------- 1491// DIV 1492// ---------------------------------------------------------------------------- 1493 1494scfx_rep * 1495div_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int div_wl) 1496{ 1497 scfx_rep &result = *new scfx_rep; 1498 1499 // 1500 // check for special cases 1501 // 1502 if (lhs.is_nan() || rhs.is_nan() || (lhs.is_inf() && rhs.is_inf()) || 1503 (lhs.is_zero() && rhs.is_zero())) { 1504 result.set_nan(); 1505 return &result; 1506 } 1507 1508 if (lhs.is_inf() || rhs.is_zero()) { 1509 result.set_inf(lhs.m_sign * rhs.m_sign); 1510 return &result; 1511 } 1512 1513 if (lhs.is_zero() || rhs.is_inf()) { 1514 result.set_zero(lhs.m_sign * rhs.m_sign); 1515 return &result; 1516 } 1517 1518 // 1519 // do it 1520 // 1521 1522 // compute one bit more for rounding 1523 div_wl++; 1524 1525 result.resize_to(sc_max(n_word(div_wl) + 1, min_mant)); 1526 result.m_mant.clear(); 1527 result.m_sign = lhs.m_sign * rhs.m_sign; 1528 1529 int msb_lhs = scfx_find_msb(lhs.m_mant[lhs.m_msw]) + 1530 (lhs.m_msw - lhs.m_wp) * bits_in_word; 1531 int msb_rhs = scfx_find_msb(rhs.m_mant[rhs.m_msw]) + 1532 (rhs.m_msw - rhs.m_wp) * bits_in_word; 1533 1534 int msb_res = msb_lhs - msb_rhs; 1535 int to_shift = -msb_res % bits_in_word; 1536 int result_index; 1537 1538 int c = (msb_res % bits_in_word >= 0) ? 1 : 0; 1539 1540 result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word; 1541 result.m_wp = (result.size() - c) - msb_res / bits_in_word; 1542 1543 scfx_rep remainder = lhs; 1544 1545 // align msb from remainder to msb from rhs 1546 remainder.lshift(to_shift); 1547 1548 // make sure msw(remainder) < size - 1 1549 if (remainder.m_msw == remainder.size() - 1) 1550 remainder.resize_to(remainder.size() + 1, 1); 1551 1552 // make sure msw(remainder) >= msw(rhs)! 1553 int msw_diff = rhs.m_msw - remainder.m_msw; 1554 if (msw_diff > 0) 1555 remainder.resize_to(remainder.size() + msw_diff, -1); 1556 1557 int counter; 1558 1559 for (counter = div_wl; counter && !remainder.is_zero(); counter--) { 1560 if (compare_msw_ff(rhs, remainder) <= 0) { 1561 result.set_bin(result_index); 1562 sub_with_index(remainder.m_mant, remainder.m_msw, remainder.m_lsw, 1563 rhs.m_mant, rhs.m_msw, rhs.m_lsw); 1564 } 1565 result_index--; 1566 remainder.shift_left(1); 1567 remainder.m_lsw = remainder.find_lsw(); 1568 } 1569 1570 // perform convergent rounding, if needed 1571 if (counter == 0) { 1572 int index = result_index + 1 - result.m_wp * bits_in_word; 1573 1574 scfx_index x = result.calc_indices(index); 1575 scfx_index x1 = result.calc_indices(index + 1); 1576 1577 if (result.o_bit_at(x) && result.o_bit_at(x1)) 1578 result.q_incr(x); 1579 1580 result.m_r_flag = true; 1581 } 1582 1583 result.find_sw(); 1584 1585 return &result; 1586} 1587 1588// ---------------------------------------------------------------------------- 1589// destructive shift mantissa to the left 1590// ---------------------------------------------------------------------------- 1591 1592void 1593scfx_rep::lshift(int n) 1594{ 1595 if (n == 0) 1596 return; 1597 1598 if (n < 0) { 1599 rshift(-n); 1600 return; 1601 } 1602 1603 if (is_normal()) { 1604 int shift_bits = n % bits_in_word; 1605 int shift_words = n / bits_in_word; 1606 1607 // resize if needed 1608 if (m_msw == size() - 1 && 1609 scfx_find_msb(m_mant[m_msw]) >= bits_in_word - shift_bits) 1610 resize_to(size() + 1, 1); 1611 1612 // do it 1613 m_wp -= shift_words; 1614 shift_left(shift_bits); 1615 find_sw(); 1616 } 1617} 1618 1619// ---------------------------------------------------------------------------- 1620// destructive shift mantissa to the right 1621// ---------------------------------------------------------------------------- 1622 1623void 1624scfx_rep::rshift(int n) 1625{ 1626 if (n == 0) 1627 return; 1628 1629 if (n < 0) { 1630 lshift(-n); 1631 return; 1632 } 1633 1634 if (is_normal()) { 1635 int shift_bits = n % bits_in_word; 1636 int shift_words = n / bits_in_word; 1637 1638 // resize if needed 1639 if (m_lsw == 0 && scfx_find_lsb(m_mant[m_lsw]) < shift_bits) 1640 resize_to(size() + 1, -1); 1641 1642 // do it 1643 m_wp += shift_words; 1644 shift_right(shift_bits); 1645 find_sw(); 1646 } 1647} 1648 1649 1650// ---------------------------------------------------------------------------- 1651// FRIEND FUNCTION : compare_abs 1652// 1653// Compares the absolute values of two scfx_reps, excluding the special cases. 1654// ---------------------------------------------------------------------------- 1655 1656int 1657compare_abs(const scfx_rep &a, const scfx_rep &b) 1658{ 1659 // check for zero 1660 word a_word = a.m_mant[a.m_msw]; 1661 word b_word = b.m_mant[b.m_msw]; 1662 1663 if (a_word == 0 || b_word == 0) { 1664 if (a_word != 0) 1665 return 1; 1666 if (b_word != 0) 1667 return -1; 1668 return 0; 1669 } 1670 1671 // compare msw index 1672 int a_msw = a.m_msw - a.m_wp; 1673 int b_msw = b.m_msw - b.m_wp; 1674 1675 if (a_msw > b_msw) 1676 return 1; 1677 1678 if (a_msw < b_msw) 1679 return -1; 1680 1681 // compare content 1682 int a_i = a.m_msw; 1683 int b_i = b.m_msw; 1684 1685 while (a_i >= a.m_lsw && b_i >= b.m_lsw) { 1686 a_word = a.m_mant[a_i]; 1687 b_word = b.m_mant[b_i]; 1688 if (a_word > b_word) 1689 return 1; 1690 if (a_word < b_word) 1691 return -1; 1692 --a_i; 1693 --b_i; 1694 } 1695 1696 bool a_zero = true; 1697 while (a_i >= a.m_lsw) { 1698 a_zero = a_zero && (a.m_mant[a_i] == 0); 1699 --a_i; 1700 } 1701 1702 bool b_zero = true; 1703 while (b_i >= b.m_lsw) { 1704 b_zero = b_zero && (b.m_mant[b_i] == 0); 1705 --b_i; 1706 } 1707 1708 // assertion: a_zero || b_zero 1709 1710 if (!a_zero && b_zero) 1711 return 1; 1712 1713 if (a_zero && !b_zero) 1714 return -1; 1715 1716 return 0; 1717} 1718 1719// ---------------------------------------------------------------------------- 1720// FRIEND FUNCTION : cmp_scfx_rep 1721// 1722// Compares the values of two scfx_reps, including the special cases. 1723// ---------------------------------------------------------------------------- 1724 1725int 1726cmp_scfx_rep(const scfx_rep &a, const scfx_rep &b) 1727{ 1728 // handle special cases 1729 1730 if (a.is_nan() || b.is_nan()) { 1731 return 2; 1732 } 1733 1734 if (a.is_inf() || b.is_inf()) { 1735 if (a.is_inf()) { 1736 if (!a.is_neg()) { 1737 if (b.is_inf() && !b.is_neg()) { 1738 return 0; 1739 } else { 1740 return 1; 1741 } 1742 } else { 1743 if (b.is_inf() && b.is_neg()) { 1744 return 0; 1745 } else { 1746 return -1; 1747 } 1748 } 1749 } 1750 if (b.is_inf()) { 1751 if (!b.is_neg()) { 1752 return -1; 1753 } else { 1754 return 1; 1755 } 1756 } 1757 } 1758 1759 if (a.is_zero() && b.is_zero()) { 1760 return 0; 1761 } 1762 1763 // compare sign 1764 if (a.m_sign != b.m_sign) { 1765 return a.m_sign; 1766 } 1767 1768 return (a.m_sign * compare_abs(a, b)); 1769} 1770 1771 1772// ---------------------------------------------------------------------------- 1773// PRIVATE METHOD : quantization 1774// 1775// Performs destructive quantization. 1776// ---------------------------------------------------------------------------- 1777 1778void 1779scfx_rep::quantization(const scfx_params ¶ms, bool &q_flag) 1780{ 1781 scfx_index x = calc_indices(params.iwl() - params.wl()); 1782 1783 if (x.wi() < 0) 1784 return; 1785 1786 if (x.wi() >= size()) 1787 resize_to(x.wi() + 1, 1); 1788 1789 bool qb = q_bit(x); 1790 bool qz = q_zero(x); 1791 1792 q_flag = (qb || ! qz); 1793 1794 if (q_flag) { 1795 switch (params.q_mode()) { 1796 case SC_TRN: // truncation 1797 { 1798 if (is_neg()) 1799 q_incr(x); 1800 break; 1801 } 1802 case SC_RND: // rounding to plus infinity 1803 { 1804 if (!is_neg()) { 1805 if (qb) 1806 q_incr(x); 1807 } else { 1808 if (qb && !qz) 1809 q_incr(x); 1810 } 1811 break; 1812 } 1813 case SC_TRN_ZERO: // truncation to zero 1814 { 1815 break; 1816 } 1817 case SC_RND_INF: // rounding to infinity 1818 { 1819 if (qb) 1820 q_incr(x); 1821 break; 1822 } 1823 case SC_RND_CONV: // convergent rounding 1824 { 1825 if ((qb && !qz) || (qb && qz && q_odd(x))) 1826 q_incr(x); 1827 break; 1828 } 1829 case SC_RND_ZERO: // rounding to zero 1830 { 1831 if (qb && !qz) 1832 q_incr(x); 1833 break; 1834 } 1835 case SC_RND_MIN_INF: // rounding to minus infinity 1836 { 1837 if (!is_neg()) { 1838 if (qb && !qz) 1839 q_incr(x); 1840 } else { 1841 if (qb) 1842 q_incr(x); 1843 } 1844 break; 1845 } 1846 default: 1847 ; 1848 } 1849 q_clear(x); 1850 1851 find_sw(); 1852 } 1853} 1854 1855 1856// ---------------------------------------------------------------------------- 1857// PRIVATE METHOD : overflow 1858// 1859// Performs destructive overflow handling. 1860// ---------------------------------------------------------------------------- 1861 1862void 1863scfx_rep::overflow(const scfx_params ¶ms, bool &o_flag) 1864{ 1865 scfx_index x = calc_indices(params.iwl() - 1); 1866 1867 if (x.wi() >= size()) 1868 resize_to(x.wi() + 1, 1); 1869 1870 if (x.wi() < 0) { 1871 resize_to(size() - x.wi(), -1); 1872 x.wi(0); 1873 } 1874 1875 bool zero_left = o_zero_left(x); 1876 bool bit_at = o_bit_at(x); 1877 bool zero_right = o_zero_right(x); 1878 1879 bool under = false; 1880 bool over = false; 1881 1882 sc_enc enc = params.enc(); 1883 1884 if (enc == SC_TC_) { 1885 if (is_neg()) { 1886 if (params.o_mode() == SC_SAT_SYM) 1887 under = (!zero_left || bit_at); 1888 else 1889 under = (!zero_left || (zero_left && bit_at && ! zero_right)); 1890 } else { 1891 over = (! zero_left || bit_at); 1892 } 1893 } else { 1894 if (is_neg()) 1895 under = (!is_zero()); 1896 else 1897 over = (!zero_left); 1898 } 1899 1900 o_flag = (under || over); 1901 1902 if (o_flag) { 1903 scfx_index x2 = calc_indices(params.iwl() - params.wl()); 1904 1905 if (x2.wi() < 0) { 1906 resize_to(size() - x2.wi(), -1); 1907 x.wi(x.wi() - x2.wi()); 1908 x2.wi(0); 1909 } 1910 1911 switch (params.o_mode()) { 1912 case SC_WRAP: // wrap-around 1913 { 1914 int n_bits = params.n_bits(); 1915 1916 if (n_bits == 0) { 1917 // wrap-around all 'wl' bits 1918 toggle_tc(); 1919 o_extend(x, enc); 1920 toggle_tc(); 1921 } else if (n_bits < params.wl()) { 1922 scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits); 1923 1924 // wrap-around least significant 'wl - n_bits' bits; 1925 // saturate most significant 'n_bits' bits 1926 toggle_tc(); 1927 o_set(x, x3, enc, under); 1928 o_extend(x, enc); 1929 toggle_tc(); 1930 } else { 1931 // saturate all 'wl' bits 1932 if (under) 1933 o_set_low(x, enc); 1934 else 1935 o_set_high(x, x2, enc); 1936 } 1937 break; 1938 } 1939 case SC_SAT: // saturation 1940 { 1941 if (under) 1942 o_set_low(x, enc); 1943 else 1944 o_set_high(x, x2, enc); 1945 break; 1946 } 1947 case SC_SAT_SYM: // symmetrical saturation 1948 { 1949 if (under) { 1950 if (enc == SC_TC_) 1951 o_set_high(x, x2, SC_TC_, -1); 1952 else 1953 o_set_low(x, SC_US_); 1954 } else { 1955 o_set_high(x, x2, enc); 1956 } 1957 break; 1958 } 1959 case SC_SAT_ZERO: // saturation to zero 1960 { 1961 set_zero(); 1962 break; 1963 } 1964 case SC_WRAP_SM: // sign magnitude wrap-around 1965 { 1966 SC_ERROR_IF_(enc == SC_US_,
|
1967 1968 int n_bits = params.n_bits(); 1969 1970 if (n_bits == 0) { 1971 scfx_index x4 = calc_indices(params.iwl()); 1972 1973 if (x4.wi() >= size()) 1974 resize_to(x4.wi() + 1, 1); 1975 1976 toggle_tc(); 1977 if (o_bit_at(x4) != o_bit_at(x)) 1978 o_invert(x2); 1979 o_extend(x, SC_TC_); 1980 toggle_tc(); 1981 } else if (n_bits == 1) { 1982 toggle_tc(); 1983 if (is_neg() != o_bit_at(x)) 1984 o_invert(x2); 1985 o_extend(x, SC_TC_); 1986 toggle_tc(); 1987 } else if (n_bits < params.wl()) { 1988 scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits); 1989 scfx_index x4 = calc_indices(params.iwl() - n_bits); 1990 1991 // wrap-around least significant 'wl - n_bits' bits; 1992 // saturate most significant 'n_bits' bits 1993 toggle_tc(); 1994 if (is_neg() == o_bit_at(x4)) 1995 o_invert(x2); 1996 o_set(x, x3, SC_TC_, under); 1997 o_extend(x, SC_TC_); 1998 toggle_tc(); 1999 } else { 2000 if (under) 2001 o_set_low(x, SC_TC_); 2002 else 2003 o_set_high(x, x2, SC_TC_); 2004 } 2005 break; 2006 } 2007 default: 2008 ; 2009 } 2010 2011 find_sw(); 2012 } 2013} 2014 2015 2016// ---------------------------------------------------------------------------- 2017// PUBLIC METHOD : cast 2018// 2019// Performs a destructive cast operation on a scfx_rep. 2020// ---------------------------------------------------------------------------- 2021 2022void 2023scfx_rep::cast(const scfx_params ¶ms, bool &q_flag, bool &o_flag) 2024{ 2025 q_flag = false; 2026 o_flag = false; 2027 2028 // check for special cases 2029 if (is_zero()) { 2030 if (is_neg()) 2031 m_sign = 1; 2032 return; 2033 } 2034 2035 // perform casting 2036 quantization(params, q_flag); 2037 overflow(params, o_flag); 2038 2039 // check for special case: -0 2040 if (is_zero() && is_neg()) 2041 m_sign = 1; 2042} 2043 2044 2045// ---------------------------------------------------------------------------- 2046// make sure, the two mantissas are aligned 2047// ---------------------------------------------------------------------------- 2048 2049void 2050align(const scfx_rep &lhs, const scfx_rep &rhs, int &new_wp, 2051 int &len_mant, scfx_mant_ref &lhs_mant, scfx_mant_ref &rhs_mant) 2052{ 2053 bool need_lhs = true; 2054 bool need_rhs = true; 2055 2056 if (lhs.m_wp != rhs.m_wp || lhs.size() != rhs.size()) { 2057 int lower_bound_lhs = lhs.m_lsw - lhs.m_wp; 2058 int upper_bound_lhs = lhs.m_msw - lhs.m_wp; 2059 int lower_bound_rhs = rhs.m_lsw - rhs.m_wp; 2060 int upper_bound_rhs = rhs.m_msw - rhs.m_wp; 2061 2062 int lower_bound = sc_min(lower_bound_lhs, lower_bound_rhs); 2063 int upper_bound = sc_max(upper_bound_lhs, upper_bound_rhs); 2064 2065 new_wp = -lower_bound; 2066 len_mant = sc_max(min_mant, upper_bound - lower_bound + 1); 2067 2068 if (new_wp != lhs.m_wp || len_mant != lhs.size()) { 2069 lhs_mant = lhs.resize(len_mant, new_wp); 2070 need_lhs = false; 2071 } 2072 2073 if (new_wp != rhs.m_wp || len_mant != rhs.size()) { 2074 rhs_mant = rhs.resize(len_mant, new_wp); 2075 need_rhs = false; 2076 } 2077 } 2078 2079 if (need_lhs) { 2080 lhs_mant = lhs.m_mant; 2081 } 2082 2083 if (need_rhs) { 2084 rhs_mant = rhs.m_mant; 2085 } 2086} 2087 2088 2089// ---------------------------------------------------------------------------- 2090// compare two mantissas 2091// ---------------------------------------------------------------------------- 2092 2093int 2094compare_msw_ff(const scfx_rep &lhs, const scfx_rep &rhs) 2095{ 2096 // special case: rhs.m_mant[rhs.m_msw + 1] == 1 2097 if (rhs.m_msw < rhs.size() - 1 && rhs.m_mant[rhs.m_msw + 1 ] != 0) { 2098 return -1; 2099 } 2100 2101 int lhs_size = lhs.m_msw - lhs.m_lsw + 1; 2102 int rhs_size = rhs.m_msw - rhs.m_lsw + 1; 2103 2104 int size = sc_min(lhs_size, rhs_size); 2105 2106 int lhs_index = lhs.m_msw; 2107 int rhs_index = rhs.m_msw; 2108 2109 int i; 2110 2111 for (i = 0; 2112 i < size && lhs.m_mant[lhs_index] == rhs.m_mant[rhs_index]; 2113 i++) { 2114 lhs_index--; 2115 rhs_index--; 2116 } 2117 2118 if (i == size) { 2119 if (lhs_size == rhs_size) { 2120 return 0; 2121 } 2122 2123 if (lhs_size < rhs_size) { 2124 return -1; 2125 } else { 2126 return 1; 2127 } 2128 } 2129 2130 if (lhs.m_mant[lhs_index] < rhs.m_mant[rhs_index]) { 2131 return -1; 2132 } else { 2133 return 1; 2134 } 2135} 2136 2137 2138// ---------------------------------------------------------------------------- 2139// divide the mantissa by ten 2140// ---------------------------------------------------------------------------- 2141 2142unsigned int 2143scfx_rep::divide_by_ten() 2144{ 2145#if defined(SC_BOOST_BIG_ENDIAN) 2146 half_word *hw = (half_word *)&m_mant[m_msw]; 2147#elif defined(SC_BOOST_LITTLE_ENDIAN) 2148 half_word *hw = ((half_word *)&m_mant[m_msw]) + 1; 2149#endif 2150 2151 unsigned int remainder = 0; 2152 2153 word_short ls; 2154 ls.l = 0; 2155 2156#if defined(SC_BOOST_BIG_ENDIAN) 2157 for (int i = 0, end = (m_msw - m_wp + 1) * 2; i < end; i++) { 2158#elif defined(SC_BOOST_LITTLE_ENDIAN) 2159 for (int i = 0, end = -(m_msw - m_wp + 1) * 2; i > end; i--) { 2160#endif 2161 ls.s.u = static_cast<half_word>(remainder); 2162 ls.s.l = hw[i]; 2163 remainder = ls.l % 10; 2164 ls.l /= 10; 2165 hw[i] = ls.s.l; 2166 } 2167 2168 return remainder; 2169} 2170 2171 2172// ---------------------------------------------------------------------------- 2173// multiply the mantissa by ten 2174// ---------------------------------------------------------------------------- 2175 2176void 2177scfx_rep::multiply_by_ten() 2178{ 2179 int size = m_mant.size() + 1; 2180 2181 scfx_mant mant8(size); 2182 scfx_mant mant2(size); 2183 2184 size--; 2185 2186 mant8[size] = (m_mant[size - 1] >> (bits_in_word - 3)); 2187 mant2[size] = (m_mant[size - 1] >> (bits_in_word - 1)); 2188 2189 while (--size) { 2190 mant8[size] = (m_mant[size] << 3) | 2191 (m_mant[size - 1] >> (bits_in_word - 3)); 2192 mant2[size] = (m_mant[size] << 1) | 2193 (m_mant[size - 1] >> (bits_in_word - 1)); 2194 } 2195 2196 mant8[0] = (m_mant[0] << 3); 2197 mant2[0] = (m_mant[0] << 1); 2198 2199 add_mants(m_mant.size(), m_mant, mant8, mant2); 2200} 2201 2202 2203// ---------------------------------------------------------------------------- 2204// normalize 2205// ---------------------------------------------------------------------------- 2206 2207void 2208scfx_rep::normalize(int exponent) 2209{ 2210 int shift = exponent % bits_in_word; 2211 if (shift < 0) { 2212 shift += bits_in_word; 2213 } 2214 2215 if (shift) { 2216 shift_left(shift); 2217 } 2218 2219 find_sw(); 2220 2221 m_wp = (shift - exponent) / bits_in_word; 2222} 2223 2224 2225// ---------------------------------------------------------------------------- 2226// return a new mantissa that is aligned and resized 2227// ---------------------------------------------------------------------------- 2228 2229scfx_mant * 2230scfx_rep::resize(int new_size, int new_wp) const 2231{ 2232 scfx_mant *result = new scfx_mant(new_size); 2233 2234 result->clear(); 2235 2236 int shift = new_wp - m_wp; 2237 2238 for (int j = m_lsw; j <= m_msw; j++) { 2239 (*result)[j + shift] = m_mant[j]; 2240 } 2241 2242 return result; 2243} 2244 2245 2246// ---------------------------------------------------------------------------- 2247// set a single bit 2248// ---------------------------------------------------------------------------- 2249 2250void 2251scfx_rep::set_bin(int i) 2252{ 2253 m_mant[i >> 5] |= 1 << (i & 31); 2254} 2255 2256 2257// ---------------------------------------------------------------------------- 2258// set three bits 2259// ---------------------------------------------------------------------------- 2260 2261void 2262scfx_rep::set_oct(int i, int n) 2263{ 2264 if (n & 1) { 2265 m_mant[i >> 5] |= 1 << (i & 31); 2266 } 2267 i++; 2268 if (n & 2) { 2269 m_mant[i >> 5] |= 1 << (i & 31); 2270 } 2271 i++; 2272 if (n & 4) { 2273 m_mant[i >> 5] |= 1 << (i & 31); 2274 } 2275} 2276 2277 2278// ---------------------------------------------------------------------------- 2279// set four bits 2280// ---------------------------------------------------------------------------- 2281 2282void 2283scfx_rep::set_hex(int i, int n) 2284{ 2285 if (n & 1) { 2286 m_mant[i >> 5] |= 1 << (i & 31); 2287 } 2288 i++; 2289 if (n & 2) { 2290 m_mant[i >> 5] |= 1 << (i & 31); 2291 } 2292 i++; 2293 if (n & 4) { 2294 m_mant[i >> 5] |= 1 << (i & 31); 2295 } 2296 i++; 2297 if (n & 8) { 2298 m_mant[i >> 5] |= 1 << (i & 31); 2299 } 2300} 2301 2302 2303// ---------------------------------------------------------------------------- 2304// PRIVATE METHOD : shift_left 2305// 2306// Shifts a scfx_rep to the left by a MAXIMUM of bits_in_word - 1 bits. 2307// ---------------------------------------------------------------------------- 2308 2309void 2310scfx_rep::shift_left(int n) 2311{ 2312 if (n != 0) { 2313 int shift_left = n; 2314 int shift_right = bits_in_word - n; 2315 2316 SC_ASSERT_(!(m_mant[size() - 1] >> shift_right), 2317 "shift_left overflow"); 2318 2319 for (int i = size() - 1; i > 0; i--) { 2320 m_mant[i] = (m_mant[i] << shift_left) | 2321 (m_mant[i - 1] >> shift_right); 2322 } 2323 m_mant[0] <<= shift_left; 2324 } 2325} 2326 2327 2328// ---------------------------------------------------------------------------- 2329// PRIVATE METHOD : shift_right 2330// 2331// Shifts a scfx_rep to the right by a MAXIMUM of bits_in_word - 1 bits. 2332// ---------------------------------------------------------------------------- 2333 2334void 2335scfx_rep::shift_right(int n) 2336{ 2337 if (n != 0) { 2338 int shift_left = bits_in_word - n; 2339 int shift_right = n; 2340 2341 SC_ASSERT_(!(m_mant[0] << shift_left), "shift_right overflow"); 2342 2343 for (int i = 0; i < size() - 1; i++) { 2344 m_mant[i] = (m_mant[i] >> shift_right) | 2345 (m_mant[i + 1] << shift_left); 2346 } 2347 m_mant[size() - 1] >>= shift_right; 2348 } 2349} 2350 2351 2352// ---------------------------------------------------------------------------- 2353// METHOD : get_bit 2354// 2355// Tests a bit, in two's complement. 2356// ---------------------------------------------------------------------------- 2357 2358bool 2359scfx_rep::get_bit(int i) const 2360{ 2361 if (!is_normal()) 2362 return false; 2363 2364 scfx_index x = calc_indices(i); 2365 2366 if (x.wi() >= size()) 2367 return is_neg(); 2368 2369 if (x.wi() < 0) 2370 return false; 2371 2372 const_cast<scfx_rep*>(this)->toggle_tc(); 2373 2374 bool result = (m_mant[x.wi()] & (1 << x.bi())) != 0; 2375 2376 const_cast<scfx_rep *>(this)->toggle_tc(); 2377 2378 return result; 2379} 2380 2381 2382// ---------------------------------------------------------------------------- 2383// METHOD : set 2384// 2385// Sets a bit, in two's complement, between iwl-1 and -fwl. 2386// ---------------------------------------------------------------------------- 2387 2388bool 2389scfx_rep::set(int i, const scfx_params ¶ms) 2390{ 2391 if (!is_normal()) 2392 return false; 2393 2394 scfx_index x = calc_indices(i); 2395 2396 if (x.wi() >= size()) { 2397 if (is_neg()) 2398 return true; 2399 else 2400 resize_to(x.wi() + 1, 1); 2401 } else if (x.wi() < 0) { 2402 resize_to(size() - x.wi(), -1); 2403 x.wi(0); 2404 } 2405 2406 toggle_tc(); 2407 2408 m_mant[x.wi()] |= 1 << x.bi(); 2409 2410 if (i == params.iwl() - 1) 2411 o_extend(x, params.enc()); // sign extension 2412 2413 toggle_tc(); 2414 2415 find_sw(); 2416 2417 return true; 2418} 2419 2420 2421// ---------------------------------------------------------------------------- 2422// METHOD : clear 2423// 2424// Clears a bit, in two's complement, between iwl-1 and -fwl. 2425// ---------------------------------------------------------------------------- 2426 2427bool 2428scfx_rep::clear(int i, const scfx_params ¶ms) 2429{ 2430 if (!is_normal()) 2431 return false; 2432 2433 scfx_index x = calc_indices(i); 2434 2435 if (x.wi() >= size()) { 2436 if (!is_neg()) 2437 return true; 2438 else 2439 resize_to(x.wi() + 1, 1); 2440 } else if (x.wi() < 0) { 2441 return true; 2442 } 2443 2444 toggle_tc(); 2445 2446 m_mant[x.wi()] &= ~(1 << x.bi()); 2447 2448 if (i == params.iwl() - 1) 2449 o_extend(x, params.enc()); // sign extension 2450 2451 toggle_tc(); 2452 2453 find_sw(); 2454 2455 return true; 2456} 2457 2458 2459// ---------------------------------------------------------------------------- 2460// METHOD : get_slice 2461// ---------------------------------------------------------------------------- 2462 2463bool 2464scfx_rep::get_slice(int i, int j, const scfx_params &, sc_bv_base &bv) const 2465{ 2466 if (is_nan() || is_inf()) 2467 return false; 2468 2469 // get the bits 2470 2471 int l = j; 2472 for (int k = 0; k < bv.length(); ++k) { 2473 bv[k] = get_bit(l); 2474 2475 if (i >= j) 2476 ++l; 2477 else 2478 --l; 2479 } 2480 2481 return true; 2482} 2483 2484bool 2485scfx_rep::set_slice(int i, int j, const scfx_params ¶ms, 2486 const sc_bv_base &bv) 2487{ 2488 if (is_nan() || is_inf()) 2489 return false; 2490 2491 // set the bits 2492 int l = j; 2493 for (int k = 0; k < bv.length(); ++k) { 2494 if (bv[k].to_bool()) 2495 set(l, params); 2496 else 2497 clear(l, params); 2498 2499 if (i >= j) 2500 ++l; 2501 else 2502 --l; 2503 } 2504 2505 return true; 2506} 2507 2508 2509// ---------------------------------------------------------------------------- 2510// METHOD : print 2511// ---------------------------------------------------------------------------- 2512 2513void 2514scfx_rep::print(::std::ostream &os) const 2515{ 2516 os << to_string(SC_DEC, -1, SC_E); 2517} 2518 2519 2520// ---------------------------------------------------------------------------- 2521// METHOD : dump 2522// ---------------------------------------------------------------------------- 2523 2524void 2525scfx_rep::dump(::std::ostream &os) const 2526{ 2527 os << "scfx_rep" << ::std::endl; 2528 os << "(" << ::std::endl; 2529 2530 os << "mant =" << ::std::endl; 2531 for (int i = size() - 1; i >= 0; i--) { 2532 char buf[BUFSIZ]; 2533 std::sprintf(buf, " %d: %10u (%8x)", i, 2534 (int)m_mant[i], (int)m_mant[i]); 2535 os << buf << ::std::endl; 2536 } 2537 2538 os << "wp = " << m_wp << ::std::endl; 2539 os << "sign = " << m_sign << ::std::endl; 2540 2541 os << "state = "; 2542 switch (m_state) { 2543 case normal: 2544 os << "normal"; 2545 break; 2546 case infinity: 2547 os << "infinity"; 2548 break; 2549 case not_a_number: 2550 os << "not_a_number"; 2551 break; 2552 default: 2553 os << "unknown"; 2554 } 2555 os << ::std::endl; 2556 2557 os << "msw = " << m_msw << ::std::endl; 2558 os << "lsw = " << m_lsw << ::std::endl; 2559 2560 os << ")" << ::std::endl; 2561} 2562 2563 2564// ---------------------------------------------------------------------------- 2565// METHOD : get_type 2566// ---------------------------------------------------------------------------- 2567 2568void 2569scfx_rep::get_type(int &wl, int &iwl, sc_enc &enc) const 2570{ 2571 if (is_nan() || is_inf()) { 2572 wl = 0; 2573 iwl = 0; 2574 enc = SC_TC_; 2575 return; 2576 } 2577 2578 if (is_zero()) { 2579 wl = 1; 2580 iwl = 1; 2581 enc = SC_US_; 2582 return; 2583 } 2584 2585 int msb = (m_msw - m_wp) * bits_in_word + 2586 scfx_find_msb(m_mant[ m_msw ]) + 1; 2587 while (get_bit(msb) == get_bit(msb - 1)) { 2588 --msb; 2589 } 2590 2591 int lsb = (m_lsw - m_wp) * bits_in_word + 2592 scfx_find_lsb(m_mant[m_lsw]); 2593 2594 if (is_neg()) { 2595 wl = msb - lsb + 1; 2596 iwl = msb + 1; 2597 enc = SC_TC_; 2598 } else { 2599 wl = msb - lsb; 2600 iwl = msb; 2601 enc = SC_US_; 2602 } 2603} 2604 2605 2606// ---------------------------------------------------------------------------- 2607// PRIVATE METHOD : round 2608// 2609// Performs convergent rounding (rounding to even) as in floating-point. 2610// ---------------------------------------------------------------------------- 2611 2612void 2613scfx_rep::round(int wl) 2614{ 2615 // check for special cases 2616 2617 if (is_nan() || is_inf() || is_zero()) 2618 return; 2619 2620 // estimate effective wordlength and compare 2621 int wl_effective; 2622 wl_effective = (m_msw - m_lsw + 1) * bits_in_word; 2623 if (wl_effective <= wl) 2624 return; 2625 2626 // calculate effective wordlength and compare 2627 int msb = scfx_find_msb(m_mant[m_msw]); 2628 int lsb = scfx_find_lsb(m_mant[m_lsw]); 2629 wl_effective = (m_msw * bits_in_word + msb) - 2630 (m_lsw * bits_in_word + lsb) + 1; 2631 if (wl_effective <= wl) 2632 return; 2633 2634 // perform rounding 2635 int wi = m_msw - (wl - 1) / bits_in_word; 2636 int bi = msb - (wl - 1) % bits_in_word; 2637 if (bi < 0) { 2638 --wi; 2639 bi += bits_in_word; 2640 } 2641 2642 scfx_index x(wi, bi); 2643 2644 if ((q_bit(x) && ! q_zero(x)) || (q_bit(x) && q_zero(x) && q_odd(x))) { 2645 q_incr(x); 2646 } 2647 q_clear(x); 2648 2649 find_sw(); 2650 2651 m_r_flag = true; 2652} 2653 2654} // namespace sc_dt
| 1968 1969 int n_bits = params.n_bits(); 1970 1971 if (n_bits == 0) { 1972 scfx_index x4 = calc_indices(params.iwl()); 1973 1974 if (x4.wi() >= size()) 1975 resize_to(x4.wi() + 1, 1); 1976 1977 toggle_tc(); 1978 if (o_bit_at(x4) != o_bit_at(x)) 1979 o_invert(x2); 1980 o_extend(x, SC_TC_); 1981 toggle_tc(); 1982 } else if (n_bits == 1) { 1983 toggle_tc(); 1984 if (is_neg() != o_bit_at(x)) 1985 o_invert(x2); 1986 o_extend(x, SC_TC_); 1987 toggle_tc(); 1988 } else if (n_bits < params.wl()) { 1989 scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits); 1990 scfx_index x4 = calc_indices(params.iwl() - n_bits); 1991 1992 // wrap-around least significant 'wl - n_bits' bits; 1993 // saturate most significant 'n_bits' bits 1994 toggle_tc(); 1995 if (is_neg() == o_bit_at(x4)) 1996 o_invert(x2); 1997 o_set(x, x3, SC_TC_, under); 1998 o_extend(x, SC_TC_); 1999 toggle_tc(); 2000 } else { 2001 if (under) 2002 o_set_low(x, SC_TC_); 2003 else 2004 o_set_high(x, x2, SC_TC_); 2005 } 2006 break; 2007 } 2008 default: 2009 ; 2010 } 2011 2012 find_sw(); 2013 } 2014} 2015 2016 2017// ---------------------------------------------------------------------------- 2018// PUBLIC METHOD : cast 2019// 2020// Performs a destructive cast operation on a scfx_rep. 2021// ---------------------------------------------------------------------------- 2022 2023void 2024scfx_rep::cast(const scfx_params ¶ms, bool &q_flag, bool &o_flag) 2025{ 2026 q_flag = false; 2027 o_flag = false; 2028 2029 // check for special cases 2030 if (is_zero()) { 2031 if (is_neg()) 2032 m_sign = 1; 2033 return; 2034 } 2035 2036 // perform casting 2037 quantization(params, q_flag); 2038 overflow(params, o_flag); 2039 2040 // check for special case: -0 2041 if (is_zero() && is_neg()) 2042 m_sign = 1; 2043} 2044 2045 2046// ---------------------------------------------------------------------------- 2047// make sure, the two mantissas are aligned 2048// ---------------------------------------------------------------------------- 2049 2050void 2051align(const scfx_rep &lhs, const scfx_rep &rhs, int &new_wp, 2052 int &len_mant, scfx_mant_ref &lhs_mant, scfx_mant_ref &rhs_mant) 2053{ 2054 bool need_lhs = true; 2055 bool need_rhs = true; 2056 2057 if (lhs.m_wp != rhs.m_wp || lhs.size() != rhs.size()) { 2058 int lower_bound_lhs = lhs.m_lsw - lhs.m_wp; 2059 int upper_bound_lhs = lhs.m_msw - lhs.m_wp; 2060 int lower_bound_rhs = rhs.m_lsw - rhs.m_wp; 2061 int upper_bound_rhs = rhs.m_msw - rhs.m_wp; 2062 2063 int lower_bound = sc_min(lower_bound_lhs, lower_bound_rhs); 2064 int upper_bound = sc_max(upper_bound_lhs, upper_bound_rhs); 2065 2066 new_wp = -lower_bound; 2067 len_mant = sc_max(min_mant, upper_bound - lower_bound + 1); 2068 2069 if (new_wp != lhs.m_wp || len_mant != lhs.size()) { 2070 lhs_mant = lhs.resize(len_mant, new_wp); 2071 need_lhs = false; 2072 } 2073 2074 if (new_wp != rhs.m_wp || len_mant != rhs.size()) { 2075 rhs_mant = rhs.resize(len_mant, new_wp); 2076 need_rhs = false; 2077 } 2078 } 2079 2080 if (need_lhs) { 2081 lhs_mant = lhs.m_mant; 2082 } 2083 2084 if (need_rhs) { 2085 rhs_mant = rhs.m_mant; 2086 } 2087} 2088 2089 2090// ---------------------------------------------------------------------------- 2091// compare two mantissas 2092// ---------------------------------------------------------------------------- 2093 2094int 2095compare_msw_ff(const scfx_rep &lhs, const scfx_rep &rhs) 2096{ 2097 // special case: rhs.m_mant[rhs.m_msw + 1] == 1 2098 if (rhs.m_msw < rhs.size() - 1 && rhs.m_mant[rhs.m_msw + 1 ] != 0) { 2099 return -1; 2100 } 2101 2102 int lhs_size = lhs.m_msw - lhs.m_lsw + 1; 2103 int rhs_size = rhs.m_msw - rhs.m_lsw + 1; 2104 2105 int size = sc_min(lhs_size, rhs_size); 2106 2107 int lhs_index = lhs.m_msw; 2108 int rhs_index = rhs.m_msw; 2109 2110 int i; 2111 2112 for (i = 0; 2113 i < size && lhs.m_mant[lhs_index] == rhs.m_mant[rhs_index]; 2114 i++) { 2115 lhs_index--; 2116 rhs_index--; 2117 } 2118 2119 if (i == size) { 2120 if (lhs_size == rhs_size) { 2121 return 0; 2122 } 2123 2124 if (lhs_size < rhs_size) { 2125 return -1; 2126 } else { 2127 return 1; 2128 } 2129 } 2130 2131 if (lhs.m_mant[lhs_index] < rhs.m_mant[rhs_index]) { 2132 return -1; 2133 } else { 2134 return 1; 2135 } 2136} 2137 2138 2139// ---------------------------------------------------------------------------- 2140// divide the mantissa by ten 2141// ---------------------------------------------------------------------------- 2142 2143unsigned int 2144scfx_rep::divide_by_ten() 2145{ 2146#if defined(SC_BOOST_BIG_ENDIAN) 2147 half_word *hw = (half_word *)&m_mant[m_msw]; 2148#elif defined(SC_BOOST_LITTLE_ENDIAN) 2149 half_word *hw = ((half_word *)&m_mant[m_msw]) + 1; 2150#endif 2151 2152 unsigned int remainder = 0; 2153 2154 word_short ls; 2155 ls.l = 0; 2156 2157#if defined(SC_BOOST_BIG_ENDIAN) 2158 for (int i = 0, end = (m_msw - m_wp + 1) * 2; i < end; i++) { 2159#elif defined(SC_BOOST_LITTLE_ENDIAN) 2160 for (int i = 0, end = -(m_msw - m_wp + 1) * 2; i > end; i--) { 2161#endif 2162 ls.s.u = static_cast<half_word>(remainder); 2163 ls.s.l = hw[i]; 2164 remainder = ls.l % 10; 2165 ls.l /= 10; 2166 hw[i] = ls.s.l; 2167 } 2168 2169 return remainder; 2170} 2171 2172 2173// ---------------------------------------------------------------------------- 2174// multiply the mantissa by ten 2175// ---------------------------------------------------------------------------- 2176 2177void 2178scfx_rep::multiply_by_ten() 2179{ 2180 int size = m_mant.size() + 1; 2181 2182 scfx_mant mant8(size); 2183 scfx_mant mant2(size); 2184 2185 size--; 2186 2187 mant8[size] = (m_mant[size - 1] >> (bits_in_word - 3)); 2188 mant2[size] = (m_mant[size - 1] >> (bits_in_word - 1)); 2189 2190 while (--size) { 2191 mant8[size] = (m_mant[size] << 3) | 2192 (m_mant[size - 1] >> (bits_in_word - 3)); 2193 mant2[size] = (m_mant[size] << 1) | 2194 (m_mant[size - 1] >> (bits_in_word - 1)); 2195 } 2196 2197 mant8[0] = (m_mant[0] << 3); 2198 mant2[0] = (m_mant[0] << 1); 2199 2200 add_mants(m_mant.size(), m_mant, mant8, mant2); 2201} 2202 2203 2204// ---------------------------------------------------------------------------- 2205// normalize 2206// ---------------------------------------------------------------------------- 2207 2208void 2209scfx_rep::normalize(int exponent) 2210{ 2211 int shift = exponent % bits_in_word; 2212 if (shift < 0) { 2213 shift += bits_in_word; 2214 } 2215 2216 if (shift) { 2217 shift_left(shift); 2218 } 2219 2220 find_sw(); 2221 2222 m_wp = (shift - exponent) / bits_in_word; 2223} 2224 2225 2226// ---------------------------------------------------------------------------- 2227// return a new mantissa that is aligned and resized 2228// ---------------------------------------------------------------------------- 2229 2230scfx_mant * 2231scfx_rep::resize(int new_size, int new_wp) const 2232{ 2233 scfx_mant *result = new scfx_mant(new_size); 2234 2235 result->clear(); 2236 2237 int shift = new_wp - m_wp; 2238 2239 for (int j = m_lsw; j <= m_msw; j++) { 2240 (*result)[j + shift] = m_mant[j]; 2241 } 2242 2243 return result; 2244} 2245 2246 2247// ---------------------------------------------------------------------------- 2248// set a single bit 2249// ---------------------------------------------------------------------------- 2250 2251void 2252scfx_rep::set_bin(int i) 2253{ 2254 m_mant[i >> 5] |= 1 << (i & 31); 2255} 2256 2257 2258// ---------------------------------------------------------------------------- 2259// set three bits 2260// ---------------------------------------------------------------------------- 2261 2262void 2263scfx_rep::set_oct(int i, int n) 2264{ 2265 if (n & 1) { 2266 m_mant[i >> 5] |= 1 << (i & 31); 2267 } 2268 i++; 2269 if (n & 2) { 2270 m_mant[i >> 5] |= 1 << (i & 31); 2271 } 2272 i++; 2273 if (n & 4) { 2274 m_mant[i >> 5] |= 1 << (i & 31); 2275 } 2276} 2277 2278 2279// ---------------------------------------------------------------------------- 2280// set four bits 2281// ---------------------------------------------------------------------------- 2282 2283void 2284scfx_rep::set_hex(int i, int n) 2285{ 2286 if (n & 1) { 2287 m_mant[i >> 5] |= 1 << (i & 31); 2288 } 2289 i++; 2290 if (n & 2) { 2291 m_mant[i >> 5] |= 1 << (i & 31); 2292 } 2293 i++; 2294 if (n & 4) { 2295 m_mant[i >> 5] |= 1 << (i & 31); 2296 } 2297 i++; 2298 if (n & 8) { 2299 m_mant[i >> 5] |= 1 << (i & 31); 2300 } 2301} 2302 2303 2304// ---------------------------------------------------------------------------- 2305// PRIVATE METHOD : shift_left 2306// 2307// Shifts a scfx_rep to the left by a MAXIMUM of bits_in_word - 1 bits. 2308// ---------------------------------------------------------------------------- 2309 2310void 2311scfx_rep::shift_left(int n) 2312{ 2313 if (n != 0) { 2314 int shift_left = n; 2315 int shift_right = bits_in_word - n; 2316 2317 SC_ASSERT_(!(m_mant[size() - 1] >> shift_right), 2318 "shift_left overflow"); 2319 2320 for (int i = size() - 1; i > 0; i--) { 2321 m_mant[i] = (m_mant[i] << shift_left) | 2322 (m_mant[i - 1] >> shift_right); 2323 } 2324 m_mant[0] <<= shift_left; 2325 } 2326} 2327 2328 2329// ---------------------------------------------------------------------------- 2330// PRIVATE METHOD : shift_right 2331// 2332// Shifts a scfx_rep to the right by a MAXIMUM of bits_in_word - 1 bits. 2333// ---------------------------------------------------------------------------- 2334 2335void 2336scfx_rep::shift_right(int n) 2337{ 2338 if (n != 0) { 2339 int shift_left = bits_in_word - n; 2340 int shift_right = n; 2341 2342 SC_ASSERT_(!(m_mant[0] << shift_left), "shift_right overflow"); 2343 2344 for (int i = 0; i < size() - 1; i++) { 2345 m_mant[i] = (m_mant[i] >> shift_right) | 2346 (m_mant[i + 1] << shift_left); 2347 } 2348 m_mant[size() - 1] >>= shift_right; 2349 } 2350} 2351 2352 2353// ---------------------------------------------------------------------------- 2354// METHOD : get_bit 2355// 2356// Tests a bit, in two's complement. 2357// ---------------------------------------------------------------------------- 2358 2359bool 2360scfx_rep::get_bit(int i) const 2361{ 2362 if (!is_normal()) 2363 return false; 2364 2365 scfx_index x = calc_indices(i); 2366 2367 if (x.wi() >= size()) 2368 return is_neg(); 2369 2370 if (x.wi() < 0) 2371 return false; 2372 2373 const_cast<scfx_rep*>(this)->toggle_tc(); 2374 2375 bool result = (m_mant[x.wi()] & (1 << x.bi())) != 0; 2376 2377 const_cast<scfx_rep *>(this)->toggle_tc(); 2378 2379 return result; 2380} 2381 2382 2383// ---------------------------------------------------------------------------- 2384// METHOD : set 2385// 2386// Sets a bit, in two's complement, between iwl-1 and -fwl. 2387// ---------------------------------------------------------------------------- 2388 2389bool 2390scfx_rep::set(int i, const scfx_params ¶ms) 2391{ 2392 if (!is_normal()) 2393 return false; 2394 2395 scfx_index x = calc_indices(i); 2396 2397 if (x.wi() >= size()) { 2398 if (is_neg()) 2399 return true; 2400 else 2401 resize_to(x.wi() + 1, 1); 2402 } else if (x.wi() < 0) { 2403 resize_to(size() - x.wi(), -1); 2404 x.wi(0); 2405 } 2406 2407 toggle_tc(); 2408 2409 m_mant[x.wi()] |= 1 << x.bi(); 2410 2411 if (i == params.iwl() - 1) 2412 o_extend(x, params.enc()); // sign extension 2413 2414 toggle_tc(); 2415 2416 find_sw(); 2417 2418 return true; 2419} 2420 2421 2422// ---------------------------------------------------------------------------- 2423// METHOD : clear 2424// 2425// Clears a bit, in two's complement, between iwl-1 and -fwl. 2426// ---------------------------------------------------------------------------- 2427 2428bool 2429scfx_rep::clear(int i, const scfx_params ¶ms) 2430{ 2431 if (!is_normal()) 2432 return false; 2433 2434 scfx_index x = calc_indices(i); 2435 2436 if (x.wi() >= size()) { 2437 if (!is_neg()) 2438 return true; 2439 else 2440 resize_to(x.wi() + 1, 1); 2441 } else if (x.wi() < 0) { 2442 return true; 2443 } 2444 2445 toggle_tc(); 2446 2447 m_mant[x.wi()] &= ~(1 << x.bi()); 2448 2449 if (i == params.iwl() - 1) 2450 o_extend(x, params.enc()); // sign extension 2451 2452 toggle_tc(); 2453 2454 find_sw(); 2455 2456 return true; 2457} 2458 2459 2460// ---------------------------------------------------------------------------- 2461// METHOD : get_slice 2462// ---------------------------------------------------------------------------- 2463 2464bool 2465scfx_rep::get_slice(int i, int j, const scfx_params &, sc_bv_base &bv) const 2466{ 2467 if (is_nan() || is_inf()) 2468 return false; 2469 2470 // get the bits 2471 2472 int l = j; 2473 for (int k = 0; k < bv.length(); ++k) { 2474 bv[k] = get_bit(l); 2475 2476 if (i >= j) 2477 ++l; 2478 else 2479 --l; 2480 } 2481 2482 return true; 2483} 2484 2485bool 2486scfx_rep::set_slice(int i, int j, const scfx_params ¶ms, 2487 const sc_bv_base &bv) 2488{ 2489 if (is_nan() || is_inf()) 2490 return false; 2491 2492 // set the bits 2493 int l = j; 2494 for (int k = 0; k < bv.length(); ++k) { 2495 if (bv[k].to_bool()) 2496 set(l, params); 2497 else 2498 clear(l, params); 2499 2500 if (i >= j) 2501 ++l; 2502 else 2503 --l; 2504 } 2505 2506 return true; 2507} 2508 2509 2510// ---------------------------------------------------------------------------- 2511// METHOD : print 2512// ---------------------------------------------------------------------------- 2513 2514void 2515scfx_rep::print(::std::ostream &os) const 2516{ 2517 os << to_string(SC_DEC, -1, SC_E); 2518} 2519 2520 2521// ---------------------------------------------------------------------------- 2522// METHOD : dump 2523// ---------------------------------------------------------------------------- 2524 2525void 2526scfx_rep::dump(::std::ostream &os) const 2527{ 2528 os << "scfx_rep" << ::std::endl; 2529 os << "(" << ::std::endl; 2530 2531 os << "mant =" << ::std::endl; 2532 for (int i = size() - 1; i >= 0; i--) { 2533 char buf[BUFSIZ]; 2534 std::sprintf(buf, " %d: %10u (%8x)", i, 2535 (int)m_mant[i], (int)m_mant[i]); 2536 os << buf << ::std::endl; 2537 } 2538 2539 os << "wp = " << m_wp << ::std::endl; 2540 os << "sign = " << m_sign << ::std::endl; 2541 2542 os << "state = "; 2543 switch (m_state) { 2544 case normal: 2545 os << "normal"; 2546 break; 2547 case infinity: 2548 os << "infinity"; 2549 break; 2550 case not_a_number: 2551 os << "not_a_number"; 2552 break; 2553 default: 2554 os << "unknown"; 2555 } 2556 os << ::std::endl; 2557 2558 os << "msw = " << m_msw << ::std::endl; 2559 os << "lsw = " << m_lsw << ::std::endl; 2560 2561 os << ")" << ::std::endl; 2562} 2563 2564 2565// ---------------------------------------------------------------------------- 2566// METHOD : get_type 2567// ---------------------------------------------------------------------------- 2568 2569void 2570scfx_rep::get_type(int &wl, int &iwl, sc_enc &enc) const 2571{ 2572 if (is_nan() || is_inf()) { 2573 wl = 0; 2574 iwl = 0; 2575 enc = SC_TC_; 2576 return; 2577 } 2578 2579 if (is_zero()) { 2580 wl = 1; 2581 iwl = 1; 2582 enc = SC_US_; 2583 return; 2584 } 2585 2586 int msb = (m_msw - m_wp) * bits_in_word + 2587 scfx_find_msb(m_mant[ m_msw ]) + 1; 2588 while (get_bit(msb) == get_bit(msb - 1)) { 2589 --msb; 2590 } 2591 2592 int lsb = (m_lsw - m_wp) * bits_in_word + 2593 scfx_find_lsb(m_mant[m_lsw]); 2594 2595 if (is_neg()) { 2596 wl = msb - lsb + 1; 2597 iwl = msb + 1; 2598 enc = SC_TC_; 2599 } else { 2600 wl = msb - lsb; 2601 iwl = msb; 2602 enc = SC_US_; 2603 } 2604} 2605 2606 2607// ---------------------------------------------------------------------------- 2608// PRIVATE METHOD : round 2609// 2610// Performs convergent rounding (rounding to even) as in floating-point. 2611// ---------------------------------------------------------------------------- 2612 2613void 2614scfx_rep::round(int wl) 2615{ 2616 // check for special cases 2617 2618 if (is_nan() || is_inf() || is_zero()) 2619 return; 2620 2621 // estimate effective wordlength and compare 2622 int wl_effective; 2623 wl_effective = (m_msw - m_lsw + 1) * bits_in_word; 2624 if (wl_effective <= wl) 2625 return; 2626 2627 // calculate effective wordlength and compare 2628 int msb = scfx_find_msb(m_mant[m_msw]); 2629 int lsb = scfx_find_lsb(m_mant[m_lsw]); 2630 wl_effective = (m_msw * bits_in_word + msb) - 2631 (m_lsw * bits_in_word + lsb) + 1; 2632 if (wl_effective <= wl) 2633 return; 2634 2635 // perform rounding 2636 int wi = m_msw - (wl - 1) / bits_in_word; 2637 int bi = msb - (wl - 1) % bits_in_word; 2638 if (bi < 0) { 2639 --wi; 2640 bi += bits_in_word; 2641 } 2642 2643 scfx_index x(wi, bi); 2644 2645 if ((q_bit(x) && ! q_zero(x)) || (q_bit(x) && q_zero(x) && q_odd(x))) { 2646 q_incr(x); 2647 } 2648 q_clear(x); 2649 2650 find_sw(); 2651 2652 m_r_flag = true; 2653} 2654 2655} // namespace sc_dt
|