sc_nbutils.h revision 12027
1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20/***************************************************************************** 21 22 sc_nbutils.h -- External and friend functions for both sc_signed and 23 sc_unsigned classes. 24 25 Original Author: Ali Dasdan, Synopsys, Inc. 26 27 *****************************************************************************/ 28 29/***************************************************************************** 30 31 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 32 changes you are making here. 33 34 Name, Affiliation, Date: 35 Description of Modification: 36 37 *****************************************************************************/ 38 39// $Log: sc_nbutils.h,v $ 40// Revision 1.6 2011/09/08 16:12:15 acg 41// Philipp A. Hartmann: fix issue with Sun machines wrt real math libraries. 42// 43// Revision 1.5 2011/08/26 23:00:01 acg 44// Torsten Maehne: remove use of ieeefp.h. 45// 46// Revision 1.4 2011/08/15 16:43:24 acg 47// Torsten Maehne: changes to remove unused argument warnings. 48// 49// Revision 1.3 2011/02/18 20:19:15 acg 50// Andy Goodrich: updating Copyright notice. 51// 52// Revision 1.2 2010/09/06 16:35:48 acg 53// Andy Goodrich: changed i386 to __i386__ in ifdef's. 54// 55// Revision 1.1.1.1 2006/12/15 20:20:05 acg 56// SystemC 2.3 57// 58// Revision 1.3 2006/01/13 18:49:32 acg 59// Added $Log command so that CVS check in comments are reproduced in the 60// source. 61// 62 63#ifndef SC_NBUTILS_H 64#define SC_NBUTILS_H 65 66#include <cmath> 67#include <limits> 68 69#include "sysc/datatypes/bit/sc_bit_ids.h" 70#include "sysc/datatypes/int/sc_int_ids.h" 71#include "sysc/datatypes/int/sc_nbdefs.h" 72#include "sysc/utils/sc_report.h" 73 74 75namespace sc_dt 76{ 77 78//----------------------------------------------------------------------------- 79//"sc_io_base" 80// 81// This inline function returns the type of an i/o stream's base as a SystemC 82// base designator. 83// stream_object = reference to the i/o stream whose base is to be returned. 84// 85//"sc_io_show_base" 86// 87// This inline function returns true if the base should be shown when a SystemC 88// value is displayed via the supplied stream operator. 89// stream_object = reference to the i/o stream to return showbase value for. 90//----------------------------------------------------------------------------- 91#if defined(__GNUC__) || defined(_MSC_VER) || defined(__SUNPRO_CC) 92 inline sc_numrep 93 sc_io_base( systemc_ostream& os, sc_numrep def_base ) 94 { 95 std::ios::fmtflags flags = os.flags() & std::ios::basefield; 96 if ( flags & ::std::ios::dec ) return SC_DEC; 97 if ( flags & ::std::ios::hex ) return SC_HEX; 98 if ( flags & ::std::ios::oct ) return SC_OCT; 99 return def_base; 100 } 101 102 inline bool 103 sc_io_show_base( systemc_ostream& os ) 104 { 105 return (os.flags() & ::std::ios::showbase) != 0 ; 106 } 107#else // Other 108 inline sc_numrep 109 sc_io_base( systemc_ostream& /*unused*/, sc_numrep /*unused*/ ) 110 { 111 return SC_DEC; 112 } 113 inline bool 114 sc_io_show_base( systemc_ostream& /*unused*/ ) 115 { 116 return false; 117 } 118#endif 119 120const std::string to_string( sc_numrep ); 121 122inline 123systemc_ostream& 124operator << ( systemc_ostream& os, sc_numrep numrep ) 125{ 126 os << to_string( numrep ); 127 return os; 128} 129 130// only used within vec_from_str (non-standard, deprecated) 131inline void 132is_valid_base(sc_numrep base) 133{ 134 switch (base) { 135 case SC_NOBASE: case SC_BIN: 136 case SC_OCT: case SC_DEC: 137 case SC_HEX: 138 break; 139 case SC_BIN_US: case SC_BIN_SM: 140 case SC_OCT_US: case SC_OCT_SM: 141 case SC_HEX_US: case SC_HEX_SM: 142 case SC_CSD: 143 SC_REPORT_ERROR( sc_core::SC_ID_NOT_IMPLEMENTED_, 144 "is_valid_base( sc_numrep base ) : " 145 "bases SC_CSD, or ending in _US and _SM are not supported" ); 146 break; 147 default: 148 char msg[BUFSIZ]; 149 std::sprintf( msg, "is_valid_base( sc_numrep base ) : " 150 "base = %s is not valid", 151 to_string( base ).c_str() ); 152 SC_REPORT_ERROR( sc_core::SC_ID_VALUE_NOT_VALID_, msg ); 153 } 154} 155 156// ---------------------------------------------------------------------------- 157 158// One transition of the FSM to find base and sign of a number. 159extern 160small_type 161fsm_move(char c, small_type &b, small_type &s, small_type &state); 162 163// Parse a character string into its equivalent binary bits. 164extern 165void parse_binary_bits( 166 const char* src_p, int dst_n, sc_digit* data_p, sc_digit* ctrl_p=0 167); 168 169 170// Parse a character string into its equivalent hexadecimal bits. 171extern 172void parse_hex_bits( 173 const char* src_p, int dst_n, sc_digit* data_p, sc_digit* ctrl_p=0 174); 175 176 177// Find the base and sign of a number in v. 178extern 179const char * 180get_base_and_sign(const char *v, small_type &base, small_type &sign); 181 182// Create a number out of v in base. 183extern 184small_type 185vec_from_str(int unb, int und, sc_digit *u, 186 const char *v, sc_numrep base = SC_NOBASE) ; 187 188 189// ---------------------------------------------------------------------------- 190// Naming convention for the vec_ functions below: 191// vec_OP(u, v, w) : computes w = u OP v. 192// vec_OP_on(u, v) : computes u = u OP v if u has more digits than v. 193// vec_OP_on2(u, v) : computes u = u OP v if u has fewer digits than v. 194// _large : parameters are vectors. 195// _small : one of the parameters is a single digit. 196// Xlen : the number of digits in X. 197// ---------------------------------------------------------------------------- 198 199// ---------------------------------------------------------------------------- 200// Functions for vector addition: w = u + v or u += v. 201// ---------------------------------------------------------------------------- 202 203extern 204void 205vec_add(int ulen, const sc_digit *u, 206 int vlen, const sc_digit *v, sc_digit *w); 207 208extern 209void 210vec_add_on(int ulen, sc_digit *u, 211 int vlen, const sc_digit *v); 212 213extern 214void 215vec_add_on2(int ulen, sc_digit *u, 216 int vlen, const sc_digit *v); 217 218extern 219void 220vec_add_small(int ulen, const sc_digit *u, 221 sc_digit v, sc_digit *w); 222 223extern 224void 225vec_add_small_on(int ulen, sc_digit *u, sc_digit v); 226 227 228// ---------------------------------------------------------------------------- 229// Functions for vector subtraction: w = u - v, u -= v, or u = v - u. 230// ---------------------------------------------------------------------------- 231 232extern 233void 234vec_sub(int ulen, const sc_digit *u, 235 int vlen, const sc_digit *v, sc_digit *w); 236 237extern 238void 239vec_sub_on(int ulen, sc_digit *u, 240 int vlen, const sc_digit *v); 241 242extern 243void 244vec_sub_on2(int ulen, sc_digit *u, 245 int vlen, const sc_digit *v); 246 247extern 248void 249vec_sub_small(int ulen, const sc_digit *u, 250 sc_digit v, sc_digit *w); 251 252extern 253void 254vec_sub_small_on(int ulen, sc_digit *u, sc_digit v); 255 256 257// ---------------------------------------------------------------------------- 258// Functions for vector multiplication: w = u * v or u *= v. 259// ---------------------------------------------------------------------------- 260 261extern 262void 263vec_mul(int ulen, const sc_digit *u, 264 int vlen, const sc_digit *v, sc_digit *w); 265 266extern 267void 268vec_mul_small(int ulen, const sc_digit *u, 269 sc_digit v, sc_digit *w); 270 271extern 272void 273vec_mul_small_on(int ulen, sc_digit *u, sc_digit v); 274 275 276// ---------------------------------------------------------------------------- 277// Functions for vector division: w = u / v. 278// ---------------------------------------------------------------------------- 279 280extern 281void 282vec_div_large(int ulen, const sc_digit *u, 283 int vlen, const sc_digit *v, sc_digit *w); 284 285extern 286void 287vec_div_small(int ulen, const sc_digit *u, 288 sc_digit v, sc_digit *w); 289 290 291// ---------------------------------------------------------------------------- 292// Functions for vector remainder: w = u % v or u %= v. 293// ---------------------------------------------------------------------------- 294 295extern 296void 297vec_rem_large(int ulen, const sc_digit *u, 298 int vlen, const sc_digit *v, sc_digit *w); 299 300extern 301sc_digit 302vec_rem_small(int ulen, const sc_digit *u, sc_digit v); 303 304extern 305sc_digit 306vec_rem_on_small(int ulen, sc_digit *u, sc_digit v); 307 308 309// ---------------------------------------------------------------------------- 310// Functions to convert between vectors of char and sc_digit. 311// ---------------------------------------------------------------------------- 312 313extern 314int 315vec_to_char(int ulen, const sc_digit *u, 316 int vlen, uchar *v); 317 318extern 319void 320vec_from_char(int ulen, const uchar *u, 321 int vlen, sc_digit *v); 322 323 324// ---------------------------------------------------------------------------- 325// Functions to shift left or right, or to create a mirror image of vectors. 326// ---------------------------------------------------------------------------- 327 328extern 329void 330vec_shift_left(int ulen, sc_digit *u, int nsl); 331 332extern 333void 334vec_shift_right(int vlen, sc_digit *u, int nsr, sc_digit fill = 0); 335 336extern 337void 338vec_reverse(int unb, int und, sc_digit *ud, 339 int l, int r = 0); 340 341 342// ---------------------------------------------------------------------------- 343// Various utility functions. 344// ---------------------------------------------------------------------------- 345 346// Return the low half part of d. 347inline 348sc_digit 349low_half(sc_digit d) 350{ 351 return (d & HALF_DIGIT_MASK); 352} 353 354// Return the high half part of d. The high part of the digit may have 355// more bits than BITS_PER_HALF_DIGIT due to, e.g., overflow in the 356// multiplication. Hence, in other functions that use high_half(), 357// make sure that the result contains BITS_PER_HALF_DIGIT if 358// necessary. This is done by high_half_masked(). 359inline 360sc_digit 361high_half(sc_digit d) 362{ 363 return (d >> BITS_PER_HALF_DIGIT); 364} 365 366inline 367sc_digit 368high_half_masked(sc_digit d) 369{ 370 return (high_half(d) & HALF_DIGIT_MASK); 371} 372 373// Concatenate the high part h and low part l. Assumes that h and l 374// are less than or equal to HALF_DIGIT_MASK; 375inline 376sc_digit 377concat(sc_digit h, sc_digit l) 378{ 379 return ((h << BITS_PER_HALF_DIGIT) | l); 380} 381 382// Create a number with n 1's. 383inline 384sc_digit 385one_and_ones(int n) 386{ 387 return (((sc_digit) 1 << n) - 1); 388} 389 390// Create a number with one 1 and n 0's. 391inline 392sc_digit 393one_and_zeros(int n) 394{ 395 return ((sc_digit) 1 << n); 396} 397 398 399// ---------------------------------------------------------------------------- 400 401// Find the digit that bit i is in. 402inline 403int 404digit_ord(int i) 405{ 406 return (i / BITS_PER_DIGIT); 407} 408 409// Find the bit in digit_ord(i) that bit i corressponds to. 410inline 411int 412bit_ord(int i) 413{ 414 return (i % BITS_PER_DIGIT); 415} 416 417 418// ---------------------------------------------------------------------------- 419// Functions to compare, zero, complement vector(s). 420// ---------------------------------------------------------------------------- 421 422// Compare u and v and return r 423// r = 0 if u == v 424// r < 0 if u < v 425// r > 0 if u > v 426// - Assume that all the leading zero digits are already skipped. 427// - ulen and/or vlen can be zero. 428// - Every digit is less than or equal to DIGIT_MASK; 429inline 430int 431vec_cmp(int ulen, const sc_digit *u, 432 int vlen, const sc_digit *v) 433{ 434 435#ifdef DEBUG_SYSTEMC 436 // assert((ulen <= 0) || (u != NULL)); 437 // assert((vlen <= 0) || (v != NULL)); 438 439 // ulen and vlen can be equal to 0 because vec_cmp can be called 440 // after vec_skip_leading_zeros. 441 assert((ulen >= 0) && (u != NULL)); 442 assert((vlen >= 0) && (v != NULL)); 443 // If ulen > 0, then the leading digit of u must be non-zero. 444 assert((ulen <= 0) || (u[ulen - 1] != 0)); 445 assert((vlen <= 0) || (v[vlen - 1] != 0)); 446#endif 447 448 if (ulen != vlen) 449 return (ulen - vlen); 450 451 // ulen == vlen >= 1 452 while ((--ulen >= 0) && (u[ulen] == v[ulen])) 453 ; 454 455 if (ulen < 0) 456 return 0; 457 458#ifdef DEBUG_SYSTEMC 459 // Test to see if the result is wrong due to the presence of 460 // overflow bits. 461 assert((u[ulen] & DIGIT_MASK) != (v[ulen] & DIGIT_MASK)); 462#endif 463 464 return (int) (u[ulen] - v[ulen]); 465 466} 467 468// Find the index of the first non-zero digit. 469// - ulen (before) = the number of digits in u. 470// - the returned value = the index of the first non-zero digit. 471// A negative value of -1 indicates that every digit in u is zero. 472inline 473int 474vec_find_first_nonzero(int ulen, const sc_digit *u) 475{ 476 477#ifdef DEBUG_SYSTEMC 478 // assert((ulen <= 0) || (u != NULL)); 479 assert((ulen > 0) && (u != NULL)); 480#endif 481 482 while ((--ulen >= 0) && (! u[ulen])) 483 ; 484 485 return ulen; 486 487} 488 489// Skip all the leading zero digits. 490// - ulen (before) = the number of digits in u. 491// - the returned value = the number of non-zero digits in u. 492// - the returned value is non-negative. 493inline 494int 495vec_skip_leading_zeros(int ulen, const sc_digit *u) 496{ 497 498#ifdef DEBUG_SYSTEMC 499 // assert((ulen <= 0) || (u != NULL)); 500 assert((ulen > 0) && (u != NULL)); 501#endif 502 503 return (1 + vec_find_first_nonzero(ulen, u)); 504 505} 506 507// Compare u and v and return r 508// r = 0 if u == v 509// r < 0 if u < v 510// r > 0 if u > v 511inline 512int 513vec_skip_and_cmp(int ulen, const sc_digit *u, 514 int vlen, const sc_digit *v) 515{ 516 517#ifdef DEBUG_SYSTEMC 518 assert((ulen > 0) && (u != NULL)); 519 assert((vlen > 0) && (v != NULL)); 520#endif 521 522 ulen = vec_skip_leading_zeros(ulen, u); 523 vlen = vec_skip_leading_zeros(vlen, v); 524 // ulen and/or vlen can be equal to zero here. 525 return vec_cmp(ulen, u, vlen, v); 526 527} 528 529// Set u[i] = 0 where i = from ... (ulen - 1). 530inline 531void 532vec_zero(int from, int ulen, sc_digit *u) 533{ 534 535#ifdef DEBUG_SYSTEMC 536 assert((ulen > 0) && (u != NULL)); 537#endif 538 539 for(int i = from; i < ulen; i++) 540 u[i] = 0; 541 542} 543 544// Set u[i] = 0 where i = 0 .. (ulen - 1). 545inline 546void 547vec_zero(int ulen, sc_digit *u) 548{ 549 vec_zero(0, ulen, u); 550} 551 552// Copy n digits from v to u. 553inline 554void 555vec_copy(int n, sc_digit *u, const sc_digit *v) 556{ 557 558#ifdef DEBUG_SYSTEMC 559 assert((n > 0) && (u != NULL) && (v != NULL)); 560#endif 561 562 for (int i = 0; i < n; ++i) 563 u[i] = v[i]; 564} 565 566// Copy v to u, where ulen >= vlen, and zero the rest of the digits in u. 567inline 568void 569vec_copy_and_zero(int ulen, sc_digit *u, 570 int vlen, const sc_digit *v) 571{ 572 573#ifdef DEBUG_SYSTEMC 574 assert((ulen > 0) && (u != NULL)); 575 assert((vlen > 0) && (v != NULL)); 576 assert(ulen >= vlen); 577#endif 578 579 vec_copy(vlen, u, v); 580 vec_zero(vlen, ulen, u); 581 582} 583 584// 2's-complement the digits in u. 585inline 586void 587vec_complement(int ulen, sc_digit *u) 588{ 589 590#ifdef DEBUG_SYSTEMC 591 assert((ulen > 0) && (u != NULL)); 592#endif 593 594 sc_digit carry = 1; 595 596 for (int i = 0; i < ulen; ++i) { 597 carry += (~u[i] & DIGIT_MASK); 598 u[i] = carry & DIGIT_MASK; 599 carry >>= BITS_PER_DIGIT; 600 } 601 602} 603 604 605// ---------------------------------------------------------------------------- 606// Functions to handle built-in types or signs. 607// ---------------------------------------------------------------------------- 608 609// u = v 610// - v is an unsigned long or uint64, and positive integer. 611template< class Type > 612inline 613void 614from_uint(int ulen, sc_digit *u, Type v) 615{ 616 617#ifdef DEBUG_SYSTEMC 618 // assert((ulen <= 0) || (u != NULL)); 619 assert((ulen > 0) && (u != NULL)); 620 assert(v >= 0); 621#endif 622 623 int i = 0; 624 625 while (v && (i < ulen)) { 626#ifndef _WIN32 627 u[i++] = static_cast<sc_digit>( v & DIGIT_MASK ); 628#else 629 u[i++] = ((sc_digit) v) & DIGIT_MASK; 630#endif 631 v >>= BITS_PER_DIGIT; 632 } 633 634 vec_zero(i, ulen, u); 635 636} 637 638 639// Get u's sign and return its absolute value. 640// u can be long, unsigned long, int64, or uint64. 641template< class Type > 642inline 643small_type 644get_sign(Type &u) 645{ 646 if (u > 0) 647 return SC_POS; 648 649 if (u == 0) 650 return SC_ZERO; 651 652 // no positive number representable for minimum value, 653 // leave as is to avoid Undefined Behaviour 654 if( SC_LIKELY_( u > (std::numeric_limits<Type>::min)() ) ) 655 u = -u; 656 657 return SC_NEG; 658} 659 660 661// Return us * vs: 662// - Return SC_ZERO if either sign is SC_ZERO. 663// - Return SC_POS if us == vs 664// - Return SC_NEG if us != vs. 665inline 666small_type 667mul_signs(small_type us, small_type vs) 668{ 669 if ((us == SC_ZERO) || (vs == SC_ZERO)) 670 return SC_ZERO; 671 672 if (us == vs) 673 return SC_POS; 674 675 return SC_NEG; 676} 677 678 679// ---------------------------------------------------------------------------- 680// Functions to test for errors and print out error messages. 681// ---------------------------------------------------------------------------- 682 683#ifdef SC_MAX_NBITS 684 685inline 686void 687test_bound(int nb) 688{ 689 if (nb > SC_MAX_NBITS) { 690 char msg[BUFSIZ]; 691 std::sprintf( msg, "test_bound( int nb ) : " 692 "nb = %d > SC_MAX_NBITS = %d is not valid", 693 nb, SC_MAX_NBITS ); 694 SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg ); 695 } 696} 697 698#endif 699 700template< class Type > 701inline 702void 703div_by_zero(Type s) 704{ 705 if (s == 0) { 706 SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_, 707 "div_by_zero<Type>( Type ) : division by zero" ); 708 } 709} 710 711 712// ---------------------------------------------------------------------------- 713// Functions to check if a given vector is zero or make one. 714// ---------------------------------------------------------------------------- 715 716// If u[i] is zero for every i = 0,..., ulen - 1, return SC_ZERO, 717// else return s. 718inline 719small_type 720check_for_zero(small_type s, int ulen, const sc_digit *u) 721{ 722 723#ifdef DEBUG_SYSTEMC 724 // assert(ulen >= 0); 725 assert((ulen > 0) && (u != NULL)); 726#endif 727 728 if (vec_find_first_nonzero(ulen, u) < 0) 729 return SC_ZERO; 730 731 return s; 732 733} 734 735// If u[i] is zero for every i = 0,..., ulen - 1, return true, 736// else return false. 737inline 738bool 739check_for_zero(int ulen, const sc_digit *u) 740{ 741 742#ifdef DEBUG_SYSTEMC 743 // assert(ulen >= 0); 744 assert((ulen > 0) && (u != NULL)); 745#endif 746 747 if (vec_find_first_nonzero(ulen, u) < 0) 748 return true; 749 750 return false; 751 752} 753 754inline 755small_type 756make_zero(int nd, sc_digit *d) 757{ 758 vec_zero(nd, d); 759 return SC_ZERO; 760} 761 762 763// ---------------------------------------------------------------------------- 764// Functions for both signed and unsigned numbers to convert sign-magnitude 765// (SM) and 2's complement (2C) representations. 766// added = 1 => for signed. 767// added = 0 => for unsigned. 768// IF_SC_SIGNED can be used as 'added'. 769// ---------------------------------------------------------------------------- 770 771// Trim the extra leading bits of a signed or unsigned number. 772inline 773void 774trim(small_type added, int nb, int nd, sc_digit *d) 775{ 776#ifdef DEBUG_SYSTEMC 777 assert((nb > 0) && (nd > 0) && (d != NULL)); 778#endif 779 780 d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + added); 781} 782 783// Convert an (un)signed number from sign-magnitude representation to 784// 2's complement representation and trim the extra bits. 785inline 786void 787convert_SM_to_2C_trimmed(small_type added, 788 small_type s, int nb, int nd, sc_digit *d) 789{ 790 if (s == SC_NEG) { 791 vec_complement(nd, d); 792 trim(added, nb, nd, d); 793 } 794} 795 796// Convert an (un)signed number from sign-magnitude representation to 797// 2's complement representation but do not trim the extra bits. 798inline 799void 800convert_SM_to_2C(small_type s, int nd, sc_digit *d) 801{ 802 if (s == SC_NEG) 803 vec_complement(nd, d); 804} 805 806 807// ---------------------------------------------------------------------------- 808// Functions to convert between sign-magnitude (SM) and 2's complement 809// (2C) representations of signed numbers. 810// ---------------------------------------------------------------------------- 811 812// Trim the extra leading bits off a signed number. 813inline 814void 815trim_signed(int nb, int nd, sc_digit *d) 816{ 817#ifdef DEBUG_SYSTEMC 818 assert((nb > 0) && (nd > 0) && (d != NULL)); 819#endif 820 821 d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + 1); 822} 823 824// Convert a signed number from 2's complement representation to 825// sign-magnitude representation, and return its sign. nd is d's 826// actual size, without zeros eliminated. 827inline 828small_type 829convert_signed_2C_to_SM(int nb, int nd, sc_digit *d) 830{ 831 832#ifdef DEBUG_SYSTEMC 833 assert((nb > 0) && (nd > 0) && (d != NULL)); 834#endif 835 836 small_type s; 837 838 int xnb = bit_ord(nb - 1) + 1; 839 840 // Test the sign bit. 841 if (d[nd - 1] & one_and_zeros(xnb - 1)) { 842 s = SC_NEG; 843 vec_complement(nd, d); 844 } 845 else 846 s = SC_POS; 847 848 // Trim the last digit. 849 d[nd - 1] &= one_and_ones(xnb); 850 851 // Check if the new number is zero. 852 if (s == SC_POS) 853 return check_for_zero(s, nd, d); 854 855 return s; 856 857} 858 859// Convert a signed number from sign-magnitude representation to 2's 860// complement representation, get its sign, convert back to 861// sign-magnitude representation, and return its sign. nd is d's 862// actual size, without zeros eliminated. 863inline 864small_type 865convert_signed_SM_to_2C_to_SM(small_type s, int nb, int nd, sc_digit *d) 866{ 867 convert_SM_to_2C(s, nd, d); 868 return convert_signed_2C_to_SM(nb, nd, d); 869} 870 871// Convert a signed number from sign-magnitude representation to 2's 872// complement representation and trim the extra bits. 873inline 874void 875convert_signed_SM_to_2C_trimmed(small_type s, int nb, int nd, sc_digit *d) 876{ 877 convert_SM_to_2C_trimmed(1, s, nb, nd, d); 878} 879 880// Convert a signed number from sign-magnitude representation to 2's 881// complement representation but do not trim the extra bits. 882inline 883void 884convert_signed_SM_to_2C(small_type s, int nd, sc_digit *d) 885{ 886 convert_SM_to_2C(s, nd, d); 887} 888 889 890// ---------------------------------------------------------------------------- 891// Functions to convert between sign-magnitude (SM) and 2's complement 892// (2C) representations of unsigned numbers. 893// ---------------------------------------------------------------------------- 894 895// Trim the extra leading bits off an unsigned number. 896inline 897void 898trim_unsigned(int nb, int nd, sc_digit *d) 899{ 900#ifdef DEBUG_SYSTEMC 901 assert((nb > 0) && (nd > 0) && (d != NULL)); 902#endif 903 904 d[nd - 1] &= one_and_ones(bit_ord(nb - 1)); 905} 906 907// Convert an unsigned number from 2's complement representation to 908// sign-magnitude representation, and return its sign. nd is d's 909// actual size, without zeros eliminated. 910inline 911small_type 912convert_unsigned_2C_to_SM(int nb, int nd, sc_digit *d) 913{ 914 trim_unsigned(nb, nd, d); 915 return check_for_zero(SC_POS, nd, d); 916} 917 918// Convert an unsigned number from sign-magnitude representation to 919// 2's complement representation, get its sign, convert back to 920// sign-magnitude representation, and return its sign. nd is d's 921// actual size, without zeros eliminated. 922inline 923small_type 924convert_unsigned_SM_to_2C_to_SM(small_type s, int nb, int nd, sc_digit *d) 925{ 926 convert_SM_to_2C(s, nd, d); 927 return convert_unsigned_2C_to_SM(nb, nd, d); 928} 929 930// Convert an unsigned number from sign-magnitude representation to 931// 2's complement representation and trim the extra bits. 932inline 933void 934convert_unsigned_SM_to_2C_trimmed(small_type s, int nb, int nd, sc_digit *d) 935{ 936 convert_SM_to_2C_trimmed(0, s, nb, nd, d); 937} 938 939// Convert an unsigned number from sign-magnitude representation to 940// 2's complement representation but do not trim the extra bits. 941inline 942void 943convert_unsigned_SM_to_2C(small_type s, int nd, sc_digit *d) 944{ 945 convert_SM_to_2C(s, nd, d); 946} 947 948 949// ---------------------------------------------------------------------------- 950// Functions to copy one (un)signed number to another. 951// ---------------------------------------------------------------------------- 952 953// Copy v to u. 954inline 955void 956copy_digits_signed(small_type &us, 957 int unb, int und, sc_digit *ud, 958 int vnb, int vnd, const sc_digit *vd) 959{ 960 961 if (und <= vnd) { 962 963 vec_copy(und, ud, vd); 964 965 if (unb <= vnb) 966 us = convert_signed_SM_to_2C_to_SM(us, unb, und, ud); 967 968 } 969 else // und > vnd 970 vec_copy_and_zero(und, ud, vnd, vd); 971 972} 973 974// Copy v to u. 975inline 976void 977copy_digits_unsigned(small_type &us, 978 int unb, int und, sc_digit *ud, 979 int /* vnb */, int vnd, const sc_digit *vd) 980{ 981 982 if (und <= vnd) 983 vec_copy(und, ud, vd); 984 985 else // und > vnd 986 vec_copy_and_zero(und, ud, vnd, vd); 987 988 us = convert_unsigned_SM_to_2C_to_SM(us, unb, und, ud); 989 990} 991 992 993// ---------------------------------------------------------------------------- 994// Faster set(i, v), without bound checking. 995// ---------------------------------------------------------------------------- 996 997// A version of set(i, v) without bound checking. 998inline 999void 1000safe_set(int i, bool v, sc_digit *d) 1001{ 1002 1003#ifdef DEBUG_SYSTEMC 1004 assert((i >= 0) && (d != NULL)); 1005#endif 1006 1007 int bit_num = bit_ord(i); 1008 int digit_num = digit_ord(i); 1009 1010 if (v) 1011 d[digit_num] |= one_and_zeros(bit_num); 1012 else 1013 d[digit_num] &= ~(one_and_zeros(bit_num)); 1014 1015} 1016 1017 1018// ---------------------------------------------------------------------------- 1019// Function to check if a double number is bad (NaN or infinite). 1020// ---------------------------------------------------------------------------- 1021 1022inline 1023bool 1024is_nan( double v ) 1025{ 1026 return std::numeric_limits<double>::has_quiet_NaN && (v != v); 1027} 1028 1029inline 1030bool 1031is_inf( double v ) 1032{ 1033 return v == std::numeric_limits<double>::infinity() 1034 || v == -std::numeric_limits<double>::infinity(); 1035} 1036 1037inline 1038void 1039is_bad_double(double v) 1040{ 1041// Windows throws exception. 1042 if( is_nan(v) || is_inf(v) ) 1043 SC_REPORT_ERROR( sc_core::SC_ID_VALUE_NOT_VALID_, 1044 "is_bad_double( double v ) : " 1045 "v is not finite - NaN or Inf" ); 1046} 1047 1048} // namespace sc_dt 1049 1050 1051#endif 1052