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

Generated on Wed Jan 21 15:32:08 2009 for SystemC by  doxygen 1.5.5