scfx_rep.cc revision 13322
1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20/***************************************************************************** 21 22 scfx_rep.cpp - 23 24 Original Author: Robert Graulich, Synopsys, Inc. 25 Martin Janssen, Synopsys, Inc. 26 27 *****************************************************************************/ 28 29/***************************************************************************** 30 31 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 32 changes you are making here. 33 34 Name, Affiliation, Date: 35 Description of Modification: 36 37 *****************************************************************************/ 38 39 40// $Log: scfx_rep.cpp,v $ 41// Revision 1.4 2011/08/24 22:05:43 acg 42// Torsten Maehne: initialization changes to remove warnings. 43// 44// Revision 1.3 2011/08/15 16:43:24 acg 45// Torsten Maehne: changes to remove unused argument warnings. 46// 47// Revision 1.2 2009/02/28 00:26:20 acg 48// Andy Goodrich: bug fixes. 49// 50// Revision 1.2 2008/11/06 17:22:47 acg 51// Andy Goodrich: bug fixes for 2.2.1. 52// 53// Revision 1.1.1.1 2006/12/15 20:31:36 acg 54// SystemC 2.2 55// 56// Revision 1.3 2006/01/13 18:53:58 acg 57// Andy Goodrich: added $Log command so that CVS comments are reproduced in 58// the source. 59// 60 61#include <cctype> 62#include <cmath> 63#include <cstdio> 64#include <cstdlib> 65 66#include "base/compiler.hh" 67#include "systemc/ext/dt/bit/sc_bv_base.hh" 68#include "systemc/ext/dt/bit/sc_lv_base.hh" 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_, 1966 "SC_WRAP_SM not defined for unsigned numbers"); 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 2655