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_rep.h -
23
24  Original Author: Robert Graulich, Synopsys, Inc.
25                   Martin Janssen,  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: scfx_rep.h,v $
40// Revision 1.6  2011/08/24 22:05:43  acg
41//  Torsten Maehne: initialization changes to remove warnings.
42//
43// Revision 1.5  2011/07/25 10:20:29  acg
44//  Andy Goodrich: check in aftermath of call to automake.
45//
46// Revision 1.4  2010/12/07 20:09:08  acg
47// Andy Goodrich: Philipp Hartmann's constructor disambiguation fix
48//
49// Revision 1.3  2010/08/03 15:54:52  acg
50//  Andy Goodrich: formatting.
51//
52// Revision 1.2  2010/03/15 18:29:01  acg
53//  Andy Goodrich: Moved default argument specifications from friend
54//  declarations to the actual function signatures.
55//
56// Revision 1.1.1.1  2006/12/15 20:20:04  acg
57// SystemC 2.3
58//
59// Revision 1.4  2006/03/13 20:24:27  acg
60//  Andy Goodrich: Addition of function declarations, e.g., neg_scfx_rep(),
61//  to keep gcc 4.x happy.
62//
63// Revision 1.3  2006/01/13 18:53:58  acg
64// Andy Goodrich: added $Log command so that CVS comments are reproduced in
65// the source.
66//
67
68#ifndef SCFX_REP_H
69#define SCFX_REP_H
70
71
72#include <climits>
73
74#include "sysc/datatypes/fx/scfx_mant.h"
75#include "sysc/datatypes/fx/scfx_params.h"
76#include "sysc/datatypes/fx/scfx_string.h"
77
78
79namespace sc_dt
80{
81
82// classes defined in this module
83class scfx_index;
84class scfx_rep;
85
86// forward class declarations
87class sc_bv_base;
88class sc_signed;
89class sc_unsigned;
90
91// function declarations
92void multiply( scfx_rep&, const scfx_rep&, const scfx_rep&,
93	       int max_wl = SC_DEFAULT_MAX_WL_ );
94scfx_rep*  neg_scfx_rep( const scfx_rep& );
95scfx_rep*  mult_scfx_rep( const scfx_rep&, const scfx_rep&,
96	                  int max_wl = SC_DEFAULT_MAX_WL_ );
97scfx_rep*  div_scfx_rep( const scfx_rep&, const scfx_rep&,
98	                 int max_wl = SC_DEFAULT_DIV_WL_ );
99scfx_rep*  add_scfx_rep( const scfx_rep&, const scfx_rep&,
100	                 int max_wl = SC_DEFAULT_MAX_WL_ );
101scfx_rep*  sub_scfx_rep( const scfx_rep&, const scfx_rep&,
102	                 int max_wl = SC_DEFAULT_MAX_WL_ );
103scfx_rep*  lsh_scfx_rep( const scfx_rep&, int );
104scfx_rep*  rsh_scfx_rep( const scfx_rep&, int );
105int        cmp_scfx_rep( const scfx_rep&, const scfx_rep& );
106
107
108const int min_mant = 4;
109
110const int bits_in_int  = sizeof(int)  * CHAR_BIT;
111const int bits_in_word = sizeof(word) * CHAR_BIT;
112
113
114// ----------------------------------------------------------------------------
115//  CLASS : scfx_index
116// ----------------------------------------------------------------------------
117
118class scfx_index
119{
120
121public:
122
123    scfx_index( int wi_, int bi_ ) : m_wi( wi_ ), m_bi( bi_ ) {}
124
125    int wi() const { return m_wi; }
126    int bi() const { return m_bi; }
127
128    void wi( int wi_ ) { m_wi = wi_; }
129
130private:
131
132    int m_wi;
133    int m_bi;
134
135};
136
137
138// ----------------------------------------------------------------------------
139//  CLASS : scfx_rep
140//
141//  Arbitrary-precision fixed-point implementation class.
142// ----------------------------------------------------------------------------
143
144class scfx_rep
145{
146    enum state
147    {
148        normal,
149        infinity,
150        not_a_number
151    };
152
153public:
154
155    // constructors
156
157             scfx_rep();
158    explicit scfx_rep( int );
159    explicit scfx_rep( unsigned int );
160    explicit scfx_rep( long );
161    explicit scfx_rep( unsigned long );
162    explicit scfx_rep( double );
163    explicit scfx_rep( const char* );
164    explicit scfx_rep( int64 );
165    explicit scfx_rep( uint64 );
166    explicit scfx_rep( const sc_signed& );
167    explicit scfx_rep( const sc_unsigned& );
168
169
170    // copy constructor
171
172             scfx_rep( const scfx_rep& );
173
174
175    // destructor
176
177    ~scfx_rep();
178
179
180    void* operator new( std::size_t );
181    void  operator delete( void*, std::size_t );
182
183
184    void from_string( const char*, int );
185
186    double to_double() const;
187
188    const char* to_string( sc_numrep,
189			   int,
190			   sc_fmt,
191			   const scfx_params* = 0 ) const;
192
193
194    // assignment operator
195
196    void operator = ( const scfx_rep& );
197
198    friend void multiply( scfx_rep&, const scfx_rep&, const scfx_rep&, int );
199
200    friend scfx_rep* neg_scfx_rep( const scfx_rep& );
201    friend scfx_rep* mult_scfx_rep( const scfx_rep&, const scfx_rep&, int );
202    friend scfx_rep* div_scfx_rep( const scfx_rep&, const scfx_rep&, int );
203    friend scfx_rep* add_scfx_rep( const scfx_rep&, const scfx_rep&, int );
204    friend scfx_rep* sub_scfx_rep( const scfx_rep&, const scfx_rep&, int );
205    friend scfx_rep* lsh_scfx_rep( const scfx_rep&, int );
206    friend scfx_rep* rsh_scfx_rep( const scfx_rep&, int );
207
208    void lshift( int );
209    void rshift( int );
210
211    friend int        cmp_scfx_rep( const scfx_rep&, const scfx_rep& );
212
213    void cast( const scfx_params&, bool&, bool& );
214
215    bool is_neg() const;
216    bool is_zero() const;
217    bool is_nan() const;
218    bool is_inf() const;
219    bool is_normal() const;
220
221    void set_zero( int = 1 );
222    void set_nan();
223    void set_inf( int );
224
225    bool   get_bit( int ) const;
226    bool   set( int, const scfx_params& );
227    bool clear( int, const scfx_params& );
228
229    bool get_slice( int, int, const scfx_params&, sc_bv_base& ) const;
230    bool set_slice( int, int, const scfx_params&, const sc_bv_base& );
231
232    void print( ::std::ostream& ) const;
233    void dump( ::std::ostream& ) const;
234
235    void get_type( int&, int&, sc_enc& ) const;
236
237    friend scfx_rep* quantization_scfx_rep( const scfx_rep&,
238					     const scfx_params&,
239					     bool& );
240    friend scfx_rep*     overflow_scfx_rep( const scfx_rep&,
241					     const scfx_params&,
242					     bool& );
243
244    bool rounding_flag() const;
245
246private:
247
248    friend void  align( const scfx_rep&, const scfx_rep&, int&, int&,
249			scfx_mant_ref&, scfx_mant_ref& );
250    friend int   compare_msw( const scfx_rep&, const scfx_rep& );
251    friend int   compare_msw_ff( const scfx_rep& lhs, const scfx_rep& rhs );
252    unsigned int divide_by_ten();
253    int          find_lsw() const;
254    int          find_msw() const;
255    void         find_sw();
256    void         multiply_by_ten();
257    void         normalize( int );
258    scfx_mant*   resize( int, int ) const;
259    void         set_bin( int );
260    void         set_oct( int, int );
261    void         set_hex( int, int );
262    void         shift_left( int );
263    void         shift_right( int );
264
265    const scfx_index calc_indices( int ) const;
266
267    void o_extend( const scfx_index&, sc_enc );
268    bool o_bit_at( const scfx_index& ) const;
269    bool o_zero_left( const scfx_index& ) const;
270    bool o_zero_right( const scfx_index& ) const;
271    void o_set_low( const scfx_index&, sc_enc );
272    void o_set_high( const scfx_index&, const scfx_index&, sc_enc, int = 1 );
273    void o_set( const scfx_index&, const scfx_index&, sc_enc, bool );
274    void o_invert( const scfx_index& );
275    bool q_bit( const scfx_index& ) const;
276    void q_clear( const scfx_index& );
277    void q_incr( const scfx_index& );
278    bool q_odd( const scfx_index& ) const;
279    bool q_zero( const scfx_index& ) const;
280
281    void resize_to( int, int = 0 );
282    int  size() const;
283    void toggle_tc();
284
285    friend void print_dec( scfx_string&, const scfx_rep&, int, sc_fmt );
286    friend void print_other( scfx_string&, const scfx_rep&, sc_numrep, int,
287			     sc_fmt, const scfx_params* );
288
289    void quantization( const scfx_params&, bool& );
290    void     overflow( const scfx_params&, bool& );
291
292    friend int compare_abs( const scfx_rep&, const scfx_rep& );
293
294    void round( int );
295
296private:
297
298    scfx_mant m_mant;     // mantissa (bits of the value).
299    int       m_wp;       // index of highest order word in value.
300    int       m_sign;     // sign of value.
301    state     m_state;    // value state, e.g., normal, inf, etc.
302    int       m_msw;      // index of most significant non-zero word.
303    int       m_lsw;      // index of least significant non-zero word.
304    bool      m_r_flag;   // true if founding occurred.
305
306};
307
308
309// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
310
311inline
312void
313scfx_rep::set_zero( int sign )
314{
315    m_mant.clear();
316    m_wp = m_msw = m_lsw = 0;
317    m_sign = sign;
318    m_state = normal;
319}
320
321inline
322void
323scfx_rep::set_nan()
324{
325    m_mant.resize_to( min_mant );
326    m_state = not_a_number;
327}
328
329inline
330void
331scfx_rep::set_inf( int sign )
332{
333    m_mant.resize_to( min_mant );
334    m_state = infinity;
335    m_sign = sign;
336}
337
338
339// constructors
340
341inline
342scfx_rep::scfx_rep( const char* s )
343: m_mant( min_mant ), m_wp( 2 ), m_sign( 1 ), m_state( normal ),
344  m_msw(0), m_lsw(0), m_r_flag( false )
345{
346    from_string( s, SC_DEFAULT_CTE_WL_ );
347}
348
349
350// destructor
351
352inline
353scfx_rep::~scfx_rep()
354{}
355
356
357// assignment operator
358
359inline
360void
361scfx_rep::operator = ( const scfx_rep& f )
362{
363    if( &f != this )
364    {
365        m_mant  = f.m_mant;
366	m_wp    = f.m_wp;
367	m_sign  = f.m_sign;
368	m_state = f.m_state;
369	m_msw   = f.m_msw;
370	m_lsw   = f.m_lsw;
371	round( SC_DEFAULT_MAX_WL_ );
372    }
373}
374
375inline
376scfx_rep*
377neg_scfx_rep( const scfx_rep& a )
378{
379    scfx_rep& c = *new scfx_rep( a );
380    c.m_sign = - c.m_sign;
381    return &c;
382}
383
384inline
385scfx_rep*
386mult_scfx_rep( const scfx_rep& a, const scfx_rep& b, int max_wl )
387{
388    scfx_rep& c = *new scfx_rep;
389    sc_dt::multiply( c, a, b, max_wl );
390    return &c;
391}
392
393inline
394scfx_rep*
395lsh_scfx_rep( const scfx_rep& a, int b )
396{
397    scfx_rep& c = *new scfx_rep( a );
398    c.lshift( b );
399    return &c;
400}
401
402inline
403scfx_rep*
404rsh_scfx_rep( const scfx_rep& a, int b )
405{
406    scfx_rep& c = *new scfx_rep( a );
407    c.rshift( b );
408    return &c;
409}
410
411inline
412int
413scfx_rep::size() const
414{
415    return m_mant.size();
416}
417
418inline
419bool
420scfx_rep::is_neg() const
421{
422    return ( m_sign == -1 );
423}
424
425inline
426bool
427scfx_rep::is_zero() const
428{
429    if( m_state != normal )
430        return false;
431
432    for( int i = 0; i < size(); i ++ )
433    {
434        if( m_mant[i] )
435	    return false;
436    }
437
438    return true;
439}
440
441inline
442bool
443scfx_rep::is_nan() const
444{
445    return ( m_state == not_a_number );
446}
447
448inline
449bool
450scfx_rep::is_inf() const
451{
452    return ( m_state == infinity );
453}
454
455inline
456bool
457scfx_rep::is_normal() const
458{
459    return ( m_state == normal );
460}
461
462inline
463scfx_rep*
464quantization_scfx_rep( const scfx_rep& a,
465			const scfx_params& params,
466			bool& q_flag )
467{
468    scfx_rep& c = *new scfx_rep( a );
469    c.quantization( params, q_flag );
470    return &c;
471}
472
473inline
474scfx_rep*
475overflow_scfx_rep( const scfx_rep& a,
476		    const scfx_params& params,
477		    bool& o_flag )
478{
479    scfx_rep& c = *new scfx_rep( a );
480    c.overflow( params, o_flag );
481    return &c;
482}
483
484inline
485bool
486scfx_rep::rounding_flag() const
487{
488    return m_r_flag;
489}
490
491inline
492void
493scfx_rep::resize_to( int new_size, int restore )
494{
495    if( restore == -1 )
496    {
497        int size_incr = new_size - size();
498	m_wp += size_incr;
499	m_msw += size_incr;
500	m_lsw += size_incr;
501    }
502    m_mant.resize_to( new_size, restore );
503}
504
505inline
506const scfx_index
507scfx_rep::calc_indices( int n ) const
508{
509    int wi = n / bits_in_word + m_wp;
510    int bi = n % bits_in_word;
511
512    if( bi < 0 )
513    {
514        bi += bits_in_word;
515	-- wi;
516    }
517
518    return scfx_index( wi, bi );
519}
520
521inline
522void
523scfx_rep::o_extend( const scfx_index& x, sc_enc enc )
524{
525    int wi = x.wi();
526    int bi = x.bi();
527
528    SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" );
529
530    if( enc == SC_US_ || ( m_mant[wi] & ( ((word)1) << bi ) ) == 0 )
531    {
532        if( bi != bits_in_word - 1 )
533	    m_mant[wi] &= ~( ((word)-1) << ( bi + 1 ) );
534	for( int i = wi + 1; i < size(); ++ i )
535	    m_mant[i] = 0;
536	m_sign = 1;
537    }
538    else
539    {
540        if( bi != bits_in_word - 1 )
541	    m_mant[wi] |= ( ((word)-1) << ( bi + 1 ) );
542	for( int i = wi + 1; i < size(); ++ i )
543	    m_mant[i] = static_cast<word>( -1 );
544	m_sign = -1;
545    }
546}
547
548inline
549bool
550scfx_rep::o_bit_at( const scfx_index& x ) const
551{
552    int wi = x.wi();
553    int bi = x.bi();
554
555    SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" );
556
557    return ( m_mant[wi] & ( ((word)1) << bi ) ) != 0;
558}
559
560inline
561bool
562scfx_rep::o_zero_left( const scfx_index& x ) const
563{
564    int wi = x.wi();
565    int bi = x.bi();
566
567    SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" );
568
569    bool zero = true;
570    if( bi != bits_in_word - 1 )
571        zero = ( m_mant[wi] & ( ((word)-1) << ( bi + 1 ) ) ) == 0;
572    for( int i = wi + 1; i < size(); ++ i )
573	zero = zero && m_mant[i] == 0;
574
575    return zero;
576}
577
578inline
579bool
580scfx_rep::o_zero_right( const scfx_index& x ) const
581{
582    int wi = x.wi();
583    int bi = x.bi();
584
585    SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" );
586
587    bool zero = ( m_mant[wi] & ~( ((word)-1) << bi ) ) == 0;
588    for( int i = wi - 1; i >= 0; -- i )
589	zero = zero && m_mant[i] == 0;
590
591    return zero;
592}
593
594inline
595void
596scfx_rep::o_set_low( const scfx_index& x, sc_enc enc )
597{
598    int wi = x.wi();
599    int bi = x.bi();
600
601    SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" );
602
603    m_mant.clear();
604
605    if( enc == SC_TC_ )
606    {
607	m_mant[wi] |= ( ((word)1) << bi );
608	m_sign = -1;
609    }
610    else
611	m_sign = 1;
612}
613
614inline
615void
616scfx_rep::o_set_high( const scfx_index& x, const scfx_index& x2,
617		      sc_enc enc, int sign )
618{
619    int wi = x.wi();
620    int bi = x.bi();
621    int wi2 = x2.wi();
622    int bi2 = x2.bi();
623
624    SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" );
625    SC_ASSERT_( wi2 >= 0 && wi2 < size(), "word index out of range" );
626
627    int i;
628
629    for( i = 0; i < size(); ++ i )
630	m_mant[i] = static_cast<word>( -1 );
631
632    m_mant[wi] &= ~( ((word)-1) << bi );
633    for( i = wi + 1; i < size(); ++ i )
634	m_mant[i] = 0;
635
636    m_mant[wi2] &= ( ((word)-1) << bi2 );
637    for( i = wi2 - 1; i >= 0; -- i )
638	m_mant[i] = 0;
639
640    if( enc == SC_TC_ )
641	m_sign = sign;
642    else
643    {
644	m_mant[wi] |= ( ((word)1) << bi );
645	m_sign = 1;
646    }
647}
648
649inline
650void
651scfx_rep::o_set( const scfx_index& x, const scfx_index& x3,
652		 sc_enc enc, bool under )
653{
654    int wi = x.wi();
655    int bi = x.bi();
656    int wi3 = x3.wi();
657    int bi3 = x3.bi();
658
659    SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" );
660    SC_ASSERT_( wi3 >= 0 && wi3 < size(), "word index out of range" );
661
662    if( bi3 != bits_in_word - 1 )
663    {
664	if( under )
665	    m_mant[wi3] &= ~( ((word)-1) << ( bi3 + 1 ) );
666	else
667	    m_mant[wi3] |= ( ((word)-1) << ( bi3 + 1 ) );
668    }
669    for( int i = wi3 + 1; i < size(); ++ i )
670    {
671	if( under )
672	    m_mant[i] = 0;
673	else
674	    m_mant[i] = static_cast<word>( -1 );
675    }
676
677    if( enc == SC_TC_ )
678    {
679	if( under )
680	    m_mant[wi] |= ( ((word)1) << bi );
681	else
682	    m_mant[wi] &= ~( ((word)1) << bi );
683    }
684}
685
686inline
687void
688scfx_rep::o_invert( const scfx_index& x2 )
689{
690    int wi2 = x2.wi();
691    int bi2 = x2.bi();
692
693    m_mant[wi2] ^= ( ((word)-1) << bi2 );
694    for( int i = wi2 + 1; i < size(); ++ i )
695	m_mant[i] = ~ m_mant[i];
696}
697
698inline
699bool
700scfx_rep::q_bit( const scfx_index& x ) const
701{
702    int wi = x.wi();
703    int bi = x.bi();
704
705    SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" );
706
707    if( bi != 0 )
708        return ( m_mant[wi] & ( ((word)1) << ( bi - 1 ) ) ) != 0;
709    else if( wi != 0 )
710        return ( m_mant[wi - 1] & ( ((word)1) << ( bits_in_word - 1 ) ) ) != 0;
711    else
712        return false;
713}
714
715inline
716void
717scfx_rep::q_clear( const scfx_index& x )
718{
719    int wi = x.wi();
720    int bi = x.bi();
721
722    SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" );
723
724    m_mant[wi] &= ( ((word)-1) << bi );
725    for( int i = wi - 1; i >= 0; -- i )
726        m_mant[i] = 0;
727}
728
729inline
730void
731scfx_rep::q_incr( const scfx_index& x )
732{
733    int wi = x.wi();
734    int bi = x.bi();
735
736    SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" );
737
738    word old_val = m_mant[wi];
739    m_mant[wi] += ( ((word)1) << bi );
740    if( m_mant[wi] <= old_val )
741    {
742        if( wi + 1 == size() )
743          resize_to( size() + 1, 1 );
744
745        for( int i = wi + 1; i < size(); ++ i )
746	{
747	    if( ++ m_mant[i] != 0 )
748	        break;
749	}
750    }
751}
752
753inline
754bool
755scfx_rep::q_odd( const scfx_index& x ) const
756{
757    int wi = x.wi();
758    int bi = x.bi();
759
760    SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" );
761
762    return ( m_mant[wi] & ( ((word)1) << bi ) ) != 0;
763}
764
765inline
766bool
767scfx_rep::q_zero( const scfx_index& x ) const
768{
769    int wi = x.wi();
770    int bi = x.bi();
771
772    SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" );
773
774    bool zero;
775
776    if( bi != 0 )
777    {
778        zero = ( m_mant[wi] & ~( ((word)-1) << (bi - 1) ) ) == 0;
779	for( int i = wi - 1; i >= 0; -- i )
780	    zero = zero && m_mant[i] == 0;
781    }
782    else if( wi != 0 )
783    {
784        zero = ( m_mant[wi - 1] & ~( ((word)-1) << (bits_in_word - 1) ) ) == 0;
785	for( int i = wi - 2; i >= 0; -- i )
786	    zero = zero && m_mant[i] == 0;
787    }
788    else
789        zero = true;
790
791    return zero;
792}
793
794inline
795int
796scfx_rep::find_lsw() const
797{
798    for( int i = 0; i < size(); i ++ )
799    {
800        if( m_mant[i] )
801	    return i;
802    }
803    return 0;
804}
805
806inline
807int
808scfx_rep::find_msw() const
809{
810    for( int i = size() - 1; i >= 0; i -- )
811    {
812        if( m_mant[i] )
813	    return i;
814    }
815    return 0;
816}
817
818inline
819void
820scfx_rep::find_sw()
821{
822    m_lsw = find_lsw();
823    m_msw = find_msw();
824}
825
826inline
827void
828scfx_rep::toggle_tc()
829{
830    if( is_neg() )
831    {
832        complement( m_mant, m_mant, m_mant.size() );
833	inc( m_mant );
834    }
835}
836
837} // namespace sc_dt
838
839
840#endif
841
842// Taf!
843