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