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