sc_int_base.cc revision 12854:c95c35407325
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
75// explicit template instantiations
76namespace sc_core
77{
78
79template class sc_vpool<sc_dt::sc_int_bitref>;
80template class sc_vpool<sc_dt::sc_int_subref>;
81
82} // namespace sc_core
83
84namespace sc_dt
85{
86
87// to avoid code bloat in sc_int_concref<T1,T2>
88
89void
90sc_int_concref_invalid_length(int length)
91{
92    std::stringstream msg;
93    msg << "sc_int_concref<T1,T2> initialization: length = " << length <<
94           "violates 1 <= length <= " << SC_INTWIDTH;
95    SC_REPORT_ERROR("out of bounds", msg.str().c_str());
96    sc_core::sc_abort(); // can't recover from here
97}
98
99
100// ----------------------------------------------------------------------------
101//  CLASS : sc_int_bitref
102//
103//  Proxy class for sc_int bit selection (r-value and l-value).
104// ----------------------------------------------------------------------------
105
106sc_core::sc_vpool<sc_int_bitref> sc_int_bitref::m_pool(9);
107
108// concatenation methods:
109
110// #### OPTIMIZE
111void sc_int_bitref::concat_set(int64 src, int low_i)
112{
113    sc_int_base aa(1);
114    *this = aa = (low_i < 64) ? src >> low_i : src >> 63;
115}
116
117void sc_int_bitref::concat_set(const sc_signed &src, int low_i)
118{
119    sc_int_base aa(1);
120    if (low_i < src.length())
121        *this = aa = 1 & (src >> low_i);
122    else
123        *this = aa = (src < 0) ? (int_type)-1 : 0;
124}
125
126void sc_int_bitref::concat_set(const sc_unsigned &src, int low_i)
127{
128    sc_int_base aa(1);
129    if (low_i < src.length())
130        *this = aa = 1 & (src >> low_i);
131    else
132        *this = aa = 0;
133}
134
135void sc_int_bitref::concat_set(uint64 src, int low_i)
136{
137    sc_int_base aa(1);
138    *this = aa = (low_i < 64) ? src >> low_i : 0;
139}
140
141
142// other methods
143void
144sc_int_bitref::scan(::std::istream &is)
145{
146    bool b;
147    is >> b;
148    *this = b;
149}
150
151
152// ----------------------------------------------------------------------------
153//  CLASS : sc_int_subref_r
154//
155//  Proxy class for sc_int part selection (l-value).
156// ----------------------------------------------------------------------------
157
158bool
159sc_int_subref_r::concat_get_ctrl(sc_digit *dst_p, int low_i) const
160{
161    int dst_i; // Word in dst_p now processing.
162    int end_i; // Highest order word in dst_p to process.
163    int high_i; // Index of high order bit in dst_p to set.
164    uint_type mask; // Mask for bits to extract or keep.
165
166    dst_i = low_i / BITS_PER_DIGIT;
167    high_i = low_i + (m_left - m_right);
168    end_i = high_i / BITS_PER_DIGIT;
169    mask = ~mask_int[m_left][m_right];
170
171    // PROCESS THE FIRST WORD:
172    dst_p[dst_i] = (sc_digit)(dst_p[dst_i] & mask);
173    switch (end_i - dst_i) {
174      // BITS ARE ACROSS TWO WORDS:
175      case 1:
176        dst_i++;
177        dst_p[dst_i] = 0;
178        break;
179
180      // BITS ARE ACROSS THREE WORDS:
181      case 2:
182        dst_i++;
183        dst_p[dst_i++] = 0;
184        dst_p[dst_i] = 0;
185        break;
186
187      // BITS ARE ACROSS FOUR WORDS:
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
198bool
199sc_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    // PROCESS THE FIRST WORD:
218    mask = ~(~UINT_ZERO << left_shift);
219    dst_p[dst_i] = (sc_digit)((dst_p[dst_i] & mask) |
220                ((val << left_shift) & DIGIT_MASK));
221
222    switch (end_i - dst_i) {
223      // BITS ARE ACROSS TWO WORDS:
224      case 1:
225        dst_i++;
226        val >>= (BITS_PER_DIGIT - left_shift);
227        dst_p[dst_i] = (sc_digit)(val & DIGIT_MASK);
228        break;
229
230      // BITS ARE ACROSS THREE WORDS:
231      case 2:
232        dst_i++;
233        val >>= (BITS_PER_DIGIT - left_shift);
234        dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
235        val >>= BITS_PER_DIGIT;
236        dst_p[dst_i] = (sc_digit)val;
237        break;
238
239      // BITS ARE ACROSS FOUR WORDS:
240      case 3:
241        dst_i++;
242        val >>= (BITS_PER_DIGIT - left_shift);
243        dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
244        val >>= BITS_PER_DIGIT;
245        dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
246        val >>= BITS_PER_DIGIT;
247        dst_p[dst_i] = (sc_digit)val;
248        break;
249    }
250    return non_zero;
251}
252
253// ----------------------------------------------------------------------------
254//  CLASS : sc_int_subref
255//
256//  Proxy class for sc_int part selection (r-value and l-value).
257// ----------------------------------------------------------------------------
258
259sc_core::sc_vpool<sc_int_subref> sc_int_subref::m_pool(9);
260
261// assignment operators
262
263sc_int_subref &
264sc_int_subref::operator = (int_type v)
265{
266    int_type val = m_obj_p->m_val;
267    uint_type mask = mask_int[m_left][m_right];
268    val &= mask;
269    val |= (v << m_right) & ~mask;
270    m_obj_p->m_val = val;
271    m_obj_p->extend_sign();
272    return *this;
273}
274
275sc_int_subref &
276sc_int_subref::operator = (const sc_signed &a)
277{
278    sc_int_base aa(length());
279    return (*this = aa = a);
280}
281
282sc_int_subref &
283sc_int_subref::operator = (const sc_unsigned &a)
284{
285    sc_int_base aa(length());
286    return (*this = aa = a);
287}
288
289sc_int_subref &
290sc_int_subref::operator = (const sc_bv_base &a)
291{
292    sc_int_base aa(length());
293    return (*this = aa = a);
294}
295
296sc_int_subref &
297sc_int_subref::operator = (const sc_lv_base &a)
298{
299    sc_int_base aa(length());
300    return (*this = aa = a);
301}
302
303
304// concatenation methods:
305// #### OPTIMIZE
306void
307sc_int_subref::concat_set(int64 src, int low_i)
308{
309    sc_int_base aa(length());
310    *this = aa = (low_i < 64) ? src >> low_i : src >> 63;
311}
312
313void
314sc_int_subref::concat_set(const sc_signed &src, int low_i)
315{
316    sc_int_base aa(length());
317    if (low_i < src.length())
318        *this = aa = src >> low_i;
319    else
320        *this = (src < 0) ? (int_type)-1 : 0;
321}
322
323void
324sc_int_subref::concat_set(const sc_unsigned &src, int low_i)
325{
326    sc_int_base aa(length());
327    if (low_i < src.length())
328        *this = aa = src >> low_i;
329    else
330        *this = 0;
331}
332
333void
334sc_int_subref::concat_set(uint64 src, int low_i)
335{
336    sc_int_base aa (length());
337    *this = aa = (low_i < 64) ? src >> low_i : 0;
338}
339
340
341// other methods
342void
343sc_int_subref::scan(::std::istream &is)
344{
345    std::string s;
346    is >> s;
347    *this = s.c_str();
348}
349
350
351// ----------------------------------------------------------------------------
352//  CLASS : sc_int_base
353//
354//  Base class for sc_int.
355// ----------------------------------------------------------------------------
356
357// support methods
358void
359sc_int_base::invalid_length() const
360{
361    std::stringstream msg;
362    msg << "sc_int[_base] initialization: length = " << m_len <<
363           " violates 1 <= length <= " << SC_INTWIDTH;
364    SC_REPORT_ERROR("out of bounds", msg.str().c_str());
365    sc_core::sc_abort(); // can't recover from here
366}
367
368void
369sc_int_base::invalid_index(int i) const
370{
371    std::stringstream msg;
372    msg << "sc_int[_base] bit selection: index = " << i <<
373           " violates 0 <= index <= " << (m_len - 1);
374    SC_REPORT_ERROR("out of bounds", msg.str().c_str());
375    sc_core::sc_abort(); // can't recover from here
376}
377
378void
379sc_int_base::invalid_range(int l, int r) const
380{
381    std::stringstream msg;
382    msg << "sc_int[_base] part selection: " <<
383           "left = " << l << ", right = " << r << " violates " <<
384           (m_len-1) << " >= left >= right >= 0";
385    SC_REPORT_ERROR("out of bounds", msg.str().c_str());
386    sc_core::sc_abort(); // can't recover from here
387}
388
389void
390sc_int_base::check_value() const
391{
392    int_type limit = (int_type)1 << (m_len - 1);
393    if (m_val < -limit || m_val >= limit) {
394        std::stringstream msg;
395        msg << "sc_int[_base]: value does not fit into a length of " << m_len;
396        SC_REPORT_WARNING("out of bounds", msg.str().c_str());
397    }
398}
399
400
401// constructors
402sc_int_base::sc_int_base(const sc_bv_base &v) :
403    m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
404{
405    check_length();
406    *this = v;
407}
408sc_int_base::sc_int_base(const sc_lv_base &v) :
409    m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
410{
411    check_length();
412    *this = v;
413}
414sc_int_base::sc_int_base(const sc_uint_subref_r &v) :
415    m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
416{
417    check_length();
418    *this = v.to_uint64();
419}
420sc_int_base::sc_int_base(const sc_signed_subref_r &v) :
421    m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
422{
423    check_length();
424    *this = v.to_uint64();
425}
426sc_int_base::sc_int_base(const sc_unsigned_subref_r &v) :
427    m_val(0), m_len(v.length()), m_ulen(SC_INTWIDTH - m_len)
428{
429    check_length();
430    *this = v.to_uint64();
431}
432
433sc_int_base::sc_int_base(const sc_signed &a) :
434    m_val(0), m_len(a.length()), m_ulen(SC_INTWIDTH - m_len)
435{
436    check_length();
437    *this = a.to_int64();
438}
439
440sc_int_base::sc_int_base(const sc_unsigned &a) :
441    m_val(0), m_len(a.length()), m_ulen(SC_INTWIDTH - m_len)
442{
443    check_length();
444    *this = a.to_int64();
445}
446
447
448// assignment operators
449sc_int_base &
450sc_int_base::operator = (const sc_signed &a)
451{
452    int minlen = sc_min(m_len, a.length());
453    int i = 0;
454    for (; i < minlen; ++i) {
455        set(i, a.test(i));
456    }
457    bool sgn = a.sign();
458    for (; i < m_len; ++i) {
459        // sign extension
460        set(i, sgn);
461    }
462    extend_sign();
463    return *this;
464}
465
466sc_int_base &
467sc_int_base::operator = (const sc_unsigned &a)
468{
469    int minlen = sc_min(m_len, a.length());
470    int i = 0;
471    for (; i < minlen; ++i) {
472        set(i, a.test(i));
473    }
474    for (; i < m_len; ++i) {
475        // zero extension
476        set(i, 0);
477    }
478    extend_sign();
479    return *this;
480}
481
482
483sc_int_base &
484sc_int_base::operator = (const sc_bv_base &a)
485{
486    int minlen = sc_min(m_len, a.length());
487    int i = 0;
488    for (; i < minlen; ++i) {
489        set(i, a.get_bit(i));
490    }
491    for (; i < m_len; ++i) {
492        // zero extension
493        set(i, 0);
494    }
495    extend_sign();
496    return *this;
497}
498
499sc_int_base &
500sc_int_base::operator = (const sc_lv_base &a)
501{
502    int minlen = sc_min(m_len, a.length());
503    int i = 0;
504    for (; i < minlen; ++i) {
505        set(i, sc_logic(a.get_bit(i)).to_bool());
506    }
507    for (; i < m_len; ++i) {
508        // zero extension
509        set(i, 0);
510    }
511    extend_sign();
512    return *this;
513}
514
515sc_int_base &
516sc_int_base::operator = (const char *a)
517{
518    if (a == 0) {
519        SC_REPORT_ERROR("conversion failed",
520                        "character string is zero");
521    } else if (*a == 0) {
522        SC_REPORT_ERROR("conversion failed",
523                        "character string is empty");
524    } else try {
525        int len = m_len;
526        sc_fix aa(a, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
527        return this->operator = (aa);
528    } catch(const sc_core::sc_report &) {
529        std::stringstream msg;
530        msg << "character string '" << a << "' is not valid";
531        SC_REPORT_ERROR("conversion failed", msg.str().c_str());
532    }
533    return *this;
534}
535
536// explicit conversion to character string
537const std::string
538sc_int_base::to_string(sc_numrep numrep) const
539{
540    int len = m_len;
541    sc_fix aa(*this, len, len, SC_TRN, SC_WRAP, 0, SC_ON);
542    return aa.to_string(numrep);
543}
544
545const std::string
546sc_int_base::to_string(sc_numrep numrep, bool w_prefix) const
547{
548    int len = m_len;
549    sc_fix 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
555bool sc_int_base::and_reduce() const { return (m_val == int_type(-1)); }
556bool sc_int_base::or_reduce() const { return (m_val != int_type(0)); }
557
558bool
559sc_int_base::xor_reduce() const
560{
561    uint_type mask = ~UINT_ZERO;
562    uint_type val = m_val & (mask >> m_ulen);
563    int n = SC_INTWIDTH;
564    do {
565        n >>= 1;
566        mask >>= n;
567        val = ((val & (mask << n)) >> n) ^ (val & mask);
568    } while (n != 1);
569    return (val != uint_type(0));
570}
571
572bool
573sc_int_base::concat_get_ctrl(sc_digit *dst_p, int low_i) const
574{
575    int dst_i; // Word in dst_p now processing.
576    int end_i; // Highest order word in dst_p to process.
577    int left_shift; // Left shift for val.
578    uint_type mask; // Mask for bits to extract or keep.
579
580    dst_i = low_i / BITS_PER_DIGIT;
581    left_shift = low_i % BITS_PER_DIGIT;
582    end_i = (low_i + (m_len - 1)) / BITS_PER_DIGIT;
583
584    mask = ~(~UINT_ZERO << left_shift);
585    dst_p[dst_i] = (sc_digit)(dst_p[dst_i] & mask);
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_int_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_int_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 non_zero; // True if value inserted is non-zero.
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    non_zero = val != 0;
624
625    // MASK OFF DATA TO BE TRANSFERRED BASED 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    switch (end_i - dst_i) {
636      // BITS ARE ACROSS TWO WORDS:
637      case 1:
638        dst_i++;
639        val >>= (BITS_PER_DIGIT - left_shift);
640        dst_p[dst_i] = (sc_digit)val;
641        break;
642
643      // BITS ARE ACROSS THREE WORDS:
644      case 2:
645        dst_i++;
646        val >>= (BITS_PER_DIGIT - left_shift);
647        dst_p[dst_i++] = ((sc_digit)val) & DIGIT_MASK;
648        val >>= BITS_PER_DIGIT;
649        dst_p[dst_i] = (sc_digit)val;
650        break;
651
652      // BITS ARE ACROSS FOUR WORDS:
653      case 3:
654        dst_i++;
655        val >>= (BITS_PER_DIGIT - left_shift);
656        dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
657        val >>= BITS_PER_DIGIT;
658        dst_p[dst_i++] = (sc_digit)(val & DIGIT_MASK);
659        val >>= BITS_PER_DIGIT;
660        dst_p[dst_i] = (sc_digit)val;
661        break;
662    }
663    return non_zero;
664}
665
666// #### OPTIMIZE
667void
668sc_int_base::concat_set(int64 src, int low_i)
669{
670    *this = (low_i < 64) ? src >> low_i : src >> 63;
671}
672
673void
674sc_int_base::concat_set(const sc_signed &src, int low_i)
675{
676    if (low_i < src.length())
677        *this = src >> low_i;
678    else
679        *this = (src < 0) ? (int_type)-1 : 0;
680}
681
682void
683sc_int_base::concat_set(const sc_unsigned &src, int low_i)
684{
685    if (low_i < src.length())
686        *this = src >> low_i;
687    else
688        *this = 0;
689}
690
691void
692sc_int_base::concat_set(uint64 src, int low_i)
693{
694    *this = (low_i < 64) ? src >> low_i : 0;
695}
696
697// other methods
698void
699sc_int_base::scan(::std::istream &is)
700{
701    std::string s;
702    is >> s;
703    *this = s.c_str();
704}
705
706} // namespace sc_dt;
707