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