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_int_base.cpp -- contains interface definitions between sc_int and
23                sc_signed, sc_unsigned, and definitions for sc_int_subref.
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
40// $Log: sc_int_base.cpp,v $
41// Revision 1.5  2011/02/18 20:19:14  acg
42//  Andy Goodrich: updating Copyright notice.
43//
44// Revision 1.4  2010/02/04 22:23:29  acg
45//  Andy Goodrich: fixed bug in concatenation reads for part selections,
46//  the mask being used was 32 bits and should have been 64 bits.
47//
48// Revision 1.3  2008/06/19 17:47:56  acg
49//  Andy Goodrich: fixes for bugs. See 2.2.1 RELEASENOTES.
50//
51// Revision 1.2  2007/11/04 21:27:00  acg
52//  Andy Goodrich: changes to make sure the proper value is returned from
53//  concat_get_data().
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:31  acg
59// Added $Log command so that CVS check in comments are reproduced in the
60// source.
61//
62
63#include "sysc/kernel/sc_macros.h"
64#include "sysc/datatypes/int/sc_signed.h"
65#include "sysc/datatypes/int/sc_unsigned.h"
66#include "sysc/datatypes/int/sc_int_base.h"
67#include "sysc/datatypes/int/sc_uint_base.h"
68#include "sysc/datatypes/int/sc_signed.h"
69#include "sysc/datatypes/int/sc_int_ids.h"
70#include "sysc/datatypes/bit/sc_bv_base.h"
71#include "sysc/datatypes/bit/sc_lv_base.h"
72#include "sysc/datatypes/misc/sc_concatref.h"
73#include "sysc/datatypes/fx/sc_fix.h"
74#include "sysc/datatypes/fx/scfx_other_defs.h"
75
76
77namespace sc_dt
78{
79
80// to avoid code bloat in sc_int_concref<T1,T2>
81
82void
83sc_int_concref_invalid_length( int length )
84{
85    char msg[BUFSIZ];
86    std::sprintf( msg,
87	     "sc_int_concref<T1,T2> initialization: length = %d "
88	     "violates 1 <= length <= %d",
89	     length, SC_INTWIDTH );
90    SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
91}
92
93
94// ----------------------------------------------------------------------------
95//  CLASS : sc_int_bitref
96//
97//  Proxy class for sc_int bit selection (r-value and l-value).
98// ----------------------------------------------------------------------------
99
100sc_core::sc_vpool<sc_int_bitref> sc_int_bitref::m_pool(9);
101
102// concatenation methods:
103
104// #### OPTIMIZE
105void sc_int_bitref::concat_set(int64 src, int low_i)
106{
107    sc_int_base aa( 1 );
108    *this = aa = (low_i < 64) ? src >> low_i : src >> 63;
109}
110
111void sc_int_bitref::concat_set(const sc_signed& src, int low_i)
112{
113    sc_int_base aa( 1 );
114    if ( low_i < src.length() )
115	*this = aa = 1 & (src >> low_i);
116    else
117	*this = aa = (src < 0) ? (int_type)-1 : 0;
118}
119
120void sc_int_bitref::concat_set(const sc_unsigned& src, int low_i)
121{
122    sc_int_base aa( 1 );
123    if ( low_i < src.length() )
124	*this = aa = 1 & (src >> low_i);
125    else
126	*this = aa = 0;
127}
128
129void sc_int_bitref::concat_set(uint64 src, int low_i)
130{
131    sc_int_base aa( 1 );
132    *this = aa = (low_i < 64) ? src >> low_i : 0;
133}
134
135
136// other methods
137
138void
139sc_int_bitref::scan( ::std::istream& is )
140{
141    bool b;
142    is >> b;
143    *this = b;
144}
145
146
147// ----------------------------------------------------------------------------
148//  CLASS : sc_int_subref_r
149//
150//  Proxy class for sc_int part selection (l-value).
151// ----------------------------------------------------------------------------
152
153bool sc_int_subref_r::concat_get_ctrl( sc_digit* dst_p, int low_i ) const
154{
155    int       dst_i;       // Word in dst_p now processing.
156    int       end_i;       // Highest order word in dst_p to process.
157    int       high_i;      // Index of high order bit in dst_p to set.
158    uint_type mask;        // Mask for bits to extract or keep.
159
160    dst_i = low_i / BITS_PER_DIGIT;
161    high_i = low_i + (m_left-m_right);
162    end_i = high_i / BITS_PER_DIGIT;
163    mask = ~mask_int[m_left][m_right];
164
165
166    // PROCESS THE FIRST WORD:
167
168    dst_p[dst_i] = (sc_digit)(dst_p[dst_i] & mask);
169    switch ( end_i - dst_i )
170    {
171     // BITS ARE ACROSS TWO WORDS:
172
173     case 1:
174        dst_i++;
175        dst_p[dst_i] = 0;
176        break;
177
178     // BITS ARE ACROSS THREE WORDS:
179
180     case 2:
181        dst_i++;
182        dst_p[dst_i++] = 0;
183        dst_p[dst_i] = 0;
184        break;
185
186     // BITS ARE ACROSS FOUR WORDS:
187
188     case 3:
189        dst_i++;
190        dst_p[dst_i++] = 0;
191        dst_p[dst_i++] = 0;
192        dst_p[dst_i] = 0;
193        break;
194    }
195    return false;
196}
197
198
199bool sc_int_subref_r::concat_get_data( sc_digit* dst_p, int low_i ) const
200{
201    int       dst_i;      // Word in dst_p now processing.
202    int       end_i;      // Highest order word in dst_p to process.
203    int       high_i;     // Index of high order bit in dst_p to set.
204    int       left_shift; // Left shift for val.
205    uint_type mask;       // Mask for bits to extract or keep.
206    bool      non_zero;	  // True if value inserted is non-zero.
207    uint_type val;        // Selection value extracted from m_obj_p.
208
209    dst_i = low_i / BITS_PER_DIGIT;
210    left_shift = low_i % BITS_PER_DIGIT;
211    high_i = low_i + (m_left-m_right);
212    end_i = high_i / BITS_PER_DIGIT;
213    mask = ~mask_int[m_left][m_right];
214    val = (m_obj_p->m_val & mask) >> m_right;
215    non_zero = val != 0;
216
217
218    // PROCESS THE FIRST WORD:
219
220    mask = ~(-1 << left_shift);
221    dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & mask) |
222		((val << left_shift) & DIGIT_MASK));
223
224    switch ( end_i - dst_i )
225    {
226     // BITS ARE ACROSS TWO WORDS:
227
228     case 1:
229        dst_i++;
230        val >>= (BITS_PER_DIGIT-left_shift);
231        dst_p[dst_i] = (sc_digit)(val & DIGIT_MASK);
232        break;
233
234     // BITS ARE ACROSS THREE WORDS:
235
236     case 2:
237        dst_i++;
238        val >>= (BITS_PER_DIGIT-left_shift);
239        dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
240        val >>= BITS_PER_DIGIT;
241        dst_p[dst_i] = (sc_digit)val;
242        break;
243
244     // BITS ARE ACROSS FOUR WORDS:
245
246     case 3:
247        dst_i++;
248        val >>= (BITS_PER_DIGIT-left_shift);
249        dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
250        val >>= BITS_PER_DIGIT;
251        dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
252        val >>= BITS_PER_DIGIT;
253        dst_p[dst_i] = (sc_digit)val;
254        break;
255    }
256    return non_zero;
257}
258
259// ----------------------------------------------------------------------------
260//  CLASS : sc_int_subref
261//
262//  Proxy class for sc_int part selection (r-value and l-value).
263// ----------------------------------------------------------------------------
264
265sc_core::sc_vpool<sc_int_subref> sc_int_subref::m_pool(9);
266
267// assignment operators
268
269sc_int_subref&
270sc_int_subref::operator = ( int_type v )
271{
272    int_type val = m_obj_p->m_val;
273    uint_type mask = mask_int[m_left][m_right];
274    val &= mask;
275    val |= (v << m_right) & ~mask;
276    m_obj_p->m_val = val;
277    m_obj_p->extend_sign();
278    return *this;
279}
280
281sc_int_subref&
282sc_int_subref::operator = ( const sc_signed& a )
283{
284    sc_int_base aa( length() );
285    return ( *this = aa = a );
286}
287
288sc_int_subref&
289sc_int_subref::operator = ( const sc_unsigned& a )
290{
291    sc_int_base aa( length() );
292    return ( *this = aa = a );
293}
294
295sc_int_subref&
296sc_int_subref::operator = ( const sc_bv_base& a )
297{
298    sc_int_base aa( length() );
299    return ( *this = aa = a );
300}
301
302sc_int_subref&
303sc_int_subref::operator = ( const sc_lv_base& a )
304{
305    sc_int_base aa( length() );
306    return ( *this = aa = a );
307}
308
309
310// concatenation methods:
311
312// #### OPTIMIZE
313void sc_int_subref::concat_set(int64 src, int low_i)
314{
315    sc_int_base aa ( length() );
316    *this = aa = (low_i < 64) ? src >> low_i : src >> 63;
317}
318
319void sc_int_subref::concat_set(const sc_signed& src, int low_i)
320{
321    sc_int_base aa( length() );
322    if ( low_i < src.length() )
323	*this = aa = src >> low_i;
324    else
325	*this = (src < 0) ? (int_type)-1 : 0;
326}
327
328void sc_int_subref::concat_set(const sc_unsigned& src, int low_i)
329{
330    sc_int_base aa( length() );
331    if ( low_i < src.length() )
332	*this = aa = src >> low_i;
333    else
334	*this = 0;
335}
336
337void sc_int_subref::concat_set(uint64 src, int low_i)
338{
339    sc_int_base aa ( length() );
340    *this = aa = (low_i < 64) ? src >> low_i : 0;
341}
342
343
344// other methods
345
346void
347sc_int_subref::scan( ::std::istream& is )
348{
349    std::string s;
350    is >> s;
351    *this = s.c_str();
352}
353
354
355// ----------------------------------------------------------------------------
356//  CLASS : sc_int_base
357//
358//  Base class for sc_int.
359// ----------------------------------------------------------------------------
360
361// support methods
362
363void
364sc_int_base::invalid_length() const
365{
366    char msg[BUFSIZ];
367    std::sprintf( msg,
368	     "sc_int[_base] initialization: length = %d violates "
369	     "1 <= length <= %d",
370	     m_len, SC_INTWIDTH );
371    SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
372}
373
374void
375sc_int_base::invalid_index( int i ) const
376{
377    char msg[BUFSIZ];
378    std::sprintf( msg,
379	     "sc_int[_base] bit selection: index = %d violates "
380	     "0 <= index <= %d",
381	     i, m_len - 1 );
382    SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
383}
384
385void
386sc_int_base::invalid_range( int l, int r ) const
387{
388    char msg[BUFSIZ];
389    std::sprintf( msg,
390	     "sc_int[_base] part selection: left = %d, right = %d violates "
391	     "%d >= left >= right >= 0",
392	     l, r, m_len - 1 );
393    SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
394}
395
396
397void
398sc_int_base::check_value() const
399{
400    int_type limit = (int_type) 1 << ( m_len - 1 );
401    if( m_val < -limit || m_val >= limit ) {
402	char msg[BUFSIZ];
403	std::sprintf( msg, "sc_int[_base]: value does not fit into a length of %d",
404		 m_len );
405	SC_REPORT_WARNING( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
406    }
407}
408
409
410// constructors
411sc_int_base::sc_int_base( const sc_bv_base& v )
412    : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len )
413{
414    check_length();
415    *this = v;
416}
417sc_int_base::sc_int_base( const sc_lv_base& v )
418    : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len )
419{
420    check_length();
421    *this = v;
422}
423sc_int_base::sc_int_base( const sc_uint_subref_r& v )
424    : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len )
425{
426    check_length();
427    *this = v.to_uint64();
428}
429sc_int_base::sc_int_base( const sc_signed_subref_r& v )
430    : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len )
431{
432    check_length();
433    *this = v.to_uint64();
434}
435sc_int_base::sc_int_base( const sc_unsigned_subref_r& v )
436    : m_val(0), m_len( v.length() ), m_ulen( SC_INTWIDTH - m_len )
437{
438    check_length();
439    *this = v.to_uint64();
440}
441
442sc_int_base::sc_int_base( const sc_signed& a )
443    : m_val( 0 ), m_len( a.length() ), m_ulen( SC_INTWIDTH - m_len )
444{
445    check_length();
446#if 0
447    for( int i = m_len - 1; i >= 0; -- i ) {
448	set( i, a.test( i ) );
449    }
450    extend_sign();
451#else
452    *this = a.to_int64();
453#endif
454}
455
456sc_int_base::sc_int_base( const sc_unsigned& a )
457    : m_val( 0 ), m_len( a.length() ), m_ulen( SC_INTWIDTH - m_len )
458{
459    check_length();
460#if 0
461    for( int i = m_len - 1; i >= 0; -- i ) {
462	set( i, a.test( i ) );
463    }
464    extend_sign();
465#else
466    *this = a.to_int64();
467#endif
468}
469
470
471// assignment operators
472
473sc_int_base&
474sc_int_base::operator = ( const sc_signed& a )
475{
476    int minlen = sc_min( m_len, a.length() );
477    int i = 0;
478    for( ; i < minlen; ++ i ) {
479	set( i, a.test( i ) );
480    }
481    bool sgn = a.sign();
482    for( ; i < m_len; ++ i ) {
483	// sign extension
484	set( i, sgn );
485    }
486    extend_sign();
487    return *this;
488}
489
490sc_int_base&
491sc_int_base::operator = ( const sc_unsigned& a )
492{
493    int minlen = sc_min( m_len, a.length() );
494    int i = 0;
495    for( ; i < minlen; ++ i ) {
496	set( i, a.test( i ) );
497    }
498    for( ; i < m_len; ++ i ) {
499	// zero extension
500	set( i, 0 );
501    }
502    extend_sign();
503    return *this;
504}
505
506
507sc_int_base&
508sc_int_base::operator = ( const sc_bv_base& a )
509{
510    int minlen = sc_min( m_len, a.length() );
511    int i = 0;
512    for( ; i < minlen; ++ i ) {
513	set( i, a.get_bit( i ) );
514    }
515    for( ; i < m_len; ++ i ) {
516	// zero extension
517	set( i, 0 );
518    }
519    extend_sign();
520    return *this;
521}
522
523sc_int_base&
524sc_int_base::operator = ( const sc_lv_base& a )
525{
526    int minlen = sc_min( m_len, a.length() );
527    int i = 0;
528    for( ; i < minlen; ++ i ) {
529	set( i, sc_logic( a.get_bit( i ) ).to_bool() );
530    }
531    for( ; i < m_len; ++ i ) {
532	// zero extension
533	set( i, 0 );
534    }
535    extend_sign();
536    return *this;
537}
538
539sc_int_base&
540sc_int_base::operator = ( const char* a )
541{
542    if( a == 0 ) {
543	SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_,
544			 "character string is zero" );
545    }
546    if( *a == 0 ) {
547	SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_,
548			 "character string is empty" );
549    }
550    try {
551	int len = m_len;
552	sc_fix aa( a, len, len, SC_TRN, SC_WRAP, 0, SC_ON );
553	return this->operator = ( aa );
554    } catch( sc_core::sc_report ) {
555	char msg[BUFSIZ];
556	std::sprintf( msg, "character string '%s' is not valid", a );
557	SC_REPORT_ERROR( sc_core::SC_ID_CONVERSION_FAILED_, msg );
558	// never reached
559	return *this;
560    }
561}
562
563// explicit conversion to character string
564
565const std::string
566sc_int_base::to_string( sc_numrep numrep ) const
567{
568    int len = m_len;
569    sc_fix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON );
570    return aa.to_string( numrep );
571}
572
573const std::string
574sc_int_base::to_string( sc_numrep numrep, bool w_prefix ) const
575{
576    int len = m_len;
577    sc_fix aa( *this, len, len, SC_TRN, SC_WRAP, 0, SC_ON );
578    return aa.to_string( numrep, w_prefix );
579}
580
581
582// reduce methods
583
584bool
585sc_int_base::and_reduce() const
586{
587    return ( m_val == int_type( -1 ) );
588}
589
590bool
591sc_int_base::or_reduce() const
592{
593    return ( m_val != int_type( 0 ) );
594}
595
596bool
597sc_int_base::xor_reduce() const
598{
599    uint_type mask = ~UINT_ZERO;
600    uint_type val = m_val & (mask >> m_ulen);
601    int n = SC_INTWIDTH;
602    do {
603	n >>= 1;
604	mask >>= n;
605	val = ((val & (mask << n)) >> n) ^ (val & mask);
606    } while( n != 1 );
607    return ( val != uint_type( 0 ) );
608}
609
610
611bool sc_int_base::concat_get_ctrl( sc_digit* dst_p, int low_i ) const
612{
613    int        dst_i;       // Word in dst_p now processing.
614    int        end_i;       // Highest order word in dst_p to process.
615    int        left_shift;  // Left shift for val.
616    uint_type  mask;        // Mask for bits to extract or keep.
617
618    dst_i = low_i / BITS_PER_DIGIT;
619    left_shift = low_i % BITS_PER_DIGIT;
620    end_i = (low_i + (m_len-1)) / BITS_PER_DIGIT;
621
622    mask = ~(-1 << left_shift);
623    dst_p[dst_i] = (sc_digit)(dst_p[dst_i] & mask);
624	dst_i++;
625	for ( ; dst_i <= end_i; dst_i++ ) dst_p[dst_i] = 0;
626	return false;
627}
628
629//------------------------------------------------------------------------------
630//"sc_int_base::concat_get_data"
631//
632// This method transfers the value of this object instance to the supplied
633// array of sc_unsigned digits starting with the bit specified by low_i within
634// the array of digits.
635//
636// Notes:
637//   (1) we don't worry about masking the high order data we transfer since
638//       concat_get_data() is called from low order bit to high order bit. So
639//       the bits above where we place ours will be filled in by someone else.
640//
641//   dst_p -> array of sc_unsigned digits to be filled in.
642//   low_i =  first bit within dst_p to be set.
643//------------------------------------------------------------------------------
644bool sc_int_base::concat_get_data( sc_digit* dst_p, int low_i ) const
645{
646    int        dst_i;       // Word in dst_p now processing.
647    int        end_i;       // Highest order word in dst_p to process.
648    int        high_i;      // Index of high order bit in dst_p to set.
649    int        left_shift;  // Left shift for val.
650    uint_type  mask;        // Mask for bits to extract or keep.
651    bool       non_zero;    // True if value inserted is non-zero.
652    uint_type  val;         // Value for this object.
653
654    dst_i = low_i / BITS_PER_DIGIT;
655    left_shift = low_i % BITS_PER_DIGIT;
656    high_i = low_i + (m_len-1);
657    end_i = high_i / BITS_PER_DIGIT;
658    val = m_val;
659    non_zero = val != 0;
660
661    // MASK OFF DATA TO BE TRANSFERRED BASED ON WIDTH:
662
663    if ( m_len < 64 )
664    {
665	mask = ~((uint_type)-1 << m_len);
666        val &=  mask;
667    }
668
669    // PROCESS THE FIRST WORD:
670
671    mask = (-1 << left_shift);
672    dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & ~mask) |
673		((val <<left_shift) & DIGIT_MASK));
674    switch ( end_i - dst_i )
675    {
676     // BITS ARE ACROSS TWO WORDS:
677
678     case 1:
679	dst_i++;
680	val >>= (BITS_PER_DIGIT-left_shift);
681	dst_p[dst_i] = (sc_digit)val;
682	break;
683
684     // BITS ARE ACROSS THREE WORDS:
685
686     case 2:
687	dst_i++;
688	val >>= (BITS_PER_DIGIT-left_shift);
689	dst_p[dst_i++] = ((sc_digit)val) & DIGIT_MASK;
690	val >>= BITS_PER_DIGIT;
691	dst_p[dst_i] = (sc_digit)val;
692	break;
693
694     // BITS ARE ACROSS FOUR WORDS:
695
696     case 3:
697	dst_i++;
698	val >>= (BITS_PER_DIGIT-left_shift);
699	dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
700	val >>= BITS_PER_DIGIT;
701	dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
702	val >>= BITS_PER_DIGIT;
703	dst_p[dst_i] = (sc_digit)val;
704	break;
705    }
706    return non_zero;
707}
708
709// #### OPTIMIZE
710void sc_int_base::concat_set(int64 src, int low_i)
711{
712    *this = (low_i < 64) ? src >> low_i : src >> 63;
713}
714
715void sc_int_base::concat_set(const sc_signed& src, int low_i)
716{
717    if ( low_i < src.length() )
718	*this = src >> low_i;
719    else
720        *this = (src < 0) ? (int_type)-1 : 0;
721}
722
723void sc_int_base::concat_set(const sc_unsigned& src, int low_i)
724{
725    if ( low_i < src.length() )
726	*this = src >> low_i;
727    else
728        *this = 0;
729}
730
731void sc_int_base::concat_set(uint64 src, int low_i)
732{
733    *this = (low_i < 64) ? src >> low_i : 0;
734}
735
736// other methods
737
738void
739sc_int_base::scan( ::std::istream& is )
740{
741    std::string s;
742    is >> s;
743    *this = s.c_str();
744}
745
746} // namespace sc_dt;
747
748
749// Taf!
750