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