SystemC  2.3.1
Accellera SystemC proof-of-concept library
scfx_ieee.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  The following code is derived, directly or indirectly, from the SystemC
4  source code Copyright (c) 1996-2014 by all Contributors.
5  All Rights reserved.
6 
7  The contents of this file are subject to the restrictions and limitations
8  set forth in the SystemC Open Source License (the "License");
9  You may not use this file except in compliance with such restrictions and
10  limitations. You may obtain instructions on how to receive a copy of the
11  License at http://www.accellera.org/. Software distributed by Contributors
12  under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
13  ANY KIND, either express or implied. See the License for the specific
14  language governing rights and limitations under the License.
15 
16  *****************************************************************************/
17 
18 /*****************************************************************************
19 
20  scfx_ieee.h -
21 
22  Original Author: Martin Janssen, Synopsys, Inc.
23 
24  *****************************************************************************/
25 
26 /*****************************************************************************
27 
28  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
29  changes you are making here.
30 
31  Name, Affiliation, Date:
32  Description of Modification:
33 
34  *****************************************************************************/
35 
36 // $Log: scfx_ieee.h,v $
37 // Revision 1.3 2011/08/24 22:05:43 acg
38 // Torsten Maehne: initialization changes to remove warnings.
39 //
40 // Revision 1.2 2011/08/07 18:55:24 acg
41 // Philipp A. Hartmann: added guard for __clang__ to get the clang platform
42 // working.
43 //
44 // Revision 1.1.1.1 2006/12/15 20:20:04 acg
45 // SystemC 2.3
46 //
47 // Revision 1.3 2006/01/13 18:53:58 acg
48 // Andy Goodrich: added $Log command so that CVS comments are reproduced in
49 // the source.
50 //
51 
52 #ifndef SCFX_IEEE_H
53 #define SCFX_IEEE_H
54 
55 
57 
58 
59 namespace sc_dt
60 {
61 
62 // classes defined in this module
63 union ieee_double;
64 class scfx_ieee_double;
65 union ieee_float;
66 class scfx_ieee_float;
67 
68 #define SCFX_MASK_(Size) \
69  ((1u << (Size))-1u)
70 
71 // ----------------------------------------------------------------------------
72 // UNION : ieee_double
73 //
74 // IEEE 754 double-precision format.
75 // ----------------------------------------------------------------------------
76 
78 {
79 
80  double d;
81 
82  struct
83  {
84 #if defined( SC_BIG_ENDIAN )
85  unsigned negative:1;
86  unsigned exponent:11;
87  unsigned mantissa0:20;
88  unsigned mantissa1:32;
89 #elif defined( SC_LITTLE_ENDIAN )
90  unsigned mantissa1:32;
91  unsigned mantissa0:20;
92  unsigned exponent:11;
93  unsigned negative:1;
94 #endif
95  } s;
96 
97 };
98 
99 
100 const unsigned int SCFX_IEEE_DOUBLE_BIAS = 1023U;
101 
102 const int SCFX_IEEE_DOUBLE_E_MAX = 1023;
103 const int SCFX_IEEE_DOUBLE_E_MIN = -1022;
104 
105 const unsigned int SCFX_IEEE_DOUBLE_M_SIZE = 52;
106 const unsigned int SCFX_IEEE_DOUBLE_M0_SIZE = 20;
107 const unsigned int SCFX_IEEE_DOUBLE_M1_SIZE = 32;
108 const unsigned int SCFX_IEEE_DOUBLE_E_SIZE = 11;
109 
110 
111 
112 // ----------------------------------------------------------------------------
113 // CLASS : scfx_ieee_double
114 //
115 // Convenient interface to union ieee_double.
116 // ----------------------------------------------------------------------------
117 
119 {
120 
121  ieee_double m_id;
122 
123 public:
124 
126  scfx_ieee_double( double );
128 
129  scfx_ieee_double& operator = ( double );
131 
132  operator double() const;
133 
134  unsigned int negative() const;
135  void negative( unsigned int );
136  int exponent() const;
137  void exponent( int );
138  unsigned int mantissa0() const;
139  void mantissa0( unsigned int );
140  unsigned int mantissa1() const;
141  void mantissa1( unsigned int );
142 
143  bool is_zero() const;
144  bool is_subnormal() const;
145  bool is_normal() const;
146  bool is_inf() const;
147  bool is_nan() const;
148 
149  void set_inf();
150  void set_nan();
151 
152  int msb() const; // most significant non-zero bit
153  int lsb() const; // least significant non-zero bit
154 
155  static const scfx_ieee_double nan();
156  static const scfx_ieee_double inf( int );
157 
158 };
159 
160 
161 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
162 
163 inline
165 {
166  m_id.d = 0.0;
167 }
168 
169 inline
171 {
172  m_id.d = d;
173 }
174 
175 inline
177 {
178  // m_id.d = a.m_id.d;
179 }
180 
181 
182 inline
185 {
186  m_id.d = d;
187  return *this;
188 }
189 
190 inline
193 {
194  m_id.d = a.m_id.d;
195  return *this;
196 }
197 
198 
199 inline
200 scfx_ieee_double::operator double() const
201 {
202  return m_id.d;
203 }
204 
205 
206 inline
207 unsigned int
209 {
210  return m_id.s.negative;
211 }
212 
213 inline
214 void
215 scfx_ieee_double::negative( unsigned int a )
216 {
217  m_id.s.negative = a & SCFX_MASK_(1);
218 }
219 
220 inline
221 int
223 {
224  return m_id.s.exponent - SCFX_IEEE_DOUBLE_BIAS;
225 }
226 
227 inline
228 void
230 {
231  m_id.s.exponent = (SCFX_IEEE_DOUBLE_BIAS + a)
233 }
234 
235 inline
236 unsigned int
238 {
239  return m_id.s.mantissa0;
240 }
241 
242 inline
243 void
245 {
246  m_id.s.mantissa0 = a & SCFX_MASK_(SCFX_IEEE_DOUBLE_M0_SIZE);
247 }
248 
249 inline
250 unsigned int
252 {
253  return m_id.s.mantissa1;
254 }
255 
256 inline
257 void
259 {
260  m_id.s.mantissa1 = a; // & SCFX_MASK_(SCFX_IEEE_DOUBLE_M1_SIZE);
261 }
262 
263 
264 inline
265 bool
267 {
268  return ( exponent() == SCFX_IEEE_DOUBLE_E_MIN - 1 &&
269  mantissa0() == 0U && mantissa1() == 0U );
270 }
271 
272 inline
273 bool
275 {
276  return ( exponent() == SCFX_IEEE_DOUBLE_E_MIN - 1 &&
277  ( mantissa0() != 0U || mantissa1() != 0U ) );
278 }
279 
280 inline
281 bool
283 {
284  return ( exponent() >= SCFX_IEEE_DOUBLE_E_MIN &&
286 }
287 
288 inline
289 bool
291 {
292  return ( exponent() == SCFX_IEEE_DOUBLE_E_MAX + 1 &&
293  mantissa0() == 0U && mantissa1() == 0U );
294 }
295 
296 inline
297 bool
299 {
300  return ( exponent() == SCFX_IEEE_DOUBLE_E_MAX + 1 &&
301  ( mantissa0() != 0U || mantissa1() != 0U ) );
302 }
303 
304 
305 inline
306 void
308 {
310  mantissa0( 0U );
311  mantissa1( 0U );
312 }
313 
314 inline
315 void
317 {
319  mantissa0( (unsigned int) -1 );
320  mantissa1( (unsigned int) -1 );
321 }
322 
323 
324 #define MSB_STATEMENT(x,n) if( x >> n ) { x >>= n; i += n; }
325 
326 inline
327 int
329 {
330  unsigned int m0 = mantissa0();
331  unsigned int m1 = mantissa1();
332  if( m0 != 0 )
333  {
334  int i = 0;
335  MSB_STATEMENT(m0,16);
336  MSB_STATEMENT(m0,8);
337  MSB_STATEMENT(m0,4);
338  MSB_STATEMENT(m0,2);
339  MSB_STATEMENT(m0,1);
340  return ( i - 20 );
341  }
342  else if( m1 != 0 )
343  {
344  int i = 0;
345  MSB_STATEMENT(m1,16);
346  MSB_STATEMENT(m1,8);
347  MSB_STATEMENT(m1,4);
348  MSB_STATEMENT(m1,2);
349  MSB_STATEMENT(m1,1);
350  return ( i - 52 );
351  }
352  else
353  {
354  return 0;
355  }
356 }
357 
358 #undef MSB_STATEMENT
359 
360 #define LSB_STATEMENT(x,n) if( x << n ) { x <<= n; i -= n; }
361 
362 inline
363 int
365 {
366  unsigned int m0 = mantissa0();
367  unsigned int m1 = mantissa1();
368  if( m1 != 0 )
369  {
370  int i = 31;
371  LSB_STATEMENT(m1,16);
372  LSB_STATEMENT(m1,8);
373  LSB_STATEMENT(m1,4);
374  LSB_STATEMENT(m1,2);
375  LSB_STATEMENT(m1,1);
376  return ( i - 52 );
377  }
378  else if( m0 != 0 )
379  {
380  int i = 31;
381  LSB_STATEMENT(m0,16);
382  LSB_STATEMENT(m0,8);
383  LSB_STATEMENT(m0,4);
384  LSB_STATEMENT(m0,2);
385  LSB_STATEMENT(m0,1);
386  return ( i - 20 );
387  }
388  else
389  {
390  return 0;
391  }
392 }
393 
394 #undef LSB_STATEMENT
395 
396 
397 inline
398 const scfx_ieee_double
400 {
401  scfx_ieee_double id;
402  id.set_nan();
403  return id;
404 }
405 
406 inline
407 const scfx_ieee_double
409 {
410  scfx_ieee_double id( sign );
411  id.set_inf();
412  return id;
413 }
414 
415 
416 // ----------------------------------------------------------------------------
417 // UNION : ieee_float
418 //
419 // IEEE 754 single-precision format.
420 // ----------------------------------------------------------------------------
421 
423 {
424 
425  float f;
426 
427  struct
428  {
429 #if defined( SC_BIG_ENDIAN )
430  unsigned negative:1;
431  unsigned exponent:8;
432  unsigned mantissa:23;
433 #elif defined( SC_LITTLE_ENDIAN )
434  unsigned mantissa:23;
435  unsigned exponent:8;
436  unsigned negative:1;
437 #endif
438  } s;
439 
440 };
441 
442 
443 const unsigned int SCFX_IEEE_FLOAT_BIAS = 127U;
444 
445 const int SCFX_IEEE_FLOAT_E_MAX = 127;
446 const int SCFX_IEEE_FLOAT_E_MIN = -126;
447 
448 const unsigned int SCFX_IEEE_FLOAT_M_SIZE = 23;
449 const unsigned int SCFX_IEEE_FLOAT_E_SIZE = 8;
450 
451 
452 // ----------------------------------------------------------------------------
453 // CLASS : scfx_ieee_float
454 //
455 // Convenient wrapper to union ieee_float.
456 // ----------------------------------------------------------------------------
457 
459 {
460 
461  ieee_float m_if;
462 
463 public:
464 
465  scfx_ieee_float();
466  scfx_ieee_float( float );
468 
469  scfx_ieee_float& operator = ( float );
471 
472  operator float() const;
473 
474  unsigned int negative() const;
475  void negative( unsigned int );
476  int exponent() const;
477  void exponent( int );
478  unsigned int mantissa() const;
479  void mantissa( unsigned int );
480 
481  bool is_zero() const;
482  bool is_subnormal() const;
483  bool is_normal() const;
484  bool is_inf() const;
485  bool is_nan() const;
486 
487  void set_inf();
488  void set_nan();
489 
490 };
491 
492 
493 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
494 
495 inline
497 {
498  m_if.f = 0.0;
499 }
500 
501 inline
503 {
504  m_if.f = f;
505 }
506 
507 inline
509 {
510  // m_if.f = a.m_if.f;
511 }
512 
513 
514 inline
517 {
518  m_if.f = f;
519  return *this;
520 }
521 
522 inline
525 {
526  m_if.f = a.m_if.f;
527  return *this;
528 }
529 
530 
531 inline
532 scfx_ieee_float::operator float() const
533 {
534  return m_if.f;
535 }
536 
537 
538 inline
539 unsigned int
541 {
542  return m_if.s.negative;
543 }
544 
545 inline
546 void
547 scfx_ieee_float::negative( unsigned int a )
548 {
549  m_if.s.negative = a & SCFX_MASK_(1);
550 }
551 
552 inline
553 int
555 {
556  return m_if.s.exponent - SCFX_IEEE_FLOAT_BIAS;
557 }
558 
559 inline
560 void
562 {
563  m_if.s.exponent = (SCFX_IEEE_FLOAT_BIAS + a)
565 }
566 
567 inline
568 unsigned int
570 {
571  return m_if.s.mantissa;
572 }
573 
574 inline
575 void
576 scfx_ieee_float::mantissa( unsigned int a )
577 {
578  m_if.s.mantissa = a & SCFX_MASK_(SCFX_IEEE_FLOAT_M_SIZE);
579 }
580 
581 
582 inline
583 bool
585 {
586  return ( exponent() == SCFX_IEEE_FLOAT_E_MIN - 1 && mantissa() == 0U );
587 }
588 
589 inline
590 bool
592 {
593  return ( exponent() == SCFX_IEEE_FLOAT_E_MIN - 1 && mantissa() != 0U );
594 }
595 
596 inline
597 bool
599 {
600  return ( exponent() >= SCFX_IEEE_FLOAT_E_MIN &&
602 }
603 
604 inline
605 bool
607 {
608  return ( exponent() == SCFX_IEEE_FLOAT_E_MAX + 1 && mantissa() == 0U );
609 }
610 
611 inline
612 bool
614 {
615  return ( exponent() == SCFX_IEEE_FLOAT_E_MAX + 1 && mantissa() != 0U );
616 }
617 
618 
619 inline
620 void
622 {
624  mantissa( 0U );
625 }
626 
627 inline
628 void
630 {
632  mantissa( (unsigned int) -1 );
633 }
634 
635 
636 // ----------------------------------------------------------------------------
637 // FUNCTION : scfx_pow2
638 //
639 // Computes 2.0**exp in double-precision.
640 // ----------------------------------------------------------------------------
641 
642 inline
643 double scfx_pow2( int exp )
644 {
646  if( exp < SCFX_IEEE_DOUBLE_E_MIN )
647  {
648  r = 0.0;
649  // handle subnormal case
650  exp -= SCFX_IEEE_DOUBLE_E_MIN;
651  if( ( exp += 20 ) >= 0 )
652  {
653  r.mantissa0( 1U << exp );
654  }
655  else if( ( exp += 32 ) >= 0 )
656  {
657  r.mantissa1( 1U << exp );
658  }
659  }
660  else if( exp > SCFX_IEEE_DOUBLE_E_MAX )
661  {
662  r.set_inf();
663  }
664  else
665  {
666  r = 1.0;
667  r.exponent( exp );
668  }
669  return r;
670 }
671 
672 
673 // ----------------------------------------------------------------------------
674 // FUNCTION : uint64_to_double
675 //
676 // Platform independent conversion from double uint64 to double.
677 // Needed because VC++6 doesn't support this conversion.
678 // ----------------------------------------------------------------------------
679 
680 inline
681 double
683 {
684 #if defined( _MSC_VER ) || defined( __clang__ )
685  // conversion from uint64 to double not implemented; use int64
686  double tmp = static_cast<double>( static_cast<int64>( a ) );
687  return ( tmp >= 0 ) ? tmp : tmp + sc_dt::scfx_pow2( 64 );
688 #else
689  return static_cast<double>( a );
690 #endif
691 }
692 
693 } // namespace sc_dt
694 
695 #undef SCFX_MASK_
696 
697 #endif
698 
699 // Taf!
const unsigned int SCFX_IEEE_FLOAT_M_SIZE
Definition: scfx_ieee.h:448
bool is_zero() const
Definition: scfx_ieee.h:584
bool is_nan() const
Definition: scfx_ieee.h:298
scfx_ieee_double & operator=(double)
Definition: scfx_ieee.h:184
int exponent() const
Definition: scfx_ieee.h:222
const int SCFX_IEEE_DOUBLE_E_MIN
Definition: scfx_ieee.h:103
const unsigned int SCFX_IEEE_DOUBLE_M_SIZE
Definition: scfx_ieee.h:105
const unsigned int SCFX_IEEE_DOUBLE_M1_SIZE
Definition: scfx_ieee.h:107
uint64_t uint64
Definition: sc_nbdefs.h:183
unsigned int mantissa0() const
Definition: scfx_ieee.h:237
bool is_subnormal() const
Definition: scfx_ieee.h:274
bool is_normal() const
Definition: scfx_ieee.h:282
bool is_normal() const
Definition: scfx_ieee.h:598
const int SCFX_IEEE_FLOAT_E_MIN
Definition: scfx_ieee.h:446
double uint64_to_double(uint64 a)
Definition: scfx_ieee.h:682
bool is_inf() const
Definition: scfx_ieee.h:606
const unsigned int SCFX_IEEE_FLOAT_E_SIZE
Definition: scfx_ieee.h:449
unsigned int negative() const
Definition: scfx_ieee.h:208
int64_t int64
Definition: sc_nbdefs.h:182
const unsigned int SCFX_IEEE_DOUBLE_E_SIZE
Definition: scfx_ieee.h:108
const int SCFX_IEEE_DOUBLE_E_MAX
Definition: scfx_ieee.h:102
bool is_subnormal() const
Definition: scfx_ieee.h:591
unsigned int mantissa1() const
Definition: scfx_ieee.h:251
const int SCFX_IEEE_FLOAT_E_MAX
Definition: scfx_ieee.h:445
#define MSB_STATEMENT(x, n)
Definition: scfx_ieee.h:324
unsigned int mantissa() const
Definition: scfx_ieee.h:569
static const scfx_ieee_double inf(int)
Definition: scfx_ieee.h:408
const unsigned int SCFX_IEEE_DOUBLE_M0_SIZE
Definition: scfx_ieee.h:106
double scfx_pow2(int exp)
Definition: scfx_ieee.h:643
scfx_ieee_float & operator=(float)
Definition: scfx_ieee.h:516
unsigned int negative() const
Definition: scfx_ieee.h:540
static const scfx_ieee_double nan()
Definition: scfx_ieee.h:399
bool is_zero() const
Definition: scfx_ieee.h:266
const unsigned int SCFX_IEEE_DOUBLE_BIAS
Definition: scfx_ieee.h:100
#define SCFX_MASK_(Size)
Definition: scfx_ieee.h:68
bool is_inf() const
Definition: scfx_ieee.h:290
bool is_nan() const
Definition: scfx_ieee.h:613
int exponent() const
Definition: scfx_ieee.h:554
struct sc_dt::ieee_double::@1 s
struct sc_dt::ieee_float::@2 s
#define LSB_STATEMENT(x, n)
Definition: scfx_ieee.h:360
const unsigned int SCFX_IEEE_FLOAT_BIAS
Definition: scfx_ieee.h:443