src/sysc/datatypes/int/sc_nbutils.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2005 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   sc_nbutils.h -- External and friend functions for both sc_signed and
00021                   sc_unsigned classes.
00022 
00023   Original Author: Ali Dasdan, Synopsys, Inc.
00024  
00025  *****************************************************************************/
00026 
00027 /*****************************************************************************
00028 
00029   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00030   changes you are making here.
00031 
00032       Name, Affiliation, Date:
00033   Description of Modification:
00034 
00035  *****************************************************************************/
00036 
00037 #ifndef SC_NBUTILS_H
00038 #define SC_NBUTILS_H
00039 
00040 
00041 #if !defined(__ppc__) && !defined(_MSC_VER) && !defined(i386) && !defined(__hpux) && !defined( __BORLANDC__ )
00042 #include <ieeefp.h>
00043 #else
00044 #include <cmath>
00045 #endif
00046 
00047 #include "sysc/datatypes/bit/sc_bit_ids.h"
00048 #include "sysc/datatypes/int/sc_int_ids.h"
00049 #include "sysc/datatypes/int/sc_nbdefs.h"
00050 #include "sysc/utils/sc_string.h"
00051 #include "sysc/utils/sc_report.h"
00052 
00053 
00054 namespace sc_dt
00055 {
00056 
00057 inline
00058 void
00059 is_valid_base(sc_numrep base)
00060 {
00061   switch (base) {
00062     case SC_NOBASE: case SC_BIN: 
00063     case SC_OCT: case SC_DEC: 
00064     case SC_HEX: 
00065         break;
00066     case SC_BIN_US: case SC_BIN_SM: 
00067     case SC_OCT_US: case SC_OCT_SM:
00068     case SC_HEX_US: case SC_HEX_SM:
00069       SC_REPORT_ERROR( sc_core::SC_ID_NOT_IMPLEMENTED_,
00070                        "is_valid_base( sc_numrep base ) : "
00071                        "base ending in _US and _SM is not supported yet" );
00072     default:
00073       char msg[BUFSIZ];
00074       sprintf( msg, "is_valid_base( sc_numrep base ) : "
00075                "base = %s is not valid",
00076                to_string( base ).c_str() );
00077       SC_REPORT_ERROR( sc_core::SC_ID_VALUE_NOT_VALID_, msg );
00078   }
00079 }
00080 
00081 // One transition of the FSM to find base and sign of a number.
00082 extern
00083 small_type 
00084 fsm_move(char c, small_type &b, small_type &s, small_type &state);
00085 
00086 // Parse a character string into its equivalent binary bits.
00087 extern
00088 void parse_binary_bits( 
00089     const char* src_p, int dst_n, unsigned long* data_p, unsigned long* ctrl_p=0
00090 );
00091 
00092 
00093 // Parse a character string into its equivalent hexadecimal bits.
00094 extern
00095 void parse_hex_bits( 
00096     const char* src_p, int dst_n, unsigned long* data_p, unsigned long* ctrl_p=0
00097 );
00098 
00099 
00100 // Find the base and sign of a number in v.
00101 extern 
00102 const char *
00103 get_base_and_sign(const char *v, small_type &base, small_type &sign);
00104 
00105 // Create a number out of v in base.
00106 extern 
00107 small_type 
00108 vec_from_str(int unb, int und, unsigned long *u, 
00109              const char *v, sc_numrep base = SC_NOBASE) ;
00110 
00111 
00112 // ----------------------------------------------------------------------------
00113 //  Naming convention for the vec_ functions below:
00114 //    vec_OP(u, v, w)  : computes w = u OP v.
00115 //    vec_OP_on(u, v)  : computes u = u OP v if u has more digits than v.
00116 //    vec_OP_on2(u, v) : computes u = u OP v if u has fewer digits than v.
00117 //    _large           : parameters are vectors.
00118 //    _small           : one of the parameters is a single digit.
00119 //    Xlen             : the number of digits in X.
00120 // ----------------------------------------------------------------------------
00121 
00122 // ----------------------------------------------------------------------------
00123 //  Functions for vector addition: w = u + v or u += v.
00124 // ----------------------------------------------------------------------------
00125 
00126 extern 
00127 void 
00128 vec_add(int ulen, const unsigned long *u, 
00129         int vlen, const unsigned long *v, unsigned long *w);
00130 
00131 extern 
00132 void 
00133 vec_add_on(int ulen, unsigned long *u, 
00134            int vlen, const unsigned long *v);
00135 
00136 extern 
00137 void 
00138 vec_add_on2(int ulen, unsigned long *u, 
00139             int vlen, const unsigned long *v);
00140 
00141 extern 
00142 void 
00143 vec_add_small(int ulen, const unsigned long *u,
00144               unsigned long v, unsigned long *w);
00145 
00146 extern 
00147 void 
00148 vec_add_small_on(int ulen, unsigned long *u, unsigned long v);
00149 
00150 
00151 // ----------------------------------------------------------------------------
00152 //  Functions for vector subtraction: w = u - v, u -= v, or u = v - u.
00153 // ----------------------------------------------------------------------------
00154 
00155 extern 
00156 void 
00157 vec_sub(int ulen, const unsigned long *u, 
00158         int vlen, const unsigned long *v, unsigned long *w);
00159 
00160 extern 
00161 void 
00162 vec_sub_on(int ulen, unsigned long *u, 
00163            int vlen, const unsigned long *v);
00164 
00165 extern 
00166 void 
00167 vec_sub_on2(int ulen, unsigned long *u,
00168             int vlen, const unsigned long *v);
00169 
00170 extern 
00171 void 
00172 vec_sub_small(int ulen, const unsigned long *u,
00173               unsigned long v, unsigned long *w);
00174 
00175 extern 
00176 void 
00177 vec_sub_small_on(int ulen, unsigned long *u, unsigned long v);
00178 
00179 
00180 // ----------------------------------------------------------------------------
00181 //  Functions for vector multiplication: w = u * v or u *= v.
00182 // ----------------------------------------------------------------------------
00183 
00184 extern 
00185 void 
00186 vec_mul(int ulen, const unsigned long *u, 
00187         int vlen, const unsigned long *v, unsigned long *w);
00188 
00189 extern 
00190 void 
00191 vec_mul_small(int ulen, const unsigned long *u,
00192               unsigned long v, unsigned long *w);
00193 
00194 extern 
00195 void 
00196 vec_mul_small_on(int ulen, unsigned long *u, unsigned long v);
00197 
00198 
00199 // ----------------------------------------------------------------------------
00200 //  Functions for vector division: w = u / v.
00201 // ----------------------------------------------------------------------------
00202 
00203 extern 
00204 void 
00205 vec_div_large(int ulen, const unsigned long *u, 
00206               int vlen, const unsigned long *v, unsigned long *w);
00207 
00208 extern 
00209 void 
00210 vec_div_small(int ulen, const unsigned long *u, 
00211               unsigned long v, unsigned long *w);
00212 
00213 
00214 // ----------------------------------------------------------------------------
00215 //  Functions for vector remainder: w = u % v or u %= v.
00216 // ----------------------------------------------------------------------------
00217 
00218 extern 
00219 void 
00220 vec_rem_large(int ulen, const unsigned long *u, 
00221               int vlen, const unsigned long *v, unsigned long *w);
00222 
00223 extern 
00224 unsigned long 
00225 vec_rem_small(int ulen, const unsigned long *u, unsigned long v);
00226 
00227 extern 
00228 unsigned long 
00229 vec_rem_on_small(int ulen, unsigned long *u, unsigned long v);
00230 
00231 
00232 // ----------------------------------------------------------------------------
00233 //  Functions to convert between vectors of char and unsigned long.
00234 // ----------------------------------------------------------------------------
00235 
00236 extern 
00237 int 
00238 vec_to_char(int ulen, const unsigned long *u, 
00239             int vlen, uchar *v);
00240 
00241 extern 
00242 void 
00243 vec_from_char(int ulen, const uchar *u,
00244               int vlen, unsigned long *v);
00245 
00246 
00247 // ----------------------------------------------------------------------------
00248 //  Functions to shift left or right, or to create a mirror image of vectors.
00249 // ----------------------------------------------------------------------------
00250 
00251 extern 
00252 void 
00253 vec_shift_left(int ulen, unsigned long *u, int nsl);
00254 
00255 extern 
00256 void 
00257 vec_shift_right(int vlen, unsigned long *u, int nsr, unsigned long fill = 0);
00258 
00259 extern
00260 void 
00261 vec_reverse(int unb, int und, unsigned long *ud, 
00262             int l, int r = 0);
00263 
00264 
00265 // ----------------------------------------------------------------------------
00266 //  Various utility functions. 
00267 // ----------------------------------------------------------------------------
00268 
00269 // Return the low half part of d.
00270 inline 
00271 unsigned long 
00272 low_half(unsigned long d) 
00273 {
00274   return (d & HALF_DIGIT_MASK);
00275 }
00276 
00277 // Return the high half part of d. The high part of the digit may have
00278 // more bits than BITS_PER_HALF_DIGIT due to, e.g., overflow in the
00279 // multiplication. Hence, in other functions that use high_half(),
00280 // make sure that the result contains BITS_PER_HALF_DIGIT if
00281 // necessary. This is done by high_half_masked().
00282 inline 
00283 unsigned long 
00284 high_half(unsigned long d) 
00285 {
00286   return (d >> BITS_PER_HALF_DIGIT);
00287 }
00288 
00289 inline
00290 unsigned long
00291 high_half_masked(unsigned long d)
00292 {
00293   return (high_half(d) & HALF_DIGIT_MASK);
00294 }
00295 
00296 // Concatenate the high part h and low part l. Assumes that h and l
00297 // are less than or equal to HALF_DIGIT_MASK;
00298 inline 
00299 unsigned long 
00300 concat(unsigned long h, unsigned long l) 
00301 {
00302   return ((h << BITS_PER_HALF_DIGIT) | l);
00303 }
00304 
00305 // Create a number with n 1's.
00306 inline
00307 unsigned long
00308 one_and_ones(int n)
00309 {
00310   return (((unsigned long) 1 << n) - 1);
00311 }
00312 
00313 // Create a number with one 1 and n 0's.
00314 inline
00315 unsigned long
00316 one_and_zeros(int n)
00317 {
00318   return ((unsigned long) 1 << n);
00319 }
00320 
00321 
00322 // ----------------------------------------------------------------------------
00323 
00324 // Find the digit that bit i is in.
00325 inline
00326 int 
00327 digit_ord(int i)
00328 {
00329   return (i / BITS_PER_DIGIT);
00330 }
00331 
00332 // Find the bit in digit_ord(i) that bit i corressponds to.
00333 inline
00334 int 
00335 bit_ord(int i)
00336 {
00337   return (i % BITS_PER_DIGIT);
00338 }
00339 
00340 
00341 // ----------------------------------------------------------------------------
00342 //  Functions to compare, zero, complement vector(s).
00343 // ----------------------------------------------------------------------------
00344 
00345 // Compare u and v and return r
00346 //  r = 0 if u == v
00347 //  r < 0 if u < v
00348 //  r > 0 if u > v
00349 // - Assume that all the leading zero digits are already skipped.
00350 // - ulen and/or vlen can be zero.
00351 // - Every digit is less than or equal to DIGIT_MASK;
00352 inline 
00353 int
00354 vec_cmp(int ulen, const unsigned long *u, 
00355         int vlen, const unsigned long *v)
00356 {
00357 
00358 #ifdef DEBUG_SYSTEMC
00359   // assert((ulen <= 0) || (u != NULL));
00360   // assert((vlen <= 0) || (v != NULL));
00361 
00362   // ulen and vlen can be equal to 0 because vec_cmp can be called
00363   // after vec_skip_leading_zeros.
00364   assert((ulen >= 0) && (u != NULL));
00365   assert((vlen >= 0) && (v != NULL));
00366   // If ulen > 0, then the leading digit of u must be non-zero.
00367   assert((ulen <= 0) || (u[ulen - 1] != 0));
00368   assert((vlen <= 0) || (v[vlen - 1] != 0));
00369 #endif
00370 
00371   if (ulen != vlen)
00372     return (ulen - vlen);
00373 
00374   // ulen == vlen >= 1
00375   while ((--ulen >= 0) && (u[ulen] == v[ulen]))
00376     ;
00377 
00378   if (ulen < 0)
00379     return 0;
00380 
00381 #ifdef DEBUG_SYSTEMC
00382   // Test to see if the result is wrong due to the presence of
00383   // overflow bits.
00384   assert((u[ulen] & DIGIT_MASK) != (v[ulen] & DIGIT_MASK));
00385 #endif
00386 
00387   return (int) (u[ulen] - v[ulen]);
00388 
00389 }
00390 
00391 // Find the index of the first non-zero digit.
00392 // - ulen (before) = the number of digits in u.
00393 // - the returned value = the index of the first non-zero digit. 
00394 // A negative value of -1 indicates that every digit in u is zero.
00395 inline
00396 int
00397 vec_find_first_nonzero(int ulen, const unsigned long *u)
00398 {
00399 
00400 #ifdef DEBUG_SYSTEMC
00401   // assert((ulen <= 0) || (u != NULL));
00402   assert((ulen > 0) && (u != NULL));
00403 #endif
00404 
00405   while ((--ulen >= 0) && (! u[ulen]))
00406     ;
00407 
00408   return ulen;
00409   
00410 }
00411 
00412 // Skip all the leading zero digits.  
00413 // - ulen (before) = the number of digits in u.
00414 // - the returned value = the number of non-zero digits in u.
00415 // - the returned value is non-negative.
00416 inline 
00417 int
00418 vec_skip_leading_zeros(int ulen, const unsigned long *u)
00419 {
00420 
00421 #ifdef DEBUG_SYSTEMC
00422   // assert((ulen <= 0) || (u != NULL));
00423   assert((ulen > 0) && (u != NULL));
00424 #endif
00425 
00426   return (1 + vec_find_first_nonzero(ulen, u));
00427 
00428 }
00429 
00430 // Compare u and v and return r
00431 //  r = 0 if u == v
00432 //  r < 0 if u < v
00433 //  r > 0 if u > v
00434 inline 
00435 int 
00436 vec_skip_and_cmp(int ulen, const unsigned long *u, 
00437                  int vlen, const unsigned long *v)
00438 {
00439 
00440 #ifdef DEBUG_SYSTEMC
00441   assert((ulen > 0) && (u != NULL));
00442   assert((vlen > 0) && (v != NULL));
00443 #endif
00444 
00445   ulen = vec_skip_leading_zeros(ulen, u);
00446   vlen = vec_skip_leading_zeros(vlen, v);
00447   // ulen and/or vlen can be equal to zero here.
00448   return vec_cmp(ulen, u, vlen, v);
00449 
00450 }
00451 
00452 // Set u[i] = 0 where i = from ... (ulen - 1).
00453 inline
00454 void
00455 vec_zero(int from, int ulen, unsigned long *u)
00456 {
00457 
00458 #ifdef DEBUG_SYSTEMC
00459   assert((ulen > 0) && (u != NULL));
00460 #endif
00461 
00462   for(int i = from; i < ulen; i++)
00463     u[i] = 0;
00464 
00465 }
00466 
00467 // Set u[i] = 0 where i = 0 .. (ulen - 1).
00468 inline
00469 void
00470 vec_zero(int ulen, unsigned long *u)
00471 {
00472   vec_zero(0, ulen, u);
00473 }
00474 
00475 // Copy n digits from v to u.
00476 inline
00477 void
00478 vec_copy(int n, unsigned long *u, const unsigned long *v)
00479 {
00480 
00481 #ifdef DEBUG_SYSTEMC
00482   assert((n > 0) && (u != NULL) && (v != NULL));
00483 #endif
00484 
00485   for (register int i = 0; i < n; ++i)
00486     u[i] = v[i];
00487 }
00488 
00489 // Copy v to u, where ulen >= vlen, and zero the rest of the digits in u.
00490 inline
00491 void
00492 vec_copy_and_zero(int ulen, unsigned long *u, 
00493                   int vlen, const unsigned long *v)
00494 {
00495 
00496 #ifdef DEBUG_SYSTEMC
00497   assert((ulen > 0) && (u != NULL));
00498   assert((vlen > 0) && (v != NULL));
00499   assert(ulen >= vlen);
00500 #endif
00501 
00502   vec_copy(vlen, u, v);
00503   vec_zero(vlen, ulen, u);
00504 
00505 }
00506 
00507 // 2's-complement the digits in u.
00508 inline
00509 void
00510 vec_complement(int ulen, unsigned long *u)
00511 {
00512 
00513 #ifdef DEBUG_SYSTEMC
00514   assert((ulen > 0) && (u != NULL));
00515 #endif
00516 
00517   register unsigned long carry = 1;
00518 
00519   for (register int i = 0; i < ulen; ++i) {
00520     carry += (~u[i] & DIGIT_MASK);
00521     u[i] = carry & DIGIT_MASK;
00522     carry >>= BITS_PER_DIGIT;
00523   }
00524   
00525 }
00526 
00527 
00528 // ----------------------------------------------------------------------------
00529 //  Functions to handle built-in types or signs.
00530 // ----------------------------------------------------------------------------
00531 
00532 // u = v
00533 // - v is an unsigned long or uint64, and positive integer.
00534 template< class Type >
00535 inline
00536 void
00537 from_uint(int ulen, unsigned long *u, Type v)
00538 {
00539 
00540 #ifdef DEBUG_SYSTEMC
00541   // assert((ulen <= 0) || (u != NULL));
00542   assert((ulen > 0) && (u != NULL));
00543   assert(v >= 0);
00544 #endif
00545 
00546   register int i = 0;
00547 
00548   while (v && (i < ulen)) {
00549 #ifndef WIN32
00550     u[i++] = static_cast<unsigned long>( v & DIGIT_MASK );
00551 #else
00552     u[i++] = ((unsigned long) v) & DIGIT_MASK;
00553 #endif
00554     v >>= BITS_PER_DIGIT;
00555   }
00556 
00557   vec_zero(i, ulen, u);
00558 
00559 }
00560 
00561 
00562 // Get u's sign and return its absolute value.
00563 // u can be long, unsigned long, int64, or uint64.
00564 template< class Type >
00565 inline
00566 small_type
00567 get_sign(Type &u) 
00568 {
00569   if (u > 0)
00570     return SC_POS;
00571 
00572   else if (u == 0)
00573     return SC_ZERO;
00574 
00575   else {
00576     u = -u;
00577     return SC_NEG;
00578   }
00579 }
00580 
00581 
00582 // Return us * vs:
00583 // - Return SC_ZERO if either sign is SC_ZERO.
00584 // - Return SC_POS if us == vs
00585 // - Return SC_NEG if us != vs.
00586 inline
00587 small_type
00588 mul_signs(small_type us, small_type vs)
00589 {
00590   if ((us == SC_ZERO) || (vs == SC_ZERO))
00591     return SC_ZERO;
00592 
00593   if (us == vs)
00594     return SC_POS;
00595 
00596   return SC_NEG;
00597 }
00598 
00599 
00600 // ----------------------------------------------------------------------------
00601 //  Functions to test for errors and print out error messages.
00602 // ----------------------------------------------------------------------------
00603 
00604 #ifdef SC_MAX_NBITS
00605 
00606 inline
00607 void
00608 test_bound(int nb)
00609 {
00610   if (nb > SC_MAX_NBITS) {
00611       char msg[BUFSIZ];
00612       sprintf( msg, "test_bound( int nb ) : "
00613                "nb = %d > SC_MAX_NBITS = %d is not valid",
00614                nb, SC_MAX_NBITS );
00615       SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
00616   }
00617 }
00618 
00619 #endif
00620 
00621 template< class Type >
00622 inline
00623 void
00624 div_by_zero(Type s)
00625 {
00626   if (s == 0) {
00627       SC_REPORT_ERROR( sc_core::SC_ID_OPERATION_FAILED_,
00628                        "div_by_zero<Type>( Type ) : division by zero" );
00629   }
00630 }
00631 
00632 
00633 // ----------------------------------------------------------------------------
00634 //  Functions to check if a given vector is zero or make one.
00635 // ----------------------------------------------------------------------------
00636 
00637 // If u[i] is zero for every i = 0,..., ulen - 1, return SC_ZERO,
00638 // else return s.
00639 inline
00640 small_type 
00641 check_for_zero(small_type s, int ulen, const unsigned long *u)
00642 {
00643 
00644 #ifdef DEBUG_SYSTEMC
00645   // assert(ulen >= 0);
00646   assert((ulen > 0) && (u != NULL));
00647 #endif
00648 
00649   if (vec_find_first_nonzero(ulen, u) < 0)
00650     return SC_ZERO;  
00651 
00652   return s;
00653 
00654 }
00655 
00656 // If u[i] is zero for every i = 0,..., ulen - 1, return true,
00657 // else return false.
00658 inline
00659 bool
00660 check_for_zero(int ulen, const unsigned long *u)
00661 {
00662 
00663 #ifdef DEBUG_SYSTEMC
00664   // assert(ulen >= 0);
00665   assert((ulen > 0) && (u != NULL));
00666 #endif
00667 
00668   if (vec_find_first_nonzero(ulen, u) < 0)
00669     return true;
00670 
00671   return false;
00672 
00673 }
00674 
00675 inline
00676 small_type
00677 make_zero(int nd, unsigned long *d)
00678 {
00679   vec_zero(nd, d);
00680   return SC_ZERO;
00681 }
00682 
00683 
00684 // ----------------------------------------------------------------------------
00685 //  Functions for both signed and unsigned numbers to convert sign-magnitude
00686 //  (SM) and 2's complement (2C) representations.
00687 //  added = 1 => for signed.
00688 //  added = 0 => for unsigned.
00689 //  IF_SC_SIGNED can be used as 'added'.
00690 // ----------------------------------------------------------------------------
00691 
00692 // Trim the extra leading bits of a signed or unsigned number.
00693 inline
00694 void
00695 trim(small_type added, int nb, int nd, unsigned long *d)
00696 {
00697 #ifdef DEBUG_SYSTEMC
00698   assert((nb > 0) && (nd > 0) && (d != NULL));
00699 #endif
00700 
00701   d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + added);    
00702 }
00703 
00704 // Convert an (un)signed number from sign-magnitude representation to
00705 // 2's complement representation and trim the extra bits.
00706 inline
00707 void
00708 convert_SM_to_2C_trimmed(small_type added, 
00709                          small_type s, int nb, int nd, unsigned long *d)
00710 {
00711   if (s == SC_NEG) {
00712     vec_complement(nd, d);
00713     trim(added, nb, nd, d);
00714   }
00715 }
00716 
00717 // Convert an (un)signed number from sign-magnitude representation to
00718 // 2's complement representation but do not trim the extra bits.
00719 inline
00720 void
00721 convert_SM_to_2C(small_type s, int nd, unsigned long *d)
00722 {
00723   if (s == SC_NEG)
00724     vec_complement(nd, d);
00725 }
00726 
00727 
00728 // ----------------------------------------------------------------------------
00729 //  Functions to convert between sign-magnitude (SM) and 2's complement
00730 //  (2C) representations of signed numbers.
00731 // ----------------------------------------------------------------------------
00732 
00733 // Trim the extra leading bits off a signed number.
00734 inline
00735 void
00736 trim_signed(int nb, int nd, unsigned long *d)
00737 {
00738 #ifdef DEBUG_SYSTEMC
00739   assert((nb > 0) && (nd > 0) && (d != NULL));
00740 #endif
00741 
00742   d[nd - 1] &= one_and_ones(bit_ord(nb - 1) + 1);
00743 }
00744 
00745 // Convert a signed number from 2's complement representation to
00746 // sign-magnitude representation, and return its sign. nd is d's
00747 // actual size, without zeros eliminated.
00748 inline
00749 small_type
00750 convert_signed_2C_to_SM(int nb, int nd, unsigned long *d)
00751 {
00752 
00753 #ifdef DEBUG_SYSTEMC
00754   assert((nb > 0) && (nd > 0) && (d != NULL));
00755 #endif
00756 
00757   small_type s;
00758 
00759   int xnb = bit_ord(nb - 1) + 1;
00760 
00761   // Test the sign bit.  
00762   if (d[nd - 1] & one_and_zeros(xnb - 1)) {
00763     s = SC_NEG;
00764     vec_complement(nd, d);
00765   }
00766   else
00767     s = SC_POS;
00768 
00769   // Trim the last digit.
00770   d[nd - 1] &= one_and_ones(xnb);
00771 
00772   // Check if the new number is zero.
00773   if (s == SC_POS)
00774     return check_for_zero(s, nd, d);
00775 
00776   return s;
00777 
00778 }
00779 
00780 // Convert a signed number from sign-magnitude representation to 2's
00781 // complement representation, get its sign, convert back to
00782 // sign-magnitude representation, and return its sign. nd is d's
00783 // actual size, without zeros eliminated.
00784 inline
00785 small_type 
00786 convert_signed_SM_to_2C_to_SM(small_type s, int nb, int nd, unsigned long *d)
00787 {
00788   convert_SM_to_2C(s, nd, d);
00789   return convert_signed_2C_to_SM(nb, nd, d);
00790 }
00791 
00792 // Convert a signed number from sign-magnitude representation to 2's
00793 // complement representation and trim the extra bits.
00794 inline
00795 void
00796 convert_signed_SM_to_2C_trimmed(small_type s, int nb, int nd, unsigned long *d)
00797 {
00798   convert_SM_to_2C_trimmed(1, s, nb, nd, d);
00799 }
00800 
00801 // Convert a signed number from sign-magnitude representation to 2's
00802 // complement representation but do not trim the extra bits.
00803 inline
00804 void
00805 convert_signed_SM_to_2C(small_type s, int nd, unsigned long *d)
00806 {
00807   convert_SM_to_2C(s, nd, d);
00808 }
00809 
00810 
00811 // ----------------------------------------------------------------------------
00812 //  Functions to convert between sign-magnitude (SM) and 2's complement
00813 //  (2C) representations of unsigned numbers.
00814 // ----------------------------------------------------------------------------
00815 
00816 // Trim the extra leading bits off an unsigned number.
00817 inline
00818 void
00819 trim_unsigned(int nb, int nd, unsigned long *d)
00820 {
00821 #ifdef DEBUG_SYSTEMC
00822   assert((nb > 0) && (nd > 0) && (d != NULL));
00823 #endif
00824 
00825   d[nd - 1] &= one_and_ones(bit_ord(nb - 1));    
00826 }
00827 
00828 // Convert an unsigned number from 2's complement representation to
00829 // sign-magnitude representation, and return its sign. nd is d's
00830 // actual size, without zeros eliminated.
00831 inline
00832 small_type
00833 convert_unsigned_2C_to_SM(int nb, int nd, unsigned long *d)
00834 {
00835   trim_unsigned(nb, nd, d);
00836   return check_for_zero(SC_POS, nd, d);
00837 }
00838 
00839 // Convert an unsigned number from sign-magnitude representation to
00840 // 2's complement representation, get its sign, convert back to
00841 // sign-magnitude representation, and return its sign. nd is d's
00842 // actual size, without zeros eliminated.
00843 inline
00844 small_type
00845 convert_unsigned_SM_to_2C_to_SM(small_type s, int nb, int nd, unsigned long *d)
00846 {
00847   convert_SM_to_2C(s, nd, d);
00848   return convert_unsigned_2C_to_SM(nb, nd, d);
00849 }
00850 
00851 // Convert an unsigned number from sign-magnitude representation to
00852 // 2's complement representation and trim the extra bits.
00853 inline
00854 void
00855 convert_unsigned_SM_to_2C_trimmed(small_type s, int nb, int nd, unsigned long *d)
00856 {
00857   convert_SM_to_2C_trimmed(0, s, nb, nd, d);
00858 }
00859 
00860 // Convert an unsigned number from sign-magnitude representation to
00861 // 2's complement representation but do not trim the extra bits.
00862 inline
00863 void
00864 convert_unsigned_SM_to_2C(small_type s, int nd, unsigned long *d)
00865 {
00866   convert_SM_to_2C(s, nd, d);
00867 }
00868 
00869 
00870 // ----------------------------------------------------------------------------
00871 //  Functions to copy one (un)signed number to another.
00872 // ----------------------------------------------------------------------------
00873 
00874 // Copy v to u.
00875 inline
00876 void
00877 copy_digits_signed(small_type &us, 
00878                    int unb, int und, unsigned long *ud,
00879                    int vnb, int vnd, const unsigned long *vd)
00880 {
00881 
00882   if (und <= vnd) {
00883 
00884     vec_copy(und, ud, vd);
00885 
00886     if (unb <= vnb)
00887       us = convert_signed_SM_to_2C_to_SM(us, unb, und, ud);
00888 
00889   }
00890   else // und > vnd
00891     vec_copy_and_zero(und, ud, vnd, vd);
00892 
00893 }
00894 
00895 // Copy v to u.
00896 inline
00897 void
00898 copy_digits_unsigned(small_type &us, 
00899                      int unb, int und, unsigned long *ud,
00900                      int vnb, int vnd, const unsigned long *vd)
00901 {
00902 
00903   if (und <= vnd)
00904     vec_copy(und, ud, vd);
00905 
00906   else // und > vnd
00907     vec_copy_and_zero(und, ud, vnd, vd);
00908 
00909   us = convert_unsigned_SM_to_2C_to_SM(us, unb, und, ud);
00910 
00911 }
00912 
00913 
00914 // ----------------------------------------------------------------------------
00915 //  Faster set(i, v), without bound checking.
00916 // ----------------------------------------------------------------------------
00917 
00918 // A version of set(i, v) without bound checking.
00919 inline
00920 void
00921 safe_set(int i, bool v, unsigned long *d)
00922 {
00923 
00924 #ifdef DEBUG_SYSTEMC
00925   assert((i >= 0) && (d != NULL));
00926 #endif
00927 
00928   int bit_num = bit_ord(i);
00929   int digit_num = digit_ord(i);    
00930   
00931   if (v)
00932     d[digit_num] |= one_and_zeros(bit_num);      
00933   else
00934     d[digit_num] &= ~(one_and_zeros(bit_num));
00935   
00936 }
00937 
00938 
00939 // ----------------------------------------------------------------------------
00940 //  Function to check if a double number is bad (NaN or infinite).
00941 // ----------------------------------------------------------------------------
00942 
00943 inline
00944 void
00945 is_bad_double(double v)
00946 {
00947 // Windows throws exception.
00948 #if !defined(WIN32) && !defined(i386) && !defined( __EDG__ )
00949 #if defined( __hpux ) && defined( isfinite )
00950   // HP-UX 11.00 does not have finite anymore
00951   if( ! isfinite( v ) ) {
00952 #else
00953   if (! finite(v)) {
00954 #endif
00955       SC_REPORT_ERROR( sc_core::SC_ID_VALUE_NOT_VALID_,
00956                        "is_bad_double( double v ) : "
00957                        "v is not finite - NaN or Inf" );
00958   }
00959 #endif
00960 }
00961 
00962 } // namespace sc_dt
00963 
00964 
00965 #endif

Generated on Wed Apr 25 13:53:27 2007 for SystemC by  doxygen 1.5.1