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