sc_uint_base.cc (13322:7391057615bd) sc_uint_base.cc (13325:86323e6cc8ec)
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) {
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("conversion failed",
506 SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_,
507 "character string is zero");
508 } else if (*a == 0) {
507 "character string is zero");
508 } else if (*a == 0) {
509 SC_REPORT_ERROR("conversion failed",
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";
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("conversion failed", msg.str().c_str());
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
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