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