Deleted Added
sdiff udiff text old ( 13138:31951157e41e ) new ( 13322:7391057615bd )
full compact
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("conversion failed",
521 "character string is zero");
522 } else if (*a == 0) {
523 SC_REPORT_ERROR("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("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;