sc_nbutils.hh revision 12853
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 __SYSTEMC_EXT_DT_INT_SC_NBUTILS_HH__ 64#define __SYSTEMC_EXT_DT_INT_SC_NBUTILS_HH__ 65 66#include <cmath> 67#include <ios> 68#include <limits> 69#include <ostream> 70 71#include "../../utils/sc_report_handler.hh" 72#include "sc_nbdefs.hh" 73 74namespace sc_dt 75{ 76 77//----------------------------------------------------------------------------- 78//"sc_io_base" 79// 80// This inline function returns the type of an i/o stream's base as a SystemC 81// base designator. 82// stream_object = reference to the i/o stream whose base is to be returned. 83// 84//"sc_io_show_base" 85// 86// This inline function returns true if the base should be shown when a SystemC 87// value is displayed via the supplied stream operator. 88// stream_object = reference to the i/o stream to return showbase value for. 89//----------------------------------------------------------------------------- 90inline sc_numrep 91sc_io_base(::std::ostream &os, sc_numrep def_base) 92{ 93 std::ios::fmtflags flags = os.flags() & std::ios::basefield; 94 if (flags & ::std::ios::dec) return SC_DEC; 95 if (flags & ::std::ios::hex) return SC_HEX; 96 if (flags & ::std::ios::oct) return SC_OCT; 97 return def_base; 98} 99 100inline bool 101sc_io_show_base(::std::ostream &os) 102{ 103 return (os.flags() & ::std::ios::showbase) != 0; 104} 105 106const std::string to_string(sc_numrep); 107 108inline ::std::ostream & 109operator << (::std::ostream &os, sc_numrep numrep) 110{ 111 os << to_string(numrep); 112 return os; 113} 114 115// ---------------------------------------------------------------------------- 116 117// One transition of the FSM to find base and sign of a number. 118extern small_type fsm_move( 119 char c, small_type &b, small_type &s, small_type &state); 120 121// Parse a character string into its equivalent binary bits. 122extern void parse_binary_bits( 123 const char *src_p, int dst_n, sc_digit *data_p, sc_digit *ctrl_p=0); 124 125// Parse a character string into its equivalent hexadecimal bits. 126extern void parse_hex_bits( 127 const char *src_p, int dst_n, sc_digit *data_p, sc_digit *ctrl_p=0); 128 129// Find the base and sign of a number in v. 130extern const char *get_base_and_sign( 131 const char *v, small_type &base, small_type &sign); 132 133// Create a number out of v in base. 134extern small_type 135vec_from_str(int unb, int und, sc_digit *u, 136 const char *v, sc_numrep base=SC_NOBASE); 137 138 139// ---------------------------------------------------------------------------- 140// Naming convention for the vec_ functions below: 141// vec_OP(u, v, w) : computes w = u OP v. 142// vec_OP_on(u, v) : computes u = u OP v if u has more digits than v. 143// vec_OP_on2(u, v) : computes u = u OP v if u has fewer digits than v. 144// _large : parameters are vectors. 145// _small : one of the parameters is a single digit. 146// Xlen : the number of digits in X. 147// ---------------------------------------------------------------------------- 148 149// ---------------------------------------------------------------------------- 150// Functions for vector addition: w = u + v or u += v. 151// ---------------------------------------------------------------------------- 152 153extern void vec_add(int ulen, const sc_digit *u, 154 int vlen, const sc_digit *v, sc_digit *w); 155extern void vec_add_on(int ulen, sc_digit *u, int vlen, const sc_digit *v); 156extern void vec_add_on2(int ulen, sc_digit *u, int vlen, const sc_digit *v); 157extern void vec_add_small(int ulen, const sc_digit *u, 158 sc_digit v, sc_digit *w); 159extern void vec_add_small_on(int ulen, sc_digit *u, sc_digit v); 160 161// ---------------------------------------------------------------------------- 162// Functions for vector subtraction: w = u - v, u -= v, or u = v - u. 163// ---------------------------------------------------------------------------- 164 165extern void vec_sub(int ulen, const sc_digit *u, 166 int vlen, const sc_digit *v, sc_digit *w); 167extern void vec_sub_on(int ulen, sc_digit *u, int vlen, const sc_digit *v); 168extern void vec_sub_on2(int ulen, sc_digit *u, int vlen, const sc_digit *v); 169extern void vec_sub_small(int ulen, const sc_digit *u, 170 sc_digit v, sc_digit *w); 171extern void vec_sub_small_on(int ulen, sc_digit *u, sc_digit v); 172 173 174// ---------------------------------------------------------------------------- 175// Functions for vector multiplication: w = u * v or u *= v. 176// ---------------------------------------------------------------------------- 177 178extern void vec_mul(int ulen, const sc_digit *u, 179 int vlen, const sc_digit *v, sc_digit *w); 180extern void vec_mul_small(int ulen, const sc_digit *u, 181 sc_digit v, sc_digit *w); 182extern void vec_mul_small_on(int ulen, sc_digit *u, sc_digit v); 183 184 185// ---------------------------------------------------------------------------- 186// Functions for vector division: w = u / v. 187// ---------------------------------------------------------------------------- 188 189extern void vec_div_large(int ulen, const sc_digit *u, 190 int vlen, const sc_digit *v, sc_digit *w); 191extern void vec_div_small(int ulen, const sc_digit *u, 192 sc_digit v, sc_digit *w); 193 194 195// ---------------------------------------------------------------------------- 196// Functions for vector remainder: w = u % v or u %= v. 197// ---------------------------------------------------------------------------- 198 199extern void vec_rem_large(int ulen, const sc_digit *u, 200 int vlen, const sc_digit *v, sc_digit *w); 201extern sc_digit vec_rem_small(int ulen, const sc_digit *u, sc_digit v); 202extern sc_digit vec_rem_on_small(int ulen, sc_digit *u, sc_digit v); 203 204 205// ---------------------------------------------------------------------------- 206// Functions to convert between vectors of char and sc_digit. 207// ---------------------------------------------------------------------------- 208 209extern int vec_to_char(int ulen, const sc_digit *u, int vlen, uchar *v); 210extern void vec_from_char(int ulen, const uchar *u, int vlen, sc_digit *v); 211 212 213// ---------------------------------------------------------------------------- 214// Functions to shift left or right, or to create a mirror image of vectors. 215// ---------------------------------------------------------------------------- 216 217extern void vec_shift_left(int ulen, sc_digit *u, int nsl); 218extern void vec_shift_right(int vlen, sc_digit *u, int nsr, sc_digit fill=0); 219extern void vec_reverse(int unb, int und, sc_digit *ud, int l, int r=0); 220 221 222// ---------------------------------------------------------------------------- 223// Various utility functions. 224// ---------------------------------------------------------------------------- 225 226// Return the low half part of d. 227inline sc_digit low_half(sc_digit d) { return (d & HALF_DIGIT_MASK); } 228 229// Return the high half part of d. The high part of the digit may have 230// more bits than BITS_PER_HALF_DIGIT due to, e.g., overflow in the 231// multiplication. Hence, in other functions that use high_half(), 232// make sure that the result contains BITS_PER_HALF_DIGIT if 233// necessary. This is done by high_half_masked(). 234inline sc_digit high_half(sc_digit d) { return (d >> BITS_PER_HALF_DIGIT); } 235inline sc_digit 236high_half_masked(sc_digit d) 237{ 238 return (high_half(d) & HALF_DIGIT_MASK); 239} 240 241// Concatenate the high part h and low part l. Assumes that h and l 242// are less than or equal to HALF_DIGIT_MASK; 243inline sc_digit 244concat(sc_digit h, sc_digit l) 245{ 246 return ((h << BITS_PER_HALF_DIGIT) | l); 247} 248 249// Create a number with n 1's. 250inline sc_digit 251one_and_ones(int n) 252{ 253 return (((sc_digit) 1 << n) - 1); 254} 255 256// Create a number with one 1 and n 0's. 257inline sc_digit one_and_zeros(int n) { return ((sc_digit) 1 << n); } 258 259 260// ---------------------------------------------------------------------------- 261 262// Find the digit that bit i is in. 263inline int digit_ord(int i) { return (i / BITS_PER_DIGIT); } 264 265// Find the bit in digit_ord(i) that bit i corressponds to. 266inline int bit_ord(int i) { return (i % BITS_PER_DIGIT); } 267 268 269// ---------------------------------------------------------------------------- 270// Functions to compare, zero, complement vector(s). 271// ---------------------------------------------------------------------------- 272 273// Compare u and v and return r 274// r = 0 if u == v 275// r < 0 if u < v 276// r > 0 if u > v 277// - Assume that all the leading zero digits are already skipped. 278// - ulen and/or vlen can be zero. 279// - Every digit is less than or equal to DIGIT_MASK; 280inline int 281vec_cmp(int ulen, const sc_digit *u, 282 int vlen, const sc_digit *v) 283{ 284 285#ifdef DEBUG_SYSTEMC 286 // sc_assert((ulen <= 0) || (u != NULL)); 287 // sc_assert((vlen <= 0) || (v != NULL)); 288 289 // ulen and vlen can be equal to 0 because vec_cmp can be called 290 // after vec_skip_leading_zeros. 291 sc_assert((ulen >= 0) && (u != NULL)); 292 sc_assert((vlen >= 0) && (v != NULL)); 293 // If ulen > 0, then the leading digit of u must be non-zero. 294 sc_assert((ulen <= 0) || (u[ulen - 1] != 0)); 295 sc_assert((vlen <= 0) || (v[vlen - 1] != 0)); 296#endif 297 298 if (ulen != vlen) 299 return (ulen - vlen); 300 301 // ulen == vlen >= 1 302 while ((--ulen >= 0) && (u[ulen] == v[ulen])) 303 {} 304 305 if (ulen < 0) 306 return 0; 307 308#ifdef DEBUG_SYSTEMC 309 // Test to see if the result is wrong due to the presence of 310 // overflow bits. 311 sc_assert((u[ulen] & DIGIT_MASK) != (v[ulen] & DIGIT_MASK)); 312#endif 313 314 return (int)(u[ulen] - v[ulen]); 315} 316 317// Find the index of the first non-zero digit. 318// - ulen (before) = the number of digits in u. 319// - the returned value = the index of the first non-zero digit. 320// A negative value of -1 indicates that every digit in u is zero. 321inline int 322vec_find_first_nonzero(int ulen, const sc_digit *u) 323{ 324 325#ifdef DEBUG_SYSTEMC 326 // sc_assert((ulen <= 0) || (u != NULL)); 327 sc_assert((ulen > 0) && (u != NULL)); 328#endif 329 330 while ((--ulen >= 0) && (! u[ulen])) 331 {} 332 333 return ulen; 334} 335 336// Skip all the leading zero digits. 337// - ulen (before) = the number of digits in u. 338// - the returned value = the number of non-zero digits in u. 339// - the returned value is non-negative. 340inline int 341vec_skip_leading_zeros(int ulen, const sc_digit *u) 342{ 343#ifdef DEBUG_SYSTEMC 344 // sc_assert((ulen <= 0) || (u != NULL)); 345 sc_assert((ulen > 0) && (u != NULL)); 346#endif 347 348 return (1 + vec_find_first_nonzero(ulen, u)); 349} 350 351// Compare u and v and return r 352// r = 0 if u == v 353// r < 0 if u < v 354// r > 0 if u > v 355inline int 356vec_skip_and_cmp(int ulen, const sc_digit *u, int vlen, const sc_digit *v) 357{ 358#ifdef DEBUG_SYSTEMC 359 sc_assert((ulen > 0) && (u != NULL)); 360 sc_assert((vlen > 0) && (v != NULL)); 361#endif 362 363 ulen = vec_skip_leading_zeros(ulen, u); 364 vlen = vec_skip_leading_zeros(vlen, v); 365 // ulen and/or vlen can be equal to zero here. 366 return vec_cmp(ulen, u, vlen, v); 367} 368 369// Set u[i] = 0 where i = from ... (ulen - 1). 370inline void 371vec_zero(int from, int ulen, sc_digit *u) 372{ 373#ifdef DEBUG_SYSTEMC 374 sc_assert((ulen > 0) && (u != NULL)); 375#endif 376 for (int i = from; i < ulen; i++) 377 u[i] = 0; 378} 379 380// Set u[i] = 0 where i = 0 .. (ulen - 1). 381inline void vec_zero(int ulen, sc_digit *u) { vec_zero(0, ulen, u); } 382 383// Copy n digits from v to u. 384inline void 385vec_copy(int n, sc_digit *u, const sc_digit *v) 386{ 387#ifdef DEBUG_SYSTEMC 388 sc_assert((n > 0) && (u != NULL) && (v != NULL)); 389#endif 390 for (int i = 0; i < n; ++i) 391 u[i] = v[i]; 392} 393 394// Copy v to u, where ulen >= vlen, and zero the rest of the digits in u. 395inline void 396vec_copy_and_zero(int ulen, sc_digit *u, int vlen, const sc_digit *v) 397{ 398 399#ifdef DEBUG_SYSTEMC 400 sc_assert((ulen > 0) && (u != NULL)); 401 sc_assert((vlen > 0) && (v != NULL)); 402 sc_assert(ulen >= vlen); 403#endif 404 vec_copy(vlen, u, v); 405 vec_zero(vlen, ulen, u); 406 407} 408 409// 2's-complement the digits in u. 410inline void 411vec_complement(int ulen, sc_digit *u) 412{ 413 414#ifdef DEBUG_SYSTEMC 415 sc_assert((ulen > 0) && (u != NULL)); 416#endif 417 418 sc_digit carry = 1; 419 420 for (int i = 0; i < ulen; ++i) { 421 carry += (~u[i] & DIGIT_MASK); 422 u[i] = carry & DIGIT_MASK; 423 carry >>= BITS_PER_DIGIT; 424 } 425} 426 427 428// ---------------------------------------------------------------------------- 429// Functions to handle built-in types or signs. 430// ---------------------------------------------------------------------------- 431 432// u = v 433// - v is an unsigned long or uint64, and positive integer. 434template<class Type> 435inline void 436from_uint(int ulen, sc_digit *u, Type v) 437{ 438#ifdef DEBUG_SYSTEMC 439 // sc_assert((ulen <= 0) || (u != NULL)); 440 sc_assert((ulen > 0) && (u != NULL)); 441 sc_assert(v >= 0); 442#endif 443 444 int i = 0; 445 446 while (v && (i < ulen)) { 447 u[i++] = static_cast<sc_digit>(v & DIGIT_MASK); 448 v >>= BITS_PER_DIGIT; 449 } 450 vec_zero(i, ulen, u); 451} 452 453#ifndef __GNUC__ 454# define SC_LIKELY_(x) !!(x) 455#else 456# define SC_LIKELY_(x) __builtin_expect(!!(x), 1) 457#endif 458 459// Get u's sign and return its absolute value. 460// u can be long, unsigned long, int64, or uint64. 461template<class Type> 462inline small_type 463get_sign(Type &u) 464{ 465 if (u > 0) 466 return SC_POS; 467 468 if (u == 0) 469 return SC_ZERO; 470 471 // no positive number representable for minimum value, 472 // leave as is to avoid Undefined Behaviour 473 if (SC_LIKELY_(u > (std::numeric_limits<Type>::min)())) 474 u = -u; 475 476 return SC_NEG; 477} 478 479#undef SC_LIKELY_ 480 481 482// Return us * vs: 483// - Return SC_ZERO if either sign is SC_ZERO. 484// - Return SC_POS if us == vs 485// - Return SC_NEG if us != vs. 486inline small_type 487mul_signs(small_type us, small_type vs) 488{ 489 if ((us == SC_ZERO) || (vs == SC_ZERO)) 490 return SC_ZERO; 491 492 if (us == vs) 493 return SC_POS; 494 495 return SC_NEG; 496} 497 498 499// ---------------------------------------------------------------------------- 500// Functions to test for errors and print out error messages. 501// ---------------------------------------------------------------------------- 502 503#ifdef SC_MAX_NBITS 504 505void test_bound_failed(int nb); 506 507inline void 508test_bound(int nb) 509{ 510 if (nb > SC_MAX_NBITS) { 511 test_bound_failed(nb); 512 sc_core::sc_abort(); // can't recover from here 513 } 514} 515 516#endif 517 518template<class Type> 519inline void 520div_by_zero(Type s) 521{ 522 if (s == 0) { 523 SC_REPORT_ERROR("operation failed", 524 "div_by_zero<Type>(Type) : division by zero"); 525 sc_core::sc_abort(); // can't recover from here 526 } 527} 528 529 530// ---------------------------------------------------------------------------- 531// Functions to check if a given vector is zero or make one. 532// ---------------------------------------------------------------------------- 533 534// If u[i] is zero for every i = 0,..., ulen - 1, return SC_ZERO, 535// else return s. 536inline small_type 537check_for_zero(small_type s, int ulen, const sc_digit *u) 538{ 539 540#ifdef DEBUG_SYSTEMC 541 // sc_assert(ulen >= 0); 542 sc_assert((ulen > 0) && (u != NULL)); 543#endif 544 545 if (vec_find_first_nonzero(ulen, u) < 0) 546 return SC_ZERO; 547 548 return s; 549} 550 551// If u[i] is zero for every i = 0,..., ulen - 1, return true, 552// else return false. 553inline bool 554check_for_zero(int ulen, const sc_digit *u) 555{ 556 557#ifdef DEBUG_SYSTEMC 558 // sc_assert(ulen >= 0); 559 sc_assert((ulen > 0) && (u != NULL)); 560#endif 561 562 if (vec_find_first_nonzero(ulen, u) < 0) 563 return true; 564 565 return false; 566} 567 568inline small_type 569make_zero(int nd, sc_digit *d) 570{ 571 vec_zero(nd, d); 572 return SC_ZERO; 573} 574 575 576// ---------------------------------------------------------------------------- 577// Functions for both signed and unsigned numbers to convert sign-magnitude 578// (SM) and 2's complement (2C) representations. 579// added = 1 => for signed. 580// added = 0 => for unsigned. 581// IF_SC_SIGNED can be used as 'added'. 582// ---------------------------------------------------------------------------- 583 584// Trim the extra leading bits of a signed or unsigned number. 585inline void 586trim(small_type added, int nb, int nd, sc_digit *d) 587{ 588#ifdef DEBUG_SYSTEMC 589 sc_assert((nb > 0) && (nd > 0) && (d != NULL)); 590#endif 591 d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + added); 592} 593 594// Convert an (un)signed number from sign-magnitude representation to 595// 2's complement representation and trim the extra bits. 596inline void 597convert_SM_to_2C_trimmed(small_type added, 598 small_type s, int nb, int nd, sc_digit *d) 599{ 600 if (s == SC_NEG) { 601 vec_complement(nd, d); 602 trim(added, nb, nd, d); 603 } 604} 605 606// Convert an (un)signed number from sign-magnitude representation to 607// 2's complement representation but do not trim the extra bits. 608inline void 609convert_SM_to_2C(small_type s, int nd, sc_digit *d) 610{ 611 if (s == SC_NEG) 612 vec_complement(nd, d); 613} 614 615 616// ---------------------------------------------------------------------------- 617// Functions to convert between sign-magnitude (SM) and 2's complement 618// (2C) representations of signed numbers. 619// ---------------------------------------------------------------------------- 620 621// Trim the extra leading bits off a signed number. 622inline void 623trim_signed(int nb, int nd, sc_digit *d) 624{ 625#ifdef DEBUG_SYSTEMC 626 sc_assert((nb > 0) && (nd > 0) && (d != NULL)); 627#endif 628 d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + 1); 629} 630 631// Convert a signed number from 2's complement representation to 632// sign-magnitude representation, and return its sign. nd is d's 633// actual size, without zeros eliminated. 634inline small_type 635convert_signed_2C_to_SM(int nb, int nd, sc_digit *d) 636{ 637#ifdef DEBUG_SYSTEMC 638 sc_assert((nb > 0) && (nd > 0) && (d != NULL)); 639#endif 640 641 small_type s; 642 643 int xnb = bit_ord(nb - 1) + 1; 644 645 // Test the sign bit. 646 if (d[nd - 1] & one_and_zeros(xnb - 1)) { 647 s = SC_NEG; 648 vec_complement(nd, d); 649 } else { 650 s = SC_POS; 651 } 652 653 // Trim the last digit. 654 d[nd - 1] &= one_and_ones(xnb); 655 656 // Check if the new number is zero. 657 if (s == SC_POS) 658 return check_for_zero(s, nd, d); 659 660 return s; 661} 662 663// Convert a signed number from sign-magnitude representation to 2's 664// complement representation, get its sign, convert back to 665// sign-magnitude representation, and return its sign. nd is d's 666// actual size, without zeros eliminated. 667inline small_type 668convert_signed_SM_to_2C_to_SM(small_type s, int nb, int nd, sc_digit *d) 669{ 670 convert_SM_to_2C(s, nd, d); 671 return convert_signed_2C_to_SM(nb, nd, d); 672} 673 674// Convert a signed number from sign-magnitude representation to 2's 675// complement representation and trim the extra bits. 676inline void 677convert_signed_SM_to_2C_trimmed(small_type s, int nb, int nd, sc_digit *d) 678{ 679 convert_SM_to_2C_trimmed(1, s, nb, nd, d); 680} 681 682// Convert a signed number from sign-magnitude representation to 2's 683// complement representation but do not trim the extra bits. 684inline void 685convert_signed_SM_to_2C(small_type s, int nd, sc_digit *d) 686{ 687 convert_SM_to_2C(s, nd, d); 688} 689 690 691// ---------------------------------------------------------------------------- 692// Functions to convert between sign-magnitude (SM) and 2's complement 693// (2C) representations of unsigned numbers. 694// ---------------------------------------------------------------------------- 695 696// Trim the extra leading bits off an unsigned number. 697inline void 698trim_unsigned(int nb, int nd, sc_digit *d) 699{ 700#ifdef DEBUG_SYSTEMC 701 sc_assert((nb > 0) && (nd > 0) && (d != NULL)); 702#endif 703 704 d[nd - 1] &= one_and_ones(bit_ord(nb - 1)); 705} 706 707// Convert an unsigned number from 2's complement representation to 708// sign-magnitude representation, and return its sign. nd is d's 709// actual size, without zeros eliminated. 710inline small_type 711convert_unsigned_2C_to_SM(int nb, int nd, sc_digit *d) 712{ 713 trim_unsigned(nb, nd, d); 714 return check_for_zero(SC_POS, nd, d); 715} 716 717// Convert an unsigned number from sign-magnitude representation to 718// 2's complement representation, get its sign, convert back to 719// sign-magnitude representation, and return its sign. nd is d's 720// actual size, without zeros eliminated. 721inline small_type 722convert_unsigned_SM_to_2C_to_SM(small_type s, int nb, int nd, sc_digit *d) 723{ 724 convert_SM_to_2C(s, nd, d); 725 return convert_unsigned_2C_to_SM(nb, nd, d); 726} 727 728// Convert an unsigned number from sign-magnitude representation to 729// 2's complement representation and trim the extra bits. 730inline void 731convert_unsigned_SM_to_2C_trimmed(small_type s, int nb, int nd, sc_digit *d) 732{ 733 convert_SM_to_2C_trimmed(0, s, nb, nd, d); 734} 735 736// Convert an unsigned number from sign-magnitude representation to 737// 2's complement representation but do not trim the extra bits. 738inline void 739convert_unsigned_SM_to_2C(small_type s, int nd, sc_digit *d) 740{ 741 convert_SM_to_2C(s, nd, d); 742} 743 744 745// ---------------------------------------------------------------------------- 746// Functions to copy one (un)signed number to another. 747// ---------------------------------------------------------------------------- 748 749// Copy v to u. 750inline void 751copy_digits_signed(small_type &us, 752 int unb, int und, sc_digit *ud, 753 int vnb, int vnd, const sc_digit *vd) 754{ 755 if (und <= vnd) { 756 vec_copy(und, ud, vd); 757 758 if (unb <= vnb) 759 us = convert_signed_SM_to_2C_to_SM(us, unb, und, ud); 760 } else { // und > vnd 761 vec_copy_and_zero(und, ud, vnd, vd); 762 } 763} 764 765// Copy v to u. 766inline void 767copy_digits_unsigned(small_type &us, 768 int unb, int und, sc_digit *ud, 769 int /* vnb */, int vnd, const sc_digit *vd) 770{ 771 if (und <= vnd) 772 vec_copy(und, ud, vd); 773 else // und > vnd 774 vec_copy_and_zero(und, ud, vnd, vd); 775 776 us = convert_unsigned_SM_to_2C_to_SM(us, unb, und, ud); 777} 778 779 780// ---------------------------------------------------------------------------- 781// Faster set(i, v), without bound checking. 782// ---------------------------------------------------------------------------- 783 784// A version of set(i, v) without bound checking. 785inline void 786safe_set(int i, bool v, sc_digit *d) 787{ 788 789#ifdef DEBUG_SYSTEMC 790 sc_assert((i >= 0) && (d != NULL)); 791#endif 792 793 int bit_num = bit_ord(i); 794 int digit_num = digit_ord(i); 795 796 if (v) 797 d[digit_num] |= one_and_zeros(bit_num); 798 else 799 d[digit_num] &= ~(one_and_zeros(bit_num)); 800} 801 802 803// ---------------------------------------------------------------------------- 804// Function to check if a double number is bad (NaN or infinite). 805// ---------------------------------------------------------------------------- 806 807inline bool 808is_nan(double v) 809{ 810 return std::numeric_limits<double>::has_quiet_NaN && (v != v); 811} 812 813inline bool 814is_inf(double v) 815{ 816 return v == std::numeric_limits<double>::infinity() || 817 v == -std::numeric_limits<double>::infinity(); 818} 819 820inline void 821is_bad_double(double v) 822{ 823 // Windows throws exception. 824 if (is_nan(v) || is_inf(v)) 825 SC_REPORT_ERROR("value is not valid", 826 "is_bad_double(double v) : " 827 "v is not finite - NaN or Inf"); 828} 829 830} // namespace sc_dt 831 832#endif // __SYSTEMC_EXT_DT_INT_SC_NBUTILS_HH__ 833