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