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